nextclaw 0.33.1 → 0.34.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.
Files changed (34) hide show
  1. package/dist/cli/app/index.js +183 -11
  2. package/dist/cli/app/index.js.map +1 -1
  3. package/package.json +13 -12
  4. package/resources/USAGE.md +29 -0
  5. package/resources/apps/nextclaw-personal-organizer/manifest.json +1 -1
  6. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-calendar.panel/assets/app.js +8 -0
  7. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-calendar.panel/assets/icon.svg +6 -0
  8. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-calendar.panel/assets/style.css +2 -0
  9. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-calendar.panel/index.html +10 -21
  10. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-calendar.panel/panel-app.json +4 -4
  11. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-todos.panel/assets/app.js +8 -0
  12. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-todos.panel/assets/icon.svg +4 -0
  13. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-todos.panel/assets/style.css +2 -0
  14. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-todos.panel/index.html +10 -40
  15. package/resources/apps/nextclaw-personal-organizer/panels/nextclaw-personal-organizer-todos.panel/panel-app.json +4 -4
  16. package/resources/apps/nextclaw-personal-organizer/service-components/nextclaw-personal-organizer-data/index.mjs +44 -18
  17. package/ui-dist/assets/{appearance-settings-page-DlGXLgff.js → appearance-settings-page-Bpd2RhK5.js} +1 -1
  18. package/ui-dist/assets/{channels-list-page-BEEk4Uc9.js → channels-list-page-CTblam4c.js} +2 -2
  19. package/ui-dist/assets/chat-page-Bg3_X8G9.js +1 -0
  20. package/ui-dist/assets/{desktop-update-config--zagjHic.js → desktop-update-config-D9AyIhJZ.js} +1 -1
  21. package/ui-dist/assets/index-VQAVqwG8.js +109 -0
  22. package/ui-dist/assets/{model-config-page-rrhFaque.js → model-config-page-B8Aubkwx.js} +1 -1
  23. package/ui-dist/assets/{provider-scoped-model-input-CFsfWEt9.js → provider-scoped-model-input-BRnIH-5O.js} +1 -1
  24. package/ui-dist/assets/providers-config-page-0r9AZNNZ.js +1 -0
  25. package/ui-dist/assets/remote-DQzE55WW.js +1 -0
  26. package/ui-dist/assets/runtime-config-page-BgeYpvMK.js +1 -0
  27. package/ui-dist/assets/{search-config-page-B3fvzMd1.js → search-config-page-CzNzLyd0.js} +1 -1
  28. package/ui-dist/assets/{secrets-config-page-ClwTxtXd.js → secrets-config-page-C4k3ik0v.js} +2 -2
  29. package/ui-dist/index.html +1 -1
  30. package/ui-dist/assets/chat-page-DUQXXqQm.js +0 -1
  31. package/ui-dist/assets/index-Ba_o5fu9.js +0 -109
  32. package/ui-dist/assets/providers-config-page-D-TYFZsF.js +0 -1
  33. package/ui-dist/assets/remote-BwVv_Qq-.js +0 -1
  34. package/ui-dist/assets/runtime-config-page-Br9j9Vxe.js +0 -1
@@ -7,11 +7,13 @@ import { constants, existsSync, mkdirSync, readFileSync, writeFileSync } from "n
7
7
  import { randomBytes } from "node:crypto";
8
8
  import { execFile } from "node:child_process";
9
9
  import path, { join, resolve } from "node:path";
10
+ import { tmpdir } from "node:os";
10
11
  import "@nextclaw/server";
11
12
  import { NextclawDistributionService, NextclawServiceRuntime, readLearningLoopRuntimeConfig } from "@nextclaw/service";
13
+ import { access, mkdtemp, readFile, rm, stat } from "node:fs/promises";
12
14
  import { McpServiceAppRuntimeService, buildServiceActionId, getServiceAppManifestPath, mergeServiceAppRuntimeActions, readServiceAppManifest } from "@nextclaw/kernel";
13
- import { access, readFile, stat } from "node:fs/promises";
14
15
  import { promisify } from "node:util";
16
+ import { AppPublishService, AppPublishValidationService } from "@nextclaw/app-runtime";
15
17
  var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
16
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
17
19
  //#endregion
@@ -3641,13 +3643,14 @@ var ServiceAppDevService = class {
3641
3643
  if (!loaded) return this.buildDevReport(appPath, void 0, [], issues);
3642
3644
  if (this.hasErrors(issues)) return this.buildDevReport(appPath, this.toServiceAppRecord(appPath, loaded.manifest, this.idleRuntimeStatus), [], issues);
3643
3645
  const runtime = this.createRuntimeService();
3646
+ const dataDirectory = await this.createDevDataDirectory();
3644
3647
  try {
3645
- const startRecord = this.toServiceAppRecord(appPath, loaded.manifest, runtime);
3648
+ const startRecord = this.toServiceAppRecord(appPath, loaded.manifest, runtime, dataDirectory);
3646
3649
  const runtimeActions = await runtime.listActions({
3647
3650
  app: startRecord,
3648
3651
  manifest: loaded.manifest
3649
3652
  });
3650
- const record = this.toServiceAppRecord(appPath, loaded.manifest, runtime);
3653
+ const record = this.toServiceAppRecord(appPath, loaded.manifest, runtime, dataDirectory);
3651
3654
  const actions = mergeServiceAppRuntimeActions({
3652
3655
  record,
3653
3656
  manifest: loaded.manifest,
@@ -3656,7 +3659,14 @@ var ServiceAppDevService = class {
3656
3659
  this.collectRuntimeIssues(record, actions, issues);
3657
3660
  return this.buildDevReport(appPath, record, actions, issues);
3658
3661
  } finally {
3659
- await runtime.dispose();
3662
+ try {
3663
+ await runtime.dispose();
3664
+ } finally {
3665
+ await rm(dataDirectory, {
3666
+ recursive: true,
3667
+ force: true
3668
+ });
3669
+ }
3660
3670
  }
3661
3671
  };
3662
3672
  call = async (target, actionName, input) => {
@@ -3676,18 +3686,19 @@ var ServiceAppDevService = class {
3676
3686
  return this.buildCallReport(appPath, record, void 0, void 0, issues);
3677
3687
  }
3678
3688
  const runtime = this.createRuntimeService();
3689
+ const dataDirectory = await this.createDevDataDirectory();
3679
3690
  try {
3680
- const record = this.toServiceAppRecord(appPath, loaded.manifest, runtime);
3691
+ const record = this.toServiceAppRecord(appPath, loaded.manifest, runtime, dataDirectory);
3681
3692
  const result = await runtime.invokeAction({
3682
3693
  app: record,
3683
3694
  manifest: loaded.manifest,
3684
3695
  actionName: action,
3685
3696
  input
3686
3697
  });
3687
- const nextRecord = this.toServiceAppRecord(appPath, loaded.manifest, runtime);
3698
+ const nextRecord = this.toServiceAppRecord(appPath, loaded.manifest, runtime, dataDirectory);
3688
3699
  return this.buildCallReport(appPath, nextRecord, buildServiceActionId(loaded.manifest.id, action), result, issues);
3689
3700
  } catch (error) {
3690
- const record = this.toServiceAppRecord(appPath, loaded.manifest, runtime);
3701
+ const record = this.toServiceAppRecord(appPath, loaded.manifest, runtime, dataDirectory);
3691
3702
  issues.push({
3692
3703
  severity: "error",
3693
3704
  code: "service.runtime.callFailed",
@@ -3695,7 +3706,14 @@ var ServiceAppDevService = class {
3695
3706
  });
3696
3707
  return this.buildCallReport(appPath, record, buildServiceActionId(loaded.manifest.id, action), void 0, issues);
3697
3708
  } finally {
3698
- await runtime.dispose();
3709
+ try {
3710
+ await runtime.dispose();
3711
+ } finally {
3712
+ await rm(dataDirectory, {
3713
+ recursive: true,
3714
+ force: true
3715
+ });
3716
+ }
3699
3717
  }
3700
3718
  };
3701
3719
  loadServiceApp = async (appPath, issues) => {
@@ -3727,7 +3745,8 @@ var ServiceAppDevService = class {
3727
3745
  return resolveConfigSecrets(loadConfig(configPath), { configPath });
3728
3746
  };
3729
3747
  idleRuntimeStatus = { getStatus: () => ({ status: "idle" }) };
3730
- toServiceAppRecord = (dirPath, manifest, runtime) => {
3748
+ createDevDataDirectory = async () => await mkdtemp(path.join(tmpdir(), "nextclaw-service-app-dev-data-"));
3749
+ toServiceAppRecord = (dirPath, manifest, runtime, dataDirectory) => {
3731
3750
  const runtimeStatus = runtime.getStatus(manifest.id);
3732
3751
  const record = {
3733
3752
  id: manifest.id,
@@ -3739,7 +3758,8 @@ var ServiceAppDevService = class {
3739
3758
  cwd: dirPath,
3740
3759
  enabled: manifest.enabled,
3741
3760
  protocol: manifest.protocol,
3742
- status: manifest.enabled ? runtimeStatus.status : "stopped"
3761
+ status: manifest.enabled ? runtimeStatus.status : "stopped",
3762
+ dataDirectory
3743
3763
  };
3744
3764
  if (manifest.description) record.description = manifest.description;
3745
3765
  if (runtimeStatus.lastError) record.lastError = runtimeStatus.lastError;
@@ -4588,13 +4608,165 @@ var AppRestartCommandController = class {
4588
4608
  };
4589
4609
  };
4590
4610
  //#endregion
4611
+ //#region src/cli/app/services/app-publishing.service.ts
4612
+ var AppPublishingService = class {
4613
+ constructor(validationService = new AppPublishValidationService(), publishService = new AppPublishService()) {
4614
+ this.validationService = validationService;
4615
+ this.publishService = publishService;
4616
+ }
4617
+ validate = async (params) => {
4618
+ const result = await this.validationService.validate({
4619
+ appDirectory: params.appDirectory,
4620
+ metadataPath: params.metadataPath,
4621
+ mode: "bundle"
4622
+ });
4623
+ if (result.profile !== "components") throw new Error("nextclaw app publish 只支持由 Panel App 或 Service App 组成的 schema v2 Mini App。");
4624
+ if (result.distributionMode !== "bundle") throw new Error("NextClaw Mini App 只支持 bundle 分发。");
4625
+ return result;
4626
+ };
4627
+ publish = async (params) => {
4628
+ const validation = await this.validate(params);
4629
+ if (validation.warnings.length > 0 && !params.allowWarnings) {
4630
+ const warningList = validation.warnings.map((warning) => `[${warning.code}] ${warning.message}`).join("; ");
4631
+ throw new Error(`发布校验包含警告:${warningList}。确认后可使用 --allow-warnings 继续。`);
4632
+ }
4633
+ const tempDirectory = await mkdtemp(path.join(tmpdir(), "nextclaw-app-publish-"));
4634
+ try {
4635
+ const result = await this.publishService.publish({
4636
+ appDirectory: params.appDirectory,
4637
+ metadataPath: params.metadataPath,
4638
+ bundleOutputPath: path.join(tempDirectory, "artifact.napp"),
4639
+ mode: "bundle"
4640
+ });
4641
+ const { item } = result;
4642
+ return {
4643
+ validation,
4644
+ publish: {
4645
+ created: result.created,
4646
+ item: {
4647
+ slug: item.slug,
4648
+ appId: item.appId,
4649
+ ownerScope: item.ownerScope,
4650
+ appName: item.appName,
4651
+ publishStatus: item.publishStatus,
4652
+ name: item.name,
4653
+ latestVersion: item.latestVersion,
4654
+ webUrl: item.publishStatus === "published" ? item.webUrl : void 0
4655
+ },
4656
+ fileCount: result.fileCount
4657
+ }
4658
+ };
4659
+ } catch (error) {
4660
+ const message = error instanceof Error ? error.message : String(error);
4661
+ throw new Error(message.replace(/缺少 marketplace publish token。请先登录 NextClaw,或传入 --token。?/g, "发布需要 NextClaw 平台登录态。请先运行 nextclaw login。").replace(/,或传入 --token。?/g, "。"));
4662
+ } finally {
4663
+ await rm(tempDirectory, {
4664
+ recursive: true,
4665
+ force: true
4666
+ });
4667
+ }
4668
+ };
4669
+ };
4670
+ //#endregion
4671
+ //#region src/cli/app/controllers/app-publish-command.controller.ts
4672
+ const PLATFORM_APPS_URL = "https://platform.nextclaw.io/apps";
4673
+ var AppPublishCommandController = class {
4674
+ constructor(appPublishingService = new AppPublishingService()) {
4675
+ this.appPublishingService = appPublishingService;
4676
+ }
4677
+ publish = async (target, options) => {
4678
+ const { allowWarnings, json, meta } = options;
4679
+ try {
4680
+ const result = await this.appPublishingService.publish({
4681
+ appDirectory: target,
4682
+ metadataPath: meta,
4683
+ allowWarnings
4684
+ });
4685
+ process.stdout.write(json ? `${JSON.stringify({
4686
+ ok: true,
4687
+ ...result
4688
+ }, null, 2)}\n` : this.format(result));
4689
+ } catch (error) {
4690
+ this.writeError(error, Boolean(json));
4691
+ process.exitCode = 1;
4692
+ }
4693
+ };
4694
+ format = (result) => {
4695
+ const { item } = result.publish;
4696
+ if (item.publishStatus === "pending") return [
4697
+ `Submitted ${item.name} (${item.appId}) ${item.latestVersion} for review.`,
4698
+ "Status: pending",
4699
+ "The app will appear in the App Marketplace after approval.",
4700
+ `Manage submissions: ${PLATFORM_APPS_URL}`,
4701
+ ""
4702
+ ].join("\n");
4703
+ return [
4704
+ `${result.publish.created ? "Published" : "Updated"} ${item.name} (${item.appId}) ${item.latestVersion}.`,
4705
+ "Status: published",
4706
+ item.webUrl ? `Details: ${item.webUrl}` : "",
4707
+ `Manage apps: ${PLATFORM_APPS_URL}`,
4708
+ ""
4709
+ ].filter((line, index, lines) => line || index === lines.length - 1).join("\n");
4710
+ };
4711
+ writeError = (error, json) => {
4712
+ const message = error instanceof Error ? error.message : String(error);
4713
+ process.stdout.write(json ? `${JSON.stringify({
4714
+ ok: false,
4715
+ error: { message }
4716
+ }, null, 2)}\n` : `Mini App publish failed: ${message}\n`);
4717
+ };
4718
+ };
4719
+ //#endregion
4720
+ //#region src/cli/app/controllers/app-validate-publish-command.controller.ts
4721
+ var AppValidatePublishCommandController = class {
4722
+ constructor(appPublishingService = new AppPublishingService()) {
4723
+ this.appPublishingService = appPublishingService;
4724
+ }
4725
+ validate = async (target, options) => {
4726
+ try {
4727
+ const validation = await this.appPublishingService.validate({
4728
+ appDirectory: target,
4729
+ metadataPath: options.meta
4730
+ });
4731
+ process.stdout.write(options.json ? `${JSON.stringify({
4732
+ ok: true,
4733
+ validation
4734
+ }, null, 2)}\n` : this.format(validation));
4735
+ } catch (error) {
4736
+ this.writeError(error, Boolean(options.json));
4737
+ process.exitCode = 1;
4738
+ }
4739
+ };
4740
+ format = (validation) => {
4741
+ const lines = [
4742
+ `Mini App publish validation passed: ${validation.appId}@${validation.version}`,
4743
+ `Components: ${validation.componentCount ?? 0}`,
4744
+ `Bundle size: ${validation.bundleSizeBytes} bytes`,
4745
+ `Metadata: ${validation.metadataPath}`
4746
+ ];
4747
+ for (const warning of validation.warnings) lines.push(`Warning [${warning.code}]: ${warning.message}`);
4748
+ return `${lines.join("\n")}\n`;
4749
+ };
4750
+ writeError = (error, json) => {
4751
+ const message = error instanceof Error ? error.message : String(error);
4752
+ process.stdout.write(json ? `${JSON.stringify({
4753
+ ok: false,
4754
+ error: { message }
4755
+ }, null, 2)}\n` : `Mini App publish validation failed: ${message}\n`);
4756
+ };
4757
+ };
4758
+ //#endregion
4591
4759
  //#region src/cli/app/register-app-commands.ts
4592
4760
  function registerAppCommands(program) {
4593
- const app = program.command("app").description("Inspect and validate lightweight NextClaw apps");
4761
+ const app = program.command("app").description("Develop, validate, and publish NextClaw apps");
4594
4762
  const appCheck = new AppCheckCommandController();
4595
4763
  const appDev = new AppDevCommandController();
4596
4764
  const appCall = new AppCallCommandController();
4597
4765
  const appRestart = new AppRestartCommandController();
4766
+ const appValidatePublish = new AppValidatePublishCommandController();
4767
+ const appPublish = new AppPublishCommandController();
4768
+ 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));
4769
+ 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));
4598
4770
  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));
4599
4771
  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));
4600
4772
  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));