@vincemakes/kiso-runtime 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,96 @@
1
+ /**
2
+ * E3 (0.2.1) — the rent ledger: every request's static model-side rent,
3
+ * one line per surface.
4
+ *
5
+ * The static rent is the surface the model pays REGARDLESS of the turn's
6
+ * content: the base system prompt, each extension's append, every tool's
7
+ * serialized spec, and the per-request envelope. One line per surface,
8
+ * four classes, measured in chars + the rounds' est-token convention
9
+ * (chars/4, ceil — the E1 script's formula, the work order's own words,
10
+ * R6):
11
+ *
12
+ * - system:base the session's own prompt as the CLI handed it
13
+ * (built-in constant + project instructions — the
14
+ * runtime cannot split those, R3). The runtime's
15
+ * generated tool table is machinery BETWEEN base and
16
+ * appends; it stays out of the ledger (counts live
17
+ * in tool:<name> lines and the base's own line).
18
+ * - system:ext:<name> one line per extension with a non-empty
19
+ * systemPrompt.append, measured on the append
20
+ * string, in load order.
21
+ * - tool:<name> one line per tool, measured on the exact
22
+ * serialized ToolSpec projection the adapters
23
+ * receive ({name, description, inputSchema} — the
24
+ * registry.toSpecs() shape, protocol/messages.ts).
25
+ * - envelope the per-request fixed overhead OUTSIDE the
26
+ * conversation payloads: the R5 skeleton
27
+ * JSON.stringify({model, messages: [], tools: []})
28
+ * — a function of the model string only, never of
29
+ * the payloads (the skeleton is the definition).
30
+ *
31
+ * R9: an absent surface is an absent line — an unconfigured mcp, a
32
+ * session with no project instructions: no line. The absence IS the
33
+ * ledger statement (the 0.1.45 diet-A precedent: not paid = no rent).
34
+ *
35
+ * Determinism (the reviewer-facing property): every line is derivable
36
+ * from components the reviewer can recompute — the exported prompt
37
+ * constant, the appends, the ToolSpec array, the request skeleton. The
38
+ * ledger stores COUNTS, never payloads (the seqRange thin-pointer
39
+ * discipline applied to rent).
40
+ *
41
+ * buildRentLedger is the SINGLE source: the R7 star gate drives a real
42
+ * session with the script's predicted composition and asserts the
43
+ * recorded ledger equals the prediction line for line.
44
+ */
45
+ /** The closed line set (the same gate discipline as the record fields). */
46
+ export const RENT_LINE_FIELDS = ["surface", "chars", "estTokens"];
47
+ const line = (surface, text) => ({
48
+ surface,
49
+ chars: text.length,
50
+ estTokens: Math.ceil(text.length / 4),
51
+ });
52
+ /** The one ledger: system:base, then system:ext:* (load order), then
53
+ * tool:* (the array's order — the registry's toSpecs() order), then the
54
+ * envelope. Absent surfaces contribute no lines (R9). */
55
+ export function buildRentLedger(input) {
56
+ const lines = [];
57
+ if (input.base !== undefined)
58
+ lines.push(line("system:base", input.base));
59
+ for (const append of input.appends ?? [])
60
+ lines.push(line(`system:ext:${append.name}`, append.text));
61
+ for (const tool of input.tools ?? []) {
62
+ lines.push(line(`tool:${tool.name}`, JSON.stringify({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema })));
63
+ }
64
+ // R5: the envelope is the request skeleton — a model-string function,
65
+ // never the payloads; the empty arrays are literal (the definition).
66
+ lines.push(line("envelope", JSON.stringify({ model: input.model, messages: [], tools: [] })));
67
+ return lines;
68
+ }
69
+ /** The line validator — the same strict discipline as the record's other
70
+ * closed sets: no key outside the spec, every spec'd key present,
71
+ * non-empty surface (R9: a line exists only for a surface that exists),
72
+ * non-negative integer chars, and the estTokens cross-check (R6). The
73
+ * schema pins the LINE, not the multiset — duplicate surfaces are the
74
+ * writer's business, never a schema crash. */
75
+ export function validateRentLine(v) {
76
+ if (typeof v !== "object" || v === null || Array.isArray(v))
77
+ return false;
78
+ const o = v;
79
+ const keys = Object.keys(o);
80
+ const fields = RENT_LINE_FIELDS;
81
+ if (keys.some((k) => !fields.includes(k)))
82
+ return false;
83
+ if (!fields.every((k) => k in o))
84
+ return false;
85
+ if (typeof o.surface !== "string" || o.surface.length === 0)
86
+ return false;
87
+ const chars = o.chars;
88
+ const estTokens = o.estTokens;
89
+ if (typeof chars !== "number" || !Number.isInteger(chars) || chars < 0)
90
+ return false;
91
+ if (typeof estTokens !== "number" || !Number.isInteger(estTokens) || estTokens < 0)
92
+ return false;
93
+ if (estTokens !== Math.ceil(chars / 4))
94
+ return false;
95
+ return true;
96
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-runtime",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "kiso runtime — durable multi-turn agent sessions: AgentDefinition, AgentRuntime, AgentSession, Run, append-only JSONL store.",
5
5
  "type": "module",
6
6
  "license": "MIT",