@workerdeck/core 1.1.0 → 1.3.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.
package/build/index.d.mts CHANGED
@@ -190,6 +190,7 @@ type AiSdkRunnerConfig = Omit<CreateSessionRequest, 'cwd'> & {
190
190
  memoryLimitBytes?: number;
191
191
  };
192
192
  executionBackend?: ToolExecutionBackend;
193
+ toolTitles?: Record<string, string>;
193
194
  shouldApprove?: (call: {
194
195
  toolName: string;
195
196
  input: unknown;
@@ -424,6 +425,7 @@ type ToolDefinition = {
424
425
  name: string;
425
426
  trust: ToolTrust;
426
427
  tool: Tool$1;
428
+ title?: string;
427
429
  };
428
430
  type ToolContextOptions = {
429
431
  executor: ToolExecutor;
@@ -462,6 +464,7 @@ declare function withMcpTools(context: ToolContext, mcpTools: ToolSet$1): ToolCo
462
464
  type HostToolDefinition = {
463
465
  tool: Tool$1;
464
466
  trust: ToolTrust;
467
+ title?: string;
465
468
  };
466
469
  declare function withHostTools(context: ToolContext, hostTools: Record<string, HostToolDefinition>, kind?: string): ToolContext;
467
470
  //#endregion
@@ -664,7 +667,11 @@ type AppServerUserMessageItem = {
664
667
  type: 'userMessage';
665
668
  content?: unknown;
666
669
  };
667
- type AppServerItem = AppServerAgentMessageItem | AppServerReasoningItem | AppServerCommandExecutionItem | AppServerFileChangeItem | AppServerMcpToolCallItem | AppServerWebSearchItem | AppServerImageGenerationItem | AppServerImageViewItem | AppServerUserMessageItem | AppServerSubAgentActivityItem | AppServerCollabAgentToolCallItem;
670
+ type AppServerContextCompactionItem = {
671
+ id: string;
672
+ type: 'contextCompaction';
673
+ };
674
+ type AppServerItem = AppServerAgentMessageItem | AppServerReasoningItem | AppServerCommandExecutionItem | AppServerFileChangeItem | AppServerMcpToolCallItem | AppServerWebSearchItem | AppServerImageGenerationItem | AppServerImageViewItem | AppServerUserMessageItem | AppServerSubAgentActivityItem | AppServerCollabAgentToolCallItem | AppServerContextCompactionItem;
668
675
  type AppServerTurn = {
669
676
  id: string;
670
677
  status: string;
@@ -728,33 +735,6 @@ declare function listCodexSessions(options: {
728
735
  declare const codexAdapter: EngineAdapter;
729
736
  //#endregion
730
737
  //#region src/engines/codex/catalog.d.ts
731
- /**
732
- * The Codex engine's model catalog, seeded from the binary's own embedded model
733
- * table (see `provenance` for the version) — that table, not the SDK's stale
734
- * `ModelReasoningEffort` union, is the truth about which reasoning efforts each
735
- * model takes. Mapping decisions: the internal `codex-auto-review` row is dropped
736
- * (the codex analogue of the CLI's `default` sentinel), `primary` mirrors the
737
- * binary's own `visibility` field so both UIs group the way codex's picker does,
738
- * and `reasoningEfforts` carries `supported_reasoning_levels` verbatim — `max`
739
- * and `ultra` go beyond the SDK union, so trust the binary and keep strings open.
740
- *
741
- * **Refresh procedure** (release checklist): extract the embedded JSON from the
742
- * platform binary and diff. The two-hop resolve is NOT optional — under pnpm's
743
- * strict layout the platform package is a dependency of `@openai/codex` and
744
- * resolves only from that wrapper's location (MODULE_NOT_FOUND otherwise), the
745
- * same two hops `resolveBundledCodexExecutable` makes.
746
- *
747
- * node -e 'const d=require("fs").readFileSync(process.argv[1]);
748
- * const s=d.indexOf(`{\n "models": [`);
749
- * let i=s,n=0; do{n+=(d[i]===123)-(d[i]===125);i++}while(n);
750
- * const c=JSON.parse(d.slice(s,i));
751
- * for(const m of c.models) console.log(m.slug, m.display_name,
752
- * m.visibility, m.supported_reasoning_levels.map(l=>l.effort).join(","))'\
753
- * "$(node -p 'const{createRequire}=require("module");
754
- * const w=require.resolve("@openai/codex/package.json");
755
- * createRequire(w).resolve("@openai/codex-darwin-arm64/package.json")
756
- * .replace("package.json","vendor/aarch64-apple-darwin/bin/codex")')"
757
- */
758
738
  declare const CODEX_CATALOG: ModelCatalog;
759
739
  //#endregion
760
740
  //#region src/engines/codex/runner.d.ts
package/build/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { createHash, randomUUID } from "node:crypto";
3
3
  import { getSessionInfo, getSessionMessages, listSessions, query } from "@anthropic-ai/claude-agent-sdk";
4
- import { ENGINE_CAPABILITIES, PROTOCOL_VERSION, SUBAGENT_HISTORY, TOOL_RESULT_HEAD_CHARS, contextReading, imagePartRef, replayCoalesceKey, replayRetains, snapshotRetains, transcriptActivity, transcriptContent, transcriptProse } from "@workerdeck/protocol";
4
+ import { ENGINE_CAPABILITIES, PROTOCOL_VERSION, SUBAGENT_HISTORY, TOOL_RESULT_HEAD_CHARS, contextReading, imagePartRef, replayCoalesceKey, replayRetains, sanitizeToolTitle, snapshotRetains, transcriptActivity, transcriptContent, transcriptProse } from "@workerdeck/protocol";
5
5
  import { ToolLoopAgent, generateText, isStepCount, tool } from "ai";
6
6
  import { execFile, spawn } from "node:child_process";
7
7
  import { appendFileSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
@@ -276,11 +276,16 @@ function mcpStatusInfo(status) {
276
276
  command: config?.command,
277
277
  args: config?.args,
278
278
  url: config?.url,
279
- tools: status.tools?.map((tool) => ({
280
- name: tool.name,
281
- description: tool.description,
282
- annotations: tool.annotations
283
- }))
279
+ tools: status.tools?.map((tool) => {
280
+ const probe = tool;
281
+ const title = probe.title ?? probe.annotations?.title;
282
+ return {
283
+ name: tool.name,
284
+ title: sanitizeToolTitle(typeof title === "string" ? title : void 0, tool.name),
285
+ description: tool.description,
286
+ annotations: tool.annotations
287
+ };
288
+ })
284
289
  };
285
290
  }
286
291
  function defaultModelFromSdk(models) {
@@ -418,7 +423,6 @@ var EventLog = class {
418
423
  get activityCount() {
419
424
  return this.#activityCount;
420
425
  }
421
- /** The unread badge's unit — see `transcriptProse`. Folded here so a restored log recomputes it. */
422
426
  get proseCount() {
423
427
  return this.#proseCount;
424
428
  }
@@ -1120,6 +1124,7 @@ var SessionRunner = class {
1120
1124
  this.#turnOverWhileBlocked = false;
1121
1125
  this.#setStatus("running");
1122
1126
  this.#fetchCapabilities();
1127
+ this.#fetchToolTitles();
1123
1128
  this.#fetchContextUsage();
1124
1129
  this.#fetchRateLimits();
1125
1130
  this.#fetchEngineTitle();
@@ -1153,6 +1158,16 @@ var SessionRunner = class {
1153
1158
  }
1154
1159
  }
1155
1160
  }
1161
+ async #fetchToolTitles() {
1162
+ const servers = await this.mcpServers().catch(() => void 0);
1163
+ if (this.#closed || !servers) return;
1164
+ const titles = {};
1165
+ for (const server of servers) for (const tool of server.tools ?? []) if (tool.title) titles[`mcp__${server.name}__${tool.name}`] = tool.title;
1166
+ if (Object.keys(titles).length > 0) this.#emit({
1167
+ type: "tool_titles",
1168
+ titles
1169
+ });
1170
+ }
1156
1171
  async #fetchCapabilities() {
1157
1172
  if (this.#capabilitiesEmitted) return;
1158
1173
  const query = this.#query;
@@ -1477,6 +1492,7 @@ var AiSdkRunner = class {
1477
1492
  start() {
1478
1493
  if (this.#started) return this.#turnChain;
1479
1494
  this.#started = true;
1495
+ this.#emitToolTitles();
1480
1496
  if (this.#config.restore) return this.#turnChain;
1481
1497
  this.#setStatus("idle");
1482
1498
  if (this.#config.prompt) this.sendMessage(this.#config.prompt);
@@ -2135,6 +2151,13 @@ var AiSdkRunner = class {
2135
2151
  detail
2136
2152
  });
2137
2153
  }
2154
+ #emitToolTitles() {
2155
+ const titles = this.#config.toolTitles;
2156
+ if (titles && Object.keys(titles).length > 0) this.#emit({
2157
+ type: "tool_titles",
2158
+ titles
2159
+ });
2160
+ }
2138
2161
  #emit(body) {
2139
2162
  this.#subscribers.emit(this.#log.append(body));
2140
2163
  }
@@ -2667,7 +2690,7 @@ function withHostTools(context, hostTools, kind = "host tool") {
2667
2690
  const definitions = [...context.definitions];
2668
2691
  const tools = { ...context.tools };
2669
2692
  const sandboxedToolNames = [...context.sandboxedToolNames];
2670
- for (const [name, { tool: hostTool, trust }] of entries) {
2693
+ for (const [name, { tool: hostTool, trust, title }] of entries) {
2671
2694
  if (name in tools) throw new Error(`${kind} '${name}' collides with an existing tool of the same name`);
2672
2695
  const executes = typeof hostTool.execute === "function";
2673
2696
  if (trust === "sandboxed" && executes) throw new Error(`${kind} '${name}' is declared sandboxed but has an \`execute\` — it would run in this process with full authority. Drop \`execute\` so it rides the ToolExecutor seam.`);
@@ -2675,7 +2698,8 @@ function withHostTools(context, hostTools, kind = "host tool") {
2675
2698
  definitions.push({
2676
2699
  name,
2677
2700
  trust,
2678
- tool: hostTool
2701
+ tool: hostTool,
2702
+ title
2679
2703
  });
2680
2704
  tools[name] = hostTool;
2681
2705
  if (trust === "sandboxed") sandboxedToolNames.push(name);
@@ -2947,6 +2971,7 @@ function createEngineSession(options) {
2947
2971
  vfs,
2948
2972
  executor,
2949
2973
  executableTools: context.sandboxedToolNames,
2974
+ toolTitles: collectToolTitles(context.definitions, options.mcp?.servers),
2950
2975
  executionBackend: typeof options.backend === "function" ? void 0 : options.backend ?? "server",
2951
2976
  executionLimits: options.executionLimits,
2952
2977
  shouldApprove: options.shouldApprove,
@@ -2955,6 +2980,18 @@ function createEngineSession(options) {
2955
2980
  }, options.id);
2956
2981
  return runner;
2957
2982
  }
2983
+ function collectToolTitles(definitions, servers) {
2984
+ const titles = {};
2985
+ for (const definition of definitions) {
2986
+ const title = sanitizeToolTitle(definition.title, definition.name);
2987
+ if (title) titles[definition.name] = title;
2988
+ }
2989
+ for (const server of servers ?? []) for (const tool of server.tools ?? []) {
2990
+ const title = sanitizeToolTitle(tool.title, tool.name);
2991
+ if (title) titles[`${server.name}__${tool.name}`] = title;
2992
+ }
2993
+ return Object.keys(titles).length > 0 ? titles : void 0;
2994
+ }
2958
2995
  function requireDeclaredServers(profileName, declared, mcp, tools) {
2959
2996
  if (!declared || declared.length === 0) return;
2960
2997
  const missing = declared.filter((name) => {
@@ -2999,12 +3036,13 @@ async function connectMcpTools(servers, options = {}) {
2999
3036
  });
3000
3037
  clients.push(client);
3001
3038
  const connected = await client.tools();
3039
+ const listed = await listToolRecords(client);
3002
3040
  for (const [toolName, mcpTool] of Object.entries(connected)) tools[`${name}__${toolName}`] = mcpTool;
3003
3041
  statuses.push({
3004
3042
  name,
3005
3043
  status: "connected",
3006
3044
  ...identity,
3007
- tools: Object.entries(connected).map(([toolName, mcpTool]) => toToolInfo(toolName, mcpTool))
3045
+ tools: Object.entries(connected).map(([toolName, mcpTool]) => toToolInfo(toolName, mcpTool, listed.get(toolName)))
3008
3046
  });
3009
3047
  } catch (error) {
3010
3048
  const message = error instanceof Error ? error.message : String(error);
@@ -3038,11 +3076,27 @@ function describeServer(server) {
3038
3076
  args: server.args
3039
3077
  };
3040
3078
  }
3041
- function toToolInfo(name, mcpTool) {
3079
+ async function listToolRecords(client) {
3080
+ const records = /* @__PURE__ */ new Map();
3081
+ if (typeof client.listTools !== "function") return records;
3082
+ try {
3083
+ const listed = await client.listTools();
3084
+ for (const record of listed.tools ?? []) records.set(record.name, record);
3085
+ } catch {}
3086
+ return records;
3087
+ }
3088
+ function toToolInfo(name, mcpTool, record) {
3042
3089
  const { description, inputSchema } = mcpTool ?? {};
3090
+ const hints = record?.annotations;
3043
3091
  return {
3044
3092
  name,
3093
+ title: sanitizeToolTitle(record?.title ?? hints?.title, name),
3045
3094
  description: typeof description === "string" ? description : void 0,
3095
+ annotations: hints ? {
3096
+ readOnly: hints.readOnlyHint,
3097
+ destructive: hints.destructiveHint,
3098
+ openWorld: hints.openWorldHint
3099
+ } : void 0,
3046
3100
  inputSchema: inputSchema?.jsonSchema
3047
3101
  };
3048
3102
  }
@@ -3171,18 +3225,12 @@ const claudeAdapter = {
3171
3225
  };
3172
3226
  //#endregion
3173
3227
  //#region src/engines/codex/connect.ts
3174
- /**
3175
- * The operator's environment reaches the child whole — WorkerDeck resolves no credential of its
3176
- * own — and the profile's CODEX_HOME is the one key it pins, last, so a profile always wins over
3177
- * an inherited value. Every path that spawns or connects to an app-server goes through here.
3178
- */
3179
3228
  function codexChildEnv(base, codexHome) {
3180
3229
  const env = {};
3181
3230
  for (const [key, value] of Object.entries(base)) if (value !== void 0) env[key] = value;
3182
3231
  if (codexHome) env.CODEX_HOME = codexHome;
3183
3232
  return env;
3184
3233
  }
3185
- /** `experimentalApi` gates the granular approval policy and there is no non-experimental fallback, so it is not per-call-site. */
3186
3234
  const INITIALIZE_PARAMS = {
3187
3235
  clientInfo: {
3188
3236
  name: "workerdeck",
@@ -4903,6 +4951,13 @@ var CodexRunner = class {
4903
4951
  this.#emitToolUse(id, "CodexImageView", { path: item.path }, agent);
4904
4952
  this.#emitToolResult(id, item.path, false, void 0, agent?.toolUseId ?? null);
4905
4953
  },
4954
+ contextCompaction: (_item, _active, id, agent) => {
4955
+ this.#emit({
4956
+ type: "context_compacted",
4957
+ uuid: id,
4958
+ parentToolUseId: agent?.toolUseId ?? null
4959
+ });
4960
+ },
4906
4961
  subAgentActivity: (item, _active, id, agent) => {
4907
4962
  if (this.#replayingHistory) {
4908
4963
  if (item.kind !== "started") return;
@@ -5094,33 +5149,6 @@ var CodexRunner = class {
5094
5149
  };
5095
5150
  //#endregion
5096
5151
  //#region src/engines/codex/catalog.ts
5097
- /**
5098
- * The Codex engine's model catalog, seeded from the binary's own embedded model
5099
- * table (see `provenance` for the version) — that table, not the SDK's stale
5100
- * `ModelReasoningEffort` union, is the truth about which reasoning efforts each
5101
- * model takes. Mapping decisions: the internal `codex-auto-review` row is dropped
5102
- * (the codex analogue of the CLI's `default` sentinel), `primary` mirrors the
5103
- * binary's own `visibility` field so both UIs group the way codex's picker does,
5104
- * and `reasoningEfforts` carries `supported_reasoning_levels` verbatim — `max`
5105
- * and `ultra` go beyond the SDK union, so trust the binary and keep strings open.
5106
- *
5107
- * **Refresh procedure** (release checklist): extract the embedded JSON from the
5108
- * platform binary and diff. The two-hop resolve is NOT optional — under pnpm's
5109
- * strict layout the platform package is a dependency of `@openai/codex` and
5110
- * resolves only from that wrapper's location (MODULE_NOT_FOUND otherwise), the
5111
- * same two hops `resolveBundledCodexExecutable` makes.
5112
- *
5113
- * node -e 'const d=require("fs").readFileSync(process.argv[1]);
5114
- * const s=d.indexOf(`{\n "models": [`);
5115
- * let i=s,n=0; do{n+=(d[i]===123)-(d[i]===125);i++}while(n);
5116
- * const c=JSON.parse(d.slice(s,i));
5117
- * for(const m of c.models) console.log(m.slug, m.display_name,
5118
- * m.visibility, m.supported_reasoning_levels.map(l=>l.effort).join(","))'\
5119
- * "$(node -p 'const{createRequire}=require("module");
5120
- * const w=require.resolve("@openai/codex/package.json");
5121
- * createRequire(w).resolve("@openai/codex-darwin-arm64/package.json")
5122
- * .replace("package.json","vendor/aarch64-apple-darwin/bin/codex")')"
5123
- */
5124
5152
  const CODEX_CATALOG = {
5125
5153
  provenance: "embedded model presets of @openai/codex@0.151.0 (darwin-arm64 binary), re-extracted 2026-09-02 and unchanged since 0.149.0",
5126
5154
  models: [