@agentshouse/session-content 0.0.0-stage → 0.1.0-c27fa9c4d6971

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anton (trof3039)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,33 @@
1
- # Temporary Holding Version
1
+ # `@agentshouse/session-content`
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Session content is one model of what an agent CLI's session reports of its work, the same for
4
+ every CLI: a turn's parts and the session's state. It has no dependencies and runs in Node and
5
+ in the browser.
6
+
7
+ - A turn is an ordered list of parts: text, reasoning, calls by kind (`command`, `edit`,
8
+ `read`, `search`, `fetch`, `tool`, `other`), sub-agents, messages between agents, images, a
9
+ plan, notices and background work. A part's `parent` is the index of the sub-agent whose own
10
+ work it is, or `null`, so sub-agents nest at any depth.
11
+ - A running turn changes by operations: `start` a part at the end, or at `0` to begin the turn
12
+ again, `append` text to a text or reasoning part, and `set` a part to a new version of itself.
13
+ `applied` folds one operation into the parts and answers `null` for one that does not fit.
14
+ - The session's state holds its title, context, limits, cost, tokens, the last turn's duration,
15
+ the files changed, git branch, worktree and pull request, model, effort, mode, the suggested
16
+ next prompt and the work that still runs.
17
+ - Bulk is bounded: a command keeps its last `OUTPUT_LINES` lines of at most
18
+ `OUTPUT_CHARACTERS`, an edit's diff of a file at most `DIFF_CHARACTERS` and beyond that only its
19
+ line counts, a fetched page's, a tool's or another call's result its first
20
+ `FIRST_PART_CHARACTERS`. `lastLines`, `keptDiff` and `firstPart` cut to those bounds.
21
+
22
+ ```ts
23
+ import { applied, isOperation, isTurn, type Part } from '@agentshouse/session-content';
24
+
25
+ let parts: readonly Part[] = [];
26
+ for (const operation of received) {
27
+ if (!isOperation(operation)) throw new Error('not Session content');
28
+ parts = applied(parts, operation) ?? parts;
29
+ }
30
+ isTurn({ parts, tokens: null, state });
31
+ ```
32
+
33
+ `isPart`, `isOperation`, `isState` and `isTurn` check a value and narrow its type.
@@ -0,0 +1,7 @@
1
+ export declare const OUTPUT_LINES = 20;
2
+ export declare const OUTPUT_CHARACTERS = 4000;
3
+ export declare const DIFF_CHARACTERS = 10000;
4
+ export declare const FIRST_PART_CHARACTERS = 2000;
5
+ export declare function lastLines(output: string): string;
6
+ export declare function firstPart(result: string): string;
7
+ export declare function keptDiff(diff: string): string | null;
package/dist/bounds.js ADDED
@@ -0,0 +1,20 @@
1
+ export const OUTPUT_LINES = 20;
2
+ export const OUTPUT_CHARACTERS = 4000;
3
+ export const DIFF_CHARACTERS = 10_000;
4
+ export const FIRST_PART_CHARACTERS = 2000;
5
+ const LOW_SURROGATE = /^[\uDC00-\uDFFF]/u;
6
+ const HIGH_SURROGATE = /[\uD800-\uDBFF]$/u;
7
+ export function lastLines(output) {
8
+ const lines = output.split('\n').slice(-OUTPUT_LINES).join('\n');
9
+ if (lines.length <= OUTPUT_CHARACTERS)
10
+ return lines;
11
+ return lines.slice(-OUTPUT_CHARACTERS).replace(LOW_SURROGATE, '');
12
+ }
13
+ export function firstPart(result) {
14
+ if (result.length <= FIRST_PART_CHARACTERS)
15
+ return result;
16
+ return result.slice(0, FIRST_PART_CHARACTERS).replace(HIGH_SURROGATE, '');
17
+ }
18
+ export function keptDiff(diff) {
19
+ return diff.length <= DIFF_CHARACTERS ? diff : null;
20
+ }
@@ -0,0 +1,18 @@
1
+ export type Check<T> = (value: unknown) => value is T;
2
+ export type Checked<C> = C extends Check<infer T> ? T : never;
3
+ type Shape = Readonly<Record<string, Check<unknown>>>;
4
+ export type Shaped<S extends Shape> = {
5
+ readonly [K in keyof S]: Checked<S[K]>;
6
+ };
7
+ export declare const text: Check<string>;
8
+ export declare const integer: Check<number>;
9
+ export declare const count: Check<number>;
10
+ export declare const figure: Check<number>;
11
+ export declare const instant: Check<string>;
12
+ export declare function oneOf<const V extends readonly string[]>(...values: V): Check<V[number]>;
13
+ export declare function where<T>(check: Check<T>, holds: (value: T) => boolean): Check<T>;
14
+ export declare function nullable<T>(check: Check<T>): Check<T | null>;
15
+ export declare function list<T>(check: Check<T>): Check<readonly T[]>;
16
+ export declare function exact<const S extends Shape>(shape: S): Check<Shaped<S>>;
17
+ export declare function anyOf<const C extends readonly Check<unknown>[]>(...checks: C): Check<Checked<C[number]>>;
18
+ export {};
package/dist/check.js ADDED
@@ -0,0 +1,31 @@
1
+ const INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/u;
2
+ export const text = (value) => typeof value === 'string';
3
+ export const integer = (value) => Number.isSafeInteger(value);
4
+ export const count = (value) => integer(value) && value >= 0;
5
+ export const figure = (value) => typeof value === 'number' && Number.isFinite(value) && value >= 0;
6
+ export const instant = (value) => text(value) && INSTANT.test(value) && !Number.isNaN(Date.parse(value));
7
+ export function oneOf(...values) {
8
+ return (value) => values.includes(value);
9
+ }
10
+ export function where(check, holds) {
11
+ return (value) => check(value) && holds(value);
12
+ }
13
+ export function nullable(check) {
14
+ return (value) => value === null || check(value);
15
+ }
16
+ export function list(check) {
17
+ return (value) => Array.isArray(value) && value.every(check);
18
+ }
19
+ export function exact(shape) {
20
+ const keys = Object.keys(shape);
21
+ return (value) => {
22
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
23
+ return false;
24
+ const held = value;
25
+ return (Object.keys(held).length === keys.length &&
26
+ keys.every((key) => Object.hasOwn(held, key) && shape[key](held[key])));
27
+ };
28
+ }
29
+ export function anyOf(...checks) {
30
+ return (value) => checks.some((check) => check(value));
31
+ }
@@ -0,0 +1,7 @@
1
+ export { DIFF_CHARACTERS, FIRST_PART_CHARACTERS, firstPart, keptDiff, lastLines, OUTPUT_CHARACTERS, OUTPUT_LINES, } from './bounds.js';
2
+ export { isPart } from './parts.js';
3
+ export type { Call, FileChange, Part, Status } from './parts.js';
4
+ export { isState } from './state.js';
5
+ export type { SessionState, Tokens } from './state.js';
6
+ export { applied, isOperation, isTurn } from './turn.js';
7
+ export type { Operation, Turn } from './turn.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { DIFF_CHARACTERS, FIRST_PART_CHARACTERS, firstPart, keptDiff, lastLines, OUTPUT_CHARACTERS, OUTPUT_LINES, } from './bounds.js';
2
+ export { isPart } from './parts.js';
3
+ export { isState } from './state.js';
4
+ export { applied, isOperation, isTurn } from './turn.js';
@@ -0,0 +1,101 @@
1
+ import { type Check, type Checked } from './check.js';
2
+ declare const STATUS: Check<"done" | "failed" | "running" | "stopped">;
3
+ export type Status = Checked<typeof STATUS>;
4
+ declare const FILE_CHANGE: Check<import("./check.js").Shaped<{
5
+ readonly path: Check<string>;
6
+ readonly added: Check<number>;
7
+ readonly removed: Check<number>;
8
+ readonly diff: Check<string | null>;
9
+ }>>;
10
+ export type FileChange = Checked<typeof FILE_CHANGE>;
11
+ export declare const BACKGROUND_KINDS: readonly ['shell', 'task', 'monitor', 'schedule'];
12
+ declare const PART: Check<import("./check.js").Shaped<{
13
+ readonly type: Check<"call">;
14
+ readonly parent: Check<number | null>;
15
+ readonly line: Check<string>;
16
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
17
+ readonly duration: Check<number | null>;
18
+ readonly kind: Check<"command">;
19
+ readonly exit: Check<number | null>;
20
+ readonly output: Check<string>;
21
+ }> | import("./check.js").Shaped<{
22
+ readonly type: Check<"call">;
23
+ readonly parent: Check<number | null>;
24
+ readonly line: Check<string>;
25
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
26
+ readonly duration: Check<number | null>;
27
+ readonly kind: Check<"edit">;
28
+ readonly files: Check<readonly import("./check.js").Shaped<{
29
+ readonly path: Check<string>;
30
+ readonly added: Check<number>;
31
+ readonly removed: Check<number>;
32
+ readonly diff: Check<string | null>;
33
+ }>[]>;
34
+ }> | import("./check.js").Shaped<{
35
+ readonly type: Check<"call">;
36
+ readonly parent: Check<number | null>;
37
+ readonly line: Check<string>;
38
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
39
+ readonly duration: Check<number | null>;
40
+ readonly kind: Check<"read" | "search">;
41
+ readonly returned: Check<number | null>;
42
+ }> | import("./check.js").Shaped<{
43
+ readonly type: Check<"call">;
44
+ readonly parent: Check<number | null>;
45
+ readonly line: Check<string>;
46
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
47
+ readonly duration: Check<number | null>;
48
+ readonly kind: Check<"fetch" | "other" | "tool">;
49
+ readonly output: Check<string>;
50
+ }> | import("./check.js").Shaped<{
51
+ readonly type: Check<"subagent">;
52
+ readonly parent: Check<number | null>;
53
+ readonly kind: Check<"agent" | "fork" | "workflow">;
54
+ readonly name: Check<string | null>;
55
+ readonly task: Check<string>;
56
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
57
+ readonly step: Check<string | null>;
58
+ readonly report: Check<string | null>;
59
+ readonly tokens: Check<number | null>;
60
+ readonly calls: Check<number | null>;
61
+ readonly duration: Check<number | null>;
62
+ }> | import("./check.js").Shaped<{
63
+ readonly type: Check<"reasoning" | "text">;
64
+ readonly parent: Check<number | null>;
65
+ readonly text: Check<string>;
66
+ }> | import("./check.js").Shaped<{
67
+ readonly type: Check<"message">;
68
+ readonly parent: Check<number | null>;
69
+ readonly command: Check<string>;
70
+ readonly target: Check<string | null>;
71
+ }> | import("./check.js").Shaped<{
72
+ readonly type: Check<"image">;
73
+ readonly parent: Check<number | null>;
74
+ readonly file: Check<string>;
75
+ readonly name: Check<string>;
76
+ readonly media_type: Check<string>;
77
+ }> | import("./check.js").Shaped<{
78
+ readonly type: Check<"plan">;
79
+ readonly parent: Check<number | null>;
80
+ readonly entries: Check<readonly import("./check.js").Shaped<{
81
+ readonly content: Check<string>;
82
+ readonly status: Check<"done" | "pending" | "running">;
83
+ }>[]>;
84
+ }> | import("./check.js").Shaped<{
85
+ readonly type: Check<"notice">;
86
+ readonly parent: Check<number | null>;
87
+ readonly kind: Check<"compaction" | "error" | "info" | "mode" | "model" | "retry" | "warning">;
88
+ readonly text: Check<string>;
89
+ }> | import("./check.js").Shaped<{
90
+ readonly type: Check<"background">;
91
+ readonly parent: Check<number | null>;
92
+ readonly kind: Check<"monitor" | "schedule" | "shell" | "task">;
93
+ readonly label: Check<string>;
94
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
95
+ }>>;
96
+ export type Part = Checked<typeof PART>;
97
+ export type Call = Extract<Part, {
98
+ readonly type: 'call';
99
+ }>;
100
+ export declare const isPart: Check<Part>;
101
+ export {};
package/dist/parts.js ADDED
@@ -0,0 +1,65 @@
1
+ import { DIFF_CHARACTERS, firstPart, lastLines } from './bounds.js';
2
+ import { anyOf, count, exact, integer, list, nullable, oneOf, text, where, } from './check.js';
3
+ const STATUS = oneOf('running', 'done', 'failed', 'stopped');
4
+ const PARENT = nullable(count);
5
+ const CALL = {
6
+ type: oneOf('call'),
7
+ parent: PARENT,
8
+ line: text,
9
+ status: STATUS,
10
+ duration: nullable(count),
11
+ };
12
+ const LAST_LINES = where(text, (output) => lastLines(output) === output);
13
+ const FIRST_PART = where(text, (output) => firstPart(output) === output);
14
+ const FILE_CHANGE = exact({
15
+ path: text,
16
+ added: count,
17
+ removed: count,
18
+ diff: nullable(where(text, (diff) => diff.length <= DIFF_CHARACTERS)),
19
+ });
20
+ const COMMAND = exact({
21
+ ...CALL,
22
+ kind: oneOf('command'),
23
+ exit: nullable(integer),
24
+ output: LAST_LINES,
25
+ });
26
+ const EDIT = exact({ ...CALL, kind: oneOf('edit'), files: list(FILE_CHANGE) });
27
+ const READ = exact({ ...CALL, kind: oneOf('read', 'search'), returned: nullable(count) });
28
+ const RESULT = exact({ ...CALL, kind: oneOf('fetch', 'tool', 'other'), output: FIRST_PART });
29
+ const SUBAGENT = exact({
30
+ type: oneOf('subagent'),
31
+ parent: PARENT,
32
+ kind: oneOf('agent', 'fork', 'workflow'),
33
+ name: nullable(text),
34
+ task: text,
35
+ status: STATUS,
36
+ step: nullable(text),
37
+ report: nullable(text),
38
+ tokens: nullable(count),
39
+ calls: nullable(count),
40
+ duration: nullable(count),
41
+ });
42
+ export const BACKGROUND_KINDS = ['shell', 'task', 'monitor', 'schedule'];
43
+ const PART = anyOf(exact({ type: oneOf('text', 'reasoning'), parent: PARENT, text }), COMMAND, EDIT, READ, RESULT, SUBAGENT, exact({ type: oneOf('message'), parent: PARENT, command: text, target: nullable(text) }), exact({
44
+ type: oneOf('image'),
45
+ parent: PARENT,
46
+ file: where(text, (file) => file !== ''),
47
+ name: text,
48
+ media_type: text,
49
+ }), exact({
50
+ type: oneOf('plan'),
51
+ parent: PARENT,
52
+ entries: list(exact({ content: text, status: oneOf('pending', 'running', 'done') })),
53
+ }), exact({
54
+ type: oneOf('notice'),
55
+ parent: PARENT,
56
+ kind: oneOf('mode', 'model', 'compaction', 'retry', 'info', 'warning', 'error'),
57
+ text,
58
+ }), exact({
59
+ type: oneOf('background'),
60
+ parent: PARENT,
61
+ kind: oneOf(...BACKGROUND_KINDS),
62
+ label: text,
63
+ status: STATUS,
64
+ }));
65
+ export const isPart = PART;
@@ -0,0 +1,60 @@
1
+ import { type Check, type Checked } from './check.js';
2
+ export declare const TOKENS: Check<import("./check.js").Shaped<{
3
+ readonly input: Check<number>;
4
+ readonly output: Check<number>;
5
+ readonly cache_read: Check<number>;
6
+ readonly cache_write: Check<number>;
7
+ }>>;
8
+ export type Tokens = Checked<typeof TOKENS>;
9
+ declare const STATE: Check<import("./check.js").Shaped<{
10
+ readonly title: Check<string | null>;
11
+ readonly context: Check<import("./check.js").Shaped<{
12
+ readonly used: Check<number>;
13
+ readonly window: Check<number>;
14
+ readonly breakdown: Check<readonly import("./check.js").Shaped<{
15
+ readonly name: Check<string>;
16
+ readonly tokens: Check<number>;
17
+ }>[]>;
18
+ }> | null>;
19
+ readonly limits: Check<readonly import("./check.js").Shaped<{
20
+ readonly name: Check<string | null>;
21
+ readonly minutes: Check<number>;
22
+ readonly percent: Check<number>;
23
+ readonly resets: Check<string | null>;
24
+ }>[]>;
25
+ readonly cost: Check<import("./check.js").Shaped<{
26
+ readonly amount: Check<number>;
27
+ readonly currency: Check<string>;
28
+ }> | null>;
29
+ readonly tokens: Check<import("./check.js").Shaped<{
30
+ readonly input: Check<number>;
31
+ readonly output: Check<number>;
32
+ readonly cache_read: Check<number>;
33
+ readonly cache_write: Check<number>;
34
+ }> | null>;
35
+ readonly duration: Check<number | null>;
36
+ readonly files: Check<readonly import("./check.js").Shaped<{
37
+ readonly path: Check<string>;
38
+ readonly added: Check<number>;
39
+ readonly removed: Check<number>;
40
+ }>[]>;
41
+ readonly branch: Check<string | null>;
42
+ readonly worktree: Check<string | null>;
43
+ readonly pull: Check<import("./check.js").Shaped<{
44
+ readonly number: Check<number>;
45
+ readonly url: Check<string>;
46
+ }> | null>;
47
+ readonly model: Check<string | null>;
48
+ readonly effort: Check<string | null>;
49
+ readonly mode: Check<string | null>;
50
+ readonly suggestion: Check<string | null>;
51
+ readonly running: Check<readonly import("./check.js").Shaped<{
52
+ readonly kind: Check<"monitor" | "schedule" | "shell" | "subagent" | "task">;
53
+ readonly label: Check<string>;
54
+ readonly progress: Check<string | null>;
55
+ readonly next: Check<string | null>;
56
+ }>[]>;
57
+ }>>;
58
+ export type SessionState = Checked<typeof STATE>;
59
+ export declare const isState: Check<SessionState>;
60
+ export {};
package/dist/state.js ADDED
@@ -0,0 +1,30 @@
1
+ import { count, exact, figure, instant, list, nullable, oneOf, text, } from './check.js';
2
+ import { BACKGROUND_KINDS } from './parts.js';
3
+ export const TOKENS = exact({ input: count, output: count, cache_read: count, cache_write: count });
4
+ const STATE = exact({
5
+ title: nullable(text),
6
+ context: nullable(exact({
7
+ used: count,
8
+ window: count,
9
+ breakdown: list(exact({ name: text, tokens: count })),
10
+ })),
11
+ limits: list(exact({ name: nullable(text), minutes: count, percent: figure, resets: nullable(instant) })),
12
+ cost: nullable(exact({ amount: figure, currency: text })),
13
+ tokens: nullable(TOKENS),
14
+ duration: nullable(count),
15
+ files: list(exact({ path: text, added: count, removed: count })),
16
+ branch: nullable(text),
17
+ worktree: nullable(text),
18
+ pull: nullable(exact({ number: count, url: text })),
19
+ model: nullable(text),
20
+ effort: nullable(text),
21
+ mode: nullable(text),
22
+ suggestion: nullable(text),
23
+ running: list(exact({
24
+ kind: oneOf('subagent', ...BACKGROUND_KINDS),
25
+ label: text,
26
+ progress: nullable(text),
27
+ next: nullable(instant),
28
+ })),
29
+ });
30
+ export const isState = STATE;
package/dist/turn.d.ts ADDED
@@ -0,0 +1,328 @@
1
+ import { type Check, type Checked } from './check.js';
2
+ import { type Part } from './parts.js';
3
+ declare const OPERATION: Check<import("./check.js").Shaped<{
4
+ readonly op: Check<"start">;
5
+ readonly index: Check<number>;
6
+ readonly part: Check<import("./check.js").Shaped<{
7
+ readonly type: Check<"call">;
8
+ readonly parent: Check<number | null>;
9
+ readonly line: Check<string>;
10
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
11
+ readonly duration: Check<number | null>;
12
+ readonly kind: Check<"command">;
13
+ readonly exit: Check<number | null>;
14
+ readonly output: Check<string>;
15
+ }> | import("./check.js").Shaped<{
16
+ readonly type: Check<"call">;
17
+ readonly parent: Check<number | null>;
18
+ readonly line: Check<string>;
19
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
20
+ readonly duration: Check<number | null>;
21
+ readonly kind: Check<"edit">;
22
+ readonly files: Check<readonly import("./check.js").Shaped<{
23
+ readonly path: Check<string>;
24
+ readonly added: Check<number>;
25
+ readonly removed: Check<number>;
26
+ readonly diff: Check<string | null>;
27
+ }>[]>;
28
+ }> | import("./check.js").Shaped<{
29
+ readonly type: Check<"call">;
30
+ readonly parent: Check<number | null>;
31
+ readonly line: Check<string>;
32
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
33
+ readonly duration: Check<number | null>;
34
+ readonly kind: Check<"read" | "search">;
35
+ readonly returned: Check<number | null>;
36
+ }> | import("./check.js").Shaped<{
37
+ readonly type: Check<"call">;
38
+ readonly parent: Check<number | null>;
39
+ readonly line: Check<string>;
40
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
41
+ readonly duration: Check<number | null>;
42
+ readonly kind: Check<"fetch" | "other" | "tool">;
43
+ readonly output: Check<string>;
44
+ }> | import("./check.js").Shaped<{
45
+ readonly type: Check<"subagent">;
46
+ readonly parent: Check<number | null>;
47
+ readonly kind: Check<"agent" | "fork" | "workflow">;
48
+ readonly name: Check<string | null>;
49
+ readonly task: Check<string>;
50
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
51
+ readonly step: Check<string | null>;
52
+ readonly report: Check<string | null>;
53
+ readonly tokens: Check<number | null>;
54
+ readonly calls: Check<number | null>;
55
+ readonly duration: Check<number | null>;
56
+ }> | import("./check.js").Shaped<{
57
+ readonly type: Check<"reasoning" | "text">;
58
+ readonly parent: Check<number | null>;
59
+ readonly text: Check<string>;
60
+ }> | import("./check.js").Shaped<{
61
+ readonly type: Check<"message">;
62
+ readonly parent: Check<number | null>;
63
+ readonly command: Check<string>;
64
+ readonly target: Check<string | null>;
65
+ }> | import("./check.js").Shaped<{
66
+ readonly type: Check<"image">;
67
+ readonly parent: Check<number | null>;
68
+ readonly file: Check<string>;
69
+ readonly name: Check<string>;
70
+ readonly media_type: Check<string>;
71
+ }> | import("./check.js").Shaped<{
72
+ readonly type: Check<"plan">;
73
+ readonly parent: Check<number | null>;
74
+ readonly entries: Check<readonly import("./check.js").Shaped<{
75
+ readonly content: Check<string>;
76
+ readonly status: Check<"done" | "pending" | "running">;
77
+ }>[]>;
78
+ }> | import("./check.js").Shaped<{
79
+ readonly type: Check<"notice">;
80
+ readonly parent: Check<number | null>;
81
+ readonly kind: Check<"compaction" | "error" | "info" | "mode" | "model" | "retry" | "warning">;
82
+ readonly text: Check<string>;
83
+ }> | import("./check.js").Shaped<{
84
+ readonly type: Check<"background">;
85
+ readonly parent: Check<number | null>;
86
+ readonly kind: Check<"monitor" | "schedule" | "shell" | "task">;
87
+ readonly label: Check<string>;
88
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
89
+ }>>;
90
+ }> | import("./check.js").Shaped<{
91
+ readonly op: Check<"append">;
92
+ readonly index: Check<number>;
93
+ readonly text: Check<string>;
94
+ }> | import("./check.js").Shaped<{
95
+ readonly op: Check<"set">;
96
+ readonly index: Check<number>;
97
+ readonly part: Check<import("./check.js").Shaped<{
98
+ readonly type: Check<"call">;
99
+ readonly parent: Check<number | null>;
100
+ readonly line: Check<string>;
101
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
102
+ readonly duration: Check<number | null>;
103
+ readonly kind: Check<"command">;
104
+ readonly exit: Check<number | null>;
105
+ readonly output: Check<string>;
106
+ }> | import("./check.js").Shaped<{
107
+ readonly type: Check<"call">;
108
+ readonly parent: Check<number | null>;
109
+ readonly line: Check<string>;
110
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
111
+ readonly duration: Check<number | null>;
112
+ readonly kind: Check<"edit">;
113
+ readonly files: Check<readonly import("./check.js").Shaped<{
114
+ readonly path: Check<string>;
115
+ readonly added: Check<number>;
116
+ readonly removed: Check<number>;
117
+ readonly diff: Check<string | null>;
118
+ }>[]>;
119
+ }> | import("./check.js").Shaped<{
120
+ readonly type: Check<"call">;
121
+ readonly parent: Check<number | null>;
122
+ readonly line: Check<string>;
123
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
124
+ readonly duration: Check<number | null>;
125
+ readonly kind: Check<"read" | "search">;
126
+ readonly returned: Check<number | null>;
127
+ }> | import("./check.js").Shaped<{
128
+ readonly type: Check<"call">;
129
+ readonly parent: Check<number | null>;
130
+ readonly line: Check<string>;
131
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
132
+ readonly duration: Check<number | null>;
133
+ readonly kind: Check<"fetch" | "other" | "tool">;
134
+ readonly output: Check<string>;
135
+ }> | import("./check.js").Shaped<{
136
+ readonly type: Check<"subagent">;
137
+ readonly parent: Check<number | null>;
138
+ readonly kind: Check<"agent" | "fork" | "workflow">;
139
+ readonly name: Check<string | null>;
140
+ readonly task: Check<string>;
141
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
142
+ readonly step: Check<string | null>;
143
+ readonly report: Check<string | null>;
144
+ readonly tokens: Check<number | null>;
145
+ readonly calls: Check<number | null>;
146
+ readonly duration: Check<number | null>;
147
+ }> | import("./check.js").Shaped<{
148
+ readonly type: Check<"reasoning" | "text">;
149
+ readonly parent: Check<number | null>;
150
+ readonly text: Check<string>;
151
+ }> | import("./check.js").Shaped<{
152
+ readonly type: Check<"message">;
153
+ readonly parent: Check<number | null>;
154
+ readonly command: Check<string>;
155
+ readonly target: Check<string | null>;
156
+ }> | import("./check.js").Shaped<{
157
+ readonly type: Check<"image">;
158
+ readonly parent: Check<number | null>;
159
+ readonly file: Check<string>;
160
+ readonly name: Check<string>;
161
+ readonly media_type: Check<string>;
162
+ }> | import("./check.js").Shaped<{
163
+ readonly type: Check<"plan">;
164
+ readonly parent: Check<number | null>;
165
+ readonly entries: Check<readonly import("./check.js").Shaped<{
166
+ readonly content: Check<string>;
167
+ readonly status: Check<"done" | "pending" | "running">;
168
+ }>[]>;
169
+ }> | import("./check.js").Shaped<{
170
+ readonly type: Check<"notice">;
171
+ readonly parent: Check<number | null>;
172
+ readonly kind: Check<"compaction" | "error" | "info" | "mode" | "model" | "retry" | "warning">;
173
+ readonly text: Check<string>;
174
+ }> | import("./check.js").Shaped<{
175
+ readonly type: Check<"background">;
176
+ readonly parent: Check<number | null>;
177
+ readonly kind: Check<"monitor" | "schedule" | "shell" | "task">;
178
+ readonly label: Check<string>;
179
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
180
+ }>>;
181
+ }>>;
182
+ export type Operation = Checked<typeof OPERATION>;
183
+ export declare const isOperation: Check<Operation>;
184
+ declare const TURN: Check<import("./check.js").Shaped<{
185
+ readonly parts: Check<readonly (import("./check.js").Shaped<{
186
+ readonly type: Check<"call">;
187
+ readonly parent: Check<number | null>;
188
+ readonly line: Check<string>;
189
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
190
+ readonly duration: Check<number | null>;
191
+ readonly kind: Check<"command">;
192
+ readonly exit: Check<number | null>;
193
+ readonly output: Check<string>;
194
+ }> | import("./check.js").Shaped<{
195
+ readonly type: Check<"call">;
196
+ readonly parent: Check<number | null>;
197
+ readonly line: Check<string>;
198
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
199
+ readonly duration: Check<number | null>;
200
+ readonly kind: Check<"edit">;
201
+ readonly files: Check<readonly import("./check.js").Shaped<{
202
+ readonly path: Check<string>;
203
+ readonly added: Check<number>;
204
+ readonly removed: Check<number>;
205
+ readonly diff: Check<string | null>;
206
+ }>[]>;
207
+ }> | import("./check.js").Shaped<{
208
+ readonly type: Check<"call">;
209
+ readonly parent: Check<number | null>;
210
+ readonly line: Check<string>;
211
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
212
+ readonly duration: Check<number | null>;
213
+ readonly kind: Check<"read" | "search">;
214
+ readonly returned: Check<number | null>;
215
+ }> | import("./check.js").Shaped<{
216
+ readonly type: Check<"call">;
217
+ readonly parent: Check<number | null>;
218
+ readonly line: Check<string>;
219
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
220
+ readonly duration: Check<number | null>;
221
+ readonly kind: Check<"fetch" | "other" | "tool">;
222
+ readonly output: Check<string>;
223
+ }> | import("./check.js").Shaped<{
224
+ readonly type: Check<"subagent">;
225
+ readonly parent: Check<number | null>;
226
+ readonly kind: Check<"agent" | "fork" | "workflow">;
227
+ readonly name: Check<string | null>;
228
+ readonly task: Check<string>;
229
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
230
+ readonly step: Check<string | null>;
231
+ readonly report: Check<string | null>;
232
+ readonly tokens: Check<number | null>;
233
+ readonly calls: Check<number | null>;
234
+ readonly duration: Check<number | null>;
235
+ }> | import("./check.js").Shaped<{
236
+ readonly type: Check<"reasoning" | "text">;
237
+ readonly parent: Check<number | null>;
238
+ readonly text: Check<string>;
239
+ }> | import("./check.js").Shaped<{
240
+ readonly type: Check<"message">;
241
+ readonly parent: Check<number | null>;
242
+ readonly command: Check<string>;
243
+ readonly target: Check<string | null>;
244
+ }> | import("./check.js").Shaped<{
245
+ readonly type: Check<"image">;
246
+ readonly parent: Check<number | null>;
247
+ readonly file: Check<string>;
248
+ readonly name: Check<string>;
249
+ readonly media_type: Check<string>;
250
+ }> | import("./check.js").Shaped<{
251
+ readonly type: Check<"plan">;
252
+ readonly parent: Check<number | null>;
253
+ readonly entries: Check<readonly import("./check.js").Shaped<{
254
+ readonly content: Check<string>;
255
+ readonly status: Check<"done" | "pending" | "running">;
256
+ }>[]>;
257
+ }> | import("./check.js").Shaped<{
258
+ readonly type: Check<"notice">;
259
+ readonly parent: Check<number | null>;
260
+ readonly kind: Check<"compaction" | "error" | "info" | "mode" | "model" | "retry" | "warning">;
261
+ readonly text: Check<string>;
262
+ }> | import("./check.js").Shaped<{
263
+ readonly type: Check<"background">;
264
+ readonly parent: Check<number | null>;
265
+ readonly kind: Check<"monitor" | "schedule" | "shell" | "task">;
266
+ readonly label: Check<string>;
267
+ readonly status: Check<"done" | "failed" | "running" | "stopped">;
268
+ }>)[]>;
269
+ readonly tokens: Check<import("./check.js").Shaped<{
270
+ readonly input: Check<number>;
271
+ readonly output: Check<number>;
272
+ readonly cache_read: Check<number>;
273
+ readonly cache_write: Check<number>;
274
+ }> | null>;
275
+ readonly state: Check<import("./check.js").Shaped<{
276
+ readonly title: Check<string | null>;
277
+ readonly context: Check<import("./check.js").Shaped<{
278
+ readonly used: Check<number>;
279
+ readonly window: Check<number>;
280
+ readonly breakdown: Check<readonly import("./check.js").Shaped<{
281
+ readonly name: Check<string>;
282
+ readonly tokens: Check<number>;
283
+ }>[]>;
284
+ }> | null>;
285
+ readonly limits: Check<readonly import("./check.js").Shaped<{
286
+ readonly name: Check<string | null>;
287
+ readonly minutes: Check<number>;
288
+ readonly percent: Check<number>;
289
+ readonly resets: Check<string | null>;
290
+ }>[]>;
291
+ readonly cost: Check<import("./check.js").Shaped<{
292
+ readonly amount: Check<number>;
293
+ readonly currency: Check<string>;
294
+ }> | null>;
295
+ readonly tokens: Check<import("./check.js").Shaped<{
296
+ readonly input: Check<number>;
297
+ readonly output: Check<number>;
298
+ readonly cache_read: Check<number>;
299
+ readonly cache_write: Check<number>;
300
+ }> | null>;
301
+ readonly duration: Check<number | null>;
302
+ readonly files: Check<readonly import("./check.js").Shaped<{
303
+ readonly path: Check<string>;
304
+ readonly added: Check<number>;
305
+ readonly removed: Check<number>;
306
+ }>[]>;
307
+ readonly branch: Check<string | null>;
308
+ readonly worktree: Check<string | null>;
309
+ readonly pull: Check<import("./check.js").Shaped<{
310
+ readonly number: Check<number>;
311
+ readonly url: Check<string>;
312
+ }> | null>;
313
+ readonly model: Check<string | null>;
314
+ readonly effort: Check<string | null>;
315
+ readonly mode: Check<string | null>;
316
+ readonly suggestion: Check<string | null>;
317
+ readonly running: Check<readonly import("./check.js").Shaped<{
318
+ readonly kind: Check<"monitor" | "schedule" | "shell" | "subagent" | "task">;
319
+ readonly label: Check<string>;
320
+ readonly progress: Check<string | null>;
321
+ readonly next: Check<string | null>;
322
+ }>[]>;
323
+ }>>;
324
+ }>>;
325
+ export type Turn = Checked<typeof TURN>;
326
+ export declare const isTurn: Check<Turn>;
327
+ export declare function applied(parts: readonly Part[], operation: Operation): readonly Part[] | null;
328
+ export {};
package/dist/turn.js ADDED
@@ -0,0 +1,33 @@
1
+ import { anyOf, count, exact, list, nullable, oneOf, text, where, } from './check.js';
2
+ import { isPart } from './parts.js';
3
+ import { isState, TOKENS } from './state.js';
4
+ const OPERATION = anyOf(exact({ op: oneOf('start'), index: count, part: isPart }), exact({ op: oneOf('append'), index: count, text }), exact({ op: oneOf('set'), index: count, part: isPart }));
5
+ export const isOperation = OPERATION;
6
+ function nested(parts, part, index) {
7
+ return part.parent === null || (part.parent < index && parts[part.parent]?.type === 'subagent');
8
+ }
9
+ const TURN = where(exact({ parts: list(isPart), tokens: nullable(TOKENS), state: isState }), (turn) => turn.parts.every((part, index) => nested(turn.parts, part, index)));
10
+ export const isTurn = TURN;
11
+ function changed(held, operation) {
12
+ if (operation.op === 'append') {
13
+ return held.type === 'text' || held.type === 'reasoning'
14
+ ? { ...held, text: held.text + operation.text }
15
+ : null;
16
+ }
17
+ return operation.part.type === held.type && operation.part.parent === held.parent
18
+ ? operation.part
19
+ : null;
20
+ }
21
+ export function applied(parts, operation) {
22
+ if (operation.op === 'start') {
23
+ if (operation.index !== 0 && operation.index !== parts.length)
24
+ return null;
25
+ const kept = parts.slice(0, operation.index);
26
+ return nested(kept, operation.part, operation.index) ? [...kept, operation.part] : null;
27
+ }
28
+ const held = parts[operation.index];
29
+ const part = held === undefined ? null : changed(held, operation);
30
+ if (part === null)
31
+ return null;
32
+ return parts.map((one, index) => (index === operation.index ? part : one));
33
+ }
package/package.json CHANGED
@@ -1,6 +1,31 @@
1
1
  {
2
2
  "name": "@agentshouse/session-content",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0-c27fa9c4d6971",
4
+ "description": "Session content: one model of what an agent CLI's session reports, the same for every CLI, with its parser, its fold of a running turn and its bounds on bulk",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "engines": {
12
+ "node": ">=24.22.1"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.js"
18
+ },
19
+ "./package.json": "./package.json"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/agentshouse/core.git",
29
+ "directory": "session-content"
30
+ }
31
+ }