@clawos-dev/clawd 0.2.278 → 0.2.279

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -6779,7 +6779,7 @@ var init_principal = __esm({
6779
6779
  });
6780
6780
 
6781
6781
  // ../protocol/src/schemas.ts
6782
- var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionImportExternalArgs, SessionListArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionInterruptArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionCurrentTurnSenderArgs, SessionSubscribeArgs, SessionPinArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, ClientInfoSchema, AuthRequestFrameSchema, AuthOkFrameSchema, DeviceConnectionEntrySchema, DeviceConnectionsResponseSchema, TunnelReadyEventSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema, PROJECT_PORT_MIN, PROJECT_PORT_MAX, projectNameRegex, DEFAULT_DEV_COMMAND, ProjectMetadataSchema, PROJECT_STAGE_VALUES, ProjectStageSchema, ProjectWithStatusSchema, ListProjectsArgsSchema, ListProjectsResultSchema, GetProjectArgsSchema, GetProjectResultSchema, CreateProjectArgsSchema, CreateProjectResultSchema, DeleteProjectArgsSchema, DeleteProjectResultSchema, UpdateProjectPortArgsSchema, UpdateProjectPortResultSchema, SetProdUrlArgsSchema, SetProdUrlResultSchema, StartDevServerArgsSchema, StartDevServerResultSchema, ASSISTANT_REPORTABLE_STAGES, ReportStageArgsSchema, ReportStageResultSchema, StopDevServerArgsSchema, StopDevServerResultSchema, AppBuilderProjectUpdatedEventSchema, PublishArgsSchema, PublishResultSchema, DismissPublishJobArgsSchema, DismissPublishJobResultSchema, AppBuilderPublishProgressEventSchema, AppBuilderPublishFailedEventSchema;
6782
+ var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, SelectOptionSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionImportExternalArgs, SessionListArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionInterruptArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionCurrentTurnSenderArgs, SessionSubscribeArgs, SessionPinArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, ClientInfoSchema, AuthRequestFrameSchema, AuthOkFrameSchema, DeviceConnectionEntrySchema, DeviceConnectionsResponseSchema, TunnelReadyEventSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema, PROJECT_PORT_MIN, PROJECT_PORT_MAX, projectNameRegex, DEFAULT_DEV_COMMAND, ProjectMetadataSchema, PROJECT_STAGE_VALUES, ProjectStageSchema, ProjectWithStatusSchema, ListProjectsArgsSchema, ListProjectsResultSchema, GetProjectArgsSchema, GetProjectResultSchema, CreateProjectArgsSchema, CreateProjectResultSchema, DeleteProjectArgsSchema, DeleteProjectResultSchema, UpdateProjectPortArgsSchema, UpdateProjectPortResultSchema, SetProdUrlArgsSchema, SetProdUrlResultSchema, StartDevServerArgsSchema, StartDevServerResultSchema, ASSISTANT_REPORTABLE_STAGES, ReportStageArgsSchema, ReportStageResultSchema, StopDevServerArgsSchema, StopDevServerResultSchema, AppBuilderProjectUpdatedEventSchema, PublishArgsSchema, PublishResultSchema, DismissPublishJobArgsSchema, DismissPublishJobResultSchema, AppBuilderPublishProgressEventSchema, AppBuilderPublishFailedEventSchema;
6783
6783
  var init_schemas = __esm({
6784
6784
  "../protocol/src/schemas.ts"() {
6785
6785
  "use strict";
@@ -6808,12 +6808,22 @@ var init_schemas = __esm({
6808
6808
  contextWindowSize: external_exports.number().int().positive().optional()
6809
6809
  };
6810
6810
  SessionMetaSchema = external_exports.object(sessionMetaShape);
6811
+ SelectOptionSchema = external_exports.object({
6812
+ value: external_exports.string(),
6813
+ label: external_exports.string(),
6814
+ description: external_exports.string().optional()
6815
+ });
6811
6816
  ModelInfoSchema = external_exports.object({
6812
6817
  id: external_exports.string().min(1),
6813
6818
  label: external_exports.string().min(1),
6814
6819
  description: external_exports.string().optional(),
6815
6820
  contextWindowSize: external_exports.number().int().positive(),
6816
- default: external_exports.boolean().optional()
6821
+ default: external_exports.boolean().optional(),
6822
+ // 该模型支持的 reasoning effort 档位(codex:per-model,gpt-5.6 系有 max/ultra、5.5 只有四档)。
6823
+ // 缺省 = 该 tool 的 effort 与模型无关(claude 即此情形),消费方回落到 configSchema 里
6824
+ // name==='effort' 那条字段的 options。
6825
+ efforts: external_exports.array(SelectOptionSchema).optional(),
6826
+ defaultEffort: external_exports.string().optional()
6817
6827
  });
6818
6828
  ModeInfoSchema = external_exports.object({
6819
6829
  id: external_exports.string().min(1),
@@ -6825,13 +6835,7 @@ var init_schemas = __esm({
6825
6835
  type: external_exports.enum(["string", "select", "toggle"]),
6826
6836
  label: external_exports.string().min(1),
6827
6837
  description: external_exports.string().optional(),
6828
- options: external_exports.array(
6829
- external_exports.object({
6830
- value: external_exports.string(),
6831
- label: external_exports.string(),
6832
- description: external_exports.string().optional()
6833
- })
6834
- ).optional(),
6838
+ options: external_exports.array(SelectOptionSchema).optional(),
6835
6839
  default: external_exports.unknown().optional(),
6836
6840
  scope: external_exports.enum(["core", "tool-specific"])
6837
6841
  });
@@ -48706,7 +48710,7 @@ function createVisitorStore(opts) {
48706
48710
  init_claude();
48707
48711
 
48708
48712
  // src/tools/codex.ts
48709
- var import_node_child_process5 = require("child_process");
48713
+ var import_node_child_process6 = require("child_process");
48710
48714
  var import_node_fs18 = __toESM(require("fs"), 1);
48711
48715
 
48712
48716
  // src/tools/codex-session.ts
@@ -49207,29 +49211,110 @@ function createCodexSession(ctx, sink, deps = {}) {
49207
49211
  };
49208
49212
  }
49209
49213
 
49214
+ // src/tools/codex-app-server-query.ts
49215
+ var import_node_child_process5 = require("child_process");
49216
+ var DEFAULT_CODEX_QUERY_TIMEOUT_MS = 8e3;
49217
+ async function queryCodexAppServer(cwd, method, params, deps = {}) {
49218
+ const cmd = process.env.CODEX_BIN ?? "codex";
49219
+ const args = ["app-server", "--listen", "stdio://"];
49220
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process5.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
49221
+ const client = new CodexAppServerClient(proc, {});
49222
+ const timeoutMs = deps.timeoutMs ?? DEFAULT_CODEX_QUERY_TIMEOUT_MS;
49223
+ let timer;
49224
+ const timeout = new Promise((_2, reject) => {
49225
+ timer = setTimeout(
49226
+ () => reject(new Error(`codex app-server ${method} timed out after ${timeoutMs}ms`)),
49227
+ timeoutMs
49228
+ );
49229
+ proc.on(
49230
+ "error",
49231
+ (err) => reject(new Error(`codex app-server spawn failed: ${err.message}`))
49232
+ );
49233
+ });
49234
+ try {
49235
+ await Promise.race([
49236
+ (async () => {
49237
+ await client.request("initialize", {
49238
+ clientInfo: { name: "clawd", title: "clawd", version: "0" },
49239
+ capabilities: null
49240
+ });
49241
+ client.notify("initialized", {});
49242
+ })(),
49243
+ timeout
49244
+ ]);
49245
+ deps.beforeRequest?.(client);
49246
+ return await Promise.race([client.request(method, params), timeout]);
49247
+ } finally {
49248
+ if (timer) clearTimeout(timer);
49249
+ if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGTERM");
49250
+ }
49251
+ }
49252
+
49253
+ // src/tools/codex-model-list.ts
49254
+ var CODEX_CONTEXT_WINDOW = 258400;
49255
+ var EFFORT_LABELS = {
49256
+ low: "Low",
49257
+ medium: "Medium",
49258
+ high: "High",
49259
+ xhigh: "Extra high",
49260
+ max: "Max",
49261
+ ultra: "Ultra"
49262
+ };
49263
+ var CODEX_DEFAULT_MODEL_ENTRY = {
49264
+ id: "",
49265
+ label: "Default",
49266
+ description: "codex config.toml \u9ED8\u8BA4",
49267
+ contextWindowSize: CODEX_CONTEXT_WINDOW,
49268
+ default: true
49269
+ };
49270
+ function mapModelList(raw) {
49271
+ if (!raw || typeof raw !== "object") throw new Error("model/list: response is not an object");
49272
+ const data = raw.data;
49273
+ if (!Array.isArray(data)) throw new Error("model/list: `data` is not an array");
49274
+ const models = [CODEX_DEFAULT_MODEL_ENTRY];
49275
+ for (const item of data) {
49276
+ if (!item || typeof item !== "object") throw new Error("model/list: entry is not an object");
49277
+ const e = item;
49278
+ if (typeof e.id !== "string" || e.id === "") throw new Error("model/list: entry missing `id`");
49279
+ if (e.hidden === true) continue;
49280
+ const efforts = Array.isArray(e.supportedReasoningEfforts) ? e.supportedReasoningEfforts.filter((x) => x && typeof x.reasoningEffort === "string").map((x) => {
49281
+ const value = x.reasoningEffort;
49282
+ return {
49283
+ value,
49284
+ label: EFFORT_LABELS[value] ?? value,
49285
+ ...typeof x.description === "string" ? { description: x.description } : {}
49286
+ };
49287
+ }) : void 0;
49288
+ models.push({
49289
+ id: e.id,
49290
+ label: typeof e.displayName === "string" && e.displayName ? e.displayName : e.id,
49291
+ ...typeof e.description === "string" ? { description: e.description } : {},
49292
+ contextWindowSize: CODEX_CONTEXT_WINDOW,
49293
+ ...efforts && efforts.length > 0 ? { efforts } : {},
49294
+ ...typeof e.defaultReasoningEffort === "string" ? { defaultEffort: e.defaultReasoningEffort } : {}
49295
+ });
49296
+ }
49297
+ return models;
49298
+ }
49299
+
49210
49300
  // src/tools/codex.ts
49211
- var CODEX_MODEL_IDS = ["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"];
49212
- var CODEX_MODELS = [
49213
- { id: "", label: "Default", description: "codex config.toml \u9ED8\u8BA4", contextWindowSize: 258400, default: true },
49214
- { id: "gpt-5.5", label: "GPT-5.5", description: "Frontier model for complex coding", contextWindowSize: 258400 },
49215
- { id: "gpt-5.4", label: "GPT-5.4", contextWindowSize: 258400 },
49216
- { id: "gpt-5.4-mini", label: "GPT-5.4-Mini", contextWindowSize: 258400 }
49217
- ];
49301
+ init_claude();
49218
49302
  var CODEX_EFFORTS = [
49219
49303
  { value: "low", label: "Low", description: "Fast responses with lighter reasoning" },
49220
49304
  { value: "medium", label: "Medium", description: "Balances speed and reasoning depth for everyday tasks" },
49221
49305
  { value: "high", label: "High", description: "Greater reasoning depth for complex problems" },
49222
- { value: "xhigh", label: "Extra high", description: "Extra high reasoning depth for complex problems" }
49306
+ { value: "xhigh", label: "Extra high", description: "Extra high reasoning depth for complex problems" },
49307
+ { value: "max", label: "Max", description: "Maximum reasoning depth for the hardest problems" },
49308
+ { value: "ultra", label: "Ultra", description: "Maximum reasoning with automatic task delegation" }
49223
49309
  ];
49224
49310
  var CODEX_APPROVAL_PRESETS = [
49225
49311
  { id: "untrusted", label: "Ask for approval", description: "\u51E0\u4E4E\u6BCF\u6761\u547D\u4EE4\u90FD\u95EE\u4F60\uFF08\u6700\u8C28\u614E\uFF09" },
49226
49312
  { id: "on-request", label: "Approve for me", description: "\u6A21\u578B\u81EA\u5DF1\u5224\u65AD\uFF0C\u53EA\u5BF9\u9AD8\u98CE\u9669\u64CD\u4F5C\u95EE\u4F60\uFF08\u9ED8\u8BA4\uFF09" },
49227
49313
  { id: "never", label: "Full Access", description: "\u4ECE\u4E0D\u8BE2\u95EE\uFF0C\u81EA\u4E3B\u6267\u884C" }
49228
49314
  ];
49229
- var CODEX_CAPABILITIES = {
49315
+ var CODEX_CAPABILITIES_BASE = {
49230
49316
  tool: "codex",
49231
49317
  toolSessionIdLabel: "Codex Thread ID",
49232
- models: CODEX_MODELS,
49233
49318
  permissionModes: CODEX_APPROVAL_PRESETS,
49234
49319
  // codex 不支持这些 clawd 功能(rewind 无 file-snapshot / 无子 agent / 无 TUI pty /
49235
49320
  // 无 observe 推送 / 无文件分享 / fork 是 claude jsonl 专用);UI 据此 gate 入口。
@@ -49240,7 +49325,8 @@ var CODEX_CAPABILITIES = {
49240
49325
  type: "select",
49241
49326
  label: "Model",
49242
49327
  scope: "core",
49243
- options: CODEX_MODELS.map((m2) => ({ value: m2.id, label: m2.label, description: m2.description })),
49328
+ options: [],
49329
+ // 运行时填充,见 buildCapabilities
49244
49330
  default: ""
49245
49331
  },
49246
49332
  {
@@ -49262,14 +49348,25 @@ var CODEX_CAPABILITIES = {
49262
49348
  }
49263
49349
  ]
49264
49350
  };
49351
+ function buildCapabilities(models) {
49352
+ return {
49353
+ ...CODEX_CAPABILITIES_BASE,
49354
+ models,
49355
+ configSchema: CODEX_CAPABILITIES_BASE.configSchema.map(
49356
+ (f) => f.name === "model" ? { ...f, options: models.map((m2) => ({ value: m2.id, label: m2.label, description: m2.description })) } : f
49357
+ )
49358
+ };
49359
+ }
49265
49360
  function sanitizeCodexModel(model) {
49266
49361
  if (model === void 0) return void 0;
49267
- return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
49362
+ if (CLAUDE_MODEL_IDS.includes(model)) return void 0;
49363
+ if (model.startsWith("claude-")) return void 0;
49364
+ return model;
49268
49365
  }
49269
49366
  async function probeCodex(env = process.env) {
49270
49367
  if (env.CODEX_BIN && import_node_fs18.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
49271
49368
  try {
49272
- const out = (0, import_node_child_process5.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
49369
+ const out = (0, import_node_child_process6.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
49273
49370
  if (out && import_node_fs18.default.existsSync(out)) return { available: true, path: out };
49274
49371
  } catch {
49275
49372
  }
@@ -49282,10 +49379,16 @@ var CodexAdapter = class {
49282
49379
  probeCache = null;
49283
49380
  logger;
49284
49381
  probeOverride;
49382
+ queryOverride;
49383
+ // capabilities 的进程级 memo。**回落结果同样被缓存**——否则 codex 没装时每次开弹窗都
49384
+ // spawn 一次必然失败的子进程。代价是装好 codex 后要重启 daemon 才恢复,与「codex 升级后
49385
+ // 要重启才更新模型表」是同一条语义。
49386
+ capsPromise;
49285
49387
  constructor(opts = {}) {
49286
49388
  this.logger = opts.logger;
49287
49389
  this.probeOverride = opts.probeOverride;
49288
49390
  this.historyReader = opts.historyReader;
49391
+ this.queryOverride = opts.queryOverride;
49289
49392
  }
49290
49393
  async probe() {
49291
49394
  if (this.probeCache) return this.probeCache;
@@ -49293,10 +49396,25 @@ var CodexAdapter = class {
49293
49396
  return this.probeCache;
49294
49397
  }
49295
49398
  async capabilities() {
49296
- return CODEX_CAPABILITIES;
49399
+ if (!this.capsPromise) this.capsPromise = this.loadCapabilities();
49400
+ return this.capsPromise;
49401
+ }
49402
+ async loadCapabilities() {
49403
+ try {
49404
+ const raw = this.queryOverride ? await this.queryOverride() : await queryCodexAppServer(process.cwd(), "model/list", {});
49405
+ return buildCapabilities(mapModelList(raw));
49406
+ } catch (err) {
49407
+ this.logger?.warn?.(
49408
+ `codex model/list failed, falling back to config.toml default only: ${err.message}`
49409
+ );
49410
+ return buildCapabilities([CODEX_DEFAULT_MODEL_ENTRY]);
49411
+ }
49297
49412
  }
49298
- resolveContextWindow(modelId) {
49299
- return (CODEX_MODELS.find((m2) => m2.id === (modelId ?? "")) ?? CODEX_MODELS[0]).contextWindowSize;
49413
+ // 纯函数、无 IO。所有 codex 模型共用同一静态窗口值(model/list 不给 contextWindow),
49414
+ // 真实窗口由运行时 modelContextWindow 事件覆盖(doc/knowledge/codex-integration.md §6),
49415
+ // 所以这里不需要模型表。
49416
+ resolveContextWindow(_modelId) {
49417
+ return CODEX_CONTEXT_WINDOW;
49300
49418
  }
49301
49419
  createSession(ctx, sink) {
49302
49420
  return createCodexSession({ ...ctx, model: sanitizeCodexModel(ctx.model) }, sink, { logger: this.logger });
@@ -51430,7 +51548,7 @@ function buildPersonaDispatchHandlers(deps) {
51430
51548
  if (args.model !== void 0) {
51431
51549
  const targetPersona2 = args.targetPersona ?? (args.dispatchId ? deps.store.get(args.dispatchId)?.targetPersonaId : void 0);
51432
51550
  const targetTool = (targetPersona2 ? deps.getPersonaTool?.(targetPersona2) : void 0) ?? "claude";
51433
- const allowed = targetTool === "codex" ? CODEX_MODEL_IDS : CLAUDE_MODEL_IDS;
51551
+ const allowed = targetTool === "codex" ? ((await deps.getCapabilities?.("codex"))?.models ?? []).map((m2) => m2.id).filter((id) => id !== "") : CLAUDE_MODEL_IDS;
51434
51552
  if (!allowed.includes(args.model)) {
51435
51553
  throw new ClawdError(
51436
51554
  ERROR_CODES.INVALID_PARAM,
@@ -51833,8 +51951,6 @@ async function forwardPeerExecToPeer(args) {
51833
51951
  }
51834
51952
 
51835
51953
  // src/tools/codex-history.ts
51836
- var import_node_child_process6 = require("child_process");
51837
- var DEFAULT_TIMEOUT_MS2 = 8e3;
51838
51954
  function rec2(v2) {
51839
51955
  return v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
51840
51956
  }
@@ -51893,34 +52009,6 @@ function threadItemToHistoryMessages(item) {
51893
52009
  return [];
51894
52010
  }
51895
52011
  }
51896
- async function queryCodexAppServer(cwd, method, params, deps) {
51897
- const cmd = process.env.CODEX_BIN ?? "codex";
51898
- const args = ["app-server", "--listen", "stdio://"];
51899
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process6.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
51900
- const client = new CodexAppServerClient(proc, {});
51901
- const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
51902
- let timer;
51903
- const timeout = new Promise((_2, reject) => {
51904
- timer = setTimeout(() => reject(new Error(`codex app-server ${method} timed out after ${timeoutMs}ms`)), timeoutMs);
51905
- proc.on("error", (err) => reject(new Error(`codex app-server spawn failed: ${err.message}`)));
51906
- });
51907
- try {
51908
- await Promise.race([
51909
- (async () => {
51910
- await client.request("initialize", {
51911
- clientInfo: { name: "clawd", title: "clawd", version: "0" },
51912
- capabilities: null
51913
- });
51914
- client.notify("initialized", {});
51915
- })(),
51916
- timeout
51917
- ]);
51918
- return await Promise.race([client.request(method, params), timeout]);
51919
- } finally {
51920
- if (timer) clearTimeout(timer);
51921
- if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGTERM");
51922
- }
51923
- }
51924
52012
  var CodexHistoryReader = class {
51925
52013
  deps;
51926
52014
  constructor(deps = {}) {
@@ -52002,9 +52090,7 @@ var CodexHistoryReader = class {
52002
52090
  };
52003
52091
 
52004
52092
  // src/tools/codex-skills.ts
52005
- var import_node_child_process7 = require("child_process");
52006
52093
  var import_node_path27 = __toESM(require("path"), 1);
52007
- var DEFAULT_TIMEOUT_MS3 = 8e3;
52008
52094
  function str3(v2) {
52009
52095
  return typeof v2 === "string" ? v2 : void 0;
52010
52096
  }
@@ -52034,34 +52120,17 @@ function mapSkillsListResponse(res) {
52034
52120
  return out;
52035
52121
  }
52036
52122
  async function listCodexSkills(cwd, deps = {}) {
52037
- const cmd = process.env.CODEX_BIN ?? "codex";
52038
- const args = ["app-server", "--listen", "stdio://"];
52039
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process7.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
52040
- const client = new CodexAppServerClient(proc, {});
52041
- const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
52042
- let timer;
52043
- const timeout = new Promise((_2, reject) => {
52044
- timer = setTimeout(() => reject(new Error(`codex app-server skills/list timed out after ${timeoutMs}ms`)), timeoutMs);
52045
- proc.on("error", (err) => reject(new Error(`codex app-server spawn failed: ${err.message}`)));
52123
+ const res = await queryCodexAppServer(cwd, "skills/list", { cwds: [cwd] }, {
52124
+ spawnOverride: deps.spawnOverride,
52125
+ timeoutMs: deps.timeoutMs,
52126
+ // skills parity:codex 不扫 .claude/skills/【实测 0.138.0】,persona 惯例装那里——
52127
+ // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
52128
+ // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
52129
+ beforeRequest: (client) => {
52130
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path27.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
52131
+ }
52046
52132
  });
52047
- try {
52048
- await Promise.race([
52049
- (async () => {
52050
- await client.request("initialize", {
52051
- clientInfo: { name: "clawd", title: "clawd", version: "0" },
52052
- capabilities: null
52053
- });
52054
- client.notify("initialized", {});
52055
- })(),
52056
- timeout
52057
- ]);
52058
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path27.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
52059
- const res = await Promise.race([client.request("skills/list", { cwds: [cwd] }), timeout]);
52060
- return mapSkillsListResponse(res);
52061
- } finally {
52062
- if (timer) clearTimeout(timer);
52063
- if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGTERM");
52064
- }
52133
+ return mapSkillsListResponse(res);
52065
52134
  }
52066
52135
 
52067
52136
  // src/workspace/browser.ts
@@ -55128,7 +55197,7 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
55128
55197
  var import_node_fs38 = __toESM(require("fs"), 1);
55129
55198
  var import_node_path42 = __toESM(require("path"), 1);
55130
55199
  var import_node_crypto9 = __toESM(require("crypto"), 1);
55131
- var import_node_child_process10 = require("child_process");
55200
+ var import_node_child_process9 = require("child_process");
55132
55201
 
55133
55202
  // src/tunnel/tunnel-store.ts
55134
55203
  var import_node_fs35 = __toESM(require("fs"), 1);
@@ -55264,7 +55333,7 @@ function escape(v2) {
55264
55333
  var import_node_fs36 = __toESM(require("fs"), 1);
55265
55334
  var import_node_os13 = __toESM(require("os"), 1);
55266
55335
  var import_node_path40 = __toESM(require("path"), 1);
55267
- var import_node_child_process8 = require("child_process");
55336
+ var import_node_child_process7 = require("child_process");
55268
55337
  var import_node_stream3 = require("stream");
55269
55338
  var import_promises5 = require("stream/promises");
55270
55339
  var FRPC_VERSION = "0.68.0";
@@ -55364,7 +55433,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
55364
55433
  import_node_fs36.default.mkdirSync(work, { recursive: true });
55365
55434
  try {
55366
55435
  await new Promise((resolve6, reject) => {
55367
- const proc = (0, import_node_child_process8.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
55436
+ const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
55368
55437
  proc.on("error", reject);
55369
55438
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
55370
55439
  });
@@ -55382,7 +55451,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
55382
55451
  // src/tunnel/frpc-process.ts
55383
55452
  var import_node_fs37 = __toESM(require("fs"), 1);
55384
55453
  var import_node_path41 = __toESM(require("path"), 1);
55385
- var import_node_child_process9 = require("child_process");
55454
+ var import_node_child_process8 = require("child_process");
55386
55455
  function frpcPidFilePath(dataDir) {
55387
55456
  return import_node_path41.default.join(dataDir, "frpc.pid");
55388
55457
  }
@@ -55468,7 +55537,7 @@ async function killStaleFrpc(deps) {
55468
55537
  async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
55469
55538
  if (process.platform === "win32") return [];
55470
55539
  return new Promise((resolve6) => {
55471
- const ps = (0, import_node_child_process9.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
55540
+ const ps = (0, import_node_child_process8.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
55472
55541
  let buf = "";
55473
55542
  ps.stdout.on("data", (c) => {
55474
55543
  buf += c.toString();
@@ -55637,7 +55706,7 @@ var TunnelManager = class {
55637
55706
  logLevel: "info"
55638
55707
  });
55639
55708
  await import_node_fs38.default.promises.writeFile(tomlPath, toml, { mode: 384 });
55640
- const proc = (this.deps.spawnImpl ?? import_node_child_process10.spawn)(frpcBin, ["-c", tomlPath], {
55709
+ const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
55641
55710
  stdio: ["ignore", "pipe", "pipe"]
55642
55711
  });
55643
55712
  const logDir = import_node_path42.default.join(this.deps.dataDir, "log");
@@ -56129,11 +56198,11 @@ var DeviceBindingClientError = class extends Error {
56129
56198
  code;
56130
56199
  cause;
56131
56200
  };
56132
- var DEFAULT_TIMEOUT_MS4 = 8e3;
56201
+ var DEFAULT_TIMEOUT_MS2 = 8e3;
56133
56202
  async function upsertDeviceBinding(opts) {
56134
56203
  const doFetch = opts.fetchImpl ?? fetch;
56135
56204
  const ac = new AbortController();
56136
- const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS4);
56205
+ const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS2);
56137
56206
  const body = { unionId: opts.unionId };
56138
56207
  if (opts.avatarUrl != null) body.avatarUrl = opts.avatarUrl;
56139
56208
  let res;
@@ -57062,11 +57131,11 @@ init_protocol();
57062
57131
  init_protocol();
57063
57132
 
57064
57133
  // src/workspace/git.ts
57065
- var import_node_child_process11 = require("child_process");
57134
+ var import_node_child_process10 = require("child_process");
57066
57135
  var import_node_fs43 = __toESM(require("fs"), 1);
57067
57136
  var import_node_path48 = __toESM(require("path"), 1);
57068
57137
  var import_node_util = require("util");
57069
- var pexec = (0, import_node_util.promisify)(import_node_child_process11.execFile);
57138
+ var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
57070
57139
  function normalizePath(p2) {
57071
57140
  const resolved = import_node_path48.default.resolve(p2);
57072
57141
  try {
@@ -58005,7 +58074,7 @@ function computeMethodAccess(args) {
58005
58074
  }
58006
58075
 
58007
58076
  // src/version.ts
58008
- var version = "0.2.278".length > 0 ? "0.2.278" : "dev";
58077
+ var version = "0.2.279".length > 0 ? "0.2.279" : "dev";
58009
58078
 
58010
58079
  // src/cli-probe/probe.ts
58011
58080
  var fs54 = __toESM(require("fs"), 1);
@@ -59021,7 +59090,7 @@ function buildExtensionHandlers(deps) {
59021
59090
 
59022
59091
  // src/app-builder/project-store.ts
59023
59092
  var import_node_fs44 = require("fs");
59024
- var import_node_child_process12 = require("child_process");
59093
+ var import_node_child_process11 = require("child_process");
59025
59094
  var import_node_path55 = require("path");
59026
59095
  init_protocol();
59027
59096
  var PROJECTS_DIR = "projects";
@@ -59126,7 +59195,7 @@ var ProjectStore = class {
59126
59195
  async scaffold(name, templateSrcDir, scaffoldScriptPath) {
59127
59196
  const destDir = this.projectDir(name);
59128
59197
  return await new Promise((resolve6, reject) => {
59129
- const child = (0, import_node_child_process12.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
59198
+ const child = (0, import_node_child_process11.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
59130
59199
  env: { ...process.env, PATH: process.env.PATH ?? "" },
59131
59200
  stdio: ["ignore", "pipe", "pipe"]
59132
59201
  });
@@ -59230,7 +59299,7 @@ var ProjectStore = class {
59230
59299
  };
59231
59300
 
59232
59301
  // src/app-builder/kill-port.ts
59233
- var import_node_child_process13 = require("child_process");
59302
+ var import_node_child_process12 = require("child_process");
59234
59303
  async function killPortOccupants(port, ownedPids, logger) {
59235
59304
  let pids;
59236
59305
  try {
@@ -59272,7 +59341,7 @@ async function killPortOccupants(port, ownedPids, logger) {
59272
59341
  }
59273
59342
  function listPidsOnPort(port) {
59274
59343
  return new Promise((resolve6, reject) => {
59275
- (0, import_node_child_process13.execFile)(
59344
+ (0, import_node_child_process12.execFile)(
59276
59345
  "lsof",
59277
59346
  ["-ti", `:${port}`],
59278
59347
  { timeout: 3e3 },
@@ -59344,7 +59413,7 @@ var PublishJobRegistry = class {
59344
59413
  };
59345
59414
 
59346
59415
  // src/app-builder/publish-job-runner.ts
59347
- var import_node_child_process14 = require("child_process");
59416
+ var import_node_child_process13 = require("child_process");
59348
59417
  var import_node_fs45 = require("fs");
59349
59418
  var import_node_path56 = require("path");
59350
59419
 
@@ -59373,7 +59442,7 @@ function tailStderrLines(buf, n) {
59373
59442
  // src/app-builder/publish-job-runner.ts
59374
59443
  async function startPublishJob(deps, args) {
59375
59444
  const { registry: registry2, projectDir } = deps;
59376
- const spawn13 = deps.spawnImpl ?? import_node_child_process14.spawn;
59445
+ const spawn12 = deps.spawnImpl ?? import_node_child_process13.spawn;
59377
59446
  if (registry2.has(args.name)) {
59378
59447
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
59379
59448
  }
@@ -59385,7 +59454,7 @@ async function startPublishJob(deps, args) {
59385
59454
  } catch {
59386
59455
  logStream = null;
59387
59456
  }
59388
- const child = spawn13("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
59457
+ const child = spawn12("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
59389
59458
  cwd: projDir,
59390
59459
  env: process.env,
59391
59460
  stdio: ["ignore", "pipe", "pipe"]
@@ -60260,15 +60329,15 @@ var import_node_crypto17 = require("crypto");
60260
60329
  init_protocol();
60261
60330
 
60262
60331
  // src/peer-ops/run-command.ts
60263
- var import_node_child_process15 = require("child_process");
60332
+ var import_node_child_process14 = require("child_process");
60264
60333
  var import_node_os21 = __toESM(require("os"), 1);
60265
- var DEFAULT_TIMEOUT_MS5 = 3e4;
60334
+ var DEFAULT_TIMEOUT_MS3 = 3e4;
60266
60335
  var MAX_TIMEOUT_MS = 3e5;
60267
60336
  var MAX_OUTPUT_BYTES = 1048576;
60268
60337
  function runCommand(command, opts = {}) {
60269
- const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5, MAX_TIMEOUT_MS);
60338
+ const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS3, MAX_TIMEOUT_MS);
60270
60339
  return new Promise((resolve6) => {
60271
- const child = (0, import_node_child_process15.spawn)("bash", ["-c", command], { cwd: import_node_os21.default.homedir() });
60340
+ const child = (0, import_node_child_process14.spawn)("bash", ["-c", command], { cwd: import_node_os21.default.homedir() });
60272
60341
  const out = [];
60273
60342
  const err = [];
60274
60343
  let outBytes = 0;
@@ -60483,7 +60552,7 @@ function buildMethodHandlers(deps) {
60483
60552
  }
60484
60553
 
60485
60554
  // src/app-builder/dev-server-supervisor.ts
60486
- var import_node_child_process16 = require("child_process");
60555
+ var import_node_child_process15 = require("child_process");
60487
60556
  var import_node_events2 = require("events");
60488
60557
  var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
60489
60558
  var DevServerSupervisor = class extends import_node_events2.EventEmitter {
@@ -60520,7 +60589,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
60520
60589
  tunnelHost: args.tunnelHost,
60521
60590
  devCommand: cmd
60522
60591
  });
60523
- const child = (0, import_node_child_process16.spawn)("sh", ["-c", cmd], {
60592
+ const child = (0, import_node_child_process15.spawn)("sh", ["-c", cmd], {
60524
60593
  cwd: args.cwd,
60525
60594
  env,
60526
60595
  stdio: "pipe",
@@ -60772,7 +60841,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
60772
60841
  }
60773
60842
 
60774
60843
  // src/extension/runtime.ts
60775
- var import_node_child_process17 = require("child_process");
60844
+ var import_node_child_process16 = require("child_process");
60776
60845
  var import_node_path60 = __toESM(require("path"), 1);
60777
60846
  var import_promises12 = require("timers/promises");
60778
60847
 
@@ -60880,7 +60949,7 @@ var Runtime = class {
60880
60949
  CLAWOS_EXT_PORT: String(port),
60881
60950
  CLAWOS_EXT_ID: extId
60882
60951
  };
60883
- const child = (0, import_node_child_process17.spawn)("sh", ["-c", cmd], {
60952
+ const child = (0, import_node_child_process16.spawn)("sh", ["-c", cmd], {
60884
60953
  cwd: dir,
60885
60954
  env,
60886
60955
  stdio: ["ignore", "pipe", "pipe"],
@@ -61984,8 +62053,10 @@ async function startDaemon(config) {
61984
62053
  },
61985
62054
  // B 角色:判断 targetPersona 是否 public(跨设备授权边界,private 拒)。
61986
62055
  getPersonaPublic: (personaId2) => personaRegistry.get(personaId2)?.public ?? false,
61987
- // model 校验按 target persona 绑定 tool 选表(claude / codex 模型集不同)
61988
- getPersonaTool: (personaId2) => personaRegistry.get(personaId2)?.tool
62056
+ // model 校验按 target persona 绑定 tool 选来源(claude / codex 模型集不同)
62057
+ getPersonaTool: (personaId2) => personaRegistry.get(personaId2)?.tool,
62058
+ // codex 模型表是运行时查 model/list 来的,校验必须问 capabilities(manager 侧有进程级缓存)
62059
+ getCapabilities: (tool) => manager.getCapabilities(tool)
61989
62060
  });
61990
62061
  Object.assign(handlers, dispatchHandlers);
61991
62062
  const shiftHandlers = buildShiftInternalHandlers({