@amaster.ai/employee-runtime-connector 0.1.1-beta.265 → 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.
- package/dist/amaster-runtime-daemon/capability-registry.mjs +7 -0
- package/dist/amaster-runtime-daemon.mjs +398 -11
- package/dist/amaster-runtime.mjs +1 -1
- package/dist/templates/.mirrorx-preset-templates.json +2 -2
- package/dist/templates//345/206/205/345/256/271/345/217/221/345/270/203/344/272/244/346/216/245/345/215/225/346/250/241/346/235/277.md +3 -0
- package/package.json +1 -1
|
@@ -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"],
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"name": "内容发布交接单模板.md",
|
|
46
|
-
"bytes":
|
|
47
|
-
"sha256": "
|
|
46
|
+
"bytes": 12591,
|
|
47
|
+
"sha256": "35b43e739c88188f0e660f8a15acbb429faa984fadf2c56ba4c2c59957abca3a"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"name": "内容计划与排期模板.md",
|
|
@@ -41,6 +41,9 @@
|
|
|
41
41
|
|
|
42
42
|
- 当前进度以相关任务及最新证据为准;Wiki 保存确认内容、截至某时的历史发布记录与有来源的复盘,不充当发布队列或新授权。
|
|
43
43
|
- 使用当前已提供且获授权的 Wiki 操作,普通用户只需打开已返回的成果链接,不要求进入开发模式。没有可用能力时保留任务成果,明确归档未安排/失败及负责处理方。
|
|
44
|
+
- 普通运营任务先用 Wiki 读取工具在当前公司默认共享空间查重;不要调用未开放的 `wiki_write`,也不要猜测或索取 operationId。需要归档时先保存一份独立归档文档,包含已确认发布包的准确版本、稳定成果引用、来源任务和确认回执,以及未发布/待审核限制;不修改已确认的清单或媒体。
|
|
45
|
+
- 使用 `runtime_action.describe(upsert_external_wait)` 获取当前合同,通过 `upsert_external_wait` 提交 `reasonCode=wiki_operation_context_missing`、`ownerType=user`、`actionKind=approval` 和 `wikiPublicationSelection`:绑定归档文档的 `documentKey/expectedRevisionId` 及 `destination` 的默认 Wiki、共享空间和稳定 `wiki/...md` 路径;已有页面更新须提供刚读取的准确 `expectedPageHash`,新页面不覆盖现有内容。这是任务页的受控归档入口,不是外部平台发文。
|
|
46
|
+
- 绑定完成后结束本轮,说明用户可在任务页查看准确文档版本并点击“归档到 Wiki”。收到服务端真实成功回执后再读取页面、核对来源与版本、将链接记入独立交接记录;失败、版本变化或成功未关联时保留明确待处理状态,不冒充已归档,不重复提交确认或生成媒体。没有准确归档文档或目标权限时先报告缺口。
|
|
44
47
|
- 核对目标 Company/空间、来源和读者权限;明确 Wiki 是原验收必交时取得成功页面与版本后才能完成,否则不擅自追加归档门禁。
|
|
45
48
|
- 原始图片/视频留在成果/附件中,Wiki 保存内容说明与稳定来源引用,不假定任务摄取会复制视频或 Office 原件,不持久化临时签名地址。
|
|
46
49
|
- 同一来源版本复用现有归档;重试归档不重复生成或再次发布。新任务复用旧内容时重新核对产品事实和有效期。
|