(ctx)
| 168 | } |
| 169 | |
| 170 | export const AgentmemoryCapturePlugin: Plugin = async (ctx) => { |
| 171 | projectPath = ctx.worktree || ctx.project?.id || process.cwd(); |
| 172 | |
| 173 | return { |
| 174 | event: async ({ event }) => { |
| 175 | const type = event.type; |
| 176 | const props = (event as any).properties || {}; |
| 177 | |
| 178 | // ── session.created ── |
| 179 | if (type === "session.created") { |
| 180 | const info = props.info as Record<string, unknown> | undefined; |
| 181 | activeSessionId = (info?.id as string) || props.sessionID || null; |
| 182 | if (!activeSessionId) return; |
| 183 | stashedFiles.set(activeSessionId, new Set()); |
| 184 | seenSubtaskIds.delete(activeSessionId); |
| 185 | seenToolCallIds.delete(activeSessionId); |
| 186 | contextInjectedSessions.delete(activeSessionId); |
| 187 | // Snapshot the session id locally — `activeSessionId` is mutable |
| 188 | // and another `session.created` event during the await could |
| 189 | // rebind it, causing context to be cached against the wrong key. |
| 190 | const sessionId = activeSessionId; |
| 191 | const startResult = await postJson("/session/start", { |
| 192 | sessionId, |
| 193 | title: info?.title ?? null, |
| 194 | parentID: info?.parentID ?? null, |
| 195 | version: info?.version ?? null, |
| 196 | project: projectPath, |
| 197 | cwd: projectPath, |
| 198 | }); |
| 199 | // cache the context returned at session/start so the |
| 200 | // chat.system.transform hook injects it without a second fetch. |
| 201 | const startCtx = (startResult as any)?.context; |
| 202 | if (typeof startCtx === "string" && startCtx.length > 0) { |
| 203 | startContextCache.set(sessionId, startCtx); |
| 204 | } |
| 205 | if (pendingConfig) { |
| 206 | await observe(sessionId, "config_loaded", pendingConfig); |
| 207 | pendingConfig = null; |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | // ── session.idle ── (summarize handled in session.status idle branch) |
| 212 | |
| 213 | // ── session.status ── |
| 214 | if (type === "session.status") { |
| 215 | const status = props.status as Record<string, unknown> | undefined; |
| 216 | const sid = props.sessionID || activeSessionId; |
| 217 | if (!sid || !status) return; |
| 218 | if (status.type === "idle") { |
| 219 | await post("/summarize", { sessionId: sid }); |
| 220 | } |
| 221 | await observe(sid, "session_status", { |
| 222 | status_type: status.type, |
| 223 | attempt: status.attempt ?? null, |
| 224 | message: safeSlice(status.message, 2000), |
| 225 | }); |
| 226 | } |
| 227 |
nothing calls this directly
no test coverage detected