nextclaw 0.17.2 → 0.17.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +375 -168
- package/package.json +10 -10
- package/resources/USAGE.md +32 -14
- package/ui-dist/assets/ChannelsList-DZWam3Ob.js +8 -0
- package/ui-dist/assets/ChatPage-YBL7iJ1X.js +43 -0
- package/ui-dist/assets/{DocBrowser-DjcghYGO.js → DocBrowser-C7-1sXqo.js} +1 -1
- package/ui-dist/assets/DocBrowser-DQjtSsY3.js +1 -0
- package/ui-dist/assets/{DocBrowserContext-CLlq7rZQ.js → DocBrowserContext-DN5tjUoS.js} +1 -1
- package/ui-dist/assets/{LogoBadge-D_dOy5U3.js → LogoBadge-DDS1sU_U.js} +1 -1
- package/ui-dist/assets/{MarketplacePage-BlIeNn3x.js → MarketplacePage-2tWWgwAb.js} +1 -1
- package/ui-dist/assets/MarketplacePage-BorWJftJ.js +1 -0
- package/ui-dist/assets/{McpMarketplacePage-mz2_IX1O.js → McpMarketplacePage-N-fB4HID.js} +1 -1
- package/ui-dist/assets/ModelConfig-DvsBTUiE.js +1 -0
- package/ui-dist/assets/ProviderScopedModelInput-D9woCARc.js +1 -0
- package/ui-dist/assets/{ProvidersList-B0RCb_Vg.js → ProvidersList-D-qPGgC4.js} +1 -1
- package/ui-dist/assets/{RemoteAccessPage-CcfQjLtx.js → RemoteAccessPage-COnjm8_x.js} +1 -1
- package/ui-dist/assets/RuntimeConfig-BHpqcaHm.js +1 -0
- package/ui-dist/assets/SearchConfig-DIT6M65Q.js +1 -0
- package/ui-dist/assets/{SecretsConfig-DbiS3txa.js → SecretsConfig-Cefg1LFJ.js} +1 -1
- package/ui-dist/assets/{SessionsConfig-CbIOcAp8.js → SessionsConfig-BZnmVTIu.js} +1 -1
- package/ui-dist/assets/{book-open-BLxSL7Dk.js → book-open-DvWqOode.js} +1 -1
- package/ui-dist/assets/chat-session-display-D4bYa0b8.js +1 -0
- package/ui-dist/assets/{chunk-JZWAC4HX-Bp0t5xoO.js → chunk-JZWAC4HX-CxfKRD7X.js} +1 -1
- package/ui-dist/assets/{config-C96FWufn.js → config-BeGwf2Ao.js} +1 -1
- package/ui-dist/assets/{createLucideIcon-B_U7Nq4F.js → createLucideIcon-C7MmdIX3.js} +1 -1
- package/ui-dist/assets/{dist-D9pHzW9z.js → dist-B6VMuIQN.js} +1 -1
- package/ui-dist/assets/{dist-BFY-GyT4.js → dist-RWNFhxvR.js} +1 -1
- package/ui-dist/assets/{external-link-BydIQTIH.js → external-link-U86Acd1t.js} +1 -1
- package/ui-dist/assets/{hash-Djdf0x1C.js → hash-D-OVfV3Z.js} +1 -1
- package/ui-dist/assets/i18n-hM3v-3YG.js +1 -0
- package/ui-dist/assets/index-CpxuJa9o.css +1 -0
- package/ui-dist/assets/{index-DqSv8Azv.js → index-DHmCjcxq.js} +3 -3
- package/ui-dist/assets/{label-Bvv4Mrea.js → label-CHJ1ATds.js} +1 -1
- package/ui-dist/assets/loader-circle-C8cpaL0w.js +1 -0
- package/ui-dist/assets/{logos-CGJJRI5_.js → logos-U1_qDA3U.js} +1 -1
- package/ui-dist/assets/{page-layout-6Nm4Cnvr.js → page-layout-Z1klaUFW.js} +1 -1
- package/ui-dist/assets/plus-CrkO1kob.js +1 -0
- package/ui-dist/assets/{popover-b9rSYI6X.js → popover-xWbqMnIN.js} +1 -1
- package/ui-dist/assets/{react-CDZz_StC.js → react-3YE87-lE.js} +1 -1
- package/ui-dist/assets/{refresh-ccw-BvSSnnCw.js → refresh-ccw-JQh1lwq-.js} +1 -1
- package/ui-dist/assets/{save-CAf0_-b9.js → save-4VRlzkii.js} +1 -1
- package/ui-dist/assets/search-EX-Papzl.js +1 -0
- package/ui-dist/assets/{security-config-DF66-l25.js → security-config-DEgOD4VX.js} +1 -1
- package/ui-dist/assets/{select-CEIMqc0H.js → select-DF-AUoie.js} +1 -1
- package/ui-dist/assets/skeleton-B0mmt1vo.js +1 -0
- package/ui-dist/assets/{status-dot-CmQI5Qq2.js → status-dot-Bq_8Ojvv.js} +1 -1
- package/ui-dist/assets/{switch-B7SxDXyR.js → switch-D7JF_RZ-.js} +1 -1
- package/ui-dist/assets/{tabs-custom-Dxt6EJJW.js → tabs-custom-CLksZ2bO.js} +1 -1
- package/ui-dist/assets/{trash-2-BnQ1PDTw.js → trash-2-VV8jvziy.js} +1 -1
- package/ui-dist/assets/{useConfirmDialog-B-vMOmhG.js → useConfirmDialog-CuQqiPx7.js} +1 -1
- package/ui-dist/assets/{useMutation-Bi39Z9_J.js → useMutation-DBTWPbTg.js} +1 -1
- package/ui-dist/assets/x-B4sxJkGY.js +1 -0
- package/ui-dist/index.html +18 -18
- package/ui-dist/assets/ChannelsList-DekMP4a3.js +0 -8
- package/ui-dist/assets/ChatPage-Dgw4vlDt.js +0 -43
- package/ui-dist/assets/DocBrowser-CExjX5is.js +0 -1
- package/ui-dist/assets/MarketplacePage-DGfzg1LG.js +0 -1
- package/ui-dist/assets/ModelConfig-C_49_a9v.js +0 -1
- package/ui-dist/assets/RuntimeConfig-DBWzwoY-.js +0 -1
- package/ui-dist/assets/SearchConfig-jSdwlH4b.js +0 -1
- package/ui-dist/assets/chat-session-display-8yW6-mtm.js +0 -1
- package/ui-dist/assets/i18n-DAekxt_G.js +0 -1
- package/ui-dist/assets/index-CHEgQIiO.css +0 -1
- package/ui-dist/assets/loader-circle-CGXXikVG.js +0 -1
- package/ui-dist/assets/plus-CrW9BJDy.js +0 -1
- package/ui-dist/assets/provider-models-IJDA940D.js +0 -1
- package/ui-dist/assets/search-DgoXxocn.js +0 -1
- package/ui-dist/assets/skeleton-BiPUQkOD.js +0 -1
- package/ui-dist/assets/x-PBSiWt3l.js +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -2486,41 +2486,79 @@ var ChannelCommands = class {
|
|
|
2486
2486
|
function createCronService() {
|
|
2487
2487
|
return new CronService(join(getDataDir(), "cron", "jobs.json"));
|
|
2488
2488
|
}
|
|
2489
|
+
function readTrimmed(value) {
|
|
2490
|
+
if (typeof value !== "string") return;
|
|
2491
|
+
return value.trim() || void 0;
|
|
2492
|
+
}
|
|
2489
2493
|
function toSchedule(opts) {
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2494
|
+
const every = readTrimmed(opts.every);
|
|
2495
|
+
const cron = readTrimmed(opts.cron);
|
|
2496
|
+
const at = readTrimmed(opts.at);
|
|
2497
|
+
if ([
|
|
2498
|
+
every,
|
|
2499
|
+
cron,
|
|
2500
|
+
at
|
|
2501
|
+
].filter((value) => value !== void 0).length !== 1) return { error: "Error: Must specify exactly one of --every, --cron, or --at" };
|
|
2502
|
+
if (every) {
|
|
2503
|
+
const everySeconds = Number(every);
|
|
2504
|
+
if (!Number.isFinite(everySeconds) || everySeconds <= 0) return { error: "Error: --every must be a positive number of seconds" };
|
|
2505
|
+
return { schedule: {
|
|
2506
|
+
kind: "every",
|
|
2507
|
+
everyMs: everySeconds * 1e3
|
|
2508
|
+
} };
|
|
2509
|
+
}
|
|
2510
|
+
if (cron) return { schedule: {
|
|
2495
2511
|
kind: "cron",
|
|
2496
|
-
expr:
|
|
2497
|
-
};
|
|
2498
|
-
|
|
2512
|
+
expr: cron
|
|
2513
|
+
} };
|
|
2514
|
+
const atMs = Date.parse(String(at));
|
|
2515
|
+
if (!Number.isFinite(atMs)) return { error: "Error: --at must be a valid ISO datetime" };
|
|
2516
|
+
return { schedule: {
|
|
2499
2517
|
kind: "at",
|
|
2500
|
-
atMs
|
|
2501
|
-
};
|
|
2502
|
-
|
|
2518
|
+
atMs
|
|
2519
|
+
} };
|
|
2520
|
+
}
|
|
2521
|
+
function createCronCreateRequest(opts) {
|
|
2522
|
+
const name = readTrimmed(opts.name);
|
|
2523
|
+
const message = readTrimmed(opts.message);
|
|
2524
|
+
if (!name || !message) return { error: "Error: name and message are required" };
|
|
2525
|
+
const schedule = toSchedule(opts);
|
|
2526
|
+
if (!schedule.schedule) return { error: schedule.error ?? "Error: Must specify --every, --cron, or --at" };
|
|
2527
|
+
return { request: {
|
|
2528
|
+
name,
|
|
2529
|
+
message,
|
|
2530
|
+
schedule: schedule.schedule,
|
|
2531
|
+
agentId: readTrimmed(opts.agent),
|
|
2532
|
+
deliver: Boolean(opts.deliver),
|
|
2533
|
+
channel: readTrimmed(opts.channel),
|
|
2534
|
+
to: readTrimmed(opts.to),
|
|
2535
|
+
accountId: readTrimmed(opts.account)
|
|
2536
|
+
} };
|
|
2503
2537
|
}
|
|
2504
2538
|
var CronLocalService = class {
|
|
2505
2539
|
list = (all) => {
|
|
2506
2540
|
return createCronService().listJobs(all);
|
|
2507
2541
|
};
|
|
2542
|
+
addRequest = (request) => {
|
|
2543
|
+
return createCronService().addJob({
|
|
2544
|
+
name: request.name,
|
|
2545
|
+
schedule: request.schedule,
|
|
2546
|
+
message: request.message,
|
|
2547
|
+
agentId: request.agentId ?? void 0,
|
|
2548
|
+
deliver: request.deliver === true,
|
|
2549
|
+
channel: request.channel ?? void 0,
|
|
2550
|
+
to: request.to ?? void 0,
|
|
2551
|
+
accountId: request.accountId ?? void 0,
|
|
2552
|
+
deleteAfterRun: request.deleteAfterRun === true
|
|
2553
|
+
});
|
|
2554
|
+
};
|
|
2508
2555
|
add = (opts) => {
|
|
2509
|
-
const
|
|
2510
|
-
if (!
|
|
2556
|
+
const request = createCronCreateRequest(opts);
|
|
2557
|
+
if (!request.request) return {
|
|
2511
2558
|
job: null,
|
|
2512
|
-
error:
|
|
2559
|
+
error: request.error
|
|
2513
2560
|
};
|
|
2514
|
-
return { job:
|
|
2515
|
-
name: opts.name,
|
|
2516
|
-
schedule,
|
|
2517
|
-
message: opts.message,
|
|
2518
|
-
agentId: opts.agent,
|
|
2519
|
-
deliver: Boolean(opts.deliver),
|
|
2520
|
-
channel: opts.channel,
|
|
2521
|
-
to: opts.to,
|
|
2522
|
-
accountId: opts.account
|
|
2523
|
-
}) };
|
|
2561
|
+
return { job: this.addRequest(request.request) };
|
|
2524
2562
|
};
|
|
2525
2563
|
remove = (jobId) => {
|
|
2526
2564
|
return createCronService().removeJob(jobId);
|
|
@@ -2550,9 +2588,11 @@ function printCronJobs(jobs) {
|
|
|
2550
2588
|
//#region src/cli/commands/shared/ui-bridge-api.service.ts
|
|
2551
2589
|
function resolveManagedApiBase() {
|
|
2552
2590
|
const state = readServiceState();
|
|
2553
|
-
if (!state?.
|
|
2591
|
+
if (!state?.pid) return null;
|
|
2554
2592
|
if (!isProcessRunning(state.pid)) return null;
|
|
2555
|
-
return state.
|
|
2593
|
+
if (typeof state.uiUrl === "string" && state.uiUrl.trim().length > 0) return state.uiUrl.replace(/\/+$/, "");
|
|
2594
|
+
if (typeof state.apiUrl === "string" && state.apiUrl.trim().length > 0) return state.apiUrl.replace(/\/api\/?$/, "").replace(/\/+$/, "");
|
|
2595
|
+
return null;
|
|
2556
2596
|
}
|
|
2557
2597
|
var UiBridgeApiClient = class {
|
|
2558
2598
|
cookie;
|
|
@@ -2590,6 +2630,10 @@ var UiBridgeApiClient = class {
|
|
|
2590
2630
|
};
|
|
2591
2631
|
//#endregion
|
|
2592
2632
|
//#region src/cli/commands/cron.ts
|
|
2633
|
+
function readErrorMessage(error) {
|
|
2634
|
+
if (error instanceof Error && error.message.trim().length > 0) return error.message.trim();
|
|
2635
|
+
return String(error ?? "unknown error");
|
|
2636
|
+
}
|
|
2593
2637
|
var CronCommands = class {
|
|
2594
2638
|
constructor(local = new CronLocalService()) {
|
|
2595
2639
|
this.local = local;
|
|
@@ -2610,12 +2654,26 @@ var CronCommands = class {
|
|
|
2610
2654
|
printCronJobs(this.local.list(includeDisabled));
|
|
2611
2655
|
};
|
|
2612
2656
|
cronAdd = async (opts) => {
|
|
2613
|
-
const
|
|
2614
|
-
if (!
|
|
2615
|
-
console.error(
|
|
2657
|
+
const request = createCronCreateRequest(opts);
|
|
2658
|
+
if (!request.request) {
|
|
2659
|
+
console.error(request.error ?? "Error: Failed to add job");
|
|
2660
|
+
return;
|
|
2661
|
+
}
|
|
2662
|
+
const apiClient = this.createApiClient();
|
|
2663
|
+
if (apiClient) try {
|
|
2664
|
+
const data = await apiClient.request({
|
|
2665
|
+
path: "/api/cron",
|
|
2666
|
+
method: "POST",
|
|
2667
|
+
body: request.request
|
|
2668
|
+
});
|
|
2669
|
+
console.log(`✓ Added job '${data.job.name}' (${data.job.id})`);
|
|
2670
|
+
return;
|
|
2671
|
+
} catch (error) {
|
|
2672
|
+
console.error(`Error: ${readErrorMessage(error)}`);
|
|
2616
2673
|
return;
|
|
2617
2674
|
}
|
|
2618
|
-
|
|
2675
|
+
const job = this.local.addRequest(request.request);
|
|
2676
|
+
console.log(`✓ Added job '${job.name}' (${job.id})`);
|
|
2619
2677
|
};
|
|
2620
2678
|
cronRemove = async (jobId) => {
|
|
2621
2679
|
const apiClient = this.createApiClient();
|
|
@@ -2627,7 +2685,10 @@ var CronCommands = class {
|
|
|
2627
2685
|
console.log(`✓ Removed job ${jobId}`);
|
|
2628
2686
|
return;
|
|
2629
2687
|
}
|
|
2630
|
-
} catch {
|
|
2688
|
+
} catch (error) {
|
|
2689
|
+
console.error(`Error: ${readErrorMessage(error)}`);
|
|
2690
|
+
return;
|
|
2691
|
+
}
|
|
2631
2692
|
if (this.local.remove(jobId)) console.log(`✓ Removed job ${jobId}`);
|
|
2632
2693
|
else console.log(`Job ${jobId} not found`);
|
|
2633
2694
|
};
|
|
@@ -2644,7 +2705,10 @@ var CronCommands = class {
|
|
|
2644
2705
|
console.log(`✓ Job '${data.job.name}' ${opts.disable ? "disabled" : "enabled"}`);
|
|
2645
2706
|
return;
|
|
2646
2707
|
}
|
|
2647
|
-
} catch {
|
|
2708
|
+
} catch (error) {
|
|
2709
|
+
console.error(`Error: ${readErrorMessage(error)}`);
|
|
2710
|
+
return;
|
|
2711
|
+
}
|
|
2648
2712
|
const job = this.local.enable(jobId, enabled);
|
|
2649
2713
|
if (job) console.log(`✓ Job '${job.name}' ${opts.disable ? "disabled" : "enabled"}`);
|
|
2650
2714
|
else console.log(`Job ${jobId} not found`);
|
|
@@ -2659,12 +2723,128 @@ var CronCommands = class {
|
|
|
2659
2723
|
});
|
|
2660
2724
|
console.log(data.executed ? "✓ Job executed" : `Failed to run job ${jobId}`);
|
|
2661
2725
|
return;
|
|
2662
|
-
} catch {
|
|
2726
|
+
} catch (error) {
|
|
2727
|
+
console.error(`Error: ${readErrorMessage(error)}`);
|
|
2728
|
+
return;
|
|
2729
|
+
}
|
|
2663
2730
|
const ok = await this.local.run(jobId, Boolean(opts.force));
|
|
2664
2731
|
console.log(ok ? "✓ Job executed" : `Failed to run job ${jobId}`);
|
|
2665
2732
|
};
|
|
2666
2733
|
};
|
|
2667
2734
|
//#endregion
|
|
2735
|
+
//#region src/cli/commands/ncp/ui-ncp-runtime-registry.ts
|
|
2736
|
+
const DEFAULT_UI_NCP_RUNTIME_KIND = "native";
|
|
2737
|
+
function normalizeRuntimeKind(value) {
|
|
2738
|
+
if (typeof value !== "string") return null;
|
|
2739
|
+
const normalized = value.trim().toLowerCase();
|
|
2740
|
+
return normalized.length > 0 ? normalized : null;
|
|
2741
|
+
}
|
|
2742
|
+
function readRequestedRuntimeKind(sessionMetadata) {
|
|
2743
|
+
return normalizeRuntimeKind(sessionMetadata.runtime) ?? normalizeRuntimeKind(sessionMetadata.session_type) ?? normalizeRuntimeKind(sessionMetadata.sessionType) ?? null;
|
|
2744
|
+
}
|
|
2745
|
+
var UiNcpRuntimeRegistry = class {
|
|
2746
|
+
registrations = /* @__PURE__ */ new Map();
|
|
2747
|
+
constructor(defaultKind = DEFAULT_UI_NCP_RUNTIME_KIND) {
|
|
2748
|
+
this.defaultKind = defaultKind;
|
|
2749
|
+
}
|
|
2750
|
+
register(registration) {
|
|
2751
|
+
const normalizedKind = normalizeRuntimeKind(registration.kind);
|
|
2752
|
+
if (!normalizedKind) throw new Error("ui ncp runtime kind must be a non-empty string");
|
|
2753
|
+
const token = Symbol(normalizedKind);
|
|
2754
|
+
this.registrations.set(normalizedKind, {
|
|
2755
|
+
...registration,
|
|
2756
|
+
kind: normalizedKind,
|
|
2757
|
+
token
|
|
2758
|
+
});
|
|
2759
|
+
return toDisposable(() => {
|
|
2760
|
+
const current = this.registrations.get(normalizedKind);
|
|
2761
|
+
if (!current || current.token !== token) return;
|
|
2762
|
+
this.registrations.delete(normalizedKind);
|
|
2763
|
+
});
|
|
2764
|
+
}
|
|
2765
|
+
createRuntime(params) {
|
|
2766
|
+
const requestedKind = readRequestedRuntimeKind(params.sessionMetadata) ?? this.defaultKind;
|
|
2767
|
+
const registration = this.registrations.get(requestedKind);
|
|
2768
|
+
if (!registration) throw new Error(`ncp runtime unavailable: ${requestedKind}`);
|
|
2769
|
+
const nextSessionMetadata = {
|
|
2770
|
+
...params.sessionMetadata,
|
|
2771
|
+
session_type: registration.kind
|
|
2772
|
+
};
|
|
2773
|
+
params.setSessionMetadata(nextSessionMetadata);
|
|
2774
|
+
return registration.createRuntime({
|
|
2775
|
+
...params,
|
|
2776
|
+
sessionMetadata: nextSessionMetadata
|
|
2777
|
+
});
|
|
2778
|
+
}
|
|
2779
|
+
async listSessionTypes(params) {
|
|
2780
|
+
const options = await Promise.all([...this.registrations.values()].map(async (registration) => {
|
|
2781
|
+
const descriptor = await registration.describeSessionType?.(params);
|
|
2782
|
+
return {
|
|
2783
|
+
value: registration.kind,
|
|
2784
|
+
label: registration.label,
|
|
2785
|
+
ready: descriptor?.ready ?? true,
|
|
2786
|
+
reason: descriptor?.reason ?? null,
|
|
2787
|
+
reasonMessage: descriptor?.reasonMessage ?? null,
|
|
2788
|
+
recommendedModel: descriptor?.recommendedModel ?? null,
|
|
2789
|
+
cta: descriptor?.cta ?? null,
|
|
2790
|
+
...descriptor?.supportedModels ? { supportedModels: descriptor.supportedModels } : {}
|
|
2791
|
+
};
|
|
2792
|
+
}));
|
|
2793
|
+
return {
|
|
2794
|
+
defaultType: this.defaultKind,
|
|
2795
|
+
options: options.sort((left, right) => {
|
|
2796
|
+
if (left.value === this.defaultKind) return -1;
|
|
2797
|
+
if (right.value === this.defaultKind) return 1;
|
|
2798
|
+
return left.value.localeCompare(right.value);
|
|
2799
|
+
})
|
|
2800
|
+
};
|
|
2801
|
+
}
|
|
2802
|
+
};
|
|
2803
|
+
//#endregion
|
|
2804
|
+
//#region src/cli/commands/agent/agent-runtime.ts
|
|
2805
|
+
function createUnusedRuntime(_params) {
|
|
2806
|
+
throw new Error("runtime creation is not available during runtime listing");
|
|
2807
|
+
}
|
|
2808
|
+
async function listAvailableAgentRuntimes(params) {
|
|
2809
|
+
const config = loadConfig();
|
|
2810
|
+
const pluginRegistry = loadPluginRegistry(config, getWorkspacePath(config.agents.defaults.workspace));
|
|
2811
|
+
logPluginDiagnostics(pluginRegistry);
|
|
2812
|
+
const extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
2813
|
+
const runtimeRegistry = new UiNcpRuntimeRegistry(DEFAULT_UI_NCP_RUNTIME_KIND);
|
|
2814
|
+
const runtimeSourceByKind = /* @__PURE__ */ new Map();
|
|
2815
|
+
runtimeRegistry.register({
|
|
2816
|
+
kind: DEFAULT_UI_NCP_RUNTIME_KIND,
|
|
2817
|
+
label: "Native",
|
|
2818
|
+
createRuntime: createUnusedRuntime
|
|
2819
|
+
});
|
|
2820
|
+
runtimeSourceByKind.set(DEFAULT_UI_NCP_RUNTIME_KIND, { source: "builtin" });
|
|
2821
|
+
for (const registration of extensionRegistry.ncpAgentRuntimes) {
|
|
2822
|
+
runtimeRegistry.register({
|
|
2823
|
+
kind: registration.kind,
|
|
2824
|
+
label: registration.label,
|
|
2825
|
+
createRuntime: registration.createRuntime,
|
|
2826
|
+
describeSessionType: registration.describeSessionType
|
|
2827
|
+
});
|
|
2828
|
+
runtimeSourceByKind.set(registration.kind, {
|
|
2829
|
+
source: "plugin",
|
|
2830
|
+
pluginId: registration.pluginId
|
|
2831
|
+
});
|
|
2832
|
+
}
|
|
2833
|
+
const listed = await runtimeRegistry.listSessionTypes(params);
|
|
2834
|
+
return {
|
|
2835
|
+
defaultRuntime: listed.defaultType,
|
|
2836
|
+
runtimes: listed.options.map((runtime) => {
|
|
2837
|
+
const source = runtimeSourceByKind.get(runtime.value);
|
|
2838
|
+
return {
|
|
2839
|
+
...runtime,
|
|
2840
|
+
default: runtime.value === listed.defaultType,
|
|
2841
|
+
source: source?.source ?? "plugin",
|
|
2842
|
+
...source?.pluginId ? { pluginId: source.pluginId } : {}
|
|
2843
|
+
};
|
|
2844
|
+
})
|
|
2845
|
+
};
|
|
2846
|
+
}
|
|
2847
|
+
//#endregion
|
|
2668
2848
|
//#region src/cli/commands/agents.ts
|
|
2669
2849
|
var AgentCommands = class {
|
|
2670
2850
|
constructor(deps) {
|
|
@@ -2683,6 +2863,31 @@ var AgentCommands = class {
|
|
|
2683
2863
|
console.log(` description: ${agent.description ?? "-"}`);
|
|
2684
2864
|
console.log(` home: ${agent.workspace}`);
|
|
2685
2865
|
console.log(` avatar: ${agent.avatar ?? "-"}`);
|
|
2866
|
+
console.log(` runtime: ${agent.runtime ?? "-"}`);
|
|
2867
|
+
}
|
|
2868
|
+
};
|
|
2869
|
+
agentsRuntimes = async (opts = {}) => {
|
|
2870
|
+
const describeMode = opts.probe ? "probe" : "observation";
|
|
2871
|
+
const listed = await listAvailableAgentRuntimes({ describeMode });
|
|
2872
|
+
if (opts.json) {
|
|
2873
|
+
console.log(JSON.stringify({
|
|
2874
|
+
defaultRuntime: listed.defaultRuntime,
|
|
2875
|
+
describeMode,
|
|
2876
|
+
runtimes: listed.runtimes
|
|
2877
|
+
}, null, 2));
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2880
|
+
for (const runtime of listed.runtimes) {
|
|
2881
|
+
const head = runtime.default ? `${runtime.value} (default)` : runtime.value;
|
|
2882
|
+
console.log(head);
|
|
2883
|
+
console.log(` label: ${runtime.label}`);
|
|
2884
|
+
console.log(` source: ${runtime.source}`);
|
|
2885
|
+
if (runtime.pluginId) console.log(` pluginId: ${runtime.pluginId}`);
|
|
2886
|
+
console.log(` ready: ${runtime.ready === false ? "no" : "yes"}`);
|
|
2887
|
+
console.log(` reason: ${runtime.reason ?? "-"}`);
|
|
2888
|
+
console.log(` reasonMessage: ${runtime.reasonMessage ?? "-"}`);
|
|
2889
|
+
console.log(` recommendedModel: ${runtime.recommendedModel ?? "-"}`);
|
|
2890
|
+
console.log(` supportedModels: ${runtime.supportedModels?.join(", ") ?? "-"}`);
|
|
2686
2891
|
}
|
|
2687
2892
|
};
|
|
2688
2893
|
agentsNew = async (agentId, opts = {}) => {
|
|
@@ -2691,48 +2896,38 @@ var AgentCommands = class {
|
|
|
2691
2896
|
displayName: opts.name,
|
|
2692
2897
|
description: opts.description,
|
|
2693
2898
|
avatar: opts.avatar,
|
|
2694
|
-
home: opts.home
|
|
2899
|
+
home: opts.home,
|
|
2900
|
+
runtime: opts.runtime
|
|
2695
2901
|
}, { initializeHomeDirectory: this.deps.initializeAgentHomeDirectory });
|
|
2696
2902
|
if (opts.json) {
|
|
2697
|
-
console.log(JSON.stringify({
|
|
2698
|
-
agent: created,
|
|
2699
|
-
restartRequired: true
|
|
2700
|
-
}, null, 2));
|
|
2903
|
+
console.log(JSON.stringify({ agent: created }, null, 2));
|
|
2701
2904
|
return;
|
|
2702
2905
|
}
|
|
2703
|
-
await this.deps.requestRestart({
|
|
2704
|
-
reason: "agents-updated",
|
|
2705
|
-
manualMessage: `Created agent '${created.id}'. Restart ${this.deps.appName} to apply agent runtime changes.`
|
|
2706
|
-
});
|
|
2707
2906
|
console.log(`✓ Created agent ${created.id}`);
|
|
2708
2907
|
console.log(` name: ${created.displayName ?? "-"}`);
|
|
2709
2908
|
console.log(` description: ${created.description ?? "-"}`);
|
|
2710
2909
|
console.log(` home: ${created.workspace}`);
|
|
2711
2910
|
console.log(` avatar: ${created.avatar ?? "-"}`);
|
|
2911
|
+
console.log(` runtime: ${created.runtime ?? created.engine ?? "-"}`);
|
|
2712
2912
|
};
|
|
2713
2913
|
agentsUpdate = async (agentId, opts = {}) => {
|
|
2714
2914
|
const updated = updateAgentProfile({
|
|
2715
2915
|
id: agentId,
|
|
2716
2916
|
displayName: opts.name,
|
|
2717
2917
|
description: opts.description,
|
|
2718
|
-
avatar: opts.avatar
|
|
2918
|
+
avatar: opts.avatar,
|
|
2919
|
+
runtime: opts.runtime
|
|
2719
2920
|
});
|
|
2720
2921
|
if (opts.json) {
|
|
2721
|
-
console.log(JSON.stringify({
|
|
2722
|
-
agent: updated,
|
|
2723
|
-
restartRequired: true
|
|
2724
|
-
}, null, 2));
|
|
2922
|
+
console.log(JSON.stringify({ agent: updated }, null, 2));
|
|
2725
2923
|
return;
|
|
2726
2924
|
}
|
|
2727
|
-
await this.deps.requestRestart({
|
|
2728
|
-
reason: "agents-updated",
|
|
2729
|
-
manualMessage: `Updated agent '${updated.id}'. Restart ${this.deps.appName} to apply agent runtime changes.`
|
|
2730
|
-
});
|
|
2731
2925
|
console.log(`✓ Updated agent ${updated.id}`);
|
|
2732
2926
|
console.log(` name: ${updated.displayName ?? "-"}`);
|
|
2733
2927
|
console.log(` description: ${updated.description ?? "-"}`);
|
|
2734
2928
|
console.log(` home: ${updated.workspace}`);
|
|
2735
2929
|
console.log(` avatar: ${updated.avatar ?? "-"}`);
|
|
2930
|
+
console.log(` runtime: ${updated.runtime ?? updated.engine ?? "-"}`);
|
|
2736
2931
|
};
|
|
2737
2932
|
agentsRemove = async (agentId, opts = {}) => {
|
|
2738
2933
|
if (agentId.trim().toLowerCase() === BUILTIN_MAIN_AGENT_ID) throw new Error(`agent id '${BUILTIN_MAIN_AGENT_ID}' is reserved`);
|
|
@@ -2740,15 +2935,10 @@ var AgentCommands = class {
|
|
|
2740
2935
|
if (opts.json) {
|
|
2741
2936
|
console.log(JSON.stringify({
|
|
2742
2937
|
removed: true,
|
|
2743
|
-
agentId
|
|
2744
|
-
restartRequired: true
|
|
2938
|
+
agentId
|
|
2745
2939
|
}, null, 2));
|
|
2746
2940
|
return;
|
|
2747
2941
|
}
|
|
2748
|
-
await this.deps.requestRestart({
|
|
2749
|
-
reason: "agents-updated",
|
|
2750
|
-
manualMessage: `Removed agent '${agentId}'. Restart ${this.deps.appName} to apply agent runtime changes.`
|
|
2751
|
-
});
|
|
2752
2942
|
console.log(`✓ Removed agent ${agentId}`);
|
|
2753
2943
|
};
|
|
2754
2944
|
toAgentListEntry = (agent) => {
|
|
@@ -2758,6 +2948,7 @@ var AgentCommands = class {
|
|
|
2758
2948
|
description: agent.description ?? null,
|
|
2759
2949
|
avatar: agent.avatar ?? null,
|
|
2760
2950
|
workspace: agent.workspace,
|
|
2951
|
+
runtime: agent.runtime ?? agent.engine ?? null,
|
|
2761
2952
|
builtIn: agent.builtIn === true
|
|
2762
2953
|
};
|
|
2763
2954
|
};
|
|
@@ -4184,13 +4375,14 @@ async function startGatewaySupportServices(params) {
|
|
|
4184
4375
|
}
|
|
4185
4376
|
function watchCronStoreFile(params) {
|
|
4186
4377
|
const cronStorePath = resolve(params.cronStorePath);
|
|
4187
|
-
chokidar.watch(cronStorePath, {
|
|
4378
|
+
const watcher = chokidar.watch(cronStorePath, {
|
|
4188
4379
|
ignoreInitial: true,
|
|
4189
4380
|
awaitWriteFinish: {
|
|
4190
4381
|
stabilityThreshold: 200,
|
|
4191
4382
|
pollInterval: 50
|
|
4192
4383
|
}
|
|
4193
|
-
})
|
|
4384
|
+
});
|
|
4385
|
+
watcher.on("all", (event, changedPath) => {
|
|
4194
4386
|
if (resolve(changedPath) !== cronStorePath) return;
|
|
4195
4387
|
if (event === "add" || event === "change" || event === "unlink") try {
|
|
4196
4388
|
params.reloadCronStore();
|
|
@@ -4198,6 +4390,85 @@ function watchCronStoreFile(params) {
|
|
|
4198
4390
|
console.error(`Cron store reload failed (${event}): ${String(error)}`);
|
|
4199
4391
|
}
|
|
4200
4392
|
});
|
|
4393
|
+
return watcher;
|
|
4394
|
+
}
|
|
4395
|
+
function watchServiceConfigFile(params) {
|
|
4396
|
+
const configPath = resolve(params.configPath);
|
|
4397
|
+
const watcher = chokidar.watch(configPath, {
|
|
4398
|
+
ignoreInitial: true,
|
|
4399
|
+
awaitWriteFinish: {
|
|
4400
|
+
stabilityThreshold: 200,
|
|
4401
|
+
pollInterval: 50
|
|
4402
|
+
}
|
|
4403
|
+
});
|
|
4404
|
+
params.watcherRegistry.remember(watcher);
|
|
4405
|
+
watcher.on("all", (event, changedPath) => {
|
|
4406
|
+
if (resolve(changedPath) !== configPath) return;
|
|
4407
|
+
if (event === "add") {
|
|
4408
|
+
params.scheduleReload("config add");
|
|
4409
|
+
return;
|
|
4410
|
+
}
|
|
4411
|
+
if (event === "change") {
|
|
4412
|
+
params.scheduleReload("config change");
|
|
4413
|
+
return;
|
|
4414
|
+
}
|
|
4415
|
+
if (event === "unlink") params.scheduleReload("config unlink");
|
|
4416
|
+
});
|
|
4417
|
+
}
|
|
4418
|
+
var ServiceFileWatcherRegistry = class {
|
|
4419
|
+
watchers = [];
|
|
4420
|
+
remember = (watcher) => {
|
|
4421
|
+
this.watchers.push(watcher);
|
|
4422
|
+
};
|
|
4423
|
+
clear = async () => {
|
|
4424
|
+
const watchers = this.watchers.splice(0);
|
|
4425
|
+
await Promise.allSettled(watchers.map(async (watcher) => {
|
|
4426
|
+
try {
|
|
4427
|
+
await watcher.close();
|
|
4428
|
+
} catch {}
|
|
4429
|
+
}));
|
|
4430
|
+
};
|
|
4431
|
+
};
|
|
4432
|
+
function writeLocalServiceDiscoveryState(uiConfig, pid = process.pid) {
|
|
4433
|
+
const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
|
|
4434
|
+
const apiUrl = `${uiUrl}/api`;
|
|
4435
|
+
const existing = readServiceState();
|
|
4436
|
+
writeServiceState({
|
|
4437
|
+
pid,
|
|
4438
|
+
startedAt: existing?.pid === pid && typeof existing.startedAt === "string" ? existing.startedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
4439
|
+
uiUrl,
|
|
4440
|
+
apiUrl,
|
|
4441
|
+
uiHost: uiConfig.host,
|
|
4442
|
+
uiPort: uiConfig.port,
|
|
4443
|
+
logPath: existing?.logPath ?? resolveServiceLogPath(),
|
|
4444
|
+
startupState: existing?.startupState ?? "ready",
|
|
4445
|
+
startupLastProbeError: existing?.startupLastProbeError ?? null,
|
|
4446
|
+
startupTimeoutMs: existing?.startupTimeoutMs,
|
|
4447
|
+
startupCheckedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4448
|
+
...existing?.remote ? { remote: existing.remote } : {}
|
|
4449
|
+
});
|
|
4450
|
+
}
|
|
4451
|
+
function clearOwnedServiceState(pid = process.pid) {
|
|
4452
|
+
if (readServiceState()?.pid === pid) clearServiceState();
|
|
4453
|
+
}
|
|
4454
|
+
function finalizeLocalUiStartup(params) {
|
|
4455
|
+
const { setUiEventPublisher, uiConfig, uiStartup } = params;
|
|
4456
|
+
setUiEventPublisher(uiStartup?.publish);
|
|
4457
|
+
if (uiStartup) writeLocalServiceDiscoveryState(uiConfig);
|
|
4458
|
+
}
|
|
4459
|
+
async function startGatewayRuntimeSupport(params) {
|
|
4460
|
+
const { cronJobs, cronStorePath, reloadCronStore, remoteModule, startCron, startHeartbeat, watchConfigFile, watcherRegistry } = params;
|
|
4461
|
+
await startGatewaySupportServices({
|
|
4462
|
+
cronJobs,
|
|
4463
|
+
remoteModule,
|
|
4464
|
+
watchConfigFile,
|
|
4465
|
+
startCron,
|
|
4466
|
+
startHeartbeat
|
|
4467
|
+
});
|
|
4468
|
+
watcherRegistry.remember(watchCronStoreFile({
|
|
4469
|
+
cronStorePath,
|
|
4470
|
+
reloadCronStore
|
|
4471
|
+
}));
|
|
4201
4472
|
}
|
|
4202
4473
|
//#endregion
|
|
4203
4474
|
//#region src/cli/commands/remote-support/remote-access-service-control.ts
|
|
@@ -4998,6 +5269,10 @@ var SpawnChildSessionTool = class extends Tool {
|
|
|
4998
5269
|
type: "string",
|
|
4999
5270
|
description: "Optional model override used only for the child session."
|
|
5000
5271
|
},
|
|
5272
|
+
runtime: {
|
|
5273
|
+
type: "string",
|
|
5274
|
+
description: "Optional runtime override used only for the child session, for example native or codex."
|
|
5275
|
+
},
|
|
5001
5276
|
agentId: {
|
|
5002
5277
|
type: "string",
|
|
5003
5278
|
description: "Optional target agent id for the child session. Omit to use the default agent for that child."
|
|
@@ -5020,6 +5295,7 @@ var SpawnChildSessionTool = class extends Tool {
|
|
|
5020
5295
|
task,
|
|
5021
5296
|
title: readOptionalString$4(params, "label"),
|
|
5022
5297
|
model: readOptionalString$4(params, "model"),
|
|
5298
|
+
runtime: readOptionalString$4(params, "runtime"),
|
|
5023
5299
|
handoffDepth: this.handoffDepth,
|
|
5024
5300
|
agentId: readOptionalString$4(params, "agentId")
|
|
5025
5301
|
});
|
|
@@ -5141,6 +5417,10 @@ var SessionSpawnTool = class extends Tool {
|
|
|
5141
5417
|
type: "string",
|
|
5142
5418
|
description: "Optional model override for the new session."
|
|
5143
5419
|
},
|
|
5420
|
+
runtime: {
|
|
5421
|
+
type: "string",
|
|
5422
|
+
description: "Optional runtime override for the new session, for example native or codex."
|
|
5423
|
+
},
|
|
5144
5424
|
agentId: {
|
|
5145
5425
|
type: "string",
|
|
5146
5426
|
description: "Optional target agent id for the new session. Omit to use the default agent."
|
|
@@ -5160,7 +5440,8 @@ var SessionSpawnTool = class extends Tool {
|
|
|
5160
5440
|
title: readOptionalString$3(params.title),
|
|
5161
5441
|
sourceSessionMetadata: this.sourceSessionMetadata,
|
|
5162
5442
|
agentId: readOptionalString$3(params.agentId),
|
|
5163
|
-
model: readOptionalString$3(params.model)
|
|
5443
|
+
model: readOptionalString$3(params.model),
|
|
5444
|
+
runtime: readOptionalString$3(params.runtime)
|
|
5164
5445
|
});
|
|
5165
5446
|
return {
|
|
5166
5447
|
kind: "nextclaw.session",
|
|
@@ -5429,6 +5710,7 @@ function prependRequestedSkills(content, requestedSkillNames) {
|
|
|
5429
5710
|
function buildSessionOrchestrationSection() {
|
|
5430
5711
|
return [
|
|
5431
5712
|
"## Session Orchestration",
|
|
5713
|
+
"- Before passing a non-default `runtime` to `spawn`, `sessions_spawn`, or agent creation/update flows, inspect the installed runtime kinds with `nextclaw agents runtimes --json`.",
|
|
5432
5714
|
"- `spawn` creates a child session, starts the delegated task there immediately, and returns a running child-session handle right away instead of waiting for the child to finish.",
|
|
5433
5715
|
"- When that child reaches its final reply, `spawn` writes the completed result back into the original tool call and resumes the current session with the child's result.",
|
|
5434
5716
|
"- Use `spawn` when the work is a subtask of the current flow and the user expects this session to pause now and then continue after that child finishes.",
|
|
@@ -5946,6 +6228,7 @@ function summarizeTask(task) {
|
|
|
5946
6228
|
function cloneInheritedMetadata(sourceMetadata) {
|
|
5947
6229
|
const nextMetadata = {};
|
|
5948
6230
|
for (const key of [
|
|
6231
|
+
"runtime",
|
|
5949
6232
|
"session_type",
|
|
5950
6233
|
"preferred_model",
|
|
5951
6234
|
"preferred_thinking",
|
|
@@ -5970,10 +6253,11 @@ function resolveSessionTitle(params) {
|
|
|
5970
6253
|
return readOptionalString$2(params.title) ?? summarizeTask(params.task);
|
|
5971
6254
|
}
|
|
5972
6255
|
function resolveSessionType(params) {
|
|
5973
|
-
return readOptionalString$2(params.sessionType) ?? readOptionalString$2(params.metadata.session_type) ?? DEFAULT_SESSION_TYPE;
|
|
6256
|
+
return readOptionalString$2(params.runtime) ?? readOptionalString$2(params.metadata.runtime) ?? readOptionalString$2(params.sessionType) ?? readOptionalString$2(params.metadata.session_type) ?? DEFAULT_SESSION_TYPE;
|
|
5974
6257
|
}
|
|
5975
6258
|
function applySessionOverrides(params) {
|
|
5976
6259
|
params.metadata.session_type = params.sessionType;
|
|
6260
|
+
params.metadata.runtime = params.sessionType;
|
|
5977
6261
|
params.metadata[SESSION_METADATA_LABEL_KEY] = params.title;
|
|
5978
6262
|
params.metadata[CHILD_SESSION_LIFECYCLE_METADATA_KEY] = params.lifecycle;
|
|
5979
6263
|
if (params.parentSessionId) {
|
|
@@ -6013,6 +6297,7 @@ var SessionCreationService = class {
|
|
|
6013
6297
|
const parentSessionId = readOptionalString$2(params.parentSessionId);
|
|
6014
6298
|
const requestId = readOptionalString$2(params.requestId);
|
|
6015
6299
|
const sessionType = resolveSessionType({
|
|
6300
|
+
runtime: params.runtime,
|
|
6016
6301
|
sessionType: params.sessionType,
|
|
6017
6302
|
metadata
|
|
6018
6303
|
});
|
|
@@ -6036,7 +6321,7 @@ var SessionCreationService = class {
|
|
|
6036
6321
|
sessionId,
|
|
6037
6322
|
agentId: resolvedAgentId,
|
|
6038
6323
|
sessionType,
|
|
6039
|
-
runtimeFamily: "native",
|
|
6324
|
+
runtimeFamily: sessionType === DEFAULT_SESSION_TYPE ? "native" : "external",
|
|
6040
6325
|
...parentSessionId ? { parentSessionId } : {},
|
|
6041
6326
|
...requestId ? { spawnedByRequestId: requestId } : {},
|
|
6042
6327
|
lifecycle: DEFAULT_LIFECYCLE,
|
|
@@ -6189,7 +6474,7 @@ var SessionRequestBroker = class {
|
|
|
6189
6474
|
this.onSessionUpdated = onSessionUpdated;
|
|
6190
6475
|
}
|
|
6191
6476
|
spawnChildSessionAndRequest = async (params) => {
|
|
6192
|
-
const { sourceSessionId, sourceToolCallId, sourceSessionMetadata, task, title, model, handoffDepth, sessionType, thinkingLevel, projectRoot, agentId } = params;
|
|
6477
|
+
const { sourceSessionId, sourceToolCallId, sourceSessionMetadata, task, title, model, runtime, handoffDepth, sessionType, thinkingLevel, projectRoot, agentId } = params;
|
|
6193
6478
|
const requestId = randomUUID();
|
|
6194
6479
|
const childSession = this.sessionCreationService.createChildSession({
|
|
6195
6480
|
parentSessionId: sourceSessionId,
|
|
@@ -6198,6 +6483,7 @@ var SessionRequestBroker = class {
|
|
|
6198
6483
|
sourceSessionMetadata,
|
|
6199
6484
|
agentId,
|
|
6200
6485
|
model,
|
|
6486
|
+
runtime,
|
|
6201
6487
|
thinkingLevel,
|
|
6202
6488
|
sessionType,
|
|
6203
6489
|
projectRoot,
|
|
@@ -6499,75 +6785,6 @@ var SessionRequestDeliveryService = class {
|
|
|
6499
6785
|
};
|
|
6500
6786
|
};
|
|
6501
6787
|
//#endregion
|
|
6502
|
-
//#region src/cli/commands/ncp/ui-ncp-runtime-registry.ts
|
|
6503
|
-
const DEFAULT_UI_NCP_RUNTIME_KIND = "native";
|
|
6504
|
-
function normalizeRuntimeKind(value) {
|
|
6505
|
-
if (typeof value !== "string") return null;
|
|
6506
|
-
const normalized = value.trim().toLowerCase();
|
|
6507
|
-
return normalized.length > 0 ? normalized : null;
|
|
6508
|
-
}
|
|
6509
|
-
function readRequestedRuntimeKind(sessionMetadata) {
|
|
6510
|
-
return normalizeRuntimeKind(sessionMetadata.session_type) ?? normalizeRuntimeKind(sessionMetadata.sessionType) ?? null;
|
|
6511
|
-
}
|
|
6512
|
-
var UiNcpRuntimeRegistry = class {
|
|
6513
|
-
registrations = /* @__PURE__ */ new Map();
|
|
6514
|
-
constructor(defaultKind = DEFAULT_UI_NCP_RUNTIME_KIND) {
|
|
6515
|
-
this.defaultKind = defaultKind;
|
|
6516
|
-
}
|
|
6517
|
-
register(registration) {
|
|
6518
|
-
const normalizedKind = normalizeRuntimeKind(registration.kind);
|
|
6519
|
-
if (!normalizedKind) throw new Error("ui ncp runtime kind must be a non-empty string");
|
|
6520
|
-
const token = Symbol(normalizedKind);
|
|
6521
|
-
this.registrations.set(normalizedKind, {
|
|
6522
|
-
...registration,
|
|
6523
|
-
kind: normalizedKind,
|
|
6524
|
-
token
|
|
6525
|
-
});
|
|
6526
|
-
return toDisposable(() => {
|
|
6527
|
-
const current = this.registrations.get(normalizedKind);
|
|
6528
|
-
if (!current || current.token !== token) return;
|
|
6529
|
-
this.registrations.delete(normalizedKind);
|
|
6530
|
-
});
|
|
6531
|
-
}
|
|
6532
|
-
createRuntime(params) {
|
|
6533
|
-
const requestedKind = readRequestedRuntimeKind(params.sessionMetadata) ?? this.defaultKind;
|
|
6534
|
-
const registration = this.registrations.get(requestedKind);
|
|
6535
|
-
if (!registration) throw new Error(`ncp runtime unavailable: ${requestedKind}`);
|
|
6536
|
-
const nextSessionMetadata = {
|
|
6537
|
-
...params.sessionMetadata,
|
|
6538
|
-
session_type: registration.kind
|
|
6539
|
-
};
|
|
6540
|
-
params.setSessionMetadata(nextSessionMetadata);
|
|
6541
|
-
return registration.createRuntime({
|
|
6542
|
-
...params,
|
|
6543
|
-
sessionMetadata: nextSessionMetadata
|
|
6544
|
-
});
|
|
6545
|
-
}
|
|
6546
|
-
async listSessionTypes(params) {
|
|
6547
|
-
const options = await Promise.all([...this.registrations.values()].map(async (registration) => {
|
|
6548
|
-
const descriptor = await registration.describeSessionType?.(params);
|
|
6549
|
-
return {
|
|
6550
|
-
value: registration.kind,
|
|
6551
|
-
label: registration.label,
|
|
6552
|
-
ready: descriptor?.ready ?? true,
|
|
6553
|
-
reason: descriptor?.reason ?? null,
|
|
6554
|
-
reasonMessage: descriptor?.reasonMessage ?? null,
|
|
6555
|
-
recommendedModel: descriptor?.recommendedModel ?? null,
|
|
6556
|
-
cta: descriptor?.cta ?? null,
|
|
6557
|
-
...descriptor?.supportedModels ? { supportedModels: descriptor.supportedModels } : {}
|
|
6558
|
-
};
|
|
6559
|
-
}));
|
|
6560
|
-
return {
|
|
6561
|
-
defaultType: this.defaultKind,
|
|
6562
|
-
options: options.sort((left, right) => {
|
|
6563
|
-
if (left.value === this.defaultKind) return -1;
|
|
6564
|
-
if (right.value === this.defaultKind) return 1;
|
|
6565
|
-
return left.value.localeCompare(right.value);
|
|
6566
|
-
})
|
|
6567
|
-
};
|
|
6568
|
-
}
|
|
6569
|
-
};
|
|
6570
|
-
//#endregion
|
|
6571
6788
|
//#region src/cli/commands/ncp/runtime/ui-ncp-agent-handle.ts
|
|
6572
6789
|
function createUiNcpAgentHandle(params) {
|
|
6573
6790
|
return {
|
|
@@ -8664,11 +8881,13 @@ function createSkillsLoader(workspace) {
|
|
|
8664
8881
|
var ServiceCommands = class {
|
|
8665
8882
|
applyLiveConfigReload = null;
|
|
8666
8883
|
liveUiNcpAgent = null;
|
|
8884
|
+
fileWatchers = new ServiceFileWatcherRegistry();
|
|
8667
8885
|
constructor(deps) {
|
|
8668
8886
|
this.deps = deps;
|
|
8669
8887
|
}
|
|
8670
8888
|
startGateway = async (options = {}) => {
|
|
8671
8889
|
logStartupTrace("service.start_gateway.begin");
|
|
8890
|
+
await this.fileWatchers.clear();
|
|
8672
8891
|
this.applyLiveConfigReload = null;
|
|
8673
8892
|
this.liveUiNcpAgent = null;
|
|
8674
8893
|
const shellContext = measureStartupSync("service.create_gateway_shell_context", () => createGatewayShellContext({
|
|
@@ -8712,7 +8931,11 @@ var ServiceCommands = class {
|
|
|
8712
8931
|
ncpSessionService: ncpSessionRealtimeBridge.sessionService,
|
|
8713
8932
|
initializeAgentHomeDirectory: this.deps.initializeAgentHomeDirectory
|
|
8714
8933
|
}));
|
|
8715
|
-
|
|
8934
|
+
finalizeLocalUiStartup({
|
|
8935
|
+
uiStartup,
|
|
8936
|
+
setUiEventPublisher: (publish) => ncpSessionRealtimeBridge.setUiEventPublisher(publish),
|
|
8937
|
+
uiConfig: shellContext.uiConfig
|
|
8938
|
+
});
|
|
8716
8939
|
bootstrapStatus.markShellReady();
|
|
8717
8940
|
await setImmediate();
|
|
8718
8941
|
const gateway = measureStartupSync("service.create_gateway_startup_context", () => createGatewayStartupContext({
|
|
@@ -8746,17 +8969,20 @@ var ServiceCommands = class {
|
|
|
8746
8969
|
publishUiEvent: uiStartup?.publish
|
|
8747
8970
|
});
|
|
8748
8971
|
console.log("✓ Capability hydration: scheduled in background");
|
|
8749
|
-
await measureStartupAsync("service.start_gateway_support_services", async () => await
|
|
8972
|
+
await measureStartupAsync("service.start_gateway_support_services", async () => await startGatewayRuntimeSupport({
|
|
8750
8973
|
cronJobs: gateway.cron.status().jobs,
|
|
8751
8974
|
remoteModule: gateway.remoteModule,
|
|
8752
|
-
watchConfigFile: () =>
|
|
8975
|
+
watchConfigFile: () => watchServiceConfigFile({
|
|
8976
|
+
configPath: resolve(getConfigPath$1()),
|
|
8977
|
+
watcherRegistry: this.fileWatchers,
|
|
8978
|
+
scheduleReload: (reason) => gateway.reloader.scheduleReload(reason)
|
|
8979
|
+
}),
|
|
8753
8980
|
startCron: () => gateway.cron.start(),
|
|
8754
|
-
startHeartbeat: () => gateway.heartbeat.start()
|
|
8755
|
-
}));
|
|
8756
|
-
watchCronStoreFile({
|
|
8981
|
+
startHeartbeat: () => gateway.heartbeat.start(),
|
|
8757
8982
|
cronStorePath: resolve(join(NextclawCore.getDataDir(), "cron", "jobs.json")),
|
|
8758
|
-
reloadCronStore: () => gateway.cron.reloadFromStore()
|
|
8759
|
-
|
|
8983
|
+
reloadCronStore: () => gateway.cron.reloadFromStore(),
|
|
8984
|
+
watcherRegistry: this.fileWatchers
|
|
8985
|
+
}));
|
|
8760
8986
|
const deferredGatewayStartupHooks = createDeferredGatewayStartupHooks({
|
|
8761
8987
|
uiStartup,
|
|
8762
8988
|
gateway,
|
|
@@ -8804,6 +9030,8 @@ var ServiceCommands = class {
|
|
|
8804
9030
|
console.error(`Deferred startup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
8805
9031
|
},
|
|
8806
9032
|
cleanup: async () => {
|
|
9033
|
+
clearOwnedServiceState();
|
|
9034
|
+
await this.fileWatchers.clear();
|
|
8807
9035
|
this.applyLiveConfigReload = null;
|
|
8808
9036
|
this.liveUiNcpAgent = null;
|
|
8809
9037
|
ncpSessionRealtimeBridge.clear();
|
|
@@ -8819,27 +9047,6 @@ var ServiceCommands = class {
|
|
|
8819
9047
|
if (typeof value !== "string") return;
|
|
8820
9048
|
return value.trim() || void 0;
|
|
8821
9049
|
};
|
|
8822
|
-
watchConfigFile = (reloader) => {
|
|
8823
|
-
const configPath = resolve(getConfigPath$1());
|
|
8824
|
-
chokidar.watch(configPath, {
|
|
8825
|
-
ignoreInitial: true,
|
|
8826
|
-
awaitWriteFinish: {
|
|
8827
|
-
stabilityThreshold: 200,
|
|
8828
|
-
pollInterval: 50
|
|
8829
|
-
}
|
|
8830
|
-
}).on("all", (event, changedPath) => {
|
|
8831
|
-
if (resolve(changedPath) !== configPath) return;
|
|
8832
|
-
if (event === "add") {
|
|
8833
|
-
reloader.scheduleReload("config add");
|
|
8834
|
-
return;
|
|
8835
|
-
}
|
|
8836
|
-
if (event === "change") {
|
|
8837
|
-
reloader.scheduleReload("config change");
|
|
8838
|
-
return;
|
|
8839
|
-
}
|
|
8840
|
-
if (event === "unlink") reloader.scheduleReload("config unlink");
|
|
8841
|
-
});
|
|
8842
|
-
};
|
|
8843
9050
|
resolveMostRecentRoutableSessionKey = (sessionManager) => {
|
|
8844
9051
|
let best = null;
|
|
8845
9052
|
for (const session of sessionManager.listSessions()) {
|
|
@@ -9552,11 +9759,7 @@ var CliRuntime = class {
|
|
|
9552
9759
|
this.mcpCommands = measureStartupSync("cli.runtime.mcp_commands", () => new McpCommands());
|
|
9553
9760
|
this.secretsCommands = measureStartupSync("cli.runtime.secrets_commands", () => new SecretsCommands({ requestRestart: (params) => this.requestRestart(params) }));
|
|
9554
9761
|
this.pluginCommands = measureStartupSync("cli.runtime.plugin_commands", () => new PluginCommands());
|
|
9555
|
-
this.agentCommands = measureStartupSync("cli.runtime.agent_commands", () => new AgentCommands({
|
|
9556
|
-
requestRestart: (params) => this.requestRestart(params),
|
|
9557
|
-
initializeAgentHomeDirectory: (homeDirectory) => this.workspaceManager.createWorkspaceTemplates(homeDirectory),
|
|
9558
|
-
appName: APP_NAME
|
|
9559
|
-
}));
|
|
9762
|
+
this.agentCommands = measureStartupSync("cli.runtime.agent_commands", () => new AgentCommands({ initializeAgentHomeDirectory: (homeDirectory) => this.workspaceManager.createWorkspaceTemplates(homeDirectory) }));
|
|
9560
9763
|
this.channelCommands = measureStartupSync("cli.runtime.channel_commands", () => new ChannelCommands({
|
|
9561
9764
|
logo: this.logo,
|
|
9562
9765
|
getBridgeDir: () => this.workspaceManager.getBridgeDir(),
|
|
@@ -9959,6 +10162,9 @@ var CliRuntime = class {
|
|
|
9959
10162
|
agentsList = (opts = {}) => {
|
|
9960
10163
|
this.agentCommands.agentsList(opts);
|
|
9961
10164
|
};
|
|
10165
|
+
agentsRuntimes = async (opts = {}) => {
|
|
10166
|
+
await this.agentCommands.agentsRuntimes(opts);
|
|
10167
|
+
};
|
|
9962
10168
|
agentsNew = async (agentId, opts = {}) => {
|
|
9963
10169
|
await this.agentCommands.agentsNew(agentId, opts);
|
|
9964
10170
|
};
|
|
@@ -10120,8 +10326,9 @@ var CliRuntime = class {
|
|
|
10120
10326
|
function registerAgentsCommands(program, runtime) {
|
|
10121
10327
|
const agents = program.command("agents").description("Manage agents");
|
|
10122
10328
|
agents.command("list").description("List available agents").option("--json", "Output JSON", false).action((opts) => runtime.agentsList(opts));
|
|
10123
|
-
agents.command("
|
|
10124
|
-
agents.command("
|
|
10329
|
+
agents.command("runtimes").description("List available agent runtimes").option("--probe", "Actively probe runtime readiness", false).option("--json", "Output JSON", false).action(async (opts) => runtime.agentsRuntimes(opts));
|
|
10330
|
+
agents.command("new <agentId>").description("Create a new agent").option("--name <name>", "Agent display name").option("--description <description>", "Agent description").option("--avatar <avatar>", "Remote avatar URL or local image path").option("--home <path>", "Agent home directory").option("--runtime <runtime>", "Agent runtime kind, for example native or codex").option("--json", "Output JSON", false).action(async (agentId, opts) => runtime.agentsNew(agentId, opts));
|
|
10331
|
+
agents.command("update <agentId>").description("Update an existing agent").option("--name <name>", "Agent display name").option("--description <description>", "Agent description").option("--avatar <avatar>", "Remote avatar URL or local image path").option("--runtime <runtime>", "Agent runtime kind, for example native or codex").option("--json", "Output JSON", false).action(async (agentId, opts) => runtime.agentsUpdate(agentId, opts));
|
|
10125
10332
|
agents.command("remove <agentId>").description("Remove an agent").option("--json", "Output JSON", false).action(async (agentId, opts) => runtime.agentsRemove(agentId, opts));
|
|
10126
10333
|
}
|
|
10127
10334
|
//#endregion
|