nextclaw 0.33.2 → 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.
@@ -13,6 +13,7 @@ import { NextclawDistributionService, NextclawServiceRuntime, readLearningLoopRu
13
13
  import { access, mkdtemp, readFile, rm, stat } from "node:fs/promises";
14
14
  import { McpServiceAppRuntimeService, buildServiceActionId, getServiceAppManifestPath, mergeServiceAppRuntimeActions, readServiceAppManifest } from "@nextclaw/kernel";
15
15
  import { promisify } from "node:util";
16
+ import { AppPublishService, AppPublishValidationService } from "@nextclaw/app-runtime";
16
17
  var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
17
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
18
19
  //#endregion
@@ -4607,13 +4608,165 @@ var AppRestartCommandController = class {
4607
4608
  };
4608
4609
  };
4609
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
4610
4759
  //#region src/cli/app/register-app-commands.ts
4611
4760
  function registerAppCommands(program) {
4612
- 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");
4613
4762
  const appCheck = new AppCheckCommandController();
4614
4763
  const appDev = new AppDevCommandController();
4615
4764
  const appCall = new AppCallCommandController();
4616
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));
4617
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));
4618
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));
4619
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));