@amaster.ai/employee-runtime-connector 0.1.0-beta.43 → 0.1.0-beta.45
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/README.md +12 -0
- package/dist/amaster-runtime-daemon.mjs +209 -18
- package/dist/amaster-runtime.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,6 +32,18 @@ The source of truth lives under this package's `src/` directory. The package bui
|
|
|
32
32
|
|
|
33
33
|
Runtime code belongs in the container image. Persist only connector state, the result outbox, and workspaces under the configured state directory.
|
|
34
34
|
|
|
35
|
+
## Pi terminal cleanup outcome
|
|
36
|
+
|
|
37
|
+
Pi execution uses three separate evidence layers:
|
|
38
|
+
|
|
39
|
+
1. a valid successful `agent_end` and output/usage contract;
|
|
40
|
+
2. a durable, inspectable Runtime Action receipt or finalized Runtime Artifact;
|
|
41
|
+
3. process cleanup disposition.
|
|
42
|
+
|
|
43
|
+
An exact process-kill `EPERM` error emitted only after the first two layers have completed may be isolated as a failed `cleanupDisposition` warning without changing the command's successful business result. Both accepted shapes require `kill` and `EPERM`; generic filesystem/process permission text such as `EPERM: operation not permitted, unlink ...` is a business error. A `runtime_action.status` readback is evidence only when its call/plan ref matches an earlier submit/commit receipt in the same transcript. The diagnostic and durable evidence reference remain in the result. Text-only or action-only-without-assistant-output streams, standalone governed reads, non-effect Runtime Action tools, rejected or pending effects, pre-terminal errors, provider failures, timeout, cancellation, resource limits, any signal, live residue, and uncertain ownership remain failures.
|
|
44
|
+
|
|
45
|
+
This isolation does not schedule a retry or a second business continuation. Command result delivery and the result outbox remain the sole idempotency boundary.
|
|
46
|
+
|
|
35
47
|
## Mutation attestation
|
|
36
48
|
|
|
37
49
|
The daemon reports its connector contract, exact package/build, platform/architecture, and discovered executor versions on every heartbeat. The server compares those facts with `AMASTER_RUNTIME_RECOMMENDED_VERSION` and `AMASTER_RUNTIME_RECOMMENDED_BUILD_COMMIT`, persists a short-lived content-bound attestation, and correlates Runtime V2 commands to that proof.
|
|
@@ -2558,6 +2558,7 @@ function isTerminalResultOutboxStatus(status) {
|
|
|
2558
2558
|
|
|
2559
2559
|
// src/amaster-runtime-daemon/prompt-compiler.mjs
|
|
2560
2560
|
var DEFAULT_PROMPT_BUDGET_CHARS = 32e3;
|
|
2561
|
+
var DEADLINE_POSTURE_GUARD = "Named-window:skip_this_window_and_continue; no lower-quality/approval-bypass/fabrication/whole-task-stop; deadline_posture_receipt=targetMilestoneRef,posture,onMiss,taskContinuation,next owner/action; not Server proof";
|
|
2561
2562
|
var MIN_PROMPT_BUDGET_CHARS = 8192;
|
|
2562
2563
|
var CONTINUATION_WAKE_PATTERN = /(continuation|continued|retry|approved|liveness|resume|max_turn)/i;
|
|
2563
2564
|
var RECOVERY_WAKE_REASONS = /* @__PURE__ */ new Set([
|
|
@@ -2670,9 +2671,10 @@ function governedReadSection(context) {
|
|
|
2670
2671
|
function fixedRules(input, includeIssueLine) {
|
|
2671
2672
|
return [
|
|
2672
2673
|
"## AMaster Runtime Connector Task",
|
|
2673
|
-
"
|
|
2674
|
-
"
|
|
2674
|
+
"MirrorX task.",
|
|
2675
|
+
"Use only the declared workspace; make concrete progress and report concisely.",
|
|
2675
2676
|
"Before changing the task status to done, audit every explicit requirement in the task against the final evidence. A successful tool or document write proves delivery, not acceptance: inspect the delivered content for required sections, diagrams, tables, and factual constraints. Do not leave stale in-progress wording such as \u201Ccurrent run\u201D in a terminal deliverable; rewrite it to the final observed state. Do not list finalization itself as remaining or next work in a terminal deliverable. If any requirement is missing or cannot be verified, do not mark done. To request review, use create_interaction with kind request_confirmation and payload.resolutionMode review; never call update_parent with status in_review. Otherwise keep the issue todo or blocked with the exact gap and next owner.",
|
|
2677
|
+
DEADLINE_POSTURE_GUARD,
|
|
2676
2678
|
"Do not install operating-system or user-global packages, and do not use host package managers such as brew, apt, yum, or global pip/npm installs. Use tools already available or workspace-local dependencies or virtual environments. If a required renderer or evaluator is unavailable, keep the source artifact, record the exact verification gap, and do not mutate the host.",
|
|
2677
2679
|
`- command id: ${input.commandId}`,
|
|
2678
2680
|
`- run id: ${input.runId ?? "unknown"}`,
|
|
@@ -3690,7 +3692,17 @@ var PI_PROVIDER_AUTH_RE = /(?:(?:\b401\b|\b403\b)[^\n]*(?:unauthorized|forbidden
|
|
|
3690
3692
|
var PI_PROVIDER_QUOTA_EXHAUSTED_RE = /(?:\binsufficient[_\s-]?user[_\s-]?quota\b|河狸币余额不足|\b402\b[^\n]*(?:余额不足|payment\s+required))/i;
|
|
3691
3693
|
var PI_PROVIDER_TRANSIENT_RE = /(?:\b(?:429|5\d{2})\b|rate[-\s]?limit(?:ed)?|too\s+many\s+requests|billing\s+admission\s+failed|service\s+unavailable|upstream[^\n]*(?:unavailable|failed|timeout)|connect(?:ion)?[^\n]*refused|temporar(?:y|ily)[^\n]*(?:unavailable|failed)|try\s+again\s+later)/i;
|
|
3692
3694
|
var PI_PROVIDER_RETRY_AFTER_SECONDS_RE = /retry[-\s]?after\s*[:=]?\s*(\d{1,6})\s*(?:seconds?|secs?|s)\b/i;
|
|
3695
|
+
var PI_TERMINAL_CLEANUP_PERMISSION_RE = /(?:\bkill\b[^\n]*\bEPERM\b|\bEPERM\b[^\n]*\bkill\b)/i;
|
|
3693
3696
|
var MAX_PI_PROVIDER_RETRY_AFTER_SECONDS = 7 * 24 * 60 * 60;
|
|
3697
|
+
var PI_DURABLE_RUNTIME_ACTION_WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
3698
|
+
"runtime_action.submit",
|
|
3699
|
+
"runtime_action.commit"
|
|
3700
|
+
]);
|
|
3701
|
+
var PI_RUNTIME_ACTION_WRITE_RECEIPT_STATUSES = /* @__PURE__ */ new Set(["accepted", "pending_reconcile"]);
|
|
3702
|
+
var PI_TERMINAL_RUNTIME_ACTION_STATUSES = /* @__PURE__ */ new Set([
|
|
3703
|
+
"completed",
|
|
3704
|
+
"succeeded"
|
|
3705
|
+
]);
|
|
3694
3706
|
function approvedMcpInvocationSucceeded(results, invocationId) {
|
|
3695
3707
|
const approvedInvocationId = readString(invocationId);
|
|
3696
3708
|
return Boolean(approvedInvocationId && (Array.isArray(results) ? results : []).some((rawResult) => {
|
|
@@ -3704,18 +3716,81 @@ function governedMcpToolResult(structuredContent) {
|
|
|
3704
3716
|
const invocationId = readString(structuredContent.invocationId);
|
|
3705
3717
|
const providerContent = asRecord(structuredContent.content);
|
|
3706
3718
|
const providerStatus = readString(providerContent.status);
|
|
3707
|
-
const
|
|
3719
|
+
const providerResult = asRecord(providerContent.result);
|
|
3720
|
+
const effectResult = asRecord(providerResult.effectResult);
|
|
3708
3721
|
const intentId = readString(effectResult.artifactIntentId);
|
|
3709
3722
|
const manifestId = readString(effectResult.manifestId);
|
|
3710
3723
|
const sourceRelativePath = readString(effectResult.sourceRelativePath);
|
|
3711
3724
|
const sha256 = readString(effectResult.sha256);
|
|
3712
3725
|
const byteSize = readNumber(effectResult.byteSize, 0);
|
|
3713
3726
|
const artifactIntent = providerStatus === "pending_reconcile" && intentId && manifestId && sourceRelativePath && /^[a-f0-9]{64}$/.test(sha256 ?? "") && Number.isSafeInteger(byteSize) && byteSize > 0 ? { intentId, manifestId, sourceRelativePath, sha256, byteSize } : null;
|
|
3727
|
+
const runtimeActionToolName = readString(providerContent.toolName);
|
|
3728
|
+
const runtimeAction = runtimeActionToolName?.startsWith("runtime_action.") ? {
|
|
3729
|
+
toolName: runtimeActionToolName,
|
|
3730
|
+
...readString(providerResult.callId) ? { callId: readString(providerResult.callId) } : {},
|
|
3731
|
+
...readString(providerResult.planId) ? { planId: readString(providerResult.planId) } : {},
|
|
3732
|
+
...readString(providerResult.status) ? { resultStatus: readString(providerResult.status) } : {}
|
|
3733
|
+
} : null;
|
|
3714
3734
|
return {
|
|
3715
3735
|
...invocationId ? { invocationId } : {},
|
|
3716
3736
|
status,
|
|
3717
3737
|
...providerStatus ? { providerStatus } : {},
|
|
3718
|
-
...artifactIntent ? { artifactIntent } : {}
|
|
3738
|
+
...artifactIntent ? { artifactIntent } : {},
|
|
3739
|
+
...runtimeAction ? { runtimeAction } : {}
|
|
3740
|
+
};
|
|
3741
|
+
}
|
|
3742
|
+
function durablePiRuntimeActionEvidence(results) {
|
|
3743
|
+
const normalizedResults = (Array.isArray(results) ? results : []).map(asRecord);
|
|
3744
|
+
const writeCallIds = /* @__PURE__ */ new Set();
|
|
3745
|
+
const writePlanIds = /* @__PURE__ */ new Set();
|
|
3746
|
+
for (const result2 of normalizedResults) {
|
|
3747
|
+
const runtimeAction = asRecord(result2.runtimeAction);
|
|
3748
|
+
const toolName = readString(runtimeAction.toolName);
|
|
3749
|
+
const callId = readString(runtimeAction.callId);
|
|
3750
|
+
const planId = readString(runtimeAction.planId);
|
|
3751
|
+
const resultStatus = readString(runtimeAction.resultStatus);
|
|
3752
|
+
const status = readString(result2.status);
|
|
3753
|
+
const providerStatus = readString(result2.providerStatus);
|
|
3754
|
+
if (status === "succeeded" && providerStatus === "accepted" && toolName && resultStatus && PI_TERMINAL_RUNTIME_ACTION_STATUSES.has(resultStatus)) {
|
|
3755
|
+
const isLinkedStatus = toolName === "runtime_action.status" && (callId && writeCallIds.has(callId) || planId && writePlanIds.has(planId));
|
|
3756
|
+
const isDurableWrite = toolName === "runtime_action.submit" ? Boolean(callId) : toolName === "runtime_action.commit" && Boolean(planId || callId);
|
|
3757
|
+
if (isLinkedStatus || isDurableWrite) {
|
|
3758
|
+
return {
|
|
3759
|
+
kind: "runtime_action",
|
|
3760
|
+
...readString(result2.invocationId) ? { invocationId: readString(result2.invocationId) } : {},
|
|
3761
|
+
toolName,
|
|
3762
|
+
...callId ? { callId } : {},
|
|
3763
|
+
...planId ? { planId } : {}
|
|
3764
|
+
};
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
if (status !== "succeeded" || !PI_DURABLE_RUNTIME_ACTION_WRITE_TOOLS.has(toolName ?? "") || !PI_RUNTIME_ACTION_WRITE_RECEIPT_STATUSES.has(providerStatus ?? "")) continue;
|
|
3768
|
+
if (callId) writeCallIds.add(callId);
|
|
3769
|
+
if (planId) writePlanIds.add(planId);
|
|
3770
|
+
}
|
|
3771
|
+
return null;
|
|
3772
|
+
}
|
|
3773
|
+
function finalizedPiRuntimeArtifactEvidence(runtimeArtifacts) {
|
|
3774
|
+
const artifact = (Array.isArray(runtimeArtifacts) ? runtimeArtifacts : []).map(asRecord).find((entry) => readString(entry.status) === "finalized");
|
|
3775
|
+
if (!artifact) return null;
|
|
3776
|
+
const intentId = readString(artifact.intentId) ?? readString(artifact.artifactIntentId);
|
|
3777
|
+
return {
|
|
3778
|
+
kind: "runtime_artifact",
|
|
3779
|
+
...intentId ? { intentId } : {}
|
|
3780
|
+
};
|
|
3781
|
+
}
|
|
3782
|
+
function classifyPiTerminalCleanupDisposition(parsed, runtimeArtifacts) {
|
|
3783
|
+
const diagnostics = Array.isArray(parsed?.cleanupDiagnostics) ? parsed.cleanupDiagnostics.map(asRecord) : [];
|
|
3784
|
+
if (parsed?.terminalEventType !== "agent_end" || readString(parsed?.stopReason) || parsed?.hasAssistantOutput !== true || diagnostics.length === 0 || diagnostics.some((diagnostic) => readString(diagnostic.phase) !== "post_terminal" || readString(diagnostic.code) !== "pi_terminal_cleanup_permission_denied") || readNumber(parsed?.nonCleanupErrorCount, 0) > 0) return null;
|
|
3785
|
+
const durableEvidence = durablePiRuntimeActionEvidence(parsed?.mcpToolResults) ?? finalizedPiRuntimeArtifactEvidence(runtimeArtifacts);
|
|
3786
|
+
if (!durableEvidence) return null;
|
|
3787
|
+
return {
|
|
3788
|
+
status: "failed",
|
|
3789
|
+
phase: "post_terminal",
|
|
3790
|
+
errorCode: "pi_terminal_cleanup_permission_denied",
|
|
3791
|
+
isolatedFromBusinessResult: true,
|
|
3792
|
+
durableEvidence,
|
|
3793
|
+
diagnostics
|
|
3719
3794
|
};
|
|
3720
3795
|
}
|
|
3721
3796
|
function codexMcpToolResults(event) {
|
|
@@ -4159,8 +4234,11 @@ function parsePiJsonl(stdout) {
|
|
|
4159
4234
|
let terminalEventType = null;
|
|
4160
4235
|
let stopReason = null;
|
|
4161
4236
|
let hasAssistantOutput = false;
|
|
4237
|
+
let nonCleanupErrorCount = 0;
|
|
4238
|
+
let nonCleanupErrorMessage = null;
|
|
4162
4239
|
const messages = [];
|
|
4163
4240
|
const mcpToolResults = [];
|
|
4241
|
+
const cleanupDiagnostics = [];
|
|
4164
4242
|
const usage = { inputTokens: 0, cachedInputTokens: 0, outputTokens: 0 };
|
|
4165
4243
|
for (const rawLine of String(stdout ?? "").split(/\r?\n/)) {
|
|
4166
4244
|
const event = parseJsonLine(rawLine.trim());
|
|
@@ -4191,12 +4269,30 @@ function parsePiJsonl(stdout) {
|
|
|
4191
4269
|
if (event.type === "turn_end") sawTurnEnd = true;
|
|
4192
4270
|
if (event.type === "turn_end" || event.type === "agent_end") terminalEventType = event.type;
|
|
4193
4271
|
stopReason = readString(event.stopReason ?? event.stop_reason) ?? piNestedMessageStopReason(event) ?? stopReason;
|
|
4194
|
-
|
|
4272
|
+
const terminalError = piStopReasonErrorText(event) ?? piNestedMessageErrorText(event);
|
|
4273
|
+
if (terminalError) {
|
|
4274
|
+
nonCleanupErrorCount += 1;
|
|
4275
|
+
nonCleanupErrorMessage = terminalError;
|
|
4276
|
+
errorMessage = terminalError;
|
|
4277
|
+
}
|
|
4195
4278
|
hasAssistantOutput = maybeCapturePiMessage(event, messages, usage) || hasAssistantOutput;
|
|
4196
4279
|
continue;
|
|
4197
4280
|
}
|
|
4198
4281
|
if (event.type === "error") {
|
|
4199
|
-
|
|
4282
|
+
const eventError = readString(event.message);
|
|
4283
|
+
if (!eventError) continue;
|
|
4284
|
+
if (PI_TERMINAL_CLEANUP_PERMISSION_RE.test(eventError)) {
|
|
4285
|
+
cleanupDiagnostics.push({
|
|
4286
|
+
code: "pi_terminal_cleanup_permission_denied",
|
|
4287
|
+
message: eventError,
|
|
4288
|
+
phase: terminalEventType === "agent_end" ? "post_terminal" : "pre_terminal"
|
|
4289
|
+
});
|
|
4290
|
+
errorMessage = nonCleanupErrorMessage ?? eventError;
|
|
4291
|
+
} else {
|
|
4292
|
+
nonCleanupErrorCount += 1;
|
|
4293
|
+
nonCleanupErrorMessage = eventError;
|
|
4294
|
+
errorMessage = eventError;
|
|
4295
|
+
}
|
|
4200
4296
|
}
|
|
4201
4297
|
}
|
|
4202
4298
|
return {
|
|
@@ -4208,6 +4304,8 @@ function parsePiJsonl(stdout) {
|
|
|
4208
4304
|
stopReason,
|
|
4209
4305
|
hasAssistantOutput,
|
|
4210
4306
|
errorMessage,
|
|
4307
|
+
...nonCleanupErrorCount > 0 ? { nonCleanupErrorCount } : {},
|
|
4308
|
+
...cleanupDiagnostics.length > 0 ? { cleanupDiagnostics } : {},
|
|
4211
4309
|
...mcpToolResults.length > 0 ? { mcpToolResults } : {}
|
|
4212
4310
|
};
|
|
4213
4311
|
}
|
|
@@ -4953,7 +5051,79 @@ function normalizeRuntimeVersionText(value) {
|
|
|
4953
5051
|
const trimmed = value.trim();
|
|
4954
5052
|
return trimmed ? trimmed : null;
|
|
4955
5053
|
}
|
|
4956
|
-
|
|
5054
|
+
var EXACT_SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
|
|
5055
|
+
function isExactSemverVersion(value) {
|
|
5056
|
+
const normalized = normalizeRuntimeVersionText(value);
|
|
5057
|
+
const match = normalized?.match(EXACT_SEMVER_PATTERN);
|
|
5058
|
+
if (!match) return false;
|
|
5059
|
+
const prerelease = match[4]?.split(".") ?? [];
|
|
5060
|
+
return !prerelease.some(
|
|
5061
|
+
(identifier) => /^\d+$/.test(identifier) && identifier.length > 1 && identifier.startsWith("0")
|
|
5062
|
+
);
|
|
5063
|
+
}
|
|
5064
|
+
function compareNumericSemverIdentifiers(left, right) {
|
|
5065
|
+
if (left.length !== right.length) return left.length < right.length ? -1 : 1;
|
|
5066
|
+
if (left === right) return 0;
|
|
5067
|
+
return left < right ? -1 : 1;
|
|
5068
|
+
}
|
|
5069
|
+
function compareExactSemverVersions(current, recommended) {
|
|
5070
|
+
const normalizedCurrent = normalizeRuntimeVersionText(current);
|
|
5071
|
+
const normalizedRecommended = normalizeRuntimeVersionText(recommended);
|
|
5072
|
+
if (!normalizedCurrent || !normalizedRecommended || !isExactSemverVersion(normalizedCurrent) || !isExactSemverVersion(normalizedRecommended)) {
|
|
5073
|
+
return null;
|
|
5074
|
+
}
|
|
5075
|
+
const currentMatch = normalizedCurrent.match(EXACT_SEMVER_PATTERN);
|
|
5076
|
+
const recommendedMatch = normalizedRecommended.match(EXACT_SEMVER_PATTERN);
|
|
5077
|
+
if (!currentMatch || !recommendedMatch) return null;
|
|
5078
|
+
for (const index of [1, 2, 3]) {
|
|
5079
|
+
const comparison = compareNumericSemverIdentifiers(
|
|
5080
|
+
currentMatch[index],
|
|
5081
|
+
recommendedMatch[index]
|
|
5082
|
+
);
|
|
5083
|
+
if (comparison !== 0) return comparison;
|
|
5084
|
+
}
|
|
5085
|
+
const currentPrerelease = currentMatch[4]?.split(".");
|
|
5086
|
+
const recommendedPrerelease = recommendedMatch[4]?.split(".");
|
|
5087
|
+
if (!currentPrerelease && !recommendedPrerelease) return 0;
|
|
5088
|
+
if (!currentPrerelease) return 1;
|
|
5089
|
+
if (!recommendedPrerelease) return -1;
|
|
5090
|
+
const identifierCount = Math.max(
|
|
5091
|
+
currentPrerelease.length,
|
|
5092
|
+
recommendedPrerelease.length
|
|
5093
|
+
);
|
|
5094
|
+
for (let index = 0; index < identifierCount; index += 1) {
|
|
5095
|
+
const currentIdentifier = currentPrerelease[index];
|
|
5096
|
+
const recommendedIdentifier = recommendedPrerelease[index];
|
|
5097
|
+
if (currentIdentifier === void 0) return -1;
|
|
5098
|
+
if (recommendedIdentifier === void 0) return 1;
|
|
5099
|
+
if (currentIdentifier === recommendedIdentifier) continue;
|
|
5100
|
+
const currentIsNumeric = /^\d+$/.test(currentIdentifier);
|
|
5101
|
+
const recommendedIsNumeric = /^\d+$/.test(recommendedIdentifier);
|
|
5102
|
+
if (currentIsNumeric && recommendedIsNumeric) {
|
|
5103
|
+
return compareNumericSemverIdentifiers(
|
|
5104
|
+
currentIdentifier,
|
|
5105
|
+
recommendedIdentifier
|
|
5106
|
+
);
|
|
5107
|
+
}
|
|
5108
|
+
if (currentIsNumeric !== recommendedIsNumeric) {
|
|
5109
|
+
return currentIsNumeric ? -1 : 1;
|
|
5110
|
+
}
|
|
5111
|
+
return currentIdentifier < recommendedIdentifier ? -1 : 1;
|
|
5112
|
+
}
|
|
5113
|
+
return 0;
|
|
5114
|
+
}
|
|
5115
|
+
function versionPairRequiresUpgrade(current, recommended) {
|
|
5116
|
+
const normalizedCurrent = normalizeRuntimeVersionText(current);
|
|
5117
|
+
const normalizedRecommended = normalizeRuntimeVersionText(recommended);
|
|
5118
|
+
if (!normalizedCurrent || !normalizedRecommended) return false;
|
|
5119
|
+
const comparison = compareExactSemverVersions(
|
|
5120
|
+
normalizedCurrent,
|
|
5121
|
+
normalizedRecommended
|
|
5122
|
+
);
|
|
5123
|
+
if (comparison !== null) return comparison < 0;
|
|
5124
|
+
return false;
|
|
5125
|
+
}
|
|
5126
|
+
function normalizedTextPairDiffers(current, recommended) {
|
|
4957
5127
|
const normalizedCurrent = normalizeRuntimeVersionText(current);
|
|
4958
5128
|
const normalizedRecommended = normalizeRuntimeVersionText(recommended);
|
|
4959
5129
|
if (!normalizedCurrent || !normalizedRecommended) return false;
|
|
@@ -4962,10 +5132,10 @@ function versionPairDiffers(current, recommended) {
|
|
|
4962
5132
|
function summarizeAmasterRuntimeVersionDrift(input = {}) {
|
|
4963
5133
|
const versionMismatches = [];
|
|
4964
5134
|
const bundleMismatches = [];
|
|
4965
|
-
if (
|
|
5135
|
+
if (versionPairRequiresUpgrade(input.connectorVersion, input.recommendedConnectorVersion)) {
|
|
4966
5136
|
versionMismatches.push("connector package version differs from the recommended package");
|
|
4967
5137
|
}
|
|
4968
|
-
if (
|
|
5138
|
+
if (normalizedTextPairDiffers(input.buildCommit, input.recommendedBuildCommit)) {
|
|
4969
5139
|
bundleMismatches.push("build commit differs from the deployed connector package");
|
|
4970
5140
|
}
|
|
4971
5141
|
const recommendedConnectorVersion = normalizeRuntimeVersionText(input.recommendedConnectorVersion);
|
|
@@ -6061,7 +6231,7 @@ function readWorkspaceStatus(cwd, opts = {}) {
|
|
|
6061
6231
|
}
|
|
6062
6232
|
|
|
6063
6233
|
// src/amaster-runtime-daemon.mjs
|
|
6064
|
-
var CONNECTOR_VERSION = "0.1.0-beta.
|
|
6234
|
+
var CONNECTOR_VERSION = "0.1.0-beta.45";
|
|
6065
6235
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
6066
6236
|
var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
|
|
6067
6237
|
var CHECKPOINT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -6339,7 +6509,10 @@ function piCapabilitySourcesDiagnostics() {
|
|
|
6339
6509
|
const piAgentHome = configuredPiAgentHome ?? piCodingAgentDir;
|
|
6340
6510
|
const piAgentHomeSource = configuredPiAgentHome ? "PI_AGENT_HOME" : piCodingAgentDirSource;
|
|
6341
6511
|
const userSkillsPath = piAgentHome ? join13(piAgentHome, "skills") : null;
|
|
6342
|
-
const
|
|
6512
|
+
const configuredMarketplaceSkillsPath = safeExpandPath(
|
|
6513
|
+
process.env.PI_AGENT_MARKETPLACE_SKILLS_DIR
|
|
6514
|
+
);
|
|
6515
|
+
const marketplaceSkillsPath = configuredMarketplaceSkillsPath ?? (piAgentHome ? join13(piAgentHome, "marketplace", "skills") : null);
|
|
6343
6516
|
const builtinSkillsPath = safeExpandPath(process.env.PI_AGENT_BUILTIN_SKILLS_DIR) ?? safeExpandPath(process.env.AMASTER_BUILTIN_SKILLS);
|
|
6344
6517
|
const mcpConfigPath = safeExpandPath(process.env.PI_AGENT_MCP_SERVERS_FILE) ?? (piAgentHome ? join13(piAgentHome, "mcp.json") : null);
|
|
6345
6518
|
const settingsConfigPath = piCodingAgentDir ? join13(piCodingAgentDir, "settings.json") : null;
|
|
@@ -6347,7 +6520,7 @@ function piCapabilitySourcesDiagnostics() {
|
|
|
6347
6520
|
safeSkillRootSummary("user", `${piAgentHomeSource}/skills`, userSkillsPath),
|
|
6348
6521
|
safeSkillRootSummary(
|
|
6349
6522
|
"marketplace",
|
|
6350
|
-
|
|
6523
|
+
configuredMarketplaceSkillsPath ? "PI_AGENT_MARKETPLACE_SKILLS_DIR" : `${piAgentHomeSource}/marketplace/skills`,
|
|
6351
6524
|
marketplaceSkillsPath
|
|
6352
6525
|
),
|
|
6353
6526
|
safeSkillRootSummary(
|
|
@@ -6357,7 +6530,9 @@ function piCapabilitySourcesDiagnostics() {
|
|
|
6357
6530
|
)
|
|
6358
6531
|
];
|
|
6359
6532
|
const visibleSkillCount = skillRoots.reduce((sum, root) => sum + readNumber(root.skillCount, 0), 0);
|
|
6360
|
-
const missingRootKinds = skillRoots.filter(
|
|
6533
|
+
const missingRootKinds = skillRoots.filter(
|
|
6534
|
+
(root) => root.configured === true && root.available !== true && (root.kind !== "marketplace" || configuredMarketplaceSkillsPath)
|
|
6535
|
+
).map((root) => root.kind);
|
|
6361
6536
|
const mcpConfig = safeJsonConfigSummary(
|
|
6362
6537
|
readString(process.env.PI_AGENT_MCP_SERVERS_FILE) ? "PI_AGENT_MCP_SERVERS_FILE" : `${piAgentHomeSource}/mcp.json`,
|
|
6363
6538
|
mcpConfigPath,
|
|
@@ -9611,18 +9786,33 @@ async function executeRunCommand(config, command) {
|
|
|
9611
9786
|
const memoryLimitError = hasMemoryLimit ? `${executor.kind === "pi" ? "Pi Agent" : "Executor"} memory limit exceeded: RSS ${readNumber(memoryLimit.rssBytes, 0)} bytes exceeded ${readNumber(memoryLimit.limitBytes, config.executorMaxRssMb * 1024 * 1024)} bytes` : null;
|
|
9612
9787
|
const piUsageDiagnostic = executor.kind === "pi" && !hasOutputFlood && piOutputUsageMetadataMissing(parsed) ? "Pi Agent exited without usage metadata" : null;
|
|
9613
9788
|
const completionOutputStopped = executor.kind === "pi" && piCompletionOutputStopped(parsed, execution);
|
|
9614
|
-
const
|
|
9615
|
-
|
|
9789
|
+
const cleanupDisposition = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition(parsed, runtimeArtifacts) : null;
|
|
9790
|
+
if (cleanupDisposition) {
|
|
9791
|
+
await ingestLog(
|
|
9792
|
+
config,
|
|
9793
|
+
command,
|
|
9794
|
+
"system",
|
|
9795
|
+
"warn",
|
|
9796
|
+
"Pi terminal result was preserved after a post-terminal cleanup permission failure",
|
|
9797
|
+
{
|
|
9798
|
+
presentationKind: "pi_terminal_cleanup",
|
|
9799
|
+
cleanupDisposition
|
|
9800
|
+
}
|
|
9801
|
+
);
|
|
9802
|
+
}
|
|
9803
|
+
const parsedForValidation = cleanupDisposition ? { ...parsed, errorMessage: null } : parsed;
|
|
9804
|
+
const piInvalidOutputError = executor.kind === "pi" ? piOutputValidationError(parsedForValidation, {
|
|
9805
|
+
allowMissingTurnEnd: completionOutputStopped || Boolean(cleanupDisposition),
|
|
9616
9806
|
allowMissingAssistantOutput: execution.completionOutputType === "approval_required"
|
|
9617
9807
|
}) : null;
|
|
9618
|
-
const piProviderFailure = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError ? classifyPiProviderError(
|
|
9619
|
-
const parsedErrorMessage = outputFloodError ?? memoryLimitError ?? piInvalidOutputError ?? nativeSessionRolloutError ?? nativeSessionRolloutCleanupError ??
|
|
9808
|
+
const piProviderFailure = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError ? classifyPiProviderError(parsedForValidation) : null;
|
|
9809
|
+
const parsedErrorMessage = outputFloodError ?? memoryLimitError ?? piInvalidOutputError ?? nativeSessionRolloutError ?? nativeSessionRolloutCleanupError ?? parsedForValidation.errorMessage;
|
|
9620
9810
|
const codexTransientFailure = executor.kind === "codex" && (execution.exitCode ?? 0) !== 0 ? classifyCodexTransientUpstreamError({
|
|
9621
9811
|
stdout: execution.stdout,
|
|
9622
9812
|
stderr: execution.stderr,
|
|
9623
9813
|
errorMessage: parsedErrorMessage
|
|
9624
9814
|
}) : null;
|
|
9625
|
-
const succeeded = !cancelled && !hasOutputFlood && !hasMemoryLimit && (execution.exitCode === 0 || completionOutputStopped) && !execution.timedOut && !execution.spawnError && !parsedErrorMessage;
|
|
9815
|
+
const succeeded = !cancelled && !hasOutputFlood && !hasMemoryLimit && (execution.exitCode === 0 || completionOutputStopped || Boolean(cleanupDisposition)) && !execution.timedOut && !execution.spawnError && !parsedErrorMessage;
|
|
9626
9816
|
const resultStderr = filterExecutionStderrForResult(executor.kind, execution.stderr);
|
|
9627
9817
|
const error = execution.timedOut ? `Executor timed out after ${config.executorTimeoutSeconds}s` : cancelled ? "Executor cancelled by AMaster control plane" : execution.spawnError ?? parsedErrorMessage ?? (succeeded ? null : `Executor exited with code ${execution.exitCode ?? "unknown"}`);
|
|
9628
9818
|
const costUsage = parsedCostUsage(parsed.usage);
|
|
@@ -9655,6 +9845,7 @@ async function executeRunCommand(config, command) {
|
|
|
9655
9845
|
timedOut: execution.timedOut,
|
|
9656
9846
|
...execution.outputDrainForcedClosed ? { outputDrainForcedClosed: true } : {},
|
|
9657
9847
|
...readString(execution.completionOutputType) ? { completionOutputType: readString(execution.completionOutputType) } : {},
|
|
9848
|
+
...cleanupDisposition ? { cleanupDisposition } : {},
|
|
9658
9849
|
...cancelled ? { cancelledByControlPlane: true } : {},
|
|
9659
9850
|
...invocation.nativeSession ? { nativeSession: invocation.nativeSession } : {},
|
|
9660
9851
|
...nativeSessionRollout ? { nativeSessionRollout } : {},
|
package/dist/amaster-runtime.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
5
5
|
import { homedir, hostname } from "node:os";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
|
|
8
|
-
const CONNECTOR_VERSION = "0.1.0-beta.
|
|
8
|
+
const CONNECTOR_VERSION = "0.1.0-beta.45";
|
|
9
9
|
|
|
10
10
|
const CAPABILITIES = [
|
|
11
11
|
"remote_registration",
|