@sema-agent/core 7.9.2 → 7.11.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/CHANGELOG.md +102 -0
- package/dist/agents/child-model-seat.d.ts +71 -14
- package/dist/agents/child-model-seat.js +23 -7
- package/dist/agents/subagent.d.ts +2 -2
- package/dist/agents/subagent.js +8 -5
- package/dist/agents/teacher.js +2 -2
- package/dist/core/ask-unresolvable-notice.d.ts +52 -0
- package/dist/core/ask-unresolvable-notice.js +25 -0
- package/dist/core/auto-mode-defaults.d.ts +15 -3
- package/dist/core/auto-mode-defaults.js +1 -0
- package/dist/core/auto-mode.d.ts +86 -23
- package/dist/core/auto-mode.js +43 -12
- package/dist/core/checkpoint-store.d.ts +14 -0
- package/dist/core/checkpoint-store.js +2 -1
- package/dist/core/engine-notice.d.ts +28 -7
- package/dist/core/gate-fold.js +1 -0
- package/dist/core/gate-lanes.d.ts +6 -1
- package/dist/core/gate-lanes.js +60 -18
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +4 -0
- package/dist/core/hooks.d.ts +37 -1
- package/dist/core/hooks.js +2 -0
- package/dist/core/permission-rule-model.d.ts +53 -16
- package/dist/core/permission-rule-model.js +59 -21
- package/dist/core/permission-rules.d.ts +6 -4
- package/dist/core/permission-rules.js +14 -14
- package/dist/core/persisted-rule-arms.js +4 -3
- package/dist/core/read-only-shell-table.d.ts +87 -0
- package/dist/core/read-only-shell-table.js +485 -0
- package/dist/core/read-only-shell.d.ts +42 -0
- package/dist/core/read-only-shell.js +316 -0
- package/dist/core/roles.d.ts +3 -2
- package/dist/core/runner/contracts.d.ts +26 -2
- package/dist/core/runner/denial-limit-arms.d.ts +14 -3
- package/dist/core/runner/denial-limit-arms.js +15 -5
- package/dist/core/runner/gate-exit.d.ts +5 -0
- package/dist/core/runner/permission-rule-lanes.d.ts +7 -1
- package/dist/core/runner/permission-rule-lanes.js +9 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +1 -1
- package/dist/core/runner/prepare-caps-and-workflow.js +35 -14
- package/dist/core/runner/prepare-gate-stations.d.ts +3 -2
- package/dist/core/runner/prepare-gate-stations.js +12 -0
- package/dist/core/runner/prepare-policy-chain.js +7 -6
- package/dist/core/runner/prepare-task.js +1 -1
- package/dist/core/runner/prepare-turn-wiring.js +1 -1
- package/dist/core/runner/prepare-wiring-manifest.d.ts +1 -1
- package/dist/core/runner/prepare-wiring-manifest.js +8 -1
- package/dist/core/runner/runtask.d.ts +33 -32
- package/dist/core/runner/runtask.js +63 -33
- package/dist/core/runner-deps.d.ts +9 -2
- package/dist/core/shell-lexer.d.ts +18 -0
- package/dist/core/shell-lexer.js +17 -10
- package/dist/core/shell-wrapper-table.js +8 -5
- package/dist/core/swappable-deps.d.ts +90 -0
- package/dist/core/swappable-deps.js +55 -0
- package/dist/core/tool-policy.d.ts +30 -1
- package/dist/core/tool-policy.js +6 -2
- package/dist/core/tools.d.ts +28 -7
- package/dist/core/tools.js +44 -4
- package/dist/core/trace.d.ts +15 -0
- package/dist/core/wiring-manifest.d.ts +15 -1
- package/dist/core/wiring-manifest.js +10 -2
- package/dist/core/workflow-journal-store.d.ts +21 -2
- package/dist/core/workflow-journal-store.js +1 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +2 -0
- package/dist/engine/execution-env/node-execution-env.js +2 -1
- package/dist/engine/harness/agent-harness.d.ts +3 -1
- package/dist/engine/harness/agent-harness.js +1 -1
- package/dist/engine/harness/types.d.ts +15 -2
- package/dist/index.d.ts +8 -4
- package/dist/index.js +7 -3
- package/dist/orchestration/run-workflow-tool.d.ts +22 -2
- package/dist/orchestration/run-workflow-tool.js +14 -1
- package/dist/orchestration/workflow-governance.d.ts +3 -2
- package/dist/orchestration/workflow-observe.d.ts +1 -1
- package/dist/orchestration/workflow-observe.js +2 -0
- package/dist/orchestration/workflow-primitives.d.ts +4 -1
- package/dist/orchestration/workflow-primitives.js +1 -6
- package/dist/orchestration/workflow-types.d.ts +37 -2
- package/dist/orchestration/workflow-types.js +16 -0
- package/dist/orchestration/workflow.d.ts +53 -6
- package/dist/orchestration/workflow.js +319 -51
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -2
- package/dist/stores/file/workflow-journal-store.js +10 -3
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +85 -5
|
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { closeSync, constants, createReadStream, mkdtempSync, openSync, readSync, statSync, truncateSync, unlinkSync } from "node:fs";
|
|
4
4
|
import { access, appendFile, lstat, mkdir, mkdtemp, open, readdir, readFile, readlink, realpath, rename, rm, unlink, writeFile, } from "node:fs/promises";
|
|
5
|
-
import { tmpdir } from "node:os";
|
|
5
|
+
import { homedir, tmpdir } from "node:os";
|
|
6
6
|
import { isAbsolute, join, resolve } from "node:path";
|
|
7
7
|
import { createInterface } from "node:readline";
|
|
8
8
|
import { ExecutionError, err, FileError, ok, toError, } from "../harness/types.js";
|
|
@@ -284,6 +284,7 @@ export function openSpoolPair(base) {
|
|
|
284
284
|
}
|
|
285
285
|
export class NodeExecutionEnv {
|
|
286
286
|
cwd;
|
|
287
|
+
homeDir = homedir();
|
|
287
288
|
shellPath;
|
|
288
289
|
shellEnv;
|
|
289
290
|
inheritEnv;
|
|
@@ -131,6 +131,7 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
131
131
|
private runPromise?;
|
|
132
132
|
private pendingSessionWrites;
|
|
133
133
|
private model;
|
|
134
|
+
/** The run's thinking level; `undefined` = undeclared (provider default, no wire key) — distinct from "off". */
|
|
134
135
|
private thinkingLevel;
|
|
135
136
|
/** RB-30 terminal fix — runner-set sink for engine-note payloads left undrained at agent_end. */
|
|
136
137
|
onUndrainedEngineNotes?: (payloads: unknown[]) => void;
|
|
@@ -410,7 +411,8 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
410
411
|
} & UserMessageProvenance): Promise<void>;
|
|
411
412
|
appendMessage(message: AgentMessage): Promise<void>;
|
|
412
413
|
getModel(): Model;
|
|
413
|
-
|
|
414
|
+
/** The current level, or `undefined` when none was declared (provider default — no wire key). */
|
|
415
|
+
getThinkingLevel(): ThinkingLevel | undefined;
|
|
414
416
|
setModel(model: Model): Promise<void>;
|
|
415
417
|
setThinkingLevel(level: ThinkingLevel): Promise<void>;
|
|
416
418
|
setActiveTools(toolNames: string[]): Promise<void>;
|
|
@@ -277,7 +277,7 @@ export class AgentHarness {
|
|
|
277
277
|
this.tools.set(tool.name, tool);
|
|
278
278
|
}
|
|
279
279
|
this.model = options.model;
|
|
280
|
-
this.thinkingLevel = options.thinkingLevel
|
|
280
|
+
this.thinkingLevel = options.thinkingLevel;
|
|
281
281
|
this.activeToolNames =
|
|
282
282
|
options.activeToolNames ?? (options.tools ?? []).map((tool) => tool.name);
|
|
283
283
|
this.steeringQueueMode = options.steeringMode ?? "one-at-a-time";
|
|
@@ -498,6 +498,17 @@ export interface ExecutionEnv extends FileSystem, Shell {
|
|
|
498
498
|
* SSH env to an organization-managed build host can be non-isolated yet omit this flag.
|
|
499
499
|
*/
|
|
500
500
|
readonly externalContentTarget?: boolean;
|
|
501
|
+
/**
|
|
502
|
+
* #644 — declared by the ADAPTER: the HOME DIRECTORY of the user this environment runs as, as an absolute
|
|
503
|
+
* path in the environment's own namespace. The base a `~/`-relative permission rule (`Edit(~/.ssh/**)`)
|
|
504
|
+
* resolves against for calls executing in this env. Omitted ⇒ the environment declares no home, and every
|
|
505
|
+
* `~/` deny/ask rule reads UNREADABLE for its calls (a fail-closed ask a person clears), because the only
|
|
506
|
+
* other candidate — the ENGINE PROCESS's home — is the wrong directory on any leg whose environment is not
|
|
507
|
+
* the engine host (a remote executor, a sandbox), and guarding the wrong directory silently was the
|
|
508
|
+
* defect. A local Node environment declares `os.homedir()` (it IS the host). A declared value that is not
|
|
509
|
+
* an absolute path is refused at prepare (`config.execution_env_home_dir_invalid`), never read as absent.
|
|
510
|
+
*/
|
|
511
|
+
readonly homeDir?: string;
|
|
501
512
|
}
|
|
502
513
|
/** Base fields shared by append-only session tree entries. */
|
|
503
514
|
export interface SessionTreeEntryBase {
|
|
@@ -1167,7 +1178,8 @@ export interface ModelSelectEvent {
|
|
|
1167
1178
|
export interface ThinkingLevelSelectEvent {
|
|
1168
1179
|
type: "thinking_level_select";
|
|
1169
1180
|
level: ThinkingLevel;
|
|
1170
|
-
|
|
1181
|
+
/** `undefined` when the run had no declared level before this selection (provider default). */
|
|
1182
|
+
previousLevel: ThinkingLevel | undefined;
|
|
1171
1183
|
}
|
|
1172
1184
|
export interface ResourcesUpdateEvent<TSkill extends Skill = Skill, TPromptTemplate extends PromptTemplate = PromptTemplate> {
|
|
1173
1185
|
type: "resources_update";
|
|
@@ -1335,7 +1347,8 @@ export interface AgentHarnessOptions<TSkill extends Skill = Skill, TPromptTempla
|
|
|
1335
1347
|
env: ExecutionEnv;
|
|
1336
1348
|
session: Session;
|
|
1337
1349
|
model: Model;
|
|
1338
|
-
|
|
1350
|
+
/** `undefined` = no level declared (provider default). */
|
|
1351
|
+
thinkingLevel: ThinkingLevel | undefined;
|
|
1339
1352
|
activeTools: TTool[];
|
|
1340
1353
|
resources: AgentHarnessResources<TSkill, TPromptTemplate>;
|
|
1341
1354
|
}) => string | Promise<string>);
|
package/dist/index.d.ts
CHANGED
|
@@ -54,6 +54,7 @@ export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
|
|
|
54
54
|
export { materializeMcpTools, MCP_PREFIX, type MaterializedMcp, type McpServerStatus, type McpRefreshResult } from "./core/mcp.js";
|
|
55
55
|
export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, classifyMcpFailure, type McpFailure, type McpFailureKind, type McpDelivered } from "./core/mcp-failure.js";
|
|
56
56
|
export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice, type McpInjectionDropReason, type McpInjectionDropFacts } from "./core/mcp-injection-drop.js";
|
|
57
|
+
export { askUnresolvableNotice, type AskUnresolvableFacts } from "./core/ask-unresolvable-notice.js";
|
|
57
58
|
export { materializeA2aTools, A2aRpcError, type MaterializedA2a, type A2aPeerStatus, type A2aRefreshResult, type A2aToolAxis } from "./core/a2a.js";
|
|
58
59
|
export { PROTOCOL_TABLE, MCP_NAMESPACE, A2A_NAMESPACE, protocolOf, type ProtocolNamespace, type ProtocolId } from "./core/protocol-table.js";
|
|
59
60
|
export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, type SessionPolicyStore, type SessionPermissionRules, type StoredSessionRules, type SessionRulesRecord, type PutRulesOptions, } from "./core/session-policy-store.js";
|
|
@@ -166,7 +167,8 @@ export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, create
|
|
|
166
167
|
export { type AskOrigin, ASK_ORIGINS, isAskOrigin, classifierMayAnswer, ORIGIN_IMPLIES_REAL_APPROVAL } from "./core/ask-origin.js";
|
|
167
168
|
export { SETTLEMENT_KINDS, type SettlementKind, isSettlementKind, type Settlement, SETTLEMENT_IS_REFUSAL, DENIED_BY_VALUES, type DeniedBy, isDeniedBy, DENIED_BY_MAY_VETO, type GateDisposition, type GateOutcome, screenGateOutcome } from "./core/gate-outcome.js";
|
|
168
169
|
export { type AskCarry } from "./core/hooks.js";
|
|
169
|
-
export {
|
|
170
|
+
export { SWAPPABLE_DEP_SEATS, SWAP_SEAT_NOTICE, isSwappableDepSeat, screenSwappableDeps, type SwappableDepSeat, type SwappableDeps } from "./core/swappable-deps.js";
|
|
171
|
+
export { parseAutoModeResponse, createAutoModeDecider, AUTO_MODE_UNAVAILABLE_CAUSES, isAutoModeUnavailableCause, AUTO_MODE_BREAKER_CAUSES, isAutoModeBreakerCause, AutoModeBreakerLedger, type AutoModeUnavailableCause, type AutoModeBreakerCause, type AutoModeBreakerTrip, type AutoModeVerdict, type AutoModeDecider, type AutoModeDeciderOptions, type AutoModeClassified, type AutoModeClassifyFn, type AutoModeClassifyInput, createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow, type AutoModeDenialTracker, type AutoModeDenialLimitOptions, type DenialLimitCounts, type DenialLimitFallbackFace, type UnarmedDenialLimitFallback, type DenialLimitFallback, type DenialLimitVerdict, } from "./core/auto-mode.js";
|
|
170
172
|
export { AUTO_MODE_DENIAL_LIMIT_DEFAULTS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS, AUTO_MODE_CLASSIFIER_MAX_TOKENS } from "./core/auto-mode-defaults.js";
|
|
171
173
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, type AutoModeRules, type BuildAutoModePromptOptions, type AutoModeWindowOptions, } from "./core/auto-mode-prompt.js";
|
|
172
174
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|
|
@@ -188,12 +190,14 @@ export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRul
|
|
|
188
190
|
* and nothing more. Removal is exported without ceremony, because narrowing on a user's behalf is
|
|
189
191
|
* allowed and widening is not.
|
|
190
192
|
*/
|
|
191
|
-
export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, programRunReachOf, PROGRAM_RUN_REACHES, type ProgramRunReach, type ProgramRunReachOutcome,
|
|
193
|
+
export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, programRunReachOf, PROGRAM_RUN_REACHES, type ProgramRunReach, type ProgramRunReachOutcome, pathRuleReachOf, ruleBasesNeeded, PATH_RULE_BASES, PATH_RULE_BASE_LABEL, ruleToolGrammarOf, COMMAND_RULE_TOOL, READ_RULE_TOOL, type PathRuleBase, type PathRuleBases, type RuleBehavior, type PersistedRuleVerdict, parseRuleText, formatRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
|
|
192
194
|
export { removePersistedRule, applyTombstones, sameScope, sameRuleIdentity, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, type DurableRulePartition, type DurableRulePartitionProvider, type RuleWriteOutcome, type StoredRules, type RemoveResult, type PutResult, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, type RuleSyncState, type RuleSyncFrontier, type RuleSyncDrop, type RuleSyncLandingReport, type RuleOwner, type QuarantinedRuleAdd, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, type PermissionRuleWriter, type WritableDurableRulePartition, type RuleWriteDelta, type RuleAddDelta, type RuleDeleteDelta, type RuleSyncJoinDelta, type RawRuleSyncState, type RedemptionAuthorization, } from "./core/permission-rule-store.js";
|
|
193
195
|
export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, type PermissionRuleSyncTransport, type PermissionRuleSyncResult, type RuleSyncRequestBody, type RuleSyncResponseBody, } from "./core/permission-rule-sync.js";
|
|
194
196
|
export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, type PermissionRuleStore, type PermissionRuleStoreProvider, type PermissionRuleStoreConfig, type EffectivePermissionRules, type EffectivePermissionRule, type RemovedPermissionRule, type RuleSource, } from "./core/permission-rule-provider.js";
|
|
195
197
|
export { InMemorySessionRulePartition, type SessionRulePartition, type SessionRuleAdd, type SessionRuleApplyResult, } from "./core/permission-rule-session.js";
|
|
196
|
-
export { readShellCommand, isFullyReadable, MAX_SHELL_READ_CHARS, SHELL_WRAPPER_TABLE, type ShellCommandShape, type ShellSegment, type ShellWord, type ShellWrapperName, } from "./core/shell-lexer.js";
|
|
198
|
+
export { readShellCommand, isFullyReadable, MAX_SHELL_READ_CHARS, SHELL_WRAPPER_TABLE, type ShellCommandShape, type ShellSegment, type ShellWord, type ShellRedirection, type ShellWrapperName, } from "./core/shell-lexer.js";
|
|
199
|
+
export { readOnlyShellVerdict, type ReadOnlyShellVerdict } from "./core/read-only-shell.js";
|
|
200
|
+
export { READ_ONLY_FLAG_ARITIES, FLAG_VALUE_ACCEPTS, READ_ONLY_COMMAND_TABLE, READ_ONLY_BARE_PROGRAMS, READ_ONLY_GLOB_PROGRAMS, READ_ONLY_EXACT_FORMS, READ_ONLY_BARE_ONLY, FIND_ACTION_PRIMARIES, FIND_VALUE_PRIMARIES, FIND_NEWER_PRIMARY, READ_ONLY_ENV_NAMES, XARGS_READ_ONLY_TARGETS, type ReadOnlyFlagArity, type ReadOnlyCommandRow, } from "./core/read-only-shell-table.js";
|
|
197
201
|
export { orgRuleVerdictFor, type OrgRuleVerdict, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, type OrgPermissionRule, type OrgRuleSnapshot, type OrgRuleSnapshotProvider, type OrgRuleStatePersistence, type PersistedOrgRuleState, type OrgRulePartitionConfig, type OrgRuleResolution, type OrgRuleStatus, } from "./core/permission-rule-org.js";
|
|
198
202
|
export { RULE_SYNC_DROP_CODES, type RuleSyncDropReason, type RuleQuarantineReason } from "./core/governance-codes.js";
|
|
199
203
|
export { prepareCardApproval, confirmRuleApproval, type ConfirmResult, type ConfirmRefusalReason, precheckEditedRuleText, type EditedRuleTextPrecheck, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, ruleOffersOfRecord, type RuleTicket, type RuleCandidate, type RuleApprovalKind, type RuleApprovalRecord, type RuleApprovalRecordStore, type RuleOffer2, type StaleRuleApprovalRecord, type RuleConsentDeps, type RedeemResult, type RedeemedBatchMember, type CcImportLayer, type ImportedSettingsLayer, type ImportPreview, } from "./core/permission-rule-consent.js";
|
|
@@ -228,7 +232,7 @@ export { type ReasoningIntensity, type ReasoningResolution, type ResolvedReasoni
|
|
|
228
232
|
export { DESIGN_REVIEW_PROMPTS, CODE_REVIEW_PROMPT, SCENARIO_REGISTRY, runScenario, type ScenarioId, type CodeReviewMode, type ScenarioProfile, type RunScenarioOptions, type RunScenarioResult, } from "./scenarios/scenario-registry.js";
|
|
229
233
|
export { teacherMode, TEACHER_PROFILE, type TeacherModePair, type TeacherProfile, } from "./scenarios/teacher-quickstart.js";
|
|
230
234
|
export { loadOrchestrationEnv, DEFAULT_REASONING_INTENSITY, type OrchestrationMode, type OrchestrationEnv, } from "./scenarios/env.js";
|
|
231
|
-
export { runWorkflow, startWorkflow, workflowAgentCallKey, WorkflowBudgetExceededError, WorkflowNestingError, WorkflowAgentSchemaError, WorkflowAgentStalledError, WorkflowAgentBlockedError, WORKFLOW_SPAWN_BLOCKED_ERROR_CODE, type WorkflowFanOutSlotError, type WorkflowFanOutOptions, WORKFLOW_SUBAGENT_PROMPT, WORKFLOW_SUBAGENT_PROMPT_SCHEMA, WORKFLOW_SUBAGENT_APPEND, WORKFLOW_SUBAGENT_APPEND_SCHEMA, type WorkflowHandle, MAX_WORKFLOW_ITEMS, type WorkflowRun, type WorkflowRunStatus, type WorkflowItemStatus, type WorkflowPhase, type WorkflowGroup, type WorkflowAgentRun, type WorkflowAgentHandle, type WorkflowRunStats, type WorkflowEvent, type WorkflowBudget, type WorkflowAgentOptions, type WorkflowRunContext, type WorkflowInternals, type RunWorkflowOptions, type RunWorkflowResult, type WorkflowTimers, } from "./orchestration/workflow.js";
|
|
235
|
+
export { runWorkflow, startWorkflow, workflowAgentCallKey, WorkflowBudgetExceededError, WorkflowNestingError, WorkflowAgentSchemaError, WorkflowAgentStalledError, WorkflowAgentBlockedError, WORKFLOW_SPAWN_BLOCKED_ERROR_CODE, WorkflowAgentParkedError, WORKFLOW_AGENT_PARKED_ERROR_CODE, type WorkflowParkedResume, type WorkflowFanOutSlotError, type WorkflowFanOutOptions, WORKFLOW_SUBAGENT_PROMPT, WORKFLOW_SUBAGENT_PROMPT_SCHEMA, WORKFLOW_SUBAGENT_APPEND, WORKFLOW_SUBAGENT_APPEND_SCHEMA, type WorkflowHandle, MAX_WORKFLOW_ITEMS, type WorkflowRun, type WorkflowRunStatus, type WorkflowItemStatus, type WorkflowPhase, type WorkflowGroup, type WorkflowAgentRun, type WorkflowAgentHandle, type WorkflowRunStats, type WorkflowEvent, type WorkflowBudget, type WorkflowAgentOptions, type WorkflowRunContext, type WorkflowInternals, type RunWorkflowOptions, type RunWorkflowResult, type WorkflowTimers, } from "./orchestration/workflow.js";
|
|
232
236
|
export { listWorkflowRuns, getWorkflowRun, subscribeWorkflow, deriveAgentDisplayStatus, type AgentDisplayStatus } from "./orchestration/workflow-observe.js";
|
|
233
237
|
export { runGoal, DECLARE_DONE_TOOL_NAME, type GoalSpec, type GoalResult, type GoalStatus, type GoalBudgetCause, type GoalVerdict, type GoalTurnState, type GoalVerificationKind, } from "./orchestration/goal.js";
|
|
234
238
|
export { emitTaskOutcome, type TaskOutcome } from "./core/task-outcome.js";
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
|
|
|
41
41
|
export { materializeMcpTools, MCP_PREFIX } from "./core/mcp.js";
|
|
42
42
|
export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, classifyMcpFailure } from "./core/mcp-failure.js";
|
|
43
43
|
export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice } from "./core/mcp-injection-drop.js";
|
|
44
|
+
export { askUnresolvableNotice } from "./core/ask-unresolvable-notice.js";
|
|
44
45
|
export { materializeA2aTools, A2aRpcError } from "./core/a2a.js";
|
|
45
46
|
export { PROTOCOL_TABLE, MCP_NAMESPACE, A2A_NAMESPACE, protocolOf } from "./core/protocol-table.js";
|
|
46
47
|
export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, } from "./core/session-policy-store.js";
|
|
@@ -140,19 +141,22 @@ export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, create
|
|
|
140
141
|
export { ASK_ORIGINS, isAskOrigin, classifierMayAnswer, ORIGIN_IMPLIES_REAL_APPROVAL } from "./core/ask-origin.js";
|
|
141
142
|
export { SETTLEMENT_KINDS, isSettlementKind, SETTLEMENT_IS_REFUSAL, DENIED_BY_VALUES, isDeniedBy, DENIED_BY_MAY_VETO, screenGateOutcome } from "./core/gate-outcome.js";
|
|
142
143
|
export {} from "./core/hooks.js";
|
|
143
|
-
export {
|
|
144
|
+
export { SWAPPABLE_DEP_SEATS, SWAP_SEAT_NOTICE, isSwappableDepSeat, screenSwappableDeps } from "./core/swappable-deps.js";
|
|
145
|
+
export { parseAutoModeResponse, createAutoModeDecider, AUTO_MODE_UNAVAILABLE_CAUSES, isAutoModeUnavailableCause, AUTO_MODE_BREAKER_CAUSES, isAutoModeBreakerCause, AutoModeBreakerLedger, createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow, } from "./core/auto-mode.js";
|
|
144
146
|
export { AUTO_MODE_DENIAL_LIMIT_DEFAULTS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS, AUTO_MODE_CLASSIFIER_MAX_TOKENS } from "./core/auto-mode-defaults.js";
|
|
145
147
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, } from "./core/auto-mode-prompt.js";
|
|
146
148
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|
|
147
149
|
export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoModeArmingRecipe, foldAutoModeArming, } from "./core/auto-mode-arming.js";
|
|
148
150
|
export { rebuildAutoModeDecider, } from "./core/auto-mode-rebuild.js";
|
|
149
151
|
export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRule, wildcardMatch, isNamespacedCoveringRuleName, namespacedRuleNameCovers, } from "./core/permission-rules.js";
|
|
150
|
-
export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, programRunReachOf, PROGRAM_RUN_REACHES,
|
|
152
|
+
export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, programRunReachOf, PROGRAM_RUN_REACHES, pathRuleReachOf, ruleBasesNeeded, PATH_RULE_BASES, PATH_RULE_BASE_LABEL, ruleToolGrammarOf, COMMAND_RULE_TOOL, READ_RULE_TOOL, parseRuleText, formatRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
|
|
151
153
|
export { removePersistedRule, applyTombstones, sameScope, sameRuleIdentity, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, } from "./core/permission-rule-store.js";
|
|
152
154
|
export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, } from "./core/permission-rule-sync.js";
|
|
153
155
|
export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, } from "./core/permission-rule-provider.js";
|
|
154
156
|
export { InMemorySessionRulePartition, } from "./core/permission-rule-session.js";
|
|
155
157
|
export { readShellCommand, isFullyReadable, MAX_SHELL_READ_CHARS, SHELL_WRAPPER_TABLE, } from "./core/shell-lexer.js";
|
|
158
|
+
export { readOnlyShellVerdict } from "./core/read-only-shell.js";
|
|
159
|
+
export { READ_ONLY_FLAG_ARITIES, FLAG_VALUE_ACCEPTS, READ_ONLY_COMMAND_TABLE, READ_ONLY_BARE_PROGRAMS, READ_ONLY_GLOB_PROGRAMS, READ_ONLY_EXACT_FORMS, READ_ONLY_BARE_ONLY, FIND_ACTION_PRIMARIES, FIND_VALUE_PRIMARIES, FIND_NEWER_PRIMARY, READ_ONLY_ENV_NAMES, XARGS_READ_ONLY_TARGETS, } from "./core/read-only-shell-table.js";
|
|
156
160
|
export { orgRuleVerdictFor, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, } from "./core/permission-rule-org.js";
|
|
157
161
|
export { RULE_SYNC_DROP_CODES } from "./core/governance-codes.js";
|
|
158
162
|
export { prepareCardApproval, confirmRuleApproval, precheckEditedRuleText, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, ruleOffersOfRecord, } from "./core/permission-rule-consent.js";
|
|
@@ -186,7 +190,7 @@ export { DEFAULT_EFFORT_LEVELS, REASONING_BUDGET_SHARE, isThinkingLevel, rankOf,
|
|
|
186
190
|
export { DESIGN_REVIEW_PROMPTS, CODE_REVIEW_PROMPT, SCENARIO_REGISTRY, runScenario, } from "./scenarios/scenario-registry.js";
|
|
187
191
|
export { teacherMode, TEACHER_PROFILE, } from "./scenarios/teacher-quickstart.js";
|
|
188
192
|
export { loadOrchestrationEnv, DEFAULT_REASONING_INTENSITY, } from "./scenarios/env.js";
|
|
189
|
-
export { runWorkflow, startWorkflow, workflowAgentCallKey, WorkflowBudgetExceededError, WorkflowNestingError, WorkflowAgentSchemaError, WorkflowAgentStalledError, WorkflowAgentBlockedError, WORKFLOW_SPAWN_BLOCKED_ERROR_CODE, WORKFLOW_SUBAGENT_PROMPT, WORKFLOW_SUBAGENT_PROMPT_SCHEMA, WORKFLOW_SUBAGENT_APPEND, WORKFLOW_SUBAGENT_APPEND_SCHEMA, MAX_WORKFLOW_ITEMS, } from "./orchestration/workflow.js";
|
|
193
|
+
export { runWorkflow, startWorkflow, workflowAgentCallKey, WorkflowBudgetExceededError, WorkflowNestingError, WorkflowAgentSchemaError, WorkflowAgentStalledError, WorkflowAgentBlockedError, WORKFLOW_SPAWN_BLOCKED_ERROR_CODE, WorkflowAgentParkedError, WORKFLOW_AGENT_PARKED_ERROR_CODE, WORKFLOW_SUBAGENT_PROMPT, WORKFLOW_SUBAGENT_PROMPT_SCHEMA, WORKFLOW_SUBAGENT_APPEND, WORKFLOW_SUBAGENT_APPEND_SCHEMA, MAX_WORKFLOW_ITEMS, } from "./orchestration/workflow.js";
|
|
190
194
|
export { listWorkflowRuns, getWorkflowRun, subscribeWorkflow, deriveAgentDisplayStatus } from "./orchestration/workflow-observe.js";
|
|
191
195
|
export { runGoal, DECLARE_DONE_TOOL_NAME, } from "./orchestration/goal.js";
|
|
192
196
|
export { emitTaskOutcome } from "./core/task-outcome.js";
|
|
@@ -260,8 +260,11 @@ export interface RunWorkflowToolDeps {
|
|
|
260
260
|
/** The HOST task's effective working root — threaded into every spawned agent's trusted internals so a
|
|
261
261
|
* TOC env factory can root the child at the parent's cwd (CC parity, 2026-07-03). */
|
|
262
262
|
parentCwd?: string;
|
|
263
|
-
/** Call-time getter for the
|
|
264
|
-
*
|
|
263
|
+
/** Call-time getter for the level a spawned agent runs at when neither the script, the agentType
|
|
264
|
+
* definition nor the governance baseline set `thinking` (the mount folds the deployment's STATED
|
|
265
|
+
* `roles.subagent.thinking` over the HOST task's current level — the child thinking seat's lower rungs).
|
|
266
|
+
* Threaded to the workflow as `defaultThinking` and applied at the launch site AFTER the agentType fold,
|
|
267
|
+
* the `parentModel` → `defaultModel` companion. */
|
|
265
268
|
parentThinking?: () => import("../core/types.js").TaskSpec["thinking"];
|
|
266
269
|
/** 5.30 merge-rescan (design/199 parity gap) — call-time getter for the HOST task's RESOLVED
|
|
267
270
|
* read-face containment; folds stricter-wins into every spawned workflow child (see
|
|
@@ -307,6 +310,23 @@ export interface RunWorkflowToolDeps {
|
|
|
307
310
|
* Absent on both seats ⇒ byte-identical baseline: a child's asks keep the pre-#342 resolution
|
|
308
311
|
* (`RunnerDeps.onAsk`, else the fail-closed headless auto-deny). */
|
|
309
312
|
parentOnAsk?: import("../core/tool-policy.js").OnAsk;
|
|
313
|
+
/** #642 — the HOST run's `durableApproval` opt-in (value copy; the Runner mints it from `spec.durableApproval`
|
|
314
|
+
* beside `parentOnAsk`, the same seat the delegation tool reads as `ctx.durableApprovalForChildren`). Folded
|
|
315
|
+
* into `RunWorkflowOptions.defaultDurableApproval` at execute — ONLY when a `store` is wired (the wa* row's
|
|
316
|
+
* durable home; without it the child keeps the pre-#642 lifecycle: its unavailable ask denies fail-closed
|
|
317
|
+
* and the `delegation.ask_unresolvable` notice says so). `ctx.durableApprovalForChildren` wins when a
|
|
318
|
+
* wrapping path provides it; this dep covers the auto-mounted tool's minimal execute ctx, like `parentOnAsk`.
|
|
319
|
+
* Absent on both seats ⇒ byte-identical: a workflow child's ask keeps the host-seat resolution alone. */
|
|
320
|
+
parentDurableApproval?: {
|
|
321
|
+
scope: string;
|
|
322
|
+
ttlMs?: number;
|
|
323
|
+
};
|
|
324
|
+
/** #642 — the decisions a host holds for PARKED wa* rows of a prior run, read at execute when the model
|
|
325
|
+
* re-invokes with `resumeFromRunId` (a call-time getter over the run id: the decisions arrive on the host's
|
|
326
|
+
* trusted run channel, `RunInternals.workflowParkedResume`, and only the ones naming THIS resume's source run
|
|
327
|
+
* apply). Threaded into `RunWorkflowOptions.parkedResume`: the resume drives the parked child on with the
|
|
328
|
+
* decision instead of re-parking. Never a tool argument — a model cannot decide an approval. */
|
|
329
|
+
parkedResume?: (resumeFromRunId: string) => ReadonlyArray<import("./workflow.js").WorkflowParkedResume> | undefined;
|
|
310
330
|
/** The HOST run's display sink (its `RunInternals.onForwardEvent` behind the runner's ctx wrapper:
|
|
311
331
|
* `task_progress` always, plus the children's content events — `text_delta`/`text_end`/
|
|
312
332
|
* `reasoning_delta`/`tool_start`/`tool_end`, UNTRUSTED-RAW: the consumer must redact — when the HOST spec set
|
|
@@ -5,6 +5,7 @@ import { redactSecrets, redactHostLeaks, boundedRedactedSummary } from "../core/
|
|
|
5
5
|
import { withDelegationProvenance } from "../core/tool-policy.js";
|
|
6
6
|
import { LAUNCH_RECEIPT_OWN_WORDS_CLAUSE, launchReceiptNoQuoteClause } from "../agents/launch-receipt-contract.js";
|
|
7
7
|
import { startWorkflow } from "./workflow.js";
|
|
8
|
+
import { WORKFLOW_AGENT_PARKED_ERROR_CODE } from "./workflow-types.js";
|
|
8
9
|
import { buildWorkflowPrimitives } from "./workflow-primitives.js";
|
|
9
10
|
import { parseWorkflowMeta, splitWorkflowMeta, workflowScriptReadsClockOrRandom } from "./workflow-meta.js";
|
|
10
11
|
import { mergeWorkflowArgs, normalizeStringArg } from "./workflow-script-store.js";
|
|
@@ -51,6 +52,7 @@ function workflowUsageBlock(run) {
|
|
|
51
52
|
agent_count: agents.length,
|
|
52
53
|
agents_done: agents.filter((a) => a.status === "completed").length,
|
|
53
54
|
agents_error: agents.filter((a) => a.status === "failed").length,
|
|
55
|
+
...(agents.some((a) => a.status === "parked") ? { agents_parked: agents.filter((a) => a.status === "parked").length } : {}),
|
|
54
56
|
agents_empty_result: agents.filter((a) => a.status === "completed" && (a.output === undefined || a.output === "")).length,
|
|
55
57
|
agents_replayed: agents.filter((a) => a.replayed === true).length,
|
|
56
58
|
...(run.journalSkips !== undefined && run.journalSkips > 0 ? { journal_skipped: run.journalSkips } : {}),
|
|
@@ -76,6 +78,7 @@ function workflowDiagnostics(runId, journalRef, resumeMiss) {
|
|
|
76
78
|
}
|
|
77
79
|
const SCRIPT_ERROR_CODES = new Set([
|
|
78
80
|
"workflow.script_error",
|
|
81
|
+
"workflow.parked_call_changed",
|
|
79
82
|
"workflow.nesting",
|
|
80
83
|
"workflow.model_not_allowed",
|
|
81
84
|
"workflow.agent_schema",
|
|
@@ -86,6 +89,12 @@ const SCRIPT_ERROR_CODES = new Set([
|
|
|
86
89
|
function failureSummary(err, runId) {
|
|
87
90
|
const e = err;
|
|
88
91
|
const code = typeof e?.code === "string" ? e.code : undefined;
|
|
92
|
+
if (code === WORKFLOW_AGENT_PARKED_ERROR_CODE) {
|
|
93
|
+
const msg = typeof e?.message === "string" ? redactSecrets(e.message) : "";
|
|
94
|
+
return (`workflow parked (${code}): ${msg.length > 200 ? `${msg.slice(0, 200)}…` : msg} — it did not fail and is not finished` +
|
|
95
|
+
(runId ? `; per-agent rows via TaskOutput("${runId}") (the parked row reads status "parked")` : "") +
|
|
96
|
+
`; do not re-issue the same call — once the approval is decided, the deployment resumes this run${runId ? ` (resumeFromRunId: "${runId}")` : ""} and the script continues from the parked call`);
|
|
97
|
+
}
|
|
89
98
|
const guide = runId
|
|
90
99
|
? `; per-agent rows via TaskOutput("${runId}"); after fixing, re-invoke with resumeFromRunId: "${runId}" (completed agents replay from the journal)`
|
|
91
100
|
: "";
|
|
@@ -465,6 +474,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
465
474
|
return structuredError(`workflow script failed to compile: ${err instanceof Error ? err.message : String(err)}`);
|
|
466
475
|
}
|
|
467
476
|
const hostOnAsk = ctx.onAsk ?? d.parentOnAsk;
|
|
477
|
+
const hostDurableApproval = ctx.durableApprovalForChildren ?? d.parentDurableApproval;
|
|
468
478
|
const runGovernance = hostOnAsk !== undefined && governance.baseline.base.onAsk === undefined
|
|
469
479
|
? {
|
|
470
480
|
...governance,
|
|
@@ -478,7 +488,7 @@ export async function createRunWorkflowTool(d) {
|
|
|
478
488
|
}
|
|
479
489
|
: governance;
|
|
480
490
|
const scriptFn = (wfCtx) => {
|
|
481
|
-
const primitives = buildWorkflowPrimitives(wfCtx, runGovernance, d.onAgentSpawn,
|
|
491
|
+
const primitives = buildWorkflowPrimitives(wfCtx, runGovernance, d.onAgentSpawn, principal, ctx.checkpointStoreDisabledForChildren === true || d.parentCheckpointStoreDisabled === true, d.parentReadFace, d.parentReadDenyPatterns, ctx.handsReadOnly === true || d.parentHandsReadOnly === true, ctx.interactiveTools === false || d.parentInteractiveTools === false);
|
|
482
492
|
return d.scriptRunner.run({ scriptSource: script, primitives, scriptArgs: effectiveArgs, signal: wfCtx.signal }).then((r) => r.result);
|
|
483
493
|
};
|
|
484
494
|
if (ctx.signal?.aborted) {
|
|
@@ -536,7 +546,10 @@ export async function createRunWorkflowTool(d) {
|
|
|
536
546
|
return d.parentMemoryCaptureState !== undefined ? { parentMemoryCaptureState: d.parentMemoryCaptureState } : {};
|
|
537
547
|
})(),
|
|
538
548
|
...(d.parentModel !== undefined ? { defaultModel: d.parentModel } : {}),
|
|
549
|
+
...(d.parentThinking !== undefined ? { defaultThinking: d.parentThinking } : {}),
|
|
539
550
|
...(d.parentGetApiKeyAndHeaders !== undefined ? { defaultGetApiKeyAndHeaders: d.parentGetApiKeyAndHeaders } : {}),
|
|
551
|
+
...(hostDurableApproval !== undefined && d.store !== undefined ? { defaultDurableApproval: { ...hostDurableApproval } } : {}),
|
|
552
|
+
...(resumeFromRunId !== undefined && d.parkedResume !== undefined && d.parkedResume(resumeFromRunId) !== undefined ? { parkedResume: d.parkedResume(resumeFromRunId) } : {}),
|
|
540
553
|
...(parentCenterArtifactDigest !== undefined ? { parentCenterArtifactDigest } : {}),
|
|
541
554
|
...(parentCenterSourceRevision !== undefined ? { parentCenterSourceRevision } : {}),
|
|
542
555
|
...((ctx.forwardEvent ?? d.forwardEvent) !== undefined ? { onForwardEvent: (ctx.forwardEvent ?? d.forwardEvent) } : {}),
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* (toolPolicy / onAsk / hooks / principal / tools / mcp / skills / lspManager / checkpointStore /
|
|
9
9
|
* getApiKeyAndHeaders / promptProvider / sessionId / signal / …) is structurally never copied. "Never
|
|
10
10
|
* copied" is a statement about the SCRIPT's spec — the child's control plane still arrives from the
|
|
11
|
-
* TRUSTED side, and some of it inherits from the HOST run on trusted lanes of its own: `principal` /
|
|
12
|
-
*
|
|
11
|
+
* TRUSTED side, and some of it inherits from the HOST run on trusted lanes of its own: `principal` / the
|
|
12
|
+
* durable off-switch via `buildWorkflowPrimitives`' engine injections, `model` / `thinking` / the stated
|
|
13
|
+
* subagent persona via the launch site's child seats (`withWorkflowChildSeats`), and the host's
|
|
13
14
|
* effective approver via the run-workflow mount's base-slot fold (`RunWorkflowToolDeps.parentOnAsk` →
|
|
14
15
|
* `baseline.base.onAsk`, backlog #342 — filled only when the deployment did not pin the seat). Those are
|
|
15
16
|
* host-ctx bindings the engine writes onto the baseline/child, never a read of anything the script wrote:
|
|
@@ -56,7 +56,7 @@ export declare function listWorkflowRuns(store: WorkflowRunStore, scope: string,
|
|
|
56
56
|
*/
|
|
57
57
|
export declare function getWorkflowRun(store: WorkflowRunStore, id: string, scope: string): Promise<WorkflowRun | null>;
|
|
58
58
|
/** design/99 MF-W display status. */
|
|
59
|
-
export type AgentDisplayStatus = "queued" | "running" | "done" | "failed" | "interrupted";
|
|
59
|
+
export type AgentDisplayStatus = "queued" | "running" | "done" | "failed" | "interrupted" | "parked";
|
|
60
60
|
/**
|
|
61
61
|
* design/99 MF-W (design-review DoR ⑤+⑥): the SHARED, anti-drift projection of a workflow agent's record-level
|
|
62
62
|
* status → a CC-style display status, derived PURELY from the persisted record (the agent's `status` + `startedAt`
|
|
@@ -66,6 +66,8 @@ export function deriveAgentDisplayStatus(agent, runStatus) {
|
|
|
66
66
|
return "done";
|
|
67
67
|
if (agent.status === "failed")
|
|
68
68
|
return "failed";
|
|
69
|
+
if (agent.status === "parked")
|
|
70
|
+
return "parked";
|
|
69
71
|
if (runStatus !== "running")
|
|
70
72
|
return "interrupted";
|
|
71
73
|
return agent.startedAt === undefined ? "queued" : "running";
|
|
@@ -31,8 +31,11 @@ export interface WorkflowGovernance {
|
|
|
31
31
|
/**
|
|
32
32
|
* Build the flat {@link WorkflowPrimitives} a {@link WorkflowScriptRunner} runs the script against. The
|
|
33
33
|
* `agent` primitive is GOVERNED when `governance` is set (LLM-authored), else a trusted pass-through.
|
|
34
|
+
* The host's model and thinking are NOT injected here: both are seats the launch site (`workflow.ts`,
|
|
35
|
+
* `withWorkflowChildSeats`) fills AFTER the agentType fold, so a definition's own value is the explicit rung
|
|
36
|
+
* — filling them here ran ahead of the fold and made the fold's "when unset" guard permanently false.
|
|
34
37
|
*/
|
|
35
|
-
export declare function buildWorkflowPrimitives(ctx: WorkflowRunContext, governance?: WorkflowGovernance, onAgentSpawn?: (handle: WorkflowAgentHandle) => void,
|
|
38
|
+
export declare function buildWorkflowPrimitives(ctx: WorkflowRunContext, governance?: WorkflowGovernance, onAgentSpawn?: (handle: WorkflowAgentHandle) => void, parentPrincipal?: string,
|
|
36
39
|
/** ruled 2026-08-04 — the host run set `TaskSpec.checkpointStore: "disabled"` (the per-run durable off
|
|
37
40
|
* switch). Every agent this workflow spawns inherits it; see the injection below. */
|
|
38
41
|
parentCheckpointStoreDisabled?: boolean,
|
|
@@ -65,7 +65,7 @@ function formatResourceClampNote(notes) {
|
|
|
65
65
|
const parts = notes.map((n) => `${n.field}: requested ${n.requested === undefined ? "unset" : n.requested} → applied ${n.applied}`);
|
|
66
66
|
return `workflow governance tightened this agent's resource limits (${parts.join("; ")})`;
|
|
67
67
|
}
|
|
68
|
-
export function buildWorkflowPrimitives(ctx, governance, onAgentSpawn,
|
|
68
|
+
export function buildWorkflowPrimitives(ctx, governance, onAgentSpawn, parentPrincipal, parentCheckpointStoreDisabled, parentReadFace, parentReadDenyPatterns, parentHandsReadOnly, parentInteractiveToolsOff) {
|
|
69
69
|
const agent = (spec, opts) => {
|
|
70
70
|
if (typeof spec === "string")
|
|
71
71
|
spec = { objective: spec };
|
|
@@ -74,11 +74,6 @@ export function buildWorkflowPrimitives(ctx, governance, onAgentSpawn, parentThi
|
|
|
74
74
|
const childSpec = governance
|
|
75
75
|
? buildGovernedChildSpec(spec, effectiveBaseline(governance.baseline), governance.models, governance.caps, (notes) => ctx.log(formatResourceClampNote(notes)), governance.onNotice)
|
|
76
76
|
: { ...spec };
|
|
77
|
-
if (childSpec.thinking === undefined && parentThinking) {
|
|
78
|
-
const inherited = parentThinking();
|
|
79
|
-
if (inherited !== undefined)
|
|
80
|
-
childSpec.thinking = inherited;
|
|
81
|
-
}
|
|
82
77
|
if (childSpec.principal === undefined && parentPrincipal !== undefined) {
|
|
83
78
|
childSpec.principal = parentPrincipal;
|
|
84
79
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { TaskResult, TaskStatus, ToolActivity } from "../core/types.js";
|
|
2
2
|
export type WorkflowRunStatus = "running" | "completed" | "failed";
|
|
3
|
-
/** Status of one phase / agent-run within a workflow.
|
|
4
|
-
|
|
3
|
+
/** Status of one phase / agent-run within a workflow. `"parked"` (#642) is an AGENT row's word only — the
|
|
4
|
+
* agent durably paused at an approval gate and the run suspended on it (the row carries the token, see
|
|
5
|
+
* {@link WorkflowAgentRun.parkedCheckpointToken}); a phase or group never parks (a parked agent ends the run). */
|
|
6
|
+
export type WorkflowItemStatus = "running" | "completed" | "failed" | "parked";
|
|
5
7
|
export interface WorkflowPhase {
|
|
6
8
|
title: string;
|
|
7
9
|
/** F7/B7 (CC pretty.js:446478): a phase PRE-REGISTERED from `meta.phases` starts as `"pending"` — the plan
|
|
@@ -119,6 +121,16 @@ export interface WorkflowAgentRun {
|
|
|
119
121
|
* (`fork(sessionId)→runTask`, or `runTask({sessionId})`) instead of a fresh re-run. An opaque id (not
|
|
120
122
|
* content) → scope-gated via `getWorkflowRun`, no redaction needed. Absent for a stub run that minted none. */
|
|
121
123
|
sessionId?: string;
|
|
124
|
+
/**
|
|
125
|
+
* #642 — the durable-approval checkpoint token this agent is PARKED on (`status: "parked"` only): the child
|
|
126
|
+
* durably paused at an approval gate under the host's forwarded `durableApproval`, the run recorded the
|
|
127
|
+
* park here and suspended. The mirror of the background agent row's `parkedCheckpointToken`, and the
|
|
128
|
+
* workflow-origin JOIN a host routes a parked approval by: a checkpoint whose `sourceTaskId` equals this
|
|
129
|
+
* row's {@link sessionId} is a workflow child's park, and this token is the same row's redemption key —
|
|
130
|
+
* the checkpoint row itself carries no workflow key. It is the resume CAPABILITY (never log it or put it
|
|
131
|
+
* in a URL); a durable row is its home exactly as on the background lane. Absent on every other status.
|
|
132
|
+
*/
|
|
133
|
+
parkedCheckpointToken?: string;
|
|
122
134
|
/**
|
|
123
135
|
* #499 — the ENGINE-minted identity of the task run behind this record (= its `TaskResult.runId`).
|
|
124
136
|
*
|
|
@@ -515,6 +527,29 @@ export declare class WorkflowAgentBlockedError extends Error {
|
|
|
515
527
|
/** Human-readable cause, already bounded + redacted by the engine (classifier text is model output). */
|
|
516
528
|
reason: string);
|
|
517
529
|
}
|
|
530
|
+
/** #642 — the machine code of a run that SUSPENDED on a parked agent (the thrown error's `code`, the run's
|
|
531
|
+
* failed terminal). Not a script fault and not a host fault: an approval a person still has to decide. */
|
|
532
|
+
export declare const WORKFLOW_AGENT_PARKED_ERROR_CODE = "workflow.agent_parked";
|
|
533
|
+
/**
|
|
534
|
+
* #642 — thrown by `ctx.agent` / `ctx.agentStream().result()` when the child durably PAUSED at an approval gate
|
|
535
|
+
* under the host's forwarded `durableApproval` (the workflow lane's park family, the background delegation's
|
|
536
|
+
* twin): the wa* row records `status:"parked"` + `parkedCheckpointToken`, the journal records the parked leg at
|
|
537
|
+
* its ordinal, and the RUN SUSPENDS — every later spawn is refused with this same error and the run's terminal
|
|
538
|
+
* is this park whatever the script body returns (the team-discussion `teamPause` shape). Nothing after the
|
|
539
|
+
* parked call runs; the script must not retry it (an identical call parks again). A resume of the run
|
|
540
|
+
* (`resumeFromRunId`) with the host's decision for the token drives the parked child on and the script
|
|
541
|
+
* continues from here; without a decision the ordinal re-parks.
|
|
542
|
+
*
|
|
543
|
+
* Carries the non-secret `checkpointId` (display/correlation) and the gate kind — never the token (the resume
|
|
544
|
+
* capability lives on the wa* row, a durable row, exactly as on the background lane).
|
|
545
|
+
*/
|
|
546
|
+
export declare class WorkflowAgentParkedError extends Error {
|
|
547
|
+
readonly label: string;
|
|
548
|
+
readonly gateKind: string;
|
|
549
|
+
readonly checkpointId?: string | undefined;
|
|
550
|
+
readonly code = "workflow.agent_parked";
|
|
551
|
+
constructor(label: string, gateKind: string, checkpointId?: string | undefined);
|
|
552
|
+
}
|
|
518
553
|
/** design/98 §D.6 hard cap: thrown by `ctx.agent` once the workflow has spawned `max` agents (a runaway
|
|
519
554
|
* LLM-authored script is bounded, not trusted — this counts cumulative spawns, so it binds even when the
|
|
520
555
|
* token budget has room left, or when no budget was set at all). */
|
|
@@ -55,6 +55,22 @@ export class WorkflowAgentBlockedError extends Error {
|
|
|
55
55
|
this.name = "WorkflowAgentBlockedError";
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
export const WORKFLOW_AGENT_PARKED_ERROR_CODE = "workflow.agent_parked";
|
|
59
|
+
export class WorkflowAgentParkedError extends Error {
|
|
60
|
+
label;
|
|
61
|
+
gateKind;
|
|
62
|
+
checkpointId;
|
|
63
|
+
code = WORKFLOW_AGENT_PARKED_ERROR_CODE;
|
|
64
|
+
constructor(label, gateKind, checkpointId) {
|
|
65
|
+
super(`workflow agent "${label}" is parked at an approval gate (${gateKind}${checkpointId !== undefined ? `, checkpoint ${checkpointId}` : ""}) — ` +
|
|
66
|
+
"the workflow is suspended until the approval is decided; nothing after this call runs. Do not re-issue the call: " +
|
|
67
|
+
"a resume of this run carrying the decision continues from here.");
|
|
68
|
+
this.label = label;
|
|
69
|
+
this.gateKind = gateKind;
|
|
70
|
+
this.checkpointId = checkpointId;
|
|
71
|
+
this.name = "WorkflowAgentParkedError";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
58
74
|
export class WorkflowMaxAgentsError extends Error {
|
|
59
75
|
max;
|
|
60
76
|
budgetTotal;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TSchema } from "typebox";
|
|
2
|
-
import type { RunnerSelfSeat } from "../core/runner/contracts.js";
|
|
3
|
-
import type {
|
|
2
|
+
import type { InheritedGate, RunnerSelfSeat } from "../core/runner/contracts.js";
|
|
3
|
+
import type { CheckpointToken, ResumeOutcome } from "../core/checkpoint-store.js";
|
|
4
|
+
import type { AgentDefinition, TaskEvent, TaskResult, TaskSpec, ThinkingLevel } from "../core/types.js";
|
|
4
5
|
import type { WorkflowRunStore } from "../core/workflow-run-store.js";
|
|
5
6
|
import type { WorkflowJournalStore, ResumeClaimArgs } from "../core/workflow-journal-store.js";
|
|
6
7
|
import type { WorkflowRun, WorkflowEvent } from "./workflow-types.js";
|
|
@@ -21,9 +22,11 @@ export declare const WORKFLOW_SUBAGENT_APPEND_SCHEMA = "---\n\nNOTE: You are run
|
|
|
21
22
|
* Apply the G5 default persona to a `ctx.agent`/`ctx.agentStream` child spec. Two-state on the EFFECTIVE
|
|
22
23
|
* schema (`agentOpts.schema` wins over a spec-carried `outputSchema`, same as the runSpec injection):
|
|
23
24
|
* • no `spec.systemPrompt` → the dedicated workflow-subagent persona REPLACES the role base (198
|
|
24
|
-
* default `workflow-subagent` agent-type semantics)
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* default `workflow-subagent` agent-type semantics) — reached only when neither the script, the
|
|
26
|
+
* agentType definition nor the deployment's stated subagent preset supplied one ({@link withWorkflowChildSeats}
|
|
27
|
+
* writes the preset first);
|
|
28
|
+
* • a `spec.systemPrompt` (custom persona: script, definition or stated preset) → the matching NOTE is
|
|
29
|
+
* APPENDED via `appendSystemPrompt` (198 composite semantics — append, never replace), after any existing append.
|
|
27
30
|
* Called AFTER the call-key is computed (the journal identity keys the AUTHORED spec, so a resume across
|
|
28
31
|
* core versions replays cleanly; the persona is an execution detail, not call identity).
|
|
29
32
|
*/
|
|
@@ -120,7 +123,9 @@ export declare class WorkflowJournalIncompatibleError extends Error {
|
|
|
120
123
|
readonly fromRunId: string;
|
|
121
124
|
readonly ordinal: number;
|
|
122
125
|
readonly code = "workflow.journal_incompatible";
|
|
123
|
-
constructor(fromRunId: string, ordinal: number
|
|
126
|
+
constructor(fromRunId: string, ordinal: number,
|
|
127
|
+
/** #642: an alternative reason clause (the parked-row cross-check); absent ⇒ the no-terminal-cause wording. */
|
|
128
|
+
reason?: string);
|
|
124
129
|
}
|
|
125
130
|
/**
|
|
126
131
|
* A TRUSTED, run-scoped internal channel carrying the workflow **nesting depth** across a process boundary
|
|
@@ -282,6 +287,18 @@ export interface WorkflowRunContext {
|
|
|
282
287
|
/** Emit a narrator log line (observability only — not stored on the run). */
|
|
283
288
|
log(message: string): void;
|
|
284
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* #642 — one decision a resume carries for a PARKED ordinal of the prior run ({@link RunWorkflowOptions.parkedResume}):
|
|
292
|
+
* the checkpoint token the wa* row is parked on (the row's `parkedCheckpointToken`, the redemption key), the
|
|
293
|
+
* caller's decision for it (the same {@link ResumeOutcome} a top-level `runner.resume` takes), and the optional
|
|
294
|
+
* cross-process re-supply of the checkpoint's opaque parent constraints. The token is matched by string equality
|
|
295
|
+
* against the journaled parked entry — an entry whose token no decision names re-parks.
|
|
296
|
+
*/
|
|
297
|
+
export interface WorkflowParkedResume {
|
|
298
|
+
token: CheckpointToken;
|
|
299
|
+
outcome: ResumeOutcome;
|
|
300
|
+
inheritedGate?: InheritedGate;
|
|
301
|
+
}
|
|
285
302
|
export interface RunWorkflowOptions {
|
|
286
303
|
/** Trusted caller-supplied run id. Used by the unified task registry so tool-launched workflows expose
|
|
287
304
|
* `task_id === runId` (`w*`) without making the model choose an id. Omit for the legacy UUID mint path. */
|
|
@@ -431,10 +448,40 @@ export interface RunWorkflowOptions {
|
|
|
431
448
|
* re-resolution that loses per-model routing (the 4/4-agents-404 incident: session model id
|
|
432
449
|
* re-resolved against the base gateway). Mirrors the subagent lane's `ctx.model` semantics. */
|
|
433
450
|
defaultModel?: () => import("../internal/llm.js").Model | undefined;
|
|
451
|
+
/** Call-time getter for the thinking level a spawned agent runs at when neither the script, the
|
|
452
|
+
* agentType definition nor the governance baseline set `thinking` — the child thinking seat's lower rungs
|
|
453
|
+
* (the deployment's STATED `roles.subagent.thinking`, else the host's current level), as the run-workflow
|
|
454
|
+
* mount folds them. Snapshotted ONCE at call entry and folded into the call identity like `defaultModel`;
|
|
455
|
+
* applied at the launch site AFTER the agentType fold ({@link withWorkflowChildSeats}). */
|
|
456
|
+
defaultThinking?: () => ThinkingLevel | undefined;
|
|
434
457
|
/** The HOST's per-model auth hook, inherited into every spawned agent's spec (the
|
|
435
458
|
* credential half of model inheritance; scripts can never set it — governance strips it — so
|
|
436
459
|
* this is always the host's). NOT call identity (auth, not behavior; a function, not data). */
|
|
437
460
|
defaultGetApiKeyAndHeaders?: TaskSpec["getApiKeyAndHeaders"];
|
|
461
|
+
/**
|
|
462
|
+
* #642 — the HOST run's `durableApproval` opt-in (value copy), inherited into every spawned agent whose
|
|
463
|
+
* fold left the seat unpinned (a deployment baseline that pins `durableApproval` wins; scripts can never set
|
|
464
|
+
* it — governance strips it). With it a workflow child's plain policy `ask` — an ask the host's approver
|
|
465
|
+
* answers `unavailable` for, or a durable mandate — PARKS durably instead of denying fail-closed, exactly as
|
|
466
|
+
* a background delegation child's does under the §7.3 park family: the wa* row records `status:"parked"` +
|
|
467
|
+
* the token, the run SUSPENDS (the script cannot continue past a parked call), and a resume drives the
|
|
468
|
+
* parked child on with the caller's decision ({@link parkedResume}). Tighten-only: a park capability,
|
|
469
|
+
* never a widening — the decision stays with a person. REQUIRES {@link store} (the wa* row's durable home;
|
|
470
|
+
* refused loudly at entry without it). Threaded by the Workflow tool from the host's trusted seat; a
|
|
471
|
+
* directly-started workflow passes its own. NOT call identity.
|
|
472
|
+
*/
|
|
473
|
+
defaultDurableApproval?: TaskSpec["durableApproval"];
|
|
474
|
+
/**
|
|
475
|
+
* #642 — the decisions a resume ({@link resumeFromRunId}) carries for PARKED ordinals of the prior run: at
|
|
476
|
+
* an ordinal whose journal entry is `parked` (a matching call key), the run drives the parked child's own
|
|
477
|
+
* resume — `runner.resumeStream(token, outcome, …)` on the pinned session, the child's spec rebuilt from
|
|
478
|
+
* the script call exactly as at spawn — and settles its result at that ordinal, so the script continues past
|
|
479
|
+
* the call it parked on. A parked ordinal with NO decision here re-parks (the row and the journal say the
|
|
480
|
+
* same thing again, the run suspends again); it is never run live. `inheritedGate` is the cross-process
|
|
481
|
+
* re-supply of the checkpoint's opaque parent constraints (the same seat the background lane's drive
|
|
482
|
+
* takes). TRUSTED: a host-supplied decision, never a script/model argument; requires `resumeFromRunId`.
|
|
483
|
+
*/
|
|
484
|
+
parkedResume?: ReadonlyArray<WorkflowParkedResume>;
|
|
438
485
|
/** design/148 S1 — the HOST run's adopted center artifact (trusted, threaded by the Workflow tool
|
|
439
486
|
* from ctx): every spawned agent composes the same closure. */
|
|
440
487
|
parentCenterArtifactDigest?: string;
|