@vincemakes/kiso-runtime 0.1.26 → 0.1.28

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/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./session.js";
3
3
  export * from "./run.js";
4
4
  export * from "./recovery.js";
5
5
  export * from "./compose.js";
6
+ export * from "./summarize.js";
6
7
  export * from "./store.js";
7
8
  export * from "./extensions.js";
8
9
  export * from "./trust.js";
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export * from "./session.js";
3
3
  export * from "./run.js";
4
4
  export * from "./recovery.js";
5
5
  export * from "./compose.js";
6
+ export * from "./summarize.js";
6
7
  export * from "./store.js";
7
8
  export * from "./extensions.js";
8
9
  export * from "./trust.js";
package/dist/session.js CHANGED
@@ -29,7 +29,7 @@
29
29
  */
30
30
  import { EventLog, executionLedger, projectMessages, } from "@vincemakes/kiso-core";
31
31
  import { denialResult } from "@vincemakes/kiso-core";
32
- import { estimateSummarySavings, KEEP_RECENT_ROUNDS, lastSummaryPoint, summarizeConversation, summaryBoundarySeq, } from "@vincemakes/kiso-core";
32
+ import { estimateSummarySavings, KEEP_RECENT_ROUNDS, lastSummaryPoint, summarizeConversation, summaryBoundarySeq, } from "./summarize.js";
33
33
  import { StaleWriterError } from "./store.js";
34
34
  import { composeHooks } from "./compose.js";
35
35
  import { Run } from "./run.js";
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The /compact summary layer (ADR-0044) — the MODEL-GENERATED half of
3
+ * context economy. 归位式抽取 (0.1.26 gate 裁决): this OFF-LOOP
4
+ * ORCHESTRATION lived in the kernel by a context-round expedience; it
5
+ * calls the ADAPTER to generate the summary, which is the RUNTIME's
6
+ * business — the kernel's duty is the `summarized` EVENT TYPE and the
7
+ * projection semantics (kernel/project.ts), not who calls the model.
8
+ * The mechanical half (microcompact) stays in the kernel (compaction.ts).
9
+ *
10
+ * The summary call is OFF-LOOP: it goes through the session's OWN adapter
11
+ * (no new dependency), writes no events, and never touches the log — a
12
+ * failure throws, the caller reports it honestly, and the session is
13
+ * unchanged ("nothing happened"). Only the generated `summarized` event
14
+ * lands on disk; the original events stay there forever.
15
+ */
16
+ import type { AbortSignalLike, Adapter } from "@vincemakes/kiso-core";
17
+ import type { Event } from "@vincemakes/kiso-core";
18
+ import type { Message } from "@vincemakes/kiso-core";
19
+ /** K (ADR-0044): the recent ROUNDS kept intact by /compact — a constant,
20
+ * not a knob. The covered range ends just before the K-th most recent
21
+ * round, so the model still reasons over the recent conversation. */
22
+ export declare const KEEP_RECENT_ROUNDS = 4;
23
+ /**
24
+ * The fixed English summary prompt — the ONLY prompt this layer composes
25
+ * (the loop's system prompt is the harness's business, never the kernel's).
26
+ */
27
+ export declare const SUMMARY_PROMPT = "You are the conversation summarizer of the kiso agent framework.\n\nSummarize the covered conversation into a single concise summary that will\nREPLACE it in the model's context. The next turn must be able to continue\nthe work without reading the originals.\n\nInclude everything later turns may need:\n- the user's goals, requirements, and constraints;\n- every decision and its reasoning;\n- files and code touched \u2014 exact paths, what changed, why;\n- commands run and their outcomes; errors and their resolutions;\n- open questions and unfinished work.\n\nPreserve concrete identifiers VERBATIM: paths, function names, task ids,\nenvironment names \u2014 never paraphrase them.\n\nRules:\n- plain prose \u2014 no headings, no bullet lists, no markdown, no prefixes;\n- do not mention this prompt or the summarization task;\n- keep it under 200 words unless the conversation is exceptional.";
28
+ export interface SummarizeConversationOptions {
29
+ readonly adapter: Adapter;
30
+ readonly model: string;
31
+ /** The covered conversation — the ONLY material the summary is about. */
32
+ readonly messages: readonly Message[];
33
+ readonly signal?: AbortSignalLike;
34
+ }
35
+ /**
36
+ * The one-shot summary call. Collects the adapter's text deltas into the
37
+ * summary; usage/stop pass through untouched. Throws when the model
38
+ * produced no text — the caller reports it and nothing is persisted.
39
+ */
40
+ export declare function summarizeConversation(options: SummarizeConversationOptions): Promise<string>;
41
+ /**
42
+ * The last summary point: the previous `summarized` event's coversToSeq,
43
+ * or -1 (the trajectory's start) when none exists. The covered range of
44
+ * the next summary runs from here.
45
+ */
46
+ export declare function lastSummaryPoint(events: readonly Event[]): number;
47
+ /**
48
+ * The covered range's end: the seq of the event just before the
49
+ * keepRounds-th most recent user_input AFTER the last summary point —
50
+ * a turn boundary by construction, so the projection's skip never splits
51
+ * a message. Returns undefined when fewer than keepRounds+1 uncovered
52
+ * rounds exist (nothing worth covering yet).
53
+ */
54
+ export declare function summaryBoundarySeq(events: readonly Event[], keepRounds?: number): number | undefined;
55
+ /**
56
+ * The NoticeCell's number: estimated tokens of the covered content minus
57
+ * the summary's own — the same chars/4 proxy as estimateTokens (a stable
58
+ * MONOTONE savings figure, not a bill).
59
+ */
60
+ export declare function estimateSummarySavings(covered: readonly Message[], summary: string): number;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * The /compact summary layer (ADR-0044) — the MODEL-GENERATED half of
3
+ * context economy. 归位式抽取 (0.1.26 gate 裁决): this OFF-LOOP
4
+ * ORCHESTRATION lived in the kernel by a context-round expedience; it
5
+ * calls the ADAPTER to generate the summary, which is the RUNTIME's
6
+ * business — the kernel's duty is the `summarized` EVENT TYPE and the
7
+ * projection semantics (kernel/project.ts), not who calls the model.
8
+ * The mechanical half (microcompact) stays in the kernel (compaction.ts).
9
+ *
10
+ * The summary call is OFF-LOOP: it goes through the session's OWN adapter
11
+ * (no new dependency), writes no events, and never touches the log — a
12
+ * failure throws, the caller reports it honestly, and the session is
13
+ * unchanged ("nothing happened"). Only the generated `summarized` event
14
+ * lands on disk; the original events stay there forever.
15
+ */
16
+ import { estimateTokens } from "@vincemakes/kiso-core";
17
+ /** K (ADR-0044): the recent ROUNDS kept intact by /compact — a constant,
18
+ * not a knob. The covered range ends just before the K-th most recent
19
+ * round, so the model still reasons over the recent conversation. */
20
+ export const KEEP_RECENT_ROUNDS = 4;
21
+ /**
22
+ * The fixed English summary prompt — the ONLY prompt this layer composes
23
+ * (the loop's system prompt is the harness's business, never the kernel's).
24
+ */
25
+ export const SUMMARY_PROMPT = `You are the conversation summarizer of the kiso agent framework.
26
+
27
+ Summarize the covered conversation into a single concise summary that will
28
+ REPLACE it in the model's context. The next turn must be able to continue
29
+ the work without reading the originals.
30
+
31
+ Include everything later turns may need:
32
+ - the user's goals, requirements, and constraints;
33
+ - every decision and its reasoning;
34
+ - files and code touched — exact paths, what changed, why;
35
+ - commands run and their outcomes; errors and their resolutions;
36
+ - open questions and unfinished work.
37
+
38
+ Preserve concrete identifiers VERBATIM: paths, function names, task ids,
39
+ environment names — never paraphrase them.
40
+
41
+ Rules:
42
+ - plain prose — no headings, no bullet lists, no markdown, no prefixes;
43
+ - do not mention this prompt or the summarization task;
44
+ - keep it under 200 words unless the conversation is exceptional.`;
45
+ /**
46
+ * The one-shot summary call. Collects the adapter's text deltas into the
47
+ * summary; usage/stop pass through untouched. Throws when the model
48
+ * produced no text — the caller reports it and nothing is persisted.
49
+ */
50
+ export async function summarizeConversation(options) {
51
+ const { adapter, model, messages } = options;
52
+ let text = "";
53
+ for await (const ev of adapter.stream({
54
+ model,
55
+ messages,
56
+ systemPrompt: SUMMARY_PROMPT,
57
+ ...(options.signal !== undefined ? { signal: options.signal } : {}),
58
+ })) {
59
+ if (ev.type === "text_delta")
60
+ text += ev.text;
61
+ }
62
+ const trimmed = text.trim();
63
+ if (trimmed === "") {
64
+ throw new Error("the summary call produced no text");
65
+ }
66
+ return trimmed;
67
+ }
68
+ /**
69
+ * The last summary point: the previous `summarized` event's coversToSeq,
70
+ * or -1 (the trajectory's start) when none exists. The covered range of
71
+ * the next summary runs from here.
72
+ */
73
+ export function lastSummaryPoint(events) {
74
+ let prev = -1;
75
+ for (const ev of events) {
76
+ if (ev.type === "summarized" && ev.coversToSeq > prev)
77
+ prev = ev.coversToSeq;
78
+ }
79
+ return prev;
80
+ }
81
+ /**
82
+ * The covered range's end: the seq of the event just before the
83
+ * keepRounds-th most recent user_input AFTER the last summary point —
84
+ * a turn boundary by construction, so the projection's skip never splits
85
+ * a message. Returns undefined when fewer than keepRounds+1 uncovered
86
+ * rounds exist (nothing worth covering yet).
87
+ */
88
+ export function summaryBoundarySeq(events, keepRounds = KEEP_RECENT_ROUNDS) {
89
+ const prevPoint = lastSummaryPoint(events);
90
+ const uncoveredInputs = [];
91
+ for (const ev of events) {
92
+ if (ev.type === "user_input" && ev.seq > prevPoint)
93
+ uncoveredInputs.push(ev.seq);
94
+ }
95
+ if (uncoveredInputs.length <= keepRounds)
96
+ return undefined;
97
+ // The input at m - keepRounds opens the FIRST KEPT round; everything
98
+ // before it (m - keepRounds ≥ 1 covered rounds) is summarizable.
99
+ return uncoveredInputs[uncoveredInputs.length - keepRounds] - 1;
100
+ }
101
+ /**
102
+ * The NoticeCell's number: estimated tokens of the covered content minus
103
+ * the summary's own — the same chars/4 proxy as estimateTokens (a stable
104
+ * MONOTONE savings figure, not a bill).
105
+ */
106
+ export function estimateSummarySavings(covered, summary) {
107
+ return Math.max(0, estimateTokens(covered) - Math.ceil(summary.length / 4));
108
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-runtime",
3
- "version": "0.1.26",
4
- "description": "kiso runtime \u2014 durable multi-turn agent sessions: AgentDefinition, AgentRuntime, AgentSession, Run, append-only JSONL store.",
3
+ "version": "0.1.28",
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",
7
7
  "exports": {
@@ -21,11 +21,11 @@
21
21
  "test": "vitest run"
22
22
  },
23
23
  "dependencies": {
24
- "@vincemakes/kiso-core": "0.1.26"
24
+ "@vincemakes/kiso-core": "0.1.28"
25
25
  },
26
26
  "peerDependencies": {
27
- "@vincemakes/kiso-provider-anthropic": "0.1.26",
28
- "@vincemakes/kiso-provider-openai": "0.1.26"
27
+ "@vincemakes/kiso-provider-anthropic": "0.1.28",
28
+ "@vincemakes/kiso-provider-openai": "0.1.28"
29
29
  },
30
30
  "peerDependenciesMeta": {
31
31
  "@vincemakes/kiso-provider-anthropic": {
@@ -36,7 +36,7 @@
36
36
  }
37
37
  },
38
38
  "devDependencies": {
39
- "@vincemakes/kiso-evals": "0.1.26",
39
+ "@vincemakes/kiso-evals": "0.1.28",
40
40
  "@types/node": "^26.1.2",
41
41
  "typescript": "^5.7.2",
42
42
  "vitest": "^3.0.0"