nextclaw 0.35.0 → 0.36.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/dist/cli/app/index.js +163 -82
- package/dist/cli/app/index.js.map +1 -1
- package/package.json +14 -14
- package/resources/USAGE.md +63 -1
- package/ui-dist/assets/api-CVjdSvJk.js +13 -0
- package/ui-dist/assets/{appearance-settings-page-CfwDf9ag.js → appearance-settings-page-BOorfaUx.js} +1 -1
- package/ui-dist/assets/{channels-list-page-Dyn83ZlS.js → channels-list-page-DuZJvYB6.js} +1 -1
- package/ui-dist/assets/{chat-page-CL0IMvgF.js → chat-page-8PTMgI0t.js} +1 -1
- package/ui-dist/assets/{config-split-page-D4D4HFhq.js → config-split-page-UuhsVcQD.js} +1 -1
- package/ui-dist/assets/{confirm-dialog-Cv6-9Nnj.js → confirm-dialog-Bnosa8UF.js} +1 -1
- package/ui-dist/assets/{desktop-update-config-Bckgulvm.js → desktop-update-config-CM4lsX4R.js} +1 -1
- package/ui-dist/assets/{dist-BrRgjiq1.js → dist-D17RZAsz.js} +1 -1
- package/ui-dist/assets/{dist-Bh_tj3FN.js → dist-_zZ8P38T.js} +1 -1
- package/ui-dist/assets/{doc-browser-BlWjhmnM.js → doc-browser-CiLvybSC.js} +1 -1
- package/ui-dist/assets/{doc-browser-context-NGYa66Xg.js → doc-browser-context-CerkiK_N.js} +1 -1
- package/ui-dist/assets/doc-browser-z7vdH3Ez.js +1 -0
- package/ui-dist/assets/{form-actions-CeKgh4SQ.js → form-actions-Cmv23dN4.js} +1 -1
- package/ui-dist/assets/index-CWdgBpSc.css +1 -0
- package/ui-dist/assets/index-DlL8uKXu.js +109 -0
- package/ui-dist/assets/loader-circle-vUsFtTfb.js +1 -0
- package/ui-dist/assets/mcp-marketplace-page-BV8WB3_L.js +1 -0
- package/ui-dist/assets/{mcp-marketplace-page-DfNmMqKs.js → mcp-marketplace-page-DN_fqcLd.js} +1 -1
- package/ui-dist/assets/{model-config-page-DHzyDV5v.js → model-config-page-BxaeCMbJ.js} +1 -1
- package/ui-dist/assets/{navigation-link-CzGgQGi_.js → navigation-link-k9rsmtC4.js} +1 -1
- package/ui-dist/assets/plus-Dc760kHj.js +1 -0
- package/ui-dist/assets/{provider-scoped-model-input-CjrHwzFb.js → provider-scoped-model-input-DLSAB6a5.js} +1 -1
- package/ui-dist/assets/{providers-config-page-ZPvJWHFN.js → providers-config-page-DM5N0aeS.js} +1 -1
- package/ui-dist/assets/{react-BXRf96P-.js → react-BgRLh3ee.js} +1 -1
- package/ui-dist/assets/{refresh-cw-ChKuqgPR.js → refresh-cw-axvJLmRG.js} +1 -1
- package/ui-dist/assets/remote-Cj1GBMaN.js +1 -0
- package/ui-dist/assets/rotate-cw-CFByP2O8.js +1 -0
- package/ui-dist/assets/{runtime-config-page-CGpPQD8K.js → runtime-config-page-WNzZyjMW.js} +1 -1
- package/ui-dist/assets/{save-BWGNAKV5.js → save-DbR4SGk8.js} +1 -1
- package/ui-dist/assets/{search-DFcT_9wJ.js → search-M9lrb8id.js} +1 -1
- package/ui-dist/assets/{search-config-page-DBBzVAQZ.js → search-config-page-DmsID8FQ.js} +1 -1
- package/ui-dist/assets/{secrets-config-page-bnJ8sIB7.js → secrets-config-page-C10OwI0b.js} +1 -1
- package/ui-dist/assets/security-config-CvU5JxDT.js +1 -0
- package/ui-dist/assets/{select-BnNrv8si.js → select-D_YBzMdv.js} +1 -1
- package/ui-dist/assets/{settings-2-CFHrgKTX.js → settings-2-zy40UwTo.js} +1 -1
- package/ui-dist/assets/skeleton-BmAtzjDM.js +1 -0
- package/ui-dist/assets/{tag-chip-L5w4xfS7.js → tag-chip-D7QRdcph.js} +1 -1
- package/ui-dist/assets/x-D9Y9hf_r.js +1 -0
- package/ui-dist/index.html +19 -19
- package/ui-dist/assets/api-Dket1cmq.js +0 -13
- package/ui-dist/assets/doc-browser-Da9hDsoQ.js +0 -1
- package/ui-dist/assets/index-Bz5yNMXA.js +0 -109
- package/ui-dist/assets/index-DSLK7zgR.css +0 -1
- package/ui-dist/assets/loader-circle-DLp2jNIf.js +0 -1
- package/ui-dist/assets/mcp-marketplace-page-CIWbjXM8.js +0 -1
- package/ui-dist/assets/plus-Dfj3tJ_m.js +0 -1
- package/ui-dist/assets/remote-C2enAZbs.js +0 -1
- package/ui-dist/assets/rotate-cw-BGkZpcc7.js +0 -1
- package/ui-dist/assets/security-config-CfbXSpgX.js +0 -1
- package/ui-dist/assets/skeleton-tfWhGuJT.js +0 -1
- package/ui-dist/assets/x-BCSE3LCQ.js +0 -1
package/dist/cli/app/index.js
CHANGED
|
@@ -10,9 +10,9 @@ import path, { join, resolve } from "node:path";
|
|
|
10
10
|
import { tmpdir } from "node:os";
|
|
11
11
|
import "@nextclaw/server";
|
|
12
12
|
import { NextclawDistributionService, NextclawServiceRuntime, readLearningLoopRuntimeConfig } from "@nextclaw/service";
|
|
13
|
-
import { AppHomeService, AppInstanceStorageService, AppPublishService, AppPublishValidationService } from "@nextclaw/app-runtime";
|
|
14
|
-
import { McpServiceAppRuntimeService, buildServiceActionId, getServiceAppManifestPath, mergeServiceAppRuntimeActions, readServiceAppManifest } from "@nextclaw/kernel";
|
|
15
13
|
import { access, mkdtemp, readFile, rm, stat } from "node:fs/promises";
|
|
14
|
+
import { AppHomeService, AppInstanceInventoryService, AppInstanceStorageService, AppPublishService, AppPublishValidationService } from "@nextclaw/app-runtime";
|
|
15
|
+
import { McpServiceAppRuntimeService, buildServiceActionId, getServiceAppManifestPath, mergeServiceAppRuntimeActions, readServiceAppManifest } from "@nextclaw/kernel";
|
|
16
16
|
import { promisify } from "node:util";
|
|
17
17
|
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
18
18
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
@@ -3633,18 +3633,24 @@ const registerHostServiceControls = ({ program, nextclaw }) => {
|
|
|
3633
3633
|
//#endregion
|
|
3634
3634
|
//#region src/cli/app/services/service-app-dev.service.ts
|
|
3635
3635
|
var ServiceAppDevService = class {
|
|
3636
|
+
instanceInventoryService = new AppInstanceInventoryService();
|
|
3636
3637
|
instanceStorageService = new AppInstanceStorageService();
|
|
3637
3638
|
constructor(params = {}) {
|
|
3638
3639
|
this.params = params;
|
|
3639
3640
|
}
|
|
3640
|
-
inspect = async (target) => {
|
|
3641
|
+
inspect = async (target, options = {}) => {
|
|
3641
3642
|
const appPath = path.resolve(target);
|
|
3642
3643
|
const issues = [];
|
|
3643
3644
|
const loaded = await this.loadServiceApp(appPath, issues);
|
|
3644
3645
|
if (!loaded) return this.buildDevReport(appPath, void 0, [], issues);
|
|
3646
|
+
if (options.resetData && options.confirmAppId?.trim() !== loaded.manifest.id) issues.push({
|
|
3647
|
+
severity: "error",
|
|
3648
|
+
code: "service.data.confirmationMismatch",
|
|
3649
|
+
message: `--reset-data requires --confirm ${loaded.manifest.id}.`
|
|
3650
|
+
});
|
|
3645
3651
|
if (this.hasErrors(issues)) return this.buildDevReport(appPath, this.toServiceAppRecord(appPath, loaded.manifest, this.idleRuntimeStatus), [], issues);
|
|
3646
3652
|
const runtime = this.createRuntimeService();
|
|
3647
|
-
const storage = await this.createDevStorage(appPath, loaded.manifest.id);
|
|
3653
|
+
const storage = await this.createDevStorage(appPath, loaded.manifest.id, options.resetData === true);
|
|
3648
3654
|
try {
|
|
3649
3655
|
const startRecord = this.toServiceAppRecord(appPath, loaded.manifest, runtime, storage);
|
|
3650
3656
|
const runtimeActions = await runtime.listActions({
|
|
@@ -3732,15 +3738,36 @@ var ServiceAppDevService = class {
|
|
|
3732
3738
|
return resolveConfigSecrets(loadConfig(configPath), { configPath });
|
|
3733
3739
|
};
|
|
3734
3740
|
idleRuntimeStatus = { getStatus: () => ({ status: "idle" }) };
|
|
3735
|
-
createDevStorage = async (appPath, appId) => {
|
|
3736
|
-
const sourceId =
|
|
3737
|
-
const
|
|
3741
|
+
createDevStorage = async (appPath, appId, resetData = false) => {
|
|
3742
|
+
const sourceId = this.getSourceId(appPath);
|
|
3743
|
+
const appHomeDirectory = new AppHomeService().getAppHomeDirectory();
|
|
3744
|
+
const instanceDirectory = path.join(appHomeDirectory, "dev-instances", appId, sourceId, "default");
|
|
3745
|
+
if (resetData && await this.pathExists(instanceDirectory)) await this.instanceInventoryService.purgeNested({
|
|
3746
|
+
instancesRoot: appHomeDirectory,
|
|
3747
|
+
pathSegments: [
|
|
3748
|
+
"dev-instances",
|
|
3749
|
+
appId,
|
|
3750
|
+
sourceId,
|
|
3751
|
+
"default"
|
|
3752
|
+
],
|
|
3753
|
+
appId,
|
|
3754
|
+
instanceId: "default"
|
|
3755
|
+
});
|
|
3738
3756
|
return (await this.instanceStorageService.materialize({
|
|
3739
3757
|
appId,
|
|
3740
3758
|
instanceId: "default",
|
|
3741
3759
|
instanceDirectory
|
|
3742
3760
|
})).storage;
|
|
3743
3761
|
};
|
|
3762
|
+
getSourceId = (appPath) => createHash("sha256").update(appPath).digest("hex").slice(0, 16);
|
|
3763
|
+
pathExists = async (targetPath) => {
|
|
3764
|
+
try {
|
|
3765
|
+
await access(targetPath);
|
|
3766
|
+
return true;
|
|
3767
|
+
} catch {
|
|
3768
|
+
return false;
|
|
3769
|
+
}
|
|
3770
|
+
};
|
|
3744
3771
|
toServiceAppRecord = (dirPath, manifest, runtime, storage) => {
|
|
3745
3772
|
const runtimeStatus = runtime.getStatus(manifest.id);
|
|
3746
3773
|
const record = {
|
|
@@ -4417,7 +4444,10 @@ var AppDevCommandController = class {
|
|
|
4417
4444
|
this.serviceAppDevService = serviceAppDevService;
|
|
4418
4445
|
}
|
|
4419
4446
|
dev = async (target, options) => {
|
|
4420
|
-
const report = await this.serviceAppDevService.inspect(target
|
|
4447
|
+
const report = await this.serviceAppDevService.inspect(target, {
|
|
4448
|
+
resetData: options.resetData,
|
|
4449
|
+
confirmAppId: options.confirm
|
|
4450
|
+
});
|
|
4421
4451
|
process.stdout.write(options.json ? `${JSON.stringify(report, null, 2)}\n` : this.format(report));
|
|
4422
4452
|
if (!report.ok) process.exitCode = 1;
|
|
4423
4453
|
};
|
|
@@ -4440,6 +4470,125 @@ var AppDevCommandController = class {
|
|
|
4440
4470
|
};
|
|
4441
4471
|
};
|
|
4442
4472
|
//#endregion
|
|
4473
|
+
//#region src/cli/app/services/local-api/local-ui-api-client.service.ts
|
|
4474
|
+
function createLocalUiApiClient() {
|
|
4475
|
+
const apiBase = resolveLocalUiApiBase();
|
|
4476
|
+
return apiBase ? new LocalUiApiClient(apiBase) : null;
|
|
4477
|
+
}
|
|
4478
|
+
var LocalUiApiClient = class {
|
|
4479
|
+
cookie;
|
|
4480
|
+
constructor(apiBase) {
|
|
4481
|
+
this.apiBase = apiBase;
|
|
4482
|
+
}
|
|
4483
|
+
request = async (params) => {
|
|
4484
|
+
const { body, method, path } = params;
|
|
4485
|
+
const cookie = await this.getCookie();
|
|
4486
|
+
const headers = {};
|
|
4487
|
+
if (body) headers["Content-Type"] = "application/json";
|
|
4488
|
+
if (cookie) headers.Cookie = cookie;
|
|
4489
|
+
const response = await fetch(`${this.apiBase}${path}`, {
|
|
4490
|
+
method: method ?? "GET",
|
|
4491
|
+
headers,
|
|
4492
|
+
...body ? { body: JSON.stringify(body) } : {}
|
|
4493
|
+
});
|
|
4494
|
+
if (!response.ok) throw new Error(`api request failed with status ${response.status}`);
|
|
4495
|
+
const payload = await response.json();
|
|
4496
|
+
if (!payload.ok) throw new Error(payload.error?.message ?? "api request failed");
|
|
4497
|
+
return payload.data;
|
|
4498
|
+
};
|
|
4499
|
+
getCookie = async () => {
|
|
4500
|
+
if (this.cookie !== void 0) return this.cookie;
|
|
4501
|
+
const response = await fetch(`${this.apiBase}/api/auth/bridge`, {
|
|
4502
|
+
method: "POST",
|
|
4503
|
+
headers: { "x-nextclaw-ui-bridge-secret": ensureUiBridgeSecret() }
|
|
4504
|
+
});
|
|
4505
|
+
if (!response.ok) throw new Error(`bridge auth failed with status ${response.status}`);
|
|
4506
|
+
const payload = await response.json();
|
|
4507
|
+
if (!payload.ok) throw new Error(payload.error?.message ?? "bridge auth failed");
|
|
4508
|
+
this.cookie = typeof payload.data.cookie === "string" && payload.data.cookie.trim() ? payload.data.cookie.trim() : null;
|
|
4509
|
+
return this.cookie;
|
|
4510
|
+
};
|
|
4511
|
+
};
|
|
4512
|
+
function resolveLocalUiApiBase() {
|
|
4513
|
+
const state = readRunningRuntimeState(resolve(getRunPath(), "ui-runtime.json")) ?? readRunningRuntimeState(resolve(getRunPath(), "service.json"));
|
|
4514
|
+
if (!state) return null;
|
|
4515
|
+
if (typeof state.uiUrl === "string" && state.uiUrl.trim()) return state.uiUrl.replace(/\/+$/, "");
|
|
4516
|
+
if (typeof state.apiUrl === "string" && state.apiUrl.trim()) return state.apiUrl.replace(/\/api\/?$/, "").replace(/\/+$/, "");
|
|
4517
|
+
return null;
|
|
4518
|
+
}
|
|
4519
|
+
function readRunningRuntimeState(statePath) {
|
|
4520
|
+
if (!existsSync(statePath)) return null;
|
|
4521
|
+
try {
|
|
4522
|
+
const state = JSON.parse(readFileSync(statePath, "utf-8"));
|
|
4523
|
+
return typeof state.pid === "number" && isProcessRunning(state.pid) ? state : null;
|
|
4524
|
+
} catch {
|
|
4525
|
+
return null;
|
|
4526
|
+
}
|
|
4527
|
+
}
|
|
4528
|
+
function isProcessRunning(pid) {
|
|
4529
|
+
try {
|
|
4530
|
+
process.kill(pid, 0);
|
|
4531
|
+
return true;
|
|
4532
|
+
} catch {
|
|
4533
|
+
return false;
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4536
|
+
function ensureUiBridgeSecret() {
|
|
4537
|
+
const dirPath = join(getDataDir(), "remote");
|
|
4538
|
+
const secretPath = join(dirPath, "ui-bridge-secret");
|
|
4539
|
+
if (existsSync(secretPath)) {
|
|
4540
|
+
const existing = readFileSync(secretPath, "utf-8").trim();
|
|
4541
|
+
if (existing) return existing;
|
|
4542
|
+
}
|
|
4543
|
+
mkdirSync(dirPath, { recursive: true });
|
|
4544
|
+
const secret = randomBytes(24).toString("hex");
|
|
4545
|
+
writeFileSync(secretPath, `${secret}\n`, "utf-8");
|
|
4546
|
+
return secret;
|
|
4547
|
+
}
|
|
4548
|
+
//#endregion
|
|
4549
|
+
//#region src/cli/app/services/local-api/app-data-live.service.ts
|
|
4550
|
+
var AppDataLiveService = class {
|
|
4551
|
+
constructor(params = {}) {
|
|
4552
|
+
this.params = params;
|
|
4553
|
+
}
|
|
4554
|
+
list = async () => await this.requireApiClient().request({ path: "/api/app-data" });
|
|
4555
|
+
deleteRetained = async (dataId, confirmAppId) => {
|
|
4556
|
+
const normalizedDataId = dataId.trim();
|
|
4557
|
+
const normalizedAppId = confirmAppId.trim();
|
|
4558
|
+
if (!normalizedDataId) throw new Error("App data id is required.");
|
|
4559
|
+
if (!normalizedAppId) throw new Error("--confirm <app-id> is required.");
|
|
4560
|
+
return await this.requireApiClient().request({
|
|
4561
|
+
path: `/api/app-data/${encodeURIComponent(normalizedDataId)}`,
|
|
4562
|
+
method: "DELETE",
|
|
4563
|
+
body: { confirmAppId: normalizedAppId }
|
|
4564
|
+
});
|
|
4565
|
+
};
|
|
4566
|
+
requireApiClient = () => {
|
|
4567
|
+
const client = this.params.createApiClient ? this.params.createApiClient() : createLocalUiApiClient();
|
|
4568
|
+
if (!client) throw new Error("NextClaw UI runtime is not running; start NextClaw before managing App data.");
|
|
4569
|
+
return client;
|
|
4570
|
+
};
|
|
4571
|
+
};
|
|
4572
|
+
//#endregion
|
|
4573
|
+
//#region src/cli/app/controllers/app-data-command.controller.ts
|
|
4574
|
+
var AppDataCommandController = class {
|
|
4575
|
+
constructor(service = new AppDataLiveService()) {
|
|
4576
|
+
this.service = service;
|
|
4577
|
+
}
|
|
4578
|
+
list = async (options) => {
|
|
4579
|
+
const result = await this.service.list();
|
|
4580
|
+
process.stdout.write(options.json ? `${JSON.stringify(result, null, 2)}\n` : this.formatList(result));
|
|
4581
|
+
};
|
|
4582
|
+
deleteRetained = async (dataId, options) => {
|
|
4583
|
+
const result = await this.service.deleteRetained(dataId, options.confirm);
|
|
4584
|
+
process.stdout.write(options.json ? `${JSON.stringify(result, null, 2)}\n` : `Deleted App data: ${result.appId}/${result.instanceId}\n`);
|
|
4585
|
+
};
|
|
4586
|
+
formatList = (result) => {
|
|
4587
|
+
if (result.entries.length === 0) return "App data: none\n";
|
|
4588
|
+
return `${result.entries.map((entry) => `${entry.id}\t${entry.lifecycle}\t${entry.source}\t${entry.appId}\t${entry.usage.totalBytes} B\t${entry.storage.instanceDirectory}`).join("\n")}\n`;
|
|
4589
|
+
};
|
|
4590
|
+
};
|
|
4591
|
+
//#endregion
|
|
4443
4592
|
//#region src/cli/app/services/service-app-live-runtime.service.ts
|
|
4444
4593
|
function readErrorMessage(error) {
|
|
4445
4594
|
if (error instanceof Error && error.message.trim().length > 0) return error.message.trim();
|
|
@@ -4502,81 +4651,9 @@ var ServiceAppLiveRuntimeService = class {
|
|
|
4502
4651
|
};
|
|
4503
4652
|
createApiClient = () => {
|
|
4504
4653
|
if (this.params.createApiClient) return this.params.createApiClient();
|
|
4505
|
-
|
|
4506
|
-
return apiBase ? new LocalUiApiClient(apiBase) : null;
|
|
4654
|
+
return createLocalUiApiClient();
|
|
4507
4655
|
};
|
|
4508
4656
|
};
|
|
4509
|
-
var LocalUiApiClient = class {
|
|
4510
|
-
cookie;
|
|
4511
|
-
constructor(apiBase) {
|
|
4512
|
-
this.apiBase = apiBase;
|
|
4513
|
-
}
|
|
4514
|
-
request = async (params) => {
|
|
4515
|
-
const { body, method, path } = params;
|
|
4516
|
-
const cookie = await this.getCookie();
|
|
4517
|
-
const headers = {};
|
|
4518
|
-
if (body) headers["Content-Type"] = "application/json";
|
|
4519
|
-
if (cookie) headers.Cookie = cookie;
|
|
4520
|
-
const requestInit = {
|
|
4521
|
-
method: method ?? "GET",
|
|
4522
|
-
headers
|
|
4523
|
-
};
|
|
4524
|
-
if (body) requestInit.body = JSON.stringify(body);
|
|
4525
|
-
const response = await fetch(`${this.apiBase}${path}`, requestInit);
|
|
4526
|
-
if (!response.ok) throw new Error(`api request failed with status ${response.status}`);
|
|
4527
|
-
const payload = await response.json();
|
|
4528
|
-
if (!payload.ok) throw new Error(payload.error?.message ?? "api request failed");
|
|
4529
|
-
return payload.data;
|
|
4530
|
-
};
|
|
4531
|
-
getCookie = async () => {
|
|
4532
|
-
if (this.cookie !== void 0) return this.cookie;
|
|
4533
|
-
const response = await fetch(`${this.apiBase}/api/auth/bridge`, {
|
|
4534
|
-
method: "POST",
|
|
4535
|
-
headers: { "x-nextclaw-ui-bridge-secret": ensureUiBridgeSecret() }
|
|
4536
|
-
});
|
|
4537
|
-
if (!response.ok) throw new Error(`bridge auth failed with status ${response.status}`);
|
|
4538
|
-
const payload = await response.json();
|
|
4539
|
-
if (!payload.ok) throw new Error(payload.error?.message ?? "bridge auth failed");
|
|
4540
|
-
this.cookie = typeof payload.data.cookie === "string" && payload.data.cookie.trim().length > 0 ? payload.data.cookie.trim() : null;
|
|
4541
|
-
return this.cookie;
|
|
4542
|
-
};
|
|
4543
|
-
};
|
|
4544
|
-
function resolveLocalUiApiBase() {
|
|
4545
|
-
const state = readRunningRuntimeState(resolve(getRunPath(), "ui-runtime.json")) ?? readRunningRuntimeState(resolve(getRunPath(), "service.json"));
|
|
4546
|
-
if (!state) return null;
|
|
4547
|
-
if (typeof state.uiUrl === "string" && state.uiUrl.trim().length > 0) return state.uiUrl.replace(/\/+$/, "");
|
|
4548
|
-
if (typeof state.apiUrl === "string" && state.apiUrl.trim().length > 0) return state.apiUrl.replace(/\/api\/?$/, "").replace(/\/+$/, "");
|
|
4549
|
-
return null;
|
|
4550
|
-
}
|
|
4551
|
-
function readRunningRuntimeState(statePath) {
|
|
4552
|
-
if (!existsSync(statePath)) return null;
|
|
4553
|
-
try {
|
|
4554
|
-
const state = JSON.parse(readFileSync(statePath, "utf-8"));
|
|
4555
|
-
return typeof state.pid === "number" && isProcessRunning(state.pid) ? state : null;
|
|
4556
|
-
} catch {
|
|
4557
|
-
return null;
|
|
4558
|
-
}
|
|
4559
|
-
}
|
|
4560
|
-
function isProcessRunning(pid) {
|
|
4561
|
-
try {
|
|
4562
|
-
process.kill(pid, 0);
|
|
4563
|
-
return true;
|
|
4564
|
-
} catch {
|
|
4565
|
-
return false;
|
|
4566
|
-
}
|
|
4567
|
-
}
|
|
4568
|
-
function ensureUiBridgeSecret() {
|
|
4569
|
-
const dirPath = join(getDataDir(), "remote");
|
|
4570
|
-
const secretPath = join(dirPath, "ui-bridge-secret");
|
|
4571
|
-
if (existsSync(secretPath)) {
|
|
4572
|
-
const existing = readFileSync(secretPath, "utf-8").trim();
|
|
4573
|
-
if (existing.length > 0) return existing;
|
|
4574
|
-
}
|
|
4575
|
-
mkdirSync(dirPath, { recursive: true });
|
|
4576
|
-
const secret = randomBytes(24).toString("hex");
|
|
4577
|
-
writeFileSync(secretPath, `${secret}\n`, "utf-8");
|
|
4578
|
-
return secret;
|
|
4579
|
-
}
|
|
4580
4657
|
//#endregion
|
|
4581
4658
|
//#region src/cli/app/controllers/app-restart-command.controller.ts
|
|
4582
4659
|
var AppRestartCommandController = class {
|
|
@@ -4759,6 +4836,7 @@ function registerAppCommands(program) {
|
|
|
4759
4836
|
const app = program.command("app").description("Develop, validate, and publish NextClaw apps");
|
|
4760
4837
|
const appCheck = new AppCheckCommandController();
|
|
4761
4838
|
const appDev = new AppDevCommandController();
|
|
4839
|
+
const appData = new AppDataCommandController();
|
|
4762
4840
|
const appCall = new AppCallCommandController();
|
|
4763
4841
|
const appRestart = new AppRestartCommandController();
|
|
4764
4842
|
const appValidatePublish = new AppValidatePublishCommandController();
|
|
@@ -4766,7 +4844,10 @@ function registerAppCommands(program) {
|
|
|
4766
4844
|
app.command("validate-publish <app-dir>").description("Validate a NextClaw Mini App before Marketplace submission").option("--meta <path>", "Use a custom marketplace metadata file").option("--json", "Output JSON", false).action(async (target, opts) => appValidatePublish.validate(target, opts));
|
|
4767
4845
|
app.command("publish <app-dir>").description("Submit a NextClaw Mini App to the App Marketplace").option("--meta <path>", "Use a custom marketplace metadata file").option("--allow-warnings", "Submit after reviewing validation warnings", false).option("--json", "Output JSON", false).action(async (target, opts) => appPublish.publish(target, opts));
|
|
4768
4846
|
app.command("check <app-dir>").description("Check a Panel App or Service App directory").option("--json", "Output JSON", false).action(async (target, opts) => appCheck.check(target, opts));
|
|
4769
|
-
app.command("dev <service-app-dir>").description("Start a Service App through the real runtime and inspect its actions").option("--json", "Output JSON", false).action(async (target, opts) => appDev.dev(target, opts));
|
|
4847
|
+
app.command("dev <service-app-dir>").description("Start a Service App through the real runtime and inspect its actions").option("--json", "Output JSON", false).option("--reset-data", "Reset the exact development instance before starting", false).option("--confirm <app-id>", "Confirm the Service App id when resetting data").action(async (target, opts) => appDev.dev(target, opts));
|
|
4848
|
+
const data = app.command("data").description("Inspect and manage NextClaw App data");
|
|
4849
|
+
data.command("list").description("List active and retained App data through the running NextClaw host").option("--json", "Output JSON", false).action(async (opts) => appData.list(opts));
|
|
4850
|
+
data.command("delete <data-id>").description("Permanently delete a retained App data instance").requiredOption("--confirm <app-id>", "Confirm the exact App id").option("--json", "Output JSON", false).action(async (dataId, opts) => appData.deleteRetained(dataId, opts));
|
|
4770
4851
|
app.command("call <service-app-dir> <action-name>").description("Call a Service App action through the real runtime").option("--input <json>", "JSON object input for the action").option("--json", "Output JSON", false).action(async (target, actionName, opts) => appCall.call(target, actionName, opts));
|
|
4771
4852
|
app.command("restart <app-id>").description("Restart a live Service App runtime in the running NextClaw UI").option("--json", "Output JSON", false).action(async (appId, opts) => appRestart.restart(appId, opts));
|
|
4772
4853
|
}
|