@oh-my-pi/pi-coding-agent 16.1.9 → 16.1.11

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 (81) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/cli.js +3455 -3430
  3. package/dist/types/config/settings-schema.d.ts +10 -0
  4. package/dist/types/edit/streaming.d.ts +5 -5
  5. package/dist/types/export/html/index.d.ts +31 -2
  6. package/dist/types/export/html/web-palette.d.ts +117 -0
  7. package/dist/types/hindsight/content.d.ts +7 -0
  8. package/dist/types/hindsight/transcript.d.ts +1 -1
  9. package/dist/types/modes/components/hook-editor.d.ts +2 -1
  10. package/dist/types/modes/controllers/selector-controller.d.ts +0 -1
  11. package/dist/types/modes/interactive-mode.d.ts +5 -0
  12. package/dist/types/modes/types.d.ts +17 -0
  13. package/dist/types/modes/utils/keybinding-matchers.d.ts +13 -0
  14. package/dist/types/sdk.d.ts +1 -0
  15. package/dist/types/session/agent-session.d.ts +4 -0
  16. package/dist/types/session/session-context.d.ts +2 -0
  17. package/dist/types/session/session-entries.d.ts +6 -0
  18. package/dist/types/session/session-manager.d.ts +2 -1
  19. package/dist/types/system-prompt.d.ts +2 -0
  20. package/dist/types/tools/acp-bridge.d.ts +29 -0
  21. package/dist/types/tools/browser/aria/aria-snapshot.d.ts +39 -0
  22. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +10 -0
  23. package/dist/types/tools/browser/tab-worker.d.ts +20 -0
  24. package/dist/types/tools/browser.d.ts +1 -0
  25. package/dist/types/tools/find.d.ts +1 -2
  26. package/dist/types/tools/write.d.ts +1 -2
  27. package/dist/types/utils/image-loading.d.ts +4 -3
  28. package/dist/types/utils/jj.d.ts +25 -0
  29. package/dist/types/utils/title-generator.d.ts +0 -2
  30. package/package.json +12 -12
  31. package/scripts/generate-aria-snapshot.ts +134 -0
  32. package/scripts/generate-share-viewer.ts +4 -2
  33. package/src/autoresearch/git.ts +12 -0
  34. package/src/config/settings-schema.ts +12 -0
  35. package/src/discovery/opencode.ts +47 -4
  36. package/src/edit/hashline/filesystem.ts +8 -0
  37. package/src/edit/modes/patch.ts +18 -2
  38. package/src/edit/modes/replace.ts +13 -10
  39. package/src/edit/streaming.ts +5 -5
  40. package/src/export/html/index.ts +50 -8
  41. package/src/export/html/web-palette.ts +142 -0
  42. package/src/hindsight/backend.ts +4 -4
  43. package/src/hindsight/content.ts +17 -1
  44. package/src/hindsight/transcript.ts +2 -2
  45. package/src/internal-urls/docs-index.generated.txt +1 -1
  46. package/src/modes/components/agent-dashboard.ts +8 -8
  47. package/src/modes/components/hook-editor.ts +13 -10
  48. package/src/modes/components/session-selector.ts +3 -0
  49. package/src/modes/controllers/event-controller.ts +29 -5
  50. package/src/modes/controllers/extension-ui-controller.ts +6 -2
  51. package/src/modes/controllers/selector-controller.ts +3 -5
  52. package/src/modes/interactive-mode.ts +69 -29
  53. package/src/modes/theme/dark.json +1 -1
  54. package/src/modes/types.ts +18 -0
  55. package/src/modes/utils/keybinding-matchers.ts +36 -1
  56. package/src/modes/utils/ui-helpers.ts +1 -0
  57. package/src/prompts/system/project-prompt.md +2 -0
  58. package/src/prompts/system/system-prompt.md +0 -1
  59. package/src/prompts/tools/browser.md +5 -2
  60. package/src/sdk.ts +20 -2
  61. package/src/session/agent-session.ts +38 -14
  62. package/src/session/session-context.ts +5 -0
  63. package/src/session/session-entries.ts +6 -0
  64. package/src/session/session-manager.ts +3 -1
  65. package/src/system-prompt.ts +15 -3
  66. package/src/task/worktree.ts +12 -4
  67. package/src/thinking.ts +1 -1
  68. package/src/tools/acp-bridge.ts +66 -0
  69. package/src/tools/bash.ts +3 -3
  70. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  71. package/src/tools/browser/aria/aria-snapshot.ts +103 -0
  72. package/src/tools/browser/cmux/cmux-tab.ts +73 -1
  73. package/src/tools/browser/tab-worker.ts +242 -47
  74. package/src/tools/browser.ts +5 -0
  75. package/src/tools/find.ts +1 -2
  76. package/src/tools/index.ts +1 -1
  77. package/src/tools/write.ts +3 -27
  78. package/src/utils/git.ts +3 -2
  79. package/src/utils/image-loading.ts +6 -3
  80. package/src/utils/jj.ts +47 -0
  81. package/src/utils/title-generator.ts +31 -99
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Web/export palette — the omp brand identity shared by the collab-web live
3
+ * client (`my.omp.sh/`) and every public HTML export / share viewer (`/s/<id>`).
4
+ *
5
+ * Why this exists separately from `modes/theme/dark.json`: the `dark` theme is
6
+ * the **default TUI theme** — its amber accent (`#febc38`) drives the terminal
7
+ * status line, syntax highlighting, thinking levels, and bash/python mode
8
+ * colors for every omp user. The public web artifacts want the collab-web
9
+ * pink/purple identity instead, so they pin this palette rather than inheriting
10
+ * the TUI's. Editing `dark.json` to repurpose it for the web would repaint
11
+ * every terminal; this file keeps the two surfaces decoupled.
12
+ *
13
+ * Token layout — emitted as CSS custom properties on `:root`:
14
+ * • Legacy export names consumed by `template.css` / `template.js`
15
+ * (`--text`, `--body-bg`, `--container-bg`, `--info-bg`, `--accent`,
16
+ * `--border`, `--success`, `--error`, `--warning`, `--muted`, `--dim`,
17
+ * `--borderAccent`, `--selectedBg`, `--userMessageBg`, `--customMessageBg`,
18
+ * `--customMessageLabel`, `--mdHeading`, `--mdLink`, `--mdCode`,
19
+ * `--mdListBullet`, `--toolOutput`, `--thinkingText`, syntax*, …).
20
+ * • collab-web-native aliases consumed by the `tv-` tool-render bridge
21
+ * (`tool-render.css`: `var(--bg-inset, …)`, `var(--fg, …)`, …) so embedded
22
+ * tool cards resolve to the *real* collab-web tokens and render
23
+ * pixel-identical to the live client.
24
+ *
25
+ * Alpha-bearing tokens (`--border`, `--ring`, `--accent-muted`, …) keep their
26
+ * `oklch(… / N%)` form — flattening them to opaque hex would produce harsh
27
+ * white borders and non-matching translucent focus rings. Opaque surfaces are
28
+ * sRGB hex (the collab-web `tokens.css` OKLCH dark-theme tokens converted via
29
+ * the standard OKLab→linear-sRGB→gamma path); if the live client palette
30
+ * changes, regenerate those from there.
31
+ */
32
+ export const WEB_EXPORT_PALETTE = {
33
+ // --- collab-web-native aliases (tv- bridge) ---
34
+ "--bg": "#0f0b14",
35
+ "--bg-raised": "#16111c",
36
+ "--bg-inset": "#09060c",
37
+ "--bg-overlay": "#211b28",
38
+ "--fg": "#e6e3ea",
39
+ "--fg-muted": "#a49faa",
40
+ "--fg-faint": "#6e6974",
41
+ "--accent": "#ed4abf",
42
+ "--accent-muted": "oklch(0.674 0.23 341 / 18%)",
43
+ "--ok": "#68ca80",
44
+ "--err": "#f05653",
45
+ "--warn": "#e4b33f",
46
+ "--ring": "oklch(0.817 0.112 205 / 70%)",
47
+ "--font-mono": 'ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Mono", Menlo, Consolas, monospace',
48
+
49
+ // --- legacy export names (template.css / template.js) ---
50
+ // surfaces — map onto the collab-web purple ramp
51
+ "--body-bg": "#0f0b14", // = --bg
52
+ "--container-bg": "#16111c", // = --bg-raised
53
+ "--info-bg": "#09060c", // = --bg-inset (recessed wells: code blocks, tool output)
54
+ // text
55
+ "--text": "#e6e3ea", // = --fg
56
+ "--muted": "#a49faa", // = --fg-muted
57
+ "--dim": "#6e6974", // = --fg-faint
58
+ "--thinkingText": "#a49faa",
59
+ // hairlines — white-alpha, matching collab-web's --border/--border-strong
60
+ "--border": "oklch(1 0 0 / 9%)",
61
+ "--borderMuted": "oklch(1 0 0 / 6%)",
62
+ // accent + brand purple (the gradient's mid stop) for secondary highlights
63
+ "--borderAccent": "#945ff9",
64
+ "--selectedBg": "#2d2535",
65
+ // status — semantic, used sparingly (cancelled / exit-code / success dots)
66
+ "--success": "#68ca80", // = --ok
67
+ "--error": "#f05653", // = --err
68
+ "--warning": "#e4b33f", // = --warn
69
+ // message bubbles
70
+ "--userMessageBg": "oklch(0.674 0.23 341 / 6%)", // accent-tinted, like template.css user-message
71
+ "--userMessageText": "#e6e3ea",
72
+ "--customMessageBg": "#211b28", // = --bg-overlay
73
+ "--customMessageText": "#a49faa", // = --fg-muted
74
+ "--customMessageLabel": "#b281d6", // lilac, matching dark.json's label hue
75
+ // tool surfaces
76
+ "--toolPendingBg": "#16111c",
77
+ "--toolSuccessBg": "#09060c",
78
+ "--toolErrorBg": "oklch(0.66 0.19 25 / 14%)",
79
+ "--toolTitle": "#e6e3ea",
80
+ "--toolOutput": "#a49faa", // = --fg-muted
81
+ // markdown
82
+ "--mdHeading": "#ed4abf", // accent — headings carry the brand
83
+ "--mdLink": "#5ad8e5", // ring cyan — links distinct from the pink accent
84
+ "--mdLinkUrl": "#6e6974", // = --fg-faint
85
+ "--mdCode": "#e6e3ea",
86
+ "--mdCodeBlock": "#e6e3ea",
87
+ "--mdCodeBlockBorder": "oklch(1 0 0 / 9%)",
88
+ "--mdQuote": "#a49faa",
89
+ "--mdQuoteBorder": "oklch(1 0 0 / 13%)",
90
+ "--mdHr": "oklch(1 0 0 / 9%)",
91
+ "--mdListBullet": "#ed4abf", // accent — bullets carry the brand
92
+ // diff
93
+ "--toolDiffAdded": "#68ca80",
94
+ "--toolDiffRemoved": "#f05653",
95
+ "--toolDiffContext": "#6e6974",
96
+ // syntax — cool-neutral with pink/purple accents for keywords/types
97
+ "--syntaxComment": "#6e6974", // = --fg-faint
98
+ "--syntaxKeyword": "#945ff9", // brand purple
99
+ "--syntaxFunction": "#e4b33f", // warn amber (analog of dark.json's DCDCAA)
100
+ "--syntaxVariable": "#5ad8e5", // ring cyan
101
+ "--syntaxString": "#68ca80", // ok green
102
+ "--syntaxNumber": "#ed4abf", // accent
103
+ "--syntaxType": "#b281d6", // lilac
104
+ "--syntaxOperator": "#e6e3ea",
105
+ "--syntaxPunctuation": "#a49faa",
106
+ // thinking-level ramp — purple → lilac, matching the brand gradient
107
+ "--thinkingOff": "#6e6974",
108
+ "--thinkingMinimal": "#6e6974",
109
+ "--thinkingLow": "#945ff9",
110
+ "--thinkingMedium": "#b281d6",
111
+ "--thinkingHigh": "#ed4abf",
112
+ "--thinkingXhigh": "#e4b33f",
113
+ // mode tints (sidebar/role tags) — not surfaced in the export tree but
114
+ // emitted for completeness so template.js role classes resolve cleanly
115
+ "--bashMode": "#5ad8e5",
116
+ "--pythonMode": "#e4b33f",
117
+ // status-line tokens are TUI-only; not consumed by the export template, but
118
+ // emitted so any future surface that reads them inherits the brand.
119
+ "--statusLineBg": "#0f0b14",
120
+ "--statusLineSep": "#6e6974",
121
+ "--statusLineModel": "#ed4abf",
122
+ "--statusLinePath": "#5ad8e5",
123
+ "--statusLineGitClean": "#68ca80",
124
+ "--statusLineGitDirty": "#e4b33f",
125
+ "--statusLineContext": "#a49faa",
126
+ "--statusLineSpend": "#5ad8e5",
127
+ "--statusLineStaged": "#68ca80",
128
+ "--statusLineDirty": "#e4b33f",
129
+ "--statusLineUntracked": "#945ff9",
130
+ "--statusLineOutput": "#b281d6",
131
+ "--statusLineCost": "#b281d6",
132
+ "--statusLineSubagents": "#ed4abf",
133
+ } as const satisfies Record<string, string>;
134
+
135
+ /** Serialize the palette as `--key: value;` declarations for `:root { … }`. */
136
+ export function webExportThemeVars(): string {
137
+ let out = "";
138
+ for (const k in WEB_EXPORT_PALETTE) {
139
+ out += `${k}: ${WEB_EXPORT_PALETTE[k as keyof typeof WEB_EXPORT_PALETTE]}; `;
140
+ }
141
+ return out.trimEnd();
142
+ }
@@ -15,7 +15,7 @@ import type { AgentSession } from "../session/agent-session";
15
15
  import { type BankScope, computeBankScope } from "./bank";
16
16
  import { createHindsightClient } from "./client";
17
17
  import { isHindsightConfigured, loadHindsightConfig } from "./config";
18
- import type { HindsightMessage } from "./content";
18
+ import { type HindsightMessage, hasSubstantiveContent } from "./content";
19
19
  import { HindsightSessionState } from "./state";
20
20
 
21
21
  const STATIC_INSTRUCTIONS = [
@@ -330,7 +330,7 @@ function flattenMessagesForRecall(messages: AgentMessage[]): HindsightMessage[]
330
330
  if (msg.role === "user") {
331
331
  const content = msg.content;
332
332
  if (typeof content === "string") {
333
- if (content.trim()) out.push({ role: "user", content });
333
+ if (hasSubstantiveContent(content)) out.push({ role: "user", content });
334
334
  continue;
335
335
  }
336
336
  if (Array.isArray(content)) {
@@ -338,7 +338,7 @@ function flattenMessagesForRecall(messages: AgentMessage[]): HindsightMessage[]
338
338
  .filter((b): b is { type: "text"; text: string } => !!b && (b as { type?: unknown }).type === "text")
339
339
  .map(b => b.text)
340
340
  .join("\n");
341
- if (text.trim()) out.push({ role: "user", content: text });
341
+ if (hasSubstantiveContent(text)) out.push({ role: "user", content: text });
342
342
  }
343
343
  continue;
344
344
  }
@@ -347,7 +347,7 @@ function flattenMessagesForRecall(messages: AgentMessage[]): HindsightMessage[]
347
347
  .filter((b): b is { type: "text"; text: string } => b.type === "text")
348
348
  .map(b => b.text)
349
349
  .join("\n");
350
- if (text.trim()) out.push({ role: "assistant", content: text });
350
+ if (hasSubstantiveContent(text)) out.push({ role: "assistant", content: text });
351
351
  }
352
352
  }
353
353
  return out;
@@ -43,6 +43,22 @@ export function stripMemoryTags(content: string): string {
43
43
  .replace(LEGACY_RELEVANT_MEMORIES_REGEX, "");
44
44
  }
45
45
 
46
+ // At least one letter or digit means the message carries a token a retriever
47
+ // can actually match on. Punctuation/whitespace-only strings (e.g. the lone
48
+ // `.` some providers emit for tool-call-only or thinking-only assistant turns)
49
+ // are dropped before retain/recall touches them — see issue #1806.
50
+ const SUBSTANTIVE_CHAR_RE = /[\p{L}\p{N}]/u;
51
+
52
+ /**
53
+ * True when `content` carries at least one letter or digit. Used by retain
54
+ * and recall paths to drop placeholder assistant turns ("." / "..." / pure
55
+ * whitespace) that would otherwise pollute the bank and waste tokens on
56
+ * embeddings with no semantic content.
57
+ */
58
+ export function hasSubstantiveContent(content: string): boolean {
59
+ return SUBSTANTIVE_CHAR_RE.test(content);
60
+ }
61
+
46
62
  /** Format recall results into a bullet list for context injection. */
47
63
  export function formatMemories(results: RecallResultLike[]): string {
48
64
  if (results.length === 0) return "";
@@ -197,7 +213,7 @@ export function prepareRetentionTranscript(
197
213
  const parts: string[] = [];
198
214
  for (const msg of targetMessages) {
199
215
  const content = stripMemoryTags(msg.content).trim();
200
- if (!content) continue;
216
+ if (!hasSubstantiveContent(content)) continue;
201
217
  parts.push(`[role: ${msg.role}]\n${content}\n[${msg.role}:end]`);
202
218
  }
203
219
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  import type { AssistantMessage } from "@oh-my-pi/pi-ai";
11
11
  import type { SessionEntry } from "../session/session-entries";
12
- import type { HindsightMessage } from "./content";
12
+ import { type HindsightMessage, hasSubstantiveContent } from "./content";
13
13
 
14
14
  export interface ReadonlySessionManagerLike {
15
15
  getEntries(): SessionEntry[];
@@ -39,7 +39,7 @@ export function extractMessages(sessionManager: ReadonlySessionManagerLike): Hin
39
39
  if (role !== "user" && role !== "assistant") continue;
40
40
 
41
41
  const text = role === "user" ? extractUserText(msg) : extractAssistantText(msg as AssistantMessage);
42
- if (text.length === 0) continue;
42
+ if (!hasSubstantiveContent(text)) continue;
43
43
  messages.push({ role, content: text });
44
44
  }
45
45