@owlmeans/llm-common 0.1.18-rc.2 → 0.1.18-rc.20

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/README.md CHANGED
@@ -20,7 +20,7 @@ extends these; `@owlmeans/llm` implements against them.
20
20
  ## Installation
21
21
 
22
22
  ```bash
23
- bun add @owlmeans/llm-common
23
+ bun add @owlmeans/llm-common@^0.1.18-rc.11
24
24
  ```
25
25
 
26
26
  ## Usage
@@ -96,7 +96,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
96
96
  your project's skill store (`.agents/skills/`):
97
97
 
98
98
  ```sh
99
- npx @owlmeans/agent-skills
99
+ npx @owlmeans/agent-skills@^0.1.18-rc.20
100
100
  ```
101
101
 
102
102
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/llm-common",
4
- "version": "0.1.18-rc.0",
5
- "generatedAt": "2026-08-16T22:20:50.510Z",
4
+ "version": "0.1.18-rc.20",
5
+ "generatedAt": "2026-09-12T14:21:25.466Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/llm-common
9
9
 
10
10
  **Layer:** Core
11
- **Install:** `"@owlmeans/llm-common": "^0.1.18-rc.0"` in `dependencies`
11
+ **Install:** `"@owlmeans/llm-common": "^0.1.18-rc.20"` in `dependencies`
12
12
 
13
13
  The contracts half of the LLM stack. **No `@langchain/*` runtime dependency** — importable
14
14
  from a browser bundle, a queue worker, or any package that must not pull an inference SDK.
@@ -25,29 +25,52 @@ The dependency direction is one-way: a domain contracts package extends these;
25
25
  | `StructuredMode` | `Native` (provider JSON-schema mode) vs `Tool` (forced tool call). |
26
26
  | `SpectatorContentType`, `SPECTATOR_GENERAL` | Observability record enums/defaults. |
27
27
  | `ModelRole` | Open `string` — declare your own enum, its values stay assignable. |
28
- | `ModelConfigPatch` / `ModelConfigOverride` | The JSON-safe config subset; never credentials. |
29
- | `ModelPolicy` | `{ effort, roleOverrides?, modelOverrides? }` — inherited by every refinement. |
28
+ | `ModelConfigPatch` / `ModelConfigOverride` | The JSON-safe config subset; never credentials. Carries the model-capability fields (`contextWindow`, `maxOutput`, `combinedWindow`) alongside the budget ones — see the `llm` skill for what each means. |
29
+ | `ModelPolicy` | `{ effort, roleOverrides?, modelOverrides?, utilityRole? }` — inherited by every refinement. |
30
+ | `UTILITY_ROLE` | `'utility'` — the conventional cheap tier for side calls (a relevance pick, a classification). `ModelPolicy.utilityRole` points it at another alias; `ExecutionService.utility` resolves it. |
30
31
  | `ExecutionState` / `TaskExecutionState` | The persistable core (`level`/`purpose`/`policy`, plus `phase`/`completed`/`cursor`/`data`). |
31
32
  | `LlmPurpose` | `{ type?, dedication? }` — metadata carried on every model call. |
32
33
  | `PromptBlock`, `PROMPT_BLOCK_ORDER`, `DEFAULT_SKILL_ORDER` | The ordered sections of a composed system prompt — the order IS the cache key. |
33
34
  | `SkillDefinition` | One named block of reusable prompt knowledge. `body` must be a pure constant. |
34
35
  | `PromptPolicy` | `{ role?, skills?, cacheSystem?, cacheTtl? }` — carried on `ExecutionState`, merged downward. |
35
36
  | `CacheTtl`, `CacheUsage` | `'5m' \| '1h'`; normalized prompt-cache accounting. |
36
- | `LlmFileProvider`, `FileProviderRef`, `resolveFileProvider` | The minimal read/write file contract prompt plugins work against. |
37
+ | `LlmFileProvider`, `FileProviderRef`, `resolveFileProvider` | The file contract prompt plugins work against — four members, every path relative to the host's project root. `FileProviderRef` accepts the provider or a thunk returning one; `resolveFileProvider` unwraps whichever form arrived, or `undefined`. |
37
38
  | `NullCapture`, `NullKind` | Full diagnostics of a call that returned nothing usable. |
38
39
  | `SpectatorArgument`, `SpectatorEntry`, `SpectatorEntryLogged`, `SpectatorEntryMessage` | What an observability sink stores. |
39
40
 
41
+ ## `LlmFileProvider` — what a host must supply
42
+
43
+ A consumer's own file helper satisfies it structurally (`interface FileHelper extends
44
+ LlmFileProvider`); implementing it from scratch means all four:
45
+
46
+ | Member | Contract |
47
+ |---|---|
48
+ | `readFile(path, noThrow?)` | Read a file relative to the root. With `noThrow`, a missing file yields `''`. |
49
+ | `getSourceList(pattern?)` | Glob for files relative to the root. Project-skill discovery in `@owlmeans/agent-skills` is built on it, so a provider that stubs it indexes nothing. |
50
+ | `writeFile(path, content)` | Write relative to the root, creating parent directories. |
51
+ | `deleteFile(path, noThrow?)` | Delete relative to the root. With `noThrow`, a missing file is a no-op. |
52
+ | `key?` | Optional. The provider's stable identity (project root, sandbox id) — the only thing a plugin caching per-project reads can key on, since providers are rebuilt per request. A provider without one is treated as uncacheable. |
53
+
54
+ Resolving the project root is deliberately NOT part of the contract, and an implementation must not
55
+ narrow an inherited signature — that is what stops a rich helper from satisfying this one.
56
+
40
57
  ## Extension rules
41
58
 
42
59
  Open types are open **on purpose** — extend, do not fork:
43
60
 
44
61
  ```typescript
62
+ import type {
63
+ ExecutionState as LlmExecutionState, LlmPurpose,
64
+ TaskExecutionState as LlmTaskExecutionState,
65
+ } from '@owlmeans/llm-common'
66
+
45
67
  // Your roles: an enum whose values satisfy the open `ModelRole` string.
46
68
  export enum MyRole { Analyst = 'analyst', Coder = 'coder' }
47
69
 
48
- // Your purpose and state: extend, never redeclare.
70
+ // Your purpose and state: extend, never redeclare. Aliasing the imports keeps your own
71
+ // `ExecutionState` the name the rest of your domain uses.
49
72
  export interface MyPurpose extends LlmPurpose { agent?: string }
50
- export interface MyExecutionState extends ExecutionState {
73
+ export interface MyExecutionState extends LlmExecutionState {
51
74
  purpose: MyPurpose
52
75
  projectId?: string
53
76
  }
package/build/consts.d.ts CHANGED
@@ -9,7 +9,21 @@ export declare enum ModelProvider {
9
9
  /** Anthropic messages API. */
10
10
  Anthropic = "anthropic",
11
11
  /** Any OpenAI-compatible endpoint — OpenRouter, HuggingFace router, Together, vLLM, … */
12
- Compatible = "compatible"
12
+ Compatible = "compatible",
13
+ /**
14
+ * No endpoint at all: the call is handed to whoever holds the execution.
15
+ *
16
+ * A delegated model does not talk to a provider. It packages the call — the system prompt, the
17
+ * conversation, the tools or the schema — and hands it to a transport the application seated,
18
+ * which carries it to something outside this process entirely: a coding agent driving the
19
+ * application through a connector, a human, a test. The answer comes back the same way and is
20
+ * turned into a completion the rest of the stack cannot tell apart from a provider's.
21
+ *
22
+ * It exists so that "who performs this call" can be a property of the SESSION rather than of the
23
+ * code: the same pipeline, the same prompts and the same retry rules, billed to somebody else's
24
+ * model.
25
+ */
26
+ Delegated = "delegated"
13
27
  }
14
28
  /**
15
29
  * Refinement level of an execution. An execution is refined downward only:
@@ -82,4 +96,11 @@ export declare enum PromptBlock {
82
96
  export declare const PROMPT_BLOCK_ORDER: readonly PromptBlock[];
83
97
  /** Sort weight of a skill that declares none — see `SkillDefinition.order`. */
84
98
  export declare const DEFAULT_SKILL_ORDER = 100;
99
+ /**
100
+ * Conventional {@link ModelRole} for the cheap side calls the layer makes on its own
101
+ * behalf — a relevance pick, a classification, a one-line judgement — rather than for the
102
+ * work a caller asked for. A deployment that names its cheap tier differently points
103
+ * `ModelPolicy.utilityRole` at its own alias; nothing else has to change.
104
+ */
105
+ export declare const UTILITY_ROLE = "utility";
85
106
  //# sourceMappingURL=consts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,oBAAY,aAAa;IACvB,yFAAyF;IACzF,MAAM,WAAW;IACjB,8BAA8B;IAC9B,SAAS,cAAc;IACvB,yFAAyF;IACzF,UAAU,eAAe;CAC1B;AAED;;;GAGG;AACH,oBAAY,cAAc;IACxB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,MAAM,WAAW;CAClB;AAED;;;;GAIG;AACH,oBAAY,eAAe;IACzB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ;AAED;;;;;;;;;GASG;AACH,oBAAY,cAAc;IACxB,MAAM,WAAW;IACjB,IAAI,SAAS;CACd;AAED,0DAA0D;AAC1D,oBAAY,oBAAoB;IAC9B,IAAI,SAAS;IACb,IAAI,SAAS;IACb,QAAQ,cAAc;CACvB;AAED,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,YAAY,CAAA;AAE1C;;;;;;;;;;;;;;GAcG;AACH,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,YAAY;CACpB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,WAAW,EAK3C,CAAA;AAEV,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,MAAM,CAAA"}
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,oBAAY,aAAa;IACvB,yFAAyF;IACzF,MAAM,WAAW;IACjB,8BAA8B;IAC9B,SAAS,cAAc;IACvB,yFAAyF;IACzF,UAAU,eAAe;IACzB;;;;;;;;;;;;OAYG;IACH,SAAS,cAAc;CACxB;AAED;;;GAGG;AACH,oBAAY,cAAc;IACxB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,MAAM,WAAW;CAClB;AAED;;;;GAIG;AACH,oBAAY,eAAe;IACzB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ;AAED;;;;;;;;;GASG;AACH,oBAAY,cAAc;IACxB,MAAM,WAAW;IACjB,IAAI,SAAS;CACd;AAED,0DAA0D;AAC1D,oBAAY,oBAAoB;IAC9B,IAAI,SAAS;IACb,IAAI,SAAS;IACb,QAAQ,cAAc;CACvB;AAED,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,YAAY,CAAA;AAE1C;;;;;;;;;;;;;;GAcG;AACH,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,YAAY;CACpB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,WAAW,EAK3C,CAAA;AAEV,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,MAAM,CAAA;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,YAAY,YAAY,CAAA"}
package/build/consts.js CHANGED
@@ -11,6 +11,20 @@ export var ModelProvider;
11
11
  ModelProvider["Anthropic"] = "anthropic";
12
12
  /** Any OpenAI-compatible endpoint — OpenRouter, HuggingFace router, Together, vLLM, … */
13
13
  ModelProvider["Compatible"] = "compatible";
14
+ /**
15
+ * No endpoint at all: the call is handed to whoever holds the execution.
16
+ *
17
+ * A delegated model does not talk to a provider. It packages the call — the system prompt, the
18
+ * conversation, the tools or the schema — and hands it to a transport the application seated,
19
+ * which carries it to something outside this process entirely: a coding agent driving the
20
+ * application through a connector, a human, a test. The answer comes back the same way and is
21
+ * turned into a completion the rest of the stack cannot tell apart from a provider's.
22
+ *
23
+ * It exists so that "who performs this call" can be a property of the SESSION rather than of the
24
+ * code: the same pipeline, the same prompts and the same retry rules, billed to somebody else's
25
+ * model.
26
+ */
27
+ ModelProvider["Delegated"] = "delegated";
14
28
  })(ModelProvider || (ModelProvider = {}));
15
29
  /**
16
30
  * Refinement level of an execution. An execution is refined downward only:
@@ -93,4 +107,11 @@ export const PROMPT_BLOCK_ORDER = [
93
107
  ];
94
108
  /** Sort weight of a skill that declares none — see `SkillDefinition.order`. */
95
109
  export const DEFAULT_SKILL_ORDER = 100;
110
+ /**
111
+ * Conventional {@link ModelRole} for the cheap side calls the layer makes on its own
112
+ * behalf — a relevance pick, a classification, a one-line judgement — rather than for the
113
+ * work a caller asked for. A deployment that names its cheap tier differently points
114
+ * `ModelPolicy.utilityRole` at its own alias; nothing else has to change.
115
+ */
116
+ export const UTILITY_ROLE = 'utility';
96
117
  //# sourceMappingURL=consts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,MAAM,CAAN,IAAY,aAOX;AAPD,WAAY,aAAa;IACvB,yFAAyF;IACzF,kCAAiB,CAAA;IACjB,8BAA8B;IAC9B,wCAAuB,CAAA;IACvB,yFAAyF;IACzF,0CAAyB,CAAA;AAC3B,CAAC,EAPW,aAAa,KAAb,aAAa,QAOxB;AAED;;;GAGG;AACH,MAAM,CAAN,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,qCAAmB,CAAA;IACnB,+BAAa,CAAA;IACb,mCAAiB,CAAA;AACnB,CAAC,EAJW,cAAc,KAAd,cAAc,QAIzB;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,sCAAmB,CAAA;IACnB,wCAAqB,CAAA;IACrB,gCAAa,CAAA;IACb,8BAAW,CAAA;AACb,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B;AAED;;;;;;;;;GASG;AACH,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,mCAAiB,CAAA;IACjB,+BAAa,CAAA;AACf,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB;AAED,0DAA0D;AAC1D,MAAM,CAAN,IAAY,oBAIX;AAJD,WAAY,oBAAoB;IAC9B,qCAAa,CAAA;IACb,qCAAa,CAAA;IACb,8CAAsB,CAAA;AACxB,CAAC,EAJW,oBAAoB,KAApB,oBAAoB,QAI/B;AAED,mFAAmF;AACnF,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAA;AAE1C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAN,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,4BAAa,CAAA;IACb,gCAAiB,CAAA;IACjB,oCAAqB,CAAA;IACrB,kCAAmB,CAAA;AACrB,CAAC,EALW,WAAW,KAAX,WAAW,QAKtB;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA2B;IACxD,WAAW,CAAC,IAAI;IAChB,WAAW,CAAC,MAAM;IAClB,WAAW,CAAC,QAAQ;IACpB,WAAW,CAAC,OAAO;CACX,CAAA;AAEV,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAA"}
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,MAAM,CAAN,IAAY,aAqBX;AArBD,WAAY,aAAa;IACvB,yFAAyF;IACzF,kCAAiB,CAAA;IACjB,8BAA8B;IAC9B,wCAAuB,CAAA;IACvB,yFAAyF;IACzF,0CAAyB,CAAA;IACzB;;;;;;;;;;;;OAYG;IACH,wCAAuB,CAAA;AACzB,CAAC,EArBW,aAAa,KAAb,aAAa,QAqBxB;AAED;;;GAGG;AACH,MAAM,CAAN,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,qCAAmB,CAAA;IACnB,+BAAa,CAAA;IACb,mCAAiB,CAAA;AACnB,CAAC,EAJW,cAAc,KAAd,cAAc,QAIzB;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,sCAAmB,CAAA;IACnB,wCAAqB,CAAA;IACrB,gCAAa,CAAA;IACb,8BAAW,CAAA;AACb,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B;AAED;;;;;;;;;GASG;AACH,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,mCAAiB,CAAA;IACjB,+BAAa,CAAA;AACf,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB;AAED,0DAA0D;AAC1D,MAAM,CAAN,IAAY,oBAIX;AAJD,WAAY,oBAAoB;IAC9B,qCAAa,CAAA;IACb,qCAAa,CAAA;IACb,8CAAsB,CAAA;AACxB,CAAC,EAJW,oBAAoB,KAApB,oBAAoB,QAI/B;AAED,mFAAmF;AACnF,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAA;AAE1C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAN,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,4BAAa,CAAA;IACb,gCAAiB,CAAA;IACjB,oCAAqB,CAAA;IACrB,kCAAmB,CAAA;AACrB,CAAC,EALW,WAAW,KAAX,WAAW,QAKtB;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA2B;IACxD,WAAW,CAAC,IAAI;IAChB,WAAW,CAAC,MAAM;IAClB,WAAW,CAAC,QAAQ;IACpB,WAAW,CAAC,OAAO;CACX,CAAA;AAEV,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/delegate/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/delegate/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * The serializable form of one model call, for a performer outside this process.
3
+ *
4
+ * A delegated call cannot pass a `BaseChatModel` or a langchain message anywhere: the thing that
5
+ * answers it is a coding agent on somebody's laptop, a test double, or a person. So the call is
6
+ * reduced to what any of them can act on — a persona, a conversation, and the shape the answer
7
+ * must take — and everything provider-specific is left behind.
8
+ *
9
+ * There is no vocabulary here from whatever pipeline asked. A `role` and a `tier` travel because
10
+ * the performer has to choose a model; nothing else about the caller does.
11
+ */
12
+ /** What the answer must be. */
13
+ export declare enum DelegatedMode {
14
+ /** Prose or code. */
15
+ Text = "text",
16
+ /** Exactly one JSON object satisfying `outputSchema`. */
17
+ Json = "json",
18
+ /** A list of calls chosen from `tools`. */
19
+ Tools = "tools"
20
+ }
21
+ /** Who a message came from. Deliberately the four roles every chat API agrees on. */
22
+ export declare enum DelegatedRole {
23
+ System = "system",
24
+ User = "user",
25
+ Assistant = "assistant",
26
+ Tool = "tool"
27
+ }
28
+ /** What shape an answer came back in. */
29
+ export declare enum DelegatedResultKind {
30
+ Text = "text",
31
+ Json = "json",
32
+ ToolCalls = "tool-calls",
33
+ /** The performer could not answer. Treated as a malformed answer: asked again, with the reason. */
34
+ Error = "error"
35
+ }
36
+ export interface DelegatedToolCall {
37
+ id?: string;
38
+ name: string;
39
+ args: Record<string, unknown>;
40
+ }
41
+ export interface DelegatedMessage {
42
+ role: DelegatedRole;
43
+ content: string;
44
+ /** Assistant turns that called tools. */
45
+ toolCalls?: DelegatedToolCall[];
46
+ /** Tool turns answer one call, and name the tool they answer. */
47
+ toolCallId?: string;
48
+ name?: string;
49
+ }
50
+ export interface DelegatedTool {
51
+ name: string;
52
+ description?: string;
53
+ /** JSON Schema of the arguments. */
54
+ parameters: Record<string, unknown>;
55
+ }
56
+ export type DelegatedToolChoice = 'auto' | 'none' | {
57
+ name: string;
58
+ };
59
+ export interface DelegatedTask {
60
+ id: string;
61
+ /** Which transport is expected to answer it — the key the application seated it under. */
62
+ delegate: string;
63
+ /** The performer's role name, for its own logging. Never load-bearing. */
64
+ role?: string;
65
+ /** Which power class the performer should run this on. */
66
+ tier?: string;
67
+ /** 0-based. Above zero means a previous answer was refused; `feedback` says why. */
68
+ attempt: number;
69
+ mode: DelegatedMode;
70
+ system?: string;
71
+ messages: DelegatedMessage[];
72
+ tools?: DelegatedTool[];
73
+ toolChoice?: DelegatedToolChoice;
74
+ outputSchema?: Record<string, unknown>;
75
+ /** A soft cap, stated so a performer can size its own call. */
76
+ maxOutputChars?: number;
77
+ feedback?: string;
78
+ /** ISO. A performer past this may say so rather than answer. */
79
+ expiresAt?: string;
80
+ }
81
+ export interface DelegatedUsage {
82
+ inputTokens?: number;
83
+ outputTokens?: number;
84
+ }
85
+ export interface DelegatedResult {
86
+ taskId: string;
87
+ kind: DelegatedResultKind;
88
+ text?: string;
89
+ json?: unknown;
90
+ toolCalls?: DelegatedToolCall[];
91
+ error?: string;
92
+ /** What the performer spent. Recorded; it costs this deployment nothing. */
93
+ usage?: DelegatedUsage;
94
+ /** What the performer actually ran. Display only. */
95
+ model?: string;
96
+ }
97
+ /**
98
+ * How a delegated call reaches its performer.
99
+ *
100
+ * One method, because that is the whole seam: everything about routing, waiting, redelivery and
101
+ * giving up belongs to whoever implements it. A transport that cannot serve the call must THROW
102
+ * rather than answer with an error result — an error result is a bad answer, which is retried,
103
+ * while a transport that is gone is terminal.
104
+ */
105
+ export interface DelegateTransport {
106
+ dispatch: (task: DelegatedTask, signal?: AbortSignal) => Promise<DelegatedResult>;
107
+ }
108
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/delegate/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,+BAA+B;AAC/B,oBAAY,aAAa;IACvB,qBAAqB;IACrB,IAAI,SAAS;IACb,yDAAyD;IACzD,IAAI,SAAS;IACb,2CAA2C;IAC3C,KAAK,UAAU;CAChB;AAED,qFAAqF;AACrF,oBAAY,aAAa;IACvB,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,IAAI,SAAS;CACd;AAED,yCAAyC;AACzC,oBAAY,mBAAmB;IAC7B,IAAI,SAAS;IACb,IAAI,SAAS;IACb,SAAS,eAAe;IACxB,mGAAmG;IACnG,KAAK,UAAU;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC/B,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,0FAA0F;IAC1F,QAAQ,EAAE,MAAM,CAAA;IAChB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,aAAa,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,KAAK,CAAC,EAAE,aAAa,EAAE,CAAA;IACvB,UAAU,CAAC,EAAE,mBAAmB,CAAA;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,mBAAmB,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4EAA4E;IAC5E,KAAK,CAAC,EAAE,cAAc,CAAA;IACtB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;CAClF"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The serializable form of one model call, for a performer outside this process.
3
+ *
4
+ * A delegated call cannot pass a `BaseChatModel` or a langchain message anywhere: the thing that
5
+ * answers it is a coding agent on somebody's laptop, a test double, or a person. So the call is
6
+ * reduced to what any of them can act on — a persona, a conversation, and the shape the answer
7
+ * must take — and everything provider-specific is left behind.
8
+ *
9
+ * There is no vocabulary here from whatever pipeline asked. A `role` and a `tier` travel because
10
+ * the performer has to choose a model; nothing else about the caller does.
11
+ */
12
+ /** What the answer must be. */
13
+ export var DelegatedMode;
14
+ (function (DelegatedMode) {
15
+ /** Prose or code. */
16
+ DelegatedMode["Text"] = "text";
17
+ /** Exactly one JSON object satisfying `outputSchema`. */
18
+ DelegatedMode["Json"] = "json";
19
+ /** A list of calls chosen from `tools`. */
20
+ DelegatedMode["Tools"] = "tools";
21
+ })(DelegatedMode || (DelegatedMode = {}));
22
+ /** Who a message came from. Deliberately the four roles every chat API agrees on. */
23
+ export var DelegatedRole;
24
+ (function (DelegatedRole) {
25
+ DelegatedRole["System"] = "system";
26
+ DelegatedRole["User"] = "user";
27
+ DelegatedRole["Assistant"] = "assistant";
28
+ DelegatedRole["Tool"] = "tool";
29
+ })(DelegatedRole || (DelegatedRole = {}));
30
+ /** What shape an answer came back in. */
31
+ export var DelegatedResultKind;
32
+ (function (DelegatedResultKind) {
33
+ DelegatedResultKind["Text"] = "text";
34
+ DelegatedResultKind["Json"] = "json";
35
+ DelegatedResultKind["ToolCalls"] = "tool-calls";
36
+ /** The performer could not answer. Treated as a malformed answer: asked again, with the reason. */
37
+ DelegatedResultKind["Error"] = "error";
38
+ })(DelegatedResultKind || (DelegatedResultKind = {}));
39
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/delegate/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,+BAA+B;AAC/B,MAAM,CAAN,IAAY,aAOX;AAPD,WAAY,aAAa;IACvB,qBAAqB;IACrB,8BAAa,CAAA;IACb,yDAAyD;IACzD,8BAAa,CAAA;IACb,2CAA2C;IAC3C,gCAAe,CAAA;AACjB,CAAC,EAPW,aAAa,KAAb,aAAa,QAOxB;AAED,qFAAqF;AACrF,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,kCAAiB,CAAA;IACjB,8BAAa,CAAA;IACb,wCAAuB,CAAA;IACvB,8BAAa,CAAA;AACf,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB;AAED,yCAAyC;AACzC,MAAM,CAAN,IAAY,mBAMX;AAND,WAAY,mBAAmB;IAC7B,oCAAa,CAAA;IACb,oCAAa,CAAA;IACb,+CAAwB,CAAA;IACxB,mGAAmG;IACnG,sCAAe,CAAA;AACjB,CAAC,EANW,mBAAmB,KAAnB,mBAAmB,QAM9B"}
@@ -17,6 +17,16 @@
17
17
  * that stops a rich helper from satisfying this one.
18
18
  */
19
19
  export interface LlmFileProvider {
20
+ /**
21
+ * Stable identity of WHAT this provider reads — a project root, a sandbox id.
22
+ *
23
+ * A prompt plugin that caches resolved reads across calls has nothing else to key on:
24
+ * providers are late-bound and often rebuilt per request, so object identity says
25
+ * nothing, and a cache shared between two projects serves the first one's files to the
26
+ * second. A provider that supplies no key is treated as uncacheable rather than as one
27
+ * more anonymous member of a shared bucket.
28
+ */
29
+ key?: string;
20
30
  /** Read a file relative to the root. With `noThrow`, a missing file yields `''`. */
21
31
  readFile: (filePath: string, noThrow?: boolean) => Promise<string>;
22
32
  /** Glob for files relative to the root. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,eAAe;IAC9B,oFAAoF;IACpF,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAElE,2CAA2C;IAC3C,aAAa,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAEtD,gFAAgF;IAChF,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAE/D,qFAAqF;IACrF,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACnE;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG,CAAC,MAAM,eAAe,CAAC,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ,oFAAoF;IACpF,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAElE,2CAA2C;IAC3C,aAAa,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAEtD,gFAAgF;IAChF,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAE/D,qFAAqF;IACrF,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACnE;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG,CAAC,MAAM,eAAe,CAAC,CAAA"}
package/build/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export type * from './types.js';
3
3
  export type * from './spectator/types.js';
4
4
  export type * from './files/types.js';
5
5
  export * from './files/utils.js';
6
+ export * from './delegate/index.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA;AAC/B,mBAAmB,sBAAsB,CAAA;AACzC,mBAAmB,kBAAkB,CAAA;AACrC,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA;AAC/B,mBAAmB,sBAAsB,CAAA;AACzC,mBAAmB,kBAAkB,CAAA;AACrC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA"}
package/build/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './consts.js';
2
2
  export * from './files/utils.js';
3
+ export * from './delegate/index.js';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAI3B,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAI3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA"}
package/build/types.d.ts CHANGED
@@ -29,6 +29,12 @@ export interface ModelConfigPatch {
29
29
  maxTokensCap?: number;
30
30
  topP?: number;
31
31
  disableThinking?: boolean;
32
+ /** Total window the model accepts (input + output). Informational / validation only. */
33
+ contextWindow?: number;
34
+ /** What the PROVIDER can emit in one request. Hard ceiling for `maxTokens`/`maxTokensCap`. */
35
+ maxOutput?: number;
36
+ /** The window is shared between input and output rather than input-only. */
37
+ combinedWindow?: boolean;
32
38
  }
33
39
  /** A JSON-safe model override: a config alias, or a partial config patch. */
34
40
  export type ModelConfigOverride = string | ModelConfigPatch;
@@ -44,6 +50,12 @@ export interface ModelPolicy {
44
50
  roleOverrides?: Partial<Record<ModelRole, ModelRole>>;
45
51
  /** "Pin a role to a specific model/config" — alias or partial config override. */
46
52
  modelOverrides?: Partial<Record<ModelRole, ModelConfigOverride>>;
53
+ /**
54
+ * Role resolved by `ExecutionService.utility` for cheap side calls. Defaults to
55
+ * `UTILITY_ROLE`; name another alias when the deployment calls its cheap tier
56
+ * something else. `roleOverrides` still applies on top of whichever one is used.
57
+ */
58
+ utilityRole?: ModelRole;
47
59
  }
48
60
  /**
49
61
  * Lifetime of a provider-side prompt cache entry. `'1h'` costs roughly twice as much to
@@ -120,9 +132,16 @@ export interface ExecutionState {
120
132
  /** Role + skills for this level; merged downward by `ExecutionService`. */
121
133
  prompt?: PromptPolicy;
122
134
  }
123
- /** Resumable state of a task-level execution. */
135
+ /**
136
+ * The task level's own fields.
137
+ *
138
+ * `phase`, `completed` and `cursor` are LABELS — for a trace line, a prompt, a log — and never a
139
+ * workflow position. Recoverable position lives on a pipeline run row (`@owlmeans/agent`), which is
140
+ * a single authority; an execution that also claimed to know where a run stood would be a second
141
+ * one, and the two would disagree the first time a step wrote only one of them.
142
+ */
124
143
  export interface TaskExecutionState extends ExecutionState {
125
- /** Abstract workflow position for checkpoint/resume. */
144
+ /** A label for the stage a task considers itself in. Never read back to decide anything. */
126
145
  phase?: string;
127
146
  completed?: string[];
128
147
  cursor?: string;
@@ -171,11 +190,18 @@ export interface NullCapture {
171
190
  tool_calls?: unknown;
172
191
  } | null;
173
192
  diagnostics: {
193
+ /** Whatever the provider called it — OpenAI's `finish_reason` or Anthropic's `stop_reason`. */
174
194
  finishReason?: string;
175
195
  inputTokens?: number;
176
196
  outputTokens?: number;
177
197
  reasoningTokens?: number;
178
198
  contentEmpty: boolean;
199
+ /**
200
+ * Content arrived, but none of it was text — the shape of an answer that was all reasoning.
201
+ * Distinguishes "spent the budget thinking" from "returned nothing at all", which
202
+ * `contentEmpty` alone cannot.
203
+ */
204
+ thinkingOnly?: boolean;
179
205
  hadToolCall: boolean;
180
206
  };
181
207
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/llm-common",
3
- "version": "0.1.18-rc.2",
3
+ "version": "0.1.18-rc.20",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -21,7 +21,7 @@
21
21
  }
22
22
  },
23
23
  "devDependencies": {
24
- "@langchain/core": "^1.1.39",
24
+ "@langchain/core": "^1.2.9",
25
25
  "@owlmeans/dep-config": "workspace:*",
26
26
  "nodemon": "^3.1.14",
27
27
  "typescript": "^7.0.2"
package/src/consts.ts CHANGED
@@ -11,6 +11,20 @@ export enum ModelProvider {
11
11
  Anthropic = 'anthropic',
12
12
  /** Any OpenAI-compatible endpoint — OpenRouter, HuggingFace router, Together, vLLM, … */
13
13
  Compatible = 'compatible',
14
+ /**
15
+ * No endpoint at all: the call is handed to whoever holds the execution.
16
+ *
17
+ * A delegated model does not talk to a provider. It packages the call — the system prompt, the
18
+ * conversation, the tools or the schema — and hands it to a transport the application seated,
19
+ * which carries it to something outside this process entirely: a coding agent driving the
20
+ * application through a connector, a human, a test. The answer comes back the same way and is
21
+ * turned into a completion the rest of the stack cannot tell apart from a provider's.
22
+ *
23
+ * It exists so that "who performs this call" can be a property of the SESSION rather than of the
24
+ * code: the same pipeline, the same prompts and the same retry rules, billed to somebody else's
25
+ * model.
26
+ */
27
+ Delegated = 'delegated',
14
28
  }
15
29
 
16
30
  /**
@@ -96,3 +110,11 @@ export const PROMPT_BLOCK_ORDER: readonly PromptBlock[] = [
96
110
 
97
111
  /** Sort weight of a skill that declares none — see `SkillDefinition.order`. */
98
112
  export const DEFAULT_SKILL_ORDER = 100
113
+
114
+ /**
115
+ * Conventional {@link ModelRole} for the cheap side calls the layer makes on its own
116
+ * behalf — a relevance pick, a classification, a one-line judgement — rather than for the
117
+ * work a caller asked for. A deployment that names its cheap tier differently points
118
+ * `ModelPolicy.utilityRole` at its own alias; nothing else has to change.
119
+ */
120
+ export const UTILITY_ROLE = 'utility'
@@ -0,0 +1 @@
1
+ export * from './types.js'
@@ -0,0 +1,116 @@
1
+ /**
2
+ * The serializable form of one model call, for a performer outside this process.
3
+ *
4
+ * A delegated call cannot pass a `BaseChatModel` or a langchain message anywhere: the thing that
5
+ * answers it is a coding agent on somebody's laptop, a test double, or a person. So the call is
6
+ * reduced to what any of them can act on — a persona, a conversation, and the shape the answer
7
+ * must take — and everything provider-specific is left behind.
8
+ *
9
+ * There is no vocabulary here from whatever pipeline asked. A `role` and a `tier` travel because
10
+ * the performer has to choose a model; nothing else about the caller does.
11
+ */
12
+
13
+ /** What the answer must be. */
14
+ export enum DelegatedMode {
15
+ /** Prose or code. */
16
+ Text = 'text',
17
+ /** Exactly one JSON object satisfying `outputSchema`. */
18
+ Json = 'json',
19
+ /** A list of calls chosen from `tools`. */
20
+ Tools = 'tools',
21
+ }
22
+
23
+ /** Who a message came from. Deliberately the four roles every chat API agrees on. */
24
+ export enum DelegatedRole {
25
+ System = 'system',
26
+ User = 'user',
27
+ Assistant = 'assistant',
28
+ Tool = 'tool',
29
+ }
30
+
31
+ /** What shape an answer came back in. */
32
+ export enum DelegatedResultKind {
33
+ Text = 'text',
34
+ Json = 'json',
35
+ ToolCalls = 'tool-calls',
36
+ /** The performer could not answer. Treated as a malformed answer: asked again, with the reason. */
37
+ Error = 'error',
38
+ }
39
+
40
+ export interface DelegatedToolCall {
41
+ id?: string
42
+ name: string
43
+ args: Record<string, unknown>
44
+ }
45
+
46
+ export interface DelegatedMessage {
47
+ role: DelegatedRole
48
+ content: string
49
+ /** Assistant turns that called tools. */
50
+ toolCalls?: DelegatedToolCall[]
51
+ /** Tool turns answer one call, and name the tool they answer. */
52
+ toolCallId?: string
53
+ name?: string
54
+ }
55
+
56
+ export interface DelegatedTool {
57
+ name: string
58
+ description?: string
59
+ /** JSON Schema of the arguments. */
60
+ parameters: Record<string, unknown>
61
+ }
62
+
63
+ export type DelegatedToolChoice = 'auto' | 'none' | { name: string }
64
+
65
+ export interface DelegatedTask {
66
+ id: string
67
+ /** Which transport is expected to answer it — the key the application seated it under. */
68
+ delegate: string
69
+ /** The performer's role name, for its own logging. Never load-bearing. */
70
+ role?: string
71
+ /** Which power class the performer should run this on. */
72
+ tier?: string
73
+ /** 0-based. Above zero means a previous answer was refused; `feedback` says why. */
74
+ attempt: number
75
+ mode: DelegatedMode
76
+ system?: string
77
+ messages: DelegatedMessage[]
78
+ tools?: DelegatedTool[]
79
+ toolChoice?: DelegatedToolChoice
80
+ outputSchema?: Record<string, unknown>
81
+ /** A soft cap, stated so a performer can size its own call. */
82
+ maxOutputChars?: number
83
+ feedback?: string
84
+ /** ISO. A performer past this may say so rather than answer. */
85
+ expiresAt?: string
86
+ }
87
+
88
+ export interface DelegatedUsage {
89
+ inputTokens?: number
90
+ outputTokens?: number
91
+ }
92
+
93
+ export interface DelegatedResult {
94
+ taskId: string
95
+ kind: DelegatedResultKind
96
+ text?: string
97
+ json?: unknown
98
+ toolCalls?: DelegatedToolCall[]
99
+ error?: string
100
+ /** What the performer spent. Recorded; it costs this deployment nothing. */
101
+ usage?: DelegatedUsage
102
+ /** What the performer actually ran. Display only. */
103
+ model?: string
104
+ }
105
+
106
+ /**
107
+ * How a delegated call reaches its performer.
108
+ *
109
+ * One method, because that is the whole seam: everything about routing, waiting, redelivery and
110
+ * giving up belongs to whoever implements it. A transport that cannot serve the call must THROW
111
+ * rather than answer with an error result — an error result is a bad answer, which is retried,
112
+ * while a transport that is gone is terminal.
113
+ */
114
+ export interface DelegateTransport {
115
+ dispatch: (task: DelegatedTask, signal?: AbortSignal) => Promise<DelegatedResult>
116
+ }
@@ -17,6 +17,17 @@
17
17
  * that stops a rich helper from satisfying this one.
18
18
  */
19
19
  export interface LlmFileProvider {
20
+ /**
21
+ * Stable identity of WHAT this provider reads — a project root, a sandbox id.
22
+ *
23
+ * A prompt plugin that caches resolved reads across calls has nothing else to key on:
24
+ * providers are late-bound and often rebuilt per request, so object identity says
25
+ * nothing, and a cache shared between two projects serves the first one's files to the
26
+ * second. A provider that supplies no key is treated as uncacheable rather than as one
27
+ * more anonymous member of a shared bucket.
28
+ */
29
+ key?: string
30
+
20
31
  /** Read a file relative to the root. With `noThrow`, a missing file yields `''`. */
21
32
  readFile: (filePath: string, noThrow?: boolean) => Promise<string>
22
33
 
package/src/index.ts CHANGED
@@ -4,3 +4,4 @@ export type * from './types.js'
4
4
  export type * from './spectator/types.js'
5
5
  export type * from './files/types.js'
6
6
  export * from './files/utils.js'
7
+ export * from './delegate/index.js'
package/src/types.ts CHANGED
@@ -32,6 +32,12 @@ export interface ModelConfigPatch {
32
32
  maxTokensCap?: number
33
33
  topP?: number
34
34
  disableThinking?: boolean
35
+ /** Total window the model accepts (input + output). Informational / validation only. */
36
+ contextWindow?: number
37
+ /** What the PROVIDER can emit in one request. Hard ceiling for `maxTokens`/`maxTokensCap`. */
38
+ maxOutput?: number
39
+ /** The window is shared between input and output rather than input-only. */
40
+ combinedWindow?: boolean
35
41
  }
36
42
 
37
43
  /** A JSON-safe model override: a config alias, or a partial config patch. */
@@ -49,6 +55,12 @@ export interface ModelPolicy {
49
55
  roleOverrides?: Partial<Record<ModelRole, ModelRole>>
50
56
  /** "Pin a role to a specific model/config" — alias or partial config override. */
51
57
  modelOverrides?: Partial<Record<ModelRole, ModelConfigOverride>>
58
+ /**
59
+ * Role resolved by `ExecutionService.utility` for cheap side calls. Defaults to
60
+ * `UTILITY_ROLE`; name another alias when the deployment calls its cheap tier
61
+ * something else. `roleOverrides` still applies on top of whichever one is used.
62
+ */
63
+ utilityRole?: ModelRole
52
64
  }
53
65
 
54
66
  /**
@@ -131,9 +143,16 @@ export interface ExecutionState {
131
143
  prompt?: PromptPolicy
132
144
  }
133
145
 
134
- /** Resumable state of a task-level execution. */
146
+ /**
147
+ * The task level's own fields.
148
+ *
149
+ * `phase`, `completed` and `cursor` are LABELS — for a trace line, a prompt, a log — and never a
150
+ * workflow position. Recoverable position lives on a pipeline run row (`@owlmeans/agent`), which is
151
+ * a single authority; an execution that also claimed to know where a run stood would be a second
152
+ * one, and the two would disagree the first time a step wrote only one of them.
153
+ */
135
154
  export interface TaskExecutionState extends ExecutionState {
136
- /** Abstract workflow position for checkpoint/resume. */
155
+ /** A label for the stage a task considers itself in. Never read back to decide anything. */
137
156
  phase?: string
138
157
  completed?: string[]
139
158
  cursor?: string
@@ -181,11 +200,18 @@ export interface NullCapture {
181
200
  tool_calls?: unknown
182
201
  } | null
183
202
  diagnostics: {
203
+ /** Whatever the provider called it — OpenAI's `finish_reason` or Anthropic's `stop_reason`. */
184
204
  finishReason?: string
185
205
  inputTokens?: number
186
206
  outputTokens?: number
187
207
  reasoningTokens?: number
188
208
  contentEmpty: boolean
209
+ /**
210
+ * Content arrived, but none of it was text — the shape of an answer that was all reasoning.
211
+ * Distinguishes "spent the budget thinking" from "returned nothing at all", which
212
+ * `contentEmpty` alone cannot.
213
+ */
214
+ thinkingOnly?: boolean
189
215
  hadToolCall: boolean
190
216
  }
191
217
  }