@useorgx/openclaw-plugin 0.4.9 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/dashboard/dist/assets/BJgZIVUQ.js +53 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
- package/dashboard/dist/assets/BXWDRGm-.js +1 -0
- package/dashboard/dist/assets/BXWDRGm-.js.br +0 -0
- package/dashboard/dist/assets/BXWDRGm-.js.gz +0 -0
- package/dashboard/dist/assets/BgOYB78t.js +4 -0
- package/dashboard/dist/assets/BgOYB78t.js.br +0 -0
- package/dashboard/dist/assets/BgOYB78t.js.gz +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
- package/dashboard/dist/assets/CE38zU4U.js +1 -0
- package/dashboard/dist/assets/CE38zU4U.js.br +0 -0
- package/dashboard/dist/assets/CE38zU4U.js.gz +0 -0
- package/dashboard/dist/assets/CFGKRAzG.js +1 -0
- package/dashboard/dist/assets/CFGKRAzG.js.br +0 -0
- package/dashboard/dist/assets/CFGKRAzG.js.gz +0 -0
- package/dashboard/dist/assets/CGGR2GZh.js +1 -0
- package/dashboard/dist/assets/CGGR2GZh.js.br +0 -0
- package/dashboard/dist/assets/CGGR2GZh.js.gz +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js +1 -0
- package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
- package/dashboard/dist/assets/CPFiTmlw.js +8 -0
- package/dashboard/dist/assets/CPFiTmlw.js.br +0 -0
- package/dashboard/dist/assets/CPFiTmlw.js.gz +0 -0
- package/dashboard/dist/assets/CZZTvkQZ.js +1 -0
- package/dashboard/dist/assets/CZZTvkQZ.js.br +0 -0
- package/dashboard/dist/assets/CZZTvkQZ.js.gz +0 -0
- package/dashboard/dist/assets/{CpJsfbXo.js → CxQ08qFN.js} +2 -2
- package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
- package/dashboard/dist/assets/D-bf6hEI.js +213 -0
- package/dashboard/dist/assets/D-bf6hEI.js.br +0 -0
- package/dashboard/dist/assets/D-bf6hEI.js.gz +0 -0
- package/dashboard/dist/assets/DG6y9wJI.js +2 -0
- package/dashboard/dist/assets/DG6y9wJI.js.br +0 -0
- package/dashboard/dist/assets/DG6y9wJI.js.gz +0 -0
- package/dashboard/dist/assets/DNxKz-GV.js +1 -0
- package/dashboard/dist/assets/DNxKz-GV.js.br +0 -0
- package/dashboard/dist/assets/DNxKz-GV.js.gz +0 -0
- package/dashboard/dist/assets/DW_rKUic.js +11 -0
- package/dashboard/dist/assets/DW_rKUic.js.br +0 -0
- package/dashboard/dist/assets/DW_rKUic.js.gz +0 -0
- package/dashboard/dist/assets/DbNoijHm.js +1 -0
- package/dashboard/dist/assets/DbNoijHm.js.br +0 -0
- package/dashboard/dist/assets/DbNoijHm.js.gz +0 -0
- package/dashboard/dist/assets/DjcdE6jC.js +2 -0
- package/dashboard/dist/assets/DjcdE6jC.js.br +0 -0
- package/dashboard/dist/assets/DjcdE6jC.js.gz +0 -0
- package/dashboard/dist/assets/FZYuCDnt.js +1 -0
- package/dashboard/dist/assets/FZYuCDnt.js.br +0 -0
- package/dashboard/dist/assets/FZYuCDnt.js.gz +0 -0
- package/dashboard/dist/assets/PAUiij_z.js +1 -0
- package/dashboard/dist/assets/PAUiij_z.js.br +0 -0
- package/dashboard/dist/assets/PAUiij_z.js.gz +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js +8 -0
- package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
- package/dashboard/dist/assets/h5biQs2I.css +1 -0
- package/dashboard/dist/assets/h5biQs2I.css.br +0 -0
- package/dashboard/dist/assets/h5biQs2I.css.gz +0 -0
- package/dashboard/dist/assets/ic2FaMnh.js +1 -0
- package/dashboard/dist/assets/ic2FaMnh.js.br +0 -0
- package/dashboard/dist/assets/ic2FaMnh.js.gz +0 -0
- package/dashboard/dist/assets/nByHNHoW.js +1 -0
- package/dashboard/dist/assets/nByHNHoW.js.br +0 -0
- package/dashboard/dist/assets/nByHNHoW.js.gz +0 -0
- package/dashboard/dist/assets/qm8xLgv-.css +1 -0
- package/dashboard/dist/assets/qm8xLgv-.css.br +0 -0
- package/dashboard/dist/assets/qm8xLgv-.css.gz +0 -0
- package/dashboard/dist/assets/tS9mbYZi.js +1 -0
- package/dashboard/dist/assets/tS9mbYZi.js.br +0 -0
- package/dashboard/dist/assets/tS9mbYZi.js.gz +0 -0
- package/dashboard/dist/brand/anthropic-mark.svg.br +0 -0
- package/dashboard/dist/brand/anthropic-mark.svg.gz +0 -0
- package/dashboard/dist/brand/openai-mark.svg.br +0 -0
- package/dashboard/dist/brand/openai-mark.svg.gz +0 -0
- package/dashboard/dist/brand/openclaw-mark.svg.br +0 -0
- package/dashboard/dist/brand/openclaw-mark.svg.gz +0 -0
- package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
- package/dashboard/dist/index.html +7 -5
- package/dashboard/dist/index.html.br +0 -0
- package/dashboard/dist/index.html.gz +0 -0
- package/dist/activity-actor-fields.js +26 -4
- package/dist/activity-store.js +34 -8
- package/dist/agent-context-store.js +79 -17
- package/dist/agent-run-store.js +44 -3
- package/dist/agent-suite.d.ts +9 -0
- package/dist/agent-suite.js +149 -9
- package/dist/artifacts/artifact-domain-schemas.d.ts +66 -0
- package/dist/artifacts/artifact-domain-schemas.js +357 -0
- package/dist/artifacts/register-artifact.d.ts +4 -3
- package/dist/artifacts/register-artifact.js +170 -57
- package/dist/chat-store.d.ts +157 -0
- package/dist/chat-store.js +586 -0
- package/dist/cli/orgx.js +11 -0
- package/dist/contracts/client.d.ts +43 -3
- package/dist/contracts/client.js +159 -30
- package/dist/contracts/retro-schema.d.ts +81 -0
- package/dist/contracts/retro-schema.js +80 -0
- package/dist/contracts/shared-types.d.ts +159 -0
- package/dist/contracts/shared-types.js +177 -1
- package/dist/contracts/skill-pack-schema.d.ts +192 -0
- package/dist/contracts/skill-pack-schema.js +180 -0
- package/dist/contracts/types.d.ts +227 -2
- package/dist/entities/auto-assignment.js +43 -17
- package/dist/event-sanitization.d.ts +11 -0
- package/dist/event-sanitization.js +113 -0
- package/dist/fs-utils.js +13 -1
- package/dist/gateway-watchdog.d.ts +5 -0
- package/dist/gateway-watchdog.js +50 -0
- package/dist/hooks/post-reporting-event.mjs +1 -5
- package/dist/http/helpers/activity-headline.js +13 -132
- package/dist/http/helpers/auto-continue-engine.d.ts +198 -10
- package/dist/http/helpers/auto-continue-engine.js +2531 -186
- package/dist/http/helpers/autopilot-operations.d.ts +19 -0
- package/dist/http/helpers/autopilot-operations.js +182 -31
- package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
- package/dist/http/helpers/autopilot-runtime.js +308 -20
- package/dist/http/helpers/autopilot-slice-utils.d.ts +18 -0
- package/dist/http/helpers/autopilot-slice-utils.js +516 -93
- package/dist/http/helpers/decision-mapper.d.ts +40 -0
- package/dist/http/helpers/decision-mapper.js +223 -7
- package/dist/http/helpers/dispatch-lifecycle.d.ts +19 -2
- package/dist/http/helpers/dispatch-lifecycle.js +242 -37
- package/dist/http/helpers/kickoff-context.js +74 -0
- package/dist/http/helpers/llm-client.d.ts +47 -0
- package/dist/http/helpers/llm-client.js +256 -0
- package/dist/http/helpers/mission-control.d.ts +102 -3
- package/dist/http/helpers/mission-control.js +498 -9
- package/dist/http/helpers/sentinel-catalog.d.ts +23 -0
- package/dist/http/helpers/sentinel-catalog.js +193 -0
- package/dist/http/helpers/session-classification.d.ts +9 -0
- package/dist/http/helpers/session-classification.js +564 -0
- package/dist/http/helpers/slice-experience-v2.d.ts +137 -0
- package/dist/http/helpers/slice-experience-v2.js +677 -0
- package/dist/http/helpers/slice-run-projections.d.ts +72 -0
- package/dist/http/helpers/slice-run-projections.js +860 -0
- package/dist/http/helpers/triage-mapper.d.ts +43 -0
- package/dist/http/helpers/triage-mapper.js +549 -0
- package/dist/http/helpers/value-utils.js +7 -2
- package/dist/http/helpers/workspace-scope.d.ts +15 -0
- package/dist/http/helpers/workspace-scope.js +170 -0
- package/dist/http/index.js +1354 -97
- package/dist/http/routes/agent-suite.d.ts +9 -0
- package/dist/http/routes/agent-suite.js +207 -8
- package/dist/http/routes/agents-catalog.js +64 -19
- package/dist/http/routes/chat.d.ts +19 -0
- package/dist/http/routes/chat.js +522 -0
- package/dist/http/routes/decision-actions.d.ts +8 -1
- package/dist/http/routes/decision-actions.js +42 -5
- package/dist/http/routes/dispatch-gateway-envelope.d.ts +25 -0
- package/dist/http/routes/dispatch-gateway-envelope.js +26 -0
- package/dist/http/routes/entities.d.ts +16 -0
- package/dist/http/routes/entities.js +294 -6
- package/dist/http/routes/live-legacy.d.ts +5 -0
- package/dist/http/routes/live-legacy.js +23 -509
- package/dist/http/routes/live-misc.d.ts +12 -0
- package/dist/http/routes/live-misc.js +251 -31
- package/dist/http/routes/live-snapshot.d.ts +48 -2
- package/dist/http/routes/live-snapshot.js +638 -19
- package/dist/http/routes/live-terminal.d.ts +11 -0
- package/dist/http/routes/live-terminal.js +261 -0
- package/dist/http/routes/live-triage.d.ts +61 -0
- package/dist/http/routes/live-triage.js +248 -0
- package/dist/http/routes/mission-control-actions.d.ts +49 -1
- package/dist/http/routes/mission-control-actions.js +1334 -84
- package/dist/http/routes/mission-control-read.d.ts +48 -3
- package/dist/http/routes/mission-control-read.js +1593 -20
- package/dist/http/routes/realtime-orchestrator.d.ts +10 -0
- package/dist/http/routes/realtime-orchestrator.js +74 -0
- package/dist/http/routes/run-control.d.ts +5 -2
- package/dist/http/routes/run-control.js +10 -0
- package/dist/http/routes/sentinels-catalog.d.ts +7 -0
- package/dist/http/routes/sentinels-catalog.js +24 -0
- package/dist/http/routes/summary.js +10 -3
- package/dist/http/routes/usage.d.ts +24 -0
- package/dist/http/routes/usage.js +362 -0
- package/dist/http/routes/work-artifacts.js +28 -9
- package/dist/index.js +165 -27
- package/dist/local-openclaw.js +29 -6
- package/dist/mcp-client-setup.js +3 -3
- package/dist/mcp-http-handler.js +33 -59
- package/dist/next-up-queue-store.d.ts +16 -1
- package/dist/next-up-queue-store.js +89 -7
- package/dist/outbox.d.ts +5 -0
- package/dist/outbox.js +113 -9
- package/dist/paths.js +24 -5
- package/dist/reporting/rollups.d.ts +53 -0
- package/dist/reporting/rollups.js +148 -0
- package/dist/retro/domain-templates.d.ts +45 -0
- package/dist/retro/domain-templates.js +297 -0
- package/dist/retro/quality-rubric.d.ts +33 -0
- package/dist/retro/quality-rubric.js +213 -0
- package/dist/runtime-cleanup.d.ts +18 -0
- package/dist/runtime-cleanup.js +87 -0
- package/dist/services/background.d.ts +11 -0
- package/dist/services/background.js +22 -0
- package/dist/services/experiment-randomization.d.ts +21 -0
- package/dist/services/experiment-randomization.js +63 -0
- package/dist/skill-pack-state.d.ts +36 -5
- package/dist/skill-pack-state.js +273 -29
- package/dist/sync/local-agent-telemetry.d.ts +13 -0
- package/dist/sync/local-agent-telemetry.js +128 -0
- package/dist/sync/outbox-replay.js +131 -24
- package/dist/team-context-store.d.ts +23 -0
- package/dist/team-context-store.js +116 -0
- package/dist/telemetry/posthog.js +4 -2
- package/dist/tools/core-tools.d.ts +10 -14
- package/dist/tools/core-tools.js +1289 -24
- package/dist/types.d.ts +2 -0
- package/dist/types.js +2 -0
- package/dist/worker-supervisor.js +23 -0
- package/package.json +14 -4
- package/dashboard/dist/assets/B3ziCA02.js +0 -8
- package/dashboard/dist/assets/B5NEElEI.css +0 -1
- package/dashboard/dist/assets/BhapSNAs.js +0 -215
- package/dashboard/dist/assets/iFdvE7lx.js +0 -1
- package/dashboard/dist/assets/jRJsmpYM.js +0 -1
- package/dashboard/dist/assets/sAhvFnpk.js +0 -4
package/dist/tools/core-tools.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { randomUUID as randomUuidFn } from "node:crypto";
|
|
2
2
|
import { registerArtifact } from "../artifacts/register-artifact.js";
|
|
3
|
+
import { validateOpenClawSkillPackManifest } from "../contracts/skill-pack-schema.js";
|
|
4
|
+
import { listBuiltInSentinels } from "../http/helpers/sentinel-catalog.js";
|
|
3
5
|
import { appendToOutbox } from "../outbox.js";
|
|
4
6
|
export function registerCoreTools(deps) {
|
|
5
|
-
const { registerTool, client, config, getCachedSnapshot, getLastSnapshotAt, doSync, text, json, formatSnapshot, autoAssignEntityForCreate, toReportingPhase, inferReportingInitiativeId, isUuid, pickNonEmptyString, resolveReportingContext, readSkillPackState, } = deps;
|
|
7
|
+
const { registerTool, client, config, getCachedSnapshot, getLastSnapshotAt, doSync, text, json, formatSnapshot, autoAssignEntityForCreate, toReportingPhase, inferReportingInitiativeId, isUuid, pickNonEmptyString, resolveReportingContext, readSkillPackState, updateSkillPackPolicy, rollbackSkillPackPolicy, } = deps;
|
|
6
8
|
const randomUUID = deps.randomUUID ?? randomUuidFn;
|
|
7
9
|
const mcpToolRegistry = new Map();
|
|
8
10
|
const registerMcpTool = (tool, options) => {
|
|
@@ -31,6 +33,34 @@ export function registerCoreTools(deps) {
|
|
|
31
33
|
},
|
|
32
34
|
}, { optional: true });
|
|
33
35
|
// --- orgx_sync ---
|
|
36
|
+
registerMcpTool({
|
|
37
|
+
name: "orgx_sentinel_catalog",
|
|
38
|
+
description: "List built-in proactive sentinel templates. Supports optional domain filter.",
|
|
39
|
+
parameters: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
domain: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "Optional domain filter (engineering, sales, operations, product).",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
additionalProperties: false,
|
|
48
|
+
},
|
|
49
|
+
async execute(_callId, params = {}) {
|
|
50
|
+
try {
|
|
51
|
+
const sentinels = listBuiltInSentinels({ domain: params.domain });
|
|
52
|
+
return json("Sentinel catalog:", {
|
|
53
|
+
generatedAt: new Date().toISOString(),
|
|
54
|
+
domain: params.domain ?? null,
|
|
55
|
+
count: sentinels.length,
|
|
56
|
+
sentinels,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
return text(`❌ Failed to load sentinel catalog: ${err instanceof Error ? err.message : err}`);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
}, { optional: true });
|
|
34
64
|
registerMcpTool({
|
|
35
65
|
name: "orgx_sync",
|
|
36
66
|
description: "Push/pull memory sync with OrgX. Send local memory/daily log; receive initiatives, tasks, decisions, model routing policy.",
|
|
@@ -45,13 +75,35 @@ export function registerCoreTools(deps) {
|
|
|
45
75
|
type: "string",
|
|
46
76
|
description: "Today's session log to push",
|
|
47
77
|
},
|
|
78
|
+
agents: {
|
|
79
|
+
type: "array",
|
|
80
|
+
description: "Optional local agent states to sync into OrgX",
|
|
81
|
+
items: {
|
|
82
|
+
type: "object",
|
|
83
|
+
properties: {
|
|
84
|
+
id: { type: "string" },
|
|
85
|
+
name: { type: "string" },
|
|
86
|
+
domain: { type: "string" },
|
|
87
|
+
status: {
|
|
88
|
+
type: "string",
|
|
89
|
+
enum: ["active", "idle", "throttled"],
|
|
90
|
+
},
|
|
91
|
+
currentTask: { type: "string" },
|
|
92
|
+
lastActive: { type: "string" },
|
|
93
|
+
},
|
|
94
|
+
required: ["id", "name", "domain", "status"],
|
|
95
|
+
additionalProperties: false,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
48
98
|
},
|
|
99
|
+
additionalProperties: false,
|
|
49
100
|
},
|
|
50
101
|
async execute(_callId, params = {}) {
|
|
51
102
|
try {
|
|
52
103
|
const resp = await client.syncMemory({
|
|
53
104
|
memory: params.memory,
|
|
54
105
|
dailyLog: params.dailyLog,
|
|
106
|
+
agents: params.agents,
|
|
55
107
|
});
|
|
56
108
|
return json("Sync complete:", resp);
|
|
57
109
|
}
|
|
@@ -286,6 +338,235 @@ export function registerCoreTools(deps) {
|
|
|
286
338
|
}
|
|
287
339
|
},
|
|
288
340
|
}, { optional: true });
|
|
341
|
+
// --- orgx_proof_status ---
|
|
342
|
+
registerMcpTool({
|
|
343
|
+
name: "orgx_proof_status",
|
|
344
|
+
description: "Check the proof chain status for a task or run. Returns a checklist of proof levels (L1-L7) with gaps highlighted. Use this to verify work is provably complete before marking done.",
|
|
345
|
+
parameters: {
|
|
346
|
+
type: "object",
|
|
347
|
+
properties: {
|
|
348
|
+
task_id: {
|
|
349
|
+
type: "string",
|
|
350
|
+
description: "ID of the task to check proof for",
|
|
351
|
+
},
|
|
352
|
+
run_id: {
|
|
353
|
+
type: "string",
|
|
354
|
+
description: "ID of the run to check proof for",
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
async execute(_callId, params = {}) {
|
|
359
|
+
const taskId = params.task_id || undefined;
|
|
360
|
+
const runId = params.run_id || undefined;
|
|
361
|
+
if (!taskId && !runId) {
|
|
362
|
+
return text("❌ Provide at least one of task_id or run_id.");
|
|
363
|
+
}
|
|
364
|
+
try {
|
|
365
|
+
const qp = new URLSearchParams();
|
|
366
|
+
if (taskId)
|
|
367
|
+
qp.set("task_id", taskId);
|
|
368
|
+
if (runId)
|
|
369
|
+
qp.set("run_id", runId);
|
|
370
|
+
const result = await client.rawRequest("GET", `/api/flywheel/proof-status?${qp.toString()}`);
|
|
371
|
+
// Format proof chain as readable checklist
|
|
372
|
+
const levels = Array.isArray(result?.levels) ? result.levels : [];
|
|
373
|
+
const overall = result?.overall_passed === true;
|
|
374
|
+
const reasonCodes = Array.isArray(result?.reason_codes) ? result.reason_codes : [];
|
|
375
|
+
if (levels.length === 0) {
|
|
376
|
+
// Server may not have proof-status route yet (phase 1)
|
|
377
|
+
return json("Proof status (local evaluation)", {
|
|
378
|
+
task_id: taskId,
|
|
379
|
+
run_id: runId,
|
|
380
|
+
note: "Proof-status API not available. Register artifacts with atomic_unit_type metadata and use orgx_quality_score to build proof chain.",
|
|
381
|
+
overall_passed: false,
|
|
382
|
+
reason_codes: ["proof_api_not_available"],
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
const lines = [];
|
|
386
|
+
lines.push(overall ? "✅ Proof chain complete" : "⚠️ Proof chain incomplete");
|
|
387
|
+
lines.push("");
|
|
388
|
+
for (const lvl of levels) {
|
|
389
|
+
const icon = lvl.passed ? "✅" : lvl.enforcement === "soft_warn" ? "⚠️" : "❌";
|
|
390
|
+
lines.push(`${icon} ${lvl.label || lvl.level}: ${lvl.passed ? "passed" : "missing"}`);
|
|
391
|
+
if (Array.isArray(lvl.missingFields) && lvl.missingFields.length > 0) {
|
|
392
|
+
lines.push(` Missing: ${lvl.missingFields.join(", ")}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (reasonCodes.length > 0) {
|
|
396
|
+
lines.push("");
|
|
397
|
+
lines.push(`Reason codes: ${reasonCodes.join(", ")}`);
|
|
398
|
+
}
|
|
399
|
+
return json(lines.join("\n"), result);
|
|
400
|
+
}
|
|
401
|
+
catch (err) {
|
|
402
|
+
// Graceful degradation: if proof API is not deployed, return helpful guidance
|
|
403
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
404
|
+
if (msg.includes("404") || msg.includes("not found") || msg.includes("Not Found")) {
|
|
405
|
+
return json("Proof status (server not ready)", {
|
|
406
|
+
task_id: taskId,
|
|
407
|
+
run_id: runId,
|
|
408
|
+
note: "Proof-status API not deployed yet. Ensure artifacts are registered with atomic_unit_type metadata to build the proof chain.",
|
|
409
|
+
overall_passed: false,
|
|
410
|
+
reason_codes: ["proof_api_not_deployed"],
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
return text(`❌ Proof status check failed: ${msg}`);
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
}, { optional: true });
|
|
417
|
+
// --- orgx_verify_completion ---
|
|
418
|
+
registerMcpTool({
|
|
419
|
+
name: "orgx_verify_completion",
|
|
420
|
+
description: "Verify that an entity (task/milestone/workstream) meets completion requirements including proof chain. Returns structured result with any blocking issues.",
|
|
421
|
+
parameters: {
|
|
422
|
+
type: "object",
|
|
423
|
+
properties: {
|
|
424
|
+
entity_type: {
|
|
425
|
+
type: "string",
|
|
426
|
+
description: "Entity type: task, milestone, workstream",
|
|
427
|
+
},
|
|
428
|
+
entity_id: {
|
|
429
|
+
type: "string",
|
|
430
|
+
description: "ID of the entity to verify",
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
required: ["entity_type", "entity_id"],
|
|
434
|
+
},
|
|
435
|
+
async execute(_callId, params = {
|
|
436
|
+
entity_type: "",
|
|
437
|
+
entity_id: "",
|
|
438
|
+
}) {
|
|
439
|
+
try {
|
|
440
|
+
const result = await client.rawRequest("POST", "/api/client/entities/verify-completion", {
|
|
441
|
+
entity_type: params.entity_type,
|
|
442
|
+
entity_id: params.entity_id,
|
|
443
|
+
});
|
|
444
|
+
const ready = result?.ready === true;
|
|
445
|
+
return json(ready
|
|
446
|
+
? `✅ ${params.entity_type} ${params.entity_id} is ready for completion.`
|
|
447
|
+
: `⚠️ ${params.entity_type} ${params.entity_id} has blocking issues.`, result);
|
|
448
|
+
}
|
|
449
|
+
catch (err) {
|
|
450
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
451
|
+
if (msg.includes("404") || msg.includes("not found") || msg.includes("Not Found")) {
|
|
452
|
+
return json("Completion verification (server not ready)", {
|
|
453
|
+
entity_type: params.entity_type,
|
|
454
|
+
entity_id: params.entity_id,
|
|
455
|
+
ready: true,
|
|
456
|
+
note: "Completion verification API not deployed. Proceeding with standard completion.",
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
return text(`❌ Completion verification failed: ${msg}`);
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
}, { optional: true });
|
|
463
|
+
// --- orgx_record_outcome ---
|
|
464
|
+
registerMcpTool({
|
|
465
|
+
name: "orgx_record_outcome",
|
|
466
|
+
description: "Record an outcome event for a completed run, linking execution to business value. Required for L5 (Impact) proof level.",
|
|
467
|
+
parameters: {
|
|
468
|
+
type: "object",
|
|
469
|
+
properties: {
|
|
470
|
+
initiative_id: {
|
|
471
|
+
type: "string",
|
|
472
|
+
description: "Initiative ID this outcome belongs to",
|
|
473
|
+
},
|
|
474
|
+
execution_id: {
|
|
475
|
+
type: "string",
|
|
476
|
+
description: "Execution/run ID that produced this outcome",
|
|
477
|
+
},
|
|
478
|
+
agent_id: {
|
|
479
|
+
type: "string",
|
|
480
|
+
description: "Agent that did the work",
|
|
481
|
+
},
|
|
482
|
+
success: {
|
|
483
|
+
type: "boolean",
|
|
484
|
+
description: "Whether the execution was successful",
|
|
485
|
+
},
|
|
486
|
+
quality_score: {
|
|
487
|
+
type: "number",
|
|
488
|
+
description: "Quality score 1-5",
|
|
489
|
+
},
|
|
490
|
+
domain: {
|
|
491
|
+
type: "string",
|
|
492
|
+
description: "Agent domain",
|
|
493
|
+
},
|
|
494
|
+
metadata: {
|
|
495
|
+
type: "object",
|
|
496
|
+
description: "Additional outcome metadata",
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
required: ["initiative_id", "execution_id", "agent_id", "success"],
|
|
500
|
+
},
|
|
501
|
+
async execute(_callId, params = {
|
|
502
|
+
initiative_id: "",
|
|
503
|
+
execution_id: "",
|
|
504
|
+
agent_id: "",
|
|
505
|
+
success: false,
|
|
506
|
+
}) {
|
|
507
|
+
try {
|
|
508
|
+
const result = await client.recordRunOutcome({
|
|
509
|
+
initiative_id: params.initiative_id,
|
|
510
|
+
execution_id: params.execution_id,
|
|
511
|
+
execution_type: "agent_run",
|
|
512
|
+
agent_id: params.agent_id,
|
|
513
|
+
success: params.success,
|
|
514
|
+
quality_score: params.quality_score,
|
|
515
|
+
domain: params.domain,
|
|
516
|
+
metadata: params.metadata,
|
|
517
|
+
});
|
|
518
|
+
return json(`✅ Outcome recorded for run ${result.run_id} (event: ${result.event_id})`, result);
|
|
519
|
+
}
|
|
520
|
+
catch (err) {
|
|
521
|
+
return text(`❌ Outcome recording failed: ${err instanceof Error ? err.message : err}`);
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
}, { optional: true });
|
|
525
|
+
// --- orgx_get_outcome_attribution ---
|
|
526
|
+
registerMcpTool({
|
|
527
|
+
name: "orgx_get_outcome_attribution",
|
|
528
|
+
description: "Get outcome attribution data for a task or run. Shows what value was attributed to the work and with what confidence. Required for L6 (Economics) proof level.",
|
|
529
|
+
parameters: {
|
|
530
|
+
type: "object",
|
|
531
|
+
properties: {
|
|
532
|
+
task_id: {
|
|
533
|
+
type: "string",
|
|
534
|
+
description: "Task ID to get attribution for",
|
|
535
|
+
},
|
|
536
|
+
run_id: {
|
|
537
|
+
type: "string",
|
|
538
|
+
description: "Run ID to get attribution for",
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
async execute(_callId, params = {}) {
|
|
543
|
+
const taskId = params.task_id || undefined;
|
|
544
|
+
const runId = params.run_id || undefined;
|
|
545
|
+
if (!taskId && !runId) {
|
|
546
|
+
return text("❌ Provide at least one of task_id or run_id.");
|
|
547
|
+
}
|
|
548
|
+
try {
|
|
549
|
+
const qp = new URLSearchParams();
|
|
550
|
+
if (taskId)
|
|
551
|
+
qp.set("task_id", taskId);
|
|
552
|
+
if (runId)
|
|
553
|
+
qp.set("run_id", runId);
|
|
554
|
+
const result = await client.rawRequest("GET", `/api/flywheel/outcome-attribution?${qp.toString()}`);
|
|
555
|
+
return json("Outcome attribution", result);
|
|
556
|
+
}
|
|
557
|
+
catch (err) {
|
|
558
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
559
|
+
if (msg.includes("404") || msg.includes("not found") || msg.includes("Not Found")) {
|
|
560
|
+
return json("Outcome attribution (not available)", {
|
|
561
|
+
task_id: taskId,
|
|
562
|
+
run_id: runId,
|
|
563
|
+
note: "Attribution API not deployed yet.",
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
return text(`❌ Attribution lookup failed: ${msg}`);
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
}, { optional: true });
|
|
289
570
|
// --- orgx_create_entity ---
|
|
290
571
|
registerMcpTool({
|
|
291
572
|
name: "orgx_create_entity",
|
|
@@ -317,9 +598,13 @@ export function registerCoreTools(deps) {
|
|
|
317
598
|
type: "string",
|
|
318
599
|
description: "Parent workstream ID (for tasks)",
|
|
319
600
|
},
|
|
601
|
+
workspace_id: {
|
|
602
|
+
type: "string",
|
|
603
|
+
description: "Workspace ID (canonical; preferred for new callers)",
|
|
604
|
+
},
|
|
320
605
|
command_center_id: {
|
|
321
606
|
type: "string",
|
|
322
|
-
description: "
|
|
607
|
+
description: "Deprecated alias for workspace_id",
|
|
323
608
|
},
|
|
324
609
|
},
|
|
325
610
|
required: ["type", "title"],
|
|
@@ -404,14 +689,537 @@ export function registerCoreTools(deps) {
|
|
|
404
689
|
async execute(_callId, params = {}) {
|
|
405
690
|
try {
|
|
406
691
|
const { type, id, ...updates } = params;
|
|
407
|
-
const
|
|
408
|
-
|
|
692
|
+
const result = await client.updateEntityDetailed(type, id, updates);
|
|
693
|
+
const payload = result.reassignment || result.initiative_reassignment
|
|
694
|
+
? {
|
|
695
|
+
entity: result.entity,
|
|
696
|
+
reassignment: result.reassignment ?? null,
|
|
697
|
+
initiative_reassignment: result.initiative_reassignment ?? null,
|
|
698
|
+
}
|
|
699
|
+
: result.entity;
|
|
700
|
+
return json(`✅ Updated ${type} ${id.slice(0, 8)}`, payload);
|
|
409
701
|
}
|
|
410
702
|
catch (err) {
|
|
411
703
|
return text(`❌ Update failed: ${err instanceof Error ? err.message : err}`);
|
|
412
704
|
}
|
|
413
705
|
},
|
|
414
706
|
}, { optional: true });
|
|
707
|
+
// --- orgx_reassign_stream ---
|
|
708
|
+
registerMcpTool({
|
|
709
|
+
name: "orgx_reassign_stream",
|
|
710
|
+
description: "Reassign a workstream's stream ownership/agents and return reassignment scheduling details.",
|
|
711
|
+
parameters: {
|
|
712
|
+
type: "object",
|
|
713
|
+
properties: {
|
|
714
|
+
workstream_id: {
|
|
715
|
+
type: "string",
|
|
716
|
+
description: "Workstream UUID to reassign",
|
|
717
|
+
minLength: 1,
|
|
718
|
+
},
|
|
719
|
+
initiative_id: {
|
|
720
|
+
type: "string",
|
|
721
|
+
description: "Parent initiative UUID",
|
|
722
|
+
minLength: 1,
|
|
723
|
+
},
|
|
724
|
+
status: {
|
|
725
|
+
type: "string",
|
|
726
|
+
description: "Optional workstream status override (active, in_progress, pending, etc.)",
|
|
727
|
+
minLength: 1,
|
|
728
|
+
},
|
|
729
|
+
domain: {
|
|
730
|
+
type: "string",
|
|
731
|
+
description: "Optional target domain for the reassigned stream",
|
|
732
|
+
minLength: 1,
|
|
733
|
+
},
|
|
734
|
+
role: {
|
|
735
|
+
type: "string",
|
|
736
|
+
description: "Optional role hint for assignment routing",
|
|
737
|
+
minLength: 1,
|
|
738
|
+
},
|
|
739
|
+
assigned_agent_ids: {
|
|
740
|
+
type: "array",
|
|
741
|
+
items: { type: "string", minLength: 1 },
|
|
742
|
+
description: "Optional assigned agent IDs",
|
|
743
|
+
},
|
|
744
|
+
assignedAgentIds: {
|
|
745
|
+
type: "array",
|
|
746
|
+
items: { type: "string", minLength: 1 },
|
|
747
|
+
description: "Alias for assigned_agent_ids",
|
|
748
|
+
},
|
|
749
|
+
assigned_agent_names: {
|
|
750
|
+
type: "array",
|
|
751
|
+
items: { type: "string", minLength: 1 },
|
|
752
|
+
description: "Optional assigned agent display names",
|
|
753
|
+
},
|
|
754
|
+
assignedAgentNames: {
|
|
755
|
+
type: "array",
|
|
756
|
+
items: { type: "string", minLength: 1 },
|
|
757
|
+
description: "Alias for assigned_agent_names",
|
|
758
|
+
},
|
|
759
|
+
assigned_agents: {
|
|
760
|
+
type: "array",
|
|
761
|
+
description: "Optional structured assigned agent list",
|
|
762
|
+
items: {
|
|
763
|
+
type: "object",
|
|
764
|
+
properties: {
|
|
765
|
+
id: { type: "string" },
|
|
766
|
+
name: { type: "string" },
|
|
767
|
+
domain: { type: "string" },
|
|
768
|
+
role: { type: "string" },
|
|
769
|
+
},
|
|
770
|
+
additionalProperties: false,
|
|
771
|
+
},
|
|
772
|
+
},
|
|
773
|
+
},
|
|
774
|
+
required: ["workstream_id", "initiative_id"],
|
|
775
|
+
additionalProperties: false,
|
|
776
|
+
},
|
|
777
|
+
async execute(_callId, params = {}) {
|
|
778
|
+
try {
|
|
779
|
+
const workstreamId = pickNonEmptyString(params.workstream_id);
|
|
780
|
+
const initiativeId = pickNonEmptyString(params.initiative_id);
|
|
781
|
+
if (!workstreamId || !initiativeId) {
|
|
782
|
+
return text("❌ workstream_id and initiative_id are required.");
|
|
783
|
+
}
|
|
784
|
+
if (!isUuid(workstreamId)) {
|
|
785
|
+
return text("❌ workstream_id must be a valid UUID.");
|
|
786
|
+
}
|
|
787
|
+
if (!isUuid(initiativeId)) {
|
|
788
|
+
return text("❌ initiative_id must be a valid UUID.");
|
|
789
|
+
}
|
|
790
|
+
const normalizeOptionalString = (value, field) => {
|
|
791
|
+
if (value === undefined)
|
|
792
|
+
return { ok: true, value: undefined };
|
|
793
|
+
if (typeof value !== "string") {
|
|
794
|
+
return { ok: false, error: `❌ ${field} must be a string when provided.` };
|
|
795
|
+
}
|
|
796
|
+
const trimmed = value.trim();
|
|
797
|
+
return { ok: true, value: trimmed || undefined };
|
|
798
|
+
};
|
|
799
|
+
const normalizeStringArray = (value, field) => {
|
|
800
|
+
if (value === undefined)
|
|
801
|
+
return { ok: true, value: undefined };
|
|
802
|
+
if (!Array.isArray(value)) {
|
|
803
|
+
return { ok: false, error: `❌ ${field} must be an array of strings.` };
|
|
804
|
+
}
|
|
805
|
+
const normalized = [];
|
|
806
|
+
for (const entry of value) {
|
|
807
|
+
if (typeof entry !== "string" || !entry.trim()) {
|
|
808
|
+
return { ok: false, error: `❌ ${field} entries must be non-empty strings.` };
|
|
809
|
+
}
|
|
810
|
+
normalized.push(entry.trim());
|
|
811
|
+
}
|
|
812
|
+
return { ok: true, value: normalized };
|
|
813
|
+
};
|
|
814
|
+
const normalizeAssignedAgents = (value) => {
|
|
815
|
+
if (value === undefined)
|
|
816
|
+
return { ok: true, value: undefined };
|
|
817
|
+
if (!Array.isArray(value)) {
|
|
818
|
+
return { ok: false, error: "❌ assigned_agents must be an array when provided." };
|
|
819
|
+
}
|
|
820
|
+
const normalized = [];
|
|
821
|
+
for (const entry of value) {
|
|
822
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
823
|
+
return {
|
|
824
|
+
ok: false,
|
|
825
|
+
error: "❌ assigned_agents entries must be objects with id, name, domain, or role.",
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
const candidate = entry;
|
|
829
|
+
const normalizedEntry = {};
|
|
830
|
+
for (const key of ["id", "name", "domain", "role"]) {
|
|
831
|
+
if (!(key in candidate) || candidate[key] === undefined || candidate[key] === null)
|
|
832
|
+
continue;
|
|
833
|
+
const valueAtKey = candidate[key];
|
|
834
|
+
if (typeof valueAtKey !== "string" || !valueAtKey.trim()) {
|
|
835
|
+
return {
|
|
836
|
+
ok: false,
|
|
837
|
+
error: `❌ assigned_agents.${key} must be a non-empty string when provided.`,
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
normalizedEntry[key] = valueAtKey.trim();
|
|
841
|
+
}
|
|
842
|
+
if (normalizedEntry.id === undefined &&
|
|
843
|
+
normalizedEntry.name === undefined &&
|
|
844
|
+
normalizedEntry.domain === undefined &&
|
|
845
|
+
normalizedEntry.role === undefined) {
|
|
846
|
+
return {
|
|
847
|
+
ok: false,
|
|
848
|
+
error: "❌ assigned_agents entries must include at least one of id, name, domain, or role.",
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
normalized.push(normalizedEntry);
|
|
852
|
+
}
|
|
853
|
+
return { ok: true, value: normalized };
|
|
854
|
+
};
|
|
855
|
+
const arraysEqual = (left, right) => left.length === right.length && left.every((value, idx) => value === right[idx]);
|
|
856
|
+
const statusInput = normalizeOptionalString(params.status, "status");
|
|
857
|
+
if (!statusInput.ok)
|
|
858
|
+
return text(statusInput.error);
|
|
859
|
+
const domainInput = normalizeOptionalString(params.domain, "domain");
|
|
860
|
+
if (!domainInput.ok)
|
|
861
|
+
return text(domainInput.error);
|
|
862
|
+
const roleInput = normalizeOptionalString(params.role, "role");
|
|
863
|
+
if (!roleInput.ok)
|
|
864
|
+
return text(roleInput.error);
|
|
865
|
+
const assignedAgentIdsSnake = normalizeStringArray(params.assigned_agent_ids, "assigned_agent_ids");
|
|
866
|
+
if (!assignedAgentIdsSnake.ok)
|
|
867
|
+
return text(assignedAgentIdsSnake.error);
|
|
868
|
+
const assignedAgentIdsCamel = normalizeStringArray(params.assignedAgentIds, "assignedAgentIds");
|
|
869
|
+
if (!assignedAgentIdsCamel.ok)
|
|
870
|
+
return text(assignedAgentIdsCamel.error);
|
|
871
|
+
const assignedAgentNamesSnake = normalizeStringArray(params.assigned_agent_names, "assigned_agent_names");
|
|
872
|
+
if (!assignedAgentNamesSnake.ok)
|
|
873
|
+
return text(assignedAgentNamesSnake.error);
|
|
874
|
+
const assignedAgentNamesCamel = normalizeStringArray(params.assignedAgentNames, "assignedAgentNames");
|
|
875
|
+
if (!assignedAgentNamesCamel.ok)
|
|
876
|
+
return text(assignedAgentNamesCamel.error);
|
|
877
|
+
const assignedAgentsInput = normalizeAssignedAgents(params.assigned_agents);
|
|
878
|
+
if (!assignedAgentsInput.ok)
|
|
879
|
+
return text(assignedAgentsInput.error);
|
|
880
|
+
if (assignedAgentIdsSnake.value &&
|
|
881
|
+
assignedAgentIdsCamel.value &&
|
|
882
|
+
!arraysEqual(assignedAgentIdsSnake.value, assignedAgentIdsCamel.value)) {
|
|
883
|
+
return text("❌ assigned_agent_ids and assignedAgentIds must match when both are provided.");
|
|
884
|
+
}
|
|
885
|
+
if (assignedAgentNamesSnake.value &&
|
|
886
|
+
assignedAgentNamesCamel.value &&
|
|
887
|
+
!arraysEqual(assignedAgentNamesSnake.value, assignedAgentNamesCamel.value)) {
|
|
888
|
+
return text("❌ assigned_agent_names and assignedAgentNames must match when both are provided.");
|
|
889
|
+
}
|
|
890
|
+
const normalizedAssignedAgentIds = assignedAgentIdsSnake.value ?? assignedAgentIdsCamel.value;
|
|
891
|
+
const normalizedAssignedAgentNames = assignedAgentNamesSnake.value ?? assignedAgentNamesCamel.value;
|
|
892
|
+
const hasReassignmentMutation = domainInput.value !== undefined ||
|
|
893
|
+
roleInput.value !== undefined ||
|
|
894
|
+
assignedAgentsInput.value !== undefined ||
|
|
895
|
+
normalizedAssignedAgentIds !== undefined ||
|
|
896
|
+
normalizedAssignedAgentNames !== undefined;
|
|
897
|
+
if (!hasReassignmentMutation) {
|
|
898
|
+
return text("❌ Include at least one reassignment field: domain, role, assigned_agents, assigned_agent_ids, or assigned_agent_names.");
|
|
899
|
+
}
|
|
900
|
+
const updates = {
|
|
901
|
+
initiative_id: initiativeId,
|
|
902
|
+
};
|
|
903
|
+
if (statusInput.value !== undefined)
|
|
904
|
+
updates.status = statusInput.value;
|
|
905
|
+
if (domainInput.value !== undefined)
|
|
906
|
+
updates.domain = domainInput.value;
|
|
907
|
+
if (roleInput.value !== undefined)
|
|
908
|
+
updates.role = roleInput.value;
|
|
909
|
+
if (assignedAgentsInput.value !== undefined)
|
|
910
|
+
updates.assigned_agents = assignedAgentsInput.value;
|
|
911
|
+
if (normalizedAssignedAgentIds !== undefined) {
|
|
912
|
+
updates.assigned_agent_ids = normalizedAssignedAgentIds;
|
|
913
|
+
}
|
|
914
|
+
if (normalizedAssignedAgentNames !== undefined) {
|
|
915
|
+
updates.assigned_agent_names = normalizedAssignedAgentNames;
|
|
916
|
+
}
|
|
917
|
+
let beforeDomainFromSnapshot = null;
|
|
918
|
+
if (typeof client.listEntities === "function") {
|
|
919
|
+
try {
|
|
920
|
+
const currentWorkstreams = await client.listEntities("workstream", {
|
|
921
|
+
initiative_id: initiativeId,
|
|
922
|
+
limit: 200,
|
|
923
|
+
});
|
|
924
|
+
const rows = currentWorkstreams &&
|
|
925
|
+
typeof currentWorkstreams === "object" &&
|
|
926
|
+
Array.isArray(currentWorkstreams.data)
|
|
927
|
+
? currentWorkstreams.data
|
|
928
|
+
: [];
|
|
929
|
+
for (const row of rows) {
|
|
930
|
+
if (!row || typeof row !== "object" || Array.isArray(row))
|
|
931
|
+
continue;
|
|
932
|
+
const record = row;
|
|
933
|
+
const id = pickNonEmptyString(record.id);
|
|
934
|
+
if (id !== workstreamId)
|
|
935
|
+
continue;
|
|
936
|
+
beforeDomainFromSnapshot = pickNonEmptyString(record.domain) ?? null;
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
catch {
|
|
941
|
+
// Best effort snapshot for before/after confirmation.
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
const result = await client.updateEntityDetailed("workstream", workstreamId, updates);
|
|
945
|
+
const entityRecord = result.entity && typeof result.entity === "object" && !Array.isArray(result.entity)
|
|
946
|
+
? result.entity
|
|
947
|
+
: null;
|
|
948
|
+
const reassignmentRecord = result.reassignment &&
|
|
949
|
+
typeof result.reassignment === "object" &&
|
|
950
|
+
!Array.isArray(result.reassignment)
|
|
951
|
+
? result.reassignment
|
|
952
|
+
: null;
|
|
953
|
+
const beforeDomain = pickNonEmptyString(beforeDomainFromSnapshot, reassignmentRecord?.before_domain, reassignmentRecord?.previous_domain, reassignmentRecord?.from_domain, entityRecord?.before_domain, entityRecord?.previous_domain, entityRecord?.from_domain) ?? null;
|
|
954
|
+
const afterDomain = pickNonEmptyString(reassignmentRecord?.after_domain, reassignmentRecord?.new_domain, reassignmentRecord?.to_domain, entityRecord?.after_domain, entityRecord?.new_domain, entityRecord?.to_domain, entityRecord?.domain, domainInput.value) ?? null;
|
|
955
|
+
return json(`✅ Reassigned workstream ${workstreamId.slice(0, 8)}`, {
|
|
956
|
+
workstream_id: workstreamId,
|
|
957
|
+
before_domain: beforeDomain,
|
|
958
|
+
after_domain: afterDomain,
|
|
959
|
+
entity: result.entity,
|
|
960
|
+
reassignment: result.reassignment ?? null,
|
|
961
|
+
initiative_reassignment: result.initiative_reassignment ?? null,
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
catch (err) {
|
|
965
|
+
return text(`❌ Stream reassignment failed: ${err instanceof Error ? err.message : err}`);
|
|
966
|
+
}
|
|
967
|
+
},
|
|
968
|
+
}, { optional: true });
|
|
969
|
+
// --- orgx_reassign_streams ---
|
|
970
|
+
registerMcpTool({
|
|
971
|
+
name: "orgx_reassign_streams",
|
|
972
|
+
description: "Convenience batch reassignment tool. Takes initiative_id and a workstream-to-domain mapping, then updates all listed workstreams.",
|
|
973
|
+
parameters: {
|
|
974
|
+
type: "object",
|
|
975
|
+
properties: {
|
|
976
|
+
initiative_id: {
|
|
977
|
+
type: "string",
|
|
978
|
+
description: "Parent initiative UUID for all workstream updates",
|
|
979
|
+
minLength: 1,
|
|
980
|
+
},
|
|
981
|
+
workstream_domains: {
|
|
982
|
+
type: "object",
|
|
983
|
+
description: "Mapping of workstream UUID -> target domain",
|
|
984
|
+
additionalProperties: {
|
|
985
|
+
type: "string",
|
|
986
|
+
minLength: 1,
|
|
987
|
+
},
|
|
988
|
+
},
|
|
989
|
+
mapping: {
|
|
990
|
+
type: "object",
|
|
991
|
+
description: "Alias for workstream_domains: mapping of workstream UUID -> target domain",
|
|
992
|
+
additionalProperties: {
|
|
993
|
+
type: "string",
|
|
994
|
+
minLength: 1,
|
|
995
|
+
},
|
|
996
|
+
},
|
|
997
|
+
mappings: {
|
|
998
|
+
type: "array",
|
|
999
|
+
description: "Optional array mapping for advanced routing fields (workstream_id, domain, role, status).",
|
|
1000
|
+
items: {
|
|
1001
|
+
type: "object",
|
|
1002
|
+
properties: {
|
|
1003
|
+
workstream_id: {
|
|
1004
|
+
type: "string",
|
|
1005
|
+
description: "Workstream UUID to reassign",
|
|
1006
|
+
minLength: 1,
|
|
1007
|
+
},
|
|
1008
|
+
domain: {
|
|
1009
|
+
type: "string",
|
|
1010
|
+
description: "Target domain for reassignment",
|
|
1011
|
+
minLength: 1,
|
|
1012
|
+
},
|
|
1013
|
+
role: {
|
|
1014
|
+
type: "string",
|
|
1015
|
+
description: "Optional role hint for assignment routing",
|
|
1016
|
+
minLength: 1,
|
|
1017
|
+
},
|
|
1018
|
+
status: {
|
|
1019
|
+
type: "string",
|
|
1020
|
+
description: "Optional workstream status override (active, in_progress, pending, etc.)",
|
|
1021
|
+
minLength: 1,
|
|
1022
|
+
},
|
|
1023
|
+
},
|
|
1024
|
+
required: ["workstream_id", "domain"],
|
|
1025
|
+
additionalProperties: false,
|
|
1026
|
+
},
|
|
1027
|
+
},
|
|
1028
|
+
status: {
|
|
1029
|
+
type: "string",
|
|
1030
|
+
description: "Optional workstream status override applied to each reassigned stream",
|
|
1031
|
+
minLength: 1,
|
|
1032
|
+
},
|
|
1033
|
+
},
|
|
1034
|
+
required: ["initiative_id"],
|
|
1035
|
+
additionalProperties: false,
|
|
1036
|
+
},
|
|
1037
|
+
async execute(_callId, params = {}) {
|
|
1038
|
+
try {
|
|
1039
|
+
const initiativeId = pickNonEmptyString(params.initiative_id);
|
|
1040
|
+
if (!initiativeId) {
|
|
1041
|
+
return text("❌ initiative_id is required.");
|
|
1042
|
+
}
|
|
1043
|
+
if (!isUuid(initiativeId)) {
|
|
1044
|
+
return text("❌ initiative_id must be a valid UUID.");
|
|
1045
|
+
}
|
|
1046
|
+
const statusInput = params.status;
|
|
1047
|
+
if (statusInput !== undefined && typeof statusInput !== "string") {
|
|
1048
|
+
return text("❌ status must be a string when provided.");
|
|
1049
|
+
}
|
|
1050
|
+
const normalizedStatus = typeof statusInput === "string" && statusInput.trim().length > 0
|
|
1051
|
+
? statusInput.trim()
|
|
1052
|
+
: undefined;
|
|
1053
|
+
const normalizedMappings = [];
|
|
1054
|
+
const seenWorkstreams = new Set();
|
|
1055
|
+
const addMapping = (workstreamIdRaw, domainRaw, options) => {
|
|
1056
|
+
const workstreamId = workstreamIdRaw.trim();
|
|
1057
|
+
if (!workstreamId || !isUuid(workstreamId)) {
|
|
1058
|
+
return `❌ workstream identifier '${workstreamIdRaw}' must be a valid UUID.`;
|
|
1059
|
+
}
|
|
1060
|
+
const domain = domainRaw.trim();
|
|
1061
|
+
if (!domain) {
|
|
1062
|
+
return `❌ workstream '${workstreamIdRaw}' must map to a non-empty domain string.`;
|
|
1063
|
+
}
|
|
1064
|
+
if (seenWorkstreams.has(workstreamId)) {
|
|
1065
|
+
return "❌ Duplicate workstream mapping detected.";
|
|
1066
|
+
}
|
|
1067
|
+
seenWorkstreams.add(workstreamId);
|
|
1068
|
+
normalizedMappings.push({
|
|
1069
|
+
workstreamId,
|
|
1070
|
+
domain,
|
|
1071
|
+
...(options?.role?.trim() ? { role: options.role.trim() } : {}),
|
|
1072
|
+
...(options?.status?.trim() ? { status: options.status.trim() } : {}),
|
|
1073
|
+
});
|
|
1074
|
+
return null;
|
|
1075
|
+
};
|
|
1076
|
+
if (params.workstream_domains !== undefined) {
|
|
1077
|
+
if (!params.workstream_domains ||
|
|
1078
|
+
typeof params.workstream_domains !== "object" ||
|
|
1079
|
+
Array.isArray(params.workstream_domains)) {
|
|
1080
|
+
return text("❌ workstream_domains must be an object mapping workstream_id to domain.");
|
|
1081
|
+
}
|
|
1082
|
+
const mappingEntries = Object.entries(params.workstream_domains);
|
|
1083
|
+
for (const [workstreamId, domainValue] of mappingEntries) {
|
|
1084
|
+
if (typeof domainValue !== "string") {
|
|
1085
|
+
return text(`❌ workstream_domains['${workstreamId}'] must be a non-empty domain string.`);
|
|
1086
|
+
}
|
|
1087
|
+
const error = addMapping(workstreamId, domainValue);
|
|
1088
|
+
if (error)
|
|
1089
|
+
return text(error);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
if (params.mapping !== undefined) {
|
|
1093
|
+
if (!params.mapping ||
|
|
1094
|
+
typeof params.mapping !== "object" ||
|
|
1095
|
+
Array.isArray(params.mapping)) {
|
|
1096
|
+
return text("❌ mapping must be an object of workstream_id -> domain.");
|
|
1097
|
+
}
|
|
1098
|
+
const mappingEntries = Object.entries(params.mapping);
|
|
1099
|
+
for (const [workstreamId, domainValue] of mappingEntries) {
|
|
1100
|
+
if (typeof domainValue !== "string") {
|
|
1101
|
+
return text(`❌ mapping['${workstreamId}'] must be a non-empty domain string.`);
|
|
1102
|
+
}
|
|
1103
|
+
const error = addMapping(workstreamId, domainValue);
|
|
1104
|
+
if (error)
|
|
1105
|
+
return text(error);
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
if (params.mappings !== undefined) {
|
|
1109
|
+
if (!Array.isArray(params.mappings)) {
|
|
1110
|
+
return text("❌ mappings must be an array when provided.");
|
|
1111
|
+
}
|
|
1112
|
+
for (const entry of params.mappings) {
|
|
1113
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
1114
|
+
return text("❌ mappings entries must be objects with workstream_id and domain.");
|
|
1115
|
+
}
|
|
1116
|
+
const candidate = entry;
|
|
1117
|
+
const workstreamId = pickNonEmptyString(candidate.workstream_id);
|
|
1118
|
+
const domain = pickNonEmptyString(candidate.domain);
|
|
1119
|
+
const role = pickNonEmptyString(candidate.role);
|
|
1120
|
+
const status = pickNonEmptyString(candidate.status);
|
|
1121
|
+
if (!workstreamId || !domain) {
|
|
1122
|
+
return text("❌ Each mappings entry requires workstream_id and domain.");
|
|
1123
|
+
}
|
|
1124
|
+
const error = addMapping(workstreamId, domain, { role, status });
|
|
1125
|
+
if (error)
|
|
1126
|
+
return text(error);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
if (normalizedMappings.length === 0) {
|
|
1130
|
+
return text("❌ Include workstream_domains, mapping, or mappings with at least one workstream reassignment.");
|
|
1131
|
+
}
|
|
1132
|
+
const updates = [];
|
|
1133
|
+
const domainBeforeByWorkstreamId = new Map();
|
|
1134
|
+
if (typeof client.listEntities === "function") {
|
|
1135
|
+
try {
|
|
1136
|
+
const currentWorkstreams = await client.listEntities("workstream", {
|
|
1137
|
+
initiative_id: initiativeId,
|
|
1138
|
+
limit: 200,
|
|
1139
|
+
});
|
|
1140
|
+
const rows = currentWorkstreams &&
|
|
1141
|
+
typeof currentWorkstreams === "object" &&
|
|
1142
|
+
Array.isArray(currentWorkstreams.data)
|
|
1143
|
+
? currentWorkstreams.data
|
|
1144
|
+
: [];
|
|
1145
|
+
for (const row of rows) {
|
|
1146
|
+
if (!row || typeof row !== "object" || Array.isArray(row))
|
|
1147
|
+
continue;
|
|
1148
|
+
const record = row;
|
|
1149
|
+
const id = pickNonEmptyString(record.id);
|
|
1150
|
+
if (!id)
|
|
1151
|
+
continue;
|
|
1152
|
+
domainBeforeByWorkstreamId.set(id, pickNonEmptyString(record.domain) ?? null);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
catch {
|
|
1156
|
+
// Best effort snapshot for before/after confirmation.
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
for (const mapping of normalizedMappings) {
|
|
1160
|
+
const workstreamId = mapping.workstreamId;
|
|
1161
|
+
const domain = mapping.domain;
|
|
1162
|
+
const beforeDomain = domainBeforeByWorkstreamId.get(workstreamId) ?? null;
|
|
1163
|
+
const payload = {
|
|
1164
|
+
initiative_id: initiativeId,
|
|
1165
|
+
domain,
|
|
1166
|
+
};
|
|
1167
|
+
if (mapping.role !== undefined)
|
|
1168
|
+
payload.role = mapping.role;
|
|
1169
|
+
if (mapping.status !== undefined) {
|
|
1170
|
+
payload.status = mapping.status;
|
|
1171
|
+
}
|
|
1172
|
+
else if (normalizedStatus !== undefined) {
|
|
1173
|
+
payload.status = normalizedStatus;
|
|
1174
|
+
}
|
|
1175
|
+
try {
|
|
1176
|
+
const result = await client.updateEntityDetailed("workstream", workstreamId, payload);
|
|
1177
|
+
const entityRecord = result.entity && typeof result.entity === "object" && !Array.isArray(result.entity)
|
|
1178
|
+
? result.entity
|
|
1179
|
+
: null;
|
|
1180
|
+
const reassignmentRecord = result.reassignment &&
|
|
1181
|
+
typeof result.reassignment === "object" &&
|
|
1182
|
+
!Array.isArray(result.reassignment)
|
|
1183
|
+
? result.reassignment
|
|
1184
|
+
: null;
|
|
1185
|
+
const resolvedBeforeDomain = pickNonEmptyString(beforeDomain, reassignmentRecord?.before_domain, reassignmentRecord?.previous_domain, reassignmentRecord?.from_domain, entityRecord?.before_domain, entityRecord?.previous_domain, entityRecord?.from_domain) ?? null;
|
|
1186
|
+
const afterDomain = pickNonEmptyString(reassignmentRecord?.after_domain, reassignmentRecord?.new_domain, reassignmentRecord?.to_domain, entityRecord?.after_domain, entityRecord?.new_domain, entityRecord?.to_domain, entityRecord?.domain, domain) ?? null;
|
|
1187
|
+
updates.push({
|
|
1188
|
+
workstream_id: workstreamId,
|
|
1189
|
+
domain,
|
|
1190
|
+
before_domain: resolvedBeforeDomain,
|
|
1191
|
+
after_domain: afterDomain,
|
|
1192
|
+
ok: true,
|
|
1193
|
+
entity: result.entity,
|
|
1194
|
+
reassignment: result.reassignment ?? null,
|
|
1195
|
+
initiative_reassignment: result.initiative_reassignment ?? null,
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
catch (updateErr) {
|
|
1199
|
+
updates.push({
|
|
1200
|
+
workstream_id: workstreamId,
|
|
1201
|
+
domain,
|
|
1202
|
+
before_domain: beforeDomain,
|
|
1203
|
+
after_domain: null,
|
|
1204
|
+
ok: false,
|
|
1205
|
+
error: updateErr instanceof Error ? updateErr.message : String(updateErr),
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
const succeeded = updates.filter((entry) => entry.ok).length;
|
|
1210
|
+
const failed = updates.length - succeeded;
|
|
1211
|
+
return json(`✅ Reassigned ${succeeded}/${updates.length} workstream(s)`, {
|
|
1212
|
+
initiative_id: initiativeId,
|
|
1213
|
+
updated_count: succeeded,
|
|
1214
|
+
failed_count: failed,
|
|
1215
|
+
updates,
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
catch (err) {
|
|
1219
|
+
return text(`❌ Batch stream reassignment failed: ${err instanceof Error ? err.message : err}`);
|
|
1220
|
+
}
|
|
1221
|
+
},
|
|
1222
|
+
}, { optional: true });
|
|
415
1223
|
// --- orgx_list_entities ---
|
|
416
1224
|
registerMcpTool({
|
|
417
1225
|
name: "orgx_list_entities",
|
|
@@ -432,6 +1240,22 @@ export function registerCoreTools(deps) {
|
|
|
432
1240
|
description: "Max results (default 20)",
|
|
433
1241
|
default: 20,
|
|
434
1242
|
},
|
|
1243
|
+
initiative_id: {
|
|
1244
|
+
type: "string",
|
|
1245
|
+
description: "Filter by initiative ID",
|
|
1246
|
+
},
|
|
1247
|
+
project_id: {
|
|
1248
|
+
type: "string",
|
|
1249
|
+
description: "Legacy project/workspace scope filter",
|
|
1250
|
+
},
|
|
1251
|
+
workspace_id: {
|
|
1252
|
+
type: "string",
|
|
1253
|
+
description: "Workspace ID (canonical scope)",
|
|
1254
|
+
},
|
|
1255
|
+
command_center_id: {
|
|
1256
|
+
type: "string",
|
|
1257
|
+
description: "Deprecated alias for workspace_id",
|
|
1258
|
+
},
|
|
435
1259
|
},
|
|
436
1260
|
required: ["type"],
|
|
437
1261
|
},
|
|
@@ -448,6 +1272,285 @@ export function registerCoreTools(deps) {
|
|
|
448
1272
|
}
|
|
449
1273
|
},
|
|
450
1274
|
}, { optional: true });
|
|
1275
|
+
function evalGateErrorForPackStatus(status) {
|
|
1276
|
+
if (typeof status !== "string")
|
|
1277
|
+
return null;
|
|
1278
|
+
const normalized = status.trim().toLowerCase();
|
|
1279
|
+
if (!normalized || normalized === "approved")
|
|
1280
|
+
return null;
|
|
1281
|
+
return `SkillPack eval gate blocked activation: status '${status}' is not approved`;
|
|
1282
|
+
}
|
|
1283
|
+
function manifestValidationErrorForPackManifest(manifest) {
|
|
1284
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
1285
|
+
return null;
|
|
1286
|
+
}
|
|
1287
|
+
const validation = validateOpenClawSkillPackManifest(manifest);
|
|
1288
|
+
if (validation.errors.length === 0)
|
|
1289
|
+
return null;
|
|
1290
|
+
return `SkillPack manifest validation errors: ${validation.errors.join("; ")}`;
|
|
1291
|
+
}
|
|
1292
|
+
function computeSkillPackUpdateAvailable(state) {
|
|
1293
|
+
return Boolean(state.remote?.checksum &&
|
|
1294
|
+
state.pack?.checksum &&
|
|
1295
|
+
state.remote.checksum !== state.pack.checksum);
|
|
1296
|
+
}
|
|
1297
|
+
function resolveAgentConfigId(input) {
|
|
1298
|
+
const value = typeof input === "string" ? input.trim() : "";
|
|
1299
|
+
if (!value || value === "default") {
|
|
1300
|
+
return "default";
|
|
1301
|
+
}
|
|
1302
|
+
return null;
|
|
1303
|
+
}
|
|
1304
|
+
function resolveAgentConfigTemplateId(input) {
|
|
1305
|
+
const value = typeof input === "string" ? input.trim().toLowerCase() : "";
|
|
1306
|
+
if (value === "startup-speed") {
|
|
1307
|
+
return "startup-speed";
|
|
1308
|
+
}
|
|
1309
|
+
return null;
|
|
1310
|
+
}
|
|
1311
|
+
function buildAgentConfigSnapshot(state) {
|
|
1312
|
+
return {
|
|
1313
|
+
config_id: "default",
|
|
1314
|
+
config_type: "skill_pack_policy",
|
|
1315
|
+
policy: state.policy,
|
|
1316
|
+
pack: state.pack,
|
|
1317
|
+
remote: state.remote,
|
|
1318
|
+
update_available: computeSkillPackUpdateAvailable(state),
|
|
1319
|
+
last_checked_at: state.lastCheckedAt,
|
|
1320
|
+
last_error: state.lastError,
|
|
1321
|
+
updated_at: state.updatedAt,
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
async function readAgentConfigState(input) {
|
|
1325
|
+
const state = readSkillPackState();
|
|
1326
|
+
if (!input?.refreshRemote) {
|
|
1327
|
+
return state;
|
|
1328
|
+
}
|
|
1329
|
+
const getSkillPack = client.getSkillPack;
|
|
1330
|
+
if (typeof getSkillPack !== "function") {
|
|
1331
|
+
return state;
|
|
1332
|
+
}
|
|
1333
|
+
try {
|
|
1334
|
+
const response = await getSkillPack({
|
|
1335
|
+
name: state.pack?.name ?? state.remote?.name ?? "orgx-agent-suite",
|
|
1336
|
+
ifNoneMatch: null,
|
|
1337
|
+
});
|
|
1338
|
+
const checkedAt = new Date().toISOString();
|
|
1339
|
+
if (!response.ok) {
|
|
1340
|
+
return {
|
|
1341
|
+
...state,
|
|
1342
|
+
updatedAt: checkedAt,
|
|
1343
|
+
lastCheckedAt: checkedAt,
|
|
1344
|
+
lastError: response.error ?? state.lastError,
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
if (response.notModified || !response.pack) {
|
|
1348
|
+
return {
|
|
1349
|
+
...state,
|
|
1350
|
+
updatedAt: checkedAt,
|
|
1351
|
+
lastCheckedAt: checkedAt,
|
|
1352
|
+
lastError: null,
|
|
1353
|
+
etag: response.etag ?? state.etag,
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
const remote = {
|
|
1357
|
+
name: response.pack.name,
|
|
1358
|
+
version: response.pack.version,
|
|
1359
|
+
checksum: response.pack.checksum,
|
|
1360
|
+
updated_at: response.pack.updated_at ?? null,
|
|
1361
|
+
};
|
|
1362
|
+
const evalGateError = evalGateErrorForPackStatus(response.pack.status);
|
|
1363
|
+
const manifestValidationError = manifestValidationErrorForPackManifest(response.pack.manifest);
|
|
1364
|
+
const activationValidationError = evalGateError ?? manifestValidationError;
|
|
1365
|
+
const shouldApplyPack = !activationValidationError &&
|
|
1366
|
+
(!state.policy.pinnedChecksum || state.policy.pinnedChecksum === response.pack.checksum);
|
|
1367
|
+
return {
|
|
1368
|
+
...state,
|
|
1369
|
+
updatedAt: checkedAt,
|
|
1370
|
+
lastCheckedAt: checkedAt,
|
|
1371
|
+
lastError: activationValidationError,
|
|
1372
|
+
etag: response.etag ?? state.etag,
|
|
1373
|
+
remote,
|
|
1374
|
+
pack: shouldApplyPack ? remote : state.pack,
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
catch {
|
|
1378
|
+
return state;
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
// --- list_agent_configs ---
|
|
1382
|
+
registerMcpTool({
|
|
1383
|
+
name: "list_agent_configs",
|
|
1384
|
+
description: "List available agent behavior configs managed by this plugin.",
|
|
1385
|
+
parameters: {
|
|
1386
|
+
type: "object",
|
|
1387
|
+
properties: {
|
|
1388
|
+
refresh_remote: {
|
|
1389
|
+
type: "boolean",
|
|
1390
|
+
description: "When true, re-fetch behavior config policy from OrgX before returning data.",
|
|
1391
|
+
},
|
|
1392
|
+
},
|
|
1393
|
+
additionalProperties: false,
|
|
1394
|
+
},
|
|
1395
|
+
async execute(_callId, params = {}) {
|
|
1396
|
+
try {
|
|
1397
|
+
const state = await readAgentConfigState({
|
|
1398
|
+
refreshRemote: params.refresh_remote === true,
|
|
1399
|
+
});
|
|
1400
|
+
return json("Agent configs:", {
|
|
1401
|
+
total: 1,
|
|
1402
|
+
configs: [buildAgentConfigSnapshot(state)],
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
catch (err) {
|
|
1406
|
+
return text(`❌ Failed to list agent configs: ${err instanceof Error ? err.message : err}`);
|
|
1407
|
+
}
|
|
1408
|
+
},
|
|
1409
|
+
}, { optional: true });
|
|
1410
|
+
// --- get_agent_config ---
|
|
1411
|
+
registerMcpTool({
|
|
1412
|
+
name: "get_agent_config",
|
|
1413
|
+
description: "Get a single agent behavior config by id (default only).",
|
|
1414
|
+
parameters: {
|
|
1415
|
+
type: "object",
|
|
1416
|
+
properties: {
|
|
1417
|
+
config_id: {
|
|
1418
|
+
type: "string",
|
|
1419
|
+
description: "Agent config identifier. Use 'default'.",
|
|
1420
|
+
},
|
|
1421
|
+
refresh_remote: {
|
|
1422
|
+
type: "boolean",
|
|
1423
|
+
description: "When true, re-fetch behavior config policy from OrgX before returning data.",
|
|
1424
|
+
},
|
|
1425
|
+
},
|
|
1426
|
+
additionalProperties: false,
|
|
1427
|
+
},
|
|
1428
|
+
async execute(_callId, params = {}) {
|
|
1429
|
+
const configId = resolveAgentConfigId(params.config_id);
|
|
1430
|
+
if (!configId) {
|
|
1431
|
+
return text("❌ config_id must be 'default'.");
|
|
1432
|
+
}
|
|
1433
|
+
try {
|
|
1434
|
+
const state = await readAgentConfigState({
|
|
1435
|
+
refreshRemote: params.refresh_remote === true,
|
|
1436
|
+
});
|
|
1437
|
+
return json("Agent config:", buildAgentConfigSnapshot(state));
|
|
1438
|
+
}
|
|
1439
|
+
catch (err) {
|
|
1440
|
+
return text(`❌ Failed to read agent config: ${err instanceof Error ? err.message : err}`);
|
|
1441
|
+
}
|
|
1442
|
+
},
|
|
1443
|
+
}, { optional: true });
|
|
1444
|
+
// --- update_agent_config ---
|
|
1445
|
+
registerMcpTool({
|
|
1446
|
+
name: "update_agent_config",
|
|
1447
|
+
description: "Update plugin-managed agent behavior config policy (default config only).",
|
|
1448
|
+
parameters: {
|
|
1449
|
+
type: "object",
|
|
1450
|
+
properties: {
|
|
1451
|
+
config_id: {
|
|
1452
|
+
type: "string",
|
|
1453
|
+
description: "Agent config identifier. Use 'default'.",
|
|
1454
|
+
},
|
|
1455
|
+
frozen: {
|
|
1456
|
+
type: "boolean",
|
|
1457
|
+
description: "Freeze remote skill-pack refresh when true.",
|
|
1458
|
+
},
|
|
1459
|
+
pinned_checksum: {
|
|
1460
|
+
type: ["string", "null"],
|
|
1461
|
+
description: "Pin behavior policy to this exact checksum.",
|
|
1462
|
+
},
|
|
1463
|
+
pin_to_current: {
|
|
1464
|
+
type: "boolean",
|
|
1465
|
+
description: "Pin to current local/remote checksum.",
|
|
1466
|
+
},
|
|
1467
|
+
clear_pin: {
|
|
1468
|
+
type: "boolean",
|
|
1469
|
+
description: "Clear any pinned checksum.",
|
|
1470
|
+
},
|
|
1471
|
+
action: {
|
|
1472
|
+
type: "string",
|
|
1473
|
+
description: "Use 'rollback' to revert to the previous config version.",
|
|
1474
|
+
},
|
|
1475
|
+
rollback_to_audit_id: {
|
|
1476
|
+
type: "string",
|
|
1477
|
+
description: "Optional audit entry id to rollback to. When omitted with action='rollback', uses the most recent audit entry.",
|
|
1478
|
+
},
|
|
1479
|
+
template_id: {
|
|
1480
|
+
type: "string",
|
|
1481
|
+
description: "Optional preset template id. Currently supports 'startup-speed'.",
|
|
1482
|
+
},
|
|
1483
|
+
},
|
|
1484
|
+
additionalProperties: false,
|
|
1485
|
+
},
|
|
1486
|
+
async execute(_callId, params = {}) {
|
|
1487
|
+
const configId = resolveAgentConfigId(params.config_id);
|
|
1488
|
+
if (!configId) {
|
|
1489
|
+
return text("❌ config_id must be 'default'.");
|
|
1490
|
+
}
|
|
1491
|
+
const templateId = resolveAgentConfigTemplateId(params.template_id);
|
|
1492
|
+
if (typeof params.template_id === "string" && !templateId) {
|
|
1493
|
+
return text("❌ template_id must be 'startup-speed' when provided.");
|
|
1494
|
+
}
|
|
1495
|
+
let hasFrozen = typeof params.frozen === "boolean";
|
|
1496
|
+
let hasPinnedChecksum = typeof params.pinned_checksum === "string" || params.pinned_checksum === null;
|
|
1497
|
+
let hasPinToCurrent = params.pin_to_current === true;
|
|
1498
|
+
let hasClearPin = params.clear_pin === true;
|
|
1499
|
+
const action = typeof params.action === "string" ? params.action.trim().toLowerCase() : "";
|
|
1500
|
+
const rollbackToAuditId = typeof params.rollback_to_audit_id === "string" && params.rollback_to_audit_id.trim()
|
|
1501
|
+
? params.rollback_to_audit_id.trim()
|
|
1502
|
+
: undefined;
|
|
1503
|
+
const isRollback = action === "rollback" || typeof rollbackToAuditId === "string";
|
|
1504
|
+
if (action.length > 0 && action !== "rollback") {
|
|
1505
|
+
return text("❌ action must be 'rollback' when provided.");
|
|
1506
|
+
}
|
|
1507
|
+
if (templateId === "startup-speed") {
|
|
1508
|
+
// Shared default config fans out to all OrgX agent domains.
|
|
1509
|
+
params.frozen = false;
|
|
1510
|
+
params.clear_pin = true;
|
|
1511
|
+
params.pin_to_current = false;
|
|
1512
|
+
params.pinned_checksum = undefined;
|
|
1513
|
+
hasFrozen = true;
|
|
1514
|
+
hasPinnedChecksum = false;
|
|
1515
|
+
hasPinToCurrent = false;
|
|
1516
|
+
hasClearPin = true;
|
|
1517
|
+
}
|
|
1518
|
+
if (isRollback) {
|
|
1519
|
+
if (hasFrozen || hasPinnedChecksum || hasPinToCurrent || hasClearPin || templateId) {
|
|
1520
|
+
return text("❌ Rollback requests cannot include update fields (frozen, pinned_checksum, pin_to_current, clear_pin, template_id).");
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
else if (!hasFrozen && !hasPinnedChecksum && !hasPinToCurrent && !hasClearPin) {
|
|
1524
|
+
return text("❌ Include at least one mutable field: frozen, pinned_checksum, pin_to_current, clear_pin, or template_id.");
|
|
1525
|
+
}
|
|
1526
|
+
if (hasPinToCurrent && hasClearPin) {
|
|
1527
|
+
return text("❌ pin_to_current and clear_pin cannot both be true.");
|
|
1528
|
+
}
|
|
1529
|
+
if (typeof params.pinned_checksum === "string" && !params.pinned_checksum.trim()) {
|
|
1530
|
+
return text("❌ pinned_checksum must be a non-empty string when provided.");
|
|
1531
|
+
}
|
|
1532
|
+
try {
|
|
1533
|
+
const state = isRollback
|
|
1534
|
+
? rollbackSkillPackPolicy({
|
|
1535
|
+
auditId: rollbackToAuditId,
|
|
1536
|
+
})
|
|
1537
|
+
: updateSkillPackPolicy({
|
|
1538
|
+
frozen: hasFrozen ? params.frozen : undefined,
|
|
1539
|
+
pinnedChecksum: typeof params.pinned_checksum === "string"
|
|
1540
|
+
? params.pinned_checksum.trim()
|
|
1541
|
+
: params.pinned_checksum === null
|
|
1542
|
+
? null
|
|
1543
|
+
: undefined,
|
|
1544
|
+
pinToCurrent: hasPinToCurrent,
|
|
1545
|
+
clearPin: hasClearPin,
|
|
1546
|
+
});
|
|
1547
|
+
return json(isRollback ? "Agent config rolled back:" : "Agent config updated:", buildAgentConfigSnapshot(state));
|
|
1548
|
+
}
|
|
1549
|
+
catch (err) {
|
|
1550
|
+
return text(`❌ Failed to ${isRollback ? "rollback" : "update"} agent config: ${err instanceof Error ? err.message : err}`);
|
|
1551
|
+
}
|
|
1552
|
+
},
|
|
1553
|
+
}, { optional: true });
|
|
451
1554
|
function withProvenanceMetadata(metadata) {
|
|
452
1555
|
const input = metadata ?? {};
|
|
453
1556
|
const out = { ...input };
|
|
@@ -490,6 +1593,26 @@ export function registerCoreTools(deps) {
|
|
|
490
1593
|
}
|
|
491
1594
|
return out;
|
|
492
1595
|
}
|
|
1596
|
+
function deriveAgentIdentity(payload) {
|
|
1597
|
+
const envAgentId = pickNonEmptyString(process.env.ORGX_AGENT_ID) ?? null;
|
|
1598
|
+
const envAgentName = pickNonEmptyString(process.env.ORGX_AGENT_NAME) ?? null;
|
|
1599
|
+
const payloadRecord = payload && typeof payload === "object" && !Array.isArray(payload)
|
|
1600
|
+
? payload
|
|
1601
|
+
: null;
|
|
1602
|
+
const metadataRaw = payloadRecord?.metadata;
|
|
1603
|
+
const metadata = metadataRaw && typeof metadataRaw === "object" && !Array.isArray(metadataRaw)
|
|
1604
|
+
? metadataRaw
|
|
1605
|
+
: {};
|
|
1606
|
+
const metadataAgentId = pickNonEmptyString(metadata.agent_id, metadata.agentId, metadata.executor_agent_id, metadata.executorAgentId, metadata.requested_by_agent_id, metadata.requestedByAgentId) ?? null;
|
|
1607
|
+
const metadataAgentName = pickNonEmptyString(metadata.agent_name, metadata.agentName, metadata.executor_agent_name, metadata.executorAgentName, metadata.requested_by_agent_name, metadata.requestedByAgentName) ?? null;
|
|
1608
|
+
return {
|
|
1609
|
+
agentId: envAgentId ?? metadataAgentId,
|
|
1610
|
+
agentName: envAgentName ?? metadataAgentName,
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
function deriveCorrelationFromRun(runId) {
|
|
1614
|
+
return `openclaw_run_${runId.replace(/[^a-zA-Z0-9]/g, "").slice(0, 24)}`;
|
|
1615
|
+
}
|
|
493
1616
|
async function emitActivityWithFallback(source, payload) {
|
|
494
1617
|
if (!payload.message || payload.message.trim().length === 0) {
|
|
495
1618
|
return text("❌ message is required");
|
|
@@ -500,6 +1623,20 @@ export function registerCoreTools(deps) {
|
|
|
500
1623
|
}
|
|
501
1624
|
const now = new Date().toISOString();
|
|
502
1625
|
const id = `progress:${randomUUID().slice(0, 8)}`;
|
|
1626
|
+
const envWorkstreamId = pickNonEmptyString(process.env.ORGX_WORKSTREAM_ID);
|
|
1627
|
+
const envTaskId = pickNonEmptyString(process.env.ORGX_TASK_ID);
|
|
1628
|
+
const { agentId, agentName } = deriveAgentIdentity(payload);
|
|
1629
|
+
const canonicalMetadata = {
|
|
1630
|
+
initiative_id: context.value.initiativeId,
|
|
1631
|
+
run_id: context.value.runId ?? null,
|
|
1632
|
+
slice_run_id: context.value.runId ?? null,
|
|
1633
|
+
correlation_id: context.value.correlationId ?? null,
|
|
1634
|
+
source_client: context.value.sourceClient ?? null,
|
|
1635
|
+
...(envWorkstreamId ? { workstream_id: envWorkstreamId } : {}),
|
|
1636
|
+
...(envTaskId ? { task_id: envTaskId } : {}),
|
|
1637
|
+
...(agentId ? { agent_id: agentId } : {}),
|
|
1638
|
+
...(agentName ? { agent_name: agentName } : {}),
|
|
1639
|
+
};
|
|
503
1640
|
const normalizedPayload = {
|
|
504
1641
|
initiative_id: context.value.initiativeId,
|
|
505
1642
|
run_id: context.value.runId,
|
|
@@ -511,6 +1648,7 @@ export function registerCoreTools(deps) {
|
|
|
511
1648
|
level: payload.level ?? "info",
|
|
512
1649
|
next_step: payload.next_step,
|
|
513
1650
|
metadata: withProvenanceMetadata({
|
|
1651
|
+
...canonicalMetadata,
|
|
514
1652
|
...(payload.metadata ?? {}),
|
|
515
1653
|
source,
|
|
516
1654
|
}),
|
|
@@ -520,12 +1658,12 @@ export function registerCoreTools(deps) {
|
|
|
520
1658
|
type: "delegation",
|
|
521
1659
|
title: payload.message,
|
|
522
1660
|
description: payload.next_step ?? null,
|
|
523
|
-
agentId
|
|
524
|
-
agentName
|
|
525
|
-
requesterAgentId:
|
|
526
|
-
requesterAgentName:
|
|
527
|
-
executorAgentId:
|
|
528
|
-
executorAgentName:
|
|
1661
|
+
agentId,
|
|
1662
|
+
agentName,
|
|
1663
|
+
requesterAgentId: agentId,
|
|
1664
|
+
requesterAgentName: agentName,
|
|
1665
|
+
executorAgentId: agentId,
|
|
1666
|
+
executorAgentName: agentName,
|
|
529
1667
|
runId: context.value.runId ?? null,
|
|
530
1668
|
initiativeId: context.value.initiativeId,
|
|
531
1669
|
timestamp: now,
|
|
@@ -537,7 +1675,29 @@ export function registerCoreTools(deps) {
|
|
|
537
1675
|
const result = await client.emitActivity(normalizedPayload);
|
|
538
1676
|
return text(`Activity emitted: ${payload.message} [${normalizedPayload.phase}${payload.progress_pct != null ? ` ${payload.progress_pct}%` : ""}] (run ${result.run_id.slice(0, 8)}...)`);
|
|
539
1677
|
}
|
|
540
|
-
catch {
|
|
1678
|
+
catch (err) {
|
|
1679
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1680
|
+
if (normalizedPayload.run_id &&
|
|
1681
|
+
/^404\b/.test(errMsg) &&
|
|
1682
|
+
/\brun\b/i.test(errMsg) &&
|
|
1683
|
+
/not found/i.test(errMsg)) {
|
|
1684
|
+
try {
|
|
1685
|
+
const retryCorrelation = normalizedPayload.correlation_id ?? deriveCorrelationFromRun(normalizedPayload.run_id);
|
|
1686
|
+
const retryResult = await client.emitActivity({
|
|
1687
|
+
...normalizedPayload,
|
|
1688
|
+
run_id: undefined,
|
|
1689
|
+
correlation_id: retryCorrelation,
|
|
1690
|
+
metadata: withProvenanceMetadata({
|
|
1691
|
+
...(normalizedPayload.metadata ?? {}),
|
|
1692
|
+
replay_run_id_as_correlation: true,
|
|
1693
|
+
}),
|
|
1694
|
+
});
|
|
1695
|
+
return text(`Activity emitted: ${payload.message} [${normalizedPayload.phase}${payload.progress_pct != null ? ` ${payload.progress_pct}%` : ""}] (run ${retryResult.run_id.slice(0, 8)}...)`);
|
|
1696
|
+
}
|
|
1697
|
+
catch {
|
|
1698
|
+
// Fall through to local outbox buffering.
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
541
1701
|
await appendToOutbox("progress", {
|
|
542
1702
|
id,
|
|
543
1703
|
type: "progress",
|
|
@@ -568,17 +1728,18 @@ export function registerCoreTools(deps) {
|
|
|
568
1728
|
};
|
|
569
1729
|
const now = new Date().toISOString();
|
|
570
1730
|
const id = `changeset:${randomUUID().slice(0, 8)}`;
|
|
1731
|
+
const { agentId, agentName } = deriveAgentIdentity();
|
|
571
1732
|
const activityItem = {
|
|
572
1733
|
id,
|
|
573
1734
|
type: "milestone_completed",
|
|
574
1735
|
title: "Changeset queued",
|
|
575
1736
|
description: `${payload.operations.length} operation${payload.operations.length === 1 ? "" : "s"}`,
|
|
576
|
-
agentId
|
|
577
|
-
agentName
|
|
578
|
-
requesterAgentId:
|
|
579
|
-
requesterAgentName:
|
|
580
|
-
executorAgentId:
|
|
581
|
-
executorAgentName:
|
|
1737
|
+
agentId,
|
|
1738
|
+
agentName,
|
|
1739
|
+
requesterAgentId: agentId,
|
|
1740
|
+
requesterAgentName: agentName,
|
|
1741
|
+
executorAgentId: agentId,
|
|
1742
|
+
executorAgentName: agentName,
|
|
582
1743
|
runId: context.value.runId ?? null,
|
|
583
1744
|
initiativeId: context.value.initiativeId,
|
|
584
1745
|
timestamp: now,
|
|
@@ -587,13 +1748,34 @@ export function registerCoreTools(deps) {
|
|
|
587
1748
|
metadata: withProvenanceMetadata({
|
|
588
1749
|
source,
|
|
589
1750
|
idempotency_key: idempotencyKey,
|
|
1751
|
+
run_id: context.value.runId ?? null,
|
|
1752
|
+
correlation_id: context.value.correlationId ?? null,
|
|
1753
|
+
...(agentId ? { agent_id: agentId } : {}),
|
|
1754
|
+
...(agentName ? { agent_name: agentName } : {}),
|
|
590
1755
|
}),
|
|
591
1756
|
};
|
|
592
1757
|
try {
|
|
593
1758
|
const result = await client.applyChangeset(requestPayload);
|
|
594
1759
|
return text(`Changeset ${result.replayed ? "replayed" : "applied"}: ${result.applied_count} op${result.applied_count === 1 ? "" : "s"} (run ${result.run_id.slice(0, 8)}...)`);
|
|
595
1760
|
}
|
|
596
|
-
catch {
|
|
1761
|
+
catch (err) {
|
|
1762
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1763
|
+
if (requestPayload.run_id &&
|
|
1764
|
+
/^404\b/.test(errMsg) &&
|
|
1765
|
+
/\brun\b/i.test(errMsg) &&
|
|
1766
|
+
/not found/i.test(errMsg)) {
|
|
1767
|
+
try {
|
|
1768
|
+
const retryResult = await client.applyChangeset({
|
|
1769
|
+
...requestPayload,
|
|
1770
|
+
run_id: undefined,
|
|
1771
|
+
correlation_id: requestPayload.correlation_id ?? deriveCorrelationFromRun(requestPayload.run_id),
|
|
1772
|
+
});
|
|
1773
|
+
return text(`Changeset ${retryResult.replayed ? "replayed" : "applied"}: ${retryResult.applied_count} op${retryResult.applied_count === 1 ? "" : "s"} (run ${retryResult.run_id.slice(0, 8)}...)`);
|
|
1774
|
+
}
|
|
1775
|
+
catch {
|
|
1776
|
+
// Fall through to local outbox buffering.
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
597
1779
|
await appendToOutbox("decisions", {
|
|
598
1780
|
id,
|
|
599
1781
|
type: "changeset",
|
|
@@ -770,6 +1952,69 @@ export function registerCoreTools(deps) {
|
|
|
770
1952
|
});
|
|
771
1953
|
},
|
|
772
1954
|
}, { optional: true });
|
|
1955
|
+
// --- update_stream_progress (legacy alias -> orgx_report_progress) ---
|
|
1956
|
+
registerMcpTool({
|
|
1957
|
+
name: "update_stream_progress",
|
|
1958
|
+
description: "Legacy alias for orgx_report_progress. Report progress at key milestones so the team can track your work.",
|
|
1959
|
+
parameters: {
|
|
1960
|
+
type: "object",
|
|
1961
|
+
properties: {
|
|
1962
|
+
initiative_id: {
|
|
1963
|
+
type: "string",
|
|
1964
|
+
description: "Initiative UUID (required unless ORGX_INITIATIVE_ID is set)",
|
|
1965
|
+
},
|
|
1966
|
+
run_id: {
|
|
1967
|
+
type: "string",
|
|
1968
|
+
description: "Optional run UUID",
|
|
1969
|
+
},
|
|
1970
|
+
correlation_id: {
|
|
1971
|
+
type: "string",
|
|
1972
|
+
description: "Required when run_id is omitted",
|
|
1973
|
+
},
|
|
1974
|
+
source_client: {
|
|
1975
|
+
type: "string",
|
|
1976
|
+
enum: ["openclaw", "codex", "claude-code", "api"],
|
|
1977
|
+
},
|
|
1978
|
+
summary: {
|
|
1979
|
+
type: "string",
|
|
1980
|
+
description: "What was accomplished (1-2 sentences, human-readable)",
|
|
1981
|
+
},
|
|
1982
|
+
phase: {
|
|
1983
|
+
type: "string",
|
|
1984
|
+
enum: ["researching", "implementing", "testing", "reviewing", "blocked"],
|
|
1985
|
+
description: "Current work phase",
|
|
1986
|
+
},
|
|
1987
|
+
progress_pct: {
|
|
1988
|
+
type: "number",
|
|
1989
|
+
description: "Progress percentage (0-100)",
|
|
1990
|
+
minimum: 0,
|
|
1991
|
+
maximum: 100,
|
|
1992
|
+
},
|
|
1993
|
+
next_step: {
|
|
1994
|
+
type: "string",
|
|
1995
|
+
description: "What you plan to do next",
|
|
1996
|
+
},
|
|
1997
|
+
},
|
|
1998
|
+
required: ["summary", "phase"],
|
|
1999
|
+
additionalProperties: false,
|
|
2000
|
+
},
|
|
2001
|
+
async execute(_callId, params = { summary: "", phase: "implementing" }) {
|
|
2002
|
+
return emitActivityWithFallback("update_stream_progress", {
|
|
2003
|
+
initiative_id: params.initiative_id,
|
|
2004
|
+
run_id: params.run_id,
|
|
2005
|
+
correlation_id: params.correlation_id,
|
|
2006
|
+
source_client: params.source_client,
|
|
2007
|
+
message: params.summary,
|
|
2008
|
+
phase: toReportingPhase(params.phase, params.progress_pct),
|
|
2009
|
+
progress_pct: params.progress_pct,
|
|
2010
|
+
next_step: params.next_step,
|
|
2011
|
+
level: params.phase === "blocked" ? "warn" : "info",
|
|
2012
|
+
metadata: {
|
|
2013
|
+
legacy_phase: params.phase,
|
|
2014
|
+
},
|
|
2015
|
+
});
|
|
2016
|
+
},
|
|
2017
|
+
}, { optional: true });
|
|
773
2018
|
// --- orgx_request_decision (alias -> orgx_apply_changeset decision.create) ---
|
|
774
2019
|
registerMcpTool({
|
|
775
2020
|
name: "orgx_request_decision",
|
|
@@ -883,6 +2128,12 @@ export function registerCoreTools(deps) {
|
|
|
883
2128
|
type: "string",
|
|
884
2129
|
description: "Artifact type code (e.g., 'eng.diff_pack', 'pr', 'document'). Falls back to 'shared.project_handbook' if the type is not recognized by OrgX.",
|
|
885
2130
|
},
|
|
2131
|
+
confidence_score: {
|
|
2132
|
+
type: "number",
|
|
2133
|
+
minimum: 0,
|
|
2134
|
+
maximum: 1,
|
|
2135
|
+
description: "Self-assessed confidence for this artifact in [0,1].",
|
|
2136
|
+
},
|
|
886
2137
|
description: {
|
|
887
2138
|
type: "string",
|
|
888
2139
|
description: "What this artifact is and why it matters",
|
|
@@ -926,19 +2177,27 @@ export function registerCoreTools(deps) {
|
|
|
926
2177
|
if (!params.url && !params.content) {
|
|
927
2178
|
return text("❌ Cannot register artifact: provide at least one of url or content.");
|
|
928
2179
|
}
|
|
2180
|
+
if (typeof params.confidence_score !== "undefined" &&
|
|
2181
|
+
(!Number.isFinite(params.confidence_score) ||
|
|
2182
|
+
params.confidence_score < 0 ||
|
|
2183
|
+
params.confidence_score > 1)) {
|
|
2184
|
+
return text("❌ Cannot register artifact: confidence_score must be a number between 0 and 1.");
|
|
2185
|
+
}
|
|
2186
|
+
const confidenceScore = typeof params.confidence_score === "number" ? params.confidence_score : null;
|
|
929
2187
|
const baseUrl = client.getBaseUrl();
|
|
930
2188
|
const artifactId = randomUUID();
|
|
2189
|
+
const { agentId, agentName } = deriveAgentIdentity(params);
|
|
931
2190
|
const activityItem = {
|
|
932
2191
|
id,
|
|
933
2192
|
type: "artifact_created",
|
|
934
2193
|
title: params.name,
|
|
935
2194
|
description: params.description ?? null,
|
|
936
|
-
agentId
|
|
937
|
-
agentName
|
|
938
|
-
requesterAgentId:
|
|
939
|
-
requesterAgentName:
|
|
940
|
-
executorAgentId:
|
|
941
|
-
executorAgentName:
|
|
2195
|
+
agentId,
|
|
2196
|
+
agentName,
|
|
2197
|
+
requesterAgentId: agentId,
|
|
2198
|
+
requesterAgentName: agentName,
|
|
2199
|
+
executorAgentId: agentId,
|
|
2200
|
+
executorAgentName: agentName,
|
|
942
2201
|
runId: null,
|
|
943
2202
|
initiativeId: resolvedEntityType === "initiative" ? resolvedEntityId : null,
|
|
944
2203
|
timestamp: now,
|
|
@@ -946,9 +2205,12 @@ export function registerCoreTools(deps) {
|
|
|
946
2205
|
metadata: withProvenanceMetadata({
|
|
947
2206
|
source: "orgx_register_artifact",
|
|
948
2207
|
artifact_type: params.artifact_type,
|
|
2208
|
+
confidence_score: confidenceScore,
|
|
949
2209
|
url: params.url,
|
|
950
2210
|
entity_type: resolvedEntityType,
|
|
951
2211
|
entity_id: resolvedEntityId,
|
|
2212
|
+
...(agentId ? { agent_id: agentId } : {}),
|
|
2213
|
+
...(agentName ? { agent_name: agentName } : {}),
|
|
952
2214
|
}),
|
|
953
2215
|
};
|
|
954
2216
|
try {
|
|
@@ -958,6 +2220,7 @@ export function registerCoreTools(deps) {
|
|
|
958
2220
|
entity_id: resolvedEntityId,
|
|
959
2221
|
name: params.name,
|
|
960
2222
|
artifact_type: params.artifact_type,
|
|
2223
|
+
confidence_score: confidenceScore,
|
|
961
2224
|
description: params.description ?? null,
|
|
962
2225
|
external_url: params.url ?? null,
|
|
963
2226
|
preview_markdown: params.content ?? null,
|
|
@@ -965,6 +2228,7 @@ export function registerCoreTools(deps) {
|
|
|
965
2228
|
metadata: {
|
|
966
2229
|
source: "orgx_register_artifact",
|
|
967
2230
|
artifact_id: artifactId,
|
|
2231
|
+
confidence_score: confidenceScore,
|
|
968
2232
|
},
|
|
969
2233
|
validate_persistence: true,
|
|
970
2234
|
});
|
|
@@ -989,6 +2253,7 @@ export function registerCoreTools(deps) {
|
|
|
989
2253
|
artifact_id: artifactId,
|
|
990
2254
|
name: params.name,
|
|
991
2255
|
artifact_type: params.artifact_type,
|
|
2256
|
+
confidence_score: confidenceScore,
|
|
992
2257
|
description: params.description,
|
|
993
2258
|
url: params.url,
|
|
994
2259
|
content: params.content,
|