@amaster.ai/employee-runtime-connector 0.1.1-beta.266 → 0.1.1-beta.267
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.
|
@@ -18,9 +18,16 @@ export const BUILD_SUPPORTED_CAPABILITIES = Object.freeze([
|
|
|
18
18
|
"logs_cost_workspace_status",
|
|
19
19
|
"browser_credential_ref_fill_v1",
|
|
20
20
|
"execution_lanes_v1",
|
|
21
|
+
"mirrorx_initialization_context_v1",
|
|
22
|
+
"mirrorx_initialization_completion_v1",
|
|
21
23
|
]);
|
|
22
24
|
|
|
23
25
|
const DYNAMIC_READINESS = Object.freeze({
|
|
26
|
+
mirrorx_initialization_completion_v1: {
|
|
27
|
+
reasonCode: "managed_linux_pi_required",
|
|
28
|
+
ready: (input) => process.platform === "linux" && input.runnerKind === "cloud_managed"
|
|
29
|
+
&& input.executors.some((executor) => executor.kind === "pi"),
|
|
30
|
+
},
|
|
24
31
|
artifact_template_catalog_v1: {
|
|
25
32
|
reasonCode: "artifact_template_catalog_not_ready",
|
|
26
33
|
ready: (input) => {
|
|
@@ -5114,7 +5114,9 @@ var AMASTER_RUNTIME_CONNECTOR_CAPABILITIES = [
|
|
|
5114
5114
|
"continue_task_v1",
|
|
5115
5115
|
"run_exit_live_path_closure_v1",
|
|
5116
5116
|
"browser_credential_ref_fill_v1",
|
|
5117
|
-
"execution_lanes_v1"
|
|
5117
|
+
"execution_lanes_v1",
|
|
5118
|
+
"mirrorx_initialization_context_v1",
|
|
5119
|
+
"mirrorx_initialization_completion_v1"
|
|
5118
5120
|
];
|
|
5119
5121
|
var RUNTIME_EXECUTION_LANES = ["business", "conversation"];
|
|
5120
5122
|
var runtimeExecutionLaneSchema = external_exports.enum(RUNTIME_EXECUTION_LANES);
|
|
@@ -13795,7 +13797,11 @@ var governedBusinessTaskEnrollmentReadModelSchema = external_exports.object({
|
|
|
13795
13797
|
discoverySource: governedBusinessTaskDiscoverySourceSchema.nullable(),
|
|
13796
13798
|
finding: external_exports.object({
|
|
13797
13799
|
code: external_exports.string().trim().min(1),
|
|
13798
|
-
message: external_exports.string().trim().min(1)
|
|
13800
|
+
message: external_exports.string().trim().min(1),
|
|
13801
|
+
invalidFields: external_exports.array(external_exports.object({
|
|
13802
|
+
path: external_exports.string().trim().min(1),
|
|
13803
|
+
code: external_exports.string().trim().min(1)
|
|
13804
|
+
}).strict()).max(20).optional()
|
|
13799
13805
|
}).strict().nullable()
|
|
13800
13806
|
}).strict();
|
|
13801
13807
|
|
|
@@ -16742,7 +16748,8 @@ var companyArtifactSchema = external_exports.object({
|
|
|
16742
16748
|
issue: external_exports.object({
|
|
16743
16749
|
id: external_exports.string().uuid(),
|
|
16744
16750
|
identifier: external_exports.string(),
|
|
16745
|
-
title: external_exports.string()
|
|
16751
|
+
title: external_exports.string(),
|
|
16752
|
+
status: external_exports.string().optional()
|
|
16746
16753
|
}),
|
|
16747
16754
|
project: external_exports.object({
|
|
16748
16755
|
id: external_exports.string().uuid(),
|
|
@@ -16761,7 +16768,8 @@ var companyArtifactGroupSchema = external_exports.object({
|
|
|
16761
16768
|
issue: external_exports.object({
|
|
16762
16769
|
id: external_exports.string().uuid(),
|
|
16763
16770
|
identifier: external_exports.string(),
|
|
16764
|
-
title: external_exports.string()
|
|
16771
|
+
title: external_exports.string(),
|
|
16772
|
+
status: external_exports.string().optional()
|
|
16765
16773
|
}),
|
|
16766
16774
|
title: external_exports.string(),
|
|
16767
16775
|
count: external_exports.number().int().min(0),
|
|
@@ -22066,6 +22074,343 @@ function reconcileManagedCodebuddyMcpProfiles(rootPath, options = {}) {
|
|
|
22066
22074
|
};
|
|
22067
22075
|
}
|
|
22068
22076
|
|
|
22077
|
+
// src/amaster-runtime-daemon/pi-initialization-completion.mjs
|
|
22078
|
+
async function runInitializationCompletion({ plan, authority, call, sleep, now, onReceipt = () => {
|
|
22079
|
+
}, timeoutMs = 12e4 }) {
|
|
22080
|
+
const deadline = now() + timeoutMs;
|
|
22081
|
+
const receipts = [];
|
|
22082
|
+
let stage = "upload";
|
|
22083
|
+
let callId;
|
|
22084
|
+
const fail3 = (code, detail) => {
|
|
22085
|
+
throw Object.assign(new Error(code), { detail });
|
|
22086
|
+
};
|
|
22087
|
+
async function invoke(name, args) {
|
|
22088
|
+
if (now() >= deadline) fail3("initialization_completion_deadline");
|
|
22089
|
+
let envelope;
|
|
22090
|
+
for (let transportFailures = 0; ; ) {
|
|
22091
|
+
if (now() >= deadline) fail3("initialization_completion_deadline");
|
|
22092
|
+
try {
|
|
22093
|
+
envelope = await call(name, args, Math.min(45e3, deadline - now()));
|
|
22094
|
+
break;
|
|
22095
|
+
} catch (error) {
|
|
22096
|
+
if (error?.retryable !== true) throw error;
|
|
22097
|
+
const leaseWait = error.code === "invocation_in_progress" && Number.isSafeInteger(error.retryAfterMs) && error.retryAfterMs >= 0;
|
|
22098
|
+
if (!leaseWait && ++transportFailures >= 3) throw error;
|
|
22099
|
+
const delay = leaseWait ? Math.max(1e3, error.retryAfterMs) : 1e3 * transportFailures;
|
|
22100
|
+
await sleep(Math.min(delay, Math.max(0, deadline - now())));
|
|
22101
|
+
}
|
|
22102
|
+
}
|
|
22103
|
+
const content = envelope?.content;
|
|
22104
|
+
const provider = envelope?.providerReceipt;
|
|
22105
|
+
if (!envelope?.invocationId || provider?.invocationId !== envelope.invocationId || provider?.provider !== "amaster_actions" || !["runId", "commandId", "issueId"].every((key) => authority[key] && provider[key] === authority[key]) || content?.schemaVersion !== "runtime-action-v1" || content?.toolName !== name.replace("runtime_action_", "runtime_action.")) {
|
|
22106
|
+
fail3("initialization_completion_receipt_mismatch");
|
|
22107
|
+
}
|
|
22108
|
+
if (envelope.status !== "succeeded" || !["accepted", "pending_reconcile"].includes(content.status)) {
|
|
22109
|
+
fail3("initialization_completion_action_not_accepted", content.error ?? { status: envelope.status });
|
|
22110
|
+
}
|
|
22111
|
+
const result2 = content.result;
|
|
22112
|
+
await onReceipt(envelope);
|
|
22113
|
+
receipts.push({
|
|
22114
|
+
stage,
|
|
22115
|
+
invocationId: envelope.invocationId,
|
|
22116
|
+
callId: result2?.callId,
|
|
22117
|
+
planId: result2?.planId,
|
|
22118
|
+
status: result2?.status
|
|
22119
|
+
});
|
|
22120
|
+
if (!result2 || result2.error) fail3("initialization_completion_action_failed", result2?.error);
|
|
22121
|
+
return result2;
|
|
22122
|
+
}
|
|
22123
|
+
async function settleCall(value, actionType) {
|
|
22124
|
+
callId = value.callId;
|
|
22125
|
+
if (!callId || value.actionType !== actionType) fail3("initialization_completion_call_mismatch");
|
|
22126
|
+
for (let attempt = 0; ; attempt++) {
|
|
22127
|
+
if (value.callId !== callId || value.actionType !== actionType) fail3("initialization_completion_call_mismatch");
|
|
22128
|
+
if (value.status === "succeeded") return value;
|
|
22129
|
+
if (!["pending_reconcile", "claimed", "executing"].includes(value.status)) {
|
|
22130
|
+
fail3("initialization_completion_action_incomplete", { status: value.status, error: value.error });
|
|
22131
|
+
}
|
|
22132
|
+
if (now() >= deadline) fail3("initialization_completion_deadline");
|
|
22133
|
+
await sleep(Math.min(1e3 * (attempt + 1), 5e3));
|
|
22134
|
+
value = await invoke("runtime_action_status", { callId });
|
|
22135
|
+
}
|
|
22136
|
+
}
|
|
22137
|
+
try {
|
|
22138
|
+
const doc = plan.initializationDocument;
|
|
22139
|
+
const materialized = plan.initializationDocumentMaterialization;
|
|
22140
|
+
if (!plan.planId || !plan.revision || !["planned", "committing", "pending_reconcile", "completed"].includes(plan.status) || materialized?.status !== "materialized" || materialized.planId !== plan.planId || materialized.revision !== plan.revision || materialized.sha256 !== doc?.sha256 || materialized.byteSize !== doc?.byteSize || materialized.path !== doc?.path) {
|
|
22141
|
+
fail3("initialization_completion_invalid_plan");
|
|
22142
|
+
}
|
|
22143
|
+
const prefix = "initialization-complete:" + plan.planId;
|
|
22144
|
+
const { createHash: createHash19 } = await import("node:crypto");
|
|
22145
|
+
const uploadKey = prefix + ":upload:" + createHash19("sha256").update(materialized.path).digest("hex");
|
|
22146
|
+
const upload = await settleCall(await invoke("runtime_action_submit", {
|
|
22147
|
+
idempotencyKey: uploadKey,
|
|
22148
|
+
action: {
|
|
22149
|
+
type: "upload_artifact",
|
|
22150
|
+
idempotencyKey: uploadKey,
|
|
22151
|
+
path: materialized.path,
|
|
22152
|
+
title: "Organization Plan",
|
|
22153
|
+
contentType: "text/markdown",
|
|
22154
|
+
artifactPurpose: "initialization_organization_plan",
|
|
22155
|
+
createWorkProduct: true,
|
|
22156
|
+
evidenceRole: "source",
|
|
22157
|
+
isPrimary: true,
|
|
22158
|
+
status: "ready_for_review"
|
|
22159
|
+
}
|
|
22160
|
+
}), "upload_artifact");
|
|
22161
|
+
if (upload.postcondition?.artifactFinalized !== true || upload.postcondition?.attachmentReadback !== true || upload.postcondition?.workProductReadback !== true || upload.effectResult?.sha256 !== doc.sha256 || upload.effectResult?.byteSize !== doc.byteSize || !upload.effectResult?.attachmentId || !upload.effectResult?.workProductId) {
|
|
22162
|
+
fail3("initialization_completion_artifact_mismatch");
|
|
22163
|
+
}
|
|
22164
|
+
stage = "commit";
|
|
22165
|
+
callId = void 0;
|
|
22166
|
+
const committed = await invoke("runtime_action_commit", { planId: plan.planId, revision: plan.revision });
|
|
22167
|
+
if (committed.planId !== plan.planId || committed.revision !== plan.revision || committed.status !== "completed" || committed.failure || committed.nextActionIndex !== committed.actionCount) {
|
|
22168
|
+
fail3("initialization_completion_plan_incomplete", { status: committed.status, failure: committed.failure });
|
|
22169
|
+
}
|
|
22170
|
+
stage = "ready";
|
|
22171
|
+
const completed = await settleCall(await invoke("runtime_action_submit", {
|
|
22172
|
+
idempotencyKey: prefix + ":done",
|
|
22173
|
+
action: { type: "update_parent", status: "done" }
|
|
22174
|
+
}), "update_parent");
|
|
22175
|
+
if (completed.effectResult?.issueId !== authority.issueId || completed.effectResult?.status !== "done" || completed.postcondition?.issuePersisted !== true || completed.postcondition?.status !== "done" || completed.postcondition?.issueTerminalizationDeferred === true) {
|
|
22176
|
+
fail3("initialization_completion_ready_not_confirmed");
|
|
22177
|
+
}
|
|
22178
|
+
return {
|
|
22179
|
+
status: "completed",
|
|
22180
|
+
planId: plan.planId,
|
|
22181
|
+
revision: plan.revision,
|
|
22182
|
+
attachmentId: upload.effectResult.attachmentId,
|
|
22183
|
+
workProductId: upload.effectResult.workProductId,
|
|
22184
|
+
completionCallId: completed.callId,
|
|
22185
|
+
receipts
|
|
22186
|
+
};
|
|
22187
|
+
} catch (error) {
|
|
22188
|
+
return {
|
|
22189
|
+
status: "incomplete",
|
|
22190
|
+
stage,
|
|
22191
|
+
planId: plan.planId,
|
|
22192
|
+
revision: plan.revision,
|
|
22193
|
+
callId,
|
|
22194
|
+
code: error.message,
|
|
22195
|
+
detail: error.detail,
|
|
22196
|
+
receipts
|
|
22197
|
+
};
|
|
22198
|
+
}
|
|
22199
|
+
}
|
|
22200
|
+
function managedPiInitializationCompletionSource() {
|
|
22201
|
+
return `const runInitializationCompletion = ${runInitializationCompletion.toString()};
|
|
22202
|
+
async function initializationCompletionCall(name, args, timeoutMs = 45000) {
|
|
22203
|
+
const server = JSON.parse(fs.readFileSync(configPath, "utf8")).mcpServers.amaster;
|
|
22204
|
+
const id = randomUUID();
|
|
22205
|
+
const chunks = []; let size = 0; let status;
|
|
22206
|
+
try {
|
|
22207
|
+
const response = await fetch(server.url, { method: "POST", redirect: "error",
|
|
22208
|
+
headers: { ...server.headers, "Content-Type": "application/json", Accept: "application/json" },
|
|
22209
|
+
body: JSON.stringify({ jsonrpc: "2.0", id, method: "tools/call", params: { name, arguments: args } }),
|
|
22210
|
+
signal: AbortSignal.timeout(timeoutMs) });
|
|
22211
|
+
status = response.status;
|
|
22212
|
+
if (!response.ok && status !== 409) {
|
|
22213
|
+
await response.body?.cancel();
|
|
22214
|
+
throw Object.assign(new Error("initialization_completion_http_" + response.status), {
|
|
22215
|
+
retryable: [429, 500, 502, 503, 504].includes(response.status),
|
|
22216
|
+
});
|
|
22217
|
+
}
|
|
22218
|
+
for await (const part of response.body) {
|
|
22219
|
+
size += part.length;
|
|
22220
|
+
if (size > 256 * 1024) throw new Error("initialization_completion_response_too_large");
|
|
22221
|
+
chunks.push(part);
|
|
22222
|
+
}
|
|
22223
|
+
} catch (error) {
|
|
22224
|
+
if (["TypeError", "TimeoutError", "AbortError"].includes(error?.name)) error.retryable = true;
|
|
22225
|
+
throw error;
|
|
22226
|
+
}
|
|
22227
|
+
const rpc = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
22228
|
+
if (status === 409) {
|
|
22229
|
+
const data = rpc?.error?.data;
|
|
22230
|
+
const leaseWait = rpc?.jsonrpc === "2.0" && rpc.id === id
|
|
22231
|
+
&& data?.reasonCode === "invocation_in_progress"
|
|
22232
|
+
&& Number.isSafeInteger(data.retryAfterMs) && data.retryAfterMs >= 0;
|
|
22233
|
+
throw Object.assign(new Error(leaseWait ? "invocation_in_progress" : "initialization_completion_http_409"), {
|
|
22234
|
+
retryable: leaseWait, code: leaseWait ? "invocation_in_progress" : undefined,
|
|
22235
|
+
retryAfterMs: leaseWait ? data.retryAfterMs : undefined,
|
|
22236
|
+
});
|
|
22237
|
+
}
|
|
22238
|
+
if (rpc?.id !== id || rpc.error) throw new Error("initialization_completion_rpc_error");
|
|
22239
|
+
return JSON.parse(rpc.result?.content?.[0]?.text);
|
|
22240
|
+
}`;
|
|
22241
|
+
}
|
|
22242
|
+
|
|
22243
|
+
// src/amaster-runtime-daemon/pi-initialization-document.mjs
|
|
22244
|
+
function managedPiInitializationDocumentExtensionSource(cwd, configPath = `${cwd}/.pi/mcp.json`, completionAuthority = null) {
|
|
22245
|
+
return `import fs from "node:fs";
|
|
22246
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
22247
|
+
const cwd = ${JSON.stringify(cwd)};
|
|
22248
|
+
const configPath = ${JSON.stringify(configPath)};
|
|
22249
|
+
const completionAuthority = ${JSON.stringify(completionAuthority)};
|
|
22250
|
+
${managedPiInitializationCompletionSource()}
|
|
22251
|
+
export default function(pi) {
|
|
22252
|
+
pi.on("tool_result", async (event) => {
|
|
22253
|
+
// Linux dir-fd paths prevent a concurrent directory replacement redirecting writes.
|
|
22254
|
+
// Other executors retain the original document workflow.
|
|
22255
|
+
if (process.platform !== "linux" || event.isError || event.details?.server !== "amaster"
|
|
22256
|
+
|| !["runtime_action_plan", "runtime_action_status"].includes(event.toolName)) return;
|
|
22257
|
+
if (!Array.isArray(event.content) || event.content.length !== 1 || event.content[0].type !== "text") return;
|
|
22258
|
+
let envelope;
|
|
22259
|
+
try { envelope = JSON.parse(event.content[0].text); } catch { return; }
|
|
22260
|
+
const call = envelope?.content;
|
|
22261
|
+
const result = call?.result;
|
|
22262
|
+
const doc = result?.initializationDocument;
|
|
22263
|
+
if (envelope?.status !== "succeeded" || call?.status !== "accepted"
|
|
22264
|
+
|| call?.schemaVersion !== "runtime-action-v1"
|
|
22265
|
+
|| !["runtime_action.plan", "runtime_action.status"].includes(call?.toolName) || !doc) return;
|
|
22266
|
+
let root, parent, file, temp;
|
|
22267
|
+
const canonicalName = "organization-plan-" + result.planId + ".md";
|
|
22268
|
+
let targetName = canonicalName;
|
|
22269
|
+
try {
|
|
22270
|
+
if (doc.version !== 1 || (doc.path !== "deliverables/" + targetName
|
|
22271
|
+
&& !(typeof doc.markdown === "string" && doc.path === "deliverables/organization-plan.md"))
|
|
22272
|
+
|| doc.contentType !== "text/markdown" || !/^[0-9a-f]{64}$/.test(doc.sha256)
|
|
22273
|
+
|| !/^[0-9a-f-]{36}$/.test(result.planId) || !result.revision || !doc.initializationId
|
|
22274
|
+
|| !Number.isSafeInteger(doc.initializationRevision) || doc.initializationRevision < 1
|
|
22275
|
+
|| !Number.isSafeInteger(doc.byteSize) || doc.byteSize < 1 || doc.byteSize > 64 * 1024 * 1024) {
|
|
22276
|
+
throw new Error("invalid_document_snapshot");
|
|
22277
|
+
}
|
|
22278
|
+
if (doc.contentRef && (doc.contentRef.kind !== "initialization_plan_document"
|
|
22279
|
+
|| doc.contentRef.planId !== result.planId || doc.contentRef.readTool !== "runtime_action.status")) {
|
|
22280
|
+
throw new Error("invalid_document_reference");
|
|
22281
|
+
}
|
|
22282
|
+
// Pin the directory and verify existing bytes before loading credentials or reading chunks.
|
|
22283
|
+
const flags = fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW;
|
|
22284
|
+
root = fs.openSync(cwd, flags);
|
|
22285
|
+
const rootPath = "/proc/self/fd/" + root;
|
|
22286
|
+
try { fs.mkdirSync(rootPath + "/deliverables", { mode: 0o700 }); }
|
|
22287
|
+
catch (error) { if (error.code !== "EEXIST") throw error; }
|
|
22288
|
+
parent = fs.openSync(rootPath + "/deliverables", flags);
|
|
22289
|
+
const parentPath = "/proc/self/fd/" + parent;
|
|
22290
|
+
let target;
|
|
22291
|
+
// Preserve conflicts and select a stable alternate; replay verifies these same candidates.
|
|
22292
|
+
function selectTarget() {
|
|
22293
|
+
for (let attempt = 0; attempt < 32; attempt++) {
|
|
22294
|
+
targetName = attempt === 0 ? canonicalName
|
|
22295
|
+
: "organization-plan-" + result.planId + "-" + doc.sha256 + "-" + attempt + ".md";
|
|
22296
|
+
target = parentPath + "/" + targetName;
|
|
22297
|
+
let existing;
|
|
22298
|
+
try {
|
|
22299
|
+
existing = fs.openSync(target, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
|
|
22300
|
+
const stat = fs.fstatSync(existing);
|
|
22301
|
+
if (stat.isFile() && stat.size === doc.byteSize
|
|
22302
|
+
&& createHash("sha256").update(fs.readFileSync(existing)).digest("hex") === doc.sha256) return true;
|
|
22303
|
+
} catch (error) {
|
|
22304
|
+
if (error.code === "ENOENT") return false;
|
|
22305
|
+
if (!["ELOOP", "EACCES", "EISDIR"].includes(error.code)) throw error;
|
|
22306
|
+
} finally { if (existing !== undefined) fs.closeSync(existing); }
|
|
22307
|
+
}
|
|
22308
|
+
throw new Error("document_recovery_paths_exhausted");
|
|
22309
|
+
}
|
|
22310
|
+
let replayed = selectTarget();
|
|
22311
|
+
if (!replayed) {
|
|
22312
|
+
let bytes;
|
|
22313
|
+
if (doc.contentRef) {
|
|
22314
|
+
// Use this run's existing governed session; references cannot select an endpoint or credential.
|
|
22315
|
+
const server = JSON.parse(fs.readFileSync(configPath, "utf8")).mcpServers.amaster;
|
|
22316
|
+
const chunks = [];
|
|
22317
|
+
let offset = 0;
|
|
22318
|
+
while (offset < doc.byteSize) {
|
|
22319
|
+
const id = randomUUID();
|
|
22320
|
+
const response = await fetch(server.url, { method: "POST", redirect: "error",
|
|
22321
|
+
headers: { ...server.headers, "Content-Type": "application/json", Accept: "application/json" },
|
|
22322
|
+
body: JSON.stringify({ jsonrpc: "2.0", id, method: "tools/call", params: {
|
|
22323
|
+
name: "runtime_action_status", arguments: { planId: result.planId, documentOffset: offset },
|
|
22324
|
+
} }), signal: AbortSignal.timeout(30000) });
|
|
22325
|
+
if (!response.ok) { await response.body?.cancel(); throw new Error("document_read_denied"); }
|
|
22326
|
+
const parts = [];
|
|
22327
|
+
let size = 0;
|
|
22328
|
+
for await (const part of response.body) {
|
|
22329
|
+
size += part.length;
|
|
22330
|
+
if (size > 256 * 1024) throw new Error("document_chunk_response_too_large");
|
|
22331
|
+
parts.push(part);
|
|
22332
|
+
}
|
|
22333
|
+
const rpc = JSON.parse(Buffer.concat(parts).toString("utf8"));
|
|
22334
|
+
const readEnvelope = JSON.parse(rpc.result?.content?.[0]?.text);
|
|
22335
|
+
const read = readEnvelope?.content;
|
|
22336
|
+
const value = read?.result;
|
|
22337
|
+
const chunk = value?.initializationDocumentChunk;
|
|
22338
|
+
if (rpc.id !== id || readEnvelope.status !== "succeeded" || read?.status !== "accepted"
|
|
22339
|
+
|| value?.planId !== result.planId || value?.revision !== result.revision
|
|
22340
|
+
|| value?.initializationDocument?.sha256 !== doc.sha256
|
|
22341
|
+
|| value?.initializationDocument?.byteSize !== doc.byteSize
|
|
22342
|
+
|| chunk?.encoding !== "base64" || chunk.offset !== offset || typeof chunk.data !== "string") {
|
|
22343
|
+
throw new Error("invalid_document_chunk");
|
|
22344
|
+
}
|
|
22345
|
+
const part = Buffer.from(chunk.data, "base64");
|
|
22346
|
+
if (!part.length || part.length > 48 * 1024 || part.toString("base64") !== chunk.data
|
|
22347
|
+
|| offset + part.length > doc.byteSize
|
|
22348
|
+
|| chunk.nextOffset !== (offset + part.length < doc.byteSize ? offset + part.length : null)) {
|
|
22349
|
+
throw new Error("invalid_document_chunk_range");
|
|
22350
|
+
}
|
|
22351
|
+
chunks.push(part);
|
|
22352
|
+
offset += part.length;
|
|
22353
|
+
}
|
|
22354
|
+
bytes = Buffer.concat(chunks);
|
|
22355
|
+
} else {
|
|
22356
|
+
// Rolling-upgrade compatibility for inline receipts from an older Server.
|
|
22357
|
+
if (typeof doc.markdown !== "string") throw new Error("missing_document_content");
|
|
22358
|
+
bytes = Buffer.from(doc.markdown, "utf8");
|
|
22359
|
+
}
|
|
22360
|
+
if (bytes.length !== doc.byteSize || createHash("sha256").update(bytes).digest("hex") !== doc.sha256) {
|
|
22361
|
+
throw new Error("invalid_document_snapshot");
|
|
22362
|
+
}
|
|
22363
|
+
temp = parentPath + "/.organization-plan-" + randomUUID();
|
|
22364
|
+
file = fs.openSync(temp, "wx", 0o600);
|
|
22365
|
+
fs.writeFileSync(file, bytes);
|
|
22366
|
+
fs.fsyncSync(file);
|
|
22367
|
+
// link is atomic and refuses replacement, including a raced-in symlink.
|
|
22368
|
+
for (let attempt = 0; ; attempt++) {
|
|
22369
|
+
try { fs.linkSync(temp, target); break; }
|
|
22370
|
+
catch (error) {
|
|
22371
|
+
if (error.code !== "EEXIST" || attempt >= 31) throw error;
|
|
22372
|
+
if (selectTarget()) { replayed = true; break; }
|
|
22373
|
+
}
|
|
22374
|
+
}
|
|
22375
|
+
}
|
|
22376
|
+
doc.path = "deliverables/" + targetName;
|
|
22377
|
+
result.initializationDocumentMaterialization = {
|
|
22378
|
+
status: "materialized", path: doc.path, sha256: doc.sha256, byteSize: doc.byteSize,
|
|
22379
|
+
planId: result.planId, revision: result.revision, replayed, uploaded: false,
|
|
22380
|
+
};
|
|
22381
|
+
} catch {
|
|
22382
|
+
// Preserve the authoritative successful plan receipt; local failure is separate.
|
|
22383
|
+
result.initializationDocumentMaterialization = { status: "failed", uploaded: false,
|
|
22384
|
+
reason: "Runner document recovery could not complete within safe limits; retry through the governed runtime recovery path before publishing." };
|
|
22385
|
+
} finally {
|
|
22386
|
+
if (file !== undefined) fs.closeSync(file);
|
|
22387
|
+
if (temp) { try { fs.unlinkSync(temp); } catch {} }
|
|
22388
|
+
if (parent !== undefined) fs.closeSync(parent);
|
|
22389
|
+
if (root !== undefined) fs.closeSync(root);
|
|
22390
|
+
}
|
|
22391
|
+
// Only an explicitly negotiated planning call starts effects. Status/document reads stay reads.
|
|
22392
|
+
const provider = envelope.providerReceipt;
|
|
22393
|
+
if (completionAuthority && event.toolName === "runtime_action_plan"
|
|
22394
|
+
&& result.initializationDocumentMaterialization?.status === "materialized"
|
|
22395
|
+
&& provider?.provider === "amaster_actions" && provider.invocationId === envelope.invocationId
|
|
22396
|
+
&& provider.planId === result.planId
|
|
22397
|
+
&& ["runId", "commandId", "issueId"].every((key) => completionAuthority[key] && provider[key] === completionAuthority[key])) {
|
|
22398
|
+
result.initializationCompletion = await runInitializationCompletion({ plan: result, authority: completionAuthority,
|
|
22399
|
+
call: initializationCompletionCall, sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)), now: Date.now,
|
|
22400
|
+
// Pi redirects extension stdout.write to stderr. This is an explicit
|
|
22401
|
+
// daemon JSON protocol event, so use fd 1 rather than extension logging.
|
|
22402
|
+
onReceipt: (receipt) => fs.writeSync(1, JSON.stringify({ type: "mirrorx_initialization_action_receipt", receipt }) + "\\n"),
|
|
22403
|
+
});
|
|
22404
|
+
if (result.initializationCompletion.status === "completed") result.initializationDocumentMaterialization.uploaded = true;
|
|
22405
|
+
}
|
|
22406
|
+
// A completed issue is not a mustEndRun handoff. Let Pi emit its ordinary
|
|
22407
|
+
// final summary; stopAfterTurn here is classified as exhausted tool work.
|
|
22408
|
+
return { content: [{ type: "text", text: JSON.stringify(envelope) }] };
|
|
22409
|
+
});
|
|
22410
|
+
}
|
|
22411
|
+
`;
|
|
22412
|
+
}
|
|
22413
|
+
|
|
22069
22414
|
// src/amaster-runtime-daemon/pi-managed-mcp-profile.mjs
|
|
22070
22415
|
import { createHash as createHash8 } from "node:crypto";
|
|
22071
22416
|
import {
|
|
@@ -23514,10 +23859,12 @@ function createManagedPiMcpProfileApi(options = {}) {
|
|
|
23514
23859
|
const fullWikiCount = fullWikiReadCount + (hasWikiWrite ? 1 : 0);
|
|
23515
23860
|
const fullConnectorCount = countIn(FULL_DIRECT_TYPED_V1_CONNECTOR_TOOL_NAMES);
|
|
23516
23861
|
const fullCatalog = mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE && tools.length === FULL_DIRECT_TYPED_V1_BASE_TOOL_NAMES.size + fullWikiCount + fullConnectorCount && covers(FULL_DIRECT_TYPED_V1_BASE_TOOL_NAMES) && (fullWikiReadCount === 0 && !hasWikiWrite || fullWikiReadCount === FULL_DIRECT_TYPED_V1_WIKI_READ_TOOL_NAMES.size) && (fullConnectorCount === 0 || fullConnectorCount === FULL_DIRECT_TYPED_V1_CONNECTOR_TOOL_NAMES.size) && tools.every((tool) => FULL_DIRECT_TYPED_V1_TOOL_NAMES.has(tool.name));
|
|
23517
|
-
|
|
23862
|
+
const initializationNames = new Set([...FULL_DIRECT_TYPED_V1_BASE_TOOL_NAMES].filter((name) => name !== "runtime_action.list" && name !== "mirrorx.list_issues"));
|
|
23863
|
+
const initializationCatalog = tools.length === initializationNames.size + fullWikiReadCount && covers(initializationNames) && !hasWikiWrite && fullConnectorCount === 0 && (fullWikiReadCount === 0 || fullWikiReadCount === FULL_DIRECT_TYPED_V1_WIKI_READ_TOOL_NAMES.size);
|
|
23864
|
+
if (mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE && !fullCatalog && !initializationCatalog) {
|
|
23518
23865
|
throw new Error("pi_managed_mcp_invalid: direct tool catalog size mismatch");
|
|
23519
23866
|
}
|
|
23520
|
-
const catalogKind = "full";
|
|
23867
|
+
const catalogKind = initializationCatalog ? "initialization" : "full";
|
|
23521
23868
|
const admittedToolNames = FULL_DIRECT_TYPED_V1_TOOL_NAMES;
|
|
23522
23869
|
const names = /* @__PURE__ */ new Set();
|
|
23523
23870
|
const exposedNames = /* @__PURE__ */ new Set();
|
|
@@ -24650,6 +24997,14 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
|
|
|
24650
24997
|
managedPiRunTerminationExtensionSource()
|
|
24651
24998
|
);
|
|
24652
24999
|
}
|
|
25000
|
+
if (directCatalog?.tools.some((tool) => tool.name === "runtime_action.plan")) {
|
|
25001
|
+
const automaticCompletion = directCatalog.tools.find((tool) => tool.name === "runtime_action.plan")?.inputSchema?.$comment === "mirrorx.initialization-completion.v1";
|
|
25002
|
+
writeProfileExtension("amaster-initialization-document.js", managedPiInitializationDocumentExtensionSource(
|
|
25003
|
+
cwd,
|
|
25004
|
+
`${cwd}/.pi/mcp.json`,
|
|
25005
|
+
automaticCompletion ? authority : null
|
|
25006
|
+
));
|
|
25007
|
+
}
|
|
24653
25008
|
const adapterVersion = piMcpAdapterVersion(sharedRuntime.home);
|
|
24654
25009
|
if (directCatalog) assertPiMcpAdapterDirectCatalogSupport(adapterVersion);
|
|
24655
25010
|
const {
|
|
@@ -28223,7 +28578,7 @@ function maybeCapturePiMessage(event, messages, usage) {
|
|
|
28223
28578
|
}
|
|
28224
28579
|
return capturedAssistantOutput;
|
|
28225
28580
|
}
|
|
28226
|
-
function piMcpToolResults(event) {
|
|
28581
|
+
function piMcpToolResults(event, expectedAuthority = null) {
|
|
28227
28582
|
const results = [];
|
|
28228
28583
|
const seen = /* @__PURE__ */ new Set();
|
|
28229
28584
|
const retain = (parsed) => {
|
|
@@ -28278,6 +28633,14 @@ function piMcpToolResults(event) {
|
|
|
28278
28633
|
if (readString(event?.type) === "tool_execution_end") {
|
|
28279
28634
|
retainMcpResult(event?.result);
|
|
28280
28635
|
}
|
|
28636
|
+
if (readString(event?.type) === "mirrorx_initialization_action_receipt" && expectedAuthority) {
|
|
28637
|
+
const receipt = asRecord(event.receipt);
|
|
28638
|
+
const provider = asRecord(receipt.providerReceipt);
|
|
28639
|
+
const content = asRecord(receipt.content);
|
|
28640
|
+
if (content.schemaVersion === "runtime-action-v1" && ["runtime_action.submit", "runtime_action.status", "runtime_action.commit"].includes(content.toolName) && ["runId", "commandId", "issueId"].every((key) => readString(expectedAuthority[key]) && provider[key] === expectedAuthority[key])) {
|
|
28641
|
+
retainMcpResult({ details: { server: "amaster" }, content: [{ type: "text", text: JSON.stringify(receipt) }] });
|
|
28642
|
+
}
|
|
28643
|
+
}
|
|
28281
28644
|
return results;
|
|
28282
28645
|
}
|
|
28283
28646
|
function piGovernedMcpUnavailableEvidence(event) {
|
|
@@ -30109,6 +30472,14 @@ function wikiAccessRuleLine(input) {
|
|
|
30109
30472
|
const access = asRecord(input.wikiAccess);
|
|
30110
30473
|
const tools = input.hasGovernedMcp === true && access.tools === true;
|
|
30111
30474
|
const treePath = readString(access.treePath);
|
|
30475
|
+
const catalogTools = asRecord(input.managedMcpToolCatalog).tools;
|
|
30476
|
+
if (input.managedMcpToolMode === "direct_typed" && Array.isArray(catalogTools)) {
|
|
30477
|
+
const wikiNames = tools ? catalogTools.map((tool) => readString(asRecord(tool).exposedName)).filter((name) => ["wiki_list", "wiki_search", "wiki_read", "wiki_write", "wiki_list_versions", "wiki_diff_versions"].includes(name)) : [];
|
|
30478
|
+
if (wikiNames.length > 0) {
|
|
30479
|
+
return `- Company wiki access in this run: ${wikiNames.join(" / ")} via the amaster MCP${treePath ? `, and the wiki tree at ${treePath}` : ""}. Use targeted reads for relevant evidence; only the listed tools are available.`;
|
|
30480
|
+
}
|
|
30481
|
+
return treePath ? `- Company wiki access in this run: the wiki tree at ${treePath}. Read wiki/index.md then the relevant pages; wiki_* tools are not available.` : "";
|
|
30482
|
+
}
|
|
30112
30483
|
if (tools && treePath) {
|
|
30113
30484
|
return `- Company wiki access in this run: the six tools wiki_list / wiki_search / wiki_read / wiki_write / wiki_list_versions / wiki_diff_versions via the amaster MCP, and the wiki tree at ${treePath} (read wiki/index.md there first).`;
|
|
30114
30485
|
}
|
|
@@ -31341,7 +31712,17 @@ ${resolvedDependencies.details.content}` : resolvedDependencies.details.content
|
|
|
31341
31712
|
const taskContextAuthority = taskContextAuthoritySection(context);
|
|
31342
31713
|
const continuationPostconditionGap = continuationPostconditionGapSection(context, input);
|
|
31343
31714
|
const companyInitializationAuthority = companyInitializationAuthoritySection(context);
|
|
31344
|
-
const
|
|
31715
|
+
const rawManagedTools = asRecord(input.managedMcpToolCatalog).tools;
|
|
31716
|
+
const managedTools = Array.isArray(rawManagedTools) ? rawManagedTools : [];
|
|
31717
|
+
const planTool = managedTools.find((tool) => asRecord(tool).name === "runtime_action.plan");
|
|
31718
|
+
const documentSchema = asRecord(asRecord(asRecord(asRecord(planTool).inputSchema).properties).initializationOrganization).properties;
|
|
31719
|
+
const serverDocumentWorkflow = companyInitializationAuthority && asRecord(context.companyInitializationAuthority).organizationMutationAuthorityMode === "initialization_plan" && input.hasGovernedMcp && input.executorKind === "pi" && input.managedMcpToolMode === "direct_typed" && !managedTools.some((tool) => asRecord(tool).name === "runtime_action.list") && asRecord(documentSchema).documentReasoning;
|
|
31720
|
+
const fallbackTemplateCatalog = runtimeTemplateCatalogSection(input);
|
|
31721
|
+
const automaticCompletion = asRecord(asRecord(planTool).inputSchema).$comment === "mirrorx.initialization-completion.v1";
|
|
31722
|
+
const runtimeTemplateCatalog = serverDocumentWorkflow ? {
|
|
31723
|
+
sourceRef: "company_initialization_server_document_renderer",
|
|
31724
|
+
content: (automaticCompletion ? "Submit your final company-specific organization decisions once through initializationOrganization with documentReasoning. This negotiated plan call requests automatic completion: Server renders the seven-section document; Runner materializes, uploads through Artifact Saga, waits for verified delivery, commits the exact plan and requests Server-validated ready completion. Do not queue upload/status/commit/done or filesystem template searches alongside the plan. The automatic sequence preserves all Server authorization, version, artifact and ready gates. A completed initializationCompletion receipt ends this run. An incomplete receipt identifies the exact stage and durable IDs for existing recovery; revise business decisions only when the error requires it. Explicit actions, omitted documentReasoning or missing initializationDocument retain the original document/upload/commit workflow." : "The initialization Organization Plan uses the Server-owned seven-section renderer. This satisfies the pre-draft template selection step for this artifact; do not search or copy filesystem templates. Submit company-specific decisions once through initializationOrganization.documentReasoning. The Runner verifies and materializes returned document bytes; a materialized receipt requires no extra file/hash inspection. Use the exact returned path in upload_artifact, then follow Artifact Saga, commit and the Server ready gates. If using explicit actions, omitting documentReasoning, or receiving no initializationDocument, use the original document workflow and configured template catalog; never claim materialization without its successful receipt.") + (fallbackTemplateCatalog ? ` Fallback-only exact catalog path: ${asRecord(input.runtimeTemplateCatalog).targetDir}` : "")
|
|
31725
|
+
} : fallbackTemplateCatalog;
|
|
31345
31726
|
const rawSections = [
|
|
31346
31727
|
{ name: "recovery_instruction", title: "Recovery Instruction", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: completeRecoveryInstruction, truncationReason: completeRecoveryInstruction ? null : "mode_selection" },
|
|
31347
31728
|
{ name: "approval_continuation", title: "Approved Runtime Action Continuation", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: approvalContinuationText(input), truncationReason: mode === "continuation" ? null : "mode_selection" },
|
|
@@ -31878,9 +32259,15 @@ var BUILD_SUPPORTED_CAPABILITIES = Object.freeze([
|
|
|
31878
32259
|
"run_terminate",
|
|
31879
32260
|
"logs_cost_workspace_status",
|
|
31880
32261
|
"browser_credential_ref_fill_v1",
|
|
31881
|
-
"execution_lanes_v1"
|
|
32262
|
+
"execution_lanes_v1",
|
|
32263
|
+
"mirrorx_initialization_context_v1",
|
|
32264
|
+
"mirrorx_initialization_completion_v1"
|
|
31882
32265
|
]);
|
|
31883
32266
|
var DYNAMIC_READINESS = Object.freeze({
|
|
32267
|
+
mirrorx_initialization_completion_v1: {
|
|
32268
|
+
reasonCode: "managed_linux_pi_required",
|
|
32269
|
+
ready: (input) => process.platform === "linux" && input.runnerKind === "cloud_managed" && input.executors.some((executor) => executor.kind === "pi")
|
|
32270
|
+
},
|
|
31884
32271
|
artifact_template_catalog_v1: {
|
|
31885
32272
|
reasonCode: "artifact_template_catalog_not_ready",
|
|
31886
32273
|
ready: (input) => {
|
|
@@ -34017,7 +34404,7 @@ function assertRequiredTaskAttachmentMaterialized(input, materialized) {
|
|
|
34017
34404
|
}
|
|
34018
34405
|
|
|
34019
34406
|
// src/amaster-runtime-daemon.mjs
|
|
34020
|
-
var CONNECTOR_VERSION = "0.1.1-beta.
|
|
34407
|
+
var CONNECTOR_VERSION = "0.1.1-beta.267";
|
|
34021
34408
|
var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
|
|
34022
34409
|
var daemonRequire = createRequire2(import.meta.url);
|
|
34023
34410
|
var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
|
|
@@ -36392,7 +36779,7 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
|
|
|
36392
36779
|
}
|
|
36393
36780
|
}
|
|
36394
36781
|
if (MIRRORX_FORMAL_TASK_EXECUTOR_KINDS.includes(executorKind) && event) {
|
|
36395
|
-
const results = executorKind === "codex" ? codexMcpToolResults(event) : executorKind === "codebuddy" ? codebuddyMcpToolResults(event) : piMcpToolResults(event);
|
|
36782
|
+
const results = executorKind === "codex" ? codexMcpToolResults(event) : executorKind === "codebuddy" ? codebuddyMcpToolResults(event) : piMcpToolResults(event, { runId: commandRunId(command), commandId: command.commandId, issueId: commandIssueId(command) });
|
|
36396
36783
|
liveMcpToolResults.push(...results);
|
|
36397
36784
|
if (results.length > 0) onMcpToolResults?.(results);
|
|
36398
36785
|
}
|
package/dist/amaster-runtime.mjs
CHANGED
|
@@ -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.
|
|
10
|
+
const CONNECTOR_VERSION = "0.1.1-beta.267";
|
|
11
11
|
|
|
12
12
|
const CONFIG_KEY_MAP = new Map([
|
|
13
13
|
["server_url", "AMASTER_EMPLOYEE_SERVER_URL"],
|