@sema-agent/core 2.3.0 → 2.4.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/agents/send-message-tool.d.ts +4 -0
- package/dist/agents/send-message-tool.js +37 -24
- package/dist/agents/subagent.js +275 -127
- package/dist/brain/errors.d.ts +1 -0
- package/dist/brain/errors.js +14 -0
- package/dist/brain/stream-engine.js +3 -3
- package/dist/core/context-edit.js +2 -1
- package/dist/core/runner/prepare-task.js +20 -1
- package/dist/core/runner/tool-output-projection.js +2 -1
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +37 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +195 -0
- package/dist/core/store-contracts/contract-harness.d.ts +6 -0
- package/dist/core/store-contracts/contract-harness.js +16 -0
- package/dist/core/store-contracts/contract-kit-version.d.ts +1 -0
- package/dist/core/store-contracts/contract-kit-version.js +2 -0
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +3 -0
- package/dist/core/store-contracts/file-snapshot-store-contract.js +126 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +6 -0
- package/dist/core/store-contracts/mailbox-store-contract.js +193 -0
- package/dist/core/store-contracts/session-repo-contract.d.ts +3 -0
- package/dist/core/store-contracts/session-repo-contract.js +36 -0
- package/dist/core/store-contracts/tool-result-store-contract.d.ts +3 -0
- package/dist/core/store-contracts/tool-result-store-contract.js +35 -0
- package/dist/core/task-notification.d.ts +2 -0
- package/dist/core/task-registry-agent.d.ts +4 -0
- package/dist/core/task-registry-agent.js +13 -0
- package/dist/core/task-registry-monitor.js +6 -6
- package/dist/core/task-registry-shared.d.ts +8 -2
- package/dist/core/task-registry-shared.js +1 -1
- package/dist/core/task-registry.d.ts +6 -0
- package/dist/core/task-registry.js +48 -4
- package/dist/core/tool-result-store.d.ts +3 -2
- package/dist/core/tool-result-store.js +12 -4
- package/dist/core/trace.d.ts +7 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -0
- package/dist/engine/lsp/node-lsp-manager.js +16 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/orchestration/builtin-workflows.d.ts +1 -1
- package/dist/orchestration/builtin-workflows.js +11 -2
- package/dist/orchestration/workflow-governance.d.ts +6 -1
- package/dist/orchestration/workflow-governance.js +24 -4
- package/dist/orchestration/workflow-primitives.js +7 -1
- package/dist/orchestration/workflow.d.ts +1 -0
- package/dist/orchestration/workflow.js +31 -2
- package/dist/tools/fs/fs-bash.d.ts +7 -1
- package/dist/tools/fs/fs-bash.js +51 -20
- package/dist/tools/fs/fs-read.js +22 -11
- package/dist/tools/fs/fs-search-tools.js +3 -3
- package/dist/tools/fs/fs-shared.d.ts +20 -7
- package/dist/tools/fs/fs-shared.js +17 -3
- package/dist/tools/fs/fs-write.js +4 -4
- package/dist/tools/fs/index.d.ts +2 -0
- package/dist/tools/fs/index.js +7 -1
- package/dist/tools/fs/repo-map.js +2 -2
- package/dist/tools/fs/safety.d.ts +10 -0
- package/dist/tools/fs/safety.js +15 -1
- package/dist/tools/monitor.js +18 -4
- package/dist/tools/web.js +6 -2
- package/dist/tools/worktree.js +46 -25
- package/package.json +1 -1
package/dist/tools/web.js
CHANGED
|
@@ -594,7 +594,7 @@ function classifySearchFailure(message) {
|
|
|
594
594
|
if (code === 408 || /\btimed? ?out\b|\betimedout\b/.test(m)) {
|
|
595
595
|
return { retryable: true, hint: "This looks like a timeout — a retry may succeed; a narrower query tends to return faster." };
|
|
596
596
|
}
|
|
597
|
-
if (/\
|
|
597
|
+
if (/\beconnrefused\b|\benotfound\b|\beai_again\b|\beconnreset\b|\bepipe\b|\bfetch failed\b|socket hang up|\bnetwork\b|\bdns\b/.test(m)) {
|
|
598
598
|
return { retryable: true, hint: "This is a network/transport fault, not a rejection of the query — one retry is reasonable; if it repeats, treat the search backend as unavailable and continue without it." };
|
|
599
599
|
}
|
|
600
600
|
if (code !== undefined && code >= 500 && code <= 599) {
|
|
@@ -751,6 +751,7 @@ export function createWebSearchTool(config) {
|
|
|
751
751
|
const domainFiltered = usable.filter((r) => webSearchResultAllowed(r.url, allowed_domains, blocked_domains));
|
|
752
752
|
const droppedByDomain = usable.length - domainFiltered.length;
|
|
753
753
|
const kept = domainFiltered.slice(0, max);
|
|
754
|
+
const droppedByMax = domainFiltered.length - kept.length;
|
|
754
755
|
const schemeAssumed = kept.filter((r) => r.schemeAssumed).length;
|
|
755
756
|
let clipped = false;
|
|
756
757
|
const shown = kept.map((r) => {
|
|
@@ -771,6 +772,9 @@ export function createWebSearchTool(config) {
|
|
|
771
772
|
const domainNote = droppedByDomain > 0
|
|
772
773
|
? `\n\n[WebSearch: ${droppedByDomain} result(s) were dropped by the ${allowed_domains?.length ? "allowed_domains" : "blocked_domains"} filter passed with this call — the backend returned them, this tool removed them. Relax or drop the filter to see them.]`
|
|
773
774
|
: "";
|
|
775
|
+
const maxResultsNote = droppedByMax > 0
|
|
776
|
+
? `\n\n[WebSearch: showing ${kept.length} of ${domainFiltered.length} results — the rest were cut off by this deployment's maxResults limit (${max}).]`
|
|
777
|
+
: "";
|
|
774
778
|
const clipNote = clipped
|
|
775
779
|
? "\n\n[WebSearch: one or more result fields exceeded the display limits and were truncated — treat the text above as an excerpt, not the backend's full result.]"
|
|
776
780
|
: "";
|
|
@@ -780,7 +784,7 @@ export function createWebSearchTool(config) {
|
|
|
780
784
|
const tailReminder = shown.length > 0
|
|
781
785
|
? "REMINDER: You MUST include the sources above in your response to the user using markdown hyperlinks."
|
|
782
786
|
: "REMINDER: this search returned ZERO usable sources — there is nothing above to cite. Do not fabricate sources, URLs or citations; tell the user the search returned no usable results (the notes above say why, when there is a why) and answer from what you already know, or try a different query.";
|
|
783
|
-
const modelText = `${fenced}${dropNote}${domainNote}${schemeNote}${clipNote}\n\n${tailReminder}`;
|
|
787
|
+
const modelText = `${fenced}${dropNote}${domainNote}${maxResultsNote}${schemeNote}${clipNote}\n\n${tailReminder}`;
|
|
784
788
|
return {
|
|
785
789
|
content: modelText,
|
|
786
790
|
details: {
|
package/dist/tools/worktree.js
CHANGED
|
@@ -164,11 +164,14 @@ export function createWorktreeTools(env, opts) {
|
|
|
164
164
|
const originalCwd = previous ? previous.originalCwd : cwdRef.current;
|
|
165
165
|
session.current = { worktreeDir: target, originalCwd, baseSha: head.value.stdout.trim(), entered: true };
|
|
166
166
|
cwdRef.current = target;
|
|
167
|
-
return
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
167
|
+
return {
|
|
168
|
+
content: `Switched into the existing worktree at ${target}${previous ? ` (the previous worktree at ${previous.worktreeDir} was left on disk, untouched)` : ""}. ` +
|
|
169
|
+
"The session's working directory is now this worktree — subsequent commands and relative paths " +
|
|
170
|
+
"operate there. Note this is a cwd switch, not a sandbox: file containment stays anchored at the " +
|
|
171
|
+
"task root. ExitWorktree will restore the original directory but will NOT remove a worktree " +
|
|
172
|
+
"entered via `path`.",
|
|
173
|
+
details: { type: "worktree", action: "enter", worktreeDir: target },
|
|
174
|
+
};
|
|
172
175
|
}
|
|
173
176
|
const base = await resolveBaseCommit(env, repoRoot, baseRef ?? "fresh");
|
|
174
177
|
if ("error" in base)
|
|
@@ -195,11 +198,14 @@ export function createWorktreeTools(env, opts) {
|
|
|
195
198
|
baseSha: base.sha,
|
|
196
199
|
};
|
|
197
200
|
cwdRef.current = createdDir;
|
|
198
|
-
return
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
return {
|
|
202
|
+
content: `Created worktree at ${createdDir} (base: ${base.label}${base.note ?? ""}). ` +
|
|
203
|
+
"The session's working directory is now the worktree — subsequent commands and relative paths " +
|
|
204
|
+
"operate there. Note this is a cwd switch, not a sandbox: file containment stays anchored at the " +
|
|
205
|
+
"task root, so the rest of the repository remains reachable. " +
|
|
206
|
+
"Use ExitWorktree to leave (an unchanged worktree is removed; a changed one is kept).",
|
|
207
|
+
details: { type: "worktree", action: "create", worktreeDir: createdDir, base: base.label },
|
|
208
|
+
};
|
|
203
209
|
},
|
|
204
210
|
});
|
|
205
211
|
const exit = defineTool({
|
|
@@ -245,16 +251,22 @@ export function createWorktreeTools(env, opts) {
|
|
|
245
251
|
cwdRef.current = restoredTo;
|
|
246
252
|
if (active.entered) {
|
|
247
253
|
const discardNote = discardChanges === true ? " (`discardChanges` does not apply to a worktree this session did not create)" : "";
|
|
248
|
-
return
|
|
249
|
-
`
|
|
250
|
-
|
|
254
|
+
return {
|
|
255
|
+
content: `Exited the worktree session; working directory restored to ${restoredTo}${restoreNote}. ` +
|
|
256
|
+
`The worktree at ${active.worktreeDir} was entered via \`path\` (not created by this session) and ` +
|
|
257
|
+
`was left on disk, untouched${discardNote}.`,
|
|
258
|
+
details: { type: "worktree", action: "exit", worktreeDir: active.worktreeDir, kept: true },
|
|
259
|
+
};
|
|
251
260
|
}
|
|
252
261
|
const wtThere = await env.exists(active.worktreeDir);
|
|
253
262
|
if (wtThere.ok && !wtThere.value) {
|
|
254
263
|
await pruneWorktrees(env, repoRoot).catch(() => undefined);
|
|
255
|
-
return
|
|
256
|
-
`
|
|
257
|
-
|
|
264
|
+
return {
|
|
265
|
+
content: `Exited the worktree session; working directory restored to ${restoredTo}${restoreNote}. ` +
|
|
266
|
+
`The worktree at ${active.worktreeDir} was already gone from disk (removed externally, not by this ` +
|
|
267
|
+
"session — any uncommitted work in it is lost); stale git worktree metadata was pruned.",
|
|
268
|
+
details: { type: "worktree", action: "exit", worktreeDir: active.worktreeDir, kept: false },
|
|
269
|
+
};
|
|
258
270
|
}
|
|
259
271
|
let changed = true;
|
|
260
272
|
let changeDetail = "could not verify the worktree state — keeping it to be safe";
|
|
@@ -278,10 +290,13 @@ export function createWorktreeTools(env, opts) {
|
|
|
278
290
|
const removeHint = wantsRemove && keep !== true
|
|
279
291
|
? " To remove it anyway and permanently discard these changes, re-invoke with discard_changes: true."
|
|
280
292
|
: "";
|
|
281
|
-
return
|
|
282
|
-
`
|
|
283
|
-
|
|
284
|
-
|
|
293
|
+
return {
|
|
294
|
+
content: `Exited the worktree session; working directory restored to ${restoredTo}${restoreNote}. ` +
|
|
295
|
+
`The worktree was KEPT at ${active.worktreeDir} (${why}) — inspect or merge it there, and remove it ` +
|
|
296
|
+
"later with `git worktree remove` if no longer needed." +
|
|
297
|
+
removeHint,
|
|
298
|
+
details: { type: "worktree", action: "exit", worktreeDir: active.worktreeDir, kept: true },
|
|
299
|
+
};
|
|
285
300
|
}
|
|
286
301
|
await env.exec(`git worktree remove --force ${shq(active.worktreeDir)}`, { cwd: repoRoot }).catch(() => undefined);
|
|
287
302
|
await pruneWorktrees(env, repoRoot).catch(() => undefined);
|
|
@@ -291,12 +306,18 @@ export function createWorktreeTools(env, opts) {
|
|
|
291
306
|
: changeDetail;
|
|
292
307
|
const stateClause = changed ? `had ${detailForDiscard} (discarded — discardChanges was set)` : "had no changes";
|
|
293
308
|
if (stillThere.ok && stillThere.value) {
|
|
294
|
-
return
|
|
295
|
-
`
|
|
296
|
-
|
|
309
|
+
return {
|
|
310
|
+
content: `Exited the worktree session; working directory restored to ${restoredTo}${restoreNote}. ` +
|
|
311
|
+
`The worktree at ${active.worktreeDir} ${changed ? "was marked for discard" : "had no changes"} but could NOT be removed — it is still on disk; ` +
|
|
312
|
+
"remove it manually with `git worktree remove --force` if no longer needed.",
|
|
313
|
+
details: { type: "worktree", action: "exit", worktreeDir: active.worktreeDir, kept: true },
|
|
314
|
+
};
|
|
297
315
|
}
|
|
298
|
-
return
|
|
299
|
-
`
|
|
316
|
+
return {
|
|
317
|
+
content: `Exited the worktree session; working directory restored to ${restoredTo}${restoreNote}. ` +
|
|
318
|
+
`The worktree at ${active.worktreeDir} ${stateClause} and was removed.`,
|
|
319
|
+
details: { type: "worktree", action: "exit", worktreeDir: active.worktreeDir, kept: false },
|
|
320
|
+
};
|
|
300
321
|
},
|
|
301
322
|
});
|
|
302
323
|
return [enter, exit];
|