@useorgx/openclaw-plugin 0.4.3 → 0.4.5
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 +72 -2
- package/dashboard/dist/assets/B68j2crt.js +1 -0
- package/dashboard/dist/assets/BZZ-fiJx.js +32 -0
- package/dashboard/dist/assets/{CE5pVdev.js → BoXlCHKa.js} +1 -1
- package/dashboard/dist/assets/Bq9x_Xyh.css +1 -0
- package/dashboard/dist/assets/DBhrRVdp.js +1 -0
- package/dashboard/dist/assets/DD1jv1Hd.js +8 -0
- package/dashboard/dist/assets/DNjbmawF.js +214 -0
- package/dashboard/dist/index.html +5 -5
- package/dist/contracts/client.js +22 -2
- package/dist/http-handler.js +14 -5
- package/dist/index.js +259 -26
- package/dist/mcp-client-setup.d.ts +30 -0
- package/dist/mcp-client-setup.js +215 -0
- package/dist/mcp-http-handler.d.ts +38 -0
- package/dist/mcp-http-handler.js +254 -0
- package/dist/telemetry/posthog.d.ts +8 -0
- package/dist/telemetry/posthog.js +81 -0
- package/package.json +1 -1
- package/dashboard/dist/assets/BqukHQH-.js +0 -8
- package/dashboard/dist/assets/Cpr7n8fE.js +0 -1
- package/dashboard/dist/assets/Nip3CrNC.js +0 -1
- package/dashboard/dist/assets/TN5wE36J.js +0 -1
- package/dashboard/dist/assets/X6IcjS74.js +0 -212
- package/dashboard/dist/assets/jyFhCND-.css +0 -1
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
<meta name="googlebot" content="noindex, nofollow, noarchive, nosnippet, noimageindex" />
|
|
10
10
|
<meta name="copyright" content="OrgX. All rights reserved." />
|
|
11
11
|
<title>OrgX Live Dashboard</title>
|
|
12
|
-
<script type="module" crossorigin src="/orgx/live/assets/
|
|
12
|
+
<script type="module" crossorigin src="/orgx/live/assets/DNjbmawF.js"></script>
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/orgx/live/assets/C-KIc3Wc.js">
|
|
14
|
-
<link rel="modulepreload" crossorigin href="/orgx/live/assets/
|
|
15
|
-
<link rel="modulepreload" crossorigin href="/orgx/live/assets/
|
|
16
|
-
<link rel="modulepreload" crossorigin href="/orgx/live/assets/
|
|
17
|
-
<link rel="stylesheet" crossorigin href="/orgx/live/assets/
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/orgx/live/assets/BZZ-fiJx.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/orgx/live/assets/DD1jv1Hd.js">
|
|
16
|
+
<link rel="modulepreload" crossorigin href="/orgx/live/assets/BoXlCHKa.js">
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/orgx/live/assets/Bq9x_Xyh.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body class="bg-[#080808] text-white antialiased">
|
|
20
20
|
<div id="root"></div>
|
package/dist/contracts/client.js
CHANGED
|
@@ -201,16 +201,36 @@ export class OrgXClient {
|
|
|
201
201
|
// Spawn Guard (Quality Gate + Model Routing)
|
|
202
202
|
// ===========================================================================
|
|
203
203
|
async checkSpawnGuard(domain, taskId) {
|
|
204
|
-
|
|
204
|
+
const response = await this.post("/api/client/spawn", {
|
|
205
205
|
domain,
|
|
206
206
|
taskId,
|
|
207
207
|
});
|
|
208
|
+
// Newer servers wrap responses in { ok, data } while older clients expect the
|
|
209
|
+
// SpawnGuardResult fields at top-level.
|
|
210
|
+
if (response &&
|
|
211
|
+
typeof response === "object" &&
|
|
212
|
+
"data" in response &&
|
|
213
|
+
response.data) {
|
|
214
|
+
return response.data;
|
|
215
|
+
}
|
|
216
|
+
return response;
|
|
208
217
|
}
|
|
209
218
|
// ===========================================================================
|
|
210
219
|
// Quality Scores
|
|
211
220
|
// ===========================================================================
|
|
212
221
|
async recordQuality(score) {
|
|
213
|
-
|
|
222
|
+
const response = await this.post("/api/client/quality", score);
|
|
223
|
+
// Backwards-compatible: accept either { success: true } or { ok: true, data: ... }.
|
|
224
|
+
if (response &&
|
|
225
|
+
typeof response === "object" &&
|
|
226
|
+
"success" in response &&
|
|
227
|
+
typeof response.success === "boolean") {
|
|
228
|
+
return response;
|
|
229
|
+
}
|
|
230
|
+
if (response && typeof response === "object" && "ok" in response) {
|
|
231
|
+
return { success: Boolean(response.ok) };
|
|
232
|
+
}
|
|
233
|
+
return { success: true };
|
|
214
234
|
}
|
|
215
235
|
// ===========================================================================
|
|
216
236
|
// Entity CRUD
|
package/dist/http-handler.js
CHANGED
|
@@ -2214,13 +2214,22 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2214
2214
|
type: "progress",
|
|
2215
2215
|
timestamp,
|
|
2216
2216
|
payload: {
|
|
2217
|
-
|
|
2217
|
+
// Keep this payload aligned with OrgXClient.emitActivity input
|
|
2218
|
+
// so outbox replay can forward it without shape translation.
|
|
2219
|
+
initiative_id: initiativeId,
|
|
2220
|
+
run_id: input.runId?.trim() || undefined,
|
|
2221
|
+
correlation_id: input.runId
|
|
2222
|
+
? undefined
|
|
2223
|
+
: (input.correlationId?.trim() || `openclaw-${Date.now()}`),
|
|
2224
|
+
source_client: "openclaw",
|
|
2218
2225
|
message,
|
|
2226
|
+
phase: input.phase,
|
|
2227
|
+
progress_pct: typeof input.progressPct === "number" && Number.isFinite(input.progressPct)
|
|
2228
|
+
? Math.max(0, Math.min(100, Math.round(input.progressPct)))
|
|
2229
|
+
: undefined,
|
|
2219
2230
|
level: input.level ?? "info",
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
nextStep: input.nextStep ?? null,
|
|
2223
|
-
metadata: input.metadata ?? null,
|
|
2231
|
+
next_step: input.nextStep ?? undefined,
|
|
2232
|
+
metadata: input.metadata ?? undefined,
|
|
2224
2233
|
},
|
|
2225
2234
|
activityItem,
|
|
2226
2235
|
});
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,10 @@ import { clearPersistedSnapshot, readPersistedSnapshot, writePersistedSnapshot,
|
|
|
22
22
|
import { appendToOutbox, readOutbox, readOutboxSummary, replaceOutbox, } from "./outbox.js";
|
|
23
23
|
import { extractProgressOutboxMessage } from "./reporting/outbox-replay.js";
|
|
24
24
|
import { ensureGatewayWatchdog } from "./gateway-watchdog.js";
|
|
25
|
+
import { createMcpHttpHandler } from "./mcp-http-handler.js";
|
|
26
|
+
import { autoConfigureDetectedMcpClients } from "./mcp-client-setup.js";
|
|
27
|
+
import { readOpenClawGatewayPort, readOpenClawSettingsSnapshot } from "./openclaw-settings.js";
|
|
28
|
+
import { posthogCapture } from "./telemetry/posthog.js";
|
|
25
29
|
export { OrgXClient } from "./api.js";
|
|
26
30
|
const DEFAULT_BASE_URL = "https://www.useorgx.com";
|
|
27
31
|
const DEFAULT_DOCS_URL = "https://orgx.mintlify.site/guides/openclaw-plugin-setup";
|
|
@@ -325,6 +329,19 @@ export default function register(api) {
|
|
|
325
329
|
api.log?.info?.("[orgx] Plugin disabled");
|
|
326
330
|
return;
|
|
327
331
|
}
|
|
332
|
+
void posthogCapture({
|
|
333
|
+
event: "openclaw_plugin_loaded",
|
|
334
|
+
distinctId: config.installationId,
|
|
335
|
+
properties: {
|
|
336
|
+
plugin_version: config.pluginVersion,
|
|
337
|
+
dashboard_enabled: config.dashboardEnabled,
|
|
338
|
+
has_api_key: Boolean(config.apiKey),
|
|
339
|
+
api_key_source: config.apiKeySource,
|
|
340
|
+
base_url: config.baseUrl,
|
|
341
|
+
},
|
|
342
|
+
}).catch(() => {
|
|
343
|
+
// best effort
|
|
344
|
+
});
|
|
328
345
|
if (!config.apiKey) {
|
|
329
346
|
api.log?.warn?.("[orgx] No API key. Set plugins.entries.orgx.config.apiKey, ORGX_API_KEY env, or ~/Code/orgx/orgx/.env.local");
|
|
330
347
|
}
|
|
@@ -350,14 +367,14 @@ export default function register(api) {
|
|
|
350
367
|
const defaultReportingCorrelationId = pickNonEmptyString(process.env.ORGX_CORRELATION_ID) ??
|
|
351
368
|
`openclaw-${config.installationId}`;
|
|
352
369
|
function resolveReportingContext(input) {
|
|
353
|
-
const initiativeId = pickNonEmptyString(input.initiative_id, process.env.ORGX_INITIATIVE_ID);
|
|
370
|
+
const initiativeId = pickNonEmptyString(input.initiative_id, input.initiativeId, process.env.ORGX_INITIATIVE_ID);
|
|
354
371
|
if (!initiativeId || !isUuid(initiativeId)) {
|
|
355
372
|
return {
|
|
356
373
|
ok: false,
|
|
357
374
|
error: "initiative_id is required (set ORGX_INITIATIVE_ID or pass initiative_id).",
|
|
358
375
|
};
|
|
359
376
|
}
|
|
360
|
-
const sourceCandidate = pickNonEmptyString(input.source_client, process.env.ORGX_SOURCE_CLIENT, "openclaw");
|
|
377
|
+
const sourceCandidate = pickNonEmptyString(input.source_client, input.sourceClient, process.env.ORGX_SOURCE_CLIENT, "openclaw");
|
|
361
378
|
const sourceClient = sourceCandidate === "codex" ||
|
|
362
379
|
sourceCandidate === "claude-code" ||
|
|
363
380
|
sourceCandidate === "api" ||
|
|
@@ -368,7 +385,10 @@ export default function register(api) {
|
|
|
368
385
|
const runId = isUuid(runIdCandidate) ? runIdCandidate : undefined;
|
|
369
386
|
const correlationId = runId
|
|
370
387
|
? undefined
|
|
371
|
-
: pickNonEmptyString(input.correlation_id,
|
|
388
|
+
: pickNonEmptyString(input.correlation_id, input.correlationId,
|
|
389
|
+
// Legacy: some buffered payloads only stored a local `runId` which is
|
|
390
|
+
// better treated as a correlation key than a server-backed run_id.
|
|
391
|
+
input.runId, defaultReportingCorrelationId, `openclaw-${Date.now()}`);
|
|
372
392
|
return {
|
|
373
393
|
ok: true,
|
|
374
394
|
value: {
|
|
@@ -391,6 +411,140 @@ export default function register(api) {
|
|
|
391
411
|
return err.message;
|
|
392
412
|
return typeof err === "string" ? err : "Unexpected error";
|
|
393
413
|
}
|
|
414
|
+
const registerTool = api.registerTool.bind(api);
|
|
415
|
+
api.registerTool = (tool, options) => {
|
|
416
|
+
const toolName = tool.name;
|
|
417
|
+
const optional = Boolean(options?.optional);
|
|
418
|
+
registerTool({
|
|
419
|
+
...tool,
|
|
420
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
421
|
+
execute: async (callId, params) => {
|
|
422
|
+
const startedAt = Date.now();
|
|
423
|
+
void posthogCapture({
|
|
424
|
+
event: "openclaw_tool_called",
|
|
425
|
+
distinctId: config.installationId,
|
|
426
|
+
properties: {
|
|
427
|
+
tool_name: toolName,
|
|
428
|
+
tool_optional: optional,
|
|
429
|
+
call_id: callId,
|
|
430
|
+
plugin_version: config.pluginVersion,
|
|
431
|
+
},
|
|
432
|
+
}).catch(() => {
|
|
433
|
+
// best effort
|
|
434
|
+
});
|
|
435
|
+
try {
|
|
436
|
+
const result = await tool.execute(callId, params);
|
|
437
|
+
const durationMs = Date.now() - startedAt;
|
|
438
|
+
void posthogCapture({
|
|
439
|
+
event: "openclaw_tool_succeeded",
|
|
440
|
+
distinctId: config.installationId,
|
|
441
|
+
properties: {
|
|
442
|
+
tool_name: toolName,
|
|
443
|
+
tool_optional: optional,
|
|
444
|
+
call_id: callId,
|
|
445
|
+
duration_ms: durationMs,
|
|
446
|
+
plugin_version: config.pluginVersion,
|
|
447
|
+
},
|
|
448
|
+
}).catch(() => {
|
|
449
|
+
// best effort
|
|
450
|
+
});
|
|
451
|
+
return result;
|
|
452
|
+
}
|
|
453
|
+
catch (err) {
|
|
454
|
+
const durationMs = Date.now() - startedAt;
|
|
455
|
+
void posthogCapture({
|
|
456
|
+
event: "openclaw_tool_failed",
|
|
457
|
+
distinctId: config.installationId,
|
|
458
|
+
properties: {
|
|
459
|
+
tool_name: toolName,
|
|
460
|
+
tool_optional: optional,
|
|
461
|
+
call_id: callId,
|
|
462
|
+
duration_ms: durationMs,
|
|
463
|
+
plugin_version: config.pluginVersion,
|
|
464
|
+
error: toErrorMessage(err),
|
|
465
|
+
},
|
|
466
|
+
}).catch(() => {
|
|
467
|
+
// best effort
|
|
468
|
+
});
|
|
469
|
+
throw err;
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
}, options);
|
|
473
|
+
};
|
|
474
|
+
const registerService = api.registerService.bind(api);
|
|
475
|
+
api.registerService = (service) => {
|
|
476
|
+
registerService({
|
|
477
|
+
...service,
|
|
478
|
+
start: async () => {
|
|
479
|
+
const startedAt = Date.now();
|
|
480
|
+
try {
|
|
481
|
+
await service.start();
|
|
482
|
+
const durationMs = Date.now() - startedAt;
|
|
483
|
+
void posthogCapture({
|
|
484
|
+
event: "openclaw_service_started",
|
|
485
|
+
distinctId: config.installationId,
|
|
486
|
+
properties: {
|
|
487
|
+
service_id: service.id,
|
|
488
|
+
duration_ms: durationMs,
|
|
489
|
+
plugin_version: config.pluginVersion,
|
|
490
|
+
},
|
|
491
|
+
}).catch(() => {
|
|
492
|
+
// best effort
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
catch (err) {
|
|
496
|
+
const durationMs = Date.now() - startedAt;
|
|
497
|
+
void posthogCapture({
|
|
498
|
+
event: "openclaw_service_start_failed",
|
|
499
|
+
distinctId: config.installationId,
|
|
500
|
+
properties: {
|
|
501
|
+
service_id: service.id,
|
|
502
|
+
duration_ms: durationMs,
|
|
503
|
+
plugin_version: config.pluginVersion,
|
|
504
|
+
error: toErrorMessage(err),
|
|
505
|
+
},
|
|
506
|
+
}).catch(() => {
|
|
507
|
+
// best effort
|
|
508
|
+
});
|
|
509
|
+
throw err;
|
|
510
|
+
}
|
|
511
|
+
},
|
|
512
|
+
stop: async () => {
|
|
513
|
+
const startedAt = Date.now();
|
|
514
|
+
try {
|
|
515
|
+
await service.stop();
|
|
516
|
+
const durationMs = Date.now() - startedAt;
|
|
517
|
+
void posthogCapture({
|
|
518
|
+
event: "openclaw_service_stopped",
|
|
519
|
+
distinctId: config.installationId,
|
|
520
|
+
properties: {
|
|
521
|
+
service_id: service.id,
|
|
522
|
+
duration_ms: durationMs,
|
|
523
|
+
plugin_version: config.pluginVersion,
|
|
524
|
+
},
|
|
525
|
+
}).catch(() => {
|
|
526
|
+
// best effort
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
catch (err) {
|
|
530
|
+
const durationMs = Date.now() - startedAt;
|
|
531
|
+
void posthogCapture({
|
|
532
|
+
event: "openclaw_service_stop_failed",
|
|
533
|
+
distinctId: config.installationId,
|
|
534
|
+
properties: {
|
|
535
|
+
service_id: service.id,
|
|
536
|
+
duration_ms: durationMs,
|
|
537
|
+
plugin_version: config.pluginVersion,
|
|
538
|
+
error: toErrorMessage(err),
|
|
539
|
+
},
|
|
540
|
+
}).catch(() => {
|
|
541
|
+
// best effort
|
|
542
|
+
});
|
|
543
|
+
throw err;
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
});
|
|
547
|
+
};
|
|
394
548
|
function clearPairingState() {
|
|
395
549
|
activePairing = null;
|
|
396
550
|
updateOnboardingState({
|
|
@@ -474,6 +628,23 @@ export default function register(api) {
|
|
|
474
628
|
installationId: config.installationId,
|
|
475
629
|
workspaceName: input.workspaceName ?? onboardingState.workspaceName,
|
|
476
630
|
});
|
|
631
|
+
if (input.source === "browser_pairing" &&
|
|
632
|
+
process.env.ORGX_DISABLE_MCP_CLIENT_AUTOCONFIG !== "1") {
|
|
633
|
+
try {
|
|
634
|
+
const snapshot = readOpenClawSettingsSnapshot();
|
|
635
|
+
const port = readOpenClawGatewayPort(snapshot.raw);
|
|
636
|
+
const localMcpUrl = `http://127.0.0.1:${port}/orgx/mcp`;
|
|
637
|
+
void autoConfigureDetectedMcpClients({
|
|
638
|
+
localMcpUrl,
|
|
639
|
+
logger: api.log ?? {},
|
|
640
|
+
}).catch(() => {
|
|
641
|
+
// best effort
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
catch {
|
|
645
|
+
// best effort
|
|
646
|
+
}
|
|
647
|
+
}
|
|
477
648
|
}
|
|
478
649
|
// ---------------------------------------------------------------------------
|
|
479
650
|
// 1. Background Sync Service
|
|
@@ -481,7 +652,6 @@ export default function register(api) {
|
|
|
481
652
|
let syncTimer = null;
|
|
482
653
|
let syncInFlight = null;
|
|
483
654
|
let syncServiceRunning = false;
|
|
484
|
-
const outboxQueues = ["progress", "decisions", "artifacts"];
|
|
485
655
|
let outboxReplayState = {
|
|
486
656
|
status: "idle",
|
|
487
657
|
lastReplayAttemptAt: null,
|
|
@@ -661,7 +831,11 @@ export default function register(api) {
|
|
|
661
831
|
throw new Error(context.error);
|
|
662
832
|
}
|
|
663
833
|
const rawPhase = pickStringField(payload, "phase") ?? "implementing";
|
|
664
|
-
const progressPct = typeof payload.progress_pct === "number"
|
|
834
|
+
const progressPct = typeof payload.progress_pct === "number"
|
|
835
|
+
? payload.progress_pct
|
|
836
|
+
: typeof payload.progressPct === "number"
|
|
837
|
+
? payload.progressPct
|
|
838
|
+
: undefined;
|
|
665
839
|
const phase = rawPhase === "intent" ||
|
|
666
840
|
rawPhase === "execution" ||
|
|
667
841
|
rawPhase === "blocked" ||
|
|
@@ -670,7 +844,11 @@ export default function register(api) {
|
|
|
670
844
|
rawPhase === "completed"
|
|
671
845
|
? rawPhase
|
|
672
846
|
: toReportingPhase(rawPhase, progressPct);
|
|
673
|
-
|
|
847
|
+
const metaRaw = payload.metadata;
|
|
848
|
+
const meta = metaRaw && typeof metaRaw === "object" && !Array.isArray(metaRaw)
|
|
849
|
+
? metaRaw
|
|
850
|
+
: {};
|
|
851
|
+
const emitPayload = {
|
|
674
852
|
initiative_id: context.value.initiativeId,
|
|
675
853
|
run_id: context.value.runId,
|
|
676
854
|
correlation_id: context.value.correlationId,
|
|
@@ -679,12 +857,44 @@ export default function register(api) {
|
|
|
679
857
|
phase,
|
|
680
858
|
progress_pct: progressPct,
|
|
681
859
|
level: pickStringField(payload, "level"),
|
|
682
|
-
next_step: pickStringField(payload, "next_step") ??
|
|
860
|
+
next_step: pickStringField(payload, "next_step") ??
|
|
861
|
+
pickStringField(payload, "nextStep") ??
|
|
862
|
+
undefined,
|
|
683
863
|
metadata: {
|
|
864
|
+
...meta,
|
|
684
865
|
source: "orgx_openclaw_outbox_replay",
|
|
685
866
|
outbox_event_id: event.id,
|
|
686
867
|
},
|
|
687
|
-
}
|
|
868
|
+
};
|
|
869
|
+
try {
|
|
870
|
+
await client.emitActivity(emitPayload);
|
|
871
|
+
}
|
|
872
|
+
catch (err) {
|
|
873
|
+
// Some locally-buffered events carry a UUID that *looks* like an OrgX run_id
|
|
874
|
+
// but was only ever used as a local correlation/grouping key. If OrgX
|
|
875
|
+
// doesn't recognize it, retry by treating it as correlation_id so OrgX can
|
|
876
|
+
// create/attach a run deterministically.
|
|
877
|
+
const msg = toErrorMessage(err);
|
|
878
|
+
if (emitPayload.run_id &&
|
|
879
|
+
/^404\\b/.test(msg) &&
|
|
880
|
+
/\\brun\\b/i.test(msg) &&
|
|
881
|
+
/not found/i.test(msg)) {
|
|
882
|
+
await client.emitActivity({
|
|
883
|
+
...emitPayload,
|
|
884
|
+
run_id: undefined,
|
|
885
|
+
// Avoid passing a bare UUID as correlation_id since some server
|
|
886
|
+
// paths may interpret UUIDs as run_id lookups.
|
|
887
|
+
correlation_id: `openclaw:${emitPayload.run_id}`,
|
|
888
|
+
metadata: {
|
|
889
|
+
...emitPayload.metadata,
|
|
890
|
+
replay_run_id_as_correlation: true,
|
|
891
|
+
},
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
else {
|
|
895
|
+
throw err;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
688
898
|
return;
|
|
689
899
|
}
|
|
690
900
|
if (event.type === "decision") {
|
|
@@ -770,7 +980,14 @@ export default function register(api) {
|
|
|
770
980
|
};
|
|
771
981
|
let hadReplayFailure = false;
|
|
772
982
|
let lastReplayError = null;
|
|
773
|
-
|
|
983
|
+
// Outbox files are keyed by *session id* (e.g. initiative/run correlation),
|
|
984
|
+
// not by event type.
|
|
985
|
+
const outboxSummary = await readOutboxSummary();
|
|
986
|
+
const queues = Object.entries(outboxSummary.pendingByQueue)
|
|
987
|
+
.filter(([, count]) => typeof count === "number" && count > 0)
|
|
988
|
+
.map(([queueId]) => queueId)
|
|
989
|
+
.sort();
|
|
990
|
+
for (const queue of queues) {
|
|
774
991
|
const pending = await readOutbox(queue);
|
|
775
992
|
if (pending.length === 0) {
|
|
776
993
|
continue;
|
|
@@ -1215,8 +1432,13 @@ export default function register(api) {
|
|
|
1215
1432
|
// ---------------------------------------------------------------------------
|
|
1216
1433
|
// 2. MCP Tools (Model Context Protocol compatible)
|
|
1217
1434
|
// ---------------------------------------------------------------------------
|
|
1435
|
+
const mcpToolRegistry = new Map();
|
|
1436
|
+
const registerMcpTool = (tool, options) => {
|
|
1437
|
+
mcpToolRegistry.set(tool.name, tool);
|
|
1438
|
+
api.registerTool(tool, options);
|
|
1439
|
+
};
|
|
1218
1440
|
// --- orgx_status ---
|
|
1219
|
-
|
|
1441
|
+
registerMcpTool({
|
|
1220
1442
|
name: "orgx_status",
|
|
1221
1443
|
description: "Get current OrgX org status: active initiatives, agent states, pending decisions, active tasks.",
|
|
1222
1444
|
parameters: {
|
|
@@ -1236,7 +1458,7 @@ export default function register(api) {
|
|
|
1236
1458
|
},
|
|
1237
1459
|
}, { optional: true });
|
|
1238
1460
|
// --- orgx_sync ---
|
|
1239
|
-
|
|
1461
|
+
registerMcpTool({
|
|
1240
1462
|
name: "orgx_sync",
|
|
1241
1463
|
description: "Push/pull memory sync with OrgX. Send local memory/daily log; receive initiatives, tasks, decisions, model routing policy.",
|
|
1242
1464
|
parameters: {
|
|
@@ -1266,7 +1488,7 @@ export default function register(api) {
|
|
|
1266
1488
|
},
|
|
1267
1489
|
}, { optional: true });
|
|
1268
1490
|
// --- orgx_delegation_preflight ---
|
|
1269
|
-
|
|
1491
|
+
registerMcpTool({
|
|
1270
1492
|
name: "orgx_delegation_preflight",
|
|
1271
1493
|
description: "Run delegation preflight to score scope quality, estimate ETA/cost, and suggest a split before autonomous execution.",
|
|
1272
1494
|
parameters: {
|
|
@@ -1317,7 +1539,7 @@ export default function register(api) {
|
|
|
1317
1539
|
},
|
|
1318
1540
|
}, { optional: true });
|
|
1319
1541
|
// --- orgx_run_action ---
|
|
1320
|
-
|
|
1542
|
+
registerMcpTool({
|
|
1321
1543
|
name: "orgx_run_action",
|
|
1322
1544
|
description: "Apply a control action to a run: pause, resume, cancel, or rollback (rollback requires checkpointId).",
|
|
1323
1545
|
parameters: {
|
|
@@ -1361,7 +1583,7 @@ export default function register(api) {
|
|
|
1361
1583
|
},
|
|
1362
1584
|
}, { optional: true });
|
|
1363
1585
|
// --- orgx_checkpoints_list ---
|
|
1364
|
-
|
|
1586
|
+
registerMcpTool({
|
|
1365
1587
|
name: "orgx_checkpoints_list",
|
|
1366
1588
|
description: "List checkpoints for a run.",
|
|
1367
1589
|
parameters: {
|
|
@@ -1386,7 +1608,7 @@ export default function register(api) {
|
|
|
1386
1608
|
},
|
|
1387
1609
|
}, { optional: true });
|
|
1388
1610
|
// --- orgx_checkpoint_restore ---
|
|
1389
|
-
|
|
1611
|
+
registerMcpTool({
|
|
1390
1612
|
name: "orgx_checkpoint_restore",
|
|
1391
1613
|
description: "Restore a run to a specific checkpoint.",
|
|
1392
1614
|
parameters: {
|
|
@@ -1425,7 +1647,7 @@ export default function register(api) {
|
|
|
1425
1647
|
},
|
|
1426
1648
|
}, { optional: true });
|
|
1427
1649
|
// --- orgx_spawn_check ---
|
|
1428
|
-
|
|
1650
|
+
registerMcpTool({
|
|
1429
1651
|
name: "orgx_spawn_check",
|
|
1430
1652
|
description: "Check quality gate + get model routing before spawning a sub-agent. Returns allowed/denied, model tier, and check details.",
|
|
1431
1653
|
parameters: {
|
|
@@ -1454,7 +1676,7 @@ export default function register(api) {
|
|
|
1454
1676
|
},
|
|
1455
1677
|
}, { optional: true });
|
|
1456
1678
|
// --- orgx_quality_score ---
|
|
1457
|
-
|
|
1679
|
+
registerMcpTool({
|
|
1458
1680
|
name: "orgx_quality_score",
|
|
1459
1681
|
description: "Record a quality score (1-5) for completed agent work. Used to gate future spawns and track performance.",
|
|
1460
1682
|
parameters: {
|
|
@@ -1492,7 +1714,7 @@ export default function register(api) {
|
|
|
1492
1714
|
},
|
|
1493
1715
|
}, { optional: true });
|
|
1494
1716
|
// --- orgx_create_entity ---
|
|
1495
|
-
|
|
1717
|
+
registerMcpTool({
|
|
1496
1718
|
name: "orgx_create_entity",
|
|
1497
1719
|
description: "Create an OrgX entity (initiative, workstream, task, decision, milestone, etc.).",
|
|
1498
1720
|
parameters: {
|
|
@@ -1577,7 +1799,7 @@ export default function register(api) {
|
|
|
1577
1799
|
},
|
|
1578
1800
|
}, { optional: true });
|
|
1579
1801
|
// --- orgx_update_entity ---
|
|
1580
|
-
|
|
1802
|
+
registerMcpTool({
|
|
1581
1803
|
name: "orgx_update_entity",
|
|
1582
1804
|
description: "Update an existing OrgX entity by type and ID.",
|
|
1583
1805
|
parameters: {
|
|
@@ -1618,7 +1840,7 @@ export default function register(api) {
|
|
|
1618
1840
|
},
|
|
1619
1841
|
}, { optional: true });
|
|
1620
1842
|
// --- orgx_list_entities ---
|
|
1621
|
-
|
|
1843
|
+
registerMcpTool({
|
|
1622
1844
|
name: "orgx_list_entities",
|
|
1623
1845
|
description: "List OrgX entities of a given type with optional status filter.",
|
|
1624
1846
|
parameters: {
|
|
@@ -1760,7 +1982,7 @@ export default function register(api) {
|
|
|
1760
1982
|
}
|
|
1761
1983
|
}
|
|
1762
1984
|
// --- orgx_emit_activity ---
|
|
1763
|
-
|
|
1985
|
+
registerMcpTool({
|
|
1764
1986
|
name: "orgx_emit_activity",
|
|
1765
1987
|
description: "Emit append-only OrgX activity telemetry (launch reporting contract primary write tool).",
|
|
1766
1988
|
parameters: {
|
|
@@ -1820,7 +2042,7 @@ export default function register(api) {
|
|
|
1820
2042
|
},
|
|
1821
2043
|
}, { optional: true });
|
|
1822
2044
|
// --- orgx_apply_changeset ---
|
|
1823
|
-
|
|
2045
|
+
registerMcpTool({
|
|
1824
2046
|
name: "orgx_apply_changeset",
|
|
1825
2047
|
description: "Apply an idempotent transactional OrgX changeset (launch reporting contract primary mutation tool).",
|
|
1826
2048
|
parameters: {
|
|
@@ -1863,7 +2085,7 @@ export default function register(api) {
|
|
|
1863
2085
|
},
|
|
1864
2086
|
}, { optional: true });
|
|
1865
2087
|
// --- orgx_report_progress (alias -> orgx_emit_activity) ---
|
|
1866
|
-
|
|
2088
|
+
registerMcpTool({
|
|
1867
2089
|
name: "orgx_report_progress",
|
|
1868
2090
|
description: "Alias for orgx_emit_activity. Report progress at key milestones so the team can track your work.",
|
|
1869
2091
|
parameters: {
|
|
@@ -1926,7 +2148,7 @@ export default function register(api) {
|
|
|
1926
2148
|
},
|
|
1927
2149
|
}, { optional: true });
|
|
1928
2150
|
// --- orgx_request_decision (alias -> orgx_apply_changeset decision.create) ---
|
|
1929
|
-
|
|
2151
|
+
registerMcpTool({
|
|
1930
2152
|
name: "orgx_request_decision",
|
|
1931
2153
|
description: "Alias for orgx_apply_changeset with decision.create. Request a human decision before proceeding.",
|
|
1932
2154
|
parameters: {
|
|
@@ -2011,7 +2233,7 @@ export default function register(api) {
|
|
|
2011
2233
|
},
|
|
2012
2234
|
}, { optional: true });
|
|
2013
2235
|
// --- orgx_register_artifact ---
|
|
2014
|
-
|
|
2236
|
+
registerMcpTool({
|
|
2015
2237
|
name: "orgx_register_artifact",
|
|
2016
2238
|
description: "Register a work output (PR, document, config change, report, etc.) with OrgX. Makes it visible in the dashboard.",
|
|
2017
2239
|
parameters: {
|
|
@@ -2184,7 +2406,18 @@ export default function register(api) {
|
|
|
2184
2406
|
}, {
|
|
2185
2407
|
getHealth: async (input = {}) => buildHealthReport({ probeRemote: input.probeRemote === true }),
|
|
2186
2408
|
});
|
|
2187
|
-
|
|
2409
|
+
const mcpHttpHandler = createMcpHttpHandler({
|
|
2410
|
+
tools: mcpToolRegistry,
|
|
2411
|
+
logger: api.log ?? {},
|
|
2412
|
+
serverName: "@useorgx/openclaw-plugin",
|
|
2413
|
+
serverVersion: config.pluginVersion,
|
|
2414
|
+
});
|
|
2415
|
+
const compositeHttpHandler = async (req, res) => {
|
|
2416
|
+
if (await mcpHttpHandler(req, res))
|
|
2417
|
+
return true;
|
|
2418
|
+
return await httpHandler(req, res);
|
|
2419
|
+
};
|
|
2420
|
+
api.registerHttpHandler(compositeHttpHandler);
|
|
2188
2421
|
api.log?.info?.("[orgx] Plugin registered", {
|
|
2189
2422
|
baseUrl: config.baseUrl,
|
|
2190
2423
|
hasApiKey: !!config.apiKey,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Logger } from "./mcp-http-handler.js";
|
|
2
|
+
export declare function patchClaudeMcpConfig(input: {
|
|
3
|
+
current: Record<string, unknown>;
|
|
4
|
+
localMcpUrl: string;
|
|
5
|
+
}): {
|
|
6
|
+
updated: boolean;
|
|
7
|
+
next: Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
export declare function patchCursorMcpConfig(input: {
|
|
10
|
+
current: Record<string, unknown>;
|
|
11
|
+
localMcpUrl: string;
|
|
12
|
+
}): {
|
|
13
|
+
updated: boolean;
|
|
14
|
+
next: Record<string, unknown>;
|
|
15
|
+
};
|
|
16
|
+
export declare function patchCodexConfigToml(input: {
|
|
17
|
+
current: string;
|
|
18
|
+
localMcpUrl: string;
|
|
19
|
+
}): {
|
|
20
|
+
updated: boolean;
|
|
21
|
+
next: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function autoConfigureDetectedMcpClients(input: {
|
|
24
|
+
localMcpUrl: string;
|
|
25
|
+
logger?: Logger;
|
|
26
|
+
homeDir?: string;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
updatedPaths: string[];
|
|
29
|
+
skippedPaths: string[];
|
|
30
|
+
}>;
|