@amaster.ai/employee-runtime-connector 0.1.1-beta.226 → 0.1.1-beta.227

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.
@@ -4314,6 +4314,7 @@ var amasterRuntimeConnectorCreateCommandSchema = external_exports.object({
4314
4314
  var amasterRuntimeConnectorPollCommandsSchema = external_exports.object({
4315
4315
  limit: external_exports.number().int().min(1).max(50).default(1),
4316
4316
  maxConcurrentCommands: external_exports.number().int().min(1).max(50).optional(),
4317
+ maxConcurrentBusinessCommands: external_exports.number().int().min(1).max(3).optional(),
4317
4318
  leaseId: external_exports.string().trim().min(1).optional(),
4318
4319
  leaseSeconds: external_exports.number().int().min(1).max(3600).default(60)
4319
4320
  });
@@ -23820,7 +23821,7 @@ function estimatedTokens(chars) {
23820
23821
  }
23821
23822
  function promptContextMode(input) {
23822
23823
  const nativeSession = asRecord(input.nativeSession);
23823
- if (nativeSession.mode === "governed_action_approval" || readString(input.context?.resumeFromRunId) || isRecoveryWakeReason(input.wakeReason) || CONTINUATION_WAKE_PATTERN.test(input.wakeReason ?? "")) return "continuation";
23824
+ if (nativeSession.mode === "governed_action_approval" || input.wakeReason === "continue_task" || readString(input.context?.resumeFromRunId) || isRecoveryWakeReason(input.wakeReason) || CONTINUATION_WAKE_PATTERN.test(input.wakeReason ?? "")) return "continuation";
23824
23825
  if (nativeSession.resume === true || Object.keys(asRecord(input.context?.paperclipContinuationSummary)).length > 0) {
23825
23826
  return "warm";
23826
23827
  }
@@ -23850,12 +23851,54 @@ function commentBodies(context) {
23850
23851
  const comments = Array.isArray(asRecord(context.paperclipWake).comments) ? asRecord(context.paperclipWake).comments : [];
23851
23852
  return comments.map((entry) => readString(asRecord(entry).body)).filter(Boolean);
23852
23853
  }
23853
- function continuationText(context) {
23854
+ function continuationText(context, { omitNextAction = false } = {}) {
23854
23855
  const summary = asRecord(context.paperclipContinuationSummary);
23855
- const body = readString(summary.body);
23856
+ const rawBody = readString(summary.body);
23857
+ const body = omitNextAction ? rawBody?.replace(/(?:^|\n)##[ \t]+Next Action[ \t]*\n[\s\S]*$/iu, "").trimEnd() : rawBody;
23856
23858
  if (!body) return "";
23857
23859
  return [readString(summary.title), body].filter(Boolean).join("\n");
23858
23860
  }
23861
+ function authoritativeContinuationNextAction(context, input) {
23862
+ if (input.wakeReason !== "continue_task") return null;
23863
+ const nextAction = readString(context.nextAction);
23864
+ const sourceRunId = readString(context.sourceRunId);
23865
+ const continuationChainId = readString(context.continuationChainId);
23866
+ const continuationIntentId = readString(context.continuationIntentId);
23867
+ if (!nextAction || !sourceRunId || !continuationChainId || !continuationIntentId) {
23868
+ throw promptBudgetError(
23869
+ "continuation_next_action_unavailable",
23870
+ "Continue Task wake requires an exact next action and complete continuation lineage"
23871
+ );
23872
+ }
23873
+ const rawCheckpointPaths = context.checkpointPaths;
23874
+ const checkpointPaths = rawCheckpointPaths === void 0 ? [] : Array.isArray(rawCheckpointPaths) ? rawCheckpointPaths.map((entry) => readString(entry)) : null;
23875
+ if (checkpointPaths === null || checkpointPaths.length > 20 || checkpointPaths.some((path) => !path) || new Set(checkpointPaths).size !== checkpointPaths.length) {
23876
+ throw promptBudgetError(
23877
+ "continuation_checkpoint_contract_invalid",
23878
+ "Continue Task wake contains invalid checkpoint path authority"
23879
+ );
23880
+ }
23881
+ return {
23882
+ sourceRef: [
23883
+ `run:${sourceRunId}`,
23884
+ `continuation-chain:${continuationChainId}`,
23885
+ `continuation-intent:${continuationIntentId}`
23886
+ ],
23887
+ content: [
23888
+ "The Server persisted this exact instruction when the predecessor Run yielded its execution slot.",
23889
+ "Execute this instruction as the current stage. Do not restart the original task or repeat completed predecessor work unless this instruction explicitly requires it.",
23890
+ "This instruction overrides any generic or inferred Next Action in the Continuation Summary.",
23891
+ ...checkpointPaths.length > 0 ? [
23892
+ `The Connector restored these exact predecessor checkpoint files into the current execution workspace: ${JSON.stringify(checkpointPaths)}.`,
23893
+ "Use only these paths as run-local file continuity evidence; other predecessor workspace files were not carried forward."
23894
+ ] : [
23895
+ "No predecessor run-local files were declared for carry-forward. Use Server-durable documents, artifacts, work products, or the exact instruction below instead of assuming an old workspace file exists."
23896
+ ],
23897
+ "",
23898
+ nextAction
23899
+ ].join("\n")
23900
+ };
23901
+ }
23859
23902
  var CONTINUATION_SUMMARY_TITLE_ALLOWLIST = /* @__PURE__ */ new Set(["Continuation Summary", "Predecessor Execution Summary"]);
23860
23903
  function continuationSectionTitle(context) {
23861
23904
  const title = readString(asRecord(context.paperclipContinuationSummary).title);
@@ -24748,7 +24791,7 @@ function runtimeAuthorizationText(context, mode, {
24748
24791
  const completionContract = !suppressOrdinaryCompletionContract && completionRole && completionDeliverable ? [
24749
24792
  workDisposition.mode === "required" ? "Before the first business mutation, ensure the current required work disposition is recorded. Read-only governed checks may precede it. If no current valid receipt exists, call runtime_action_describe for record_work_disposition and persist exactly one truthful disposition before upsert_document, update_parent, add_comment, create_interaction, publish_delivery_manifest, or any other business mutation. Before ending this run, persist durable progress through Runtime Actions; browser and tool history alone are not durable progress." : "Before ending this run, persist durable progress through Runtime Actions and record one explicit task disposition. Browser and tool history alone are not durable progress.",
24750
24793
  firstDocumentCheckpoint,
24751
- continueTaskEnabled ? "Treat one Run as one bounded, durable checkpoint. Once that checkpoint is persisted and another independent research, build, or revision phase remains, call continue_task immediately with a concrete nextAction and stable idempotencyKey instead of keeping the current Run open, then end the run. Do not split an unfinished atomic mutation or claim progress that is not durable. For a future time recheck use schedule_monitor; for an external person or system action use upsert_external_wait. These are mutually exclusive final live paths. Do not call update_parent with status: in_progress." : "If work remains in an ordinary productive run, call update_parent with status: in_progress and a concrete next action so bounded continuation recovery can preserve a live path. Status: todo does not queue a normal continuation from an ordinary productive run. Only a server-issued successful-run handoff recovery may use status: todo, and only according to its exact Recovery Instruction. Otherwise use a supported terminal or waiting disposition."
24794
+ continueTaskEnabled ? "Treat one Run as one bounded, durable checkpoint. Once that checkpoint is persisted and another independent research, build, or revision phase remains, call continue_task immediately with a concrete nextAction and stable idempotencyKey instead of keeping the current Run open, then end the run. If the nextAction depends on files created in this run, include their exact workspace-relative POSIX paths in checkpointPaths; only those files are integrity-checked and carried into the successor workspace. A run-local file omitted from checkpointPaths is not durable continuation state. Do not split an unfinished atomic mutation or claim progress that is not durable. For a future time recheck use schedule_monitor; for an external person or system action use upsert_external_wait. These are mutually exclusive final live paths. Do not call update_parent with status: in_progress." : "If work remains in an ordinary productive run, call update_parent with status: in_progress and a concrete next action so bounded continuation recovery can preserve a live path. Status: todo does not queue a normal continuation from an ordinary productive run. Only a server-issued successful-run handoff recovery may use status: todo, and only according to its exact Recovery Instruction. Otherwise use a supported terminal or waiting disposition."
24752
24795
  ].filter(Boolean).join(" ") : "";
24753
24796
  const businessOutcomeOwnershipContract = businessOutcome.mode === "required" ? evidenceAutoAcceptance ? [
24754
24797
  "Evidence-auto Business Outcome closure is owned by the Server terminal reconciler.",
@@ -25094,6 +25137,7 @@ var COMPANY_INITIALIZATION_PRE_AUTHORITY_SECTIONS = /* @__PURE__ */ new Set([
25094
25137
  "execution_review_contract",
25095
25138
  "governed_business_state",
25096
25139
  "continuation_postcondition_gap",
25140
+ "continuation_next_action",
25097
25141
  "continuation_summary",
25098
25142
  "resolved_dependencies",
25099
25143
  "runtime_delivery_readiness",
@@ -25433,8 +25477,12 @@ function compileCommandPromptWithManifest(input, options = {}) {
25433
25477
  `issue:${input.issueId ?? "unknown"}`,
25434
25478
  ...taskCommentIds.map((commentId) => `comment:${commentId}`)
25435
25479
  ];
25436
- const continuationSummary = continuationText(context);
25437
- const includeTask = mode === "cold" || !continuationSummary && asRecord(input.nativeSession).mode !== "governed_action_approval";
25480
+ const continuationNextAction = authoritativeContinuationNextAction(context, input);
25481
+ const rawContinuationSummary = continuationText(context);
25482
+ const continuationSummary = continuationText(context, {
25483
+ omitNextAction: Boolean(continuationNextAction)
25484
+ });
25485
+ const includeTask = mode === "cold" || !rawContinuationSummary && !continuationNextAction && asRecord(input.nativeSession).mode !== "governed_action_approval";
25438
25486
  const wakeBodies = commentBodies(context);
25439
25487
  const hasTaskCommentIds = Array.isArray(context.paperclipTaskMarkdownCommentIds);
25440
25488
  const commentsDuplicatedByTask = !hasTaskCommentIds && hasTask && wakeBodies.length > 0 && wakeBodies.every((body) => taskText.includes(body));
@@ -25486,6 +25534,7 @@ ${resolvedDependencies.details.content}` : resolvedDependencies.details.content
25486
25534
  const rawSections = [
25487
25535
  { name: "recovery_instruction", title: "Recovery Instruction", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: completeRecoveryInstruction, truncationReason: completeRecoveryInstruction ? null : "mode_selection" },
25488
25536
  { name: "approval_continuation", title: "Approved Runtime Action Continuation", priority: 99, sourceRef: `run:${input.runId ?? "unknown"}`, content: approvalContinuationText(input), truncationReason: mode === "continuation" ? null : "mode_selection" },
25537
+ ...continuationNextAction ? [{ name: "continuation_next_action", title: "Authoritative Continuation Next Action", priority: 100, ...continuationNextAction }] : [],
25489
25538
  { name: "wake_comments", title: wakeDeltaTitle, priority: interactionResolution ? 99 : 95, sourceRef: wakeDeltaSourceRefs, originalContent: wakeDeltaOriginal, content: wakeDeltaContent, truncationReason: commentsSelected ? null : "duplicate_task_context" },
25490
25539
  { name: "task", title: "Task Context", priority: 90, sourceRef: taskSourceRefs, originalContent: [taskText, taskCommentRefGuidance(input, taskText)].filter(Boolean).join("\n"), content: includeTask ? [taskText, taskCommentRefGuidance(input, taskText)].filter(Boolean).join("\n") : "", truncationReason: includeTask ? null : "mode_selection" },
25491
25540
  ...taskAcceptanceContract ? [{ name: "task_acceptance_contract", title: "Task Acceptance Contract", priority: 100, ...taskAcceptanceContract }] : [],
@@ -26986,6 +27035,17 @@ var PI_TERMINATING_RUNTIME_ACTION_TOOLS = /* @__PURE__ */ new Set([
26986
27035
  "runtime_action.submit",
26987
27036
  "runtime_action.status"
26988
27037
  ]);
27038
+ function continuationCheckpointPaths(value) {
27039
+ if (value === void 0) return [];
27040
+ if (!Array.isArray(value) || value.length < 1 || value.length > 20) return null;
27041
+ const paths = value.map((entry) => readString(entry));
27042
+ if (paths.some((entry) => !entry)) return null;
27043
+ if (new Set(paths).size !== paths.length) return null;
27044
+ for (const path of paths) {
27045
+ if (path.includes("\\") || path.startsWith("/") || /^[A-Za-z]:\//.test(path) || path.split("/").some((segment) => !segment || segment === "." || segment === ".." || segment.startsWith(".")) || path.startsWith("input-attachments/") || ["AGENTS.md", "SOUL.md"].includes(path.split("/").at(-1) ?? "")) return null;
27046
+ }
27047
+ return paths;
27048
+ }
26989
27049
  function approvedMcpInvocationSucceeded(results, invocationId) {
26990
27050
  const approvedInvocationId = readString(invocationId);
26991
27051
  return Boolean(approvedInvocationId && (Array.isArray(results) ? results : []).some((rawResult) => {
@@ -27049,7 +27109,8 @@ function governedMcpToolResult(structuredContent) {
27049
27109
  const continuationExecutionEpoch = readNumber(effectResult.executionEpoch, 0);
27050
27110
  const continuationCount = readNumber(effectResult.continuationCount, 0);
27051
27111
  const maxContinuations = readNumber(effectResult.maxContinuations, 0);
27052
- const exactContinuation = runDisposition === "continuation_scheduled" && continuationChainId && continuationIntentId && continuationWakeId && Number.isSafeInteger(continuationExecutionEpoch) && continuationExecutionEpoch > 0 && Number.isSafeInteger(continuationCount) && continuationCount > 0 && Number.isSafeInteger(maxContinuations) && continuationCount <= maxContinuations;
27112
+ const continuationCheckpointPathList = continuationCheckpointPaths(effectResult.checkpointPaths);
27113
+ const exactContinuation = runDisposition === "continuation_scheduled" && continuationChainId && continuationIntentId && continuationWakeId && Number.isSafeInteger(continuationExecutionEpoch) && continuationExecutionEpoch > 0 && Number.isSafeInteger(continuationCount) && continuationCount > 0 && Number.isSafeInteger(maxContinuations) && continuationCount <= maxContinuations && continuationCheckpointPathList !== null;
27053
27114
  const exactQueuedWakeHandoff = runDisposition === "handoff_existing_live_path" && readString(existingOwner.kind) === "queued_wake" && Boolean(readString(existingOwner.id)) && ["pending_dispatch", "queued", "deferred_issue_execution"].includes(
27054
27115
  readString(existingOwner.status) ?? ""
27055
27116
  ) && Number.isSafeInteger(existingOwnerEpoch) && existingOwnerEpoch > 0 && readString(existingOwner.nextAction) === "end_current_run";
@@ -27071,7 +27132,8 @@ function governedMcpToolResult(structuredContent) {
27071
27132
  wakeId: continuationWakeId,
27072
27133
  executionEpoch: continuationExecutionEpoch,
27073
27134
  count: continuationCount,
27074
- max: maxContinuations
27135
+ max: maxContinuations,
27136
+ ...continuationCheckpointPathList.length > 0 ? { checkpointPaths: continuationCheckpointPathList } : {}
27075
27137
  }
27076
27138
  } : {},
27077
27139
  ...exactQueuedWakeHandoff ? {
@@ -27162,7 +27224,8 @@ function piTerminatingRunDispositionEvidence(results, expected = {}) {
27162
27224
  wakeId: readString(continuation.wakeId),
27163
27225
  executionEpoch: readNumber(continuation.executionEpoch, 0),
27164
27226
  count: readNumber(continuation.count, 0),
27165
- max: readNumber(continuation.max, 0)
27227
+ max: readNumber(continuation.max, 0),
27228
+ ...Array.isArray(continuation.checkpointPaths) ? { checkpointPaths: continuation.checkpointPaths.map((entry) => readString(entry)).filter(Boolean) } : {}
27166
27229
  }
27167
27230
  } : {},
27168
27231
  ...readString(existingOwner.kind) === "queued_wake" && readString(existingOwner.id) ? {
@@ -27841,14 +27904,11 @@ function piRuntimeWebEvidence(event) {
27841
27904
  }
27842
27905
  function parsePiJsonl(stdout) {
27843
27906
  let sessionId = null;
27844
- let errorMessage = null;
27845
27907
  let streamingText = "";
27846
27908
  let sawTurnEnd = false;
27847
27909
  let terminalEventType = null;
27848
27910
  let stopReason = null;
27849
27911
  let hasAssistantOutput = false;
27850
- let nonCleanupErrorCount = 0;
27851
- let nonCleanupErrorMessage = null;
27852
27912
  let terminalEventIndex = null;
27853
27913
  let sawAgentSettled = false;
27854
27914
  let settledEventIndex = null;
@@ -27857,12 +27917,45 @@ function parsePiJsonl(stdout) {
27857
27917
  const mcpToolResults = [];
27858
27918
  const cleanupDiagnostics = [];
27859
27919
  const diagnostics = [];
27920
+ const errorEvents = [];
27921
+ let retry = null;
27922
+ let turnStartIndex = -1;
27923
+ let successfulAssistantIndex = -1;
27860
27924
  const usage = { inputTokens: 0, cachedInputTokens: 0, outputTokens: 0 };
27861
27925
  for (const rawLine of String(stdout ?? "").split(/\r?\n/)) {
27862
27926
  const event = parseJsonLine(rawLine.trim());
27863
27927
  if (!event) continue;
27864
27928
  eventIndex += 1;
27865
27929
  mcpToolResults.push(...piMcpToolResults(event));
27930
+ if (event.type === "turn_start") turnStartIndex = eventIndex;
27931
+ if (event.type === "auto_retry_start") {
27932
+ const message = readString(event.errorMessage);
27933
+ const lastError = errorEvents.at(-1);
27934
+ const matched = Number.isSafeInteger(event.attempt) && event.attempt > 0 && (event.attempt === 1 || event.attempt === retry?.attempt + 1) && turnStartIndex >= 0 && lastError?.provider === true && lastError.message === message && lastError.eventIndex === terminalEventIndex && terminalEventType === "agent_end";
27935
+ const priorErrors = retry && event.attempt === retry.attempt + 1 ? retry.errors : [];
27936
+ retry = matched ? {
27937
+ attempt: event.attempt,
27938
+ startIndex: eventIndex,
27939
+ errors: [...priorErrors, ...errorEvents.filter((error) => error.eventIndex >= turnStartIndex && error.provider && error.message === message)]
27940
+ } : null;
27941
+ continue;
27942
+ }
27943
+ if (event.type === "auto_retry_end") {
27944
+ if (event.success === true && retry && event.attempt === retry.attempt && successfulAssistantIndex > retry.startIndex) {
27945
+ for (const error of retry.errors) error.recoveredAt = eventIndex;
27946
+ diagnostics.push({
27947
+ source: "provider",
27948
+ phase: "retry",
27949
+ severity: "info",
27950
+ code: "pi_provider_retry_recovered",
27951
+ attempt: retry.attempt,
27952
+ recoveredErrorEventCount: retry.errors.length,
27953
+ eventIndex
27954
+ });
27955
+ }
27956
+ retry = null;
27957
+ continue;
27958
+ }
27866
27959
  if (event.type === "session") {
27867
27960
  sessionId = readString(event.sessionId) ?? readString(event.id) ?? sessionId;
27868
27961
  continue;
@@ -27898,9 +27991,12 @@ function parsePiJsonl(stdout) {
27898
27991
  stopReason = readString(event.stopReason ?? event.stop_reason) ?? piNestedMessageStopReason(event) ?? stopReason;
27899
27992
  const terminalError = piStopReasonErrorText(event) ?? piNestedMessageErrorText(event);
27900
27993
  if (terminalError) {
27901
- nonCleanupErrorCount += 1;
27902
- nonCleanupErrorMessage = terminalError;
27903
- errorMessage = terminalError;
27994
+ errorEvents.push({
27995
+ message: terminalError,
27996
+ eventIndex,
27997
+ provider: classifyPiProviderError({ errorMessage: terminalError })?.errorFamily === "transient_upstream"
27998
+ });
27999
+ successfulAssistantIndex = -1;
27904
28000
  if (PI_PROVIDER_PROTOCOL_RE.test(terminalError)) {
27905
28001
  diagnostics.push({
27906
28002
  source: "provider",
@@ -27912,6 +28008,9 @@ function parsePiJsonl(stdout) {
27912
28008
  });
27913
28009
  }
27914
28010
  }
28011
+ if (event.type === "message_end" && asRecord(event.message).role === "assistant" && !terminalError && ["stop", "toolUse"].includes(piMessageStopReason(event.message))) {
28012
+ successfulAssistantIndex = eventIndex;
28013
+ }
27915
28014
  hasAssistantOutput = maybeCapturePiMessage(event, messages, usage) || hasAssistantOutput;
27916
28015
  continue;
27917
28016
  }
@@ -27931,11 +28030,9 @@ function parsePiJsonl(stdout) {
27931
28030
  ...diagnostic,
27932
28031
  eventIndex
27933
28032
  });
27934
- errorMessage = nonCleanupErrorMessage ?? eventError;
27935
28033
  } else {
27936
- nonCleanupErrorCount += 1;
27937
- nonCleanupErrorMessage = eventError;
27938
- errorMessage = eventError;
28034
+ errorEvents.push({ message: eventError, eventIndex, provider: false });
28035
+ successfulAssistantIndex = -1;
27939
28036
  if (PI_PROVIDER_PROTOCOL_RE.test(eventError)) {
27940
28037
  diagnostics.push({
27941
28038
  source: "provider",
@@ -27949,6 +28046,9 @@ function parsePiJsonl(stdout) {
27949
28046
  }
27950
28047
  }
27951
28048
  }
28049
+ const unresolvedErrors = errorEvents.filter((error) => !(Number.isInteger(error.recoveredAt) && terminalEventIndex > error.recoveredAt && sawAgentSettled && settledEventIndex > terminalEventIndex));
28050
+ const nonCleanupErrorCount = unresolvedErrors.length;
28051
+ const errorMessage = unresolvedErrors.at(-1)?.message ?? cleanupDiagnostics.at(-1)?.message ?? null;
27952
28052
  const uniqueMcpToolResults = dedupeGovernedMcpToolResults(mcpToolResults);
27953
28053
  return {
27954
28054
  sessionId,
@@ -29943,7 +30043,7 @@ function assertRequiredTaskAttachmentMaterialized(input, materialized) {
29943
30043
  }
29944
30044
 
29945
30045
  // src/amaster-runtime-daemon.mjs
29946
- var CONNECTOR_VERSION = "0.1.1-beta.226";
30046
+ var CONNECTOR_VERSION = "0.1.1-beta.227";
29947
30047
  var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
29948
30048
  var daemonRequire = createRequire(import.meta.url);
29949
30049
  var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
@@ -30783,6 +30883,10 @@ function maxConcurrentCommands(config) {
30783
30883
  capabilities: config.capabilities
30784
30884
  });
30785
30885
  }
30886
+ function maxConcurrentBusinessCommands(config) {
30887
+ const configured = Number(config.maxConcurrentCommands);
30888
+ return Number.isInteger(configured) && configured > 0 ? Math.min(configured, 3) : 1;
30889
+ }
30786
30890
  function activeRunCommandCount(config, options = {}) {
30787
30891
  const excludeCommandIds = new Set(readStringArray(options.excludeCommandIds));
30788
30892
  const commandIds = new Set([
@@ -31034,6 +31138,7 @@ async function poll(config) {
31034
31138
  const body = await postJson(config, `/api/amaster/runtime-connectors/${connectorId}/commands/poll`, {
31035
31139
  limit: Math.max(1, limit),
31036
31140
  maxConcurrentCommands: maxCommands,
31141
+ maxConcurrentBusinessCommands: maxConcurrentBusinessCommands(config),
31037
31142
  leaseId: `amaster-${Date.now()}`,
31038
31143
  leaseSeconds: config.leaseSeconds
31039
31144
  });
@@ -34762,10 +34867,36 @@ function safeCheckpointRelativePath(rawPath) {
34762
34867
  function hashFileSha256(filePath) {
34763
34868
  return createHash17("sha256").update(readFileSync18(filePath)).digest("hex");
34764
34869
  }
34870
+ function expectedContinuationCheckpoint(command) {
34871
+ const payload = asRecord(command.payload);
34872
+ const envelope = asRecord(payload.contextEnvelope);
34873
+ const context = asRecord(asRecord(envelope.runDecisionContext).content);
34874
+ if (readString(context.wakeReason) !== "continue_task") return null;
34875
+ const rawPaths = context.checkpointPaths;
34876
+ if (rawPaths === void 0) return null;
34877
+ if (!Array.isArray(rawPaths) || rawPaths.length < 1 || rawPaths.length > 20) {
34878
+ throw new Error("continuation_checkpoint_contract_invalid: checkpointPaths");
34879
+ }
34880
+ const paths = rawPaths.map((entry) => safeCheckpointRelativePath(readString(entry)));
34881
+ if (paths.some((entry) => !entry) || new Set(paths).size !== paths.length) {
34882
+ throw new Error("continuation_checkpoint_contract_invalid: checkpointPaths");
34883
+ }
34884
+ const sourceRunId = readString(context.sourceRunId);
34885
+ const continuationChainId = readString(context.continuationChainId);
34886
+ const continuationIntentId = readString(context.continuationIntentId);
34887
+ if (!sourceRunId || !continuationChainId || !continuationIntentId) {
34888
+ throw new Error("continuation_checkpoint_contract_invalid: lineage");
34889
+ }
34890
+ return { paths, sourceRunId, continuationChainId, continuationIntentId };
34891
+ }
34765
34892
  async function materializeIssueCheckpoint(config, command, workspace) {
34766
34893
  const checkpointDir = issueCheckpointDir(workspace);
34767
34894
  const manifestPath = join17(checkpointDir, "manifest.json");
34768
- if (!existsSync17(manifestPath)) return [];
34895
+ const expectedContinuation = expectedContinuationCheckpoint(command);
34896
+ if (!existsSync17(manifestPath)) {
34897
+ if (expectedContinuation) throw new Error("continuation_checkpoint_unavailable: manifest_missing");
34898
+ return [];
34899
+ }
34769
34900
  let manifest;
34770
34901
  try {
34771
34902
  manifest = asRecord(JSON.parse(readFileSync18(manifestPath, "utf8")));
@@ -34776,11 +34907,21 @@ async function materializeIssueCheckpoint(config, command, workspace) {
34776
34907
  const expiresAt = Date.parse(readString(manifest.expiresAt) ?? "");
34777
34908
  if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() || readString(manifest.issueId) !== commandIssueId(command)) {
34778
34909
  rmSync9(checkpointDir, { recursive: true, force: true });
34910
+ if (expectedContinuation) throw new Error("continuation_checkpoint_unavailable: manifest_expired_or_mismatched");
34779
34911
  return [];
34780
34912
  }
34781
34913
  try {
34914
+ if (readString(manifest.kind) === "continue_task" && !expectedContinuation) {
34915
+ return [];
34916
+ }
34782
34917
  const files = Array.isArray(manifest.files) ? manifest.files : [];
34783
34918
  if (files.length > 20) throw new Error("issue checkpoint manifest exceeds the limit of 20 files");
34919
+ if (expectedContinuation) {
34920
+ const manifestPaths = files.map((entry) => safeCheckpointRelativePath(readString(asRecord(entry).path)));
34921
+ if (readString(manifest.kind) !== "continue_task" || readString(manifest.sourceRunId) !== expectedContinuation.sourceRunId || readString(manifest.continuationChainId) !== expectedContinuation.continuationChainId || readString(manifest.continuationIntentId) !== expectedContinuation.continuationIntentId || manifestPaths.some((entry) => !entry) || manifestPaths.length !== expectedContinuation.paths.length || manifestPaths.some((entry, index) => entry !== expectedContinuation.paths[index])) {
34922
+ throw new Error("continuation_checkpoint_lineage_mismatch");
34923
+ }
34924
+ }
34784
34925
  const filesRoot = realpathSync8(join17(checkpointDir, "files"));
34785
34926
  const workspaceRoot = realpathSync8(workspace.cwd);
34786
34927
  const validated = [];
@@ -34809,22 +34950,45 @@ async function materializeIssueCheckpoint(config, command, workspace) {
34809
34950
  }
34810
34951
  totalBytes += expectedByteSize;
34811
34952
  if (totalBytes > MAX_CHECKPOINT_BYTES) throw new Error("issue checkpoint exceeds the 20 MB restore limit");
34812
- validated.push({ relativePath, source, target });
34953
+ validated.push({
34954
+ relativePath,
34955
+ source,
34956
+ target,
34957
+ expectedSha256,
34958
+ expectedByteSize
34959
+ });
34813
34960
  }
34814
34961
  const materialized = [];
34815
- for (const { relativePath, source, target } of validated) {
34816
- try {
34817
- lstatSync11(target);
34818
- continue;
34819
- } catch (err) {
34820
- if (err?.code !== "ENOENT") throw err;
34821
- }
34962
+ for (const { relativePath, source, target, expectedSha256, expectedByteSize } of validated) {
34822
34963
  mkdirSync9(dirname11(target), { recursive: true });
34823
34964
  const targetParent = realpathSync8(dirname11(target));
34824
34965
  if (!pathWithin3(targetParent, workspaceRoot)) {
34825
34966
  throw new Error(`issue checkpoint target escapes its workspace: ${relativePath}`);
34826
34967
  }
34827
- copyFileSync2(source, target);
34968
+ let existingTarget = null;
34969
+ try {
34970
+ existingTarget = lstatSync11(target);
34971
+ } catch (err) {
34972
+ if (err?.code !== "ENOENT") throw err;
34973
+ }
34974
+ if (existingTarget && !existingTarget.isFile()) {
34975
+ throw new Error(`issue checkpoint target is not a regular file: ${relativePath}`);
34976
+ }
34977
+ if (existingTarget && existingTarget.size === expectedByteSize && hashFileSha256(target) === expectedSha256) {
34978
+ materialized.push(relativePath);
34979
+ continue;
34980
+ }
34981
+ const temporaryTarget = join17(targetParent, `.${basename8(target)}.checkpoint-${randomUUID()}.tmp`);
34982
+ try {
34983
+ copyFileSync2(source, temporaryTarget);
34984
+ const temporaryStat = lstatSync11(temporaryTarget);
34985
+ if (!temporaryStat.isFile() || temporaryStat.size !== expectedByteSize || hashFileSha256(temporaryTarget) !== expectedSha256) {
34986
+ throw new Error(`issue checkpoint target verification failed: ${relativePath}`);
34987
+ }
34988
+ renameSync10(temporaryTarget, target);
34989
+ } finally {
34990
+ rmSync9(temporaryTarget, { force: true });
34991
+ }
34828
34992
  materialized.push(relativePath);
34829
34993
  }
34830
34994
  if (materialized.length > 0) {
@@ -34846,48 +35010,112 @@ async function materializeIssueCheckpoint(config, command, workspace) {
34846
35010
  throw restoreErr;
34847
35011
  }
34848
35012
  }
34849
- async function saveIssueCheckpoint(config, command, workspace, candidates) {
35013
+ async function saveIssueCheckpoint(config, command, workspace, candidates, options = {}) {
34850
35014
  const checkpointDir = issueCheckpointDir(workspace);
34851
- const filesDir = join17(checkpointDir, "files");
34852
- rmSync9(checkpointDir, { recursive: true, force: true });
35015
+ const commandKey = readString(command.commandId)?.replace(/[^A-Za-z0-9_-]/g, "-") ?? randomUUID();
35016
+ const stagingDir = `${checkpointDir}.tmp-${commandKey}`;
35017
+ const backupDir = `${checkpointDir}.previous-${commandKey}`;
35018
+ const filesDir = join17(stagingDir, "files");
35019
+ rmSync9(stagingDir, { recursive: true, force: true });
35020
+ rmSync9(backupDir, { recursive: true, force: true });
34853
35021
  mkdirSync9(filesDir, { recursive: true });
34854
- const files = [];
34855
- let totalBytes = 0;
34856
- const workspaceRoot = realpathSync8(workspace.cwd);
34857
- for (const candidate of candidates.slice(0, 20)) {
34858
- const relativePath = safeCheckpointRelativePath(candidate.rawPath);
34859
- const source = readString(candidate.filePath);
34860
- if (!relativePath || !source || !existsSync17(source) || !statSync11(source).isFile()) continue;
34861
- const ownedSource = realpathSync8(source);
34862
- if (!pathWithin3(ownedSource, workspaceRoot)) {
34863
- throw new Error(`issue checkpoint source escapes its execution workspace: ${relativePath}`);
34864
- }
34865
- const byteSize = statSync11(ownedSource).size;
34866
- if (byteSize <= 0 || totalBytes + byteSize > MAX_CHECKPOINT_BYTES) continue;
34867
- const target = resolve16(filesDir, relativePath);
34868
- if (!pathWithin3(target, filesDir)) continue;
34869
- mkdirSync9(dirname11(target), { recursive: true });
34870
- copyFileSync2(ownedSource, target);
34871
- totalBytes += byteSize;
34872
- files.push({ path: relativePath, byteSize, sha256: hashFileSha256(ownedSource) });
34873
- }
34874
- if (files.length === 0) {
34875
- rmSync9(checkpointDir, { recursive: true, force: true });
34876
- return null;
34877
- }
34878
- const manifest = {
34879
- version: 1,
34880
- issueId: commandIssueId(command),
34881
- sourceRunId: commandRunId(command),
34882
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
34883
- expiresAt: new Date(Date.now() + CHECKPOINT_TTL_MS).toISOString(),
34884
- totalBytes,
34885
- files
34886
- };
34887
- writeFileSync11(join17(checkpointDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
35022
+ try {
35023
+ const files = [];
35024
+ let totalBytes = 0;
35025
+ const workspaceRoot = realpathSync8(workspace.cwd);
35026
+ const requiredPaths = Array.isArray(options.requiredPaths) ? options.requiredPaths : [];
35027
+ const selectedCandidates = requiredPaths.length > 0 ? requiredPaths.map((requiredPath) => {
35028
+ const normalized = safeCheckpointRelativePath(requiredPath);
35029
+ if (!normalized) {
35030
+ throw new Error(`continuation_checkpoint_file_unavailable: ${requiredPath}`);
35031
+ }
35032
+ const sourceCandidate = resolve16(workspaceRoot, normalized);
35033
+ if (!pathWithin3(sourceCandidate, workspaceRoot)) {
35034
+ throw new Error(`continuation_checkpoint_file_unavailable: ${requiredPath}`);
35035
+ }
35036
+ let sourceStat;
35037
+ try {
35038
+ sourceStat = lstatSync11(sourceCandidate);
35039
+ } catch (err) {
35040
+ if (err?.code === "ENOENT") {
35041
+ throw new Error(`continuation_checkpoint_file_unavailable: ${requiredPath}`);
35042
+ }
35043
+ throw err;
35044
+ }
35045
+ if (!sourceStat.isFile()) {
35046
+ throw new Error(`continuation_checkpoint_file_unavailable: ${requiredPath}`);
35047
+ }
35048
+ const ownedSource = realpathSync8(sourceCandidate);
35049
+ if (!pathWithin3(ownedSource, workspaceRoot)) {
35050
+ throw new Error(`issue checkpoint source escapes its execution workspace: ${normalized}`);
35051
+ }
35052
+ return { rawPath: normalized, filePath: ownedSource };
35053
+ }) : candidates.slice(0, 20);
35054
+ for (const candidate of selectedCandidates) {
35055
+ const relativePath = safeCheckpointRelativePath(candidate.rawPath);
35056
+ const source = readString(candidate.filePath);
35057
+ if (!relativePath || !source || !existsSync17(source) || !statSync11(source).isFile()) {
35058
+ if (requiredPaths.length > 0) throw new Error(`continuation_checkpoint_file_unavailable: ${candidate.rawPath}`);
35059
+ continue;
35060
+ }
35061
+ const ownedSource = realpathSync8(source);
35062
+ if (!pathWithin3(ownedSource, workspaceRoot)) {
35063
+ throw new Error(`issue checkpoint source escapes its execution workspace: ${relativePath}`);
35064
+ }
35065
+ const byteSize = statSync11(ownedSource).size;
35066
+ if (byteSize <= 0 || totalBytes + byteSize > MAX_CHECKPOINT_BYTES) {
35067
+ if (requiredPaths.length > 0) throw new Error(`continuation_checkpoint_file_size_invalid: ${relativePath}`);
35068
+ continue;
35069
+ }
35070
+ const target = resolve16(filesDir, relativePath);
35071
+ if (!pathWithin3(target, filesDir)) continue;
35072
+ mkdirSync9(dirname11(target), { recursive: true });
35073
+ copyFileSync2(ownedSource, target);
35074
+ const storedStat = lstatSync11(target);
35075
+ if (!storedStat.isFile() || storedStat.size !== byteSize) {
35076
+ throw new Error(`issue checkpoint copy verification failed: ${relativePath}`);
35077
+ }
35078
+ totalBytes += byteSize;
35079
+ files.push({ path: relativePath, byteSize, sha256: hashFileSha256(target) });
35080
+ }
35081
+ if (files.length === 0) {
35082
+ rmSync9(stagingDir, { recursive: true, force: true });
35083
+ rmSync9(checkpointDir, { recursive: true, force: true });
35084
+ return null;
35085
+ }
35086
+ const manifest = {
35087
+ version: options.continuation ? 2 : 1,
35088
+ issueId: commandIssueId(command),
35089
+ sourceRunId: commandRunId(command),
35090
+ ...options.continuation ? {
35091
+ kind: "continue_task",
35092
+ continuationChainId: options.continuation.chainId,
35093
+ continuationIntentId: options.continuation.intentId
35094
+ } : {},
35095
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
35096
+ expiresAt: new Date(Date.now() + CHECKPOINT_TTL_MS).toISOString(),
35097
+ totalBytes,
35098
+ files
35099
+ };
35100
+ writeFileSync11(join17(stagingDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
34888
35101
  `);
34889
- await ingestLog(config, command, "system", "warn", `Saved ${files.length} required deliverable(s) for continuation recovery`, manifest);
34890
- return manifest;
35102
+ const replacingExistingCheckpoint = existsSync17(checkpointDir);
35103
+ if (replacingExistingCheckpoint) renameSync10(checkpointDir, backupDir);
35104
+ try {
35105
+ renameSync10(stagingDir, checkpointDir);
35106
+ } catch (err) {
35107
+ if (replacingExistingCheckpoint && existsSync17(backupDir) && !existsSync17(checkpointDir)) {
35108
+ renameSync10(backupDir, checkpointDir);
35109
+ }
35110
+ throw err;
35111
+ }
35112
+ rmSync9(backupDir, { recursive: true, force: true });
35113
+ await ingestLog(config, command, "system", "info", `Saved ${files.length} issue checkpoint file(s) for continuation`, manifest);
35114
+ return manifest;
35115
+ } catch (err) {
35116
+ rmSync9(stagingDir, { recursive: true, force: true });
35117
+ throw err;
35118
+ }
34891
35119
  }
34892
35120
  function piOutputUsageMetadataMissing(parsed) {
34893
35121
  const usage = parsed?.usage ?? {};
@@ -34960,7 +35188,7 @@ async function executeRunCommand(config, command) {
34960
35188
  agentInstructionFiles: [...finalAgentInstructionFiles.values()].sort((left, right) => left.path.localeCompare(right.path)),
34961
35189
  workspaceProjectInstructionProjection: workspaceProjectInstructionReceipt
34962
35190
  });
34963
- await materializeIssueCheckpoint(config, command, workspace);
35191
+ const materializedCheckpointFiles = await materializeIssueCheckpoint(config, command, workspace);
34964
35192
  const requiredArtifactInputs = await materializeRequiredArtifactInputs(config, command, workspace);
34965
35193
  let materializedAttachments = requiredArtifactInputs;
34966
35194
  try {
@@ -35470,6 +35698,31 @@ async function executeRunCommand(config, command) {
35470
35698
  commandId: command.commandId,
35471
35699
  issueId: commandIssueId(command)
35472
35700
  }) : null;
35701
+ let continuationCheckpoint = null;
35702
+ if (readString(terminalRunDisposition?.disposition) === "continuation_scheduled") {
35703
+ const continuation = asRecord(terminalRunDisposition.continuation);
35704
+ const checkpointPaths = Array.isArray(continuation.checkpointPaths) ? continuation.checkpointPaths.map((entry) => readString(entry)).filter(Boolean) : [];
35705
+ if (checkpointPaths.length > 0) {
35706
+ continuationCheckpoint = await saveIssueCheckpoint(
35707
+ config,
35708
+ command,
35709
+ workspace,
35710
+ workspaceStatus.artifacts.map((artifact) => ({
35711
+ rawPath: artifact.relativePath,
35712
+ filePath: resolve16(cwd, artifact.relativePath)
35713
+ })),
35714
+ {
35715
+ requiredPaths: checkpointPaths,
35716
+ continuation: {
35717
+ chainId: readString(continuation.chainId),
35718
+ intentId: readString(continuation.intentId)
35719
+ }
35720
+ }
35721
+ );
35722
+ } else {
35723
+ await clearIssueCheckpoint(config, command, workspace, "continue_task_without_checkpoint_paths");
35724
+ }
35725
+ }
35473
35726
  if (terminalRunDisposition) {
35474
35727
  const disposition = readString(terminalRunDisposition.disposition);
35475
35728
  parsed.summary = disposition === "handoff_existing_live_path" ? "This run handed control to the existing queued live path and ended normally without creating a duplicate interaction." : disposition === "continuation_scheduled" ? "A bounded continuation was persisted; this run ended normally so another queued command can use the released execution slot." : disposition === "waiting_human" ? "The requested human interaction was persisted; this run ended normally and will resume only under its continuation policy." : disposition === "waiting_external" ? "The external wait was persisted; this run ended normally and will resume only after the recorded condition is satisfied." : "The monitor schedule was persisted; this run ended normally and will resume only at the scheduled check.";
@@ -35716,6 +35969,14 @@ async function executeRunCommand(config, command) {
35716
35969
  ...costUsage ? { costUsage } : {},
35717
35970
  ...terminalTextRepair ? { terminalTextRepair: terminalTextRepair.audit } : {},
35718
35971
  ...terminalRunDisposition ? { terminalRunDisposition } : {},
35972
+ ...continuationCheckpoint ? {
35973
+ continuationCheckpoint: {
35974
+ fileCount: continuationCheckpoint.files.length,
35975
+ totalBytes: continuationCheckpoint.totalBytes,
35976
+ paths: continuationCheckpoint.files.map((file) => file.path)
35977
+ }
35978
+ } : {},
35979
+ ...materializedCheckpointFiles.length > 0 ? { materializedCheckpointFiles } : {},
35719
35980
  ...runtimeArtifacts.length > 0 ? { runtimeArtifacts } : {},
35720
35981
  ...runtimeDocuments.length > 0 ? { runtimeDocuments } : {},
35721
35982
  outputTelemetry,
@@ -36023,6 +36284,7 @@ async function runOnce(config) {
36023
36284
  const polled = await postJson(config, `/api/amaster/runtime-connectors/${config.connectorId}/commands/poll`, {
36024
36285
  limit: Math.max(1, availableSlots),
36025
36286
  maxConcurrentCommands: maxConcurrentCommands(config),
36287
+ maxConcurrentBusinessCommands: maxConcurrentBusinessCommands(config),
36026
36288
  leaseId,
36027
36289
  leaseSeconds: config.leaseSeconds
36028
36290
  });
@@ -36059,6 +36321,7 @@ async function dispatchAvailableCommands(config, options = {}) {
36059
36321
  const polled = await postJson(config, `/api/amaster/runtime-connectors/${config.connectorId}/commands/poll`, {
36060
36322
  limit: Math.max(1, availableSlots),
36061
36323
  maxConcurrentCommands: maxConcurrentCommands(config),
36324
+ maxConcurrentBusinessCommands: maxConcurrentBusinessCommands(config),
36062
36325
  leaseId,
36063
36326
  leaseSeconds: config.leaseSeconds
36064
36327
  });
@@ -7,7 +7,7 @@ import { homedir, hostname } from "node:os";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { BUILD_SUPPORTED_CAPABILITIES } from "./amaster-runtime-daemon/capability-registry.mjs";
9
9
 
10
- const CONNECTOR_VERSION = "0.1.1-beta.226";
10
+ const CONNECTOR_VERSION = "0.1.1-beta.227";
11
11
 
12
12
  const CONFIG_KEY_MAP = new Map([
13
13
  ["server_url", "AMASTER_EMPLOYEE_SERVER_URL"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/employee-runtime-connector",
3
- "version": "0.1.1-beta.226",
3
+ "version": "0.1.1-beta.227",
4
4
  "description": "MirrorX runtime connector CLI and daemon",
5
5
  "license": "MIT",
6
6
  "type": "module",