@sema-agent/core 7.23.1 → 7.23.3
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/CHANGELOG.md +40 -0
- package/dist/agents/agent-transcript-tool.js +2 -1
- package/dist/agents/cascade.js +2 -1
- package/dist/agents/list-agents-tool.js +2 -1
- package/dist/agents/observer.js +3 -2
- package/dist/agents/peer-session-drain.js +2 -1
- package/dist/agents/retain-ledger.js +2 -1
- package/dist/agents/send-message-tool.js +11 -10
- package/dist/agents/subagent.js +18 -17
- package/dist/agents/teacher.js +5 -4
- package/dist/brain/circuit-breaker.js +2 -1
- package/dist/brain/degrading.js +2 -1
- package/dist/brain/errors.js +24 -15
- package/dist/brain/failover.js +2 -1
- package/dist/brain/stream-engine.js +2 -1
- package/dist/core/a2a.js +4 -3
- package/dist/core/artifact-host.js +2 -1
- package/dist/core/ask-question.js +3 -2
- package/dist/core/auto-promote.js +3 -2
- package/dist/core/gate-bounded-await.js +2 -1
- package/dist/core/gate-fold.js +4 -1
- package/dist/core/gate-lanes.js +4 -2
- package/dist/core/git-worktree-env.js +6 -5
- package/dist/core/hooks.js +4 -4
- package/dist/core/lsp-session.js +3 -2
- package/dist/core/mcp.js +4 -3
- package/dist/core/memory-admission.js +2 -1
- package/dist/core/memory-engine/consolidation-driver.js +5 -4
- package/dist/core/memory-engine/consolidation.js +2 -1
- package/dist/core/memory-engine/delegation-settlement.js +4 -3
- package/dist/core/memory-engine/distiller.js +8 -4
- package/dist/core/memory-engine/engine.js +63 -55
- package/dist/core/memory-engine/file-backend.js +11 -10
- package/dist/core/memory-engine/layout.js +5 -4
- package/dist/core/memory-engine/session-incarnation.js +2 -1
- package/dist/core/memory.js +2 -1
- package/dist/core/oracle-isolation.js +3 -2
- package/dist/core/permission-rule-store.js +2 -1
- package/dist/core/runner/announce-once-ledger.js +2 -1
- package/dist/core/runner/compaction-seams.js +3 -2
- package/dist/core/runner/gate-exit.d.ts +5 -0
- package/dist/core/runner/git-leg-delivery.js +4 -3
- package/dist/core/runner/git-status-frame.js +2 -1
- package/dist/core/runner/mcp-redial.js +2 -1
- package/dist/core/runner/memory-consolidation-driver.js +2 -1
- package/dist/core/runner/permission-rule-lanes.js +3 -2
- package/dist/core/runner/prepare-artifact.js +2 -1
- package/dist/core/runner/prepare-ask-lane.js +2 -1
- package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
- package/dist/core/runner/prepare-inherited-gate.js +2 -1
- package/dist/core/runner/prepare-memory-engine-session.js +2 -1
- package/dist/core/runner/prepare-memory.js +5 -4
- package/dist/core/runner/prepare-policy-chain.js +3 -2
- package/dist/core/runner/prepare-project-context.js +3 -2
- package/dist/core/runner/prepare-protocol-tools.js +3 -2
- package/dist/core/runner/prepare-suspend-saga.js +2 -1
- package/dist/core/runner/prepare-task.js +6 -5
- package/dist/core/runner/prepare-turn-wiring.js +2 -1
- package/dist/core/runner/resume-apply.js +5 -4
- package/dist/core/runner/resume-preflight.js +3 -2
- package/dist/core/runner/run-git-lane.js +4 -3
- package/dist/core/runner/run-leg.js +4 -3
- package/dist/core/runner/run-recovery-lanes.js +3 -2
- package/dist/core/runner/run-settle-and-teardown.js +2 -1
- package/dist/core/runner/run-stop-and-final-verify.js +2 -1
- package/dist/core/runner/run-telemetry-and-budget-seats.js +2 -1
- package/dist/core/runner/run-terminal-adoption.js +6 -5
- package/dist/core/runner/run-turn-boundary.js +5 -4
- package/dist/core/runner/runtask.js +2 -1
- package/dist/core/runner/stream-settle-backstop.js +5 -4
- package/dist/core/runner/stream-steer-verb.js +2 -1
- package/dist/core/runner/strict-output-schema.js +2 -1
- package/dist/core/runner/teardown-bounded.js +2 -1
- package/dist/core/safe-notify.js +2 -1
- package/dist/core/skills-directory.js +2 -1
- package/dist/core/strategy-store.js +2 -1
- package/dist/core/task-registry-agent.js +2 -1
- package/dist/core/task-registry-monitor.js +2 -1
- package/dist/core/task-registry-workflow.js +2 -1
- package/dist/core/task-registry.js +3 -2
- package/dist/core/thrown-value.d.ts +79 -0
- package/dist/core/thrown-value.js +56 -0
- package/dist/core/tool-errors.d.ts +0 -6
- package/dist/core/tool-errors.js +36 -14
- package/dist/core/tool-model-gate.js +2 -1
- package/dist/core/tool-policy.js +6 -13
- package/dist/core/tool-result-store.js +2 -1
- package/dist/core/tool-spec.d.ts +12 -0
- package/dist/core/write-protect.js +3 -2
- package/dist/engine/compaction/compaction.js +3 -4
- package/dist/engine/harness/agent-harness.js +2 -1
- package/dist/engine/harness/types.js +8 -7
- package/dist/engine/loop/agent-loop.js +7 -6
- package/dist/engine/lsp/node-lsp-manager.js +5 -4
- package/dist/engine/lsp/stdio-lsp-transport.js +12 -5
- package/dist/orchestration/dev-vm-script-runner.js +2 -1
- package/dist/orchestration/run-workflow-tool.js +7 -6
- package/dist/orchestration/workflow-governance.js +2 -1
- package/dist/orchestration/workflow-sandbox-conformance.js +3 -2
- package/dist/orchestration/workflow-script-store.js +2 -1
- package/dist/orchestration/workflow.js +15 -14
- package/dist/server/http.js +3 -2
- package/dist/stores/file/adoption/adopt.js +3 -2
- package/dist/stores/file/fs-atomic.js +2 -1
- package/dist/stores/file/permission-rule-adopt.js +2 -1
- package/dist/stores/file/permission-rule-store.js +2 -1
- package/dist/stores/file/session-store.js +4 -3
- package/dist/stores/file/strategy-store.js +7 -6
- package/dist/tools/artifact/artifact-tool.js +3 -2
- package/dist/tools/artifact/conformance.js +4 -3
- package/dist/tools/fs/bash-readonly-classifier.d.ts +20 -9
- package/dist/tools/fs/bash-readonly-classifier.js +7 -3
- package/dist/tools/fs/fs-bash.d.ts +16 -10
- package/dist/tools/fs/fs-bash.js +84 -35
- package/dist/tools/fs/fs-write.js +3 -2
- package/dist/tools/fs/safety.js +2 -1
- package/dist/tools/fs/search.js +3 -2
- package/dist/tools/monitor.js +3 -2
- package/dist/tools/sql.js +2 -1
- package/dist/tools/web.js +5 -15
- package/dist/tools/worktree.js +12 -9
- package/package.json +2 -1
- package/wire-changes/core@7.23.2.json +42 -0
- package/wire-changes/core@7.23.3.json +25 -0
|
@@ -33,12 +33,6 @@ export declare function truncateError(s: string): string;
|
|
|
33
33
|
* budget of one character. */
|
|
34
34
|
export declare const OUTPUT_BUDGET_MIN_CHARS = 512;
|
|
35
35
|
export declare function clipWithFilePointer(s: string, limit: number, fullOutputPath?: string): string;
|
|
36
|
-
/**
|
|
37
|
-
* Format a thrown tool error into model-facing text (design/64 §11.1/§11.2): a shell/exec error becomes
|
|
38
|
-
* `Exit code N` + stderr + stdout; a plain Error becomes its message (+ any captured streams); anything
|
|
39
|
-
* else is stringified. The result is truncated to {@link MAX_ERROR_CHARS}. An AbortError is reported as an
|
|
40
|
-
* interruption.
|
|
41
|
-
*/
|
|
42
36
|
export declare function formatToolError(error: unknown): string;
|
|
43
37
|
/**
|
|
44
38
|
* A typed, read-side fold of a `TaskResult.errorCode` into the failure CLASS it belongs to (design/80
|
package/dist/core/tool-errors.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Value } from "typebox/value";
|
|
|
2
2
|
const MAX_ERROR_CHARS = 10_000;
|
|
3
3
|
const HALF = MAX_ERROR_CHARS / 2;
|
|
4
4
|
import { isHighSurrogate, isLowSurrogate, sliceHeadSafe, sliceTailSafe } from "./surrogate-safe-slice.js";
|
|
5
|
+
import { readMember, thrownText } from "./thrown-value.js";
|
|
5
6
|
export function truncateError(s) {
|
|
6
7
|
if (s.length <= MAX_ERROR_CHARS)
|
|
7
8
|
return s;
|
|
@@ -31,28 +32,49 @@ export function clipWithFilePointer(s, limit, fullOutputPath) {
|
|
|
31
32
|
return `${s.slice(0, headEnd)}${markerFor(kept)}${s.slice(tailStart)}`;
|
|
32
33
|
}
|
|
33
34
|
function isShellLike(e) {
|
|
34
|
-
|
|
35
|
+
try {
|
|
36
|
+
return typeof e === "object" && e !== null && ("exitCode" in e || "stderr" in e || "stdout" in e);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function isErrorInstance(v) {
|
|
43
|
+
try {
|
|
44
|
+
return v instanceof Error;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
35
49
|
}
|
|
36
50
|
export function formatToolError(error) {
|
|
37
|
-
if (error instanceof Error && error.name === "AbortError")
|
|
38
|
-
return "Interrupted";
|
|
39
51
|
const parts = [];
|
|
52
|
+
const name = readMember(error, "name");
|
|
53
|
+
if (isErrorInstance(error) && name === "AbortError")
|
|
54
|
+
return "Interrupted";
|
|
55
|
+
const message = readMember(error, "message");
|
|
56
|
+
const messageText = typeof message === "string" ? message : undefined;
|
|
40
57
|
if (isShellLike(error)) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
const exitCode = readMember(error, "exitCode");
|
|
59
|
+
const stderr = readMember(error, "stderr");
|
|
60
|
+
const stdout = readMember(error, "stdout");
|
|
61
|
+
if (typeof exitCode === "number")
|
|
62
|
+
parts.push(`Exit code ${exitCode}`);
|
|
63
|
+
if (isErrorInstance(error) && messageText !== undefined && messageText !== "")
|
|
64
|
+
parts.push(messageText);
|
|
65
|
+
if (typeof stderr === "string" && stderr.trim())
|
|
66
|
+
parts.push(stderr);
|
|
67
|
+
if (typeof stdout === "string" && stdout.trim())
|
|
68
|
+
parts.push(stdout);
|
|
49
69
|
}
|
|
50
|
-
else if (error
|
|
51
|
-
parts.push(
|
|
70
|
+
else if (isErrorInstance(error)) {
|
|
71
|
+
parts.push((messageText ?? "") || (typeof name === "string" ? name : "") || "Error");
|
|
52
72
|
}
|
|
53
73
|
else {
|
|
54
|
-
parts.push(
|
|
74
|
+
parts.push(thrownText(error));
|
|
55
75
|
}
|
|
76
|
+
if (parts.length === 0)
|
|
77
|
+
parts.push(thrownText(error));
|
|
56
78
|
return truncateError(parts.join("\n").trim() || "Error");
|
|
57
79
|
}
|
|
58
80
|
const BRAIN_FLAT_CODES = new Set([
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { thrownText } from "./thrown-value.js";
|
|
1
2
|
export function modelIdTail(id) {
|
|
2
3
|
return id.toLowerCase().split("/").pop() ?? "";
|
|
3
4
|
}
|
|
@@ -217,7 +218,7 @@ export function applyToolModelGate(input) {
|
|
|
217
218
|
throw e;
|
|
218
219
|
let msg;
|
|
219
220
|
try {
|
|
220
|
-
msg =
|
|
221
|
+
msg = thrownText(e);
|
|
221
222
|
}
|
|
222
223
|
catch {
|
|
223
224
|
msg = "[unreportable throw]";
|
package/dist/core/tool-policy.js
CHANGED
|
@@ -8,6 +8,8 @@ import { BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName } from "../tools/f
|
|
|
8
8
|
import { protectivePathTargetOf } from "./tool-registry.js";
|
|
9
9
|
import { boundInputHashOf } from "./canonical-json.js";
|
|
10
10
|
import { delimitUntrusted, inlineUntrusted, REVIEWER_NOTE_MAX_BODY } from "./untrusted-text.js";
|
|
11
|
+
import { describeRejectedValue } from "./tool-search-setting.js";
|
|
12
|
+
import { thrownText } from "./thrown-value.js";
|
|
11
13
|
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, parsePermissionRule } from "./permission-rules.js";
|
|
12
14
|
import { protocolOf } from "./protocol-table.js";
|
|
13
15
|
import { isAbsoluteForFamily, isAbsolutePathForm, joinForFamily, normalizeAbsPathLexically, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
|
|
@@ -944,19 +946,10 @@ export function tryCloneArgs(v) {
|
|
|
944
946
|
}
|
|
945
947
|
}
|
|
946
948
|
export function describeThrown(err) {
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
const message = err.message;
|
|
952
|
-
if (typeof message === "string" && message !== "")
|
|
953
|
-
return containThrownText(message);
|
|
954
|
-
}
|
|
955
|
-
return `a non-Error value was thrown (${err === null ? "null" : typeof err})`;
|
|
956
|
-
}
|
|
957
|
-
catch {
|
|
958
|
-
return "the value could not be described";
|
|
959
|
-
}
|
|
949
|
+
const contained = containThrownText(thrownText(err));
|
|
950
|
+
if (contained !== "")
|
|
951
|
+
return contained;
|
|
952
|
+
return containThrownText(describeRejectedValue(err));
|
|
960
953
|
}
|
|
961
954
|
const THROWN_TEXT_MAX = 300;
|
|
962
955
|
function containThrownText(text) {
|
|
@@ -5,6 +5,7 @@ import { defineTool, errorResult } from "./tools.js";
|
|
|
5
5
|
import { deliverEngineNotice } from "./types.js";
|
|
6
6
|
import { TOOL_SEARCH_NAME } from "./runner/tool-disclosure.js";
|
|
7
7
|
import { toolFace } from "./tool-catalog-entries.js";
|
|
8
|
+
import { thrownText } from "./thrown-value.js";
|
|
8
9
|
export const TOOL_RESULT_REF_CONFLICT_CODE = "tool_result.ref_conflict";
|
|
9
10
|
export class ToolResultRefConflictError extends Error {
|
|
10
11
|
ref;
|
|
@@ -176,7 +177,7 @@ export function createOffloadPersist(store, sessionId, onNotice) {
|
|
|
176
177
|
return (toolCallId, fullText) => {
|
|
177
178
|
const ref = buildToolResultRef(sessionId, toolCallId, toolResultContentSegment(fullText));
|
|
178
179
|
const reportFailedWrite = (err) => {
|
|
179
|
-
const cause =
|
|
180
|
+
const cause = thrownText(err);
|
|
180
181
|
const message = `tool-result offload: persisting ref "${ref}" failed (${cause}) — this write attempt stored nothing; ` +
|
|
181
182
|
`unless an earlier attempt already stored this ref, the inline preview is all that survived. ` +
|
|
182
183
|
`A later re-clear of the same result retries the write.`;
|
package/dist/core/tool-spec.d.ts
CHANGED
|
@@ -69,6 +69,18 @@ export interface ReversibilityVerdict {
|
|
|
69
69
|
* arm with no named directory) is confirm-or-refuse, and must not be worded as though a grant answers it.
|
|
70
70
|
*/
|
|
71
71
|
mandated?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* The WEAKER rung of the same ladder as {@link mandated}: a read boundary the deployment declared was
|
|
74
|
+
* consulted and DECLINED TO JUDGE where this command reads — it named no path, so it neither declared an
|
|
75
|
+
* objection nor vouched anything. The resulting ask is ORDINARY on purpose: every ANSWERER may settle it (a
|
|
76
|
+
* person, the auto-mode classifier, a person's stored allow rule). What it excludes is the other kind of
|
|
77
|
+
* clearing — an engine table that answers nothing and merely recognises a command SHAPE
|
|
78
|
+
* (`readOnlyShellVerdict`, whose tables read program names and never paths). A mandate would take the
|
|
79
|
+
* answerers out too, a trade this class was deliberately not given. TIGHTENING-ONLY like {@link mandated}:
|
|
80
|
+
* one more question surviving one more configuration, never an ask becoming an allow, read on the demotion
|
|
81
|
+
* arm alone. Read PRESENCE, never absence.
|
|
82
|
+
*/
|
|
83
|
+
boundaryDeclined?: boolean;
|
|
72
84
|
/**
|
|
73
85
|
* The directory-scoped GRANT that would clear THIS ask, when the probe can name one: PRESENT ⇒ the only
|
|
74
86
|
* thing between this call and a plain `reversible: true` verdict is the session's declared read
|
|
@@ -3,6 +3,7 @@ import { protectivePathTargetOf } from "./tool-registry.js";
|
|
|
3
3
|
import { pathTargetBaseOf } from "./effective-path-target.js";
|
|
4
4
|
import { canonicalDataRootKeys, dataRootSpellings, relativeUnderRoot } from "./sensitive-path-policy.js";
|
|
5
5
|
import { symlinkChainHops } from "./path-identity.js";
|
|
6
|
+
import { thrownText } from "./thrown-value.js";
|
|
6
7
|
const freezeTable = (rows) => Object.freeze(rows.map((r) => Object.freeze(r)));
|
|
7
8
|
export const WRITE_PROTECTED_DEFAULT_TABLE = freezeTable([
|
|
8
9
|
{ name: ".gitconfig", kind: "basename" },
|
|
@@ -276,7 +277,7 @@ export function compileWriteProtection(entries, opts) {
|
|
|
276
277
|
noteAbsence(canon.message, canon.unresolvedSymlink === true);
|
|
277
278
|
}
|
|
278
279
|
catch (err) {
|
|
279
|
-
noteAbsence(
|
|
280
|
+
noteAbsence(thrownText(err), false);
|
|
280
281
|
}
|
|
281
282
|
try {
|
|
282
283
|
if (canonKey !== undefined) {
|
|
@@ -308,7 +309,7 @@ export function compileWriteProtection(entries, opts) {
|
|
|
308
309
|
}
|
|
309
310
|
}
|
|
310
311
|
catch (err) {
|
|
311
|
-
noteAbsence(
|
|
312
|
+
noteAbsence(thrownText(err), false);
|
|
312
313
|
}
|
|
313
314
|
return { kind: "clear" };
|
|
314
315
|
},
|
|
@@ -5,6 +5,7 @@ import { CompactionError, err, isSyntheticApiErrorMessage, ok, } from "../harnes
|
|
|
5
5
|
import { budgetInvokedSkillsRetention, computeFileLists, createFileOps, extractFileOpsFromMessage, extractInvokedSkills, extractPersistedOutputRefs, formatFileOperations, formatPersistedOutputRefs, PERSISTED_OUTPUT_REFS_MAX_ENTRIES, readElidedMessages, readPersistedOutputRefs, readRetainedInvokedSkills, readUnsummarizedMessages, replaceInvokedSkillBodiesForSummary, serializeConversation, stripFileOperationsFooter, } from "./utils.js";
|
|
6
6
|
import { ENGINE_AUTHORITY_ENVELOPE_TAGS, sanitizeUntrustedText } from "../../core/untrusted-text.js";
|
|
7
7
|
import { sliceHeadSafe } from "../../core/surrogate-safe-slice.js";
|
|
8
|
+
import { thrownText } from "../../core/thrown-value.js";
|
|
8
9
|
function safeJsonStringify(value) {
|
|
9
10
|
try {
|
|
10
11
|
return JSON.stringify(value) ?? "undefined";
|
|
@@ -803,9 +804,7 @@ async function summarizeWithPtlRetry(req) {
|
|
|
803
804
|
return ok(unwrapped);
|
|
804
805
|
}
|
|
805
806
|
const failureMessage = didThrow
|
|
806
|
-
? thrown
|
|
807
|
-
? thrown.message
|
|
808
|
-
: String(thrown)
|
|
807
|
+
? thrownText(thrown)
|
|
809
808
|
: result && !result.ok
|
|
810
809
|
? result.error.message
|
|
811
810
|
: "";
|
|
@@ -913,7 +912,7 @@ async function forkSummarize(fork, model, baseMaxTokens, apiKey, headers, custom
|
|
|
913
912
|
result = await summarizeWithLengthRecovery("Summarization", model, context, baseMaxTokens, apiKey, headers, signal, thinkingLevel, streamFn, runtime, charsPerToken);
|
|
914
913
|
}
|
|
915
914
|
catch (e) {
|
|
916
|
-
const msg =
|
|
915
|
+
const msg = thrownText(e);
|
|
917
916
|
if (parsePromptTooLong(msg).isPtl)
|
|
918
917
|
return { kind: "fallback", detail: msg };
|
|
919
918
|
throw e;
|
|
@@ -4,6 +4,7 @@ import { resolveAgentCoreStreamFn } from "../loop/runtime-deps.js";
|
|
|
4
4
|
import { normalizeEngineSegments } from "../../core/untrusted-text.js";
|
|
5
5
|
import { AUTH_CARRIER_NAMES } from "../../brain/request-params.js";
|
|
6
6
|
import { convertToLlm } from "./messages.js";
|
|
7
|
+
import { thrownText } from "../../core/thrown-value.js";
|
|
7
8
|
import { AgentHarnessError, CompactionError, SessionError, SYNTHETIC_MESSAGE_MODEL, toError, } from "./types.js";
|
|
8
9
|
const API_FAILURE_RECORD_MAX_CHARS = 2000;
|
|
9
10
|
function createUserMessage(text, images, provenance) {
|
|
@@ -57,7 +58,7 @@ function createFailureMessage(model, error, aborted) {
|
|
|
57
58
|
provider: model.provider,
|
|
58
59
|
model: model.id,
|
|
59
60
|
stopReason: aborted ? "aborted" : "error",
|
|
60
|
-
errorMessage:
|
|
61
|
+
errorMessage: thrownText(error),
|
|
61
62
|
timestamp: Date.now(),
|
|
62
63
|
usage: {
|
|
63
64
|
input: 0,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asThrownError } from "../../core/thrown-value.js";
|
|
1
2
|
export function ok(value) {
|
|
2
3
|
return { ok: true, value };
|
|
3
4
|
}
|
|
@@ -5,18 +6,18 @@ export function err(error) {
|
|
|
5
6
|
return { ok: false, error };
|
|
6
7
|
}
|
|
7
8
|
export function toError(error) {
|
|
8
|
-
if (error instanceof Error) {
|
|
9
|
-
return error;
|
|
10
|
-
}
|
|
11
|
-
if (typeof error === "string") {
|
|
12
|
-
return new Error(error);
|
|
13
|
-
}
|
|
14
9
|
try {
|
|
10
|
+
if (error instanceof Error) {
|
|
11
|
+
return error;
|
|
12
|
+
}
|
|
13
|
+
if (typeof error === "string") {
|
|
14
|
+
return new Error(error);
|
|
15
|
+
}
|
|
15
16
|
return new Error(JSON.stringify(error));
|
|
16
17
|
}
|
|
17
18
|
catch {
|
|
18
|
-
return new Error(String(error));
|
|
19
19
|
}
|
|
20
|
+
return asThrownError(error);
|
|
20
21
|
}
|
|
21
22
|
export class FileError extends Error {
|
|
22
23
|
code;
|
|
@@ -2,6 +2,7 @@ import { findToolByName, validateToolArguments } from "../llm/index.js";
|
|
|
2
2
|
import { truncateError } from "../../core/tool-errors.js";
|
|
3
3
|
import { INTERRUPTED_BY_USER_FOR_TOOL_USE_MARKER, INTERRUPTED_BY_USER_MARKER, } from "../../core/session-reconcile.js";
|
|
4
4
|
import { resolveAgentCoreStreamFn } from "./runtime-deps.js";
|
|
5
|
+
import { thrownText } from "../../core/thrown-value.js";
|
|
5
6
|
function appendTextDeltaToAssistantMessage(message, contentIndex, delta) {
|
|
6
7
|
const content = [...message.content];
|
|
7
8
|
const currentContent = content[contentIndex];
|
|
@@ -1107,7 +1108,7 @@ class StreamToolExecutor {
|
|
|
1107
1108
|
this.retainCancellation(error);
|
|
1108
1109
|
entry.immediate = {
|
|
1109
1110
|
kind: "immediate",
|
|
1110
|
-
result: createErrorToolResult(
|
|
1111
|
+
result: createErrorToolResult(thrownText(error), error),
|
|
1111
1112
|
isError: true,
|
|
1112
1113
|
};
|
|
1113
1114
|
}
|
|
@@ -1359,7 +1360,7 @@ async function prepareToolCall(currentContext, assistantMessage, toolCall, confi
|
|
|
1359
1360
|
catch (error) {
|
|
1360
1361
|
return {
|
|
1361
1362
|
kind: "immediate",
|
|
1362
|
-
result: createErrorToolResult(
|
|
1363
|
+
result: createErrorToolResult(thrownText(error), error),
|
|
1363
1364
|
isError: true,
|
|
1364
1365
|
};
|
|
1365
1366
|
}
|
|
@@ -1400,7 +1401,7 @@ async function executePreparedToolCall(prepared, signal, emit, abortResultDetail
|
|
|
1400
1401
|
}
|
|
1401
1402
|
catch (error) {
|
|
1402
1403
|
outcome = {
|
|
1403
|
-
result: createErrorToolResult(
|
|
1404
|
+
result: createErrorToolResult(thrownText(error), error),
|
|
1404
1405
|
isError: true,
|
|
1405
1406
|
};
|
|
1406
1407
|
}
|
|
@@ -1410,7 +1411,7 @@ async function executePreparedToolCall(prepared, signal, emit, abortResultDetail
|
|
|
1410
1411
|
return outcome;
|
|
1411
1412
|
const reason = deliveryFailure.reason;
|
|
1412
1413
|
const details = annotateDeliveryFailure(outcome.result, {
|
|
1413
|
-
message:
|
|
1414
|
+
message: thrownText(reason),
|
|
1414
1415
|
});
|
|
1415
1416
|
return details === UNANNOTATED ? outcome : { result: { ...outcome.result, details }, isError: outcome.isError };
|
|
1416
1417
|
})();
|
|
@@ -1482,7 +1483,7 @@ async function executePreparedWithDisclosure(currentContext, assistantMessage, p
|
|
|
1482
1483
|
if (isAbortSemanticsError(error))
|
|
1483
1484
|
throw error;
|
|
1484
1485
|
executed = {
|
|
1485
|
-
result: createErrorToolResult(`[tool execution harness failed: ${
|
|
1486
|
+
result: createErrorToolResult(`[tool execution harness failed: ${thrownText(error)}]`, error),
|
|
1486
1487
|
isError: true,
|
|
1487
1488
|
};
|
|
1488
1489
|
}
|
|
@@ -1512,7 +1513,7 @@ async function finalizeExecutedToolCall(currentContext, assistantMessage, prepar
|
|
|
1512
1513
|
}
|
|
1513
1514
|
}
|
|
1514
1515
|
catch (error) {
|
|
1515
|
-
const note = truncateError(`[post-tool processing failed (the tool already executed): ${
|
|
1516
|
+
const note = truncateError(`[post-tool processing failed (the tool already executed): ${thrownText(error)}]`);
|
|
1516
1517
|
result = { ...result, content: [...result.content, { type: "text", text: note }] };
|
|
1517
1518
|
}
|
|
1518
1519
|
if (deliveryMark !== undefined && readDeliveryFailureMark(result.details) === undefined) {
|
|
@@ -8,6 +8,7 @@ import { LspDiagnosticsRegistry } from "../../core/lsp-diagnostics.js";
|
|
|
8
8
|
import { TransportLspSession } from "../../core/lsp-session.js";
|
|
9
9
|
import { StdioLspTransport } from "./stdio-lsp-transport.js";
|
|
10
10
|
import { MAX_LSP_FILE_BYTES, SharedAbortScope, settleOnAbort } from "../../core/lsp.js";
|
|
11
|
+
import { asThrownError, thrownText } from "../../core/thrown-value.js";
|
|
11
12
|
export const DEFAULT_LSP_SERVERS = {
|
|
12
13
|
typescript: "typescript-language-server --stdio",
|
|
13
14
|
javascript: "typescript-language-server --stdio",
|
|
@@ -231,7 +232,7 @@ export class NodeLspManager {
|
|
|
231
232
|
child = await this.spawnFn(command, args, root, signal);
|
|
232
233
|
}
|
|
233
234
|
catch (e) {
|
|
234
|
-
this.log("lsp_spawn_error", { language, root, command, err:
|
|
235
|
+
this.log("lsp_spawn_error", { language, root, command, err: thrownText(e) });
|
|
235
236
|
return undefined;
|
|
236
237
|
}
|
|
237
238
|
if (!child) {
|
|
@@ -262,7 +263,7 @@ export class NodeLspManager {
|
|
|
262
263
|
}
|
|
263
264
|
else
|
|
264
265
|
this.initFailures.set(key, attempt);
|
|
265
|
-
this.log("lsp_init_degraded", { language, root, err:
|
|
266
|
+
this.log("lsp_init_degraded", { language, root, err: thrownText(e), attempt, latched });
|
|
266
267
|
return undefined;
|
|
267
268
|
}
|
|
268
269
|
this.initFailures.delete(key);
|
|
@@ -333,7 +334,7 @@ export const defaultLspSpawn = (command, args, cwd, signal) => new Promise((reso
|
|
|
333
334
|
child = spawn(command, args, lspSpawnOptions(cwd));
|
|
334
335
|
}
|
|
335
336
|
catch (e) {
|
|
336
|
-
return reject(
|
|
337
|
+
return reject(asThrownError(e));
|
|
337
338
|
}
|
|
338
339
|
child.on("error", () => { });
|
|
339
340
|
const onSpawn = () => {
|
|
@@ -345,7 +346,7 @@ export const defaultLspSpawn = (command, args, cwd, signal) => new Promise((reso
|
|
|
345
346
|
if (err?.code === "ENOENT")
|
|
346
347
|
resolve(undefined);
|
|
347
348
|
else
|
|
348
|
-
reject(
|
|
349
|
+
reject(asThrownError(err));
|
|
349
350
|
};
|
|
350
351
|
const onAbort = () => {
|
|
351
352
|
cleanup();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { encodeFrame, createFrameDecoder } from "./frame-decoder.js";
|
|
2
2
|
import { killProcessTree } from "../execution-env/kill-tree.js";
|
|
3
3
|
import { brandLspFailure } from "../../core/lsp.js";
|
|
4
|
+
import { asThrownError } from "../../core/thrown-value.js";
|
|
4
5
|
export class StdioLspTransport {
|
|
5
6
|
child;
|
|
6
7
|
requestTimeoutMs;
|
|
@@ -132,7 +133,7 @@ export class StdioLspTransport {
|
|
|
132
133
|
this.send({ jsonrpc: "2.0", id, method, params });
|
|
133
134
|
}
|
|
134
135
|
catch (e) {
|
|
135
|
-
this.failAll(brandLspFailure(
|
|
136
|
+
this.failAll(brandLspFailure(asThrownError(e), "server_terminated"));
|
|
136
137
|
}
|
|
137
138
|
});
|
|
138
139
|
}
|
|
@@ -166,8 +167,14 @@ function jsonRpcReason(code) {
|
|
|
166
167
|
return "server_error";
|
|
167
168
|
}
|
|
168
169
|
function toError(e) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
try {
|
|
171
|
+
if (e instanceof Error)
|
|
172
|
+
return e;
|
|
173
|
+
const m = e?.message;
|
|
174
|
+
if (typeof m === "string" && m)
|
|
175
|
+
return new Error(m);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
}
|
|
179
|
+
return asThrownError(e);
|
|
173
180
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import vm from "node:vm";
|
|
2
2
|
import { splitWorkflowMeta, WorkflowScriptError } from "./workflow-meta.js";
|
|
3
|
+
import { thrownText } from "../core/thrown-value.js";
|
|
3
4
|
export const WORKFLOW_DATE_ERR = "Date.now() / new Date() are unavailable in workflow scripts (breaks resume). Stamp results after the workflow returns, or pass timestamps via args.";
|
|
4
5
|
export const WORKFLOW_RANDOM_ERR = "Math.random() is unavailable in workflow scripts (breaks resume). For N independent samples, include the index in the agent label or prompt.";
|
|
5
6
|
const DETERMINISM_SHIM = `(() => {
|
|
@@ -45,7 +46,7 @@ export const devWorkflowScriptRunner = {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
catch (err) {
|
|
48
|
-
throw new WorkflowScriptError(`workflow script failed to compile: ${
|
|
49
|
+
throw new WorkflowScriptError(`workflow script failed to compile: ${thrownText(err)}`);
|
|
49
50
|
}
|
|
50
51
|
const noHostApi = (name) => () => {
|
|
51
52
|
throw new WorkflowScriptError(`${name} is not available in workflow scripts — there are no Node/host APIs here. Use agent()/log()/` +
|
|
@@ -20,6 +20,7 @@ import { mergeWorkflowArgs, normalizeStringArg } from "./workflow-script-store.j
|
|
|
20
20
|
import { builtinWorkflowListings, canonicalWorkflowName, resolveBuiltinWorkflow, workflowNameProbeOrder } from "./builtin-workflows.js";
|
|
21
21
|
import { workflowSizeGuidelineSection } from "./workflow-size-guideline.js";
|
|
22
22
|
import { toolFace } from "../core/tool-catalog-entries.js";
|
|
23
|
+
import { thrownText } from "../core/thrown-value.js";
|
|
23
24
|
export const RUN_WORKFLOW_TOOL_NAME = "Workflow";
|
|
24
25
|
function parentFaceSeat(ctxSeat, dep) {
|
|
25
26
|
if (ctxSeat !== "roots")
|
|
@@ -289,7 +290,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
289
290
|
};
|
|
290
291
|
}
|
|
291
292
|
catch (e) {
|
|
292
|
-
return { form: "script", parseError:
|
|
293
|
+
return { form: "script", parseError: thrownText(e).slice(0, 300), scriptChars: a.script.length };
|
|
293
294
|
}
|
|
294
295
|
},
|
|
295
296
|
description: "Author and run your own deterministic JS WORKFLOW that spawns and coordinates sub-agents. Pass `script` " +
|
|
@@ -425,7 +426,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
425
426
|
script = await d.scriptStore.load(rawScriptPath, taskScope ?? "default");
|
|
426
427
|
}
|
|
427
428
|
catch (err) {
|
|
428
|
-
return structuredError(`failed to read workflow script at scriptPath: ${redactSecrets(
|
|
429
|
+
return structuredError(`failed to read workflow script at scriptPath: ${redactSecrets(thrownText(err)).slice(0, 300)}`);
|
|
429
430
|
}
|
|
430
431
|
}
|
|
431
432
|
else if (typeof rawScript === "string" && rawScript.length > 0) {
|
|
@@ -444,7 +445,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
444
445
|
resolved = await d.scriptStore.resolveName(probeName);
|
|
445
446
|
}
|
|
446
447
|
catch (err) {
|
|
447
|
-
return structuredError(`failed to resolve workflow name: ${redactSecrets(
|
|
448
|
+
return structuredError(`failed to resolve workflow name: ${redactSecrets(thrownText(err)).slice(0, 300)}`);
|
|
448
449
|
}
|
|
449
450
|
const resolvedShape = resolved;
|
|
450
451
|
if (resolvedShape !== undefined && (resolvedShape === null || typeof resolvedShape !== "object")) {
|
|
@@ -478,7 +479,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
478
479
|
meta = parseWorkflowMeta(script);
|
|
479
480
|
}
|
|
480
481
|
catch (err) {
|
|
481
|
-
return structuredError(
|
|
482
|
+
return structuredError(thrownText(err));
|
|
482
483
|
}
|
|
483
484
|
try {
|
|
484
485
|
const { body } = splitWorkflowMeta(script);
|
|
@@ -489,7 +490,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
489
490
|
}
|
|
490
491
|
}
|
|
491
492
|
catch (err) {
|
|
492
|
-
return structuredError(`workflow script failed to compile: ${
|
|
493
|
+
return structuredError(`workflow script failed to compile: ${thrownText(err)}`);
|
|
493
494
|
}
|
|
494
495
|
const hostOnAsk = ctx.onAsk ?? d.parentOnAsk;
|
|
495
496
|
const hostDurableApproval = ctx.durableApprovalForChildren ?? d.parentDurableApproval;
|
|
@@ -583,7 +584,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
583
584
|
}, { workflowDepth: d.workflowDepth });
|
|
584
585
|
}
|
|
585
586
|
catch (err) {
|
|
586
|
-
return structuredError(
|
|
587
|
+
return structuredError(thrownText(err));
|
|
587
588
|
}
|
|
588
589
|
const runId = handle.runId;
|
|
589
590
|
let persistedScriptPath;
|
|
@@ -5,6 +5,7 @@ import { compileReadDeny } from "../tools/fs/read-deny.js";
|
|
|
5
5
|
import { WorkflowScriptError } from "./workflow-meta.js";
|
|
6
6
|
import { uuidv7 } from "../engine/session/uuid.js";
|
|
7
7
|
import { retiredCheckpointStoreNull } from "../core/checkpoint-store.js";
|
|
8
|
+
import { thrownText } from "../core/thrown-value.js";
|
|
8
9
|
export class WorkflowModelNotAllowedError extends Error {
|
|
9
10
|
modelName;
|
|
10
11
|
code = "workflow.model_not_allowed";
|
|
@@ -302,7 +303,7 @@ function pickWhitelist(scriptSpec) {
|
|
|
302
303
|
compileReadDeny(entries, "agent(spec).readDenyPatterns");
|
|
303
304
|
}
|
|
304
305
|
catch (err) {
|
|
305
|
-
throw new WorkflowScriptError(
|
|
306
|
+
throw new WorkflowScriptError(thrownText(err));
|
|
306
307
|
}
|
|
307
308
|
safe.readDenyPatterns = entries;
|
|
308
309
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
+
import { thrownText } from "../core/thrown-value.js";
|
|
2
3
|
const META = "export const meta = { name: 'conformance', description: 'sandbox escape probes' }\n";
|
|
3
4
|
const WITNESS_FN = "__probeWitness";
|
|
4
5
|
const WITNESS_PRELUDE = `function ${WITNESS_FN}(v) {\n` +
|
|
@@ -114,7 +115,7 @@ async function runLivenessCanary(runner) {
|
|
|
114
115
|
result = out.result;
|
|
115
116
|
}
|
|
116
117
|
catch (err) {
|
|
117
|
-
return { ok: false, detail: `run() REJECTED with: ${
|
|
118
|
+
return { ok: false, detail: `run() REJECTED with: ${thrownText(err)}` };
|
|
118
119
|
}
|
|
119
120
|
const expected = { marker: CANARY_MARKER, nonce, sum: 42, joined: `${CANARY_MARKER}:${nonce}` };
|
|
120
121
|
try {
|
|
@@ -134,7 +135,7 @@ async function runProbeBody(runner, scriptSource, primitives, family, signal) {
|
|
|
134
135
|
const live = await runLivenessCanary(runner);
|
|
135
136
|
assert.ok(live.ok, `${family}: the probe threw AND the runner then failed the liveness canary — this runner is BROKEN, ` +
|
|
136
137
|
`not blocking, so nothing about its membrane was proven. probe: ${scriptSource.slice(META.length)} | ` +
|
|
137
|
-
`probe threw: ${
|
|
138
|
+
`probe threw: ${thrownText(err)} | canary: ${live.detail}`);
|
|
138
139
|
return { executed: false };
|
|
139
140
|
}
|
|
140
141
|
}
|
|
@@ -2,6 +2,7 @@ import { mkdirSync, readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
|
2
2
|
import { join, resolve, sep } from "node:path";
|
|
3
3
|
import { physicalPathOfExisting } from "../core/physical-path.js";
|
|
4
4
|
import { sanitizeScope } from "../stores/file/fs-atomic.js";
|
|
5
|
+
import { thrownText } from "../core/thrown-value.js";
|
|
5
6
|
function isPlainObject(v) {
|
|
6
7
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
7
8
|
}
|
|
@@ -85,7 +86,7 @@ export function createFileWorkflowScriptStore(dir) {
|
|
|
85
86
|
defaultArgs = JSON.parse(readFileSync(argsPath, "utf-8"));
|
|
86
87
|
}
|
|
87
88
|
catch (err) {
|
|
88
|
-
throw new Error(`workflow script store: invalid defaultArgs JSON in ${stem}.args.json: ${
|
|
89
|
+
throw new Error(`workflow script store: invalid defaultArgs JSON in ${stem}.args.json: ${thrownText(err)}`);
|
|
89
90
|
}
|
|
90
91
|
return { script, defaultArgs };
|
|
91
92
|
},
|