@clawos-dev/clawd 0.2.562 → 0.2.564

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.
@@ -21498,7 +21498,12 @@ var EnvPackageSchema = external_exports.object({
21498
21498
  version: external_exports.string().optional(),
21499
21499
  // 版本下限('20.6' 这种)。与 version 的区别:version 是「就要这个」,min 是「不低于」。
21500
21500
  // 两者都缺省即完全不约束。
21501
- min: external_exports.string().optional()
21501
+ min: external_exports.string().optional(),
21502
+ /**
21503
+ * 没有可执行、只是个包(引擎扩展这类:pi 底座里的 cliproxyapi 扩展)。构建器只断言它装上了(npm ls),不查 PATH 上有没有 `name` 这条命令。
21504
+ * 只有引擎底座清单(cloud-host/engines/<e>/manifest.json)用得到;扫描器不产它。
21505
+ */
21506
+ library: external_exports.boolean().optional()
21502
21507
  });
21503
21508
  var EnvSecretSchema = external_exports.object({
21504
21509
  // 凭据的命名引用('aliyun-ak' / 'supabase-shared')。部署时按这个名字去解析实际的值。
@@ -24954,7 +24959,7 @@ var L = [
24954
24959
  " # \u767B\u8BB0\u6B63\u5F0F\u53EA\u662F\u5F80 gateway \u5199\u4E00\u884C\uFF0Cgateway \u4E0D\u78B0\u955C\u50CF\uFF1B\u96C6\u7FA4\u62C9\u955C\u50CF\u53D1\u751F\u5728\u7B2C\u4E00\u4E2A\u4EFB\u52A1\u5230\u6765\u65F6\u3002",
24955
24960
  " # \u6CA1\u6709\u8FD9\u4E00\u6B65\uFF0C\u6D41\u6C34\u7EBF\u7EFF\u4E86\u53EA\u4EE3\u8868\u300C\u767B\u8BB0\u4E86\u300D\u3002",
24956
24961
  // 模型 / 档位 / 连接器 smoke 也要:试跑那次要跟正式那次拿到同一份,否则验的不是将要上线的东西。
24957
- // 名字形状 deploy-file.mjs 已卡死(persona_id [a-z0-9-]、model / effort [A-Za-z0-9._-]、size 三档枚举、task_concurrency 正整数、connectors 无单引号
24962
+ // 名字形状 deploy-file.mjs 已卡死(persona_id [a-z0-9-]、model / effort [A-Za-z0-9._/-](`/` 是 pi 的 provider/id,不是元字符)、size 四档枚举、task_concurrency 正整数、connectors 无单引号
24958
24963
  // 无换行),所以单引号包住直接拼进命令行是安全的。
24959
24964
  " env:",
24960
24965
  " CLAWD_GATEWAY_URL: ${{ vars.CLAWD_GATEWAY_URL }}",
package/dist/cli.cjs CHANGED
@@ -6019,7 +6019,12 @@ var init_environment_schemas = __esm({
6019
6019
  version: external_exports.string().optional(),
6020
6020
  // 版本下限('20.6' 这种)。与 version 的区别:version 是「就要这个」,min 是「不低于」。
6021
6021
  // 两者都缺省即完全不约束。
6022
- min: external_exports.string().optional()
6022
+ min: external_exports.string().optional(),
6023
+ /**
6024
+ * 没有可执行、只是个包(引擎扩展这类:pi 底座里的 cliproxyapi 扩展)。构建器只断言它装上了(npm ls),不查 PATH 上有没有 `name` 这条命令。
6025
+ * 只有引擎底座清单(cloud-host/engines/<e>/manifest.json)用得到;扫描器不产它。
6026
+ */
6027
+ library: external_exports.boolean().optional()
6023
6028
  });
6024
6029
  EnvSecretSchema = external_exports.object({
6025
6030
  // 凭据的命名引用('aliyun-ak' / 'supabase-shared')。部署时按这个名字去解析实际的值。
@@ -6106,12 +6111,12 @@ function isScanFresh(scan, repo2, released) {
6106
6111
  return scan.head === contentHeadOf(repo2, released) && !repo2.dirty;
6107
6112
  }
6108
6113
  function cloudEngineOk(tool) {
6109
- return (tool || "claude") === "codex";
6114
+ return CLOUD_ENGINES.includes(tool || "claude");
6110
6115
  }
6111
6116
  function repoSlug(url) {
6112
6117
  return url.trim().replace(/^git@[^:]+:/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/\.git$/, "");
6113
6118
  }
6114
- var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, DeployStateSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6119
+ var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, CLOUD_ENGINES, DeployStateSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6115
6120
  var init_deploy_schemas = __esm({
6116
6121
  "../protocol/src/deploy-schemas.ts"() {
6117
6122
  "use strict";
@@ -6218,6 +6223,7 @@ var init_deploy_schemas = __esm({
6218
6223
  /** run 刚入队时可能一条都还没有 */
6219
6224
  jobs: external_exports.array(DeployJobSchema)
6220
6225
  }).strict();
6226
+ CLOUD_ENGINES = ["codex", "pi"];
6221
6227
  DeployStateSchema = external_exports.object({
6222
6228
  personaId: external_exports.string().min(1),
6223
6229
  /** 本机 GitHub 身份(机器级,githubAuth:* 的同一份;上云页顶上那张卡用)。老 daemon 不给(可选只为兼容),UI 缺席时按未知处理 */
@@ -44537,7 +44543,7 @@ Env (advanced):
44537
44543
  var import_node_path78 = __toESM(require("path"), 1);
44538
44544
  var import_node_fs60 = __toESM(require("fs"), 1);
44539
44545
  var import_node_os28 = __toESM(require("os"), 1);
44540
- var import_node_crypto23 = require("crypto");
44546
+ var import_node_crypto24 = require("crypto");
44541
44547
  var import_node_url5 = require("url");
44542
44548
 
44543
44549
  // src/logger.ts
@@ -59451,7 +59457,7 @@ var L2 = [
59451
59457
  " # \u767B\u8BB0\u6B63\u5F0F\u53EA\u662F\u5F80 gateway \u5199\u4E00\u884C\uFF0Cgateway \u4E0D\u78B0\u955C\u50CF\uFF1B\u96C6\u7FA4\u62C9\u955C\u50CF\u53D1\u751F\u5728\u7B2C\u4E00\u4E2A\u4EFB\u52A1\u5230\u6765\u65F6\u3002",
59452
59458
  " # \u6CA1\u6709\u8FD9\u4E00\u6B65\uFF0C\u6D41\u6C34\u7EBF\u7EFF\u4E86\u53EA\u4EE3\u8868\u300C\u767B\u8BB0\u4E86\u300D\u3002",
59453
59459
  // 模型 / 档位 / 连接器 smoke 也要:试跑那次要跟正式那次拿到同一份,否则验的不是将要上线的东西。
59454
- // 名字形状 deploy-file.mjs 已卡死(persona_id [a-z0-9-]、model / effort [A-Za-z0-9._-]、size 三档枚举、task_concurrency 正整数、connectors 无单引号
59460
+ // 名字形状 deploy-file.mjs 已卡死(persona_id [a-z0-9-]、model / effort [A-Za-z0-9._/-](`/` 是 pi 的 provider/id,不是元字符)、size 四档枚举、task_concurrency 正整数、connectors 无单引号
59455
59461
  // 无换行),所以单引号包住直接拼进命令行是安全的。
59456
59462
  " env:",
59457
59463
  " CLAWD_GATEWAY_URL: ${{ vars.CLAWD_GATEWAY_URL }}",
@@ -59819,7 +59825,7 @@ function ensureOwner(ctx) {
59819
59825
  }
59820
59826
  var invalid = (msg) => new ClawdError(ERROR_CODES.VALIDATION_ERROR, `VALIDATION_ERROR: ${msg}`);
59821
59827
  function wrongEngine(tool) {
59822
- return cloudEngineOk(tool) ? void 0 : `\u5F15\u64CE\u662F ${tool || "claude"}\uFF0C\u4E91\u4E0A\u53EA\u8DD1 Codex\u2014\u2014\u53BB persona \u8BBE\u7F6E\u91CC\u628A\u5F15\u64CE\u5207\u6210 Codex\uFF0C\u518D\u9009\u4E2A\u6A21\u578B`;
59828
+ return cloudEngineOk(tool) ? void 0 : `\u5F15\u64CE\u662F ${tool || "claude"}\uFF0C\u4E91\u4E0A\u53EA\u8DD1 Codex \u6216 pi\u2014\u2014\u53BB persona \u8BBE\u7F6E\u91CC\u628A\u5F15\u64CE\u5207\u6210 Codex \u6216 pi\uFF0C\u518D\u9009\u4E2A\u6A21\u578B`;
59823
59829
  }
59824
59830
  var NO_GITHUB_AUTH = "\u8FD8\u6CA1\u5173\u8054 GitHub\uFF1A\u5728\u8BBE\u7F6E \u2192 \u8D26\u53F7\uFF08\u6216\u4E0A\u4E91\u9875\u9876\u4E0A\u90A3\u5F20\u5361\uFF09\u91CC\u70B9\u300C\u5173\u8054 GitHub\u300D";
59825
59831
  function toClawdError(err) {
@@ -62594,6 +62600,7 @@ async function centralGithubAuthToken(opts) {
62594
62600
  }
62595
62601
 
62596
62602
  // src/cloud/gateway-client.ts
62603
+ var CLOUD_WORKSPACE_SLOT = "{{WORKSPACE}}";
62597
62604
  var GATEWAY_ROUTES = {
62598
62605
  healthz: () => "/healthz",
62599
62606
  session: (personaId2) => `/p/${encodeURIComponent(personaId2)}/session`,
@@ -62694,7 +62701,8 @@ var CloudGatewayClient = class {
62694
62701
  * 会话通道。返回的行流在 Pod 就绪前就能 write:写入先攒着,收到 `ready` 控制行后按序 POST 出去——
62695
62702
  * 编排那头一构造就发 initialize,不用知道 Pod 还在起。
62696
62703
  * `toolSessionId`:调用方预分配的引擎会话 id(pi 的 --session-id;codex 的 thread id 是协议内的、不传),进 open 的 body `engineSessionId`
62697
- * (契约 2026-09-18 §3.2)。
62704
+ * (契约 2026-09-18 §3.2)。`instructions`:会话级指令(pi-cloud 的连接 intro,工作目录写 CLOUD_WORKSPACE_SLOT),进 body `instructions`,
62705
+ * gateway 落成 Pod 里的 /run/agent/instructions.md(契约 §3.1);codex-cloud 不发(走协议内 developerInstructions)。
62698
62706
  */
62699
62707
  async openSession(personaId2, opts = {}) {
62700
62708
  const { apiKey, gatewayUrl } = await this.credentials();
@@ -62704,6 +62712,7 @@ var CloudGatewayClient = class {
62704
62712
  apiKey,
62705
62713
  personaId: personaId2,
62706
62714
  ...opts.toolSessionId ? { engineSessionId: opts.toolSessionId } : {},
62715
+ ...opts.instructions ? { instructions: opts.instructions } : {},
62707
62716
  logger: this.deps.logger
62708
62717
  });
62709
62718
  }
@@ -62748,7 +62757,7 @@ function parseControlLine(line) {
62748
62757
  }
62749
62758
  }
62750
62759
  function openHttpLineStream(opts) {
62751
- const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, engineSessionId, logger } = opts;
62760
+ const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, engineSessionId, instructions, logger } = opts;
62752
62761
  const headers = { authorization: `Bearer ${apiKey}`, "content-type": "application/json" };
62753
62762
  const ac = new AbortController();
62754
62763
  const lineCbs = [];
@@ -62805,7 +62814,7 @@ function openHttpLineStream(opts) {
62805
62814
  res = await fetchImpl(gatewayUrl + GATEWAY_ROUTES.session(personaId2), {
62806
62815
  method: "POST",
62807
62816
  headers,
62808
- body: JSON.stringify(engineSessionId ? { engineSessionId } : {}),
62817
+ body: JSON.stringify({ ...engineSessionId ? { engineSessionId } : {}, ...instructions ? { instructions } : {} }),
62809
62818
  signal: ac.signal
62810
62819
  });
62811
62820
  } catch (e) {
@@ -63162,6 +63171,9 @@ var CloudCodexAdapter = class {
63162
63171
  }
63163
63172
  };
63164
63173
 
63174
+ // src/tools/pi-cloud.ts
63175
+ init_protocol();
63176
+
63165
63177
  // src/tools/pi.ts
63166
63178
  var import_node_child_process11 = require("child_process");
63167
63179
  var import_node_fs37 = __toESM(require("fs"), 1);
@@ -63964,6 +63976,152 @@ var PiAdapter = class {
63964
63976
  }
63965
63977
  };
63966
63978
 
63979
+ // src/tools/pi-cloud-session.ts
63980
+ var import_node_crypto11 = require("crypto");
63981
+ function cloudPiInstructions(ctx) {
63982
+ return [ctx.extraSystemPrompt, workDirPrompt(CLOUD_WORKSPACE_SLOT, ctx.personaMode ?? "owner")].filter((x2) => Boolean(x2)).join("\n\n");
63983
+ }
63984
+ function createCloudPiSession(ctx, sink, deps) {
63985
+ const personaId2 = personaIdFromCloudCwd(ctx.cwd);
63986
+ const sessionId = ctx.toolSessionId ?? (0, import_node_crypto11.randomUUID)();
63987
+ const stream = deferredLineStream();
63988
+ let channel = null;
63989
+ const driver = drivePiSession({
63990
+ sink,
63991
+ stream,
63992
+ sessionId,
63993
+ logger: deps.logger,
63994
+ fetchImage: deps.fetchImage ?? makeImageFetcher(),
63995
+ // 「让对端走人」= 断开下行流,gateway 收到就删 Pod;信号对 Pod 没有意义
63996
+ kill: () => stream.close(),
63997
+ onTurnCompleted: () => void channel?.mirror()
63998
+ });
63999
+ if (!personaId2) {
64000
+ queueMicrotask(() => {
64001
+ sink.onError(`cloud session has no persona id (cwd=${ctx.cwd})`);
64002
+ stream.close();
64003
+ });
64004
+ return driver.session;
64005
+ }
64006
+ void deps.client.openSession(personaId2, { toolSessionId: sessionId, instructions: cloudPiInstructions(ctx) }).then(
64007
+ (opened) => {
64008
+ channel = opened;
64009
+ channel.onControl((c2) => {
64010
+ if (c2.kind === "queued") {
64011
+ sink.pushEvents([{ kind: "meta-text", text: `\u4E91\u4E0A\u673A\u5668\u6709 ${c2.running} \u4E2A\u4EFB\u52A1\u5728\u8DD1\uFF0C\u7B49\u4E00\u4E2A\u7ED3\u675F\u5C31\u8F6E\u5230\u4F60` }]);
64012
+ } else if (c2.kind === "error") {
64013
+ sink.onError(`\u4E91\u4E0A persona \u8D77\u4E0D\u6765\uFF1A${c2.message}`);
64014
+ }
64015
+ });
64016
+ stream.attach(channel);
64017
+ },
64018
+ (e) => {
64019
+ sink.onError(e instanceof CloudApiKeyRequiredError ? e.message : `\u8FDE\u4E0D\u4E0A\u4E91 gateway\uFF1A${e.message}`);
64020
+ stream.close();
64021
+ }
64022
+ );
64023
+ return driver.session;
64024
+ }
64025
+
64026
+ // src/tools/pi-cloud-history.ts
64027
+ var CloudPiHistoryReader = class {
64028
+ constructor(client, logger) {
64029
+ this.client = client;
64030
+ this.logger = logger;
64031
+ }
64032
+ client;
64033
+ logger;
64034
+ async listProjects() {
64035
+ return [];
64036
+ }
64037
+ /** 云 persona 没有「关联已有会话」的动线:会话列表就是本机的会话记录 */
64038
+ async listSessions() {
64039
+ return [];
64040
+ }
64041
+ async read(args) {
64042
+ const text = await this.client.fetchRollout(args.toolSessionId);
64043
+ if (text === null) throw new Error(`pi session not found for ${args.toolSessionId}`);
64044
+ const parsed = parsePiSession(text);
64045
+ if (!parsed.meta) this.logger?.warn("cloud pi session has no header line", { toolSessionId: args.toolSessionId });
64046
+ return pageMessages(parsed.messages, args);
64047
+ }
64048
+ async listSubagents(_args) {
64049
+ return [];
64050
+ }
64051
+ async readSubagent(args) {
64052
+ throw new Error(`pi has no subagent threads (${args.subagentId})`);
64053
+ }
64054
+ computeRewindDiff() {
64055
+ return { canRewind: false, files: [], totalInsertions: 0, totalDeletions: 0 };
64056
+ }
64057
+ listRewindableUserMessageIds() {
64058
+ return [];
64059
+ }
64060
+ };
64061
+
64062
+ // src/tools/pi-cloud.ts
64063
+ var CLOUD_APPROVAL2 = { id: "never", label: "Full Access", description: "\u4E91\u4E0A\u65E0\u4EBA\u503C\u5B88\uFF1A\u4ECE\u4E0D\u8BE2\u95EE\uFF0C\u81EA\u4E3B\u6267\u884C" };
64064
+ var CLOUD_PI_CAPABILITIES = {
64065
+ tool: PI_CLOUD_TOOL_ID,
64066
+ toolSessionIdLabel: "pi Session ID",
64067
+ models: [],
64068
+ permissionModes: [CLOUD_APPROVAL2],
64069
+ // 无 rewind / 无子 agent(pi 核心没有)/ 无 pty / observer 是 CC jsonl 解析器 / 无文件分享 / fork 是 claude jsonl 专用
64070
+ features: { rewind: false, subagents: false, tui: false, observe: false, fileSharing: false, fork: false },
64071
+ configSchema: [
64072
+ {
64073
+ name: "permissionMode",
64074
+ type: "select",
64075
+ label: "Approval",
64076
+ scope: "core",
64077
+ options: [{ value: CLOUD_APPROVAL2.id, label: CLOUD_APPROVAL2.label, description: CLOUD_APPROVAL2.description }],
64078
+ default: "never"
64079
+ }
64080
+ ]
64081
+ };
64082
+ var CloudPiAdapter = class {
64083
+ id = PI_CLOUD_TOOL_ID;
64084
+ /** manager 据此跳过「cwd 是本机目录」的校验(cwd 是 gateway 上的地址) */
64085
+ remote = true;
64086
+ historyReader;
64087
+ client;
64088
+ logger;
64089
+ constructor(opts) {
64090
+ this.client = opts.client;
64091
+ this.logger = opts.logger;
64092
+ this.historyReader = new CloudPiHistoryReader(opts.history, opts.logger);
64093
+ }
64094
+ /** 可用 = 能拿到凭据(登了飞书、生成过 key、中心配了 gateway),与本机装没装 pi 无关 */
64095
+ async probe() {
64096
+ try {
64097
+ const { gatewayUrl } = await this.client.credentials();
64098
+ return { available: true, path: gatewayUrl };
64099
+ } catch (err) {
64100
+ this.logger?.debug?.("pi-cloud probe: unavailable", { reason: err.message });
64101
+ return { available: false };
64102
+ }
64103
+ }
64104
+ async capabilities() {
64105
+ return CLOUD_PI_CAPABILITIES;
64106
+ }
64107
+ // 模型由登记行定、本机不知道它的窗口:给 pi 的缺省,运行时 get_state 的 meta_update 会补真值
64108
+ resolveContextWindow(_modelId) {
64109
+ return PI_DEFAULT_CONTEXT_WINDOW;
64110
+ }
64111
+ createSession(ctx, sink) {
64112
+ return createCloudPiSession(ctx, sink, { client: this.client, logger: this.logger });
64113
+ }
64114
+ spawn(_ctx) {
64115
+ throw new Error("CloudPiAdapter uses createSession, not spawn");
64116
+ }
64117
+ parseLine(_line) {
64118
+ return [];
64119
+ }
64120
+ encodeStdin(text, _ctx) {
64121
+ return text;
64122
+ }
64123
+ };
64124
+
63967
64125
  // src/index.ts
63968
64126
  init_protocol();
63969
64127
 
@@ -64908,7 +65066,7 @@ var wrapper_default = import_websocket.default;
64908
65066
 
64909
65067
  // src/transport/local-ws-server.ts
64910
65068
  var import_node_http = __toESM(require("http"), 1);
64911
- var import_node_crypto11 = require("crypto");
65069
+ var import_node_crypto12 = require("crypto");
64912
65070
  var LocalWsServer = class {
64913
65071
  constructor(opts) {
64914
65072
  this.opts = opts;
@@ -65125,7 +65283,7 @@ var LocalWsServer = class {
65125
65283
  }
65126
65284
  }
65127
65285
  onConnection(socket, remoteAddress) {
65128
- const id = (0, import_node_crypto11.randomUUID)();
65286
+ const id = (0, import_node_crypto12.randomUUID)();
65129
65287
  const subscribedSessions = /* @__PURE__ */ new Map();
65130
65288
  const handle = {
65131
65289
  id,
@@ -66090,7 +66248,7 @@ var import_node_path49 = __toESM(require("path"), 1);
66090
66248
  // src/attachment/upload.ts
66091
66249
  var import_node_fs43 = __toESM(require("fs"), 1);
66092
66250
  var import_node_path47 = __toESM(require("path"), 1);
66093
- var import_node_crypto12 = __toESM(require("crypto"), 1);
66251
+ var import_node_crypto13 = __toESM(require("crypto"), 1);
66094
66252
  var import_promises7 = require("stream/promises");
66095
66253
  var UploadError = class extends Error {
66096
66254
  constructor(code, message) {
@@ -66114,11 +66272,11 @@ async function writeUploadedAttachment(args) {
66114
66272
  } catch (err) {
66115
66273
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
66116
66274
  }
66117
- const hasher = import_node_crypto12.default.createHash("sha256");
66275
+ const hasher = import_node_crypto13.default.createHash("sha256");
66118
66276
  let actualSize = 0;
66119
66277
  const tmpPath = import_node_path47.default.join(
66120
66278
  attachmentsRoot,
66121
- `.upload-${process.pid}-${Date.now()}-${import_node_crypto12.default.randomBytes(4).toString("hex")}`
66279
+ `.upload-${process.pid}-${Date.now()}-${import_node_crypto13.default.randomBytes(4).toString("hex")}`
66122
66280
  );
66123
66281
  try {
66124
66282
  await (0, import_promises7.pipeline)(
@@ -66962,7 +67120,7 @@ function runAttachmentGc(args) {
66962
67120
  // src/attachment/group.ts
66963
67121
  var import_node_fs46 = __toESM(require("fs"), 1);
66964
67122
  var import_node_path51 = __toESM(require("path"), 1);
66965
- var import_node_crypto13 = __toESM(require("crypto"), 1);
67123
+ var import_node_crypto14 = __toESM(require("crypto"), 1);
66966
67124
  init_protocol();
66967
67125
  var GroupFileStore = class {
66968
67126
  dataDir;
@@ -67051,7 +67209,7 @@ var GroupFileStore = class {
67051
67209
  entries[idx] = next;
67052
67210
  } else {
67053
67211
  next = {
67054
- id: `gf-${import_node_crypto13.default.randomBytes(6).toString("base64url")}`,
67212
+ id: `gf-${import_node_crypto14.default.randomBytes(6).toString("base64url")}`,
67055
67213
  relPath: input.relPath,
67056
67214
  from: input.from,
67057
67215
  label: input.label,
@@ -67197,7 +67355,7 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
67197
67355
  // src/tunnel/tunnel-manager.ts
67198
67356
  var import_node_fs51 = __toESM(require("fs"), 1);
67199
67357
  var import_node_path56 = __toESM(require("path"), 1);
67200
- var import_node_crypto14 = __toESM(require("crypto"), 1);
67358
+ var import_node_crypto15 = __toESM(require("crypto"), 1);
67201
67359
  var import_node_child_process15 = require("child_process");
67202
67360
 
67203
67361
  // src/tunnel/tunnel-store.ts
@@ -67696,7 +67854,7 @@ var TunnelManager = class {
67696
67854
  override: this.deps.frpcBinaryOverride ?? void 0
67697
67855
  });
67698
67856
  const tomlPath = import_node_path56.default.join(this.deps.dataDir, "frpc.toml");
67699
- const proxyName = `clawd-${t2.subdomain}-${localPort}-${import_node_crypto14.default.randomBytes(3).toString("hex")}`;
67857
+ const proxyName = `clawd-${t2.subdomain}-${localPort}-${import_node_crypto15.default.randomBytes(3).toString("hex")}`;
67700
67858
  const toml = buildFrpcToml({
67701
67859
  serverAddr: t2.frpsHost,
67702
67860
  serverPort: t2.frpsPort,
@@ -67797,7 +67955,7 @@ async function waitForFrpcReady(proc, timeoutMs) {
67797
67955
  // src/tunnel/device-key.ts
67798
67956
  var import_node_os18 = __toESM(require("os"), 1);
67799
67957
  var import_node_path57 = __toESM(require("path"), 1);
67800
- var import_node_crypto15 = __toESM(require("crypto"), 1);
67958
+ var import_node_crypto16 = __toESM(require("crypto"), 1);
67801
67959
  var DERIVE_SALT = "clawd-tunnel-device-v1";
67802
67960
  function deriveStableDeviceKey(opts = {}) {
67803
67961
  const hostname = opts.hostname ?? import_node_os18.default.hostname();
@@ -67807,13 +67965,13 @@ function deriveStableDeviceKey(opts = {}) {
67807
67965
  const normalizedDataDir = opts.dataDir ? import_node_path57.default.resolve(opts.dataDir) : null;
67808
67966
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
67809
67967
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
67810
- return import_node_crypto15.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
67968
+ return import_node_crypto16.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
67811
67969
  }
67812
67970
 
67813
67971
  // src/auth-store.ts
67814
67972
  var import_node_fs52 = __toESM(require("fs"), 1);
67815
67973
  var import_node_path58 = __toESM(require("path"), 1);
67816
- var import_node_crypto16 = __toESM(require("crypto"), 1);
67974
+ var import_node_crypto17 = __toESM(require("crypto"), 1);
67817
67975
  var AUTH_FILE_NAME = "auth.json";
67818
67976
  function authFilePath(dataDir) {
67819
67977
  return import_node_path58.default.join(dataDir, AUTH_FILE_NAME);
@@ -67850,10 +68008,10 @@ function loadOrCreateTunnelDeviceKey(opts) {
67850
68008
  return tunnelDeviceKey;
67851
68009
  }
67852
68010
  function defaultGenerateToken() {
67853
- return import_node_crypto16.default.randomBytes(32).toString("base64url");
68011
+ return import_node_crypto17.default.randomBytes(32).toString("base64url");
67854
68012
  }
67855
68013
  function defaultGenerateOwnerPrincipalId() {
67856
- return `owner-${import_node_crypto16.default.randomUUID()}`;
68014
+ return `owner-${import_node_crypto17.default.randomUUID()}`;
67857
68015
  }
67858
68016
  function readAuthFile(file) {
67859
68017
  try {
@@ -67985,7 +68143,7 @@ var OwnerIdentityStore = class {
67985
68143
  };
67986
68144
 
67987
68145
  // src/feishu-auth/login-flow.ts
67988
- var import_node_crypto17 = __toESM(require("crypto"), 1);
68146
+ var import_node_crypto18 = __toESM(require("crypto"), 1);
67989
68147
  var STATE_TTL_MS = 5 * 60 * 1e3;
67990
68148
  var LoginFlow = class {
67991
68149
  constructor(deps) {
@@ -67994,7 +68152,7 @@ var LoginFlow = class {
67994
68152
  deps;
67995
68153
  pendingStates = /* @__PURE__ */ new Map();
67996
68154
  start() {
67997
- const state = import_node_crypto17.default.randomBytes(16).toString("base64url");
68155
+ const state = import_node_crypto18.default.randomBytes(16).toString("base64url");
67998
68156
  const now = (this.deps.now ?? Date.now)();
67999
68157
  this.pendingStates.set(state, now);
68000
68158
  this.gcExpired(now);
@@ -68525,7 +68683,7 @@ init_protocol();
68525
68683
  var import_node_fs55 = __toESM(require("fs"), 1);
68526
68684
  var import_node_os20 = __toESM(require("os"), 1);
68527
68685
  var import_node_path61 = __toESM(require("path"), 1);
68528
- var import_node_crypto18 = require("crypto");
68686
+ var import_node_crypto19 = require("crypto");
68529
68687
  init_claude_history();
68530
68688
  function readJsonlEntries(file) {
68531
68689
  const raw = import_node_fs55.default.readFileSync(file, "utf8");
@@ -68562,7 +68720,7 @@ function forkSession(input) {
68562
68720
  throw new Error(`fork: messageUuid not found in transcript: ${input.messageUuid}`);
68563
68721
  }
68564
68722
  const sliced = mainEntries.slice(0, targetIdx + 1);
68565
- const forkedToolSessionId = (0, import_node_crypto18.randomUUID)();
68723
+ const forkedToolSessionId = (0, import_node_crypto19.randomUUID)();
68566
68724
  let parentUuid = null;
68567
68725
  const forkedLines = [];
68568
68726
  for (const entry of sliced) {
@@ -69769,7 +69927,7 @@ function buildWorkspaceHandlers(deps) {
69769
69927
  const args = AgentsListArgs.parse(frame);
69770
69928
  const cwdAbs = path80.resolve(args.cwd);
69771
69929
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
69772
- if (isCodexFamily(args.tool) || args.tool === PI_TOOL_ID) {
69930
+ if (isCodexFamily(args.tool) || isPiFamily(args.tool)) {
69773
69931
  return { response: { type: "agents:list", agents: [] } };
69774
69932
  }
69775
69933
  const list2 = agents.list(args);
@@ -71150,7 +71308,7 @@ function computeMethodAccess(args) {
71150
71308
  }
71151
71309
 
71152
71310
  // src/version.ts
71153
- var version = "0.2.562".length > 0 ? "0.2.562" : "dev";
71311
+ var version = "0.2.564".length > 0 ? "0.2.564" : "dev";
71154
71312
 
71155
71313
  // src/cli-probe/probe.ts
71156
71314
  var fs78 = __toESM(require("fs"), 1);
@@ -71547,7 +71705,7 @@ init_protocol();
71547
71705
  // src/extension/bundle-zip.ts
71548
71706
  var import_promises11 = __toESM(require("fs/promises"), 1);
71549
71707
  var import_node_path67 = __toESM(require("path"), 1);
71550
- var import_node_crypto19 = __toESM(require("crypto"), 1);
71708
+ var import_node_crypto20 = __toESM(require("crypto"), 1);
71551
71709
  var import_jszip2 = __toESM(require_lib3(), 1);
71552
71710
  async function bundleExtensionDir(dir) {
71553
71711
  const entries = await listFilesSorted(dir);
@@ -71562,7 +71720,7 @@ async function bundleExtensionDir(dir) {
71562
71720
  compression: "DEFLATE",
71563
71721
  compressionOptions: { level: 6 }
71564
71722
  });
71565
- const sha256 = import_node_crypto19.default.createHash("sha256").update(buffer).digest("hex");
71723
+ const sha256 = import_node_crypto20.default.createHash("sha256").update(buffer).digest("hex");
71566
71724
  return { buffer, sha256 };
71567
71725
  }
71568
71726
  var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
@@ -71630,7 +71788,7 @@ function computePublishCheck(args) {
71630
71788
  var import_promises12 = __toESM(require("fs/promises"), 1);
71631
71789
  var import_node_path69 = __toESM(require("path"), 1);
71632
71790
  var import_node_os25 = __toESM(require("os"), 1);
71633
- var import_node_crypto20 = __toESM(require("crypto"), 1);
71791
+ var import_node_crypto21 = __toESM(require("crypto"), 1);
71634
71792
  var import_jszip3 = __toESM(require_lib3(), 1);
71635
71793
 
71636
71794
  // src/extension/paths.ts
@@ -71659,7 +71817,7 @@ var InstallError = class extends Error {
71659
71817
  };
71660
71818
  async function installFromChannel(args, deps) {
71661
71819
  const { channelRef, snapshotHash, bundleZip } = args;
71662
- const computed = import_node_crypto20.default.createHash("sha256").update(bundleZip).digest("hex");
71820
+ const computed = import_node_crypto21.default.createHash("sha256").update(bundleZip).digest("hex");
71663
71821
  if (computed !== snapshotHash) {
71664
71822
  throw new InstallError(
71665
71823
  "HASH_MISMATCH",
@@ -71751,7 +71909,7 @@ async function installFromChannel(args, deps) {
71751
71909
  var import_promises13 = __toESM(require("fs/promises"), 1);
71752
71910
  var import_node_path70 = __toESM(require("path"), 1);
71753
71911
  var import_node_os26 = __toESM(require("os"), 1);
71754
- var import_node_crypto21 = __toESM(require("crypto"), 1);
71912
+ var import_node_crypto22 = __toESM(require("crypto"), 1);
71755
71913
  var import_jszip4 = __toESM(require_lib3(), 1);
71756
71914
  var UpdateError = class extends Error {
71757
71915
  constructor(code, message) {
@@ -71789,7 +71947,7 @@ async function updateFromChannel(args, deps) {
71789
71947
  if (e instanceof UpdateError) throw e;
71790
71948
  throw e;
71791
71949
  }
71792
- const computed = import_node_crypto21.default.createHash("sha256").update(bundleZip).digest("hex");
71950
+ const computed = import_node_crypto22.default.createHash("sha256").update(bundleZip).digest("hex");
71793
71951
  if (computed !== snapshotHash) {
71794
71952
  throw new UpdateError(
71795
71953
  "HASH_MISMATCH",
@@ -72918,7 +73076,7 @@ async function uninstall(deps) {
72918
73076
  }
72919
73077
 
72920
73078
  // src/handlers/index.ts
72921
- var import_node_crypto22 = require("crypto");
73079
+ var import_node_crypto23 = require("crypto");
72922
73080
 
72923
73081
  // src/handlers/peer-exec.ts
72924
73082
  init_protocol();
@@ -73073,7 +73231,7 @@ function buildMethodHandlers(deps) {
73073
73231
  const c2 = deps.contactStore.get(deviceId);
73074
73232
  return c2 ? { deviceId: c2.deviceId, remoteUrl: c2.remoteUrl, connectToken: c2.connectToken } : null;
73075
73233
  },
73076
- genId: () => (0, import_node_crypto22.randomUUID)(),
73234
+ genId: () => (0, import_node_crypto23.randomUUID)(),
73077
73235
  now: () => Date.now(),
73078
73236
  forwardInboxPostToPeer,
73079
73237
  logger: deps.logger
@@ -73802,7 +73960,7 @@ async function startDaemon(config) {
73802
73960
  const channelStore = createChannelStore({
73803
73961
  filePath: import_node_path78.default.join(config.dataDir, "channels.json"),
73804
73962
  now: () => Date.now(),
73805
- genId: () => `ch-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
73963
+ genId: () => `ch-${(0, import_node_crypto24.randomUUID)().slice(0, 8)}`,
73806
73964
  onFlushError: (err) => logger.error("channel store flush failed", {
73807
73965
  reason: err instanceof Error ? err.message : String(err)
73808
73966
  })
@@ -73811,7 +73969,7 @@ async function startDaemon(config) {
73811
73969
  const topicStore = createTopicStore({
73812
73970
  filePath: import_node_path78.default.join(config.dataDir, "topics.json"),
73813
73971
  now: () => Date.now(),
73814
- genId: () => `tp-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
73972
+ genId: () => `tp-${(0, import_node_crypto24.randomUUID)().slice(0, 8)}`,
73815
73973
  onFlushError: (err) => logger.error("topic store flush failed", {
73816
73974
  reason: err instanceof Error ? err.message : String(err)
73817
73975
  })
@@ -73819,7 +73977,7 @@ async function startDaemon(config) {
73819
73977
  await topicStore.load();
73820
73978
  let deliverPendingRef;
73821
73979
  const personaDispatchManager = new PersonaDispatchManager({
73822
- genId: () => (0, import_node_crypto23.randomUUID)(),
73980
+ genId: () => (0, import_node_crypto24.randomUUID)(),
73823
73981
  store: dispatchStore,
73824
73982
  now: () => Date.now(),
73825
73983
  onCompleted: (sid) => deliverPendingRef?.(sid),
@@ -74266,22 +74424,23 @@ async function startDaemon(config) {
74266
74424
  getSignSecret: () => authFile.token
74267
74425
  })
74268
74426
  );
74427
+ const cloudHistorySource = {
74428
+ fetchRollout: (threadId) => {
74429
+ const loginPass = ownerIdentityStore.read()?.loginPass;
74430
+ if (!loginPass) return Promise.resolve(null);
74431
+ return centralGetThread({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, loginPass, threadId });
74432
+ }
74433
+ };
74269
74434
  registerAdapter(
74270
74435
  CODEX_CLOUD_TOOL_ID,
74271
74436
  new CloudCodexAdapter({
74272
74437
  client: cloudGateway,
74273
- // 历史副本从中心拉(design 2026-09-19-cloud-session-oss §3.4):没登录就没有历史,不抛
74274
- history: {
74275
- fetchRollout: (threadId) => {
74276
- const loginPass = ownerIdentityStore.read()?.loginPass;
74277
- if (!loginPass) return Promise.resolve(null);
74278
- return centralGetThread({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, loginPass, threadId });
74279
- }
74280
- },
74438
+ history: cloudHistorySource,
74281
74439
  logger,
74282
74440
  getSignSecret: () => authFile.token
74283
74441
  })
74284
74442
  );
74443
+ registerAdapter(PI_CLOUD_TOOL_ID, new CloudPiAdapter({ client: cloudGateway, history: cloudHistorySource, logger }));
74285
74444
  const piMcpBridgeCandidates = [
74286
74445
  import_node_path78.default.join(here, "pi-mcp-bridge", "extension.cjs"),
74287
74446
  import_node_path78.default.join(here, "..", "dist", "pi-mcp-bridge", "extension.cjs")
@@ -74802,7 +74961,7 @@ async function startDaemon(config) {
74802
74961
  const deployHandlers = buildDeployHandlers({
74803
74962
  hasPersona: (personaId2) => personaStore.has(personaId2),
74804
74963
  personaDir: (personaId2) => personaStore.personaDirPath(personaId2),
74805
- // 发布前落闸要看它现在配的引擎和模型(云上只跑 codex,且模型跟着这次发布走)
74964
+ // 发布前落闸要看它现在配的引擎和模型(云上只跑 codex / pi,且模型跟着这次发布走)
74806
74965
  personaEngine: (personaId2) => {
74807
74966
  const p3 = personaRegistry.get(personaId2);
74808
74967
  return p3 ? { ...p3.tool ? { tool: p3.tool } : {}, ...p3.model ? { model: p3.model } : {} } : void 0;
@@ -21312,7 +21312,12 @@ var EnvPackageSchema = external_exports.object({
21312
21312
  version: external_exports.string().optional(),
21313
21313
  // 版本下限('20.6' 这种)。与 version 的区别:version 是「就要这个」,min 是「不低于」。
21314
21314
  // 两者都缺省即完全不约束。
21315
- min: external_exports.string().optional()
21315
+ min: external_exports.string().optional(),
21316
+ /**
21317
+ * 没有可执行、只是个包(引擎扩展这类:pi 底座里的 cliproxyapi 扩展)。构建器只断言它装上了(npm ls),不查 PATH 上有没有 `name` 这条命令。
21318
+ * 只有引擎底座清单(cloud-host/engines/<e>/manifest.json)用得到;扫描器不产它。
21319
+ */
21320
+ library: external_exports.boolean().optional()
21316
21321
  });
21317
21322
  var EnvSecretSchema = external_exports.object({
21318
21323
  // 凭据的命名引用('aliyun-ak' / 'supabase-shared')。部署时按这个名字去解析实际的值。
@@ -21498,7 +21498,12 @@ var EnvPackageSchema = external_exports.object({
21498
21498
  version: external_exports.string().optional(),
21499
21499
  // 版本下限('20.6' 这种)。与 version 的区别:version 是「就要这个」,min 是「不低于」。
21500
21500
  // 两者都缺省即完全不约束。
21501
- min: external_exports.string().optional()
21501
+ min: external_exports.string().optional(),
21502
+ /**
21503
+ * 没有可执行、只是个包(引擎扩展这类:pi 底座里的 cliproxyapi 扩展)。构建器只断言它装上了(npm ls),不查 PATH 上有没有 `name` 这条命令。
21504
+ * 只有引擎底座清单(cloud-host/engines/<e>/manifest.json)用得到;扫描器不产它。
21505
+ */
21506
+ library: external_exports.boolean().optional()
21502
21507
  });
21503
21508
  var EnvSecretSchema = external_exports.object({
21504
21509
  // 凭据的命名引用('aliyun-ak' / 'supabase-shared')。部署时按这个名字去解析实际的值。
@@ -24954,7 +24959,7 @@ var L = [
24954
24959
  " # \u767B\u8BB0\u6B63\u5F0F\u53EA\u662F\u5F80 gateway \u5199\u4E00\u884C\uFF0Cgateway \u4E0D\u78B0\u955C\u50CF\uFF1B\u96C6\u7FA4\u62C9\u955C\u50CF\u53D1\u751F\u5728\u7B2C\u4E00\u4E2A\u4EFB\u52A1\u5230\u6765\u65F6\u3002",
24955
24960
  " # \u6CA1\u6709\u8FD9\u4E00\u6B65\uFF0C\u6D41\u6C34\u7EBF\u7EFF\u4E86\u53EA\u4EE3\u8868\u300C\u767B\u8BB0\u4E86\u300D\u3002",
24956
24961
  // 模型 / 档位 / 连接器 smoke 也要:试跑那次要跟正式那次拿到同一份,否则验的不是将要上线的东西。
24957
- // 名字形状 deploy-file.mjs 已卡死(persona_id [a-z0-9-]、model / effort [A-Za-z0-9._-]、size 三档枚举、task_concurrency 正整数、connectors 无单引号
24962
+ // 名字形状 deploy-file.mjs 已卡死(persona_id [a-z0-9-]、model / effort [A-Za-z0-9._/-](`/` 是 pi 的 provider/id,不是元字符)、size 四档枚举、task_concurrency 正整数、connectors 无单引号
24958
24963
  // 无换行),所以单引号包住直接拼进命令行是安全的。
24959
24964
  " env:",
24960
24965
  " CLAWD_GATEWAY_URL: ${{ vars.CLAWD_GATEWAY_URL }}",
@@ -21498,7 +21498,12 @@ var EnvPackageSchema = external_exports.object({
21498
21498
  version: external_exports.string().optional(),
21499
21499
  // 版本下限('20.6' 这种)。与 version 的区别:version 是「就要这个」,min 是「不低于」。
21500
21500
  // 两者都缺省即完全不约束。
21501
- min: external_exports.string().optional()
21501
+ min: external_exports.string().optional(),
21502
+ /**
21503
+ * 没有可执行、只是个包(引擎扩展这类:pi 底座里的 cliproxyapi 扩展)。构建器只断言它装上了(npm ls),不查 PATH 上有没有 `name` 这条命令。
21504
+ * 只有引擎底座清单(cloud-host/engines/<e>/manifest.json)用得到;扫描器不产它。
21505
+ */
21506
+ library: external_exports.boolean().optional()
21502
21507
  });
21503
21508
  var EnvSecretSchema = external_exports.object({
21504
21509
  // 凭据的命名引用('aliyun-ak' / 'supabase-shared')。部署时按这个名字去解析实际的值。
@@ -24954,7 +24959,7 @@ var L = [
24954
24959
  " # \u767B\u8BB0\u6B63\u5F0F\u53EA\u662F\u5F80 gateway \u5199\u4E00\u884C\uFF0Cgateway \u4E0D\u78B0\u955C\u50CF\uFF1B\u96C6\u7FA4\u62C9\u955C\u50CF\u53D1\u751F\u5728\u7B2C\u4E00\u4E2A\u4EFB\u52A1\u5230\u6765\u65F6\u3002",
24955
24960
  " # \u6CA1\u6709\u8FD9\u4E00\u6B65\uFF0C\u6D41\u6C34\u7EBF\u7EFF\u4E86\u53EA\u4EE3\u8868\u300C\u767B\u8BB0\u4E86\u300D\u3002",
24956
24961
  // 模型 / 档位 / 连接器 smoke 也要:试跑那次要跟正式那次拿到同一份,否则验的不是将要上线的东西。
24957
- // 名字形状 deploy-file.mjs 已卡死(persona_id [a-z0-9-]、model / effort [A-Za-z0-9._-]、size 三档枚举、task_concurrency 正整数、connectors 无单引号
24962
+ // 名字形状 deploy-file.mjs 已卡死(persona_id [a-z0-9-]、model / effort [A-Za-z0-9._/-](`/` 是 pi 的 provider/id,不是元字符)、size 四档枚举、task_concurrency 正整数、connectors 无单引号
24958
24963
  // 无换行),所以单引号包住直接拼进命令行是安全的。
24959
24964
  " env:",
24960
24965
  " CLAWD_GATEWAY_URL: ${{ vars.CLAWD_GATEWAY_URL }}",