@minpeter/pss-runtime 0.0.10 → 0.1.0-next.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.
Files changed (58) hide show
  1. package/README.md +191 -20
  2. package/dist/agent-loop.d.ts +1 -0
  3. package/dist/agent-loop.js +14 -8
  4. package/dist/agent-loop.js.map +1 -1
  5. package/dist/agent.d.ts +8 -10
  6. package/dist/agent.js +34 -13
  7. package/dist/agent.js.map +1 -1
  8. package/dist/index.d.ts +8 -4
  9. package/dist/index.js +6 -1
  10. package/dist/llm.js +7 -1
  11. package/dist/llm.js.map +1 -1
  12. package/dist/plugins/compaction.d.ts +15 -0
  13. package/dist/plugins/compaction.js +98 -0
  14. package/dist/plugins/compaction.js.map +1 -0
  15. package/dist/plugins/index.d.ts +5 -0
  16. package/dist/plugins/index.js +5 -0
  17. package/dist/plugins/memory.d.ts +11 -0
  18. package/dist/plugins/memory.js +146 -0
  19. package/dist/plugins/memory.js.map +1 -0
  20. package/dist/plugins/runner.d.ts +1 -0
  21. package/dist/plugins/runner.js +83 -0
  22. package/dist/plugins/runner.js.map +1 -0
  23. package/dist/plugins/scope.d.ts +1 -0
  24. package/dist/plugins/scope.js +13 -0
  25. package/dist/plugins/scope.js.map +1 -0
  26. package/dist/plugins/sessions.d.ts +12 -0
  27. package/dist/plugins/sessions.js +34 -0
  28. package/dist/plugins/sessions.js.map +1 -0
  29. package/dist/plugins/tool-hook-handlers.js +77 -0
  30. package/dist/plugins/tool-hook-handlers.js.map +1 -0
  31. package/dist/plugins/tool-hook-results.js +64 -0
  32. package/dist/plugins/tool-hook-results.js.map +1 -0
  33. package/dist/plugins/tool-hooks.js +111 -0
  34. package/dist/plugins/tool-hooks.js.map +1 -0
  35. package/dist/plugins/types.d.ts +105 -0
  36. package/dist/plugins/types.js +20 -0
  37. package/dist/plugins/types.js.map +1 -0
  38. package/dist/session/events.d.ts +19 -2
  39. package/dist/session/input.d.ts +4 -0
  40. package/dist/session/lifecycle.d.ts +12 -0
  41. package/dist/session/lifecycle.js +126 -0
  42. package/dist/session/lifecycle.js.map +1 -0
  43. package/dist/session/mapping.js +2 -1
  44. package/dist/session/mapping.js.map +1 -1
  45. package/dist/session/overlay-anchor.js +151 -0
  46. package/dist/session/overlay-anchor.js.map +1 -0
  47. package/dist/session/overlay.js +141 -0
  48. package/dist/session/overlay.js.map +1 -0
  49. package/dist/session/runtime-input.d.ts +1 -0
  50. package/dist/session/runtime-input.js +89 -0
  51. package/dist/session/runtime-input.js.map +1 -0
  52. package/dist/session/session.js +164 -117
  53. package/dist/session/session.js.map +1 -1
  54. package/dist/session/snapshot.d.ts +1 -0
  55. package/dist/session/snapshot.js +31 -5
  56. package/dist/session/snapshot.js.map +1 -1
  57. package/package.json +6 -1
  58. package/dist/hooks.d.ts +0 -32
@@ -0,0 +1,151 @@
1
+ //#region src/session/overlay-anchor.ts
2
+ function createCurrentTurnAnchor(priorHistory, message) {
3
+ return {
4
+ index: priorHistory.length,
5
+ matchOrdinal: countMatchingMessages(priorHistory, message) + 1,
6
+ message
7
+ };
8
+ }
9
+ function resolveCurrentTurnIndex({ canonicalHistory, currentTurn, history }) {
10
+ if (!currentTurn) return -1;
11
+ if (canonicalHistory !== void 0 && currentTurn.index < canonicalHistory.length) {
12
+ const canonicalRegionStart = findCanonicalHistoryRegionStart(history, canonicalHistory);
13
+ if (canonicalRegionStart !== -1) return canonicalRegionStart + currentTurn.index;
14
+ }
15
+ const ordinalIndex = findCurrentTurnIndexByOrdinal(history, currentTurn.message, currentTurn.matchOrdinal);
16
+ if (ordinalIndex !== -1) return ordinalIndex;
17
+ const referenceIndex = history.lastIndexOf(currentTurn.message);
18
+ if (referenceIndex !== -1) return referenceIndex;
19
+ return findCurrentTurnIndexByValue(history, currentTurn.message);
20
+ }
21
+ function findCanonicalHistoryRegionStart(history, canonicalHistory) {
22
+ if (canonicalHistory.length === 0) return 0;
23
+ const suffixStart = history.length - canonicalHistory.length;
24
+ if (suffixStart >= 0 && historyRegionMatches(history, canonicalHistory, suffixStart)) return suffixStart;
25
+ if (historyRegionMatches(history, canonicalHistory, 0)) return 0;
26
+ for (let start = 1; start <= history.length - canonicalHistory.length; start += 1) if (historyRegionMatches(history, canonicalHistory, start)) return start;
27
+ return -1;
28
+ }
29
+ function historyRegionMatches(history, canonicalHistory, start) {
30
+ return canonicalHistory.every((message, offset) => modelMessageEquals(history[start + offset], message));
31
+ }
32
+ function findCurrentTurnIndexByOrdinal(history, currentTurnMessage, currentTurnMatchOrdinal) {
33
+ let seen = 0;
34
+ for (let index = 0; index < history.length; index += 1) if (modelMessageEquals(history[index], currentTurnMessage)) {
35
+ seen += 1;
36
+ if (seen === currentTurnMatchOrdinal) return index;
37
+ }
38
+ return -1;
39
+ }
40
+ function findCurrentTurnIndexByValue(history, currentTurnMessage) {
41
+ for (let index = history.length - 1; index >= 0; index -= 1) if (modelMessageEquals(history[index], currentTurnMessage)) return index;
42
+ return -1;
43
+ }
44
+ function countMatchingMessages(history, currentTurnMessage) {
45
+ return history.filter((message) => modelMessageEquals(message, currentTurnMessage)).length;
46
+ }
47
+ function modelMessageEquals(left, right) {
48
+ return left !== void 0 && modelContentEquals(left, right);
49
+ }
50
+ function modelContentEquals(left, right) {
51
+ const pending = [[left, right]];
52
+ const seen = /* @__PURE__ */ new WeakMap();
53
+ while (pending.length > 0) {
54
+ const pair = pending.pop();
55
+ if (!pair) continue;
56
+ const [leftValue, rightValue] = pair;
57
+ if (Object.is(leftValue, rightValue)) continue;
58
+ if (Array.isArray(leftValue) || Array.isArray(rightValue)) {
59
+ if (!arraysEqual(leftValue, rightValue, seen, pending)) return false;
60
+ continue;
61
+ }
62
+ if (isRecord(leftValue) || isRecord(rightValue)) {
63
+ if (!recordsEqual(leftValue, rightValue, seen, pending)) return false;
64
+ continue;
65
+ }
66
+ return false;
67
+ }
68
+ return true;
69
+ }
70
+ function arraysEqual(left, right, seen, pending) {
71
+ if (!(Array.isArray(left) && Array.isArray(right))) return false;
72
+ if (isSeenPair(left, right, seen)) return true;
73
+ const leftLength = arrayLength(left);
74
+ const rightLength = arrayLength(right);
75
+ if (leftLength === void 0 || rightLength === void 0 || leftLength !== rightLength) return false;
76
+ const leftKeys = enumerableKeys(left);
77
+ const rightKeys = enumerableKeys(right);
78
+ if (!(leftKeys && rightKeys && keysEqual(leftKeys, rightKeys))) return false;
79
+ rememberPair(left, right, seen);
80
+ for (const key of leftKeys) if (!enqueuePropertyComparison(left, right, key, pending)) return false;
81
+ return true;
82
+ }
83
+ function recordsEqual(left, right, seen, pending) {
84
+ if (!(isRecord(left) && isRecord(right))) return false;
85
+ if (isSeenPair(left, right, seen)) return true;
86
+ const leftKeys = enumerableKeys(left);
87
+ const rightKeys = enumerableKeys(right);
88
+ if (!(leftKeys && rightKeys && keysEqual(leftKeys, rightKeys))) return false;
89
+ rememberPair(left, right, seen);
90
+ for (const key of leftKeys) if (!enqueuePropertyComparison(left, right, key, pending)) return false;
91
+ return true;
92
+ }
93
+ function enumerableKeys(value) {
94
+ try {
95
+ return Object.keys(value);
96
+ } catch {
97
+ return;
98
+ }
99
+ }
100
+ function arrayLength(value) {
101
+ try {
102
+ return value.length;
103
+ } catch {
104
+ return;
105
+ }
106
+ }
107
+ function keysEqual(leftKeys, rightKeys) {
108
+ if (leftKeys.length !== rightKeys.length) return false;
109
+ const rightKeySet = new Set(rightKeys);
110
+ return leftKeys.every((key) => rightKeySet.has(key));
111
+ }
112
+ function enqueuePropertyComparison(left, right, key, pending) {
113
+ const leftDescriptor = propertyDescriptor(left, key);
114
+ const rightDescriptor = propertyDescriptor(right, key);
115
+ if (!(leftDescriptor?.enumerable && rightDescriptor?.enumerable)) return false;
116
+ const leftHasValue = "value" in leftDescriptor;
117
+ const rightHasValue = "value" in rightDescriptor;
118
+ if (leftHasValue || rightHasValue) {
119
+ if (!(leftHasValue && rightHasValue)) return false;
120
+ pending.push([leftDescriptor.value, rightDescriptor.value]);
121
+ return true;
122
+ }
123
+ pending.push([leftDescriptor.get, rightDescriptor.get]);
124
+ pending.push([leftDescriptor.set, rightDescriptor.set]);
125
+ return true;
126
+ }
127
+ function propertyDescriptor(value, key) {
128
+ try {
129
+ return Object.getOwnPropertyDescriptor(value, key);
130
+ } catch {
131
+ return;
132
+ }
133
+ }
134
+ function isSeenPair(left, right, seen) {
135
+ return seen.get(left)?.has(right) ?? false;
136
+ }
137
+ function rememberPair(left, right, seen) {
138
+ const rights = seen.get(left);
139
+ if (rights) {
140
+ rights.add(right);
141
+ return;
142
+ }
143
+ seen.set(left, new WeakSet([right]));
144
+ }
145
+ function isRecord(value) {
146
+ return value !== null && typeof value === "object" && !Array.isArray(value);
147
+ }
148
+ //#endregion
149
+ export { createCurrentTurnAnchor, resolveCurrentTurnIndex };
150
+
151
+ //# sourceMappingURL=overlay-anchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-anchor.js","names":[],"sources":["../../src/session/overlay-anchor.ts"],"sourcesContent":["import type { ModelMessage } from \"ai\";\n\nexport interface CurrentTurnAnchor {\n readonly index: number;\n readonly matchOrdinal: number;\n readonly message: ModelMessage;\n}\n\nexport function createCurrentTurnAnchor(\n priorHistory: readonly ModelMessage[],\n message: ModelMessage\n): CurrentTurnAnchor {\n return {\n index: priorHistory.length,\n matchOrdinal: countMatchingMessages(priorHistory, message) + 1,\n message,\n };\n}\n\nexport function resolveCurrentTurnIndex({\n canonicalHistory,\n currentTurn,\n history,\n}: {\n readonly canonicalHistory?: readonly ModelMessage[];\n readonly currentTurn?: CurrentTurnAnchor;\n readonly history: readonly ModelMessage[];\n}): number {\n if (!currentTurn) {\n return -1;\n }\n\n if (\n canonicalHistory !== undefined &&\n currentTurn.index < canonicalHistory.length\n ) {\n const canonicalRegionStart = findCanonicalHistoryRegionStart(\n history,\n canonicalHistory\n );\n if (canonicalRegionStart !== -1) {\n return canonicalRegionStart + currentTurn.index;\n }\n }\n\n const ordinalIndex = findCurrentTurnIndexByOrdinal(\n history,\n currentTurn.message,\n currentTurn.matchOrdinal\n );\n if (ordinalIndex !== -1) {\n return ordinalIndex;\n }\n\n const referenceIndex = history.lastIndexOf(currentTurn.message);\n if (referenceIndex !== -1) {\n return referenceIndex;\n }\n\n return findCurrentTurnIndexByValue(history, currentTurn.message);\n}\n\nfunction findCanonicalHistoryRegionStart(\n history: readonly ModelMessage[],\n canonicalHistory: readonly ModelMessage[]\n): number {\n if (canonicalHistory.length === 0) {\n return 0;\n }\n\n const suffixStart = history.length - canonicalHistory.length;\n if (\n suffixStart >= 0 &&\n historyRegionMatches(history, canonicalHistory, suffixStart)\n ) {\n return suffixStart;\n }\n\n if (historyRegionMatches(history, canonicalHistory, 0)) {\n return 0;\n }\n\n for (\n let start = 1;\n start <= history.length - canonicalHistory.length;\n start += 1\n ) {\n if (historyRegionMatches(history, canonicalHistory, start)) {\n return start;\n }\n }\n\n return -1;\n}\n\nfunction historyRegionMatches(\n history: readonly ModelMessage[],\n canonicalHistory: readonly ModelMessage[],\n start: number\n): boolean {\n return canonicalHistory.every((message, offset) =>\n modelMessageEquals(history[start + offset], message)\n );\n}\n\nfunction findCurrentTurnIndexByOrdinal(\n history: readonly ModelMessage[],\n currentTurnMessage: ModelMessage,\n currentTurnMatchOrdinal: number\n): number {\n let seen = 0;\n for (let index = 0; index < history.length; index += 1) {\n if (modelMessageEquals(history[index], currentTurnMessage)) {\n seen += 1;\n if (seen === currentTurnMatchOrdinal) {\n return index;\n }\n }\n }\n\n return -1;\n}\n\nfunction findCurrentTurnIndexByValue(\n history: readonly ModelMessage[],\n currentTurnMessage: ModelMessage\n): number {\n for (let index = history.length - 1; index >= 0; index -= 1) {\n if (modelMessageEquals(history[index], currentTurnMessage)) {\n return index;\n }\n }\n\n return -1;\n}\n\nfunction countMatchingMessages(\n history: readonly ModelMessage[],\n currentTurnMessage: ModelMessage\n): number {\n return history.filter((message) =>\n modelMessageEquals(message, currentTurnMessage)\n ).length;\n}\n\nfunction modelMessageEquals(\n left: ModelMessage | undefined,\n right: ModelMessage\n): boolean {\n return left !== undefined && modelContentEquals(left, right);\n}\n\nfunction modelContentEquals(left: unknown, right: unknown): boolean {\n const pending: [unknown, unknown][] = [[left, right]];\n const seen = new WeakMap<object, WeakSet<object>>();\n\n while (pending.length > 0) {\n const pair = pending.pop();\n if (!pair) {\n continue;\n }\n\n const [leftValue, rightValue] = pair;\n if (Object.is(leftValue, rightValue)) {\n continue;\n }\n\n if (Array.isArray(leftValue) || Array.isArray(rightValue)) {\n if (!arraysEqual(leftValue, rightValue, seen, pending)) {\n return false;\n }\n continue;\n }\n\n if (isRecord(leftValue) || isRecord(rightValue)) {\n if (!recordsEqual(leftValue, rightValue, seen, pending)) {\n return false;\n }\n continue;\n }\n\n return false;\n }\n\n return true;\n}\n\nfunction arraysEqual(\n left: unknown,\n right: unknown,\n seen: WeakMap<object, WeakSet<object>>,\n pending: [unknown, unknown][]\n): boolean {\n if (!(Array.isArray(left) && Array.isArray(right))) {\n return false;\n }\n\n if (isSeenPair(left, right, seen)) {\n return true;\n }\n\n const leftLength = arrayLength(left);\n const rightLength = arrayLength(right);\n if (\n leftLength === undefined ||\n rightLength === undefined ||\n leftLength !== rightLength\n ) {\n return false;\n }\n\n const leftKeys = enumerableKeys(left);\n const rightKeys = enumerableKeys(right);\n if (!(leftKeys && rightKeys && keysEqual(leftKeys, rightKeys))) {\n return false;\n }\n\n rememberPair(left, right, seen);\n for (const key of leftKeys) {\n if (!enqueuePropertyComparison(left, right, key, pending)) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction recordsEqual(\n left: unknown,\n right: unknown,\n seen: WeakMap<object, WeakSet<object>>,\n pending: [unknown, unknown][]\n): boolean {\n if (!(isRecord(left) && isRecord(right))) {\n return false;\n }\n\n if (isSeenPair(left, right, seen)) {\n return true;\n }\n\n const leftKeys = enumerableKeys(left);\n const rightKeys = enumerableKeys(right);\n if (!(leftKeys && rightKeys && keysEqual(leftKeys, rightKeys))) {\n return false;\n }\n\n rememberPair(left, right, seen);\n for (const key of leftKeys) {\n if (!enqueuePropertyComparison(left, right, key, pending)) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction enumerableKeys(value: object): readonly string[] | undefined {\n try {\n return Object.keys(value);\n } catch {\n return;\n }\n}\n\nfunction arrayLength(value: readonly unknown[]): number | undefined {\n try {\n return value.length;\n } catch {\n return;\n }\n}\n\nfunction keysEqual(\n leftKeys: readonly string[],\n rightKeys: readonly string[]\n): boolean {\n if (leftKeys.length !== rightKeys.length) {\n return false;\n }\n\n const rightKeySet = new Set(rightKeys);\n return leftKeys.every((key) => rightKeySet.has(key));\n}\n\nfunction enqueuePropertyComparison(\n left: object,\n right: object,\n key: string,\n pending: [unknown, unknown][]\n): boolean {\n const leftDescriptor = propertyDescriptor(left, key);\n const rightDescriptor = propertyDescriptor(right, key);\n if (!(leftDescriptor?.enumerable && rightDescriptor?.enumerable)) {\n return false;\n }\n\n const leftHasValue = \"value\" in leftDescriptor;\n const rightHasValue = \"value\" in rightDescriptor;\n if (leftHasValue || rightHasValue) {\n if (!(leftHasValue && rightHasValue)) {\n return false;\n }\n\n pending.push([leftDescriptor.value, rightDescriptor.value]);\n return true;\n }\n\n pending.push([leftDescriptor.get, rightDescriptor.get]);\n pending.push([leftDescriptor.set, rightDescriptor.set]);\n return true;\n}\n\nfunction propertyDescriptor(\n value: object,\n key: string\n): PropertyDescriptor | undefined {\n try {\n return Object.getOwnPropertyDescriptor(value, key);\n } catch {\n return;\n }\n}\n\nfunction isSeenPair(\n left: object,\n right: object,\n seen: WeakMap<object, WeakSet<object>>\n): boolean {\n return seen.get(left)?.has(right) ?? false;\n}\n\nfunction rememberPair(\n left: object,\n right: object,\n seen: WeakMap<object, WeakSet<object>>\n): void {\n const rights = seen.get(left);\n if (rights) {\n rights.add(right);\n return;\n }\n\n seen.set(left, new WeakSet([right]));\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n"],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ import { userInputToModelMessage } from "./mapping.js";
2
+ import { createCurrentTurnAnchor, resolveCurrentTurnIndex } from "./overlay-anchor.js";
3
+ import { normalizeAgentInput } from "./runtime-input.js";
4
+ //#region src/session/overlay.ts
5
+ let overlayCounter = 0;
6
+ var SessionOverlayState = class {
7
+ #activeFrame;
8
+ #activeInferenceStarted = false;
9
+ #activeStepEndOverlayInputAdded = false;
10
+ #activeTurn;
11
+ #pendingEntries = [];
12
+ appendActiveOverlay(input, placement) {
13
+ const activeFrame = this.#activeFrame;
14
+ if (!activeFrame) return;
15
+ const phase = this.#activeInferenceStarted ? "post-inference" : "pre-inference";
16
+ const entry = appendOverlay(activeFrame, input, placement, phase);
17
+ if (entry.placement === "step-end" && phase === "post-inference") this.#activeStepEndOverlayInputAdded = true;
18
+ return entry;
19
+ }
20
+ appendPendingOverlay(input) {
21
+ const frame = createInferenceFrame(this.#pendingEntries);
22
+ const entry = appendOverlay(frame, input, "idle", "pre-inference");
23
+ this.#pendingEntries = cloneOverlayEntries(frame.preInferenceContext);
24
+ return entry;
25
+ }
26
+ compose(history, canonicalHistory) {
27
+ return composeOverlayHistory({
28
+ canonicalHistory,
29
+ currentTurn: this.#activeTurn,
30
+ frame: this.#activeFrame,
31
+ history
32
+ });
33
+ }
34
+ consumeStepEndOverlayInputAdded() {
35
+ const added = this.#activeStepEndOverlayInputAdded;
36
+ this.#activeStepEndOverlayInputAdded = false;
37
+ return added;
38
+ }
39
+ expireActiveFrame(reason) {
40
+ const count = frameOverlayCount(this.#activeFrame);
41
+ if (count === 0) return;
42
+ this.#activeFrame = void 0;
43
+ return {
44
+ count,
45
+ reason,
46
+ type: "overlay-expired"
47
+ };
48
+ }
49
+ markInferenceStarted() {
50
+ this.#activeInferenceStarted = true;
51
+ }
52
+ resetActiveTurn() {
53
+ this.#activeFrame = void 0;
54
+ this.#activeInferenceStarted = false;
55
+ this.#activeStepEndOverlayInputAdded = false;
56
+ this.#activeTurn = void 0;
57
+ }
58
+ startTurn(input, priorHistory) {
59
+ const currentTurnMessage = userInputToModelMessage(input);
60
+ this.#activeFrame = createInferenceFrame(this.#pendingEntries);
61
+ this.#activeInferenceStarted = false;
62
+ this.#activeStepEndOverlayInputAdded = false;
63
+ this.#activeTurn = createCurrentTurnAnchor(priorHistory, currentTurnMessage);
64
+ this.#pendingEntries = [];
65
+ }
66
+ };
67
+ function createInferenceFrame(preInferenceContext = []) {
68
+ return {
69
+ postInferenceContext: [],
70
+ preInferenceContext: structuredClone([...preInferenceContext])
71
+ };
72
+ }
73
+ function appendOverlay(frame, input, placement, phase) {
74
+ const normalized = normalizeAgentInput(input);
75
+ const entry = {
76
+ id: `overlay-${++overlayCounter}`,
77
+ input: structuredClone(normalized),
78
+ message: userInputToModelMessage(normalized),
79
+ placement,
80
+ summary: summarizeOverlayInput(normalized)
81
+ };
82
+ if (phase === "pre-inference") {
83
+ frame.preInferenceContext.push(entry);
84
+ return entry;
85
+ }
86
+ frame.postInferenceContext.push(entry);
87
+ return entry;
88
+ }
89
+ function composeOverlayHistory({ canonicalHistory, currentTurn, frame, history }) {
90
+ if (!frame || frame.preInferenceContext.length === 0 && frame.postInferenceContext.length === 0) return structuredClone([...history]);
91
+ const snapshot = [...history];
92
+ const pre = frame.preInferenceContext.map((entry) => entry.message);
93
+ const post = frame.postInferenceContext.map((entry) => entry.message);
94
+ const resolvedCurrentTurnIndex = resolveCurrentTurnIndex({
95
+ canonicalHistory,
96
+ currentTurn,
97
+ history: snapshot
98
+ });
99
+ if (resolvedCurrentTurnIndex === -1) return structuredClone([
100
+ ...snapshot,
101
+ ...pre,
102
+ ...post
103
+ ]);
104
+ return structuredClone([
105
+ ...snapshot.slice(0, resolvedCurrentTurnIndex),
106
+ ...pre,
107
+ ...snapshot.slice(resolvedCurrentTurnIndex),
108
+ ...post
109
+ ]);
110
+ }
111
+ function frameOverlayCount(frame) {
112
+ return frame ? frame.preInferenceContext.length + frame.postInferenceContext.length : 0;
113
+ }
114
+ function cloneOverlayEntries(entries) {
115
+ return structuredClone([...entries]);
116
+ }
117
+ function summarizeOverlayInput(input) {
118
+ if (input.type === "user-text") {
119
+ const text = typeof input.text === "string" ? input.text : input.text.join("\n");
120
+ return {
121
+ preview: text ? "text" : "(empty message)",
122
+ textLength: text.length,
123
+ type: "user-text"
124
+ };
125
+ }
126
+ const text = input.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
127
+ return {
128
+ partCount: input.content.length,
129
+ preview: summarizeNonTextParts(input.content),
130
+ textLength: text.length,
131
+ type: "user-message"
132
+ };
133
+ }
134
+ function summarizeNonTextParts(parts) {
135
+ const kinds = parts.map((part) => part.type);
136
+ return kinds.length === 0 ? "(empty message)" : kinds.join(", ");
137
+ }
138
+ //#endregion
139
+ export { SessionOverlayState };
140
+
141
+ //# sourceMappingURL=overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay.js","names":["#activeFrame","#activeInferenceStarted","#activeStepEndOverlayInputAdded","#pendingEntries","#activeTurn"],"sources":["../../src/session/overlay.ts"],"sourcesContent":["import type { ModelMessage, UserModelMessage } from \"ai\";\nimport type { OverlayInputSummary, OverlayPlacement } from \"./events\";\nimport type { AgentInput, UserInput, UserMessageContentPart } from \"./input\";\nimport { userInputToModelMessage } from \"./mapping\";\nimport {\n type CurrentTurnAnchor,\n createCurrentTurnAnchor,\n resolveCurrentTurnIndex,\n} from \"./overlay-anchor\";\nimport { normalizeAgentInput } from \"./runtime-input\";\n\nexport type OverlayPhase = \"post-inference\" | \"pre-inference\";\n\nexport interface OverlayEntry {\n readonly id: string;\n readonly input: UserInput;\n readonly message: UserModelMessage;\n readonly placement: OverlayPlacement;\n readonly summary: OverlayInputSummary;\n}\n\nexport interface InferenceFrame {\n readonly postInferenceContext: OverlayEntry[];\n readonly preInferenceContext: OverlayEntry[];\n}\n\nexport interface OverlayExpiredEvent {\n readonly count: number;\n readonly reason: \"kill\" | \"turn-abort\" | \"turn-end\" | \"turn-error\";\n readonly type: \"overlay-expired\";\n}\n\nlet overlayCounter = 0;\n\nexport class SessionOverlayState {\n #activeFrame?: InferenceFrame;\n #activeInferenceStarted = false;\n #activeStepEndOverlayInputAdded = false;\n #activeTurn?: CurrentTurnAnchor;\n #pendingEntries: OverlayEntry[] = [];\n\n appendActiveOverlay(\n input: AgentInput,\n placement: OverlayPlacement\n ): OverlayEntry | undefined {\n const activeFrame = this.#activeFrame;\n if (!activeFrame) {\n return;\n }\n\n const phase = this.#activeInferenceStarted\n ? \"post-inference\"\n : \"pre-inference\";\n const entry = appendOverlay(activeFrame, input, placement, phase);\n if (entry.placement === \"step-end\" && phase === \"post-inference\") {\n this.#activeStepEndOverlayInputAdded = true;\n }\n return entry;\n }\n\n appendPendingOverlay(input: AgentInput): OverlayEntry {\n const frame = createInferenceFrame(this.#pendingEntries);\n const entry = appendOverlay(frame, input, \"idle\", \"pre-inference\");\n this.#pendingEntries = cloneOverlayEntries(frame.preInferenceContext);\n return entry;\n }\n\n compose(\n history: readonly ModelMessage[],\n canonicalHistory: readonly ModelMessage[]\n ): ModelMessage[] {\n return composeOverlayHistory({\n canonicalHistory,\n currentTurn: this.#activeTurn,\n frame: this.#activeFrame,\n history,\n });\n }\n\n consumeStepEndOverlayInputAdded(): boolean {\n const added = this.#activeStepEndOverlayInputAdded;\n this.#activeStepEndOverlayInputAdded = false;\n return added;\n }\n\n expireActiveFrame(\n reason: OverlayExpiredEvent[\"reason\"]\n ): OverlayExpiredEvent | undefined {\n const count = frameOverlayCount(this.#activeFrame);\n if (count === 0) {\n return;\n }\n\n this.#activeFrame = undefined;\n return { count, reason, type: \"overlay-expired\" };\n }\n\n markInferenceStarted(): void {\n this.#activeInferenceStarted = true;\n }\n\n resetActiveTurn(): void {\n this.#activeFrame = undefined;\n this.#activeInferenceStarted = false;\n this.#activeStepEndOverlayInputAdded = false;\n this.#activeTurn = undefined;\n }\n\n startTurn(input: UserInput, priorHistory: readonly ModelMessage[]): void {\n const currentTurnMessage = userInputToModelMessage(input);\n this.#activeFrame = createInferenceFrame(this.#pendingEntries);\n this.#activeInferenceStarted = false;\n this.#activeStepEndOverlayInputAdded = false;\n this.#activeTurn = createCurrentTurnAnchor(\n priorHistory,\n currentTurnMessage\n );\n this.#pendingEntries = [];\n }\n}\n\nexport function createInferenceFrame(\n preInferenceContext: readonly OverlayEntry[] = []\n): InferenceFrame {\n return {\n postInferenceContext: [],\n preInferenceContext: structuredClone([...preInferenceContext]),\n };\n}\n\nexport function appendOverlay(\n frame: InferenceFrame,\n input: AgentInput,\n placement: OverlayPlacement,\n phase: OverlayPhase\n): OverlayEntry {\n const normalized = normalizeAgentInput(input);\n const entry = {\n id: `overlay-${++overlayCounter}`,\n input: structuredClone(normalized),\n message: userInputToModelMessage(normalized),\n placement,\n summary: summarizeOverlayInput(normalized),\n };\n\n if (phase === \"pre-inference\") {\n frame.preInferenceContext.push(entry);\n return entry;\n }\n\n frame.postInferenceContext.push(entry);\n return entry;\n}\n\nexport function composeOverlayHistory({\n canonicalHistory,\n currentTurn,\n frame,\n history,\n}: {\n readonly canonicalHistory?: readonly ModelMessage[];\n readonly currentTurn?: CurrentTurnAnchor;\n readonly frame?: InferenceFrame;\n readonly history: readonly ModelMessage[];\n}): ModelMessage[] {\n if (\n !frame ||\n (frame.preInferenceContext.length === 0 &&\n frame.postInferenceContext.length === 0)\n ) {\n return structuredClone([...history]);\n }\n\n const snapshot = [...history];\n const pre = frame.preInferenceContext.map((entry) => entry.message);\n const post = frame.postInferenceContext.map((entry) => entry.message);\n const resolvedCurrentTurnIndex = resolveCurrentTurnIndex({\n canonicalHistory,\n currentTurn,\n history: snapshot,\n });\n\n if (resolvedCurrentTurnIndex === -1) {\n return structuredClone([...snapshot, ...pre, ...post]);\n }\n\n return structuredClone([\n ...snapshot.slice(0, resolvedCurrentTurnIndex),\n ...pre,\n ...snapshot.slice(resolvedCurrentTurnIndex),\n ...post,\n ]);\n}\n\nexport function frameOverlayCount(frame: InferenceFrame | undefined): number {\n return frame\n ? frame.preInferenceContext.length + frame.postInferenceContext.length\n : 0;\n}\n\nexport function cloneOverlayEntries(\n entries: readonly OverlayEntry[]\n): OverlayEntry[] {\n return structuredClone([...entries]);\n}\n\nfunction summarizeOverlayInput(input: UserInput): OverlayInputSummary {\n if (input.type === \"user-text\") {\n const text =\n typeof input.text === \"string\" ? input.text : input.text.join(\"\\n\");\n return {\n preview: text ? \"text\" : \"(empty message)\",\n textLength: text.length,\n type: \"user-text\",\n };\n }\n\n const text = input.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\\n\");\n return {\n partCount: input.content.length,\n preview: summarizeNonTextParts(input.content),\n textLength: text.length,\n type: \"user-message\",\n };\n}\n\nfunction summarizeNonTextParts(\n parts: readonly UserMessageContentPart[]\n): string {\n const kinds = parts.map((part) => part.type);\n return kinds.length === 0 ? \"(empty message)\" : kinds.join(\", \");\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,89 @@
1
+ //#region src/session/runtime-input.ts
2
+ function createRuntimeInputState() {
3
+ return {
4
+ pending: Promise.resolve(),
5
+ queue: []
6
+ };
7
+ }
8
+ function addRuntimeInput(runtimeInput, input) {
9
+ const next = runtimeInput.pending.then(() => {
10
+ if (runtimeInput.closedReason) throw runtimeInputClosedError(runtimeInput.closedReason);
11
+ runtimeInput.queue.push({
12
+ input: normalizeAgentInput(input),
13
+ placement: runtimeInput.steerPlacement ?? runtimeInput.placement ?? "step-end"
14
+ });
15
+ });
16
+ runtimeInput.pending = next.catch(() => void 0);
17
+ return next;
18
+ }
19
+ function closeRuntimeInput(runtimeInput, reason = "the run reached a terminal state") {
20
+ if (!runtimeInput?.closedReason && runtimeInput) {
21
+ runtimeInput.closedReason = reason;
22
+ runtimeInput.placement = void 0;
23
+ }
24
+ }
25
+ function shiftRuntimeInput(runtimeInput, placement) {
26
+ const index = runtimeInput.queue.findIndex((input) => input.placement === placement);
27
+ if (index === -1) return;
28
+ return runtimeInput.queue.splice(index, 1)[0];
29
+ }
30
+ function normalizeAgentInput(input) {
31
+ if (typeof input === "string") return {
32
+ type: "user-text",
33
+ text: input
34
+ };
35
+ if (isStringArrayInput(input)) return {
36
+ type: "user-text",
37
+ text: structuredClone(input)
38
+ };
39
+ if (isArrayInput(input)) {
40
+ assertUserMessageContent(input);
41
+ return {
42
+ type: "user-message",
43
+ content: structuredClone(input)
44
+ };
45
+ }
46
+ if (isUserMessage(input)) {
47
+ assertUserMessageContent(input.content);
48
+ assertUserMessageMetadata(input.metadata);
49
+ }
50
+ return structuredClone(input);
51
+ }
52
+ function isStringArrayInput(input) {
53
+ return isArrayInput(input) && input.every((part) => typeof part === "string");
54
+ }
55
+ function isArrayInput(input) {
56
+ return Array.isArray(input);
57
+ }
58
+ function isUserMessage(input) {
59
+ return input.type === "user-message";
60
+ }
61
+ function assertUserMessageContent(input) {
62
+ for (const part of input) if (!isUserMessageContentPart(part)) throw new TypeError("Agent input content parts must be { type: \"text\", text }, { type: \"image\", image }, or { type: \"file\", data, mediaType }.");
63
+ }
64
+ function assertUserMessageMetadata(metadata) {
65
+ if (metadata !== void 0 && (metadata === null || typeof metadata !== "object" || Array.isArray(metadata))) throw new TypeError("Agent input metadata must be an object when provided.");
66
+ }
67
+ function isUserMessageContentPart(part) {
68
+ if (part === null || typeof part !== "object" || !("type" in part)) return false;
69
+ if (part.type === "text") return "text" in part && typeof part.text === "string";
70
+ if (part.type === "image") return "image" in part && typeof part.image === "string" && (!("mediaType" in part) || typeof part.mediaType === "string");
71
+ if (part.type === "file") return "data" in part && isUserMessageFileData(part.data) && "mediaType" in part && typeof part.mediaType === "string" && (!("filename" in part) || typeof part.filename === "string");
72
+ return false;
73
+ }
74
+ function isUserMessageFileData(data) {
75
+ if (typeof data === "string") return true;
76
+ if (data === null || typeof data !== "object" || !("type" in data)) return false;
77
+ if (data.type === "data") return "data" in data && typeof data.data === "string";
78
+ if (data.type === "reference") return "reference" in data && data.reference !== null && typeof data.reference === "object" && Object.values(data.reference).every((value) => typeof value === "string");
79
+ if (data.type === "text") return "text" in data && typeof data.text === "string";
80
+ if (data.type === "url") return "url" in data && typeof data.url === "string";
81
+ return false;
82
+ }
83
+ function runtimeInputClosedError(reason) {
84
+ return /* @__PURE__ */ new Error(`session.steer() cannot be used after ${reason}`);
85
+ }
86
+ //#endregion
87
+ export { addRuntimeInput, closeRuntimeInput, createRuntimeInputState, normalizeAgentInput, shiftRuntimeInput };
88
+
89
+ //# sourceMappingURL=runtime-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-input.js","names":[],"sources":["../../src/session/runtime-input.ts"],"sourcesContent":["import type {\n RuntimeInput,\n UserMessage,\n UserMessageContentPart,\n} from \"./events\";\nimport type { AgentInput, UserInput } from \"./input\";\n\nexport type RuntimeInputPlacement = RuntimeInput[\"placement\"];\n\nexport interface QueuedRuntimeInput {\n readonly input: UserInput;\n readonly placement: RuntimeInputPlacement;\n}\n\nexport interface RuntimeInputState {\n closedReason?: string;\n pending: Promise<void>;\n placement?: RuntimeInputPlacement;\n readonly queue: QueuedRuntimeInput[];\n steerPlacement?: RuntimeInputPlacement;\n}\n\nexport function createRuntimeInputState(): RuntimeInputState {\n return {\n pending: Promise.resolve(),\n queue: [],\n };\n}\n\nexport function addRuntimeInput(\n runtimeInput: RuntimeInputState,\n input: AgentInput\n): Promise<void> {\n const next = runtimeInput.pending.then(() => {\n if (runtimeInput.closedReason) {\n throw runtimeInputClosedError(runtimeInput.closedReason);\n }\n\n runtimeInput.queue.push({\n input: normalizeAgentInput(input),\n placement:\n runtimeInput.steerPlacement ?? runtimeInput.placement ?? \"step-end\",\n });\n });\n runtimeInput.pending = next.catch(() => undefined);\n return next;\n}\n\nexport function closeRuntimeInput(\n runtimeInput: RuntimeInputState | undefined,\n reason = \"the run reached a terminal state\"\n): void {\n if (!runtimeInput?.closedReason && runtimeInput) {\n runtimeInput.closedReason = reason;\n runtimeInput.placement = undefined;\n }\n}\n\nexport function shiftRuntimeInput(\n runtimeInput: RuntimeInputState,\n placement: RuntimeInputPlacement\n): QueuedRuntimeInput | undefined {\n const index = runtimeInput.queue.findIndex(\n (input) => input.placement === placement\n );\n if (index === -1) {\n return;\n }\n\n return runtimeInput.queue.splice(index, 1)[0];\n}\n\nexport function normalizeAgentInput(input: AgentInput): UserInput {\n if (typeof input === \"string\") {\n return {\n type: \"user-text\",\n text: input,\n };\n }\n\n if (isStringArrayInput(input)) {\n return {\n type: \"user-text\",\n text: structuredClone(input) as readonly string[],\n };\n }\n\n if (isArrayInput(input)) {\n assertUserMessageContent(input);\n return {\n type: \"user-message\",\n content: structuredClone(input) as readonly UserMessageContentPart[],\n };\n }\n\n if (isUserMessage(input)) {\n assertUserMessageContent(input.content);\n assertUserMessageMetadata(input.metadata);\n }\n\n return structuredClone(input);\n}\n\nfunction isStringArrayInput(input: AgentInput): input is readonly string[] {\n return isArrayInput(input) && input.every((part) => typeof part === \"string\");\n}\n\nfunction isArrayInput(\n input: AgentInput\n): input is readonly string[] | readonly UserMessageContentPart[] {\n return Array.isArray(input);\n}\n\nfunction isUserMessage(input: UserInput): input is UserMessage {\n return input.type === \"user-message\";\n}\n\nfunction assertUserMessageContent(\n input: readonly unknown[]\n): asserts input is readonly UserMessageContentPart[] {\n for (const part of input) {\n if (!isUserMessageContentPart(part)) {\n throw new TypeError(\n 'Agent input content parts must be { type: \"text\", text }, { type: \"image\", image }, or { type: \"file\", data, mediaType }.'\n );\n }\n }\n}\n\nfunction assertUserMessageMetadata(metadata: unknown): void {\n if (\n metadata !== undefined &&\n (metadata === null ||\n typeof metadata !== \"object\" ||\n Array.isArray(metadata))\n ) {\n throw new TypeError(\n \"Agent input metadata must be an object when provided.\"\n );\n }\n}\n\nfunction isUserMessageContentPart(\n part: unknown\n): part is UserMessageContentPart {\n if (part === null || typeof part !== \"object\" || !(\"type\" in part)) {\n return false;\n }\n\n if (part.type === \"text\") {\n return \"text\" in part && typeof part.text === \"string\";\n }\n\n if (part.type === \"image\") {\n return (\n \"image\" in part &&\n typeof part.image === \"string\" &&\n (!(\"mediaType\" in part) || typeof part.mediaType === \"string\")\n );\n }\n\n if (part.type === \"file\") {\n return (\n \"data\" in part &&\n isUserMessageFileData(part.data) &&\n \"mediaType\" in part &&\n typeof part.mediaType === \"string\" &&\n (!(\"filename\" in part) || typeof part.filename === \"string\")\n );\n }\n\n return false;\n}\n\nfunction isUserMessageFileData(data: unknown): boolean {\n if (typeof data === \"string\") {\n return true;\n }\n\n if (data === null || typeof data !== \"object\" || !(\"type\" in data)) {\n return false;\n }\n\n if (data.type === \"data\") {\n return \"data\" in data && typeof data.data === \"string\";\n }\n\n if (data.type === \"reference\") {\n return (\n \"reference\" in data &&\n data.reference !== null &&\n typeof data.reference === \"object\" &&\n Object.values(data.reference).every((value) => typeof value === \"string\")\n );\n }\n\n if (data.type === \"text\") {\n return \"text\" in data && typeof data.text === \"string\";\n }\n\n if (data.type === \"url\") {\n return \"url\" in data && typeof data.url === \"string\";\n }\n\n return false;\n}\n\nfunction runtimeInputClosedError(reason: string): Error {\n return new Error(`session.steer() cannot be used after ${reason}`);\n}\n"],"mappings":"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"}