ompchamber 1.0.0 → 1.2.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 (233) hide show
  1. package/dist/client/index.html +1 -1
  2. package/dist/client/static/css/index.b938f4a693.css +2 -0
  3. package/dist/client/static/js/77.8022a800b5.js +139 -0
  4. package/dist/client/static/js/async/{1k.5974df3b87.js → 1k.a411fe5b43.js} +2 -2
  5. package/dist/client/static/js/async/{3y.71f2ccf3b6.js → 3y.3186ecdd63.js} +5 -5
  6. package/dist/client/static/js/async/5b.d88304bc13.js +1 -0
  7. package/dist/client/static/js/async/66.86544ad741.js +93 -0
  8. package/dist/client/static/js/async/7g.db82aca7ba.js +1 -0
  9. package/dist/client/static/js/async/7l.fadbbc0583.js +1 -0
  10. package/dist/client/static/js/async/{dc.856fda6560.js → ar.ad5c8822a8.js} +2 -2
  11. package/dist/client/static/js/async/cx.9c8268d542.js +226 -0
  12. package/dist/client/static/js/async/e.6443e739a2.js +79 -0
  13. package/dist/client/static/js/async/f7.46971e9d6d.js +2 -0
  14. package/dist/client/static/js/async/g.ee41bfed7f.js +2 -0
  15. package/dist/client/static/js/async/h1.d7091cef78.js +1 -0
  16. package/dist/client/static/js/async/hs.e7c59d8090.js +41 -0
  17. package/dist/client/static/js/async/jl.4911fa3383.js +1 -0
  18. package/dist/client/static/js/async/{k.7466330d1a.js → k.d16cd09ae7.js} +2 -2
  19. package/dist/client/static/js/async/{m.c038c71b9f.js → m.2e1ea3db9e.js} +2 -2
  20. package/dist/client/static/js/async/m3.d2b05f9604.js +2 -0
  21. package/dist/client/static/js/async/mt.853be2b5aa.js +1 -0
  22. package/dist/client/static/js/async/{oc.9c060c9779.js → oc.eb22093f05.js} +1 -1
  23. package/dist/client/static/js/async/{og.634fba99ac.js → og.53f068804c.js} +1 -1
  24. package/dist/client/static/js/async/{5b.0d6ae50fe8.js → q.b453193538.js} +10 -10
  25. package/dist/client/static/js/async/q5.88b50ffa95.js +286 -0
  26. package/dist/client/static/js/async/q8.7f1b48e9cd.js +21 -0
  27. package/dist/client/static/js/async/{sy.d16be843a7.js → s.aad2ecebc6.js} +1 -1
  28. package/dist/client/static/js/async/{tr.e878658140.js → tr.2a0d2b7600.js} +1 -1
  29. package/dist/client/static/js/async/vt.20406a5604.js +1 -0
  30. package/dist/client/static/js/async/x1.fe8af17016.js +90 -0
  31. package/dist/client/static/js/async/yg.5a94e1fc8a.js +149 -0
  32. package/dist/client/static/js/async/yx.af2936c368.js +10 -0
  33. package/dist/client/static/js/index.57b39ffa7f.js +34 -0
  34. package/package.json +1 -1
  35. package/src/client/components/common/ComposerPicker.tsx +16 -4
  36. package/src/client/components/common/ComposerTextarea.tsx +1 -0
  37. package/src/client/components/common/file-icon/index.tsx +4 -1
  38. package/src/client/components/common/image-viewer/index.tsx +224 -0
  39. package/src/client/components/layout/RightActivityBar.tsx +1 -1
  40. package/src/client/components/layout/desktop-layout/ResizeHandle.tsx +2 -2
  41. package/src/client/components/layout/desktop-layout/TopNavbar.tsx +13 -2
  42. package/src/client/components/layout/desktop-layout/WorkspacePanels.tsx +107 -56
  43. package/src/client/components/layout/desktop-layout/index.tsx +25 -96
  44. package/src/client/components/layout/desktop-layout/resizer/index.tsx +79 -118
  45. package/src/client/components/layout/desktop-layout/resizer/separator-drag.ts +140 -0
  46. package/src/client/components/layout/session-sidebar/Header.tsx +1 -1
  47. package/src/client/components/layout/session-sidebar/SessionItem.tsx +26 -12
  48. package/src/client/components/layout/session-sidebar/SubagentList.tsx +6 -4
  49. package/src/client/components/mobile/mobile-right-sidebar/FullEditor.tsx +57 -43
  50. package/src/client/components/mobile/mobile-right-sidebar/Header.tsx +31 -24
  51. package/src/client/components/settings/Modal.tsx +1 -0
  52. package/src/client/components/settings/categories/ChatSettings.tsx +6 -2
  53. package/src/client/components/settings/categories/chat-settings/TitleSection.tsx +99 -0
  54. package/src/client/components/workspace/btw-panel/AskCard.tsx +155 -0
  55. package/src/client/components/workspace/btw-panel/Composer.tsx +181 -0
  56. package/src/client/components/workspace/btw-panel/Messages.tsx +100 -0
  57. package/src/client/components/workspace/btw-panel/TopicMenu.tsx +106 -0
  58. package/src/client/components/workspace/btw-panel/attachments.ts +80 -0
  59. package/src/client/components/workspace/btw-panel/index.tsx +83 -0
  60. package/src/client/components/workspace/chat-timeline/ComposerDock.tsx +39 -20
  61. package/src/client/components/workspace/chat-timeline/EmptyWorkspacePrompt.tsx +3 -0
  62. package/src/client/components/workspace/chat-timeline/MinimapShortcuts.tsx +49 -12
  63. package/src/client/components/workspace/chat-timeline/SubagentView.tsx +3 -1
  64. package/src/client/components/workspace/chat-timeline/TimelineBody.tsx +10 -6
  65. package/src/client/components/workspace/chat-timeline/chat-input/AttachmentToolbar.tsx +2 -1
  66. package/src/client/components/workspace/chat-timeline/chat-input/DropOverlay.tsx +17 -0
  67. package/src/client/components/workspace/chat-timeline/chat-input/index.tsx +67 -43
  68. package/src/client/components/workspace/chat-timeline/index.tsx +14 -9
  69. package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Goal.tsx +3 -3
  70. package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Read.tsx +25 -7
  71. package/src/client/components/workspace/editor/Toolbar.tsx +32 -23
  72. package/src/client/components/workspace/editor/index.tsx +45 -36
  73. package/src/client/components/workspace/model-dropdown/groups.ts +35 -2
  74. package/src/client/components/workspace/model-dropdown/index.tsx +48 -7
  75. package/src/client/components/workspace/model-dropdown/use-catalog.ts +28 -4
  76. package/src/client/hooks/chat/btw/index.ts +180 -0
  77. package/src/client/hooks/chat/btw/intercept.ts +43 -0
  78. package/src/client/hooks/chat/btw/mode.ts +179 -0
  79. package/src/client/hooks/chat/composer/attachments.ts +198 -0
  80. package/src/client/hooks/chat/composer/drop-entries.ts +204 -0
  81. package/src/client/hooks/chat/composer/drop-payload.test.ts +97 -0
  82. package/src/client/hooks/chat/composer/drop-payload.ts +130 -0
  83. package/src/client/hooks/chat/composer/drop-references.ts +106 -0
  84. package/src/client/hooks/chat/composer/file-drop.test.ts +194 -0
  85. package/src/client/hooks/chat/composer/file-drop.ts +226 -0
  86. package/src/client/hooks/chat/composer/file-reads.test.ts +211 -0
  87. package/src/client/hooks/chat/composer/file-reads.ts +238 -0
  88. package/src/client/hooks/chat/composer/index.ts +35 -9
  89. package/src/client/hooks/chat/composer/pipeline.ts +181 -0
  90. package/src/client/hooks/chat/omp/index.ts +3 -3
  91. package/src/client/hooks/chat/omp/prompt-send.ts +5 -5
  92. package/src/client/hooks/chat/timeline/actions.ts +40 -4
  93. package/src/client/hooks/chat/timeline/deferred-model.test.ts +219 -0
  94. package/src/client/hooks/chat/timeline/deferred-model.ts +92 -0
  95. package/src/client/hooks/chat/timeline/index.ts +29 -9
  96. package/src/client/hooks/chat/timeline/prompt-text.ts +6 -1
  97. package/src/client/hooks/chat/timeline/send.ts +45 -70
  98. package/src/client/hooks/chat/timeline/session-load.ts +2 -1
  99. package/src/client/hooks/chat/timeline/session-pagination.ts +161 -14
  100. package/src/client/hooks/chat/timeline/user-turns.ts +149 -0
  101. package/src/client/hooks/editor/file-actions.ts +49 -0
  102. package/src/client/hooks/editor/use-file-editor.ts +38 -27
  103. package/src/client/hooks/editor/use-file-transfer.ts +78 -0
  104. package/src/client/hooks/workspace/available-width.ts +33 -0
  105. package/src/client/hooks/workspace/panel-widths.ts +34 -37
  106. package/src/client/tailwind.css +22 -0
  107. package/src/server/db.server.ts +21 -287
  108. package/src/server/lib/btw/frames.test.ts +68 -0
  109. package/src/server/lib/btw/frames.ts +56 -0
  110. package/src/server/lib/btw/prompt.ts +28 -0
  111. package/src/server/lib/btw/registry.server.ts +141 -0
  112. package/src/server/lib/btw/runtime.server.ts +324 -0
  113. package/src/server/lib/btw/schema.server.ts +44 -0
  114. package/src/server/lib/btw/service.server.ts +171 -0
  115. package/src/server/lib/btw/session-copy.server.ts +213 -0
  116. package/src/server/lib/btw/session-copy.test.ts +166 -0
  117. package/src/server/lib/btw/store.server.ts +240 -0
  118. package/src/server/lib/db/schema.ts +110 -0
  119. package/src/server/lib/db/seed.ts +160 -0
  120. package/src/server/lib/db/workspace-sync.ts +70 -0
  121. package/src/server/lib/fs/root.ts +37 -0
  122. package/src/server/lib/models/preferences.server.ts +110 -0
  123. package/src/server/lib/models/registry.server.ts +206 -0
  124. package/src/server/lib/omp/rpc/frame-fold.ts +207 -0
  125. package/src/server/lib/omp/rpc/manager.ts +27 -123
  126. package/src/server/lib/omp/rpc/utility.ts +7 -1
  127. package/src/server/lib/omp/session/auto-title.server.test.ts +137 -0
  128. package/src/server/lib/omp/session/auto-title.server.ts +152 -0
  129. package/src/server/lib/omp/session/blobs.server.test.ts +100 -0
  130. package/src/server/lib/omp/session/blobs.server.ts +76 -0
  131. package/src/server/lib/omp/session/file-scan.ts +174 -0
  132. package/src/server/lib/omp/session/files.test.ts +147 -0
  133. package/src/server/lib/omp/session/files.ts +52 -35
  134. package/src/server/lib/omp/session/locator.ts +2 -2
  135. package/src/server/lib/omp/session/merge-stored.test.ts +118 -0
  136. package/src/server/lib/omp/session/merge-stored.ts +171 -0
  137. package/src/server/lib/omp/session/messages.ts +34 -0
  138. package/src/server/lib/omp/session/reader.ts +2 -2
  139. package/src/server/lib/omp/session/subagent-presence.ts +9 -6
  140. package/src/server/lib/queue/delivery.server.test.ts +260 -0
  141. package/src/server/lib/queue/delivery.server.ts +63 -11
  142. package/src/server/plugins/ssr.ts +29 -2
  143. package/src/server/routes/btw/events.ts +70 -0
  144. package/src/server/routes/btw/index.ts +8 -0
  145. package/src/server/routes/btw/topics.ts +87 -0
  146. package/src/server/routes/btw/ws.ts +136 -0
  147. package/src/server/routes/chat/index.ts +2 -0
  148. package/src/server/routes/chat/session.ts +1 -115
  149. package/src/server/routes/chat/turns.ts +87 -0
  150. package/src/server/routes/fs/index.ts +4 -1
  151. package/src/server/routes/fs/raw.ts +85 -0
  152. package/src/server/routes/fs/read.ts +58 -3
  153. package/src/server/routes/index.ts +7 -1
  154. package/src/server/routes/models/root.ts +88 -215
  155. package/src/server/routes/settings/commands.ts +59 -18
  156. package/src/shared/lib/chat/attachments.test.ts +208 -0
  157. package/src/shared/lib/chat/attachments.ts +200 -15
  158. package/src/shared/lib/chat/btw/client.ts +94 -0
  159. package/src/shared/lib/chat/composer/client.test.ts +48 -0
  160. package/src/shared/lib/chat/composer/client.ts +23 -9
  161. package/src/shared/lib/chat/composer/commands.ts +290 -0
  162. package/src/shared/lib/chat/composer/composer.test.ts +195 -0
  163. package/src/shared/lib/chat/composer/filter.ts +21 -7
  164. package/src/shared/lib/chat/composer/trigger.ts +154 -21
  165. package/src/shared/lib/chat/omp/agent-events.ts +33 -80
  166. package/src/shared/lib/chat/omp/socket.ts +11 -6
  167. package/src/shared/lib/chat/omp/sse.ts +11 -6
  168. package/src/shared/lib/chat/omp/tool-results.ts +102 -0
  169. package/src/shared/lib/chat/omp/transport.ts +19 -3
  170. package/src/shared/lib/chat/text-file.ts +148 -0
  171. package/src/shared/lib/chat/timeline/omp-callbacks.ts +18 -32
  172. package/src/shared/lib/chat/timeline/stream-coalescer.ts +66 -0
  173. package/src/shared/lib/chat/timeline/turns.ts +7 -0
  174. package/src/shared/lib/fs/file-kind.ts +50 -0
  175. package/src/shared/lib/fs/paths.ts +19 -1
  176. package/src/shared/lib/markdown/math.test.ts +20 -3
  177. package/src/shared/lib/models/preferences.test.ts +131 -0
  178. package/src/shared/lib/models/preferences.ts +88 -0
  179. package/src/shared/lib/models/provider-models.ts +8 -1
  180. package/src/shared/lib/omp/session/inlined-attachments.test.ts +82 -0
  181. package/src/shared/lib/omp/session/mapper.ts +24 -4
  182. package/src/shared/lib/omp/session/messages-map.ts +16 -3
  183. package/src/shared/lib/omp/session/messages-parse.ts +2 -2
  184. package/src/shared/lib/omp/session/parse-message-blocks.ts +85 -5
  185. package/src/shared/lib/omp/subagent/label.test.ts +94 -0
  186. package/src/shared/lib/omp/subagent/label.ts +84 -0
  187. package/src/shared/lib/workspace/panel-widths.test.ts +113 -18
  188. package/src/shared/lib/workspace/panel-widths.ts +161 -30
  189. package/src/shared/lib/workspace/right-panels.ts +50 -11
  190. package/src/shared/lib/workspace/session-state/store.ts +3 -0
  191. package/src/shared/types/btw.ts +65 -0
  192. package/src/shared/types/chat.ts +77 -66
  193. package/src/shared/types/index.ts +2 -0
  194. package/src/shared/types/models.ts +101 -0
  195. package/src/shared/types/omp/agent.ts +14 -1
  196. package/src/shared/types/omp/session.ts +4 -1
  197. package/src/shared/types/omp/subagent.ts +4 -0
  198. package/src/shared/types/settings/command.ts +13 -0
  199. package/src/shared/types/settings/state.ts +5 -0
  200. package/dist/client/static/css/index.e880517fcd.css +0 -2
  201. package/dist/client/static/js/async/5bh.8b2363424f.js +0 -1
  202. package/dist/client/static/js/async/66.5dfa29f957.js +0 -93
  203. package/dist/client/static/js/async/7g.a7814350c3.js +0 -1
  204. package/dist/client/static/js/async/7l.7a6a377ecc.js +0 -1
  205. package/dist/client/static/js/async/cx.ca5feec570.js +0 -226
  206. package/dist/client/static/js/async/e.93214d622b.js +0 -79
  207. package/dist/client/static/js/async/g.a06ca3b3e9.js +0 -2
  208. package/dist/client/static/js/async/h1.e8d5aa8e80.js +0 -1
  209. package/dist/client/static/js/async/hs.6d480d0ded.js +0 -41
  210. package/dist/client/static/js/async/jl.874d352278.js +0 -1
  211. package/dist/client/static/js/async/mt.0352e976d8.js +0 -1
  212. package/dist/client/static/js/async/nam.b5663e919f.js +0 -10
  213. package/dist/client/static/js/async/q.23af2a358f.js +0 -21
  214. package/dist/client/static/js/async/q5.e683f7c26e.js +0 -286
  215. package/dist/client/static/js/async/s.222ee974f6.js +0 -2
  216. package/dist/client/static/js/async/uf.46ad6209fa.js +0 -2
  217. package/dist/client/static/js/async/vt.42416b707d.js +0 -1
  218. package/dist/client/static/js/async/x1.da8687159b.js +0 -90
  219. package/dist/client/static/js/async/yg.35bebd6d0c.js +0 -149
  220. package/dist/client/static/js/index.0de15c5e17.js +0 -33
  221. package/dist/client/static/js/jp.50817896f3.js +0 -139
  222. /package/dist/client/static/js/{jp.50817896f3.js.LICENSE.txt → 77.8022a800b5.js.LICENSE.txt} +0 -0
  223. /package/dist/client/static/js/async/{1k.5974df3b87.js.LICENSE.txt → 1k.a411fe5b43.js.LICENSE.txt} +0 -0
  224. /package/dist/client/static/js/async/{3y.71f2ccf3b6.js.LICENSE.txt → 3y.3186ecdd63.js.LICENSE.txt} +0 -0
  225. /package/dist/client/static/js/async/{dc.856fda6560.js.LICENSE.txt → ar.ad5c8822a8.js.LICENSE.txt} +0 -0
  226. /package/dist/client/static/js/async/{m.c038c71b9f.js.LICENSE.txt → f7.46971e9d6d.js.LICENSE.txt} +0 -0
  227. /package/dist/client/static/js/async/{5b.0d6ae50fe8.js.LICENSE.txt → g.ee41bfed7f.js.LICENSE.txt} +0 -0
  228. /package/dist/client/static/js/async/{q.23af2a358f.js.LICENSE.txt → m.2e1ea3db9e.js.LICENSE.txt} +0 -0
  229. /package/dist/client/static/js/async/{s.222ee974f6.js.LICENSE.txt → m3.d2b05f9604.js.LICENSE.txt} +0 -0
  230. /package/dist/client/static/js/async/{g.a06ca3b3e9.js.LICENSE.txt → q.b453193538.js.LICENSE.txt} +0 -0
  231. /package/dist/client/static/js/async/{uf.46ad6209fa.js.LICENSE.txt → q8.7f1b48e9cd.js.LICENSE.txt} +0 -0
  232. /package/dist/client/static/js/async/{nam.b5663e919f.js.LICENSE.txt → yx.af2936c368.js.LICENSE.txt} +0 -0
  233. /package/dist/client/static/js/{index.0de15c5e17.js.LICENSE.txt → index.57b39ffa7f.js.LICENSE.txt} +0 -0
@@ -3,13 +3,34 @@ import type { ApprovalMode } from '@/shared/lib/omp/config/access-mode';
3
3
 
4
4
  export interface Attachment {
5
5
  id: string;
6
+ /**
7
+ * Display name. Written at creation so a replayed attachment — one that has
8
+ * been through the queue's JSON round trip or back out of committed history —
9
+ * still renders and still inlines.
10
+ */
6
11
  name?: string;
7
- file: File;
12
+ /**
13
+ * Live file handle. ABSENT on every replayed attachment: `File` is not
14
+ * serializable (`JSON.stringify(new File(...))` is `{}`), so the queue row and
15
+ * the committed message keep only the display fields below. Read the fields
16
+ * through `@/shared/lib/chat/attachments` accessors — `a.file.name` throws
17
+ * here, which is what used to break queue delivery and retry.
18
+ */
19
+ file?: File;
8
20
  preview: string;
9
21
  type?: string;
10
22
  size?: number;
11
23
  /** Base64 payload for image attachments (sent to the omp model). */
12
24
  dataBase64?: string;
25
+ /** Inlined text-file contents, persisted with the committed user turn so a
26
+ * retry can re-send them without the original `File`. */
27
+ content?: string;
28
+ /**
29
+ * Set when `content` came from sniffing the file's bytes rather than from its
30
+ * name or MIME. A promised-file drag from another app has neither, so without
31
+ * this marker the send path would classify it as binary and drop it again.
32
+ */
33
+ sniffedText?: boolean;
13
34
  }
14
35
 
15
36
  export type ChatAttachment = Attachment;
@@ -166,6 +187,23 @@ export interface ChatMessageData {
166
187
  };
167
188
  }
168
189
 
190
+ /** One user turn of a session's FULL history, as listed by
191
+ * `GET /api/chat/:sessionId/turns`. The timeline jump rail draws one tick per
192
+ * entry and pages the timeline to it, so an entry carries the row id the
193
+ * timeline renders (the jump target) and the row's position in the full
194
+ * message list (`index`, the cursor the older-window loader pages from). */
195
+ export interface UserTurnRef {
196
+ id: string;
197
+ /** 0-based position in the session's full message list. `-1` for a row that
198
+ * exists only in the live timeline (an optimistic send the committed
199
+ * history does not carry yet) — such a row is always mounted. */
200
+ index: number;
201
+ /** Truncated prompt text for the rail tooltip. */
202
+ preview: string;
203
+ date?: string;
204
+ timestamp?: string;
205
+ }
206
+
169
207
  /** Model settings snapshotted with a queued message so auto-delivery replays
170
208
  * them (set_model / set_thinking_level RPC + spawn access mode) instead of
171
209
  * using whatever the session happens to run with at delivery time. */
@@ -187,71 +225,6 @@ export interface QueuedMessage {
187
225
  model: QueuedMessageModel | null;
188
226
  }
189
227
 
190
- export interface AIModelOption {
191
- id: string;
192
- name: string;
193
- provider: string;
194
- providerIcon?: string;
195
- contextWindow?: string | number;
196
- isCmdAgent?: boolean;
197
- isFavorite?: boolean;
198
- isRecent?: boolean;
199
- thinkingLevel?: string;
200
- /** Baked thinking ladder for this model: `["off", ...efforts]`. */
201
- thinkingLevels?: string[];
202
- capabilities?: string[];
203
- input?: string;
204
- output?: string;
205
- cost?: {
206
- input: string | number;
207
- output: string | number;
208
- cacheRead?: string | number;
209
- cacheWrite?: string | number;
210
- };
211
- description?: string;
212
- }
213
-
214
- // ── Real omp model registry (forked from omp-web) ──────────────────────────
215
-
216
- /** One pickable model from the omp catalog (`/api/models` modelList). */
217
- export interface ModelEntry {
218
- id: string;
219
- name: string;
220
- provider: string;
221
- supportsFastMode?: boolean;
222
- contextWindow?: number;
223
- maxTokens?: number;
224
- /** Baked thinking ladder for this model: `["off", ...efforts]`. */
225
- thinkingLevels?: string[];
226
- /** Cost in $/1M tokens (omp catalog). */
227
- cost?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number };
228
- }
229
-
230
- /** A model selected by provider + modelId (omp's set_model shape). */
231
- export interface SelectedModel {
232
- provider: string;
233
- modelId: string;
234
- }
235
-
236
- /** Model-level thinking metadata read off the live session state. */
237
- export interface ThinkingModelMeta {
238
- provider: string;
239
- modelId: string;
240
- name?: string;
241
- reasoning?: boolean;
242
- thinking?: { efforts?: string[] };
243
- }
244
-
245
- /** Response shape of GET /api/models (mirrors omp-web ModelsData). */
246
- export interface ModelsData {
247
- models: Record<string, string>;
248
- modelList: ModelEntry[];
249
- defaultModel: SelectedModel | null;
250
- thinkingLevels: Record<string, string[]>;
251
- connectedProviders?: { id: string; name: string; disabled: boolean }[];
252
- modelError?: string;
253
- }
254
-
255
228
  // ── Composer autocomplete (@file/agent / /command+skill) ───────────────────
256
229
 
257
230
  /** Trigger group that opened the composer autocomplete: `@` → mention, `/` → command. */
@@ -259,6 +232,13 @@ export type ComposerPickKind = 'mention' | 'command';
259
232
  /** Origin of a pickable item: an `@` mention is an agent or a workspace file. */
260
233
  export type ComposerPickSource = 'agent' | 'file' | 'command' | 'skill';
261
234
 
235
+ /**
236
+ * Which part of a slash invocation the popup is completing. oh-my-pi splits
237
+ * these the same way: `name` completes the command token itself, `args`
238
+ * completes a declarative subcommand after `<command> `.
239
+ */
240
+ export type ComposerTriggerPhase = 'name' | 'args';
241
+
262
242
  /** A detected trigger: the `@`/`/` char plus the query typed after it. */
263
243
  export interface ComposerTrigger {
264
244
  kind: ComposerPickKind;
@@ -267,6 +247,18 @@ export interface ComposerTrigger {
267
247
  start: number;
268
248
  /** Caret index when detected. */
269
249
  end: number;
250
+ /** Command completion phase; `mention` triggers are always `name`. */
251
+ phase: ComposerTriggerPhase;
252
+ /** Index the accepted text replaces from — equals `start` in the `name` phase. */
253
+ replaceFrom: number;
254
+ /** Command the `args` phase belongs to (name or alias as typed). */
255
+ command?: string;
256
+ /**
257
+ * The `/token` sits mid-prompt (prose precedes it on the line or an earlier
258
+ * line exists), so only skill entries may surface — oh-my-pi's
259
+ * `buildMidPromptSkillCompletions` gate.
260
+ */
261
+ midPrompt?: boolean;
270
262
  }
271
263
 
272
264
  /** One autocomplete item surfaced in the composer popover. */
@@ -281,6 +273,25 @@ export interface ComposerPickItem {
281
273
  token: string;
282
274
  /** Workspace-relative path (file items only). */
283
275
  path?: string;
276
+ /**
277
+ * Suppress the trailing space on insertion. Set on the collapsed `/skill:`
278
+ * namespace row so the popup reopens with the individual skills, matching
279
+ * oh-my-pi's accept path.
280
+ */
281
+ insertWithoutSpace?: boolean;
282
+ /** Command aliases from oh-my-pi (`/models` for `/model`). */
283
+ aliases?: string[];
284
+ /** Declarative subcommands; drives the `args` phase. */
285
+ subcommands?: ComposerSubcommand[];
286
+ /** Argument hint (`[on|off|status]`), prefixed to the description like omp. */
287
+ inputHint?: string;
288
+ }
289
+
290
+ /** One declarative subcommand of an oh-my-pi slash command. */
291
+ export interface ComposerSubcommand {
292
+ name: string;
293
+ description?: string;
294
+ usage?: string;
284
295
  }
285
296
 
286
297
  /** A pick item after filtering, with the matched range within `name` (or null). */
@@ -2,6 +2,8 @@ export * from '@/shared/types/workspace';
2
2
  export * from '@/shared/types/fs';
3
3
  export * from '@/shared/types/git';
4
4
  export * from '@/shared/types/chat';
5
+ export * from '@/shared/types/btw';
6
+ export * from '@/shared/types/models';
5
7
  export * from '@/shared/types/terminal';
6
8
  export * from '@/shared/types/settings/state';
7
9
  export * from '@/shared/types/tokenUsage';
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @license
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ /**
7
+ * Model catalog types shared by the composer picker, the settings pages and
8
+ * the `/api/models` route: the picker row (`AIModelOption`), the registry entry
9
+ * (`ModelEntry`), the selection reference omp's `set_model` takes, and the
10
+ * stored favorite/recent preference pair.
11
+ *
12
+ * Split out of `chat.ts` so that file stays under the per-file ceiling — the
13
+ * picker's row shape is not part of the chat message model it was nested in.
14
+ */
15
+
16
+ export interface AIModelOption {
17
+ id: string;
18
+ name: string;
19
+ provider: string;
20
+ providerIcon?: string;
21
+ contextWindow?: string | number;
22
+ isCmdAgent?: boolean;
23
+ /**
24
+ * Favorite / last-used flag. On a picker row these are DERIVED from the
25
+ * stored preference keys (`ModelPreferences`), never read off the registry —
26
+ * a favorite is a chamber-local preference, not a property of omp's config.
27
+ * On the MOCK catalog they are the seed for a fresh install's rails.
28
+ */
29
+ isFavorite?: boolean;
30
+ /** MOCK seed only — the RECENT rail is ordered by `ModelPreferences.recentKeys`. */
31
+ isRecent?: boolean;
32
+ thinkingLevel?: string;
33
+ /** Baked thinking ladder for this model: `["off", ...efforts]`. */
34
+ thinkingLevels?: string[];
35
+ capabilities?: string[];
36
+ input?: string;
37
+ output?: string;
38
+ cost?: {
39
+ input: string | number;
40
+ output: string | number;
41
+ cacheRead?: string | number;
42
+ cacheWrite?: string | number;
43
+ };
44
+ description?: string;
45
+ }
46
+
47
+ // ── Real omp model registry (forked from omp-web) ──────────────────────────
48
+
49
+ /** One pickable model from the omp catalog (`/api/models` modelList). */
50
+ export interface ModelEntry {
51
+ id: string;
52
+ name: string;
53
+ provider: string;
54
+ supportsFastMode?: boolean;
55
+ contextWindow?: number;
56
+ maxTokens?: number;
57
+ /** Baked thinking ladder for this model: `["off", ...efforts]`. */
58
+ thinkingLevels?: string[];
59
+ /** Cost in $/1M tokens (omp catalog). */
60
+ cost?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number };
61
+ }
62
+
63
+ /** A model selected by provider + modelId (omp's set_model shape). */
64
+ export interface SelectedModel {
65
+ provider: string;
66
+ modelId: string;
67
+ }
68
+
69
+ /** Model-level thinking metadata read off the live session state. */
70
+ export interface ThinkingModelMeta {
71
+ provider: string;
72
+ modelId: string;
73
+ name?: string;
74
+ reasoning?: boolean;
75
+ thinking?: { efforts?: string[] };
76
+ }
77
+
78
+ /**
79
+ * The user's favorite + last-used models, keyed by the composite `provider:id`
80
+ * identity (`modelKey`). Stored separately from the model registry because the
81
+ * registry is a read-only view of omp's config — a favorite is a chamber-local
82
+ * preference, and an id-only key would light up every provider serving it.
83
+ */
84
+ export interface ModelPreferences {
85
+ /** Composite keys in the order the FAVORITES rail renders them. */
86
+ favorites: string[];
87
+ /** Composite keys, most recently used first, capped at `RECENT_MODELS_LIMIT`. */
88
+ recentKeys: string[];
89
+ }
90
+
91
+ /** Response shape of GET /api/models (mirrors omp-web ModelsData). */
92
+ export interface ModelsData {
93
+ models: Record<string, string>;
94
+ modelList: ModelEntry[];
95
+ defaultModel: SelectedModel | null;
96
+ thinkingLevels: Record<string, string[]>;
97
+ connectedProviders?: { id: string; name: string; disabled: boolean }[];
98
+ modelError?: string;
99
+ /** Absent when the settings row has never been written. */
100
+ modelPreferences?: ModelPreferences;
101
+ }
@@ -38,6 +38,12 @@ export interface OmpAgentCallbacks {
38
38
  * on the live stream: it never enters get_state.messages or the session
39
39
  * JSONL, so the timeline must render it from this frame or it is lost. */
40
40
  onCommandOutput?: (text: string) => void;
41
+ /** omp changed the session's display title (auto-generation, /rename, or an
42
+ * RPC set_session_name). The frame is the only push signal for it — the
43
+ * sidebar reads titles from the session file, which the 256-byte slot write
44
+ * updates without changing the scan cache's mtime key — so consumers must
45
+ * revalidate the session list from here. */
46
+ onSessionTitleChanged?: (title: string) => void;
41
47
  onNotice?: (level: string, message: string) => void;
42
48
  onConnected?: () => void;
43
49
  /** Mount-time probe found the session mid-run → the stream was reattached
@@ -61,8 +67,15 @@ export interface OmpAgentState {
61
67
  error: string | null;
62
68
  }
63
69
 
64
- /** An attached image payload accepted by every prompt-bearing RPC command. */
70
+ /**
71
+ * An attached image payload accepted by every prompt-bearing RPC command.
72
+ * `type` is part of omp's `ImageContent` contract and is REQUIRED: omp's
73
+ * history encoder (`pi-ai/src/dialect/history.ts`) and its text fallback
74
+ * (`pi-ai/src/dialect/rendering.ts`) both select blocks by `type === "image"`,
75
+ * so a payload without it is dropped from the model's context.
76
+ */
65
77
  export interface AgentImage {
78
+ type: 'image';
66
79
  data: string;
67
80
  mimeType: string;
68
81
  }
@@ -132,7 +132,10 @@ export interface OmpSession extends OmpSessionBase {
132
132
  name?: string;
133
133
  /** ISO timestamp of session creation (header timestamp). */
134
134
  created: string;
135
- /** ISO timestamp of last modification (file mtime). */
135
+ /** ISO timestamp of the session's last entry — the newest JSONL record's own
136
+ * `timestamp`. Drives "latest session" ordering and the row's relative age;
137
+ * the file mtime is deliberately not used (a title-slot rewrite bumps it
138
+ * without a turn having happened). */
136
139
  modified: string;
137
140
  /** Parent session id when this session was forked/branched. */
138
141
  parentSessionId?: string;
@@ -150,6 +150,10 @@ export interface SubagentInfo {
150
150
  detached?: boolean;
151
151
  progress?: SubagentProgress;
152
152
  lastUpdate?: number;
153
+ /** Model role the run resolved to. On-disk history entries carry it here
154
+ * (folded from the parent's task toolResult); live snapshots carry it on
155
+ * `progress` instead, because it arrives with the progress frame. */
156
+ modelRole?: string;
153
157
  /** Settled result for history entries (SingleResult-derived). */
154
158
  result?: SubagentHistoryResult;
155
159
  /** Roster origin: live frames/snapshots (default) vs on-disk history. */
@@ -1,5 +1,12 @@
1
1
  export type CommandScope = 'system' | 'user' | 'project';
2
2
 
3
+ /** Declarative subcommand of an oh-my-pi builtin (drives `/cmd <sub>` completion). */
4
+ export interface CommandSubcommand {
5
+ name: string;
6
+ description?: string;
7
+ usage?: string;
8
+ }
9
+
3
10
  export interface CommandItem {
4
11
  id: string;
5
12
  name: string;
@@ -9,4 +16,10 @@ export interface CommandItem {
9
16
  overrideModel?: string;
10
17
  template: string;
11
18
  isBuiltIn?: boolean;
19
+ /** oh-my-pi aliases (`/models` for `/model`); live agent commands only. */
20
+ aliases?: string[];
21
+ /** Declarative subcommands; live agent commands only. */
22
+ subcommands?: CommandSubcommand[];
23
+ /** Argument hint (`[on|off|status]`); live agent commands only. */
24
+ inputHint?: string;
12
25
  }
@@ -40,6 +40,11 @@ export interface SettingsState {
40
40
  editorFont: string;
41
41
  streamResponses: boolean;
42
42
  streamTransport: StreamTransport;
43
+ /** Generate a session title from the first settled run. omp suppresses its
44
+ * own auto-titling under `--mode rpc-ui` (PI_NO_TITLE), so without this a
45
+ * chamber session keeps its `New Session - <timestamp>` placeholder. A
46
+ * user-set name is never overwritten. */
47
+ autoSessionTitle: boolean;
43
48
  expandedThinking: boolean;
44
49
  detailedToolCalls: boolean;
45
50
  notificationsEnabled: boolean;