( line: string, sessionId: string, onDebug: (msg: string) => void, )
| 105 | } |
| 106 | |
| 107 | function extractActivities( |
| 108 | line: string, |
| 109 | sessionId: string, |
| 110 | onDebug: (msg: string) => void, |
| 111 | ): SessionActivity[] { |
| 112 | let parsed: unknown |
| 113 | try { |
| 114 | parsed = jsonParse(line) |
| 115 | } catch { |
| 116 | return [] |
| 117 | } |
| 118 | |
| 119 | if (!parsed || typeof parsed !== 'object') { |
| 120 | return [] |
| 121 | } |
| 122 | |
| 123 | const msg = parsed as Record<string, unknown> |
| 124 | const activities: SessionActivity[] = [] |
| 125 | const now = Date.now() |
| 126 | |
| 127 | switch (msg.type) { |
| 128 | case 'assistant': { |
| 129 | const message = msg.message as Record<string, unknown> | undefined |
| 130 | if (!message) break |
| 131 | const content = message.content |
| 132 | if (!Array.isArray(content)) break |
| 133 | |
| 134 | for (const block of content) { |
| 135 | if (!block || typeof block !== 'object') continue |
| 136 | const b = block as Record<string, unknown> |
| 137 | |
| 138 | if (b.type === 'tool_use') { |
| 139 | const name = (b.name as string) ?? 'Tool' |
| 140 | const input = (b.input as Record<string, unknown>) ?? {} |
| 141 | const summary = toolSummary(name, input) |
| 142 | activities.push({ |
| 143 | type: 'tool_start', |
| 144 | summary, |
| 145 | timestamp: now, |
| 146 | }) |
| 147 | onDebug( |
| 148 | `[bridge:activity] sessionId=${sessionId} tool_use name=${name} ${inputPreview(input)}`, |
| 149 | ) |
| 150 | } else if (b.type === 'text') { |
| 151 | const text = (b.text as string) ?? '' |
| 152 | if (text.length > 0) { |
| 153 | activities.push({ |
| 154 | type: 'text', |
| 155 | summary: text.slice(0, 80), |
| 156 | timestamp: now, |
| 157 | }) |
| 158 | onDebug( |
| 159 | `[bridge:activity] sessionId=${sessionId} text "${text.slice(0, 100)}"`, |
| 160 | ) |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | break |
no test coverage detected