@livx.cc/agentx 0.99.40 → 0.99.41

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.
@@ -1,4 +1,4 @@
1
- import { A as AgentTool } from './tools-BWzPQVy0.js';
1
+ import { A as AgentTool } from './tools-S-ArIR3o.js';
2
2
 
3
3
  /**
4
4
  * MCP bridge — adapt a Model Context Protocol tool list into the agent's AgentTool[],
@@ -1,5 +1,5 @@
1
- import { e as McpToolSearchOptions, f as McpToolSpec } from './mcp-aONOXRNk.js';
2
- import { A as AgentTool } from './tools-BWzPQVy0.js';
1
+ import { e as McpToolSearchOptions, f as McpToolSpec } from './mcp-D5eN0JyQ.js';
2
+ import { A as AgentTool } from './tools-S-ArIR3o.js';
3
3
  import '@livx.cc/wcli/core';
4
4
 
5
5
  /** A JSON-RPC 2.0 transport: request (awaits a result), notify (fire-and-forget), close. */
package/dist/models.d.ts CHANGED
@@ -10,6 +10,20 @@
10
10
  declare const MODEL_ALIASES: Record<string, string>;
11
11
  /** Resolve an alias to a concrete id. A provider prefix ("anthropic/") is preserved; unknown ids pass through. */
12
12
  declare function resolveModelAlias(input: string): string;
13
+ /** The provider of a model id ("cursor/x" -> "cursor"). Provider-specific `providerOptions` are only
14
+ * portable within the same provider — leaking them across is a hard 400.
15
+ *
16
+ * A BARE id is the common case, not the exception: `resolveModelAlias('haiku')` yields
17
+ * `claude-haiku-4-5-20251001` with no prefix (ai.libx.js resolves it fuzzily downstream), so reading
18
+ * only the literal "/" made every aliased child look like a provider switch and silently dropped the
19
+ * parent's options. The fix belongs HERE — the alias table must keep emitting the ids ai.libx.js
20
+ * expects, and the comparison is provider identity, not string identity.
21
+ *
22
+ * A bare id we can't attribute is UNKNOWN, not a shared provider: it gets a per-id marker so two
23
+ * different unknown ids never compare equal (returning "" for both made them look like one provider
24
+ * and would have leaked one host's options onto the other's model). An unknown id still compares
25
+ * equal to ITSELF, so a child staying on the parent's exact model keeps the parent's options. */
26
+ declare function modelProvider(model: string): string;
13
27
  /** Short, human-friendly name for a resolved model id (e.g. "anthropic/claude-opus-4-8" → "opus"). */
14
28
  declare function modelShortLabel(model?: string): string;
15
29
  interface ResolveModelSwitchOpts {
@@ -39,4 +53,4 @@ interface ModelSwitch {
39
53
  */
40
54
  declare function resolveModelSwitch(opts: ResolveModelSwitchOpts): ModelSwitch;
41
55
 
42
- export { MODEL_ALIASES, type ModelSwitch, type ResolveModelSwitchOpts, modelShortLabel, resolveModelAlias, resolveModelSwitch };
56
+ export { MODEL_ALIASES, type ModelSwitch, type ResolveModelSwitchOpts, modelProvider, modelShortLabel, resolveModelAlias, resolveModelSwitch };
package/dist/models.js CHANGED
@@ -15,6 +15,12 @@ function resolveModelAlias(input) {
15
15
  const rest = slash === -1 ? input : input.slice(slash + 1);
16
16
  return prefix + (MODEL_ALIASES[rest.toLowerCase()] ?? rest);
17
17
  }
18
+ function modelProvider(model) {
19
+ const i = model.indexOf("/");
20
+ if (i !== -1) return model.slice(0, i);
21
+ if (/^claude-/i.test(model)) return "anthropic";
22
+ return `?${model}`;
23
+ }
18
24
  function modelShortLabel(model) {
19
25
  if (!model) return "default";
20
26
  const id = model.split("/").pop();
@@ -38,6 +44,7 @@ function resolveModelSwitch(opts) {
38
44
  }
39
45
  export {
40
46
  MODEL_ALIASES,
47
+ modelProvider,
41
48
  modelShortLabel,
42
49
  resolveModelAlias,
43
50
  resolveModelSwitch
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/models.ts"],"sourcesContent":["/**\n * Model aliasing + mid-conversation switch resolution — pure, dependency-free.\n *\n * Harness-level so every agentx consumer (unclaw, para-chat, …) resolves `[opus]`-style\n * aliases, gates by an allow-list, and announces a switch the same way. Policy (which models\n * a caller may use) and session state (the prior model) stay with the consumer; this module\n * is the shared mechanism.\n */\n\n/** Canonical short aliases → concrete Anthropic model ids. */\nexport const MODEL_ALIASES: Record<string, string> = {\n fable: 'claude-fable-5',\n 'fable-5': 'claude-fable-5',\n opus: 'claude-opus-4-8',\n 'opus-4-8': 'claude-opus-4-8',\n 'opus-4-7': 'claude-opus-4-7',\n 'opus-4-6': 'claude-opus-4-6',\n sonnet: 'claude-sonnet-4-6',\n haiku: 'claude-haiku-4-5-20251001',\n};\n\n/** Resolve an alias to a concrete id. A provider prefix (\"anthropic/\") is preserved; unknown ids pass through. */\nexport function resolveModelAlias(input: string): string {\n const slash = input.indexOf('/');\n const prefix = slash === -1 ? '' : input.slice(0, slash + 1);\n const rest = slash === -1 ? input : input.slice(slash + 1);\n return prefix + (MODEL_ALIASES[rest.toLowerCase()] ?? rest);\n}\n\n/** Short, human-friendly name for a resolved model id (e.g. \"anthropic/claude-opus-4-8\" → \"opus\"). */\nexport function modelShortLabel(model?: string): string {\n if (!model) return 'default';\n const id = model.split('/').pop()!;\n return id.replace(/^claude-/, '').replace(/-\\d.*$/, '');\n}\n\nexport interface ResolveModelSwitchOpts {\n /** Model requested for this turn (e.g. from an inline directive). Undefined = keep `current`. */\n requested?: string;\n /** The turn's default/current model when nothing is requested. */\n current: string;\n /** The session's prior resolved model — drives change detection + the notice. */\n prior?: string;\n /** If set, `requested` must match one of these (by short label) or it's denied and `current` is kept. */\n allowed?: string[];\n /** Announcement formatter. Default: `_[switching from x to y]_\\n\\n`. */\n format?: (from: string, to: string) => string;\n}\n\nexport interface ModelSwitch {\n /** The model to run this turn. */\n model: string;\n /** True when `requested` was rejected by `allowed` and `model` fell back to `current`. */\n denied: boolean;\n /** Inline notice to surface when the model actually changed vs `prior`, else undefined. */\n notice?: string;\n}\n\n/**\n * Resolve which model a turn runs, given an optional request, an allow-list, and the prior model.\n * Comparisons are by short label so provider-prefixed and dated ids unify\n * (\"anthropic/claude-opus-4-8\" ≡ \"claude-opus-4-8\" ≡ \"opus\").\n */\nexport function resolveModelSwitch(opts: ResolveModelSwitchOpts): ModelSwitch {\n const { requested, current, prior, allowed } = opts;\n if (!requested) return { model: current, denied: false };\n if (allowed && !allowed.some((a) => modelShortLabel(a) === modelShortLabel(requested))) {\n return { model: current, denied: true };\n }\n const fmt = opts.format ?? ((from: string, to: string) => `_[switching from ${from} to ${to}]_\\n\\n`);\n const changed = prior !== undefined && modelShortLabel(prior) !== modelShortLabel(requested);\n return {\n model: requested,\n denied: false,\n notice: changed ? fmt(modelShortLabel(prior!), modelShortLabel(requested)) : undefined,\n };\n}\n"],"mappings":";AAUO,IAAM,gBAAwC;AAAA,EACnD,OAAO;AAAA,EACP,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,OAAO;AACT;AAGO,SAAS,kBAAkB,OAAuB;AACvD,QAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,QAAM,SAAS,UAAU,KAAK,KAAK,MAAM,MAAM,GAAG,QAAQ,CAAC;AAC3D,QAAM,OAAO,UAAU,KAAK,QAAQ,MAAM,MAAM,QAAQ,CAAC;AACzD,SAAO,UAAU,cAAc,KAAK,YAAY,CAAC,KAAK;AACxD;AAGO,SAAS,gBAAgB,OAAwB;AACtD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI;AAChC,SAAO,GAAG,QAAQ,YAAY,EAAE,EAAE,QAAQ,UAAU,EAAE;AACxD;AA6BO,SAAS,mBAAmB,MAA2C;AAC5E,QAAM,EAAE,WAAW,SAAS,OAAO,QAAQ,IAAI;AAC/C,MAAI,CAAC,UAAW,QAAO,EAAE,OAAO,SAAS,QAAQ,MAAM;AACvD,MAAI,WAAW,CAAC,QAAQ,KAAK,CAAC,MAAM,gBAAgB,CAAC,MAAM,gBAAgB,SAAS,CAAC,GAAG;AACtF,WAAO,EAAE,OAAO,SAAS,QAAQ,KAAK;AAAA,EACxC;AACA,QAAM,MAAM,KAAK,WAAW,CAAC,MAAc,OAAe,oBAAoB,IAAI,OAAO,EAAE;AAAA;AAAA;AAC3F,QAAM,UAAU,UAAU,UAAa,gBAAgB,KAAK,MAAM,gBAAgB,SAAS;AAC3F,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ,UAAU,IAAI,gBAAgB,KAAM,GAAG,gBAAgB,SAAS,CAAC,IAAI;AAAA,EAC/E;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/models.ts"],"sourcesContent":["/**\n * Model aliasing + mid-conversation switch resolution — pure, dependency-free.\n *\n * Harness-level so every agentx consumer (unclaw, para-chat, …) resolves `[opus]`-style\n * aliases, gates by an allow-list, and announces a switch the same way. Policy (which models\n * a caller may use) and session state (the prior model) stay with the consumer; this module\n * is the shared mechanism.\n */\n\n/** Canonical short aliases → concrete Anthropic model ids. */\nexport const MODEL_ALIASES: Record<string, string> = {\n fable: 'claude-fable-5',\n 'fable-5': 'claude-fable-5',\n opus: 'claude-opus-4-8',\n 'opus-4-8': 'claude-opus-4-8',\n 'opus-4-7': 'claude-opus-4-7',\n 'opus-4-6': 'claude-opus-4-6',\n sonnet: 'claude-sonnet-4-6',\n haiku: 'claude-haiku-4-5-20251001',\n};\n\n/** Resolve an alias to a concrete id. A provider prefix (\"anthropic/\") is preserved; unknown ids pass through. */\nexport function resolveModelAlias(input: string): string {\n const slash = input.indexOf('/');\n const prefix = slash === -1 ? '' : input.slice(0, slash + 1);\n const rest = slash === -1 ? input : input.slice(slash + 1);\n return prefix + (MODEL_ALIASES[rest.toLowerCase()] ?? rest);\n}\n\n/** The provider of a model id (\"cursor/x\" -> \"cursor\"). Provider-specific `providerOptions` are only\n * portable within the same provider — leaking them across is a hard 400.\n *\n * A BARE id is the common case, not the exception: `resolveModelAlias('haiku')` yields\n * `claude-haiku-4-5-20251001` with no prefix (ai.libx.js resolves it fuzzily downstream), so reading\n * only the literal \"/\" made every aliased child look like a provider switch and silently dropped the\n * parent's options. The fix belongs HERE — the alias table must keep emitting the ids ai.libx.js\n * expects, and the comparison is provider identity, not string identity.\n *\n * A bare id we can't attribute is UNKNOWN, not a shared provider: it gets a per-id marker so two\n * different unknown ids never compare equal (returning \"\" for both made them look like one provider\n * and would have leaked one host's options onto the other's model). An unknown id still compares\n * equal to ITSELF, so a child staying on the parent's exact model keeps the parent's options. */\nexport function modelProvider(model: string): string {\n const i = model.indexOf('/');\n if (i !== -1) return model.slice(0, i);\n if (/^claude-/i.test(model)) return 'anthropic';\n return `?${model}`; // unknown: identity-scoped, never equal to a different unknown id\n}\n\n/** Short, human-friendly name for a resolved model id (e.g. \"anthropic/claude-opus-4-8\" → \"opus\"). */\nexport function modelShortLabel(model?: string): string {\n if (!model) return 'default';\n const id = model.split('/').pop()!;\n return id.replace(/^claude-/, '').replace(/-\\d.*$/, '');\n}\n\nexport interface ResolveModelSwitchOpts {\n /** Model requested for this turn (e.g. from an inline directive). Undefined = keep `current`. */\n requested?: string;\n /** The turn's default/current model when nothing is requested. */\n current: string;\n /** The session's prior resolved model — drives change detection + the notice. */\n prior?: string;\n /** If set, `requested` must match one of these (by short label) or it's denied and `current` is kept. */\n allowed?: string[];\n /** Announcement formatter. Default: `_[switching from x to y]_\\n\\n`. */\n format?: (from: string, to: string) => string;\n}\n\nexport interface ModelSwitch {\n /** The model to run this turn. */\n model: string;\n /** True when `requested` was rejected by `allowed` and `model` fell back to `current`. */\n denied: boolean;\n /** Inline notice to surface when the model actually changed vs `prior`, else undefined. */\n notice?: string;\n}\n\n/**\n * Resolve which model a turn runs, given an optional request, an allow-list, and the prior model.\n * Comparisons are by short label so provider-prefixed and dated ids unify\n * (\"anthropic/claude-opus-4-8\" ≡ \"claude-opus-4-8\" ≡ \"opus\").\n */\nexport function resolveModelSwitch(opts: ResolveModelSwitchOpts): ModelSwitch {\n const { requested, current, prior, allowed } = opts;\n if (!requested) return { model: current, denied: false };\n if (allowed && !allowed.some((a) => modelShortLabel(a) === modelShortLabel(requested))) {\n return { model: current, denied: true };\n }\n const fmt = opts.format ?? ((from: string, to: string) => `_[switching from ${from} to ${to}]_\\n\\n`);\n const changed = prior !== undefined && modelShortLabel(prior) !== modelShortLabel(requested);\n return {\n model: requested,\n denied: false,\n notice: changed ? fmt(modelShortLabel(prior!), modelShortLabel(requested)) : undefined,\n };\n}\n"],"mappings":";AAUO,IAAM,gBAAwC;AAAA,EACnD,OAAO;AAAA,EACP,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,OAAO;AACT;AAGO,SAAS,kBAAkB,OAAuB;AACvD,QAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,QAAM,SAAS,UAAU,KAAK,KAAK,MAAM,MAAM,GAAG,QAAQ,CAAC;AAC3D,QAAM,OAAO,UAAU,KAAK,QAAQ,MAAM,MAAM,QAAQ,CAAC;AACzD,SAAO,UAAU,cAAc,KAAK,YAAY,CAAC,KAAK;AACxD;AAeO,SAAS,cAAc,OAAuB;AACnD,QAAM,IAAI,MAAM,QAAQ,GAAG;AAC3B,MAAI,MAAM,GAAI,QAAO,MAAM,MAAM,GAAG,CAAC;AACrC,MAAI,YAAY,KAAK,KAAK,EAAG,QAAO;AACpC,SAAO,IAAI,KAAK;AAClB;AAGO,SAAS,gBAAgB,OAAwB;AACtD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI;AAChC,SAAO,GAAG,QAAQ,YAAY,EAAE,EAAE,QAAQ,UAAU,EAAE;AACxD;AA6BO,SAAS,mBAAmB,MAA2C;AAC5E,QAAM,EAAE,WAAW,SAAS,OAAO,QAAQ,IAAI;AAC/C,MAAI,CAAC,UAAW,QAAO,EAAE,OAAO,SAAS,QAAQ,MAAM;AACvD,MAAI,WAAW,CAAC,QAAQ,KAAK,CAAC,MAAM,gBAAgB,CAAC,MAAM,gBAAgB,SAAS,CAAC,GAAG;AACtF,WAAO,EAAE,OAAO,SAAS,QAAQ,KAAK;AAAA,EACxC;AACA,QAAM,MAAM,KAAK,WAAW,CAAC,MAAc,OAAe,oBAAoB,IAAI,OAAO,EAAE;AAAA;AAAA;AAC3F,QAAM,UAAU,UAAU,UAAa,gBAAgB,KAAK,MAAM,gBAAgB,SAAS;AAC3F,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ,UAAU,IAAI,gBAAgB,KAAM,GAAG,gBAAgB,SAAS,CAAC,IAAI;AAAA,EAC/E;AACF;","names":[]}
@@ -407,6 +407,15 @@ interface AgentTool {
407
407
  data: string;
408
408
  }[];
409
409
  }>;
410
+ /** Optional: return a copy of this tool bound to a different real-disk working directory.
411
+ * Implemented by tools that escape the VFS (the real `Shell`), which are cwd-bound at construction
412
+ * and would otherwise keep pointing at the PARENT's tree when the tool instance is inherited by an
413
+ * isolated child agent. `subagent.ts` calls this for a worktree child; tools without it pass through.
414
+ * Return `undefined` for a capability that CANNOT follow the child (the background-job companions,
415
+ * bound to the parent's job registry) — the tool is then dropped from the child's toolbelt.
416
+ * An implementation must carry over any post-construction mutation the host made to the instance
417
+ * (a renamed `name`/`description`) — rebuilding from the factory's options alone loses it. */
418
+ withCwd?(cwd: string): AgentTool | undefined;
410
419
  }
411
420
  /** Build a tool context bound to a filesystem backend (Mem / Disk / …) and an optional host. */
412
421
  declare function makeContext(fs: IFilesystem, host?: HostBridge): ToolContext;
@@ -427,7 +436,10 @@ declare function defaultTools(): AgentTool[];
427
436
  * surface picks from this registry; embedders can build a custom tool set by name.
428
437
  */
429
438
  declare function toolRegistry(): Record<string, AgentTool>;
430
- /** Resolve a list of tool names against the registry (unknown names throw). */
431
- declare function toolsByName(names: string[]): AgentTool[];
439
+ /** Resolve a list of tool names against `available` (host-supplied tools, e.g. a parent agent's
440
+ * toolbelt or mounted MCP tools) first, then the built-in registry. Unknown names throw.
441
+ * Without `available` an allowlist could only ever name a built-in — so a def could not scope a
442
+ * child to a tool its parent injected (`Bash`, `ToolSearch`, …). */
443
+ declare function toolsByName(names: string[], available?: AgentTool[]): AgentTool[];
432
444
 
433
445
  export { type AgentTool as A, makeJobTools as B, type ChatLike as C, messageHasImage as D, messageHasImageRef as E, messageHasInlineImage as F, mintImageRef as G, type HostBridge as H, IMAGE_ELIDE_STUB as I, parseImageRef as J, readTool as K, remintImageRefs as L, type Message as M, sendBytes as N, sendBytesPer as O, toWireTools as P, todoWriteTool as Q, type Role as R, SandboxJobRegistry as S, type TodoItem as T, type UserQuestion as U, toolImageRef as V, toolRegistry as W, toolsByName as X, type ChatOptions as a, type ChatResponse as b, type ContentPart as c, type HostEvent as d, IMAGE_REF_SCHEME as e, type ImageRef as f, type MessageContent as g, type StreamChunk as h, type Tool as i, type ToolCall as j, type ToolContext as k, bashTool as l, clearImageRefs as m, contentBytes as n, contentText as o, defaultTools as p, editTool as q, elideImages as r, elideInlineImages as s, elideStaleImages as t, exitSessionTool as u, expandImagesForSend as v, imagePart as w, imageRefPart as x, imageRefResult as y, makeContext as z };
@@ -1,4 +1,4 @@
1
- import { A as AgentTool } from './tools-BWzPQVy0.js';
1
+ import { A as AgentTool } from './tools-S-ArIR3o.js';
2
2
  import '@livx.cc/wcli/core';
3
3
 
4
4
  /**
@@ -146,7 +146,11 @@ declare class ShellJobRegistry {
146
146
  }
147
147
  /** Build an opt-in real-shell tool bound to `options.cwd`. */
148
148
  declare function makeRealShellTool(options: RealShellOptions): AgentTool;
149
- /** Build the background-job companion tools (ShellOutput / ShellStatus / ShellKill) over a registry. */
149
+ /** Build the background-job companion tools (ShellOutput / ShellStatus / ShellKill) over a registry.
150
+ * Each closes over THIS registry, i.e. this agent's jobs in this agent's cwd, so none of them can be
151
+ * rebound to an isolated child's root: `withCwd` returns `undefined` and they are dropped from the
152
+ * child's toolbelt. That keeps the capability coherent — the child's `Shell` cannot START a background
153
+ * job (its registry is dropped), so it must not be able to inspect or SIGTERM the parent's either. */
150
154
  declare function makeShellJobTools(registry: ShellJobRegistry): AgentTool[];
151
155
 
152
156
  export { type JobExitHandler, type JobExitNotice, type JobStatus, type RealShellOptions, type ShellJobConfig, ShellJobRegistry, type SpawnFn, type SpawnedProcess, formatJobExit, makeRealShellTool, makeShellJobTools };
@@ -679,6 +679,24 @@ function makeRealShellTool(options) {
679
679
  };
680
680
  return {
681
681
  name: "Shell",
682
+ // Rebind for an isolated child agent (git worktree): same policy/env/timeouts, new cwd. The
683
+ // `registry` is deliberately dropped — it is bound to the PARENT's cwd (and, in hosts like
684
+ // shraga-ee, to the parent's session), so a background job started from the child would run
685
+ // outside the child's isolation and report into the parent. Background stays a parent capability
686
+ // (`makeShellJobTools`' companions drop out of an isolated child entirely — see their `withCwd`).
687
+ // Only `run` is rebuilt: everything else is carried over from THIS instance, because a host may
688
+ // have mutated the tool AFTER construction (shraga-ee renames `Shell` -> `Bash` and its system
689
+ // prompt says `Bash` everywhere). Rebuilding from `options` alone silently dropped that rename,
690
+ // so a worktree child advertised `Shell` while being told to call `Bash` — an unknown-tool error
691
+ // on its first call, and a hard failure for an agentType def whose allowlist names `Bash`.
692
+ // `description` is the ONE thing taken from the rebound tool instead: it is derived from the
693
+ // options and states whether `background:true` works — the rebind drops the registry, so carrying
694
+ // the parent's text over would advertise a background capability the child does not have. (The
695
+ // spread also collapses the getter below to a plain value, which is why this override is explicit.)
696
+ withCwd(cwd) {
697
+ const rebound = makeRealShellTool({ ...options, cwd, registry: void 0 });
698
+ return { ...this, description: rebound.description, run: rebound.run, withCwd: rebound.withCwd };
699
+ },
682
700
  get description() {
683
701
  return `Run a shell command via /bin/sh in the working directory. Executes any installed binary \u2014 ls, cat, grep, git, bun, node, curl, scripts, etc. Returns combined stdout+stderr; non-zero exits are prefixed \`[exit N]\`. Runs non-interactively with no terminal (stdin is /dev/null): commands that prompt for input fail fast rather than hang \u2014 for privileged actions use a non-interactive flag (e.g. \`sudo -n\`), or ask the user to run the command themselves. Each command is killed after ${defaultTimeoutMs}ms (result \`[exit 124]\` with whatever output it produced) \u2014 pass \`timeoutMs\` (max ${maxTimeoutMs}) for a legitimately slower command, and always bound network commands yourself (e.g. \`curl -m 10\`). ` + backgroundDoc();
684
702
  },
@@ -793,8 +811,10 @@ ${body}` : head;
793
811
  var NO_JOB = (id) => `Error: no background job '${id}'. Use ShellStatus with no id to list jobs, or start one with Shell({background:true}).`;
794
812
  function makeShellJobTools(registry) {
795
813
  const idParam = { type: "object", properties: { id: { type: "string", description: "the job id from Shell({background:true})" } } };
814
+ const dropOnRebind = { withCwd: () => void 0 };
796
815
  return [
797
816
  {
817
+ ...dropOnRebind,
798
818
  name: "ShellOutput",
799
819
  description: "Read the accumulated output (tail) of a background Shell job by id.",
800
820
  parameters: { type: "object", required: ["id"], properties: { id: { type: "string" } } },
@@ -807,6 +827,7 @@ ${clean(out) || "(no output yet)"}`;
807
827
  }
808
828
  },
809
829
  {
830
+ ...dropOnRebind,
810
831
  name: "ShellStatus",
811
832
  description: "Status of a background Shell job (running/exited/killed + exit code). Omit `id` to list all jobs.",
812
833
  parameters: idParam,
@@ -820,6 +841,7 @@ ${clean(out) || "(no output yet)"}`;
820
841
  }
821
842
  },
822
843
  {
844
+ ...dropOnRebind,
823
845
  name: "ShellKill",
824
846
  description: "Stop a running background Shell job by id (SIGTERM).",
825
847
  parameters: { type: "object", required: ["id"], properties: { id: { type: "string" } } },