features: /changes, /search, /fork, web_search, prompt memoization, per-turn spend cap, workspace refresh
ci / check (macos-latest) (push) Canceled after 0s
ci / check (ubuntu-latest) (push) Canceled after 0s
ci / check (windows-latest) (push) Canceled after 0s

- /changes diffs the last turn's file snapshot (added/modified/deleted), reusing undo infra via SnapshotStack.peek()
- system prompt memoized behind version counters (notebook/memory/skills/plugins/tools/workspace); hit-rate in /cost, foundation for provider caching
- web_search: DuckDuckGo Lite, keyless, 5 results, SSRF-filtered, in the net set with ask permission
- /search <query>: full-text grep over saved sessions incl. tool-input JSON
- workspace file list re-walks at a turn boundary after writes
- maxSpendPerTurn: per-turn cap stops a runaway step with a notice
- /fork: branch the session at the last turn boundary, original untouched

821 tests pass, typecheck clean, build green
This commit is contained in:
asepharyana committed 2026-09-09 18:06:31 +07:00
1 parent 0bdf642672
commit e709737df1
24 files changed
+720 -41

No files matched your search

+3
View File
@@ -23,6 +23,8 @@ export type Config = {
maxRetries?: number;
/** USD ceiling for a session's spend: warn at 80%, refuse the next turn at 100%. */
maxSpendUsd?: number;
/** USD ceiling per individual turn: abort a step if the turn's delta exceeds this. */
maxSpendPerTurn?: number;
/** Model id for subagents; omit to share the parent's. */
subagentModel?: string;
/** Default agent variant name. */
@@ -113,6 +115,7 @@ export async function loadConfig(): Promise<Config> {
...(file.presetId ? { presetId: file.presetId } : {}),
...(file.maxRetries !== undefined ? { maxRetries: file.maxRetries } : {}),
...(typeof file.maxSpendUsd === 'number' && file.maxSpendUsd > 0 ? { maxSpendUsd: file.maxSpendUsd } : {}),
...(typeof file.maxSpendPerTurn === 'number' && file.maxSpendPerTurn > 0 ? { maxSpendPerTurn: file.maxSpendPerTurn } : {}),
...(file.subagentModel ? { subagentModel: file.subagentModel } : {}),
...(file.agent ? { agent: file.agent } : {}),
...(file.thinking ? { thinking: file.thinking } : {}),