@rejacky/opencode-insights 0.1.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.
package/dist/tui.js ADDED
@@ -0,0 +1,234 @@
1
+ import {
2
+ applySubagentEvent,
3
+ createMetricsState,
4
+ createSubagentState,
5
+ getSubagentSidebarModel,
6
+ recordAssistantDelta,
7
+ recordAssistantMessage,
8
+ recordToolActivity,
9
+ renderMetricsText,
10
+ renderSubagentFooter
11
+ } from "./chunk-WF6BN2SB.js";
12
+
13
+ // src/tui.tsx
14
+ import { createTextAttributes, StyledText } from "@opentui/core";
15
+ import { onCleanup } from "solid-js";
16
+ import { jsx } from "@opentui/solid/jsx-runtime";
17
+ function isSessionID(value) {
18
+ return typeof value === "string" && value.startsWith("ses");
19
+ }
20
+ function PromptRight(props) {
21
+ let text;
22
+ const sync = () => {
23
+ if (!text) return;
24
+ text.content = props.text();
25
+ props.api.renderer.requestRender();
26
+ };
27
+ const unsubscribe = props.subscribe(sync);
28
+ onCleanup(unsubscribe);
29
+ return /* @__PURE__ */ jsx(
30
+ "text",
31
+ {
32
+ ref: (ref) => {
33
+ text = ref;
34
+ sync();
35
+ },
36
+ fg: props.api.theme.current.textMuted,
37
+ children: props.text()
38
+ }
39
+ );
40
+ }
41
+ function ReactiveText(props) {
42
+ let text;
43
+ const sync = () => {
44
+ if (!text) return;
45
+ text.content = props.text();
46
+ props.api.renderer.requestRender();
47
+ };
48
+ const unsubscribe = props.subscribe(sync);
49
+ onCleanup(unsubscribe);
50
+ return /* @__PURE__ */ jsx(
51
+ "text",
52
+ {
53
+ ref: (ref) => {
54
+ text = ref;
55
+ sync();
56
+ },
57
+ fg: props.api.theme.current.textMuted,
58
+ children: props.text()
59
+ }
60
+ );
61
+ }
62
+ function SubagentSidebar(props) {
63
+ let text;
64
+ const titleAttributes = createTextAttributes({ bold: true });
65
+ const sync = () => {
66
+ if (!text) return;
67
+ text.content = renderSubagentStyledSidebar(props.state, props.sessionID, props.api, titleAttributes);
68
+ props.api.renderer.requestRender();
69
+ };
70
+ const unsubscribe = props.subscribe(sync);
71
+ const timer = setInterval(sync, 1e3);
72
+ onCleanup(() => {
73
+ unsubscribe();
74
+ clearInterval(timer);
75
+ });
76
+ return /* @__PURE__ */ jsx(
77
+ "text",
78
+ {
79
+ ref: (ref) => {
80
+ text = ref;
81
+ sync();
82
+ },
83
+ fg: props.api.theme.current.textMuted,
84
+ children: ""
85
+ }
86
+ );
87
+ }
88
+ function renderSubagentStyledSidebar(state, sessionID, api, titleAttributes) {
89
+ const model = getSubagentSidebarModel(state, sessionID);
90
+ if (!model) return "";
91
+ const chunks = [
92
+ textChunk(`${model.title}
93
+ `, api.theme.current.text, titleAttributes),
94
+ textChunk(`${model.summary}
95
+ `, api.theme.current.textMuted)
96
+ ];
97
+ for (const [index, row] of model.rows.entries()) {
98
+ if (index > 0) chunks.push(textChunk("\n", api.theme.current.textMuted));
99
+ chunks.push(textChunk(`${row.title}
100
+ `, api.theme.current.text));
101
+ chunks.push(textChunk(row.subtitle, api.theme.current.textMuted));
102
+ }
103
+ return new StyledText(chunks);
104
+ }
105
+ function textChunk(text, fg, attributes) {
106
+ return {
107
+ __isChunk: true,
108
+ text,
109
+ ...fg === void 0 ? {} : { fg },
110
+ ...attributes === void 0 ? {} : { attributes }
111
+ };
112
+ }
113
+ var tui = async (api) => {
114
+ const metrics = createMetricsState();
115
+ const subagents = createSubagentState();
116
+ const listeners = /* @__PURE__ */ new Set();
117
+ const bump = () => {
118
+ for (const listener of listeners) listener();
119
+ };
120
+ const subscribe = (listener) => {
121
+ listeners.add(listener);
122
+ return () => listeners.delete(listener);
123
+ };
124
+ const offDelta = api.event.on("message.part.delta", (evt) => {
125
+ if (evt.properties.field !== "text") return;
126
+ recordAssistantDelta(metrics, {
127
+ sessionID: evt.properties.sessionID,
128
+ messageID: evt.properties.messageID,
129
+ delta: evt.properties.delta,
130
+ at: Date.now()
131
+ });
132
+ bump();
133
+ });
134
+ const offMessage = api.event.on("message.updated", (evt) => {
135
+ const info = evt.properties.info;
136
+ if (applySubagentEvent(subagents, evt)) bump();
137
+ if (info.role !== "assistant") return;
138
+ const messageInput = {
139
+ sessionID: info.sessionID ?? evt.properties.sessionID,
140
+ messageID: info.id,
141
+ createdAt: info.time.created,
142
+ outputTokens: info.tokens.output,
143
+ reasoningTokens: info.tokens.reasoning
144
+ };
145
+ if (typeof info.time.completed === "number") messageInput.completedAt = info.time.completed;
146
+ if (typeof info.finish === "string") messageInput.finish = info.finish;
147
+ recordAssistantMessage(metrics, messageInput);
148
+ bump();
149
+ });
150
+ const offPart = api.event.on("message.part.updated", (evt) => {
151
+ const part = evt.properties.part;
152
+ if (part.type === "tool") {
153
+ recordToolActivity(metrics, part.sessionID ?? evt.properties.sessionID, part.messageID, Date.now());
154
+ }
155
+ applySubagentEvent(subagents, evt);
156
+ bump();
157
+ });
158
+ const offSessionCreated = api.event.on("session.created", (evt) => {
159
+ if (applySubagentEvent(subagents, evt)) bump();
160
+ });
161
+ const offSessionUpdated = api.event.on("session.updated", (evt) => {
162
+ if (applySubagentEvent(subagents, evt)) bump();
163
+ });
164
+ const offSessionStatus = api.event.on("session.status", (evt) => {
165
+ if (applySubagentEvent(subagents, evt)) bump();
166
+ });
167
+ const offSessionIdle = api.event.on("session.idle", (evt) => {
168
+ if (applySubagentEvent(subagents, evt)) bump();
169
+ });
170
+ const offSessionError = api.event.on("session.error", (evt) => {
171
+ if (applySubagentEvent(subagents, evt)) bump();
172
+ });
173
+ const offSlots = api.slots.register({
174
+ slots: {
175
+ session_prompt_right: (_ctx, props) => /* @__PURE__ */ jsx(
176
+ PromptRight,
177
+ {
178
+ api,
179
+ sessionID: props.session_id,
180
+ subscribe,
181
+ text: () => {
182
+ if (!isSessionID(props.session_id)) return "";
183
+ const status = api.state.session.status(props.session_id);
184
+ return renderMetricsText(metrics, props.session_id, { idle: status?.type === "idle" });
185
+ }
186
+ }
187
+ ),
188
+ home_prompt_right: () => /* @__PURE__ */ jsx(
189
+ PromptRight,
190
+ {
191
+ api,
192
+ sessionID: "",
193
+ subscribe,
194
+ text: () => ""
195
+ }
196
+ ),
197
+ sidebar_content: (_ctx, props) => /* @__PURE__ */ jsx(
198
+ SubagentSidebar,
199
+ {
200
+ api,
201
+ sessionID: props.session_id,
202
+ state: subagents,
203
+ subscribe
204
+ }
205
+ ),
206
+ sidebar_footer: (_ctx, props) => /* @__PURE__ */ jsx(
207
+ ReactiveText,
208
+ {
209
+ api,
210
+ subscribe,
211
+ text: () => renderSubagentFooter(subagents, props.session_id)
212
+ }
213
+ )
214
+ }
215
+ });
216
+ api.lifecycle.onDispose(() => {
217
+ offDelta();
218
+ offMessage();
219
+ offPart();
220
+ offSessionCreated();
221
+ offSessionUpdated();
222
+ offSessionStatus();
223
+ offSessionIdle();
224
+ offSessionError();
225
+ });
226
+ };
227
+ var id = "opencode-insights-tui";
228
+ var tui_default = { id, tui };
229
+ export {
230
+ tui_default as default,
231
+ id,
232
+ tui
233
+ };
234
+ //# sourceMappingURL=tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tui.tsx"],"sourcesContent":["/** @jsxImportSource @opentui/solid */\nimport { createTextAttributes, StyledText, type TextChunk, type TextRenderable } from \"@opentui/core\";\nimport type { TuiPlugin, TuiPluginApi, TuiPluginModule } from \"@opencode-ai/plugin/tui\";\nimport { onCleanup } from \"solid-js\";\nimport {\n createMetricsState,\n recordAssistantDelta,\n recordAssistantMessage,\n recordToolActivity,\n renderMetricsText\n} from \"./metrics.js\";\nimport {\n applySubagentEvent,\n createSubagentState,\n getSubagentSidebarModel,\n renderSubagentFooter,\n type SubagentState\n} from \"./subagents.js\";\n\ntype Listener = () => void;\n\nfunction isSessionID(value: string | undefined): value is string {\n return typeof value === \"string\" && value.startsWith(\"ses\");\n}\n\nfunction PromptRight(props: {\n api: TuiPluginApi;\n sessionID: string;\n text: () => string;\n subscribe: (listener: Listener) => () => void;\n}) {\n let text: TextRenderable | undefined;\n\n const sync = () => {\n if (!text) return;\n text.content = props.text();\n props.api.renderer.requestRender();\n };\n\n const unsubscribe = props.subscribe(sync);\n onCleanup(unsubscribe);\n\n return (\n <text\n ref={(ref: TextRenderable) => {\n text = ref;\n sync();\n }}\n fg={props.api.theme.current.textMuted}\n >\n {props.text()}\n </text>\n );\n}\n\nfunction ReactiveText(props: {\n api: TuiPluginApi;\n text: () => string;\n subscribe: (listener: Listener) => () => void;\n}) {\n let text: TextRenderable | undefined;\n\n const sync = () => {\n if (!text) return;\n text.content = props.text();\n props.api.renderer.requestRender();\n };\n\n const unsubscribe = props.subscribe(sync);\n onCleanup(unsubscribe);\n\n return (\n <text\n ref={(ref: TextRenderable) => {\n text = ref;\n sync();\n }}\n fg={props.api.theme.current.textMuted}\n >\n {props.text()}\n </text>\n );\n}\n\nfunction SubagentSidebar(props: {\n api: TuiPluginApi;\n sessionID: string;\n state: SubagentState;\n subscribe: (listener: Listener) => () => void;\n}) {\n let text: TextRenderable | undefined;\n const titleAttributes = createTextAttributes({ bold: true });\n\n const sync = () => {\n if (!text) return;\n text.content = renderSubagentStyledSidebar(props.state, props.sessionID, props.api, titleAttributes);\n props.api.renderer.requestRender();\n };\n\n const unsubscribe = props.subscribe(sync);\n const timer = setInterval(sync, 1_000);\n onCleanup(() => {\n unsubscribe();\n clearInterval(timer);\n });\n\n return (\n <text\n ref={(ref: TextRenderable) => {\n text = ref;\n sync();\n }}\n fg={props.api.theme.current.textMuted}\n >\n {\"\"}\n </text>\n );\n}\n\nfunction renderSubagentStyledSidebar(\n state: SubagentState,\n sessionID: string,\n api: TuiPluginApi,\n titleAttributes: number\n) {\n const model = getSubagentSidebarModel(state, sessionID);\n if (!model) return \"\";\n\n const chunks: TextChunk[] = [\n textChunk(`${model.title}\\n`, api.theme.current.text, titleAttributes),\n textChunk(`${model.summary}\\n`, api.theme.current.textMuted)\n ];\n\n for (const [index, row] of model.rows.entries()) {\n if (index > 0) chunks.push(textChunk(\"\\n\", api.theme.current.textMuted));\n chunks.push(textChunk(`${row.title}\\n`, api.theme.current.text));\n chunks.push(textChunk(row.subtitle, api.theme.current.textMuted));\n }\n\n return new StyledText(chunks);\n}\n\nfunction textChunk(text: string, fg?: TextChunk[\"fg\"], attributes?: number): TextChunk {\n return {\n __isChunk: true,\n text,\n ...(fg === undefined ? {} : { fg }),\n ...(attributes === undefined ? {} : { attributes })\n };\n}\n\nconst tui: TuiPlugin = async (api) => {\n const metrics = createMetricsState();\n const subagents = createSubagentState();\n const listeners = new Set<Listener>();\n const bump = () => {\n for (const listener of listeners) listener();\n };\n const subscribe = (listener: Listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n };\n\n const offDelta = api.event.on(\"message.part.delta\", (evt) => {\n if (evt.properties.field !== \"text\") return;\n recordAssistantDelta(metrics, {\n sessionID: evt.properties.sessionID,\n messageID: evt.properties.messageID,\n delta: evt.properties.delta,\n at: Date.now()\n });\n bump();\n });\n\n const offMessage = api.event.on(\"message.updated\", (evt) => {\n const info = evt.properties.info;\n if (applySubagentEvent(subagents, evt)) bump();\n if (info.role !== \"assistant\") return;\n\n const messageInput: {\n sessionID: string;\n messageID: string;\n createdAt: number;\n completedAt?: number;\n outputTokens?: number;\n reasoningTokens?: number;\n finish?: string;\n } = {\n sessionID: info.sessionID ?? evt.properties.sessionID,\n messageID: info.id,\n createdAt: info.time.created,\n outputTokens: info.tokens.output,\n reasoningTokens: info.tokens.reasoning\n };\n if (typeof info.time.completed === \"number\") messageInput.completedAt = info.time.completed;\n if (typeof info.finish === \"string\") messageInput.finish = info.finish;\n recordAssistantMessage(metrics, messageInput);\n bump();\n });\n\n const offPart = api.event.on(\"message.part.updated\", (evt) => {\n const part = evt.properties.part;\n if (part.type === \"tool\") {\n recordToolActivity(metrics, part.sessionID ?? evt.properties.sessionID, part.messageID, Date.now());\n }\n applySubagentEvent(subagents, evt);\n bump();\n });\n\n const offSessionCreated = api.event.on(\"session.created\", (evt) => {\n if (applySubagentEvent(subagents, evt)) bump();\n });\n\n const offSessionUpdated = api.event.on(\"session.updated\", (evt) => {\n if (applySubagentEvent(subagents, evt)) bump();\n });\n\n const offSessionStatus = api.event.on(\"session.status\", (evt) => {\n if (applySubagentEvent(subagents, evt)) bump();\n });\n\n const offSessionIdle = api.event.on(\"session.idle\", (evt) => {\n if (applySubagentEvent(subagents, evt)) bump();\n });\n\n const offSessionError = api.event.on(\"session.error\", (evt) => {\n if (applySubagentEvent(subagents, evt)) bump();\n });\n\n const offSlots = api.slots.register({\n slots: {\n session_prompt_right: (_ctx, props) => (\n <PromptRight\n api={api}\n sessionID={props.session_id}\n subscribe={subscribe}\n text={() => {\n if (!isSessionID(props.session_id)) return \"\";\n const status = api.state.session.status(props.session_id);\n return renderMetricsText(metrics, props.session_id, { idle: status?.type === \"idle\" });\n }}\n />\n ),\n home_prompt_right: () => (\n <PromptRight\n api={api}\n sessionID=\"\"\n subscribe={subscribe}\n text={() => \"\"}\n />\n ),\n sidebar_content: (_ctx, props) => (\n <SubagentSidebar\n api={api}\n sessionID={props.session_id}\n state={subagents}\n subscribe={subscribe}\n />\n ),\n sidebar_footer: (_ctx, props) => (\n <ReactiveText\n api={api}\n subscribe={subscribe}\n text={() => renderSubagentFooter(subagents, props.session_id)}\n />\n )\n }\n });\n\n api.lifecycle.onDispose(() => {\n offDelta();\n offMessage();\n offPart();\n offSessionCreated();\n offSessionUpdated();\n offSessionStatus();\n offSessionIdle();\n offSessionError();\n });\n};\n\nconst id = \"opencode-insights-tui\";\n\nexport { id, tui };\nexport default { id, tui } satisfies TuiPluginModule;\n"],"mappings":";;;;;;;;;;;;;AACA,SAAS,sBAAsB,kBAAuD;AAEtF,SAAS,iBAAiB;AAwCtB;AAtBJ,SAAS,YAAY,OAA4C;AAC/D,SAAO,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK;AAC5D;AAEA,SAAS,YAAY,OAKlB;AACD,MAAI;AAEJ,QAAM,OAAO,MAAM;AACjB,QAAI,CAAC,KAAM;AACX,SAAK,UAAU,MAAM,KAAK;AAC1B,UAAM,IAAI,SAAS,cAAc;AAAA,EACnC;AAEA,QAAM,cAAc,MAAM,UAAU,IAAI;AACxC,YAAU,WAAW;AAErB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,CAAC,QAAwB;AAC5B,eAAO;AACP,aAAK;AAAA,MACP;AAAA,MACA,IAAI,MAAM,IAAI,MAAM,QAAQ;AAAA,MAE3B,gBAAM,KAAK;AAAA;AAAA,EACd;AAEJ;AAEA,SAAS,aAAa,OAInB;AACD,MAAI;AAEJ,QAAM,OAAO,MAAM;AACjB,QAAI,CAAC,KAAM;AACX,SAAK,UAAU,MAAM,KAAK;AAC1B,UAAM,IAAI,SAAS,cAAc;AAAA,EACnC;AAEA,QAAM,cAAc,MAAM,UAAU,IAAI;AACxC,YAAU,WAAW;AAErB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,CAAC,QAAwB;AAC5B,eAAO;AACP,aAAK;AAAA,MACP;AAAA,MACA,IAAI,MAAM,IAAI,MAAM,QAAQ;AAAA,MAE3B,gBAAM,KAAK;AAAA;AAAA,EACd;AAEJ;AAEA,SAAS,gBAAgB,OAKtB;AACD,MAAI;AACJ,QAAM,kBAAkB,qBAAqB,EAAE,MAAM,KAAK,CAAC;AAE3D,QAAM,OAAO,MAAM;AACjB,QAAI,CAAC,KAAM;AACX,SAAK,UAAU,4BAA4B,MAAM,OAAO,MAAM,WAAW,MAAM,KAAK,eAAe;AACnG,UAAM,IAAI,SAAS,cAAc;AAAA,EACnC;AAEA,QAAM,cAAc,MAAM,UAAU,IAAI;AACxC,QAAM,QAAQ,YAAY,MAAM,GAAK;AACrC,YAAU,MAAM;AACd,gBAAY;AACZ,kBAAc,KAAK;AAAA,EACrB,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,CAAC,QAAwB;AAC5B,eAAO;AACP,aAAK;AAAA,MACP;AAAA,MACA,IAAI,MAAM,IAAI,MAAM,QAAQ;AAAA,MAE3B;AAAA;AAAA,EACH;AAEJ;AAEA,SAAS,4BACP,OACA,WACA,KACA,iBACA;AACA,QAAM,QAAQ,wBAAwB,OAAO,SAAS;AACtD,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,SAAsB;AAAA,IAC1B,UAAU,GAAG,MAAM,KAAK;AAAA,GAAM,IAAI,MAAM,QAAQ,MAAM,eAAe;AAAA,IACrE,UAAU,GAAG,MAAM,OAAO;AAAA,GAAM,IAAI,MAAM,QAAQ,SAAS;AAAA,EAC7D;AAEA,aAAW,CAAC,OAAO,GAAG,KAAK,MAAM,KAAK,QAAQ,GAAG;AAC/C,QAAI,QAAQ,EAAG,QAAO,KAAK,UAAU,MAAM,IAAI,MAAM,QAAQ,SAAS,CAAC;AACvE,WAAO,KAAK,UAAU,GAAG,IAAI,KAAK;AAAA,GAAM,IAAI,MAAM,QAAQ,IAAI,CAAC;AAC/D,WAAO,KAAK,UAAU,IAAI,UAAU,IAAI,MAAM,QAAQ,SAAS,CAAC;AAAA,EAClE;AAEA,SAAO,IAAI,WAAW,MAAM;AAC9B;AAEA,SAAS,UAAU,MAAc,IAAsB,YAAgC;AACrF,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA,GAAI,OAAO,SAAY,CAAC,IAAI,EAAE,GAAG;AAAA,IACjC,GAAI,eAAe,SAAY,CAAC,IAAI,EAAE,WAAW;AAAA,EACnD;AACF;AAEA,IAAM,MAAiB,OAAO,QAAQ;AACpC,QAAM,UAAU,mBAAmB;AACnC,QAAM,YAAY,oBAAoB;AACtC,QAAM,YAAY,oBAAI,IAAc;AACpC,QAAM,OAAO,MAAM;AACjB,eAAW,YAAY,UAAW,UAAS;AAAA,EAC7C;AACA,QAAM,YAAY,CAAC,aAAuB;AACxC,cAAU,IAAI,QAAQ;AACtB,WAAO,MAAM,UAAU,OAAO,QAAQ;AAAA,EACxC;AAEA,QAAM,WAAW,IAAI,MAAM,GAAG,sBAAsB,CAAC,QAAQ;AAC3D,QAAI,IAAI,WAAW,UAAU,OAAQ;AACrC,yBAAqB,SAAS;AAAA,MAC5B,WAAW,IAAI,WAAW;AAAA,MAC1B,WAAW,IAAI,WAAW;AAAA,MAC1B,OAAO,IAAI,WAAW;AAAA,MACtB,IAAI,KAAK,IAAI;AAAA,IACf,CAAC;AACD,SAAK;AAAA,EACP,CAAC;AAED,QAAM,aAAa,IAAI,MAAM,GAAG,mBAAmB,CAAC,QAAQ;AAC1D,UAAM,OAAO,IAAI,WAAW;AAC5B,QAAI,mBAAmB,WAAW,GAAG,EAAG,MAAK;AAC7C,QAAI,KAAK,SAAS,YAAa;AAE/B,UAAM,eAQF;AAAA,MACF,WAAW,KAAK,aAAa,IAAI,WAAW;AAAA,MAC5C,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK,KAAK;AAAA,MACrB,cAAc,KAAK,OAAO;AAAA,MAC1B,iBAAiB,KAAK,OAAO;AAAA,IAC/B;AACA,QAAI,OAAO,KAAK,KAAK,cAAc,SAAU,cAAa,cAAc,KAAK,KAAK;AAClF,QAAI,OAAO,KAAK,WAAW,SAAU,cAAa,SAAS,KAAK;AAChE,2BAAuB,SAAS,YAAY;AAC5C,SAAK;AAAA,EACP,CAAC;AAED,QAAM,UAAU,IAAI,MAAM,GAAG,wBAAwB,CAAC,QAAQ;AAC5D,UAAM,OAAO,IAAI,WAAW;AAC5B,QAAI,KAAK,SAAS,QAAQ;AACxB,yBAAmB,SAAS,KAAK,aAAa,IAAI,WAAW,WAAW,KAAK,WAAW,KAAK,IAAI,CAAC;AAAA,IACpG;AACA,uBAAmB,WAAW,GAAG;AACjC,SAAK;AAAA,EACP,CAAC;AAED,QAAM,oBAAoB,IAAI,MAAM,GAAG,mBAAmB,CAAC,QAAQ;AACjE,QAAI,mBAAmB,WAAW,GAAG,EAAG,MAAK;AAAA,EAC/C,CAAC;AAED,QAAM,oBAAoB,IAAI,MAAM,GAAG,mBAAmB,CAAC,QAAQ;AACjE,QAAI,mBAAmB,WAAW,GAAG,EAAG,MAAK;AAAA,EAC/C,CAAC;AAED,QAAM,mBAAmB,IAAI,MAAM,GAAG,kBAAkB,CAAC,QAAQ;AAC/D,QAAI,mBAAmB,WAAW,GAAG,EAAG,MAAK;AAAA,EAC/C,CAAC;AAED,QAAM,iBAAiB,IAAI,MAAM,GAAG,gBAAgB,CAAC,QAAQ;AAC3D,QAAI,mBAAmB,WAAW,GAAG,EAAG,MAAK;AAAA,EAC/C,CAAC;AAED,QAAM,kBAAkB,IAAI,MAAM,GAAG,iBAAiB,CAAC,QAAQ;AAC7D,QAAI,mBAAmB,WAAW,GAAG,EAAG,MAAK;AAAA,EAC/C,CAAC;AAED,QAAM,WAAW,IAAI,MAAM,SAAS;AAAA,IAClC,OAAO;AAAA,MACL,sBAAsB,CAAC,MAAM,UAC3B;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,WAAW,MAAM;AAAA,UACjB;AAAA,UACA,MAAM,MAAM;AACV,gBAAI,CAAC,YAAY,MAAM,UAAU,EAAG,QAAO;AAC3C,kBAAM,SAAS,IAAI,MAAM,QAAQ,OAAO,MAAM,UAAU;AACxD,mBAAO,kBAAkB,SAAS,MAAM,YAAY,EAAE,MAAM,QAAQ,SAAS,OAAO,CAAC;AAAA,UACvF;AAAA;AAAA,MACF;AAAA,MAEF,mBAAmB,MACjB;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,WAAU;AAAA,UACV;AAAA,UACA,MAAM,MAAM;AAAA;AAAA,MACd;AAAA,MAEF,iBAAiB,CAAC,MAAM,UACtB;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,WAAW,MAAM;AAAA,UACjB,OAAO;AAAA,UACP;AAAA;AAAA,MACF;AAAA,MAEF,gBAAgB,CAAC,MAAM,UACrB;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,MAAM,MAAM,qBAAqB,WAAW,MAAM,UAAU;AAAA;AAAA,MAC9D;AAAA,IAEJ;AAAA,EACF,CAAC;AAED,MAAI,UAAU,UAAU,MAAM;AAC5B,aAAS;AACT,eAAW;AACX,YAAQ;AACR,sBAAkB;AAClB,sBAAkB;AAClB,qBAAiB;AACjB,mBAAe;AACf,oBAAgB;AAAA,EAClB,CAAC;AACH;AAEA,IAAM,KAAK;AAGX,IAAO,cAAQ,EAAE,IAAI,IAAI;","names":[]}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/package.json",
3
+ "name": "@rejacky/opencode-insights",
4
+ "version": "0.1.0",
5
+ "description": "OpenCode plugin for local request capture, TPS metrics, and subagent status visibility.",
6
+ "type": "module",
7
+ "author": "opencode-insights contributors",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "bin": {
11
+ "opencode-insights": "./dist/cli.js"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./tui": {
19
+ "types": "./dist/tui.d.ts",
20
+ "import": "./dist/tui.js"
21
+ },
22
+ "./cli": {
23
+ "types": "./dist/cli.d.ts",
24
+ "import": "./dist/cli.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "README.md",
30
+ "DEVELOPMENT.md"
31
+ ],
32
+ "scripts": {
33
+ "build": "tsup",
34
+ "test": "vitest run",
35
+ "typecheck": "tsc --noEmit",
36
+ "verify": "npm run typecheck && npm run test && npm run build",
37
+ "prepack": "npm run build",
38
+ "prepublishOnly": "npm run verify"
39
+ },
40
+ "keywords": [
41
+ "opencode",
42
+ "plugin",
43
+ "llm",
44
+ "sqlite",
45
+ "tps",
46
+ "subagent"
47
+ ],
48
+ "license": "MIT",
49
+ "engines": {
50
+ "node": ">=22.13"
51
+ },
52
+ "peerDependencies": {
53
+ "@opencode-ai/plugin": ">=1.15.0 <2",
54
+ "@opentui/core": ">=0.4.0 <0.5",
55
+ "@opentui/solid": ">=0.4.0 <0.5",
56
+ "solid-js": "1.9.12"
57
+ },
58
+ "devDependencies": {
59
+ "@opencode-ai/plugin": "^1.17.13",
60
+ "@opentui/core": "^0.4.3",
61
+ "@opentui/solid": "^0.4.3",
62
+ "@types/node": "^24.12.2",
63
+ "solid-js": "1.9.12",
64
+ "tsup": "^8.5.1",
65
+ "typescript": "^6.0.3",
66
+ "vitest": "^4.1.10"
67
+ }
68
+ }