@vincemakes/kiso-runtime 0.41.2 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +6 -0
- package/dist/agent.js +1 -0
- package/dist/compose.d.ts +19 -2
- package/dist/compose.js +31 -6
- package/dist/run.js +24 -9
- package/dist/session.d.ts +4 -1
- package/dist/session.js +3 -2
- package/package.json +6 -6
package/dist/agent.d.ts
CHANGED
|
@@ -89,6 +89,12 @@ export interface AgentDefinition {
|
|
|
89
89
|
readonly tool: string;
|
|
90
90
|
readonly line: string;
|
|
91
91
|
}>;
|
|
92
|
+
/** 0.42.0: "off" withholds the generated "Tool use:" block entirely —
|
|
93
|
+
* no fixed directives, no snippets, no guidelines — so the system
|
|
94
|
+
* prompt is exactly the configured text (a host matching another
|
|
95
|
+
* system byte for byte). The tool schemas still ride the request.
|
|
96
|
+
* Default "on". Type-only additive; never part of the profile digest. */
|
|
97
|
+
readonly toolTable?: "on" | "off";
|
|
92
98
|
/** E1: loaded extensions — their tools merge into the registry (a name
|
|
93
99
|
* collision with a built-in is a loud startup error), their hooks
|
|
94
100
|
* compose after the agent's own (the existing come first), their approvals join the
|
package/dist/agent.js
CHANGED
|
@@ -178,6 +178,7 @@ export class AgentRuntime {
|
|
|
178
178
|
...(this.#definition.maxRetries !== undefined ? { maxRetries: this.#definition.maxRetries } : {}),
|
|
179
179
|
...(this.#definition.streamIdleMs !== undefined ? { streamIdleMs: this.#definition.streamIdleMs } : {}),
|
|
180
180
|
...(this.#definition.toolRules !== undefined ? { toolRules: this.#definition.toolRules } : {}),
|
|
181
|
+
...(this.#definition.toolTable !== undefined ? { toolTable: this.#definition.toolTable } : {}),
|
|
181
182
|
...(this.#definition.extensions !== undefined ? { extensions: this.#definition.extensions } : {}),
|
|
182
183
|
};
|
|
183
184
|
// 0.40.0: the last bill's time rides the RECORD, not the event.
|
package/dist/compose.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* from session.ts: the extension system-prompt appends, the extension
|
|
4
4
|
* hook composition (the existing come first), and the loop's microcompact config lookup.
|
|
5
5
|
*/
|
|
6
|
-
import type { ApprovalChain, Event, HookHost, KisoExtension, ToolRegistry } from "@vincemakes/kiso-core";
|
|
6
|
+
import type { Adapter, ApprovalChain, Event, HookHost, KisoExtension, ToolRegistry } from "@vincemakes/kiso-core";
|
|
7
7
|
import type { SessionConfig } from "./session.js";
|
|
8
8
|
/**
|
|
9
9
|
* 0.1.40 (R-C item 1) — the tool substitution table: vocabulary rows, each
|
|
@@ -29,7 +29,12 @@ export type ToolRules = ReadonlyArray<{
|
|
|
29
29
|
* then the tool table (generated machinery sits BETWEEN the base and the
|
|
30
30
|
* extension appends). One function, so an in-band summary outside a run
|
|
31
31
|
* (ADR-0055 A2, /compact) sends the exact prefix a run sends. */
|
|
32
|
-
|
|
32
|
+
/** 0.42.0: `"off"` leaves the base prompt exactly as configured — no
|
|
33
|
+
* "Tool use:" block, no snippets, no guidelines — for a host whose prompt
|
|
34
|
+
* must match another system's byte for byte. The tool SCHEMAS still ride
|
|
35
|
+
* the request; only the generated prose is withheld. */
|
|
36
|
+
export type ToolTableMode = "on" | "off";
|
|
37
|
+
export declare function runBasePrompt(systemPrompt: string | undefined, registry: ToolRegistry, rules?: ToolRules, table?: ToolTableMode): string | undefined;
|
|
33
38
|
/** The table, or "" when the registry is empty (no vocabulary, no tools). */
|
|
34
39
|
export declare function composeToolTable(registry: ToolRegistry, rules?: ToolRules): string;
|
|
35
40
|
/**
|
|
@@ -37,7 +42,19 @@ export declare function composeToolTable(registry: ToolRegistry, rules?: ToolRul
|
|
|
37
42
|
* order, \n\n-joined — deterministic (same extension list → same prompt).
|
|
38
43
|
* No appends → the base passes through byte-identical.
|
|
39
44
|
*/
|
|
45
|
+
/** An extension's append as text: a string as is, a function evaluated
|
|
46
|
+
* NOW (0.42.0 — the per-run seam; call this once per composition). */
|
|
47
|
+
export declare function appendOf(extension: KisoExtension): string | undefined;
|
|
40
48
|
export declare function composeSystemPrompt(base: string | undefined, extensions: readonly KisoExtension[]): string | undefined;
|
|
49
|
+
/** The base and the append texts, \n\n-joined; no appends → the base as is. */
|
|
50
|
+
export declare function joinPrompt(base: string | undefined, appends: readonly string[]): string | undefined;
|
|
51
|
+
/** 0.42.0: the OUTERMOST adapter layer — `compose` runs exactly once per
|
|
52
|
+
* provider attempt (a retry is a new attempt) and its result is the
|
|
53
|
+
* request's system prompt as every inner layer, the tracer first, sees
|
|
54
|
+
* it: what the trace records is what the model was sent, by construction.
|
|
55
|
+
* Never a getter on the config — the kernel and the tracer each read
|
|
56
|
+
* their field twice, and an observer must not run the product's code. */
|
|
57
|
+
export declare function promptPerAttempt(adapter: Adapter, compose: () => string | undefined): Adapter;
|
|
41
58
|
/**
|
|
42
59
|
* E1: extension hooks compose AFTER the agent's own (the existing come first — the existing
|
|
43
60
|
* hook sees every event first). Observers all run, in order; onUserMessage
|
package/dist/compose.js
CHANGED
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
* from session.ts: the extension system-prompt appends, the extension
|
|
4
4
|
* hook composition (the existing come first), and the loop's microcompact config lookup.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* (ADR-0055 A2, /compact) sends the exact prefix a run sends. */
|
|
10
|
-
export function runBasePrompt(systemPrompt, registry, rules = []) {
|
|
6
|
+
export function runBasePrompt(systemPrompt, registry, rules = [], table = "on") {
|
|
7
|
+
if (table === "off")
|
|
8
|
+
return systemPrompt;
|
|
11
9
|
const toolTable = composeToolTable(registry, rules);
|
|
12
10
|
return toolTable === "" ? systemPrompt : systemPrompt === undefined ? toolTable : `${systemPrompt}\n\n${toolTable}`;
|
|
13
11
|
}
|
|
@@ -37,12 +35,39 @@ export function composeToolTable(registry, rules = []) {
|
|
|
37
35
|
* order, \n\n-joined — deterministic (same extension list → same prompt).
|
|
38
36
|
* No appends → the base passes through byte-identical.
|
|
39
37
|
*/
|
|
38
|
+
/** An extension's append as text: a string as is, a function evaluated
|
|
39
|
+
* NOW (0.42.0 — the per-run seam; call this once per composition). */
|
|
40
|
+
export function appendOf(extension) {
|
|
41
|
+
const append = extension.systemPrompt?.append;
|
|
42
|
+
return typeof append === "function" ? append() : append;
|
|
43
|
+
}
|
|
40
44
|
export function composeSystemPrompt(base, extensions) {
|
|
41
|
-
|
|
45
|
+
return joinPrompt(base, extensions.flatMap((e) => {
|
|
46
|
+
const text = appendOf(e);
|
|
47
|
+
return text === undefined ? [] : [text];
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
/** The base and the append texts, \n\n-joined; no appends → the base as is. */
|
|
51
|
+
export function joinPrompt(base, appends) {
|
|
42
52
|
if (appends.length === 0)
|
|
43
53
|
return base;
|
|
44
54
|
return base === undefined ? appends.join("\n\n") : `${base}\n\n${appends.join("\n\n")}`;
|
|
45
55
|
}
|
|
56
|
+
/** 0.42.0: the OUTERMOST adapter layer — `compose` runs exactly once per
|
|
57
|
+
* provider attempt (a retry is a new attempt) and its result is the
|
|
58
|
+
* request's system prompt as every inner layer, the tracer first, sees
|
|
59
|
+
* it: what the trace records is what the model was sent, by construction.
|
|
60
|
+
* Never a getter on the config — the kernel and the tracer each read
|
|
61
|
+
* their field twice, and an observer must not run the product's code. */
|
|
62
|
+
export function promptPerAttempt(adapter, compose) {
|
|
63
|
+
return {
|
|
64
|
+
stream: (options) => {
|
|
65
|
+
const systemPrompt = compose();
|
|
66
|
+
const { systemPrompt: _fixed, ...rest } = options;
|
|
67
|
+
return adapter.stream(systemPrompt === undefined ? rest : { ...rest, systemPrompt });
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
46
71
|
/**
|
|
47
72
|
* E1: extension hooks compose AFTER the agent's own (the existing come first — the existing
|
|
48
73
|
* hook sees every event first). Observers all run, in order; onUserMessage
|
package/dist/run.js
CHANGED
|
@@ -7,7 +7,7 @@ import { denialResult, loop } from "@vincemakes/kiso-core";
|
|
|
7
7
|
import { ABORTED, MergedSignal, abortable, openRunId } from "./recovery.js";
|
|
8
8
|
import { resolveReasoning } from "./provider/metadata.js";
|
|
9
9
|
import { deriveRecoveryPlan, invocationSeqOf } from "./recovery-plan.js";
|
|
10
|
-
import { composeApprovalChain,
|
|
10
|
+
import { appendOf, composeApprovalChain, joinPrompt, promptPerAttempt, runBasePrompt } from "./compose.js";
|
|
11
11
|
import { truncationGuard } from "./truncation-guard.js";
|
|
12
12
|
import { overflowBelt } from "./overflow-belt.js";
|
|
13
13
|
import { DEFAULT_STREAM_IDLE_MS, idleGuard } from "./idle-guard.js";
|
|
@@ -88,16 +88,33 @@ export class Run {
|
|
|
88
88
|
// session's base prompt and the extension appends: generated
|
|
89
89
|
// machinery never outranks the deliberate extension text (the E2
|
|
90
90
|
// "append lands at the END" contract holds). "" when empty.
|
|
91
|
-
const basePrompt = runBasePrompt(this.#config.systemPrompt, this.#config.registry, this.#config.toolRules ?? []);
|
|
91
|
+
const basePrompt = runBasePrompt(this.#config.systemPrompt, this.#config.registry, this.#config.toolRules ?? [], this.#config.toolTable ?? "on");
|
|
92
92
|
// E3 — the ledger's parts: the base as CONFIGURED (what the CLI
|
|
93
93
|
// handed the runtime — the tool table is generated machinery, R3)
|
|
94
94
|
// and the extension appends in load order (R4 attribution). The
|
|
95
95
|
// composed string below is their result; the ledger counts the
|
|
96
96
|
// parts, observation-only. exactOptionalPropertyTypes: an absent
|
|
97
97
|
// surface is an absent key — never an explicit undefined (R9).
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
// 0.42.0 (the products' request #11): an extension's append is
|
|
99
|
+
// evaluated ONCE PER PROVIDER ATTEMPT, never during a tool — by
|
|
100
|
+
// `snapshot`, which the outermost adapter layer (promptPerAttempt,
|
|
101
|
+
// in loopConfig) calls as it builds each attempt's request. The
|
|
102
|
+
// one evaluation composes the request's prompt from the fixed
|
|
103
|
+
// base AND fills the rent ledger's `appends`: the tracer, inside
|
|
104
|
+
// that layer, records the bytes the model was sent. The in-band
|
|
105
|
+
// summary reads the last attempt's snapshot (the prefix the run
|
|
106
|
+
// last sent) or takes one if no attempt has happened yet.
|
|
107
|
+
const rentParts = { ...(this.#config.systemPrompt !== undefined ? { base: this.#config.systemPrompt } : {}), appends: [] };
|
|
108
|
+
let lastPrompt;
|
|
109
|
+
let taken = false;
|
|
110
|
+
const snapshot = () => {
|
|
111
|
+
const appends = (this.#config.extensions ?? []).flatMap((e) => {
|
|
112
|
+
const text = appendOf(e);
|
|
113
|
+
return text === undefined ? [] : [{ name: e.name, text }];
|
|
114
|
+
});
|
|
115
|
+
rentParts.appends = appends;
|
|
116
|
+
taken = true;
|
|
117
|
+
return (lastPrompt = joinPrompt(basePrompt, appends.map((a) => a.text)));
|
|
101
118
|
};
|
|
102
119
|
// E1 (1.2.0): the request tracer — the observation ledger. It
|
|
103
120
|
// sits at the adapter boundary; the model-visible byte stream is
|
|
@@ -124,7 +141,6 @@ export class Run {
|
|
|
124
141
|
// E2: the session's own systemPrompt first, then every extension
|
|
125
142
|
// append in LOAD order — deterministic (same extensions → same
|
|
126
143
|
// prompt); no appends → byte-identical to the extension-less run.
|
|
127
|
-
const systemPrompt = composeSystemPrompt(basePrompt, this.#config.extensions ?? []);
|
|
128
144
|
const approvalChain = composeApprovalChain(this.#config.extensions ?? []);
|
|
129
145
|
// ADR-0055 Amendment 1 (A1b): the compaction point the kernel asks
|
|
130
146
|
// before every request — the run's own prefix, so an in-band
|
|
@@ -139,7 +155,7 @@ export class Run {
|
|
|
139
155
|
wireReasoning = undefined;
|
|
140
156
|
}
|
|
141
157
|
const compact = this.#session.compactionPoint({
|
|
142
|
-
|
|
158
|
+
systemPrompt: () => (taken ? lastPrompt : snapshot()),
|
|
143
159
|
tools: () => this.#config.registry.snapshot().specs,
|
|
144
160
|
...(wireReasoning !== undefined ? { reasoning: wireReasoning } : {}),
|
|
145
161
|
signal,
|
|
@@ -154,10 +170,9 @@ export class Run {
|
|
|
154
170
|
// ADR-0055 Amendment 2 (decision 3): the overflow belt sits outside
|
|
155
171
|
// the guards, so a stall or a cut on a request known not to fit is
|
|
156
172
|
// classified as the overflow it is, and the tracer records that.
|
|
157
|
-
adapter: traceGuard(tracer, overflowBelt(truncationGuard(idleGuard(this.#adapter, this.#config.streamIdleMs ?? DEFAULT_STREAM_IDLE_MS)), () => this.#session.overflowMeasure())), // tracer assigned above, before loopConfig
|
|
173
|
+
adapter: promptPerAttempt(traceGuard(tracer, overflowBelt(truncationGuard(idleGuard(this.#adapter, this.#config.streamIdleMs ?? DEFAULT_STREAM_IDLE_MS)), () => this.#session.overflowMeasure())), snapshot), // tracer assigned above, before loopConfig
|
|
158
174
|
model: this.#config.model,
|
|
159
175
|
sessionId: this.#session.id, // P3: tools see their session (ToolContext.sessionId)
|
|
160
|
-
...(systemPrompt !== undefined ? { systemPrompt } : {}),
|
|
161
176
|
registry: this.#config.registry,
|
|
162
177
|
...(this.#config.hooks !== undefined ? { hooks: this.#config.hooks } : {}),
|
|
163
178
|
...(this.#config.maxTurns !== undefined ? { maxTurns: this.#config.maxTurns } : {}),
|
package/dist/session.d.ts
CHANGED
|
@@ -147,7 +147,8 @@ export declare class AgentSession {
|
|
|
147
147
|
* standing prune here, for SDK callers — the kernel no longer has one.
|
|
148
148
|
*/
|
|
149
149
|
compactionPoint(run: {
|
|
150
|
-
|
|
150
|
+
/** 0.42.0: a thunk — evaluated ONCE per in-band summary (the run's per-attempt snapshot). */
|
|
151
|
+
readonly systemPrompt?: string | (() => string | undefined);
|
|
151
152
|
readonly tools: () => readonly ToolSpec[];
|
|
152
153
|
readonly reasoning?: {
|
|
153
154
|
readonly thinking?: "adaptive" | "enabled" | "disabled";
|
|
@@ -559,6 +560,8 @@ export interface SessionConfig {
|
|
|
559
560
|
readonly tool: string;
|
|
560
561
|
readonly line: string;
|
|
561
562
|
}>;
|
|
563
|
+
/** 0.42.0: "off" withholds the generated tool table entirely (see AgentDefinition). */
|
|
564
|
+
readonly toolTable?: "on" | "off";
|
|
562
565
|
/**
|
|
563
566
|
* E1: loaded extensions — their tools join the registry (idempotently;
|
|
564
567
|
* a collision with a built-in name was already rejected at agent
|
package/dist/session.js
CHANGED
|
@@ -394,12 +394,13 @@ export class AgentSession {
|
|
|
394
394
|
const boundary = checkpointBoundarySeq(events, { keepTokens: tail });
|
|
395
395
|
if (boundary === undefined)
|
|
396
396
|
return null;
|
|
397
|
+
const summaryPrompt = typeof run.systemPrompt === "function" ? run.systemPrompt() : run.systemPrompt;
|
|
397
398
|
let path;
|
|
398
399
|
let result;
|
|
399
400
|
try {
|
|
400
401
|
({ result, path } = await this.#checkpointCall({
|
|
401
402
|
messages,
|
|
402
|
-
inBand: { ...(
|
|
403
|
+
inBand: { ...(summaryPrompt !== undefined ? { systemPrompt: summaryPrompt } : {}), tools: run.tools() },
|
|
403
404
|
...(run.reasoning !== undefined ? { reasoning: run.reasoning } : {}),
|
|
404
405
|
serialized: () => serializeCovered({ events, prevPoint: lastSummaryPoint(events), boundary }),
|
|
405
406
|
serializedReasoning: true,
|
|
@@ -842,7 +843,7 @@ export class AgentSession {
|
|
|
842
843
|
// the one fallback. The budget is unchanged: measured for the
|
|
843
844
|
// manual gesture, fixed for the policy (0.39.2).
|
|
844
845
|
const cfg = this.#effectiveConfig();
|
|
845
|
-
const systemPrompt = composeSystemPrompt(runBasePrompt(cfg.systemPrompt, cfg.registry, cfg.toolRules ?? []), cfg.extensions ?? []);
|
|
846
|
+
const systemPrompt = composeSystemPrompt(runBasePrompt(cfg.systemPrompt, cfg.registry, cfg.toolRules ?? [], cfg.toolTable ?? "on"), cfg.extensions ?? []);
|
|
846
847
|
const wire = cfg.reasoning === undefined ? undefined : resolveReasoning(binding.model, cfg.reasoning, binding.baseUrl);
|
|
847
848
|
const { result: call, path } = await this.#checkpointCall({
|
|
848
849
|
messages: this.projected(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"description": "kiso runtime \u2014 durable multi-turn agent sessions: AgentDefinition, AgentRuntime, AgentSession, Run, append-only JSONL store.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"test": "vitest run"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@vincemakes/kiso-core": "0.
|
|
28
|
+
"@vincemakes/kiso-core": "0.42.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@vincemakes/kiso-provider-anthropic": "0.
|
|
32
|
-
"@vincemakes/kiso-provider-openai": "0.
|
|
33
|
-
"@vincemakes/kiso-provider-openai-responses": "0.
|
|
31
|
+
"@vincemakes/kiso-provider-anthropic": "0.42.0",
|
|
32
|
+
"@vincemakes/kiso-provider-openai": "0.42.0",
|
|
33
|
+
"@vincemakes/kiso-provider-openai-responses": "0.42.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependenciesMeta": {
|
|
36
36
|
"@vincemakes/kiso-provider-anthropic": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@vincemakes/kiso-evals": "0.
|
|
47
|
+
"@vincemakes/kiso-evals": "0.42.0",
|
|
48
48
|
"@types/node": "^26.1.2",
|
|
49
49
|
"typescript": "^5.7.2",
|
|
50
50
|
"vitest": "^3.0.0"
|