@ikarmic/forge-core 5.1.1 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agent.js +208 -57
- package/dist/agent/enhance-prompt.js +2 -1
- package/dist/agent/goal.d.ts +5 -8
- package/dist/agent/prompts.d.ts +15 -0
- package/dist/agent/prompts.js +34 -0
- package/dist/agent/race-abort.d.ts +8 -0
- package/dist/agent/race-abort.js +24 -0
- package/dist/agent/retry.d.ts +50 -0
- package/dist/agent/retry.js +192 -0
- package/dist/agent/shell-command.d.ts +23 -0
- package/dist/agent/shell-command.js +93 -0
- package/dist/agent/stack-facts.d.ts +23 -0
- package/dist/agent/stack-facts.js +150 -0
- package/dist/catalog/models-dev-snapshot.d.ts +1 -0
- package/dist/catalog/models-dev-snapshot.js +3 -0
- package/dist/catalog/models-dev.d.ts +35 -0
- package/dist/catalog/models-dev.js +143 -0
- package/dist/code-index/parser.js +48 -3
- package/dist/context/compaction.js +8 -2
- package/dist/git/auto-commit.d.ts +4 -2
- package/dist/git/auto-commit.js +16 -5
- package/dist/github/github-tools.d.ts +2 -18
- package/dist/index.d.ts +11 -3
- package/dist/index.js +9 -2
- package/dist/journey/answers-block.js +14 -1
- package/dist/journey/offer.js +2 -1
- package/dist/mcp/json-schema-to-zod.js +12 -1
- package/dist/memory/session-digest.js +2 -1
- package/dist/orchestrator/index.d.ts +1 -1
- package/dist/orchestrator/index.js +1 -1
- package/dist/orchestrator/orchestrator.d.ts +45 -6
- package/dist/orchestrator/orchestrator.js +62 -12
- package/dist/orchestrator/router.d.ts +1 -1
- package/dist/orchestrator/router.js +4 -1
- package/dist/orchestrator/specialists.d.ts +6 -1
- package/dist/orchestrator/specialists.js +165 -68
- package/dist/orchestrator/types.d.ts +1 -1
- package/dist/policy/policy.d.ts +6 -59
- package/dist/pricing.d.ts +2 -0
- package/dist/pricing.js +47 -16
- package/dist/structured/schema.js +9 -12
- package/dist/tools/apply-patch.d.ts +1 -5
- package/dist/tools/ask-user.d.ts +2 -10
- package/dist/tools/ask-user.js +12 -4
- package/dist/tools/browser-tools.d.ts +15 -31
- package/dist/tools/codebase-search.d.ts +1 -7
- package/dist/tools/command-sandbox.d.ts +24 -0
- package/dist/tools/command-sandbox.js +73 -0
- package/dist/tools/dependency-audit.d.ts +30 -0
- package/dist/tools/dependency-audit.js +197 -0
- package/dist/tools/edit-file.d.ts +9 -15
- package/dist/tools/edit-file.js +64 -16
- package/dist/tools/fetch-url.d.ts +1 -18
- package/dist/tools/find-references.d.ts +1 -5
- package/dist/tools/find-symbol.d.ts +10 -8
- package/dist/tools/git-diff.d.ts +13 -0
- package/dist/tools/git-diff.js +85 -0
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/index.js +5 -1
- package/dist/tools/list-files.d.ts +1 -19
- package/dist/tools/list-symbols.d.ts +1 -5
- package/dist/tools/memory.d.ts +23 -43
- package/dist/tools/notebook.d.ts +11 -17
- package/dist/tools/read-file.d.ts +1 -11
- package/dist/tools/read-image.d.ts +1 -12
- package/dist/tools/read-only.d.ts +1 -1
- package/dist/tools/read-only.js +2 -0
- package/dist/tools/run-command.d.ts +1 -17
- package/dist/tools/run-command.js +12 -2
- package/dist/tools/search-files.d.ts +1 -17
- package/dist/tools/search-files.js +8 -49
- package/dist/tools/search-worker.d.ts +23 -0
- package/dist/tools/search-worker.js +77 -0
- package/dist/tools/sub-agent-wait.d.ts +2 -8
- package/dist/tools/sub-agent.d.ts +2 -70
- package/dist/tools/sub-agent.js +1 -0
- package/dist/tools/todo.d.ts +8 -20
- package/dist/tools/web-search.d.ts +1 -7
- package/dist/tools/write-file.d.ts +1 -7
- package/dist/types.d.ts +60 -1
- package/package.json +3 -3
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search_files' matching, run in a worker thread with a time limit. JavaScript cannot interrupt a running regex, so a
|
|
3
|
+
* pattern that backtracks badly on the main thread froze the process (in VS Code, the extension host): in a worker it
|
|
4
|
+
* is terminated after `timeoutMs`. The worker source is a plain string, not a function's text, so a bundler cannot
|
|
5
|
+
* rename or wrap anything in it; the same string runs in-process when a worker cannot start.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
import { Worker } from 'node:worker_threads';
|
|
9
|
+
export const DEFAULT_SEARCH_TIMEOUT_MS = 20_000;
|
|
10
|
+
/** Body of `function (job, readFile)`: read each file, skip binaries, match line by line, keep context. */
|
|
11
|
+
const MATCH_BODY = String.raw `
|
|
12
|
+
var regex = new RegExp(job.source, job.flags);
|
|
13
|
+
var matches = [];
|
|
14
|
+
var truncated = false;
|
|
15
|
+
var filesScanned = 0;
|
|
16
|
+
function truncateByLines(text, maxLines) {
|
|
17
|
+
var lines = text.split(/\r?\n/);
|
|
18
|
+
if (lines.length <= maxLines) return text;
|
|
19
|
+
var dropped = lines.length - maxLines;
|
|
20
|
+
return lines.slice(0, maxLines).join('\n') + '\n\n... (' + dropped + ' more line' + (dropped === 1 ? '' : 's') + ' truncated; re-read with a smaller offset to see more)';
|
|
21
|
+
}
|
|
22
|
+
for (var f = 0; f < job.files.length; f++) {
|
|
23
|
+
if (matches.length >= job.maxResults) { truncated = true; break; }
|
|
24
|
+
var file = job.files[f];
|
|
25
|
+
filesScanned++;
|
|
26
|
+
var buf;
|
|
27
|
+
try { buf = readFile(file.abs); } catch (e) { continue; }
|
|
28
|
+
if (buf.includes(0)) continue;
|
|
29
|
+
var lines = buf.toString('utf8').split(/\r?\n/);
|
|
30
|
+
for (var i = 0; i < lines.length; i++) {
|
|
31
|
+
if (matches.length >= job.maxResults) { truncated = true; break; }
|
|
32
|
+
regex.lastIndex = 0;
|
|
33
|
+
if (regex.test(lines[i])) {
|
|
34
|
+
var start = Math.max(0, i - job.contextLines);
|
|
35
|
+
var end = Math.min(lines.length - 1, i + job.contextLines);
|
|
36
|
+
var block = [];
|
|
37
|
+
for (var j = start; j <= end; j++) block.push((j === i ? '>' : ' ') + ' ' + String(j + 1).padStart(6) + '\t' + lines[j]);
|
|
38
|
+
matches.push({ path: file.rel, line: i + 1, text: truncateByLines(block.join('\n'), 10) });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { matches: matches, truncated: truncated, filesScanned: filesScanned };
|
|
43
|
+
`;
|
|
44
|
+
const WORKER_SOURCE = `
|
|
45
|
+
const { parentPort, workerData } = require('node:worker_threads');
|
|
46
|
+
const fs = require('node:fs');
|
|
47
|
+
const match = new Function('job', 'readFile', ${JSON.stringify(MATCH_BODY)});
|
|
48
|
+
parentPort.postMessage(match(workerData, (p) => fs.readFileSync(p)));
|
|
49
|
+
`;
|
|
50
|
+
function matchInProcess(job) {
|
|
51
|
+
return new Function('job', 'readFile', MATCH_BODY)(job, (p) => readFileSync(p));
|
|
52
|
+
}
|
|
53
|
+
/** Match `job` in a worker; throws when it runs longer than `timeoutMs`. Falls back to in-process if no worker starts. */
|
|
54
|
+
export function matchInWorker(job, opts) {
|
|
55
|
+
let worker;
|
|
56
|
+
try {
|
|
57
|
+
worker = (opts.startWorker ?? ((source, data) => new Worker(source, { eval: true, workerData: data })))(WORKER_SOURCE, job);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return Promise.resolve(matchInProcess(job));
|
|
61
|
+
}
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const timer = setTimeout(() => {
|
|
64
|
+
void worker.terminate();
|
|
65
|
+
reject(new Error(`The search pattern took longer than ${Math.round(opts.timeoutMs / 1000)} s and was stopped. Simplify it (avoid repeated groups that can match the same text in several ways) or search fewer files.`));
|
|
66
|
+
}, opts.timeoutMs);
|
|
67
|
+
worker.once('message', (result) => {
|
|
68
|
+
clearTimeout(timer);
|
|
69
|
+
void worker.terminate();
|
|
70
|
+
resolve(result);
|
|
71
|
+
});
|
|
72
|
+
worker.once('error', (err) => {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
reject(err);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { ToolDefinition } from '../types.js';
|
|
3
3
|
declare const params: z.ZodObject<{
|
|
4
|
-
ids: z.ZodOptional<z.ZodArray<z.ZodString
|
|
4
|
+
ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
5
5
|
timeout_seconds: z.ZodOptional<z.ZodNumber>;
|
|
6
|
-
},
|
|
7
|
-
ids?: string[] | undefined;
|
|
8
|
-
timeout_seconds?: number | undefined;
|
|
9
|
-
}, {
|
|
10
|
-
ids?: string[] | undefined;
|
|
11
|
-
timeout_seconds?: number | undefined;
|
|
12
|
-
}>;
|
|
6
|
+
}, z.core.$strip>;
|
|
13
7
|
export interface SubAgentWaitResult {
|
|
14
8
|
agents: Array<{
|
|
15
9
|
id: string;
|
|
@@ -2,84 +2,16 @@ import { z } from 'zod';
|
|
|
2
2
|
import { type AgentDef } from '../agents/agent-files.js';
|
|
3
3
|
import type { AgentConfig, ModelConfig, ToolContext, ToolDefinition } from '../types.js';
|
|
4
4
|
declare const params: z.ZodObject<{
|
|
5
|
-
/** The task for the sub-agent to perform. Free-form text. */
|
|
6
5
|
task: z.ZodString;
|
|
7
|
-
/** Name of an agent file (`.forge/agents/<name>.md`) to run as: its prompt, tools, model and step cap. */
|
|
8
6
|
agent: z.ZodOptional<z.ZodString>;
|
|
9
|
-
/** Hard cap on iterations for the sub-agent. Default 10. */
|
|
10
7
|
max_iterations: z.ZodOptional<z.ZodNumber>;
|
|
11
|
-
/**
|
|
12
|
-
* Run the sub-agent without approval prompts (autonomous). Defaults to
|
|
13
|
-
* `false` even when the parent is in `--auto` mode: the sub-agent is
|
|
14
|
-
* expected to be focused and short-lived, so the explicit opt-in is
|
|
15
|
-
* deliberate to avoid runaway destructive work.
|
|
16
|
-
*/
|
|
17
8
|
auto: z.ZodOptional<z.ZodBoolean>;
|
|
18
|
-
/**
|
|
19
|
-
* Working directory for the sub-agent. Defaults to the parent's cwd.
|
|
20
|
-
* Useful when the sub-task should operate on a subdirectory without
|
|
21
|
-
* dragging the parent through the navigation.
|
|
22
|
-
*/
|
|
23
9
|
cwd: z.ZodOptional<z.ZodString>;
|
|
24
|
-
/**
|
|
25
|
-
* Run the sub-agent in an isolated git worktree. The worktree is
|
|
26
|
-
* created at `<repoRoot>/.forge/worktrees/<label>/`, the child runs
|
|
27
|
-
* there, and the worktree is removed on completion (success or
|
|
28
|
-
* error). Falls back to plain `cwd` mode (with a stderr warning)
|
|
29
|
-
* when the parent's cwd is not inside a git repo.
|
|
30
|
-
*
|
|
31
|
-
* Pair this with `orchestrator run` parallel dispatch (v2.3) to
|
|
32
|
-
* safely run multiple specialists concurrently without them
|
|
33
|
-
* clobbering each other's files.
|
|
34
|
-
*/
|
|
35
10
|
use_worktree: z.ZodOptional<z.ZodBoolean>;
|
|
36
|
-
/**
|
|
37
|
-
* Human-readable label for the worktree (used in the branch name and
|
|
38
|
-
* directory). Defaults to a random short hash. Ignored when
|
|
39
|
-
* `use_worktree` is false.
|
|
40
|
-
*/
|
|
41
11
|
worktree_label: z.ZodOptional<z.ZodString>;
|
|
42
|
-
/**
|
|
43
|
-
* v2.14: when `use_worktree: true`, also delete the auto-created
|
|
44
|
-
* `forge/<label>-<short-sha>` branch once the worktree's working
|
|
45
|
-
* tree is gone. Default `true` because sub-agents are short-lived
|
|
46
|
-
* and orphan branches are pure clutter.
|
|
47
|
-
*
|
|
48
|
-
* Set to `false` when you want to inspect the diff afterwards (e.g.
|
|
49
|
-
* `git diff main..forge/<label>-<sha>`) or hand the branch to a
|
|
50
|
-
* human reviewer.
|
|
51
|
-
*
|
|
52
|
-
* The branch is only deleted when no other worktree currently
|
|
53
|
-
* references it, so two Forge sessions working on the same branch
|
|
54
|
-
* won't collide.
|
|
55
|
-
*/
|
|
56
12
|
cleanup_branch: z.ZodOptional<z.ZodBoolean>;
|
|
57
|
-
/**
|
|
58
|
-
* Start the child and return at once. The child keeps working while the parent continues; collect its answer with
|
|
59
|
-
* `sub_agent_wait`. Only where the surface can show background runs; elsewhere the child runs to completion as usual.
|
|
60
|
-
*/
|
|
61
13
|
background: z.ZodOptional<z.ZodBoolean>;
|
|
62
|
-
},
|
|
63
|
-
task: string;
|
|
64
|
-
agent?: string | undefined;
|
|
65
|
-
cwd?: string | undefined;
|
|
66
|
-
auto?: boolean | undefined;
|
|
67
|
-
background?: boolean | undefined;
|
|
68
|
-
max_iterations?: number | undefined;
|
|
69
|
-
use_worktree?: boolean | undefined;
|
|
70
|
-
worktree_label?: string | undefined;
|
|
71
|
-
cleanup_branch?: boolean | undefined;
|
|
72
|
-
}, {
|
|
73
|
-
task: string;
|
|
74
|
-
agent?: string | undefined;
|
|
75
|
-
cwd?: string | undefined;
|
|
76
|
-
auto?: boolean | undefined;
|
|
77
|
-
background?: boolean | undefined;
|
|
78
|
-
max_iterations?: number | undefined;
|
|
79
|
-
use_worktree?: boolean | undefined;
|
|
80
|
-
worktree_label?: string | undefined;
|
|
81
|
-
cleanup_branch?: boolean | undefined;
|
|
82
|
-
}>;
|
|
14
|
+
}, z.core.$strip>;
|
|
83
15
|
/** What `sub_agent { background: true }` returns instead of a result. */
|
|
84
16
|
export interface SubAgentStarted {
|
|
85
17
|
started: true;
|
|
@@ -145,7 +77,7 @@ export declare function childAgentConfig(setup: {
|
|
|
145
77
|
model: ModelConfig;
|
|
146
78
|
maxIterations: number;
|
|
147
79
|
systemPrompt?: string;
|
|
148
|
-
}, ctx: Pick<ToolContext, 'autoApproveTools' | 'permissionRules' | 'toolSandbox' | 'askBudget'>, cwd: string, auto: boolean): AgentConfig;
|
|
80
|
+
}, ctx: Pick<ToolContext, 'autoApproveTools' | 'permissionRules' | 'toolSandbox' | 'askBudget' | 'commandSandbox'>, cwd: string, auto: boolean): AgentConfig;
|
|
149
81
|
/** What a child runs without asking: what the parent does, else the read-only tools. Destructive tools still never run unasked. */
|
|
150
82
|
export declare function childAutoApprove(ctx: Pick<ToolContext, 'autoApproveTools'>): string[];
|
|
151
83
|
/** The configured sub-agent model, else the parent's, else a last-resort default. */
|
package/dist/tools/sub-agent.js
CHANGED
|
@@ -328,6 +328,7 @@ export function childAgentConfig(setup, ctx, cwd, auto) {
|
|
|
328
328
|
autoApproveTools: childAutoApprove(ctx),
|
|
329
329
|
...(ctx.permissionRules ? { permissionRules: ctx.permissionRules } : {}),
|
|
330
330
|
...(ctx.toolSandbox ? { toolSandbox: ctx.toolSandbox } : {}),
|
|
331
|
+
...(ctx.commandSandbox ? { commandSandbox: ctx.commandSandbox } : {}),
|
|
331
332
|
// The same budget object, not a copy: a child that started its own four
|
|
332
333
|
// would be a way around the limit the parent is under (RB-14).
|
|
333
334
|
...(ctx.askBudget ? { askBudget: ctx.askBudget } : {}),
|
package/dist/tools/todo.d.ts
CHANGED
|
@@ -7,26 +7,14 @@ import type { TodoItem, ToolDefinition } from '../types.js';
|
|
|
7
7
|
declare const writeParams: z.ZodObject<{
|
|
8
8
|
todos: z.ZodArray<z.ZodObject<{
|
|
9
9
|
content: z.ZodString;
|
|
10
|
-
status: z.ZodEnum<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}, "strip", z.ZodTypeAny, {
|
|
19
|
-
todos: {
|
|
20
|
-
status: "pending" | "in_progress" | "completed";
|
|
21
|
-
content: string;
|
|
22
|
-
}[];
|
|
23
|
-
}, {
|
|
24
|
-
todos: {
|
|
25
|
-
status: "pending" | "in_progress" | "completed";
|
|
26
|
-
content: string;
|
|
27
|
-
}[];
|
|
28
|
-
}>;
|
|
29
|
-
declare const readParams: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
10
|
+
status: z.ZodEnum<{
|
|
11
|
+
pending: "pending";
|
|
12
|
+
in_progress: "in_progress";
|
|
13
|
+
completed: "completed";
|
|
14
|
+
}>;
|
|
15
|
+
}, z.core.$strip>>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
declare const readParams: z.ZodObject<{}, z.core.$strip>;
|
|
30
18
|
export declare const todoWriteTool: ToolDefinition<z.infer<typeof writeParams>, {
|
|
31
19
|
todos: TodoItem[];
|
|
32
20
|
}>;
|
|
@@ -39,13 +39,7 @@ export declare function searchWeb(cfg: WebSearchConfig, query: string, count: nu
|
|
|
39
39
|
declare const params: z.ZodObject<{
|
|
40
40
|
query: z.ZodString;
|
|
41
41
|
max_results: z.ZodOptional<z.ZodNumber>;
|
|
42
|
-
},
|
|
43
|
-
query: string;
|
|
44
|
-
max_results?: number | undefined;
|
|
45
|
-
}, {
|
|
46
|
-
query: string;
|
|
47
|
-
max_results?: number | undefined;
|
|
48
|
-
}>;
|
|
42
|
+
}, z.core.$strip>;
|
|
49
43
|
export interface WebSearchToolResult {
|
|
50
44
|
provider: WebSearchProvider;
|
|
51
45
|
query: string;
|
|
@@ -3,13 +3,7 @@ import type { ToolDefinition } from '../types.js';
|
|
|
3
3
|
declare const params: z.ZodObject<{
|
|
4
4
|
path: z.ZodString;
|
|
5
5
|
content: z.ZodString;
|
|
6
|
-
},
|
|
7
|
-
path: string;
|
|
8
|
-
content: string;
|
|
9
|
-
}, {
|
|
10
|
-
path: string;
|
|
11
|
-
content: string;
|
|
12
|
-
}>;
|
|
6
|
+
}, z.core.$strip>;
|
|
13
7
|
export interface WriteFileResult {
|
|
14
8
|
path: string;
|
|
15
9
|
bytes: number;
|
package/dist/types.d.ts
CHANGED
|
@@ -107,6 +107,10 @@ export interface ToolContext {
|
|
|
107
107
|
* the default `child_process` runner.
|
|
108
108
|
*/
|
|
109
109
|
commandRunner?: CommandRunner;
|
|
110
|
+
/** How long `search_files` may match before its worker is stopped. Default 20 s. */
|
|
111
|
+
searchTimeoutMs?: number;
|
|
112
|
+
/** Run `run_command` inside the OS sandbox (`AgentConfig.commandSandbox`); handed to sub-agents. */
|
|
113
|
+
commandSandbox?: CommandSandbox;
|
|
110
114
|
/** The model sub-agents use instead of the parent's (`AgentConfig.subAgentModel`). */
|
|
111
115
|
subAgentModel?: ModelConfig;
|
|
112
116
|
/** Folder `AGENTS.md` paths already shown in this run; `read_file` adds each folder's file once. */
|
|
@@ -176,6 +180,13 @@ export type ModelRouter = (ctx: {
|
|
|
176
180
|
/** Tool names the model called on the previous step (empty on the first). */
|
|
177
181
|
lastToolNames: string[];
|
|
178
182
|
}) => ModelConfig | undefined;
|
|
183
|
+
/** What `run_command`'s OS sandbox allows besides writing to the workspace and the temp folder. */
|
|
184
|
+
export interface CommandSandbox {
|
|
185
|
+
/** Let commands reach the network. */
|
|
186
|
+
network: boolean;
|
|
187
|
+
/** More folders commands may write to (a package manager's cache, say). */
|
|
188
|
+
extraWritable?: string[];
|
|
189
|
+
}
|
|
179
190
|
/**
|
|
180
191
|
* Executes one shell command on behalf of `run_command`. Return `null` to decline
|
|
181
192
|
* (e.g. no terminal available); the default `child_process` runner then handles it.
|
|
@@ -250,6 +261,11 @@ export interface ChildProgressEvent {
|
|
|
250
261
|
/** Any event the child emitted. */
|
|
251
262
|
event: AgentEvent;
|
|
252
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* How a tool call was let through: the person approved it, a permission rule allowed it, it is on the
|
|
266
|
+
* auto-approve list, memory writes are allowed, the command is on the "Always allow" list, or the run is Autonomous.
|
|
267
|
+
*/
|
|
268
|
+
export type ApprovalSource = 'person' | 'rule' | 'list' | 'memory' | 'always' | 'autonomous';
|
|
253
269
|
/** Streamed agent event: surfaced to the UI via the AgentRunOptions.onEvent callback. */
|
|
254
270
|
export type AgentEvent = {
|
|
255
271
|
type: 'text_delta';
|
|
@@ -263,11 +279,14 @@ export type AgentEvent = {
|
|
|
263
279
|
} | {
|
|
264
280
|
type: 'reasoning_done';
|
|
265
281
|
text: string;
|
|
266
|
-
}
|
|
282
|
+
}
|
|
283
|
+
/** `approval` says how the call was let through; absent for bookkeeping tools that never ask (the todo list). */
|
|
284
|
+
| {
|
|
267
285
|
type: 'tool_call';
|
|
268
286
|
name: string;
|
|
269
287
|
id: string;
|
|
270
288
|
args: unknown;
|
|
289
|
+
approval?: ApprovalSource;
|
|
271
290
|
} | {
|
|
272
291
|
type: 'tool_result';
|
|
273
292
|
name: string;
|
|
@@ -343,6 +362,22 @@ export type AgentEvent = {
|
|
|
343
362
|
} | {
|
|
344
363
|
type: 'continuation'; /** 1-based count of continuations so far in this run. */
|
|
345
364
|
count: number;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* The step now running failed (a provider error worth retrying, or an empty reply) and is being asked again after
|
|
368
|
+
* `delayMs`. Everything it streamed is discarded: a UI drops the step's partial text.
|
|
369
|
+
*/
|
|
370
|
+
/** The model ended a turn with `open` items of its own todo list still open and was reminded once (RB-44). */
|
|
371
|
+
| {
|
|
372
|
+
type: 'todo_nudge';
|
|
373
|
+
open: number;
|
|
374
|
+
} | {
|
|
375
|
+
type: 'retry';
|
|
376
|
+
kind: 'provider_error' | 'empty_reply' | 'offline';
|
|
377
|
+
attempt: number;
|
|
378
|
+
maxRetries: number;
|
|
379
|
+
delayMs: number;
|
|
380
|
+
reason: string;
|
|
346
381
|
} | {
|
|
347
382
|
type: 'phase';
|
|
348
383
|
/** Architect/editor mode: which phase the following events belong to. */
|
|
@@ -564,6 +599,8 @@ export interface AgentConfig {
|
|
|
564
599
|
* be surprising.
|
|
565
600
|
*/
|
|
566
601
|
disableMemory?: boolean;
|
|
602
|
+
/** Leave out the `<stack>` block (the versions the workspace's files state). Default: included. */
|
|
603
|
+
disableStackFacts?: boolean;
|
|
567
604
|
/**
|
|
568
605
|
* Skip injecting `AGENTS.md` / `CLAUDE.md` / `CONVENTIONS.md` from the
|
|
569
606
|
* working directory into the system prompt.
|
|
@@ -740,6 +777,23 @@ export interface AgentConfig {
|
|
|
740
777
|
* Each continuation is a normal iteration (counts toward every cap).
|
|
741
778
|
*/
|
|
742
779
|
maxContinuations?: number;
|
|
780
|
+
/**
|
|
781
|
+
* Retrying a step whose model call failed with something a retry can fix (429, 5xx, overload, dropped
|
|
782
|
+
* connection). Default 5 retries, back-off from 2 s (doubling, capped at 30 s) unless the provider sends
|
|
783
|
+
* retry-after. An empty or reasoning-only reply is asked for again twice, separately.
|
|
784
|
+
*/
|
|
785
|
+
providerRetry?: {
|
|
786
|
+
maxRetries?: number;
|
|
787
|
+
baseDelayMs?: number;
|
|
788
|
+
/**
|
|
789
|
+
* With no network at all (DNS or route gone) the run waits instead of spending retries: it probes every
|
|
790
|
+
* `offlinePollMs` (default 3 s) for up to `maxOfflineMs` in total (default 15 min), then reports the error.
|
|
791
|
+
*/
|
|
792
|
+
offlinePollMs?: number;
|
|
793
|
+
maxOfflineMs?: number;
|
|
794
|
+
/** True when the network is reachable; default dials a few public addresses over TCP. */
|
|
795
|
+
networkProbe?: () => Promise<boolean>;
|
|
796
|
+
};
|
|
743
797
|
/**
|
|
744
798
|
* Pick the model for each step (cheap for exploration, strong for planning…).
|
|
745
799
|
* Return `undefined` to keep the current model. Cost is priced per routed model.
|
|
@@ -747,6 +801,11 @@ export interface AgentConfig {
|
|
|
747
801
|
modelRouter?: ModelRouter;
|
|
748
802
|
/** Replace how `run_command` executes. See {@link CommandRunner}. */
|
|
749
803
|
commandRunner?: CommandRunner;
|
|
804
|
+
/**
|
|
805
|
+
* Confine `run_command` with the OS sandbox: bubblewrap on Linux, sandbox-exec on macOS. A command is refused when
|
|
806
|
+
* the tool is missing; Windows has no equivalent, so there commands run as before. Absent = off.
|
|
807
|
+
*/
|
|
808
|
+
commandSandbox?: CommandSandbox;
|
|
750
809
|
/**
|
|
751
810
|
* Answers `ask_user`. When absent, or when `auto` is on, the model is not offered the tool.
|
|
752
811
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ikarmic/forge-core",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"description": "Agent engine for IKarmic AI Forge. Model loop, tools, MCP, sandbox, memory, compaction, plan mode, skills, hooks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -56,13 +56,13 @@
|
|
|
56
56
|
"tree-sitter-wasms": "^0.1.13",
|
|
57
57
|
"undici": "^7.30.0",
|
|
58
58
|
"web-tree-sitter": "0.20.8",
|
|
59
|
-
"zod": "^
|
|
59
|
+
"zod": "^4.6.7"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@ai-sdk/provider": "^4.0.0",
|
|
63
63
|
"@types/node": "^22.7.0",
|
|
64
64
|
"typescript": "^5.6.3",
|
|
65
|
-
"vitest": "^5.0.
|
|
65
|
+
"vitest": "^5.0.5"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
68
68
|
"build": "tsc -p tsconfig.json",
|