@agentuity/opencode 1.0.15 → 1.0.17

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 (137) hide show
  1. package/dist/agents/architect.d.ts +1 -1
  2. package/dist/agents/architect.d.ts.map +1 -1
  3. package/dist/agents/architect.js +30 -33
  4. package/dist/agents/architect.js.map +1 -1
  5. package/dist/agents/builder.d.ts +1 -1
  6. package/dist/agents/builder.d.ts.map +1 -1
  7. package/dist/agents/builder.js +53 -60
  8. package/dist/agents/builder.js.map +1 -1
  9. package/dist/agents/expert-backend.d.ts +1 -1
  10. package/dist/agents/expert-backend.d.ts.map +1 -1
  11. package/dist/agents/expert-backend.js +32 -40
  12. package/dist/agents/expert-backend.js.map +1 -1
  13. package/dist/agents/expert-frontend.d.ts +1 -1
  14. package/dist/agents/expert-frontend.d.ts.map +1 -1
  15. package/dist/agents/expert-frontend.js +18 -24
  16. package/dist/agents/expert-frontend.js.map +1 -1
  17. package/dist/agents/expert-ops.d.ts +1 -1
  18. package/dist/agents/expert-ops.d.ts.map +1 -1
  19. package/dist/agents/expert-ops.js +37 -51
  20. package/dist/agents/expert-ops.js.map +1 -1
  21. package/dist/agents/expert.d.ts +1 -1
  22. package/dist/agents/expert.d.ts.map +1 -1
  23. package/dist/agents/expert.js +33 -43
  24. package/dist/agents/expert.js.map +1 -1
  25. package/dist/agents/lead.d.ts +1 -1
  26. package/dist/agents/lead.d.ts.map +1 -1
  27. package/dist/agents/lead.js +179 -222
  28. package/dist/agents/lead.js.map +1 -1
  29. package/dist/agents/memory.d.ts +1 -1
  30. package/dist/agents/memory.d.ts.map +1 -1
  31. package/dist/agents/memory.js +62 -90
  32. package/dist/agents/memory.js.map +1 -1
  33. package/dist/agents/monitor.d.ts +1 -1
  34. package/dist/agents/monitor.d.ts.map +1 -1
  35. package/dist/agents/monitor.js +84 -44
  36. package/dist/agents/monitor.js.map +1 -1
  37. package/dist/agents/product.d.ts +1 -1
  38. package/dist/agents/product.d.ts.map +1 -1
  39. package/dist/agents/product.js +16 -22
  40. package/dist/agents/product.js.map +1 -1
  41. package/dist/agents/reviewer.d.ts +1 -1
  42. package/dist/agents/reviewer.d.ts.map +1 -1
  43. package/dist/agents/reviewer.js +15 -27
  44. package/dist/agents/reviewer.js.map +1 -1
  45. package/dist/agents/runner.d.ts +1 -1
  46. package/dist/agents/runner.d.ts.map +1 -1
  47. package/dist/agents/runner.js +52 -76
  48. package/dist/agents/runner.js.map +1 -1
  49. package/dist/agents/scout.d.ts +1 -1
  50. package/dist/agents/scout.d.ts.map +1 -1
  51. package/dist/agents/scout.js +42 -43
  52. package/dist/agents/scout.js.map +1 -1
  53. package/dist/agents/types.d.ts +8 -0
  54. package/dist/agents/types.d.ts.map +1 -1
  55. package/dist/background/manager.d.ts +18 -0
  56. package/dist/background/manager.d.ts.map +1 -1
  57. package/dist/background/manager.js +201 -33
  58. package/dist/background/manager.js.map +1 -1
  59. package/dist/background/types.d.ts +3 -0
  60. package/dist/background/types.d.ts.map +1 -1
  61. package/dist/config/loader.js +2 -2
  62. package/dist/plugin/hooks/cadence.d.ts +3 -1
  63. package/dist/plugin/hooks/cadence.d.ts.map +1 -1
  64. package/dist/plugin/hooks/cadence.js +167 -70
  65. package/dist/plugin/hooks/cadence.js.map +1 -1
  66. package/dist/plugin/hooks/compaction-utils.d.ts +48 -0
  67. package/dist/plugin/hooks/compaction-utils.d.ts.map +1 -0
  68. package/dist/plugin/hooks/compaction-utils.js +259 -0
  69. package/dist/plugin/hooks/compaction-utils.js.map +1 -0
  70. package/dist/plugin/hooks/completion.d.ts +14 -0
  71. package/dist/plugin/hooks/completion.d.ts.map +1 -0
  72. package/dist/plugin/hooks/completion.js +45 -0
  73. package/dist/plugin/hooks/completion.js.map +1 -0
  74. package/dist/plugin/hooks/params.d.ts +47 -2
  75. package/dist/plugin/hooks/params.d.ts.map +1 -1
  76. package/dist/plugin/hooks/params.js +82 -1
  77. package/dist/plugin/hooks/params.js.map +1 -1
  78. package/dist/plugin/hooks/session-memory.d.ts +2 -1
  79. package/dist/plugin/hooks/session-memory.d.ts.map +1 -1
  80. package/dist/plugin/hooks/session-memory.js +101 -48
  81. package/dist/plugin/hooks/session-memory.js.map +1 -1
  82. package/dist/plugin/hooks/tools.d.ts.map +1 -1
  83. package/dist/plugin/hooks/tools.js +26 -1
  84. package/dist/plugin/hooks/tools.js.map +1 -1
  85. package/dist/plugin/plugin.d.ts.map +1 -1
  86. package/dist/plugin/plugin.js +38 -9
  87. package/dist/plugin/plugin.js.map +1 -1
  88. package/dist/sqlite/index.d.ts +1 -1
  89. package/dist/sqlite/index.d.ts.map +1 -1
  90. package/dist/sqlite/queries.d.ts +1 -0
  91. package/dist/sqlite/queries.d.ts.map +1 -1
  92. package/dist/sqlite/queries.js +4 -0
  93. package/dist/sqlite/queries.js.map +1 -1
  94. package/dist/sqlite/reader.d.ts +11 -1
  95. package/dist/sqlite/reader.d.ts.map +1 -1
  96. package/dist/sqlite/reader.js +62 -0
  97. package/dist/sqlite/reader.js.map +1 -1
  98. package/dist/sqlite/types.d.ts +40 -0
  99. package/dist/sqlite/types.d.ts.map +1 -1
  100. package/dist/tools/background.d.ts.map +1 -1
  101. package/dist/tools/background.js +15 -0
  102. package/dist/tools/background.js.map +1 -1
  103. package/dist/types.d.ts +46 -0
  104. package/dist/types.d.ts.map +1 -1
  105. package/dist/types.js +10 -0
  106. package/dist/types.js.map +1 -1
  107. package/package.json +3 -3
  108. package/src/agents/architect.ts +30 -33
  109. package/src/agents/builder.ts +53 -60
  110. package/src/agents/expert-backend.ts +32 -40
  111. package/src/agents/expert-frontend.ts +18 -24
  112. package/src/agents/expert-ops.ts +37 -51
  113. package/src/agents/expert.ts +33 -43
  114. package/src/agents/lead.ts +179 -222
  115. package/src/agents/memory.ts +62 -90
  116. package/src/agents/monitor.ts +84 -44
  117. package/src/agents/product.ts +16 -22
  118. package/src/agents/reviewer.ts +15 -27
  119. package/src/agents/runner.ts +52 -76
  120. package/src/agents/scout.ts +42 -43
  121. package/src/agents/types.ts +8 -0
  122. package/src/background/manager.ts +227 -38
  123. package/src/background/types.ts +3 -0
  124. package/src/config/loader.ts +2 -2
  125. package/src/plugin/hooks/cadence.ts +188 -74
  126. package/src/plugin/hooks/compaction-utils.ts +291 -0
  127. package/src/plugin/hooks/completion.ts +61 -0
  128. package/src/plugin/hooks/params.ts +107 -2
  129. package/src/plugin/hooks/session-memory.ts +113 -47
  130. package/src/plugin/hooks/tools.ts +32 -1
  131. package/src/plugin/plugin.ts +54 -10
  132. package/src/sqlite/index.ts +4 -0
  133. package/src/sqlite/queries.ts +5 -0
  134. package/src/sqlite/reader.ts +69 -0
  135. package/src/sqlite/types.ts +40 -0
  136. package/src/tools/background.ts +28 -0
  137. package/src/types.ts +40 -0
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Get the current git branch name.
3
+ * Moved here from cadence.ts and session-memory.ts to deduplicate.
4
+ */
5
+ export async function getCurrentBranch() {
6
+ try {
7
+ const proc = Bun.spawn(['git', 'branch', '--show-current'], {
8
+ stdout: 'pipe',
9
+ stderr: 'pipe',
10
+ });
11
+ const stdout = await new Response(proc.stdout).text();
12
+ await proc.exited;
13
+ return stdout.trim() || 'unknown';
14
+ }
15
+ catch {
16
+ return 'unknown';
17
+ }
18
+ }
19
+ /**
20
+ * Access Agentuity KV storage via CLI.
21
+ * All calls are wrapped in try/catch — returns null on failure.
22
+ */
23
+ async function kvGet(namespace, key) {
24
+ try {
25
+ const proc = Bun.spawn(['agentuity', 'cloud', 'kv', 'get', namespace, key, '--json'], {
26
+ stdout: 'pipe',
27
+ stderr: 'pipe',
28
+ });
29
+ const output = await new Response(proc.stdout).text();
30
+ const exitCode = await proc.exited;
31
+ if (exitCode !== 0)
32
+ return null;
33
+ return JSON.parse(output);
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ async function kvSet(namespace, key, value) {
40
+ try {
41
+ const proc = Bun.spawn(['agentuity', 'cloud', 'kv', 'set', namespace, key, JSON.stringify(value)], { stdout: 'pipe', stderr: 'pipe' });
42
+ const exitCode = await proc.exited;
43
+ return exitCode === 0;
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ /**
50
+ * Build the custom compaction prompt for our agent system.
51
+ * This REPLACES the default OpenCode compaction prompt via output.prompt.
52
+ */
53
+ export function buildCustomCompactionPrompt(mode) {
54
+ const cadenceSection = mode === 'cadence'
55
+ ? `
56
+
57
+ ## Cadence Loop State
58
+ - Loop ID, iteration number, max iterations
59
+ - Current phase and what's in progress
60
+ - Whether this is a Lead-of-Leads session with child tasks`
61
+ : '';
62
+ return `You are generating a continuation context for a multi-agent coding system (Agentuity Coder). Your summary will be the ONLY context the orchestrating Lead agent has after this compaction. Preserve everything needed for seamless continuation.
63
+
64
+ ## CRITICAL — Preserve These Verbatim
65
+ 1. The current task/objective (quote the user's original request exactly)
66
+ 2. All background task IDs (bg_xxx) with status, purpose, and session IDs
67
+ 3. Active planning state: current phase, completed phases, next steps, blockers
68
+ 4. ALL file paths being actively worked on (with role: created/modified/read)
69
+ 5. Key decisions made and their rationale
70
+ 6. Any corrections or gotchas discovered during the session
71
+ 7. Todo list state (what's done, in progress, pending)
72
+ 8. Descriptions of any images or attachments that appeared in conversation${cadenceSection}
73
+
74
+ ## Structure Your Summary As:
75
+
76
+ ### Active Task
77
+ [Verbatim objective + what the agent was doing when compaction fired]
78
+
79
+ ### Planning State
80
+ [Phases with status. Include phase notes, not just titles.]
81
+
82
+ ### Background Tasks
83
+ [bg_xxx: description → status (running/completed/errored). Include session IDs.]
84
+
85
+ ### Key Context
86
+ [Decisions, constraints, user preferences, corrections discovered]
87
+
88
+ ### Active Files
89
+ [filepath → role (creating/modifying/reading) + what's being done to it]
90
+
91
+ ### Images & Attachments
92
+ [Describe any images/screenshots: what they showed, when they appeared, why they mattered]
93
+
94
+ ### Next Steps
95
+ [What should happen immediately after compaction resumes]
96
+
97
+ ## Rules
98
+ - Use specific file paths, task IDs, phase names — NOT vague references.
99
+ - State what tools returned, not just that they were called.
100
+ - NEVER drop background task references — the agent MUST know what's still running.
101
+ - Prefer completeness over brevity — this is the agent's entire working memory.`;
102
+ }
103
+ /**
104
+ * Fetch planning state from KV and format as markdown.
105
+ * Returns null if KV is unavailable or no planning state exists.
106
+ */
107
+ export async function fetchAndFormatPlanningState(sessionId) {
108
+ try {
109
+ const record = await kvGet('agentuity-opencode-memory', `session:${sessionId}`);
110
+ if (!record || typeof record !== 'object')
111
+ return null;
112
+ const data = record.data ?? record;
113
+ const planning = data.planning;
114
+ if (!planning)
115
+ return null;
116
+ const lines = ['## Planning State (from KV)'];
117
+ if (planning.objective)
118
+ lines.push(`**Objective:** ${planning.objective}`);
119
+ if (planning.current)
120
+ lines.push(`**Current:** ${planning.current}`);
121
+ if (planning.next)
122
+ lines.push(`**Next:** ${planning.next}`);
123
+ const phases = planning.phases;
124
+ if (phases?.length) {
125
+ lines.push('', '### Phases:');
126
+ for (const p of phases) {
127
+ const status = p.status ?? 'unknown';
128
+ const title = p.title ?? p.content ?? 'untitled';
129
+ const notes = p.notes ? ` — ${String(p.notes).slice(0, 100)}` : '';
130
+ lines.push(`- [${status}] ${title}${notes}`);
131
+ }
132
+ }
133
+ const findings = planning.findings;
134
+ if (findings?.length) {
135
+ lines.push('', '### Key Findings:');
136
+ for (const f of findings.slice(0, 5)) {
137
+ lines.push(`- ${String(f).slice(0, 150)}`);
138
+ }
139
+ }
140
+ const errors = planning.errors;
141
+ if (errors?.length) {
142
+ lines.push('', '### Errors to Avoid:');
143
+ for (const e of errors.slice(0, 3)) {
144
+ lines.push(`- ${String(e).slice(0, 150)}`);
145
+ }
146
+ }
147
+ return lines.join('\n');
148
+ }
149
+ catch {
150
+ return null;
151
+ }
152
+ }
153
+ /**
154
+ * Get image/attachment descriptions from SQLite for compaction context.
155
+ * Returns brief metadata about non-text parts in the conversation.
156
+ */
157
+ export function getImageDescriptions(dbReader, sessionId) {
158
+ if (!dbReader?.isAvailable())
159
+ return null;
160
+ try {
161
+ const parts = dbReader.getNonTextParts(sessionId);
162
+ if (!parts.length)
163
+ return null;
164
+ // Filter to image-like parts (not tool calls — those are separate)
165
+ const imageParts = parts.filter((p) => !['tool-invocation', 'tool-result', 'text'].includes(p.type));
166
+ if (!imageParts.length)
167
+ return null;
168
+ const lines = ['## Images & Attachments'];
169
+ for (const part of imageParts.slice(0, 10)) {
170
+ const when = part.timestamp ? ` at ${part.timestamp}` : '';
171
+ lines.push(`- [${part.type}]${when}: message ${part.messageId}`);
172
+ }
173
+ return lines.join('\n');
174
+ }
175
+ catch {
176
+ return null;
177
+ }
178
+ }
179
+ /**
180
+ * Get recent tool call summaries for compaction context.
181
+ * CONCISE — capped at limit calls, brief descriptions only.
182
+ */
183
+ export function getRecentToolCallSummaries(dbReader, sessionId, limit = 5) {
184
+ if (!dbReader?.isAvailable() || limit <= 0)
185
+ return null;
186
+ try {
187
+ const calls = dbReader.getRecentToolCalls(sessionId, limit);
188
+ if (!calls.length)
189
+ return null;
190
+ const lines = ['## Recent Tool Activity'];
191
+ for (const call of calls) {
192
+ const inputBrief = call.input ? ` — ${String(call.input).slice(0, 80)}` : '';
193
+ const outputBrief = call.output ? ` → ${String(call.output).slice(0, 80)}` : '';
194
+ lines.push(`- ${call.toolName}${inputBrief}${outputBrief}`);
195
+ }
196
+ return lines.join('\n');
197
+ }
198
+ catch {
199
+ return null;
200
+ }
201
+ }
202
+ /**
203
+ * Store a pre-compaction snapshot to KV as a recovery mechanism.
204
+ */
205
+ export async function storePreCompactionSnapshot(sessionId, snapshot) {
206
+ try {
207
+ await kvSet('agentuity-opencode-memory', `compaction:snapshot:${sessionId}`, snapshot);
208
+ }
209
+ catch {
210
+ // Silently fail — this is a best-effort recovery mechanism
211
+ }
212
+ }
213
+ /**
214
+ * Persist Cadence session state to KV for recovery after plugin restart.
215
+ */
216
+ export async function persistCadenceStateToKV(sessionId, state) {
217
+ try {
218
+ await kvSet('agentuity-opencode-memory', `cadence:active:${sessionId}`, state);
219
+ }
220
+ catch {
221
+ // Silently fail
222
+ }
223
+ }
224
+ /**
225
+ * Restore Cadence session state from KV.
226
+ */
227
+ export async function restoreCadenceStateFromKV(sessionId) {
228
+ try {
229
+ const state = await kvGet('agentuity-opencode-memory', `cadence:active:${sessionId}`);
230
+ return state;
231
+ }
232
+ catch {
233
+ return null;
234
+ }
235
+ }
236
+ /**
237
+ * Format compaction diagnostics — brief summary of what was preserved.
238
+ */
239
+ export function formatCompactionDiagnostics(stats) {
240
+ const parts = [];
241
+ if (stats.planningPhasesCount > 0)
242
+ parts.push(`${stats.planningPhasesCount} planning phases`);
243
+ if (stats.backgroundTasksCount > 0)
244
+ parts.push(`${stats.backgroundTasksCount} background tasks`);
245
+ if (stats.imageDescriptionsCount > 0)
246
+ parts.push(`${stats.imageDescriptionsCount} image refs`);
247
+ if (stats.toolCallSummariesCount > 0)
248
+ parts.push(`${stats.toolCallSummariesCount} tool calls`);
249
+ if (!parts.length)
250
+ return '';
251
+ return `> **Compaction preserved:** ${parts.join(', ')} (~${stats.estimatedTokens} tokens injected)`;
252
+ }
253
+ /** Count markdown list items in a string */
254
+ export function countListItems(s) {
255
+ if (!s)
256
+ return 0;
257
+ return (s.match(/^- /gm) ?? []).length;
258
+ }
259
+ //# sourceMappingURL=compaction-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction-utils.js","sourceRoot":"","sources":["../../../src/plugin/hooks/compaction-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ import type { CoderConfig } from '../../types';
3
+ export interface CompletionHooks {
4
+ onParams: (input: unknown) => void;
5
+ onMessage: (input: unknown) => void;
6
+ }
7
+ /**
8
+ * Creates hooks for logging agent completion metrics.
9
+ *
10
+ * Tracks the start of each LLM call (via chat.params) and logs
11
+ * agent name, model, and duration when the response arrives (via chat.message).
12
+ */
13
+ export declare function createCompletionHooks(ctx: PluginInput, _config: CoderConfig): CompletionHooks;
14
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/completion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,eAAe,CA8C7F"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Creates hooks for logging agent completion metrics.
3
+ *
4
+ * Tracks the start of each LLM call (via chat.params) and logs
5
+ * agent name, model, and duration when the response arrives (via chat.message).
6
+ */
7
+ export function createCompletionHooks(ctx, _config) {
8
+ const startTimes = new Map();
9
+ return {
10
+ onParams(input) {
11
+ const inp = input;
12
+ if (!inp.sessionID)
13
+ return;
14
+ startTimes.set(inp.sessionID, {
15
+ startedAt: Date.now(),
16
+ agent: inp.agent,
17
+ model: inp.model,
18
+ });
19
+ },
20
+ onMessage(input) {
21
+ const inp = input;
22
+ if (!inp.sessionID)
23
+ return;
24
+ const start = startTimes.get(inp.sessionID);
25
+ if (!start)
26
+ return;
27
+ const durationMs = Date.now() - start.startedAt;
28
+ const durationSec = (durationMs / 1000).toFixed(1);
29
+ const logLine = `Completion: agent=${start.agent ?? 'unknown'} model=${start.model ?? 'unknown'} duration=${durationSec}s`;
30
+ // Verbose local logging for immediate visibility
31
+ console.debug(`[agentuity-coder] ${logLine}`);
32
+ // Also send to the OpenCode log service
33
+ ctx.client.app.log({
34
+ body: {
35
+ service: 'agentuity-coder',
36
+ level: 'debug',
37
+ message: logLine,
38
+ },
39
+ });
40
+ // Clean up after logging
41
+ startTimes.delete(inp.sessionID);
42
+ },
43
+ };
44
+ }
45
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../src/plugin/hooks/completion.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAgB,EAAE,OAAoB;IAC3E,MAAM,UAAU,GAAG,IAAI,GAAG,EAAiE,CAAC;IAE5F,OAAO;QACN,QAAQ,CAAC,KAAc;YACtB,MAAM,GAAG,GAAG,KAIX,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,SAAS;gBAAE,OAAO;YAC3B,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE;gBAC7B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,KAAK,EAAE,GAAG,CAAC,KAAK;aAChB,CAAC,CAAC;QACJ,CAAC;QAED,SAAS,CAAC,KAAc;YACvB,MAAM,GAAG,GAAG,KAA+B,CAAC;YAC5C,IAAI,CAAC,GAAG,CAAC,SAAS;gBAAE,OAAO;YAE3B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC5C,IAAI,CAAC,KAAK;gBAAE,OAAO;YAEnB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;YAChD,MAAM,WAAW,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAEnD,MAAM,OAAO,GAAG,qBAAqB,KAAK,CAAC,KAAK,IAAI,SAAS,UAAU,KAAK,CAAC,KAAK,IAAI,SAAS,aAAa,WAAW,GAAG,CAAC;YAE3H,iDAAiD;YACjD,OAAO,CAAC,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;YAE9C,wCAAwC;YACxC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBAClB,IAAI,EAAE;oBACL,OAAO,EAAE,iBAAiB;oBAC1B,KAAK,EAAE,OAAO;oBACd,OAAO,EAAE,OAAO;iBAChB;aACD,CAAC,CAAC;YAEH,yBAAyB;YACzB,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import type { PluginInput } from '@opencode-ai/plugin';
2
- import type { CoderConfig } from '../../types';
2
+ import type { AgentConfig, CoderConfig } from '../../types';
3
3
  export interface ParamsHooks {
4
4
  onParams: (input: unknown, output: unknown) => Promise<void>;
5
5
  }
6
- export declare function createParamsHooks(ctx: PluginInput, _config: CoderConfig): ParamsHooks;
6
+ export declare function createParamsHooks(ctx: PluginInput, _config: CoderConfig, lastUserMessages?: Map<string, string>): ParamsHooks;
7
7
  /**
8
8
  * Advertised magic words for users:
9
9
  *
@@ -18,4 +18,49 @@ export declare function createParamsHooks(ctx: PluginInput, _config: CoderConfig
18
18
  *
19
19
  * Note: Triggers use multi-word phrases to avoid false positives from common words.
20
20
  */
21
+ /** Retryable HTTP status codes that should trigger model fallback */
22
+ export declare const RETRYABLE_STATUS_CODES: readonly [429, 500, 502, 503];
23
+ /**
24
+ * Tracks API errors per agent to enable model fallback on subsequent calls.
25
+ *
26
+ * When an agent's primary model fails with a retryable error (429, 500, 502, 503),
27
+ * the next `chat.params` call can select a fallback model from the agent's
28
+ * `fallbackModels` list.
29
+ *
30
+ * Current limitation: The `chat.params` hook can modify temperature/topP/topK/options
31
+ * but CANNOT change the model itself (model is in the input, not output). Full model
32
+ * fallback requires one of:
33
+ * 1. A `chat.error` hook that allows retrying with a different model
34
+ * 2. A `chat.model` hook that allows overriding the model selection
35
+ * 3. Adding `model` to the `chat.params` output type
36
+ *
37
+ * TODO: When OpenCode adds a suitable hook, implement the retry logic here:
38
+ * - On API error (429/5xx), record the failure in `agentErrorState`
39
+ * - On next `chat.params` call for the same agent, select next fallback model
40
+ * - Log: `[ModelFallback] Switching from ${currentModel} to ${fallbackModel} due to ${error}`
41
+ * - Reset fallback state after successful completion or after TTL expires
42
+ */
43
+ export declare class ModelFallbackTracker {
44
+ /**
45
+ * Map of agent name → { failedModel, failedAt, errorCode, fallbackIndex }
46
+ * Used to track which agents have experienced API errors.
47
+ */
48
+ private agentErrorState;
49
+ /** TTL for error state — reset after 5 minutes */
50
+ private readonly ERROR_STATE_TTL_MS;
51
+ /**
52
+ * Record an API error for an agent. Call this from an event handler
53
+ * when a retryable API error is detected.
54
+ */
55
+ recordError(agentName: string, model: string, errorCode: number): void;
56
+ /**
57
+ * Get the next fallback model for an agent, if one is available.
58
+ * Returns undefined if no fallback is needed or available.
59
+ */
60
+ getNextFallback(agentName: string, agentConfig: AgentConfig): string | undefined;
61
+ /**
62
+ * Clear error state for an agent (e.g., after successful completion).
63
+ */
64
+ clearError(agentName: string): void;
65
+ }
21
66
  //# sourceMappingURL=params.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/params.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AA4FD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,WAAW,CA+ErF;AAED;;;;;;;;;;;;;GAaG"}
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/params.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AA4FD,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,WAAW,EACpB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,WAAW,CAoFb;AAED;;;;;;;;;;;;;GAaG;AAMH,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,+BAAgC,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,oBAAoB;IAChC;;;OAGG;IACH,OAAO,CAAC,eAAe,CAQnB;IAEJ,kDAAkD;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAiB;IAEpD;;;OAGG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IActE;;;OAGG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;IAqBhF;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAGnC"}
@@ -80,7 +80,7 @@ function detectMode(messageContent) {
80
80
  }
81
81
  return null;
82
82
  }
83
- export function createParamsHooks(ctx, _config) {
83
+ export function createParamsHooks(ctx, _config, lastUserMessages) {
84
84
  return {
85
85
  async onParams(input, output) {
86
86
  // Input contains: sessionID, agent, model, provider, message
@@ -91,6 +91,10 @@ export function createParamsHooks(ctx, _config) {
91
91
  const messageContent = inputObj.message?.content || '';
92
92
  if (!messageContent)
93
93
  return;
94
+ // Store user message text for downstream hooks (e.g. cadence trigger detection)
95
+ if (lastUserMessages && inputObj.sessionID) {
96
+ lastUserMessages.set(inputObj.sessionID, messageContent);
97
+ }
94
98
  // Check for dynamic mode triggers
95
99
  const detected = detectMode(messageContent);
96
100
  if (!detected)
@@ -157,4 +161,81 @@ export function createParamsHooks(ctx, _config) {
157
161
  *
158
162
  * Note: Triggers use multi-word phrases to avoid false positives from common words.
159
163
  */
164
+ // ─────────────────────────────────────────────────────────────────────────────
165
+ // Model Fallback Chain
166
+ // ─────────────────────────────────────────────────────────────────────────────
167
+ /** Retryable HTTP status codes that should trigger model fallback */
168
+ export const RETRYABLE_STATUS_CODES = [429, 500, 502, 503];
169
+ /**
170
+ * Tracks API errors per agent to enable model fallback on subsequent calls.
171
+ *
172
+ * When an agent's primary model fails with a retryable error (429, 500, 502, 503),
173
+ * the next `chat.params` call can select a fallback model from the agent's
174
+ * `fallbackModels` list.
175
+ *
176
+ * Current limitation: The `chat.params` hook can modify temperature/topP/topK/options
177
+ * but CANNOT change the model itself (model is in the input, not output). Full model
178
+ * fallback requires one of:
179
+ * 1. A `chat.error` hook that allows retrying with a different model
180
+ * 2. A `chat.model` hook that allows overriding the model selection
181
+ * 3. Adding `model` to the `chat.params` output type
182
+ *
183
+ * TODO: When OpenCode adds a suitable hook, implement the retry logic here:
184
+ * - On API error (429/5xx), record the failure in `agentErrorState`
185
+ * - On next `chat.params` call for the same agent, select next fallback model
186
+ * - Log: `[ModelFallback] Switching from ${currentModel} to ${fallbackModel} due to ${error}`
187
+ * - Reset fallback state after successful completion or after TTL expires
188
+ */
189
+ export class ModelFallbackTracker {
190
+ /**
191
+ * Map of agent name → { failedModel, failedAt, errorCode, fallbackIndex }
192
+ * Used to track which agents have experienced API errors.
193
+ */
194
+ agentErrorState = new Map();
195
+ /** TTL for error state — reset after 5 minutes */
196
+ ERROR_STATE_TTL_MS = 5 * 60 * 1000;
197
+ /**
198
+ * Record an API error for an agent. Call this from an event handler
199
+ * when a retryable API error is detected.
200
+ */
201
+ recordError(agentName, model, errorCode) {
202
+ const existing = this.agentErrorState.get(agentName);
203
+ const fallbackIndex = existing ? existing.fallbackIndex + 1 : 0;
204
+ this.agentErrorState.set(agentName, {
205
+ failedModel: model,
206
+ failedAt: Date.now(),
207
+ errorCode,
208
+ fallbackIndex,
209
+ });
210
+ console.debug(`[ModelFallback] Recorded error for ${agentName}: model=${model} code=${errorCode} fallbackIndex=${fallbackIndex}`);
211
+ }
212
+ /**
213
+ * Get the next fallback model for an agent, if one is available.
214
+ * Returns undefined if no fallback is needed or available.
215
+ */
216
+ getNextFallback(agentName, agentConfig) {
217
+ const state = this.agentErrorState.get(agentName);
218
+ if (!state)
219
+ return undefined;
220
+ // Check TTL
221
+ if (Date.now() - state.failedAt > this.ERROR_STATE_TTL_MS) {
222
+ this.agentErrorState.delete(agentName);
223
+ return undefined;
224
+ }
225
+ const fallbacks = agentConfig.fallbackModels;
226
+ if (!fallbacks?.length)
227
+ return undefined;
228
+ if (state.fallbackIndex >= fallbacks.length) {
229
+ // Exhausted all fallbacks
230
+ return undefined;
231
+ }
232
+ return fallbacks[state.fallbackIndex];
233
+ }
234
+ /**
235
+ * Clear error state for an agent (e.g., after successful completion).
236
+ */
237
+ clearError(agentName) {
238
+ this.agentErrorState.delete(agentName);
239
+ }
240
+ }
160
241
  //# sourceMappingURL=params.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"params.js","sourceRoot":"","sources":["../../../src/plugin/hooks/params.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"params.js","sourceRoot":"","sources":["../../../src/plugin/hooks/params.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,MAAM,aAAa,GAAG;IACrB;;;OAGG;IACH,QAAQ,EAAE;QACT,QAAQ,EAAE;YACT,YAAY;YACZ,aAAa;YACb,cAAc;YACd,eAAe;YACf,iBAAiB;YACjB,sBAAsB;YACtB,uBAAuB;SACvB;QACD,QAAQ,EAAE;YACT,WAAW,EAAE,GAAG;SAChB;KACD;IAED;;;OAGG;IACH,SAAS,EAAE;QACV,QAAQ,EAAE;YACT,YAAY;YACZ,cAAc;YACd,qBAAqB;YACrB,mBAAmB;YACnB,oBAAoB;YACpB,yBAAyB;SACzB;QACD,QAAQ,EAAE;YACT,yDAAyD;YACzD,+CAA+C;YAC/C,QAAQ,EAAE;gBACT,IAAI,EAAE,SAAS;gBACf,YAAY,EAAE,KAAK;aACnB;SACD;KACD;IAED;;;OAGG;IACH,QAAQ,EAAE;QACT,QAAQ,EAAE;YACT,UAAU;YACV,SAAS;YACT,WAAW;YACX,gBAAgB;YAChB,aAAa;YACb,eAAe;SACf;QACD,QAAQ,EAAE;YACT,QAAQ,EAAE,EAAE;SACZ;KACD;CACQ,CAAC;AAEX;;GAEG;AACH,SAAS,UAAU,CAClB,cAAsB;IAEtB,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QAChE,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACvC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7B,OAAO;oBACN,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,MAAM,CAAC,QAAmC;iBACpD,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,iBAAiB,CAChC,GAAgB,EAChB,OAAoB,EACpB,gBAAsC;IAEtC,OAAO;QACN,KAAK,CAAC,QAAQ,CAAC,KAAc,EAAE,MAAe;YAC7C,6DAA6D;YAC7D,MAAM,QAAQ,GAAG,KAIhB,CAAC;YAEF,oDAAoD;YACpD,MAAM,SAAS,GAAG,MAKjB,CAAC;YAEF,yCAAyC;YACzC,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;YACvD,IAAI,CAAC,cAAc;gBAAE,OAAO;YAE5B,gFAAgF;YAChF,IAAI,gBAAgB,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBAC5C,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YAC1D,CAAC;YAED,kCAAkC;YAClC,MAAM,QAAQ,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;YAC5C,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAEtB,+BAA+B;YAC/B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBAClB,IAAI,EAAE;oBACL,OAAO,EAAE,iBAAiB;oBAC1B,KAAK,EAAE,MAAM;oBACb,OAAO,EAAE,2BAA2B,QAAQ,CAAC,IAAI,EAAE;oBACnD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE;iBAC3D;aACD,CAAC,CAAC;YAEH,qBAAqB;YACrB,MAAM,YAAY,GAA2B;gBAC5C,QAAQ,EAAE,wDAAwD;gBAClE,SAAS,EAAE,2DAA2D;gBACtE,QAAQ,EAAE,sDAAsD;aAChE,CAAC;YAEF,IAAI,CAAC;gBACJ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;oBACxB,IAAI,EAAE;wBACL,OAAO,EAAE,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,iBAAiB;wBACzE,OAAO,EAAE,MAAM;qBACf;iBACD,CAAC,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACR,8DAA8D;YAC/D,CAAC;YAED,iCAAiC;YACjC,IACC,aAAa,IAAI,QAAQ,CAAC,QAAQ;gBAClC,OAAO,QAAQ,CAAC,QAAQ,CAAC,WAAW,KAAK,QAAQ,EAChD,CAAC;gBACF,SAAS,CAAC,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;YACvD,CAAC;YAED,8BAA8B;YAC9B,IAAI,UAAU,IAAI,QAAQ,CAAC,QAAQ,IAAI,OAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACvF,SAAS,CAAC,OAAO,GAAG;oBACnB,GAAG,SAAS,CAAC,OAAO;oBACpB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,QAAQ;iBACpC,CAAC;YACH,CAAC;YAED,yDAAyD;YACzD,IAAI,UAAU,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACrC,SAAS,CAAC,OAAO,GAAG;oBACnB,GAAG,SAAS,CAAC,OAAO;oBACpB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,QAAQ;iBACpC,CAAC;YACH,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AAEH,gFAAgF;AAChF,uBAAuB;AACvB,gFAAgF;AAEhF,qEAAqE;AACrE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,oBAAoB;IAChC;;;OAGG;IACK,eAAe,GAAG,IAAI,GAAG,EAQ9B,CAAC;IAEJ,kDAAkD;IACjC,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAEpD;;;OAGG;IACH,WAAW,CAAC,SAAiB,EAAE,KAAa,EAAE,SAAiB;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,EAAE;YACnC,WAAW,EAAE,KAAK;YAClB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;YACpB,SAAS;YACT,aAAa;SACb,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,CACZ,sCAAsC,SAAS,WAAW,KAAK,SAAS,SAAS,kBAAkB,aAAa,EAAE,CAClH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,SAAiB,EAAE,WAAwB;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAE7B,YAAY;QACZ,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC3D,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACvC,OAAO,SAAS,CAAC;QAClB,CAAC;QAED,MAAM,SAAS,GAAG,WAAW,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,SAAS,EAAE,MAAM;YAAE,OAAO,SAAS,CAAC;QAEzC,IAAI,KAAK,CAAC,aAAa,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;YAC7C,0BAA0B;YAC1B,OAAO,SAAS,CAAC;QAClB,CAAC;QAED,OAAO,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,SAAiB;QAC3B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;CACD"}
@@ -1,6 +1,7 @@
1
1
  import type { PluginInput } from '@opencode-ai/plugin';
2
2
  import type { CoderConfig } from '../../types';
3
3
  import type { BackgroundManager } from '../../background';
4
+ import type { OpenCodeDBReader } from '../../sqlite';
4
5
  export interface SessionMemoryHooks {
5
6
  onEvent: (input: {
6
7
  event: {
@@ -22,5 +23,5 @@ export interface SessionMemoryHooks {
22
23
  * 1. On compacting: Inject Memory system info into compaction prompt
23
24
  * 2. On session.compacted: Tell Lead to have Memory save the summary (it's already in context!)
24
25
  */
25
- export declare function createSessionMemoryHooks(ctx: PluginInput, _config: CoderConfig, backgroundManager?: BackgroundManager): SessionMemoryHooks;
26
+ export declare function createSessionMemoryHooks(ctx: PluginInput, config: CoderConfig, backgroundManager?: BackgroundManager, dbReader?: OpenCodeDBReader): SessionMemoryHooks;
26
27
  //# sourceMappingURL=session-memory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-memory.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/session-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAmB1D,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,CAAC,KAAK,EAAE;QAChB,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,CAAC;KAC9D,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,YAAY,EAAE,CACb,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,EAC5B,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAC1C,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,WAAW,EACpB,iBAAiB,CAAC,EAAE,iBAAiB,GACnC,kBAAkB,CAkKpB"}
1
+ {"version":3,"file":"session-memory.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/session-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAarD,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,CAAC,KAAK,EAAE;QAChB,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,CAAC;KAC9D,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,YAAY,EAAE,CACb,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,EAC5B,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAC1C,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,WAAW,EACnB,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,QAAQ,CAAC,EAAE,gBAAgB,GACzB,kBAAkB,CAwOpB"}