@kanyun-ai-infra/band-cli 0.1.0 → 0.2.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 (96) hide show
  1. package/bundled/examples/aitutor-tool/band/views/release/package.json +1 -1
  2. package/bundled/examples/aitutor-tool/band/views/tool-preview/package.json +1 -1
  3. package/bundled/examples/analysis/band/views/intake/package.json +1 -1
  4. package/bundled/examples/compliance/band/views/compliance/package.json +1 -1
  5. package/bundled/examples/content-review/band/views/checklist/package.json +1 -1
  6. package/bundled/examples/rush-site/band/views/rush-db/package.json +1 -1
  7. package/bundled/examples/rush-site/band/views/rush-deploy/package.json +1 -1
  8. package/bundled/examples/video/band/views/timeline/package.json +1 -1
  9. package/bundled/kernel/fixture.js +1 -1
  10. package/bundled/kernel/index.js +1 -1
  11. package/bundled/official/activity/package.json +4 -4
  12. package/bundled/official/approval/package.json +4 -4
  13. package/bundled/official/artifacts/package.json +4 -4
  14. package/bundled/official/chat/package.json +4 -4
  15. package/bundled/official/chunks/chunk-DIL5YSVK.js +1 -0
  16. package/bundled/official/comment/dist/index.js +2 -2
  17. package/bundled/official/comment/package.json +4 -4
  18. package/bundled/official/header/package.json +4 -4
  19. package/bundled/official/home/package.json +4 -4
  20. package/bundled/official/layouts/package.json +4 -4
  21. package/bundled/official/library/dist/index.js +1 -1
  22. package/bundled/official/library/package.json +4 -4
  23. package/bundled/official/members/dist/index.js +1 -1
  24. package/bundled/official/members/package.json +4 -4
  25. package/bundled/official/memory/dist/index.js +2 -2
  26. package/bundled/official/memory/package.json +4 -4
  27. package/bundled/official/native/package.json +2 -2
  28. package/bundled/official/params-form/package.json +4 -4
  29. package/bundled/official/plugins/package.json +4 -4
  30. package/bundled/official/project/dist/index.js +1 -1
  31. package/bundled/official/project/package.json +4 -4
  32. package/bundled/official/queue/package.json +4 -4
  33. package/bundled/official/settings/dist/index.js +1 -1
  34. package/bundled/official/settings/package.json +4 -4
  35. package/bundled/official/settings/plugin.yaml +7 -0
  36. package/bundled/official/shell/dist/index.js +1 -1
  37. package/bundled/official/shell/package.json +4 -4
  38. package/bundled/official/stages/package.json +4 -4
  39. package/bundled/official/threads/package.json +4 -4
  40. package/bundled/official/turn-bar/package.json +4 -4
  41. package/bundled/official/turn-trace/package.json +4 -4
  42. package/bundled/official/version-switch/dist/index.js +1 -1
  43. package/bundled/official/version-switch/package.json +4 -4
  44. package/bundled/official/viewer-entity/package.json +2 -2
  45. package/bundled/official/viewer-external/package.json +2 -2
  46. package/bundled/official/viewer-image/package.json +2 -2
  47. package/bundled/official/viewer-media/index.js +2 -2
  48. package/bundled/official/viewer-media/package.json +2 -2
  49. package/bundled/official/viewer-storyboard/index.js +2 -2
  50. package/bundled/official/viewer-storyboard/package.json +2 -2
  51. package/bundled/official/viewer-text/dist/index.js +2 -2
  52. package/bundled/official/viewer-text/package.json +4 -4
  53. package/bundled/official/viewer-tool/package.json +2 -2
  54. package/bundled/official/viewer-web/package.json +2 -2
  55. package/bundled/official/viewer-web-app/package.json +2 -2
  56. package/bundled/official/workshops/dist/index.js +2 -2
  57. package/bundled/official/workshops/package.json +4 -4
  58. package/bundled/official/workshops/plugin.yaml +2 -2
  59. package/bundled/skills/band-plugin/SKILL.md +20 -273
  60. package/bundled/skills/band-plugin/references/code.md +58 -0
  61. package/bundled/skills/band-plugin/references/dev.md +37 -0
  62. package/bundled/skills/band-plugin/references/execution.md +26 -0
  63. package/bundled/skills/band-plugin/references/manifest.md +65 -0
  64. package/bundled/skills/band-plugin/references/placement.md +34 -0
  65. package/bundled/skills/band-plugin/references/reuse.md +38 -0
  66. package/bundled/skills/band-plugin/references/rules.md +13 -0
  67. package/bundled/skills/band-plugin/references/shape.md +17 -0
  68. package/bundled/skills/band-plugin/references/testing-publish.md +35 -0
  69. package/bundled/skills/band-plugin/references/viewer-comments.md +25 -0
  70. package/bundled/skills/band-plugin/templates/dev/fixture.ts +15 -0
  71. package/bundled/skills/band-plugin/templates/dev/resources.ts +6 -0
  72. package/bundled/skills/band-plugin/templates/panel/index.ts +24 -0
  73. package/bundled/skills/band-plugin/templates/panel/package.json +12 -0
  74. package/bundled/skills/band-plugin/templates/panel/plugin.yaml +5 -0
  75. package/bundled/skills/band-plugin/templates/toolbar-dock/plugin.yaml +11 -0
  76. package/dev-host/Inspector.tsx +28 -10
  77. package/dev-host/app.tsx +11 -6
  78. package/dev-host/host.css +11 -0
  79. package/dev-host/main.tsx +5 -0
  80. package/dist/bin.js +3 -3
  81. package/dist/build-plugin.d.ts +1 -1
  82. package/dist/build-plugin.js +1 -1
  83. package/dist/{chunk-TN7Z3OF6.js → chunk-LGYGWMSY.js} +19 -17
  84. package/dist/{chunk-VVJNG5GV.js → chunk-Q2XJXNVH.js} +22 -15
  85. package/dist/{chunk-RAD6MMSL.js → chunk-XPLYTHNX.js} +1 -1
  86. package/dist/{dev-server-RAZQ32W7.js → dev-server-Q7NTJ3QD.js} +116 -11
  87. package/dist/fixture.d.ts +11 -0
  88. package/dist/index.d.ts +2 -2
  89. package/dist/index.js +3 -3
  90. package/dist/vite.d.ts +1 -1
  91. package/dist/vite.js +2 -2
  92. package/dist/{workshop-repo-CO6YMDee.d.ts → workshop-repo-DqoVdcGu.d.ts} +10 -10
  93. package/package.json +10 -7
  94. package/src/dev-managers.ts +16 -0
  95. package/src/inspector-plugins.ts +18 -0
  96. package/bundled/official/chunks/chunk-JI6ZNGOE.js +0 -1
@@ -10,7 +10,7 @@ import {
10
10
  officialProfilePath,
11
11
  resolvePluginRepo,
12
12
  workshopNameOf
13
- } from "./chunk-RAD6MMSL.js";
13
+ } from "./chunk-XPLYTHNX.js";
14
14
  import {
15
15
  IMPLICIT_STAGE,
16
16
  SELF_CONTAINED_EXTENSIONS,
@@ -29,7 +29,7 @@ import {
29
29
  rolePermissions,
30
30
  selfContainedProblems,
31
31
  workshopFileReader
32
- } from "./chunk-TN7Z3OF6.js";
32
+ } from "./chunk-LGYGWMSY.js";
33
33
 
34
34
  // src/index.ts
35
35
  import { execFileSync } from "child_process";
@@ -310,6 +310,8 @@ function newPlugin(root, name, opts) {
310
310
  description: title,
311
311
  type: "module",
312
312
  peerDependencies: {
313
+ react: "^19.0.0",
314
+ "react-dom": "^19.0.0",
313
315
  "@kanyun-ai-infra/band-plugin-sdk": `^${BAND_PROTOCOL_VERSION}`,
314
316
  [PROJECT]: "*"
315
317
  }
@@ -432,6 +434,8 @@ ${t.manifest}`,
432
434
  // 不带 --passWithNoTests:收不到测试要红,不吞成绿(band#456)
433
435
  scripts: { check: "tsc -p tsconfig.json", test: "vitest run" },
434
436
  peerDependencies: {
437
+ react: "^19.0.0",
438
+ "react-dom": "^19.0.0",
435
439
  "@kanyun-ai-infra/band-plugin-sdk": "workspace:*",
436
440
  [PROJECT]: "workspace:*"
437
441
  },
@@ -642,7 +646,7 @@ import { parse } from "yaml";
642
646
  // package.json
643
647
  var package_default = {
644
648
  name: "@kanyun-ai-infra/band-cli",
645
- version: "0.1.0",
649
+ version: "0.2.0",
646
650
  description: "band \u547D\u4EE4\u884C\uFF1A\u65B0\u5EFA\u3001\u672C\u5730\u8C03\u8BD5\u3001\u6821\u9A8C\u4E0E\u53D1\u5E03 Band \u5DE5\u574A\u548C\u63D2\u4EF6",
647
651
  license: "UNLICENSED",
648
652
  type: "module",
@@ -657,7 +661,8 @@ var package_default = {
657
661
  },
658
662
  "./build": {
659
663
  types: "./dist/build-plugin.d.ts",
660
- import: "./dist/build-plugin.js"
664
+ import: "./dist/build-plugin.js",
665
+ default: "./dist/build-plugin.js"
661
666
  },
662
667
  "./catalog": {
663
668
  types: "./dist/plugin-entry.d.ts",
@@ -692,8 +697,8 @@ var package_default = {
692
697
  "@kanyun-ai-infra/band-plugin-react": "workspace:^",
693
698
  "@kanyun-ai-infra/band-plugin-sdk": "workspace:^",
694
699
  "es-module-lexer": "^2.3.2",
695
- react: "^18.3.1",
696
- "react-dom": "^18.3.1",
700
+ react: "^19.3.1",
701
+ "react-dom": "^19.3.1",
697
702
  semver: "^7.8.5",
698
703
  vite: "^6.0.7",
699
704
  yaml: "^2.6.1",
@@ -705,8 +710,8 @@ var package_default = {
705
710
  "@kanyun-ai-infra/band-tokens": "workspace:*",
706
711
  "@kanyun-ai-infra/band-workshop": "workspace:*",
707
712
  "@types/node": "^22.10.0",
708
- "@types/react": "^18.3.12",
709
- "@types/react-dom": "^18.3.1",
713
+ "@types/react": "^19.3.0",
714
+ "@types/react-dom": "^19.3.0",
710
715
  tsup: "^8.4.0",
711
716
  typescript: "5.9.3",
712
717
  vitest: "^4.0.17"
@@ -775,7 +780,7 @@ function newPluginRepo(parentDir, packageName, opts) {
775
780
  "npx band dev .\uFF1A\u7528 dev/ \u5939\u5177\u5DE5\u574A\u8D77\u9875\u9762\uFF0C\u672C\u4ED3\u5E93\u7684\u63D2\u4EF6\u81EA\u52A8\u88C5\u4E0A",
776
781
  "npx band check .\uFF1A\u6821\u9A8C\u63D2\u4EF6\u4E0E\u5939\u5177\u5DE5\u574A\u7684\u88C5\u914D",
777
782
  placementHint(opts.template, packageName, name, opts.stage),
778
- "\u53D1\u5E03\uFF08band publish --plugin\uFF09\u4E0E CI \u53D1\u5305\u8FD8\u6CA1\u843D\u5730\uFF1A\u73B0\u5728 CI \u6A21\u677F\u53EA\u8DD1 band check"
783
+ "\u53D1\u5E03\u8FD8\u6CA1\u63A5\u4E0A\uFF08\u63D2\u4EF6\u7531 Band \u6253\u5305\u5206\u53D1\uFF0C\u4E0D\u7ECF npm \u53D1\u5305\uFF09\uFF1A\u73B0\u5728 CI \u6A21\u677F\u53EA\u8DD1 band check"
779
784
  ]
780
785
  };
781
786
  }
@@ -796,9 +801,12 @@ function packageJson(packageName, title) {
796
801
  files: ["src", "plugin.yaml", "README.md"],
797
802
  scripts: { dev: "band dev .", check: "band check ." },
798
803
  peerDependencies: {
804
+ react: "^19.0.0",
805
+ "react-dom": "^19.0.0",
799
806
  "@kanyun-ai-infra/band-plugin-sdk": `^${BAND_PROTOCOL_VERSION2}`,
800
807
  [PROJECT2]: "*"
801
808
  },
809
+ peerDependenciesMeta: { [PROJECT2]: { optional: true } },
802
810
  devDependencies: {
803
811
  "@kanyun-ai-infra/band-cli": `^${CLI_VERSION}`,
804
812
  "@kanyun-ai-infra/band-plugin-sdk": `^${BAND_PROTOCOL_VERSION2}`
@@ -897,7 +905,7 @@ function CI(packageName) {
897
905
  # \u8FDB\u884C\u4E2D\uFF0C\u8FD8\u6CA1\u63A5\u4E0A\uFF1A
898
906
  # - \u5355\u6D4B\uFF1B
899
907
  # - \u9632\u6CC4\u9732\u626B\u63CF\uFF1B
900
- # - \u6253 v* tag \u65F6\u53D1\u79C1\u6709 cnpm\uFF0C\u5E76\u7528 \`band publish --plugin\` \u767B\u8BB0\u8FDB Band \u63D2\u4EF6\u76EE\u5F55\u3002
908
+ # - \u53D1\u5E03\uFF1A\u63D2\u4EF6\u7531 Band \u6253\u5305\u3001\u6309\u5185\u5BB9\u54C8\u5E0C\u5B58\u653E\u4E0E\u5206\u53D1\uFF0C\u4E0D\u7ECF npm \u53D1\u5305\uFF1B\u63A5\u4E0A\u4E4B\u524D\u8FD9\u91CC\u53EA\u8DD1 band check\u3002
901
909
  stages: [check]
902
910
 
903
911
  band-check:
@@ -923,7 +931,7 @@ ${title}\uFF1A\u4E00\u4E2A\u72EC\u7ACB\u7684 Band \u63D2\u4EF6\uFF08\u4E0D\u5C5E
923
931
  | \`src/index.ts\` | \u5165\u53E3\uFF0C\u9ED8\u8BA4\u5BFC\u51FA \`definePlugin({ surfaces })\` |
924
932
  | \`dev/workshop.yaml\` | \u672C\u5730\u5939\u5177\u5DE5\u574A\uFF1A\u6700\u5C0F\u5B9A\u4E49\uFF0C\u53EA\u7ED9 \`band dev\` / \`band check\` \u7528\uFF0C\u4E0D\u53D1\u5E03 |
925
933
  | \`dev/fixture.ts\` | \u5939\u5177\uFF1A\u793A\u4F8B\u4EA7\u7269\u3001\u7248\u672C\u4E0E\u6587\u4EF6 |
926
- | \`.gitlab-ci.yml\` | CI \u6A21\u677F\uFF1A\u73B0\u5728\u8DD1 \`band check\`\uFF1B\u5355\u6D4B\u3001\u53D1\u5305\u4E0E\u767B\u8BB0\u8FDB\u884C\u4E2D |
934
+ | \`.gitlab-ci.yml\` | CI \u6A21\u677F\uFF1A\u73B0\u5728\u8DD1 \`band check\`\uFF1B\u5355\u6D4B\u3001\u9632\u6CC4\u9732\u626B\u63CF\u4E0E\u53D1\u5E03\u8FDB\u884C\u4E2D |
927
935
 
928
936
  \u754C\u9762\u51FA\u73B0\u5728${place}\u3002
929
937
 
@@ -937,14 +945,13 @@ npx band check . # \u6821\u9A8C package.json\u3001plugin.yaml \u4E0E\u5939\u
937
945
 
938
946
  ## \u53D1\u5E03\uFF08\u8FDB\u884C\u4E2D\uFF09
939
947
 
940
- \`band publish --plugin\` \u4E0E\u79C1\u6709 cnpm \u8FD8\u5728\u843D\u5730\uFF1A\u73B0\u5728\u53EA\u80FD\u5728\u672C\u5730\u8C03\u8BD5\u4E0E\u6821\u9A8C\u3002\u843D\u5730\u540E\u6253 \`v*\` tag \u65F6 CI \u53D1\u5305\u5E76\u767B\u8BB0\uFF0C
948
+ \u53D1\u5E03\u8FD8\u6CA1\u63A5\u4E0A\uFF1A\u73B0\u5728\u53EA\u80FD\u5728\u672C\u5730\u8C03\u8BD5\u4E0E\u6821\u9A8C\u3002\u63D2\u4EF6\u7531 Band \u6253\u5305\u3001\u6309\u5185\u5BB9\u54C8\u5E0C\u5B58\u653E\u4E0E\u5206\u53D1\uFF0C\u4E0D\u7ECF npm \u53D1\u5305\uFF0C
941
949
  \u9875\u9762\u52A0\u8F7D\u7684\u59CB\u7EC8\u662F Band \u6784\u5EFA\u3001\u6309\u5185\u5BB9\u54C8\u5E0C\u5F52\u6863\u7684\u90A3\u4E00\u4EFD\u3002
942
950
 
943
951
  ## \u6539\u6210\u81EA\u5DF1\u7684
944
952
 
945
953
  - \u6807\u9898\u3001\u8BF4\u660E\uFF1A\`package.json\` \u7684 \`description\` \u4E0E \`plugin.yaml\` \u8D21\u732E\u7684 \`title\`\uFF1B
946
- - \u5939\u5177\uFF1A\`dev/workshop.yaml\` \u7684 \`views\` \u51B3\u5B9A\u63D2\u4EF6\u5728\u9875\u9762\u4E0A\u7684\u4F4D\u7F6E\uFF0C\`dev/fixture.ts\` \u7ED9\u51FA\u7248\u672C\u4E0E\u6587\u4EF6\uFF1B
947
- - \u53D1\u5E03\u524D\u5728 \`package.json\` \u52A0 \`publishConfig.registry\`\uFF0C\u5199\u56E2\u961F\u5B9E\u9645\u4F7F\u7528\u7684\u79C1\u6709 npm \u6E90\u5730\u5740\u3002
954
+ - \u5939\u5177\uFF1A\`dev/workshop.yaml\` \u7684 \`views\` \u51B3\u5B9A\u63D2\u4EF6\u5728\u9875\u9762\u4E0A\u7684\u4F4D\u7F6E\uFF0C\`dev/fixture.ts\` \u7ED9\u51FA\u7248\u672C\u4E0E\u6587\u4EF6\u3002
948
955
  `;
949
956
  }
950
957
 
@@ -1980,7 +1987,7 @@ async function main(argv) {
1980
1987
  if (cmd === "dev") {
1981
1988
  const { args, flags } = parseArgs(rest, ["port", "host"]);
1982
1989
  const port = flags.port === void 0 ? void 0 : parsePort(flags.port);
1983
- const { startDevServer } = await import("./dev-server-RAZQ32W7.js");
1990
+ const { startDevServer } = await import("./dev-server-Q7NTJ3QD.js");
1984
1991
  const server = await startDevServer(args[0] ?? ".", {
1985
1992
  ...port !== void 0 ? { port } : {},
1986
1993
  ...flags.host ? { host: flags.host } : {}
@@ -11,7 +11,7 @@ import {
11
11
  resolveWorkshopRepo,
12
12
  rolePermissions,
13
13
  workshopFileRefs
14
- } from "./chunk-TN7Z3OF6.js";
14
+ } from "./chunk-LGYGWMSY.js";
15
15
 
16
16
  // src/bundled.ts
17
17
  import { existsSync } from "fs";
@@ -5,15 +5,17 @@ import {
5
5
  bundledDir,
6
6
  renderDevModule,
7
7
  resolveDevWorkshop
8
- } from "./chunk-RAD6MMSL.js";
9
- import "./chunk-TN7Z3OF6.js";
8
+ } from "./chunk-XPLYTHNX.js";
9
+ import "./chunk-LGYGWMSY.js";
10
10
 
11
11
  // src/dev-server.ts
12
- import { createHash } from "crypto";
13
- import { existsSync, readFileSync } from "fs";
12
+ import { createHash as createHash2 } from "crypto";
13
+ import { existsSync, readFileSync, readdirSync } from "fs";
14
14
  import { tmpdir } from "os";
15
15
  import { dirname, join, sep } from "path";
16
16
  import { fileURLToPath } from "url";
17
+ import { SHARED_MODULES } from "@kanyun-ai-infra/band-plugin-sdk";
18
+ import { initSync, parse } from "es-module-lexer";
17
19
  import { createServer as createServer2, searchForWorkspaceRoot } from "vite";
18
20
 
19
21
  // src/browser-port.mjs
@@ -113,10 +115,82 @@ async function selectBrowserPort(bind, release) {
113
115
  throw new Error("\u8FDE\u7EED 100 \u6B21\u672A\u5206\u914D\u5230\u6D4F\u89C8\u5668\u5B89\u5168\u7AEF\u53E3");
114
116
  }
115
117
 
118
+ // src/upstream-key.ts
119
+ import { createHash, timingSafeEqual } from "crypto";
120
+ var UPSTREAM_KEY_HEADER = "x-band-upstream-key";
121
+ var UPSTREAM_KEY_ENV = "BAND_DEV_UPSTREAM_KEY";
122
+ function upstreamKeyFromEnv(env = process.env) {
123
+ const value = env[UPSTREAM_KEY_ENV];
124
+ if (value === void 0) return void 0;
125
+ if (value === "") throw new Error(`${UPSTREAM_KEY_ENV} \u8BBE\u6210\u4E86\u7A7A\u4E32\uFF1A\u8981\u4E48\u4E0D\u8BBE\uFF0C\u8981\u4E48\u7ED9\u4E00\u4E2A\u5BC6\u94A5`);
126
+ return value;
127
+ }
128
+ var digest = (v) => createHash("sha256").update(v).digest();
129
+ function upstreamKeyMatches(header, key) {
130
+ if (typeof header !== "string") return false;
131
+ return timingSafeEqual(digest(header), digest(key));
132
+ }
133
+ function reject(socket) {
134
+ socket.end(
135
+ "HTTP/1.1 403 Forbidden\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: 9\r\nConnection: close\r\n\r\nForbidden"
136
+ );
137
+ }
138
+ function upstreamKeyGuard(key) {
139
+ if (key === "") throw new Error("\u4E0A\u6E38\u5BC6\u94A5\u4E0D\u80FD\u662F\u7A7A\u4E32");
140
+ return {
141
+ name: "band-upstream-key",
142
+ configureServer(server) {
143
+ const deny = (req, res) => {
144
+ if (req.method === "GET" && req.url === "/") {
145
+ res.statusCode = 204;
146
+ res.setHeader("Cache-Control", "no-store");
147
+ res.end();
148
+ return;
149
+ }
150
+ res.statusCode = 403;
151
+ res.setHeader("Content-Type", "text/plain; charset=utf-8");
152
+ res.end("Forbidden");
153
+ };
154
+ server.middlewares.use((req, res, next) => {
155
+ if (upstreamKeyMatches(req.headers[UPSTREAM_KEY_HEADER], key)) return next();
156
+ deny(req, res);
157
+ });
158
+ const http = server.httpServer;
159
+ if (!http) return;
160
+ const original = http.listeners("upgrade");
161
+ const originalRequest = http.listeners("request");
162
+ http.removeAllListeners("request");
163
+ http.on("request", (req, res) => {
164
+ if (!upstreamKeyMatches(req.headers[UPSTREAM_KEY_HEADER], key)) return deny(req, res);
165
+ for (const listener of originalRequest) listener.call(http, req, res);
166
+ });
167
+ http.removeAllListeners("upgrade");
168
+ http.on("upgrade", (req, socket, head) => {
169
+ if (!upstreamKeyMatches(req.headers[UPSTREAM_KEY_HEADER], key)) return reject(socket);
170
+ for (const listener of original) listener.call(http, req, socket, head);
171
+ });
172
+ }
173
+ };
174
+ }
175
+
116
176
  // src/dev-server.ts
117
177
  var VIRTUAL = "virtual:band-dev";
118
178
  var RESOLVED = `\0${VIRTUAL}`;
119
179
  var DEV_HOST_DIR = fileURLToPath(new URL("../dev-host/", import.meta.url));
180
+ function heartbeatPlugin(ms) {
181
+ return {
182
+ name: "band-heartbeat",
183
+ configureServer(server) {
184
+ if (ms <= 0) return;
185
+ const timer = setInterval(
186
+ () => server.ws.send({ type: "custom", event: "band:heartbeat" }),
187
+ ms
188
+ );
189
+ timer.unref();
190
+ server.httpServer?.once("close", () => clearInterval(timer));
191
+ }
192
+ };
193
+ }
120
194
  function bandDevPlugin(root, initial) {
121
195
  let ws = initial;
122
196
  let server;
@@ -174,14 +248,14 @@ function packageJsonOf(name) {
174
248
  );
175
249
  }
176
250
  }
177
- function bundledPrebundle() {
178
- const out = [
251
+ function bundledPrebundle(dir = bundledDir()) {
252
+ const out = /* @__PURE__ */ new Set([
179
253
  "react",
180
254
  "react/jsx-runtime",
181
255
  "react/jsx-dev-runtime",
182
256
  "react-dom",
183
257
  "react-dom/client"
184
- ];
258
+ ]);
185
259
  for (const name of [
186
260
  "@kanyun-ai-infra/band-contracts",
187
261
  "@kanyun-ai-infra/band-plugin-sdk",
@@ -191,10 +265,31 @@ function bundledPrebundle() {
191
265
  for (const [sub, target] of Object.entries(pkg.exports ?? {})) {
192
266
  const file = typeof target === "string" ? target : target.import;
193
267
  if (sub.includes("*") || !file?.endsWith(".js")) continue;
194
- out.push(sub === "." ? name : `${name}/${sub.slice(2)}`);
268
+ out.add(sub === "." ? name : `${name}/${sub.slice(2)}`);
195
269
  }
196
270
  }
197
- return out;
271
+ if (dir)
272
+ for (const s of sharedImportsIn([join(dir, "official"), join(dir, "kernel")])) out.add(s);
273
+ return [...out];
274
+ }
275
+ function sharedImportsIn(dirs) {
276
+ initSync();
277
+ const found = /* @__PURE__ */ new Set();
278
+ const shared = (spec) => SHARED_MODULES.some((m) => spec === m || spec.startsWith(`${m}/`));
279
+ const walk = (d) => {
280
+ if (!existsSync(d)) return;
281
+ for (const e of readdirSync(d, { withFileTypes: true })) {
282
+ const f = join(d, e.name);
283
+ if (e.isDirectory()) {
284
+ if (e.name !== "node_modules") walk(f);
285
+ } else if (e.name.endsWith(".js")) {
286
+ const [imports] = parse(readFileSync(f, "utf8"), f);
287
+ for (const i of imports) if (i.n && shared(i.n)) found.add(i.n);
288
+ }
289
+ }
290
+ };
291
+ for (const d of dirs) walk(d);
292
+ return [...found].sort();
198
293
  }
199
294
  function allowedRoots(workshopRoot) {
200
295
  const roots = [searchForWorkspaceRoot(DEV_HOST_DIR), workshopRoot];
@@ -205,6 +300,7 @@ function allowedRoots(workshopRoot) {
205
300
  }
206
301
  async function startDevServer(root, opts = {}) {
207
302
  const workshop = resolveDevWorkshop(root);
303
+ const upstreamKey = opts.upstreamKey ?? upstreamKeyFromEnv();
208
304
  let nextPort = opts.port ?? 5310;
209
305
  if (nextPort !== 0 && !isBrowserPortSafe(nextPort))
210
306
  throw new Error(`\u7AEF\u53E3 ${nextPort} \u88AB\u6D4F\u89C8\u5668\u5C01\u7981\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u7AEF\u53E3`);
@@ -214,11 +310,16 @@ async function startDevServer(root, opts = {}) {
214
310
  cacheDir: opts.cacheDir ?? join(
215
311
  tmpdir(),
216
312
  "band-dev",
217
- createHash("sha256").update(workshop.root).digest("hex").slice(0, 12)
313
+ createHash2("sha256").update(workshop.root).digest("hex").slice(0, 12)
218
314
  ),
219
315
  logLevel: opts.logLevel ?? "info",
220
316
  clearScreen: false,
221
- plugins: [bandDevPlugin(workshop.root, workshop)],
317
+ // 密钥守卫排第一:它的中间件要先于一切(含 Vite 自己的)
318
+ plugins: [
319
+ ...upstreamKey === void 0 ? [] : [upstreamKeyGuard(upstreamKey)],
320
+ heartbeatPlugin(opts.heartbeatMs ?? 6e4),
321
+ bandDevPlugin(workshop.root, workshop)
322
+ ],
222
323
  esbuild: { jsx: "automatic" },
223
324
  resolve: {
224
325
  alias: bundledAliases(),
@@ -233,6 +334,9 @@ async function startDevServer(root, opts = {}) {
233
334
  strictPort: false,
234
335
  // 插件导入失败由页面列进「没加载的插件」,其余照常;全屏报错层会把整页挡住(缺口 #14)
235
336
  hmr: { overlay: false },
337
+ // 设了上游密钥时请求带的是沙箱 ingress 的域名(`<前缀>-<沙箱标识>.<基础域>`),Vite 的 Host 检查会按 403 拒掉;
338
+ // 这时门是密钥头,不是 Host(没设密钥的本机运行照旧用 Vite 缺省)。
339
+ ...upstreamKey === void 0 ? {} : { allowedHosts: true },
236
340
  fs: { allow: allowedRoots(workshop.root) }
237
341
  }
238
342
  });
@@ -268,5 +372,6 @@ export {
268
372
  DEV_HOST_DIR,
269
373
  bundledAliases,
270
374
  bundledPrebundle,
375
+ sharedImportsIn,
271
376
  startDevServer
272
377
  };
package/dist/fixture.d.ts CHANGED
@@ -43,6 +43,17 @@ interface FixtureData {
43
43
  stages?: StageRunSummary[];
44
44
  gates?: GateState[];
45
45
  members?: MemberView[];
46
+ /**
47
+ * 项目创建人的用户 id(服务端里创建人就是 owner 角色,天然是管理员)。缺省没有创建人:不从起始身份推,
48
+ * 否则 `band dev` 这类固定身份的宿主里任何角色都会被当成管理员。`apps/web` 的 `kernelData()` 传
49
+ * `project.createdBy`,`band dev` 的 dev-host 按 `?role=` 传 `managers`,各自传。
50
+ */
51
+ createdBy?: string;
52
+ /**
53
+ * 创建人之外的项目管理员(服务端 `members.role` 是 maintainer 的人;dev-host 里按角色参数决定)。
54
+ * `MemberView.roles` 是业务标签,不是管理角色,不参与。缺省没有管理员。
55
+ */
56
+ managers?: string[];
46
57
  /** 初始回合状态;缺省没有回合、队列为空。 */
47
58
  turn?: TurnState;
48
59
  /** 产物列表;缺省按版本里出现过的 artifactId 生成(名字即 id)。 */
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as WorkshopRepo, R as ResolvedPlugin, S as SkippedPlugin } from './workshop-repo-CO6YMDee.js';
2
- export { W as WORKSHOP_FORBIDDEN_IMPORTS, d as WorkshopRepoError, c as checkPlugin, a as checkPluginSources, p as pluginName, r as readPlugin, e as readProfileLocked, f as resolveOfficialPlugins, g as resolveWorkshopRepo } from './workshop-repo-CO6YMDee.js';
1
+ import { b as WorkshopRepo, R as ResolvedPlugin, S as SkippedPlugin } from './workshop-repo-DqoVdcGu.js';
2
+ export { W as WORKSHOP_FORBIDDEN_IMPORTS, d as WorkshopRepoError, c as checkPlugin, a as checkPluginSources, p as pluginName, r as readPlugin, e as readProfileLocked, f as resolveOfficialPlugins, g as resolveWorkshopRepo } from './workshop-repo-DqoVdcGu.js';
3
3
  import { LockedRole, StageRunSummary, GateState } from '@kanyun-ai-infra/band-plugin-sdk';
4
4
  import { PluginEntry } from './plugin-entry.js';
5
5
  import '@kanyun-ai-infra/band-contracts';
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  officialPluginCatalog,
11
11
  renderOfficialCatalog,
12
12
  writeOfficialCatalog
13
- } from "./chunk-VVJNG5GV.js";
13
+ } from "./chunk-Q2XJXNVH.js";
14
14
  import "./chunk-CL3FV65M.js";
15
15
  import {
16
16
  DevSetupError,
@@ -18,7 +18,7 @@ import {
18
18
  renderDevModule,
19
19
  resolveDevWorkshop,
20
20
  resolvePluginRepo
21
- } from "./chunk-RAD6MMSL.js";
21
+ } from "./chunk-XPLYTHNX.js";
22
22
  import {
23
23
  WORKSHOP_FORBIDDEN_IMPORTS,
24
24
  WorkshopRepoError,
@@ -29,7 +29,7 @@ import {
29
29
  readProfileLocked,
30
30
  resolveOfficialPlugins,
31
31
  resolveWorkshopRepo
32
- } from "./chunk-TN7Z3OF6.js";
32
+ } from "./chunk-LGYGWMSY.js";
33
33
  export {
34
34
  DevSetupError,
35
35
  NewPluginError,
package/dist/vite.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { LockedRole } from '@kanyun-ai-infra/band-plugin-sdk';
2
2
  import { Plugin } from 'vite';
3
- import { b as WorkshopRepo, R as ResolvedPlugin, S as SkippedPlugin } from './workshop-repo-CO6YMDee.js';
3
+ import { b as WorkshopRepo, R as ResolvedPlugin, S as SkippedPlugin } from './workshop-repo-DqoVdcGu.js';
4
4
  import '@kanyun-ai-infra/band-contracts';
5
5
  import 'zod';
6
6
 
package/dist/vite.js CHANGED
@@ -4,12 +4,12 @@ import {
4
4
  import {
5
5
  officialPluginsDir,
6
6
  officialProfilePath
7
- } from "./chunk-RAD6MMSL.js";
7
+ } from "./chunk-XPLYTHNX.js";
8
8
  import {
9
9
  readProfileLocked,
10
10
  resolveOfficialPlugins,
11
11
  resolveWorkshopRepo
12
- } from "./chunk-TN7Z3OF6.js";
12
+ } from "./chunk-LGYGWMSY.js";
13
13
 
14
14
  // src/vite.ts
15
15
  import { existsSync } from "fs";
@@ -38,10 +38,10 @@ interface PayloadSchema {
38
38
  declare const StageSchema: z.ZodObject<{
39
39
  kind: z.ZodOptional<z.ZodEnum<{
40
40
  external: "external";
41
- human: "human";
42
41
  agent: "agent";
43
- workflow: "workflow";
42
+ human: "human";
44
43
  job: "job";
44
+ workflow: "workflow";
45
45
  }>>;
46
46
  type: z.ZodOptional<z.ZodEnum<{
47
47
  generate: "generate";
@@ -194,13 +194,13 @@ declare const WorkshopSchema: z.ZodObject<{
194
194
  }>>>;
195
195
  connectors: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
196
196
  scope: z.ZodEnum<{
197
- workshop: "workshop";
198
197
  personal: "personal";
198
+ workshop: "workshop";
199
199
  deployment: "deployment";
200
200
  }>;
201
201
  inTurn: z.ZodOptional<z.ZodArray<z.ZodString>>;
202
202
  }, z.core.$strict>>, Record<string, {
203
- scope: "workshop" | "personal" | "deployment";
203
+ scope: "personal" | "workshop" | "deployment";
204
204
  inTurn?: string[] | undefined;
205
205
  }>>>;
206
206
  overrides: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodUnknown>, Record<string, unknown>>>;
@@ -216,9 +216,9 @@ declare const WorkshopSchema: z.ZodObject<{
216
216
  process: "process";
217
217
  }>>;
218
218
  storage: z.ZodOptional<z.ZodEnum<{
219
+ external: "external";
219
220
  git: "git";
220
221
  store: "store";
221
- external: "external";
222
222
  }>>;
223
223
  exports: z.ZodOptional<z.ZodArray<z.ZodEnum<{
224
224
  pdf: "pdf";
@@ -265,10 +265,10 @@ declare const WorkshopSchema: z.ZodObject<{
265
265
  stages: z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
266
266
  kind: z.ZodOptional<z.ZodEnum<{
267
267
  external: "external";
268
- human: "human";
269
268
  agent: "agent";
270
- workflow: "workflow";
269
+ human: "human";
271
270
  job: "job";
271
+ workflow: "workflow";
272
272
  }>>;
273
273
  type: z.ZodOptional<z.ZodEnum<{
274
274
  generate: "generate";
@@ -516,14 +516,14 @@ declare const WorkshopSchema: z.ZodObject<{
516
516
  }>>>;
517
517
  surfaces: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>, Record<string, string[]>>>;
518
518
  statusLabels: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodEnum<{
519
+ failed: "failed";
519
520
  blocked: "blocked";
520
521
  ready: "ready";
521
522
  in_progress: "in_progress";
522
523
  in_review: "in_review";
523
524
  approved: "approved";
524
525
  stale: "stale";
525
- failed: "failed";
526
- }> & z.core.$partial, z.ZodString>, Partial<Record<"blocked" | "ready" | "in_progress" | "in_review" | "approved" | "stale" | "failed", string>>>>;
526
+ }> & z.core.$partial, z.ZodString>, Partial<Record<"failed" | "blocked" | "ready" | "in_progress" | "in_review" | "approved" | "stale", string>>>>;
527
527
  }, z.core.$strict>>;
528
528
  }, z.core.$strict>;
529
529
  type WorkshopDef = z.infer<typeof WorkshopSchema>;
@@ -600,7 +600,7 @@ interface CompiledWorkshop {
600
600
  agents: Record<string, CompiledAgent>;
601
601
  /** 进行中的流程实例钉住这个哈希;新版工坊只影响新项目。 */
602
602
  workshopHash: string;
603
- /** 1.x 仍接受、2.0 起报错的写法;`band check` 原样打印,不算失败。 */
603
+ /** 当前仍接受、以后的协议大版本会改成报错的写法;`band check` 原样打印,不算失败。 */
604
604
  warnings: string[];
605
605
  }
606
606
  interface CompileOptions {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanyun-ai-infra/band-cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "band 命令行:新建、本地调试、校验与发布 Band 工坊和插件",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -15,7 +15,8 @@
15
15
  },
16
16
  "./build": {
17
17
  "types": "./dist/build-plugin.d.ts",
18
- "import": "./dist/build-plugin.js"
18
+ "import": "./dist/build-plugin.js",
19
+ "default": "./dist/build-plugin.js"
19
20
  },
20
21
  "./catalog": {
21
22
  "types": "./dist/plugin-entry.d.ts",
@@ -33,6 +34,8 @@
33
34
  "files": [
34
35
  "dist",
35
36
  "dev-host",
37
+ "src/dev-managers.ts",
38
+ "src/inspector-plugins.ts",
36
39
  "src/load-plugins.ts",
37
40
  "bundled"
38
41
  ],
@@ -40,12 +43,12 @@
40
43
  "node": ">=22.19"
41
44
  },
42
45
  "dependencies": {
43
- "@kanyun-ai-infra/band-contracts": "^0.1.1",
44
- "@kanyun-ai-infra/band-plugin-react": "^0.1.1",
45
- "@kanyun-ai-infra/band-plugin-sdk": "^1.213.0",
46
+ "@kanyun-ai-infra/band-contracts": "^0.1.3",
47
+ "@kanyun-ai-infra/band-plugin-react": "^0.2.0",
48
+ "@kanyun-ai-infra/band-plugin-sdk": "^2.0.0",
46
49
  "es-module-lexer": "^2.3.2",
47
- "react": "^18.3.1",
48
- "react-dom": "^18.3.1",
50
+ "react": "^19.3.1",
51
+ "react-dom": "^19.3.1",
49
52
  "semver": "^7.8.5",
50
53
  "vite": "^6.0.7",
51
54
  "yaml": "^2.6.1",
@@ -0,0 +1,16 @@
1
+ /**
2
+ * band dev 的 dev-host 里谁算项目管理员(夹具 `FixtureData.managers`)。
3
+ *
4
+ * 与线上同构:只有 owner / maintainer 管项目。不带 `?role=`(或角色不在工坊里)是默认开发身份,按管理员看;
5
+ * 选了工坊里的业务角色(`?role=teacher` 这类)就是非管理员,预览得到非管理员视图。业务角色不是管理角色。
6
+ * 不从起始身份推创建人:dev-host 的身份恒为 `dev`,推出来会让任何角色都变成管理员。
7
+ */
8
+ export function devManagers(
9
+ roleParam: string | null,
10
+ workshopRoles: readonly string[],
11
+ memberId: string,
12
+ ): string[] {
13
+ const picked = roleParam !== null && workshopRoles.includes(roleParam);
14
+ const manages = !picked || roleParam === "owner" || roleParam === "maintainer";
15
+ return manages ? [memberId] : [];
16
+ }
@@ -0,0 +1,18 @@
1
+ import type { AssembledPlugin } from "@kanyun-ai-infra/band-plugin-sdk";
2
+
3
+ /**
4
+ * `band dev` 宿主自己在运行时里的身份:不贡献任何东西,只为拿一份项目作用域的 ctx。装配里它的 origin 是
5
+ * official,但它不是官方插件,「夹具」栏不列它。
6
+ */
7
+ export const DEV_HOST_PLUGIN = "@kanyun-ai-infra/band-dev-host";
8
+
9
+ /** 「夹具」栏的插件一行:作者自己的插件展开列,官方插件折起来;宿主自己不列。 */
10
+ export function splitInspectorPlugins<P extends Pick<AssembledPlugin, "name" | "origin">>(
11
+ plugins: P[],
12
+ ): { own: P[]; official: P[] } {
13
+ const listed = plugins.filter((p) => p.name !== DEV_HOST_PLUGIN);
14
+ return {
15
+ own: listed.filter((p) => p.origin !== "official"),
16
+ official: listed.filter((p) => p.origin === "official"),
17
+ };
18
+ }