@owlmeans/llm-common 0.1.15 → 0.1.16-rc.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.
@@ -7,7 +7,7 @@ applyTo: "**/*.ts, **/*.tsx"
7
7
  # @owlmeans/llm-common
8
8
 
9
9
  **Layer:** Core
10
- **Install:** `"@owlmeans/llm-common": "^0.1.15"` in `dependencies`
10
+ **Install:** `"@owlmeans/llm-common": "^0.1.16-rc.0"` in `dependencies`
11
11
 
12
12
  The contracts half of the LLM stack. **No `@langchain/*` runtime dependency** — importable
13
13
  from a browser bundle or a queue worker. Dependency direction is one-way: a domain contracts
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@owlmeans/llm-common",
4
- "version": "0.1.15",
5
- "generatedAt": "2026-08-07T17:06:32.908Z",
4
+ "version": "0.1.16-rc.0",
5
+ "generatedAt": "2026-08-11T14:02:34.991Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: llm-common
3
- description: How to use @owlmeans/llm-common — runtime-free serializable contracts for LLM inference and execution (ModelProvider, ExecutionEffort/Level, ModelPolicy, ExecutionState, spectator records, NullCapture). Auto-invoked when importing those contracts or extending them for a domain.
3
+ description: How to use @owlmeans/llm-common — runtime-free serializable contracts for LLM inference and execution (ModelProvider, ExecutionEffort/Level, ModelPolicy, PromptPolicy, SkillDefinition, ExecutionState, spectator records, NullCapture, LlmFileProvider). Auto-invoked when importing those contracts or extending them for a domain.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -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.15"` in `dependencies`
11
+ **Install:** `"@owlmeans/llm-common": "^0.1.16-rc.0"` 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.
@@ -29,6 +29,11 @@ The dependency direction is one-way: a domain contracts package extends these;
29
29
  | `ModelPolicy` | `{ effort, roleOverrides?, modelOverrides? }` — inherited by every refinement. |
30
30
  | `ExecutionState` / `TaskExecutionState` | The persistable core (`level`/`purpose`/`policy`, plus `phase`/`completed`/`cursor`/`data`). |
31
31
  | `LlmPurpose` | `{ type?, dedication? }` — metadata carried on every model call. |
32
+ | `PromptBlock`, `PROMPT_BLOCK_ORDER`, `DEFAULT_SKILL_ORDER` | The ordered sections of a composed system prompt — the order IS the cache key. |
33
+ | `SkillDefinition` | One named block of reusable prompt knowledge. `body` must be a pure constant. |
34
+ | `PromptPolicy` | `{ role?, skills?, cacheSystem?, cacheTtl? }` — carried on `ExecutionState`, merged downward. |
35
+ | `CacheTtl`, `CacheUsage` | `'5m' \| '1h'`; normalized prompt-cache accounting. |
36
+ | `LlmFileProvider`, `FileProviderRef`, `resolveFileProvider` | The minimal read/write file contract prompt plugins work against. |
32
37
  | `NullCapture`, `NullKind` | Full diagnostics of a call that returned nothing usable. |
33
38
  | `SpectatorArgument`, `SpectatorEntry`, `SpectatorEntryLogged`, `SpectatorEntryMessage` | What an observability sink stores. |
34
39
 
package/build/consts.d.ts CHANGED
@@ -53,4 +53,33 @@ export declare enum SpectatorContentType {
53
53
  }
54
54
  /** Default spectator entry kind for consumers that do not classify their calls. */
55
55
  export declare const SPECTATOR_GENERAL = "general";
56
+ /**
57
+ * Ordered sections of a composed system prompt.
58
+ *
59
+ * The ordering is not cosmetic — it IS the prompt-cache design. Every provider caches
60
+ * a prompt by exact PREFIX match, so the sections are laid out most-stable first and a
61
+ * cache breakpoint is placed at each stability boundary:
62
+ *
63
+ * - `Role` — the base system prompt defining who the model is. Stable per role.
64
+ * - `Skills` — the statically declared capabilities, rendered in a deterministic
65
+ * order. Stable per helper. A breakpoint closes `Role` + `Skills`.
66
+ * - `Packages` — capabilities resolved from whatever the request happens to mention.
67
+ * Varies per request, so it gets its OWN breakpoint and can never
68
+ * invalidate the two blocks above it.
69
+ * - `Context` — volatile, caller-supplied system text. Never cached.
70
+ */
71
+ export declare enum PromptBlock {
72
+ Role = "role",
73
+ Skills = "skills",
74
+ Packages = "packages",
75
+ Context = "context"
76
+ }
77
+ /**
78
+ * Emission order of {@link PromptBlock}. Declared explicitly rather than derived from
79
+ * the enum: the composed prompt must be byte-identical across processes and runtimes,
80
+ * and enum iteration order is not part of any contract worth betting a cache on.
81
+ */
82
+ export declare const PROMPT_BLOCK_ORDER: readonly PromptBlock[];
83
+ /** Sort weight of a skill that declares none — see `SkillDefinition.order`. */
84
+ export declare const DEFAULT_SKILL_ORDER = 100;
56
85
  //# 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"}
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"}
package/build/consts.js CHANGED
@@ -58,4 +58,39 @@ export var SpectatorContentType;
58
58
  })(SpectatorContentType || (SpectatorContentType = {}));
59
59
  /** Default spectator entry kind for consumers that do not classify their calls. */
60
60
  export const SPECTATOR_GENERAL = 'general';
61
+ /**
62
+ * Ordered sections of a composed system prompt.
63
+ *
64
+ * The ordering is not cosmetic — it IS the prompt-cache design. Every provider caches
65
+ * a prompt by exact PREFIX match, so the sections are laid out most-stable first and a
66
+ * cache breakpoint is placed at each stability boundary:
67
+ *
68
+ * - `Role` — the base system prompt defining who the model is. Stable per role.
69
+ * - `Skills` — the statically declared capabilities, rendered in a deterministic
70
+ * order. Stable per helper. A breakpoint closes `Role` + `Skills`.
71
+ * - `Packages` — capabilities resolved from whatever the request happens to mention.
72
+ * Varies per request, so it gets its OWN breakpoint and can never
73
+ * invalidate the two blocks above it.
74
+ * - `Context` — volatile, caller-supplied system text. Never cached.
75
+ */
76
+ export var PromptBlock;
77
+ (function (PromptBlock) {
78
+ PromptBlock["Role"] = "role";
79
+ PromptBlock["Skills"] = "skills";
80
+ PromptBlock["Packages"] = "packages";
81
+ PromptBlock["Context"] = "context";
82
+ })(PromptBlock || (PromptBlock = {}));
83
+ /**
84
+ * Emission order of {@link PromptBlock}. Declared explicitly rather than derived from
85
+ * the enum: the composed prompt must be byte-identical across processes and runtimes,
86
+ * and enum iteration order is not part of any contract worth betting a cache on.
87
+ */
88
+ export const PROMPT_BLOCK_ORDER = [
89
+ PromptBlock.Role,
90
+ PromptBlock.Skills,
91
+ PromptBlock.Packages,
92
+ PromptBlock.Context,
93
+ ];
94
+ /** Sort weight of a skill that declares none — see `SkillDefinition.order`. */
95
+ export const DEFAULT_SKILL_ORDER = 100;
61
96
  //# 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"}
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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The slice of a host application's file access that the LLM layer is allowed to see.
3
+ *
4
+ * A consumer almost always owns a much richer file helper (project metadata, source
5
+ * classification, remote/sandbox transports). This contract is deliberately the smallest
6
+ * useful subset, so a prompt plugin can read a package manifest or write a scratch file
7
+ * without the common layer learning anything about the consumer's project model. A
8
+ * consumer's own helper satisfies it structurally — declare
9
+ * `interface FileHelper extends LlmFileProvider` and nothing else changes.
10
+ *
11
+ * It lives in `llm-common` (not `llm`) because it is a contract, not a runtime: the
12
+ * package stays dependency-free and browser-safe.
13
+ *
14
+ * Every path is relative to the host's project root. Resolving that root is deliberately
15
+ * NOT part of the contract — a consumer with a multi-root layout types its own accessor
16
+ * with its own enum, and narrowing an inherited signature is exactly the kind of change
17
+ * that stops a rich helper from satisfying this one.
18
+ */
19
+ export interface LlmFileProvider {
20
+ /** Read a file relative to the root. With `noThrow`, a missing file yields `''`. */
21
+ readFile: (filePath: string, noThrow?: boolean) => Promise<string>;
22
+ /** Glob for files relative to the root. */
23
+ getSourceList: (pattern?: string) => Promise<string[]>;
24
+ /** Write a file relative to the root, creating parent directories as needed. */
25
+ writeFile: (filePath: string, content: string) => Promise<void>;
26
+ /** Delete a file relative to the root. With `noThrow`, a missing file is a no-op. */
27
+ deleteFile: (filePath: string, noThrow?: boolean) => Promise<void>;
28
+ }
29
+ /**
30
+ * A provider, or a resolver for one.
31
+ *
32
+ * Collaborators in this layer are usually late-bound functions so a service can be
33
+ * swapped or cloned — but a file helper is just as often a plain object a consumer
34
+ * already holds. Accepting both spares every call site a wrapper.
35
+ */
36
+ export type FileProviderRef = LlmFileProvider | (() => LlmFileProvider);
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { FileProviderRef, LlmFileProvider } from './types.js';
2
+ /** Unwrap a {@link FileProviderRef} whichever form it arrived in. */
3
+ export declare const resolveFileProvider: (ref: FileProviderRef | undefined) => LlmFileProvider | undefined;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/files/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAElE,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,GAC9B,KAAK,eAAe,GAAG,SAAS,KAC/B,eAAe,GAAG,SAAoD,CAAA"}
@@ -0,0 +1,3 @@
1
+ /** Unwrap a {@link FileProviderRef} whichever form it arrived in. */
2
+ export const resolveFileProvider = (ref) => typeof ref === 'function' ? ref() : ref;
3
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/files/utils.ts"],"names":[],"mappings":"AAEA,qEAAqE;AACrE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,GAAgC,EACH,EAAE,CAAC,OAAO,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA"}
package/build/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from './consts.js';
2
2
  export type * from './types.js';
3
3
  export type * from './spectator/types.js';
4
+ export type * from './files/types.js';
5
+ export * from './files/utils.js';
4
6
  //# 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"}
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"}
package/build/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './consts.js';
2
+ export * from './files/utils.js';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAI3B,cAAc,kBAAkB,CAAA"}
package/build/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ExecutionEffort, ExecutionLevel } from './consts.js';
1
+ import type { ExecutionEffort, ExecutionLevel, PromptBlock } from './consts.js';
2
2
  /**
3
3
  * Free-form observability metadata attached to every model call — forwarded to the
4
4
  * inference provider as run metadata and recorded on every spectator entry. Kept
@@ -45,6 +45,68 @@ export interface ModelPolicy {
45
45
  /** "Pin a role to a specific model/config" — alias or partial config override. */
46
46
  modelOverrides?: Partial<Record<ModelRole, ModelConfigOverride>>;
47
47
  }
48
+ /**
49
+ * Lifetime of a provider-side prompt cache entry. `'1h'` costs roughly twice as much to
50
+ * write as `'5m'`, so it only pays off from the third read onward — use it for a system
51
+ * prefix that survives a long run, not for a one-shot call.
52
+ */
53
+ export type CacheTtl = '5m' | '1h';
54
+ /**
55
+ * One named, reusable chunk of system-prompt knowledge — a capability the model is told
56
+ * it has. Registered once (by the package that owns the knowledge or by the final app)
57
+ * and referenced by `alias` from any execution level.
58
+ *
59
+ * `body` must be a PURE CONSTANT: no timestamps, no absolute paths, no interpolated
60
+ * request data. Every skill lands in the cached region of the system prompt, and one
61
+ * varying byte invalidates the whole prefix for every call that shares it.
62
+ */
63
+ export interface SkillDefinition {
64
+ /** Stable slug — how executions reference the skill. */
65
+ alias: string;
66
+ /** Rendered as the skill's heading; falls back to `alias`. */
67
+ title?: string;
68
+ /** Not sent to the model — documentation for whoever wires the registry. */
69
+ description?: string;
70
+ /** The prompt text itself. */
71
+ body: string;
72
+ /** Sort weight; ties broken by `alias`. Defaults to `DEFAULT_SKILL_ORDER`. */
73
+ order?: number;
74
+ /** Which block to render into. Defaults to `PromptBlock.Skills`. */
75
+ block?: PromptBlock;
76
+ /** Aliases pulled in transitively when this skill is enabled. */
77
+ requires?: string[];
78
+ }
79
+ /**
80
+ * The "flexible execution parameters" that shape a system prompt. Carried on
81
+ * {@link ExecutionState}, so it is JSON-safe, survives a checkpoint/restore round trip,
82
+ * and accumulates down the execution chain: a task adds skills on top of the project,
83
+ * a helper on top of the task. `role` is overridden by the deepest level that sets it;
84
+ * `skills` are unioned.
85
+ */
86
+ export interface PromptPolicy {
87
+ /** Base system prompt — becomes the first block. */
88
+ role?: string;
89
+ /** Skill aliases enabled at this level. */
90
+ skills?: string[];
91
+ /** Mark the composed system prompt cacheable. Defaults to `true`. */
92
+ cacheSystem?: boolean;
93
+ /** Cache lifetime for the system prefix. Defaults to `'5m'`. */
94
+ cacheTtl?: CacheTtl;
95
+ }
96
+ /**
97
+ * Prompt-cache accounting for a single call, normalized across providers. The only
98
+ * reliable way to tell whether caching actually works: if `read` stays 0 across repeated
99
+ * calls with the same prefix, something is silently invalidating it.
100
+ */
101
+ export interface CacheUsage {
102
+ /** Tokens served from cache (~0.1x price). */
103
+ read: number;
104
+ /** Tokens written to cache (~1.25x price at 5m TTL, ~2x at 1h). */
105
+ creation: number;
106
+ /** Tokens processed at full price. */
107
+ input: number;
108
+ output: number;
109
+ }
48
110
  /**
49
111
  * Serializable execution state — no functions, no file access, no model instances.
50
112
  * The runtime `Execution` (`@owlmeans/llm`) = this state + attached collaborators.
@@ -55,6 +117,8 @@ export interface ExecutionState {
55
117
  level: ExecutionLevel;
56
118
  purpose: LlmPurpose;
57
119
  policy: ModelPolicy;
120
+ /** Role + skills for this level; merged downward by `ExecutionService`. */
121
+ prompt?: PromptPolicy;
58
122
  }
59
123
  /** Resumable state of a task-level execution. */
60
124
  export interface TaskExecutionState extends ExecutionState {
@@ -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.15",
3
+ "version": "0.1.16-rc.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/consts.ts CHANGED
@@ -59,3 +59,40 @@ export enum SpectatorContentType {
59
59
 
60
60
  /** Default spectator entry kind for consumers that do not classify their calls. */
61
61
  export const SPECTATOR_GENERAL = 'general'
62
+
63
+ /**
64
+ * Ordered sections of a composed system prompt.
65
+ *
66
+ * The ordering is not cosmetic — it IS the prompt-cache design. Every provider caches
67
+ * a prompt by exact PREFIX match, so the sections are laid out most-stable first and a
68
+ * cache breakpoint is placed at each stability boundary:
69
+ *
70
+ * - `Role` — the base system prompt defining who the model is. Stable per role.
71
+ * - `Skills` — the statically declared capabilities, rendered in a deterministic
72
+ * order. Stable per helper. A breakpoint closes `Role` + `Skills`.
73
+ * - `Packages` — capabilities resolved from whatever the request happens to mention.
74
+ * Varies per request, so it gets its OWN breakpoint and can never
75
+ * invalidate the two blocks above it.
76
+ * - `Context` — volatile, caller-supplied system text. Never cached.
77
+ */
78
+ export enum PromptBlock {
79
+ Role = 'role',
80
+ Skills = 'skills',
81
+ Packages = 'packages',
82
+ Context = 'context',
83
+ }
84
+
85
+ /**
86
+ * Emission order of {@link PromptBlock}. Declared explicitly rather than derived from
87
+ * the enum: the composed prompt must be byte-identical across processes and runtimes,
88
+ * and enum iteration order is not part of any contract worth betting a cache on.
89
+ */
90
+ export const PROMPT_BLOCK_ORDER: readonly PromptBlock[] = [
91
+ PromptBlock.Role,
92
+ PromptBlock.Skills,
93
+ PromptBlock.Packages,
94
+ PromptBlock.Context,
95
+ ] as const
96
+
97
+ /** Sort weight of a skill that declares none — see `SkillDefinition.order`. */
98
+ export const DEFAULT_SKILL_ORDER = 100
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The slice of a host application's file access that the LLM layer is allowed to see.
3
+ *
4
+ * A consumer almost always owns a much richer file helper (project metadata, source
5
+ * classification, remote/sandbox transports). This contract is deliberately the smallest
6
+ * useful subset, so a prompt plugin can read a package manifest or write a scratch file
7
+ * without the common layer learning anything about the consumer's project model. A
8
+ * consumer's own helper satisfies it structurally — declare
9
+ * `interface FileHelper extends LlmFileProvider` and nothing else changes.
10
+ *
11
+ * It lives in `llm-common` (not `llm`) because it is a contract, not a runtime: the
12
+ * package stays dependency-free and browser-safe.
13
+ *
14
+ * Every path is relative to the host's project root. Resolving that root is deliberately
15
+ * NOT part of the contract — a consumer with a multi-root layout types its own accessor
16
+ * with its own enum, and narrowing an inherited signature is exactly the kind of change
17
+ * that stops a rich helper from satisfying this one.
18
+ */
19
+ export interface LlmFileProvider {
20
+ /** Read a file relative to the root. With `noThrow`, a missing file yields `''`. */
21
+ readFile: (filePath: string, noThrow?: boolean) => Promise<string>
22
+
23
+ /** Glob for files relative to the root. */
24
+ getSourceList: (pattern?: string) => Promise<string[]>
25
+
26
+ /** Write a file relative to the root, creating parent directories as needed. */
27
+ writeFile: (filePath: string, content: string) => Promise<void>
28
+
29
+ /** Delete a file relative to the root. With `noThrow`, a missing file is a no-op. */
30
+ deleteFile: (filePath: string, noThrow?: boolean) => Promise<void>
31
+ }
32
+
33
+ /**
34
+ * A provider, or a resolver for one.
35
+ *
36
+ * Collaborators in this layer are usually late-bound functions so a service can be
37
+ * swapped or cloned — but a file helper is just as often a plain object a consumer
38
+ * already holds. Accepting both spares every call site a wrapper.
39
+ */
40
+ export type FileProviderRef = LlmFileProvider | (() => LlmFileProvider)
@@ -0,0 +1,6 @@
1
+ import type { FileProviderRef, LlmFileProvider } from './types.js'
2
+
3
+ /** Unwrap a {@link FileProviderRef} whichever form it arrived in. */
4
+ export const resolveFileProvider = (
5
+ ref: FileProviderRef | undefined,
6
+ ): LlmFileProvider | undefined => typeof ref === 'function' ? ref() : ref
package/src/index.ts CHANGED
@@ -2,3 +2,5 @@
2
2
  export * from './consts.js'
3
3
  export type * from './types.js'
4
4
  export type * from './spectator/types.js'
5
+ export type * from './files/types.js'
6
+ export * from './files/utils.js'
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ExecutionEffort, ExecutionLevel } from './consts.js'
1
+ import type { ExecutionEffort, ExecutionLevel, PromptBlock } from './consts.js'
2
2
 
3
3
  /**
4
4
  * Free-form observability metadata attached to every model call — forwarded to the
@@ -51,6 +51,72 @@ export interface ModelPolicy {
51
51
  modelOverrides?: Partial<Record<ModelRole, ModelConfigOverride>>
52
52
  }
53
53
 
54
+ /**
55
+ * Lifetime of a provider-side prompt cache entry. `'1h'` costs roughly twice as much to
56
+ * write as `'5m'`, so it only pays off from the third read onward — use it for a system
57
+ * prefix that survives a long run, not for a one-shot call.
58
+ */
59
+ export type CacheTtl = '5m' | '1h'
60
+
61
+ /**
62
+ * One named, reusable chunk of system-prompt knowledge — a capability the model is told
63
+ * it has. Registered once (by the package that owns the knowledge or by the final app)
64
+ * and referenced by `alias` from any execution level.
65
+ *
66
+ * `body` must be a PURE CONSTANT: no timestamps, no absolute paths, no interpolated
67
+ * request data. Every skill lands in the cached region of the system prompt, and one
68
+ * varying byte invalidates the whole prefix for every call that shares it.
69
+ */
70
+ export interface SkillDefinition {
71
+ /** Stable slug — how executions reference the skill. */
72
+ alias: string
73
+ /** Rendered as the skill's heading; falls back to `alias`. */
74
+ title?: string
75
+ /** Not sent to the model — documentation for whoever wires the registry. */
76
+ description?: string
77
+ /** The prompt text itself. */
78
+ body: string
79
+ /** Sort weight; ties broken by `alias`. Defaults to `DEFAULT_SKILL_ORDER`. */
80
+ order?: number
81
+ /** Which block to render into. Defaults to `PromptBlock.Skills`. */
82
+ block?: PromptBlock
83
+ /** Aliases pulled in transitively when this skill is enabled. */
84
+ requires?: string[]
85
+ }
86
+
87
+ /**
88
+ * The "flexible execution parameters" that shape a system prompt. Carried on
89
+ * {@link ExecutionState}, so it is JSON-safe, survives a checkpoint/restore round trip,
90
+ * and accumulates down the execution chain: a task adds skills on top of the project,
91
+ * a helper on top of the task. `role` is overridden by the deepest level that sets it;
92
+ * `skills` are unioned.
93
+ */
94
+ export interface PromptPolicy {
95
+ /** Base system prompt — becomes the first block. */
96
+ role?: string
97
+ /** Skill aliases enabled at this level. */
98
+ skills?: string[]
99
+ /** Mark the composed system prompt cacheable. Defaults to `true`. */
100
+ cacheSystem?: boolean
101
+ /** Cache lifetime for the system prefix. Defaults to `'5m'`. */
102
+ cacheTtl?: CacheTtl
103
+ }
104
+
105
+ /**
106
+ * Prompt-cache accounting for a single call, normalized across providers. The only
107
+ * reliable way to tell whether caching actually works: if `read` stays 0 across repeated
108
+ * calls with the same prefix, something is silently invalidating it.
109
+ */
110
+ export interface CacheUsage {
111
+ /** Tokens served from cache (~0.1x price). */
112
+ read: number
113
+ /** Tokens written to cache (~1.25x price at 5m TTL, ~2x at 1h). */
114
+ creation: number
115
+ /** Tokens processed at full price. */
116
+ input: number
117
+ output: number
118
+ }
119
+
54
120
  /**
55
121
  * Serializable execution state — no functions, no file access, no model instances.
56
122
  * The runtime `Execution` (`@owlmeans/llm`) = this state + attached collaborators.
@@ -61,6 +127,8 @@ export interface ExecutionState {
61
127
  level: ExecutionLevel
62
128
  purpose: LlmPurpose
63
129
  policy: ModelPolicy
130
+ /** Role + skills for this level; merged downward by `ExecutionService`. */
131
+ prompt?: PromptPolicy
64
132
  }
65
133
 
66
134
  /** Resumable state of a task-level execution. */