neoctl 0.2.46 → 0.2.48

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 (85) hide show
  1. package/README.md +59 -59
  2. package/dist/agents/agent-activity.js +1 -1
  3. package/dist/agents/agent-activity.js.map +1 -1
  4. package/dist/agents/agent-tool.js +2 -1
  5. package/dist/agents/agent-tool.js.map +1 -1
  6. package/dist/context/compaction.d.ts +1 -0
  7. package/dist/context/compaction.js +6 -2
  8. package/dist/context/compaction.js.map +1 -1
  9. package/dist/context/prompts.js +3 -4
  10. package/dist/context/prompts.js.map +1 -1
  11. package/dist/context/system.md +16 -16
  12. package/dist/core/abortable-stream.d.ts +2 -0
  13. package/dist/core/abortable-stream.js +17 -0
  14. package/dist/core/abortable-stream.js.map +1 -1
  15. package/dist/core/compaction-progress.d.ts +1 -1
  16. package/dist/core/compaction-progress.js +7 -5
  17. package/dist/core/compaction-progress.js.map +1 -1
  18. package/dist/core/execution-state.d.ts +2 -0
  19. package/dist/core/execution-state.js +2 -1
  20. package/dist/core/execution-state.js.map +1 -1
  21. package/dist/core/message-pipeline.js +2 -2
  22. package/dist/core/message-pipeline.js.map +1 -1
  23. package/dist/core/query-engine.d.ts +12 -1
  24. package/dist/core/query-engine.js +125 -21
  25. package/dist/core/query-engine.js.map +1 -1
  26. package/dist/core/query.js +46 -6
  27. package/dist/core/query.js.map +1 -1
  28. package/dist/execution/filesystem.js +22 -22
  29. package/dist/execution/process.js +44 -44
  30. package/dist/model/model-gateway.d.ts +4 -0
  31. package/dist/model/model-gateway.js.map +1 -1
  32. package/dist/model/model-metadata.json +137 -137
  33. package/dist/model/openai-chat-mapper.js +2 -0
  34. package/dist/model/openai-chat-mapper.js.map +1 -1
  35. package/dist/model/openai-responses-mapper.js +3 -0
  36. package/dist/model/openai-responses-mapper.js.map +1 -1
  37. package/dist/model/tool-input-stream.d.ts +31 -0
  38. package/dist/model/tool-input-stream.js +226 -0
  39. package/dist/model/tool-input-stream.js.map +1 -0
  40. package/dist/repl/index.js +30 -30
  41. package/dist/repl/index.js.map +1 -1
  42. package/dist/session/session-store.js +2 -0
  43. package/dist/session/session-store.js.map +1 -1
  44. package/dist/session/tool-result-memory.js +2 -2
  45. package/dist/session/tool-result-memory.js.map +1 -1
  46. package/dist/tasks/subagent-tools.js +1 -1
  47. package/dist/tasks/subagent-tools.js.map +1 -1
  48. package/dist/tools/builtins/exec-process-manager.d.ts +2 -1
  49. package/dist/tools/builtins/exec-process-manager.js +2 -1
  50. package/dist/tools/builtins/exec-process-manager.js.map +1 -1
  51. package/dist/tools/builtins/exec-tool.js +1 -1
  52. package/dist/tools/builtins/exec-tool.js.map +1 -1
  53. package/dist/tools/builtins/image-capabilities.d.ts +2 -2
  54. package/dist/tools/builtins/image-capabilities.js +3 -3
  55. package/dist/tools/builtins/image-capabilities.js.map +1 -1
  56. package/dist/tools/builtins/image-generation-tool.js +1 -1
  57. package/dist/tools/builtins/image-generation-tool.js.map +1 -1
  58. package/dist/tools/builtins/image-loader-tool.js +2 -1
  59. package/dist/tools/builtins/image-loader-tool.js.map +1 -1
  60. package/dist/tools/run-tool-use.js +2 -1
  61. package/dist/tools/run-tool-use.js.map +1 -1
  62. package/dist/tools/terminal-output-store.d.ts +1 -0
  63. package/dist/tools/terminal-output-store.js +13 -1
  64. package/dist/tools/terminal-output-store.js.map +1 -1
  65. package/dist/types/events.d.ts +11 -0
  66. package/dist/web/demo-tools.js +1 -1
  67. package/dist/web/demo-tools.js.map +1 -1
  68. package/dist/web/html.js +5 -5
  69. package/dist/web/image-result-metadata.d.ts +6 -0
  70. package/dist/web/image-result-metadata.js +3 -0
  71. package/dist/web/image-result-metadata.js.map +1 -1
  72. package/dist/web/index.d.ts +15 -1
  73. package/dist/web/index.js +134 -20
  74. package/dist/web/index.js.map +1 -1
  75. package/dist/web/terminal-presentation.js +1 -1
  76. package/dist/web/terminal-presentation.js.map +1 -1
  77. package/dist/web/tool-activity.d.ts +9 -0
  78. package/dist/web/tool-activity.js +19 -0
  79. package/dist/web/tool-activity.js.map +1 -0
  80. package/dist/web/tool-observation-result.d.ts +1 -0
  81. package/dist/web/tool-observation-result.js +35 -0
  82. package/dist/web/tool-observation-result.js.map +1 -0
  83. package/docs/prompt-config.md +86 -86
  84. package/package.json +1 -1
  85. package/scripts/copy-prompt-resources.mjs +5 -5
@@ -0,0 +1,226 @@
1
+ // Decode only the provider's tool-argument JSON protocol, never assistant prose.
2
+ // These drafts cannot execute tools; execution uses the validated final tool_use.
3
+ export const TOOL_INPUT_PREVIEW_LIMIT = 80_000;
4
+ const safeKey = (key) => !['__proto__', 'constructor', 'prototype'].includes(String(key));
5
+ /** Immutable path-copying: unchanged branches retain identity for UI subscriptions. */
6
+ export function applyToolInputChanges(input, changes) {
7
+ let result = input;
8
+ for (const change of changes) {
9
+ if (!change.path.length || change.path.length > 20 || change.path.some(key => !safeKey(key) || (typeof key === 'number' && (!Number.isSafeInteger(key) || key < 0 || key > 80000))))
10
+ continue;
11
+ const root = { ...result };
12
+ let target = root, source = result;
13
+ for (let i = 0; i < change.path.length; i++) {
14
+ const key = change.path[i], at = target;
15
+ const before = source && typeof source === 'object' ? source[key] : undefined;
16
+ if (i === change.path.length - 1) {
17
+ at[key] = change.op === 'append' ? (typeof before === 'string' ? before : '') + change.value : structuredClone(change.value);
18
+ }
19
+ else {
20
+ const child = Array.isArray(before) ? [...before] : before && typeof before === 'object' ? { ...before } : typeof change.path[i + 1] === 'number' ? [] : {};
21
+ at[key] = child;
22
+ target = child;
23
+ source = before;
24
+ }
25
+ }
26
+ result = root;
27
+ }
28
+ return result;
29
+ }
30
+ export class ToolInputStream {
31
+ frames = [];
32
+ root;
33
+ token;
34
+ size = 0;
35
+ invalid = false;
36
+ closed = false;
37
+ changes = [];
38
+ truncated = false;
39
+ /** Only newly decoded fields/string suffixes, not a full argument snapshot. */
40
+ append(delta) {
41
+ this.changes = [];
42
+ const room = Math.max(0, TOOL_INPUT_PREVIEW_LIMIT - this.size);
43
+ if (delta.length > room)
44
+ this.truncated = true;
45
+ const chunk = delta.slice(0, room);
46
+ this.size += chunk.length;
47
+ for (const c of chunk) {
48
+ if (this.invalid)
49
+ break;
50
+ this.consume(c);
51
+ }
52
+ return this.changes;
53
+ }
54
+ snapshot() { return structuredClone(this.root || {}); }
55
+ emit(change) {
56
+ const previous = this.changes.at(-1);
57
+ if (previous?.op === 'append' && change.op === 'append' && JSON.stringify(previous.path) === JSON.stringify(change.path)) {
58
+ previous.value += change.value;
59
+ return;
60
+ }
61
+ this.changes.push(change);
62
+ }
63
+ path() {
64
+ const f = this.frames.at(-1);
65
+ const key = Array.isArray(f.value) ? f.index : f.key;
66
+ return f.path && key !== undefined && safeKey(key) ? [...f.path, key] : undefined;
67
+ }
68
+ finish() { const f = this.frames.at(-1); f.state = 'comma'; f.key = undefined; f.index++; }
69
+ write(value) {
70
+ const f = this.frames.at(-1);
71
+ const key = Array.isArray(f.value) ? f.index : f.key;
72
+ const path = this.path();
73
+ if (path && key !== undefined) {
74
+ f.value[key] = value;
75
+ this.emit({ op: 'set', path, value: structuredClone(value) });
76
+ }
77
+ }
78
+ text(value) {
79
+ const t = this.token;
80
+ t.value += value;
81
+ if (!t.key && t.path) {
82
+ const f = this.frames.at(-1);
83
+ const key = t.path.at(-1);
84
+ f.value[key] = t.value;
85
+ this.emit({ op: 'append', path: t.path, value });
86
+ }
87
+ }
88
+ consume(c) {
89
+ const t = this.token;
90
+ if (t?.kind === 'string') {
91
+ if (t.unicode !== undefined) {
92
+ if (!/[\da-f]/i.test(c)) {
93
+ this.invalid = true;
94
+ return;
95
+ }
96
+ t.unicode += c;
97
+ if (t.unicode.length === 4) {
98
+ this.text(String.fromCharCode(parseInt(t.unicode, 16)));
99
+ t.unicode = undefined;
100
+ }
101
+ return;
102
+ }
103
+ if (t.escape) {
104
+ t.escape = false;
105
+ if (c === 'u') {
106
+ t.unicode = '';
107
+ return;
108
+ }
109
+ const escape = { '"': '"', '\\': '\\', '/': '/', n: '\n', r: '\r', t: '\t', b: '\b', f: '\f' };
110
+ if (!(c in escape)) {
111
+ this.invalid = true;
112
+ return;
113
+ }
114
+ this.text(escape[c]);
115
+ return;
116
+ }
117
+ if (c === '\\') {
118
+ t.escape = true;
119
+ return;
120
+ }
121
+ if (c === '"') {
122
+ if (t.key) {
123
+ const f = this.frames.at(-1);
124
+ f.key = t.value;
125
+ f.state = 'colon';
126
+ }
127
+ else
128
+ this.finish();
129
+ this.token = undefined;
130
+ return;
131
+ }
132
+ if (c < ' ') {
133
+ this.invalid = true;
134
+ return;
135
+ }
136
+ this.text(c);
137
+ return;
138
+ }
139
+ if (t?.kind === 'primitive') {
140
+ if (/[\s,}\]]/.test(c)) {
141
+ try {
142
+ this.write(JSON.parse(t.value));
143
+ this.finish();
144
+ }
145
+ catch {
146
+ this.invalid = true;
147
+ return;
148
+ }
149
+ this.token = undefined;
150
+ this.consume(c);
151
+ return;
152
+ }
153
+ t.value += c;
154
+ return;
155
+ }
156
+ if (/\s/.test(c))
157
+ return;
158
+ if (this.closed) {
159
+ this.invalid = true;
160
+ return;
161
+ }
162
+ const f = this.frames.at(-1);
163
+ if (!f) {
164
+ if (c !== '{' || this.root) {
165
+ this.invalid = true;
166
+ return;
167
+ }
168
+ this.root = {};
169
+ this.frames.push({ value: this.root, path: [], state: 'key', index: 0 });
170
+ return;
171
+ }
172
+ if ((c === '}' && !Array.isArray(f.value) && ['key', 'comma'].includes(f.state)) || (c === ']' && Array.isArray(f.value) && ['value', 'comma'].includes(f.state))) {
173
+ this.frames.pop();
174
+ if (!this.frames.length)
175
+ this.closed = true;
176
+ return;
177
+ }
178
+ if (f.state === 'key' || f.state === 'keyAfterComma') {
179
+ if (c !== '"') {
180
+ this.invalid = true;
181
+ return;
182
+ }
183
+ this.token = { kind: 'string', key: true, value: '', escape: false };
184
+ return;
185
+ }
186
+ if (f.state === 'colon') {
187
+ if (c !== ':') {
188
+ this.invalid = true;
189
+ return;
190
+ }
191
+ f.state = 'value';
192
+ return;
193
+ }
194
+ if (f.state === 'comma') {
195
+ if (c !== ',') {
196
+ this.invalid = true;
197
+ return;
198
+ }
199
+ f.state = Array.isArray(f.value) ? 'valueAfterComma' : 'keyAfterComma';
200
+ return;
201
+ }
202
+ if (c === '{' || c === '[') {
203
+ if (this.frames.length >= 20) {
204
+ this.invalid = true;
205
+ return;
206
+ }
207
+ const path = this.path(), value = c === '{' ? {} : [];
208
+ this.write(value);
209
+ this.finish();
210
+ this.frames.push({ value, path, state: c === '{' ? 'key' : 'value', index: 0 });
211
+ return;
212
+ }
213
+ if (c === '"') {
214
+ const path = this.path();
215
+ this.write('');
216
+ this.token = { kind: 'string', key: false, value: '', escape: false, path };
217
+ return;
218
+ }
219
+ if (!/[-\dtfn]/.test(c)) {
220
+ this.invalid = true;
221
+ return;
222
+ }
223
+ this.token = { kind: 'primitive', key: false, value: c, escape: false };
224
+ }
225
+ }
226
+ //# sourceMappingURL=tool-input-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-input-stream.js","sourceRoot":"","sources":["../../src/model/tool-input-stream.ts"],"names":[],"mappings":"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"}
@@ -1986,11 +1986,11 @@ function SubagentLivePanel({ activities, width: terminalWidth, animationTick })
1986
1986
  const activeCount = activities.filter((activity) => activity.status === "running" || activity.status === "pending").length;
1987
1987
  const recentCount = Math.max(0, activities.length - activeCount);
1988
1988
  const countText = activeCount > 1
1989
- ? `${activeCount} active${recentCount ? ` · ${recentCount} recent` : ""}`
1989
+ ? `${activeCount} active${recentCount ? ` ${recentCount} recent` : ""}`
1990
1990
  : recentCount && activeCount === 0
1991
1991
  ? `${recentCount} recent`
1992
1992
  : "";
1993
- const text = `↳ subagent ${subagentStatusText(selected.status, animationTick)}${countText ? ` · ${countText}` : ""} · ${compactAgentSummary(selected, width)}`;
1993
+ const text = `↳ subagent ${subagentStatusText(selected.status, animationTick)}${countText ? ` ${countText}` : ""} ${compactAgentSummary(selected, width)}`;
1994
1994
  return e(Text, { color: statusColor(selected.status) }, fitToWidth(text, width));
1995
1995
  }
1996
1996
  function sortAgentActivitiesForPanel(activities) {
@@ -2010,7 +2010,7 @@ function compactAgentSummary(activity, maxLength) {
2010
2010
  ? `${activity.currentTool.name}${activity.currentTool.inputPreview ? ` ${activity.currentTool.inputPreview}` : ""}`
2011
2011
  : firstSafeSubagentPreview(activity.resultPreview, activity.error, activity.lastText, activity.prompt);
2012
2012
  const elapsed = formatElapsed(Date.now() - new Date(activity.startedAt).getTime());
2013
- return truncateMiddle(`${activity.description || activity.agentId} · ${elapsed} · tools:${activity.totalToolUseCount} · ${current.replace(/\s+/g, " ")}`, Math.max(8, maxLength));
2013
+ return truncateMiddle(`${activity.description || activity.agentId} ${elapsed} tools:${activity.totalToolUseCount} ${current.replace(/\s+/g, " ")}`, Math.max(8, maxLength));
2014
2014
  }
2015
2015
  function firstSafeSubagentPreview(...values) {
2016
2016
  return values.find((value) => value && !isInternalContinuationPreview(value)) ?? "working";
@@ -2051,7 +2051,7 @@ function BackgroundTaskStatusLine({ tasks, width: terminalWidth }) {
2051
2051
  const width = statusBarWidth(terminalWidth);
2052
2052
  const summary = `◆ background tools: ${tasks.length} task${tasks.length === 1 ? "" : "s"}`;
2053
2053
  const detailTasks = tasks.slice(0, 2);
2054
- return e(Box, { flexDirection: "column", width, overflow: "hidden" }, e(Text, { color: "yellow" }, fitToWidth(summary, width)), ...detailTasks.map((task, index) => e(Text, { key: `bg-task-${task.taskId}-${index}`, color: "yellow" }, fitToWidth(` ${task.type}:${truncateMiddle(task.description || task.agentId || task.taskId, Math.max(12, width - 30))} · ${task.status} · ${formatElapsed(Date.now() - new Date(task.createdAt).getTime())}`, width))));
2054
+ return e(Box, { flexDirection: "column", width, overflow: "hidden" }, e(Text, { color: "yellow" }, fitToWidth(summary, width)), ...detailTasks.map((task, index) => e(Text, { key: `bg-task-${task.taskId}-${index}`, color: "yellow" }, fitToWidth(` ${task.type}:${truncateMiddle(task.description || task.agentId || task.taskId, Math.max(12, width - 30))} ${task.status} ${formatElapsed(Date.now() - new Date(task.createdAt).getTime())}`, width))));
2055
2055
  }
2056
2056
  function formatElapsed(ms) {
2057
2057
  const seconds = Math.max(0, Math.floor(ms / 1000));
@@ -2206,8 +2206,8 @@ function skillNameCompletions(skills, current, action) {
2206
2206
  }));
2207
2207
  }
2208
2208
  function formatSkillCompletionDescription(skill) {
2209
- const tags = skill.tags?.length ? ` · ${skill.tags.join(",")}` : "";
2210
- return `${skill.description}${skill.execution ? ` · ${skill.execution}` : ""}${tags}`;
2209
+ const tags = skill.tags?.length ? ` ${skill.tags.join(",")}` : "";
2210
+ return `${skill.description}${skill.execution ? ` ${skill.execution}` : ""}${tags}`;
2211
2211
  }
2212
2212
  function secretCommandCompletions(prefix, secrets) {
2213
2213
  const hasTrailingSpace = /\s$/.test(prefix);
@@ -2288,7 +2288,7 @@ function secretKeyCompletions(secrets, current, action) {
2288
2288
  .map((secret) => ({
2289
2289
  value: secret.key,
2290
2290
  insertText: `/secret ${action} ${secret.key}${action === "rename" ? " " : ""}`,
2291
- description: `${secret.status} · length=${secret.length}${secret.requestReason ? ` · ${secret.requestReason}` : ""}`,
2291
+ description: `${secret.status} length=${secret.length}${secret.requestReason ? ` ${secret.requestReason}` : ""}`,
2292
2292
  arguments: "optional",
2293
2293
  kind: "secret-key",
2294
2294
  }));
@@ -2327,7 +2327,7 @@ function modelCompletion(modelId) {
2327
2327
  metadata?.reasoning ? (efforts?.length ? `reasoning: ${efforts.join("/")}` : "reasoning") : undefined,
2328
2328
  metadata?.imageInput ? "vision" : undefined,
2329
2329
  window.tokens ? `${formatCompactNumber(window.tokens)} ctx` : undefined,
2330
- ].filter(Boolean).join(" · ");
2330
+ ].filter(Boolean).join(" ");
2331
2331
  return {
2332
2332
  value: modelId,
2333
2333
  insertText: `/model ${modelId}`,
@@ -2437,7 +2437,7 @@ function SlashCompletionLines({ completions, width, prompt, selectedIndex }) {
2437
2437
  const nameWidth = Math.min(32, Math.max(...visibleCompletions.map((completion) => completion.value.length)));
2438
2438
  const pageCount = slashCompletionPageCount(completions);
2439
2439
  const pageIndex = Math.floor(pageStart / SLASH_COMPLETION_PAGE_SIZE) + 1;
2440
- const footer = pageCount > 1 ? "↑/↓ select · ←/→ page · Tab complete" : "↑/↓ select · Tab complete";
2440
+ const footer = pageCount > 1 ? "↑/↓ select ←/→ page Tab complete" : "↑/↓ select Tab complete";
2441
2441
  const rows = visibleCompletions.map((completion, index) => {
2442
2442
  const selected = index === safeSelectedIndex;
2443
2443
  const numberPrefix = `${pageStart + index + 1}.`.padStart(String(completions.length).length + 1);
@@ -3139,11 +3139,11 @@ function SessionsBrowser({ state, width }) {
3139
3139
  const showPagination = pageCount > 1;
3140
3140
  const contentWidth = Math.max(20, width);
3141
3141
  const header = showPagination
3142
- ? `Saved sessions (${state.sessions.length}) · page ${state.pageIndex + 1}/${pageCount}`
3142
+ ? `Saved sessions (${state.sessions.length}) page ${state.pageIndex + 1}/${pageCount}`
3143
3143
  : `Saved sessions (${state.sessions.length})`;
3144
3144
  const footer = showPagination
3145
- ? "↑/↓ select · ←/→ page · Enter resume · d/Delete remove · Esc close"
3146
- : "↑/↓ select · Enter resume · d/Delete remove · Esc close";
3145
+ ? "↑/↓ select ←/→ page Enter resume d/Delete remove Esc close"
3146
+ : "↑/↓ select Enter resume d/Delete remove Esc close";
3147
3147
  return e(Box, { flexDirection: "column", marginTop: 1 }, e(Text, { color: "cyan", bold: true }, fitToWidth(header, contentWidth)), ...pageItems.map((session, index) => {
3148
3148
  const selected = index === state.selectedIndex;
3149
3149
  const absoluteIndex = state.pageIndex * state.pageSize + index;
@@ -3160,11 +3160,11 @@ function SkillsBrowser({ state, width }) {
3160
3160
  const showPagination = pageCount > 1;
3161
3161
  const contentWidth = Math.max(20, width);
3162
3162
  const header = showPagination
3163
- ? `Skills (${state.skills.length}) · page ${state.pageIndex + 1}/${pageCount}`
3163
+ ? `Skills (${state.skills.length}) page ${state.pageIndex + 1}/${pageCount}`
3164
3164
  : `Skills (${state.skills.length})`;
3165
3165
  const footer = showPagination
3166
- ? "↑/↓ select · ←/→ page · Enter details · i invoke · a import · d/Delete remove · Esc close"
3167
- : "↑/↓ select · Enter details · i invoke · a import · d/Delete remove · Esc close";
3166
+ ? "↑/↓ select ←/→ page Enter details i invoke a import d/Delete remove Esc close"
3167
+ : "↑/↓ select Enter details i invoke a import d/Delete remove Esc close";
3168
3168
  const nameWidth = Math.min(28, Math.max(...pageItems.map((skill) => skill.name.length)));
3169
3169
  return e(Box, { flexDirection: "column", marginTop: 1 }, e(Text, { color: "cyan", bold: true }, fitToWidth(header, contentWidth)), ...pageItems.map((skill, index) => {
3170
3170
  const selected = index === state.selectedIndex;
@@ -3183,11 +3183,11 @@ function SecretsBrowser({ state, width }) {
3183
3183
  const showPagination = pageCount > 1;
3184
3184
  const contentWidth = Math.max(20, width);
3185
3185
  const header = showPagination
3186
- ? `Secrets (${state.secrets.length}) · page ${state.pageIndex + 1}/${pageCount}`
3186
+ ? `Secrets (${state.secrets.length}) page ${state.pageIndex + 1}/${pageCount}`
3187
3187
  : `Secrets (${state.secrets.length})`;
3188
3188
  const footer = showPagination
3189
- ? "↑/↓ select · ←/→ page · Enter info · s set · r rename · a add · e empty · d/Delete remove · Esc close"
3190
- : "↑/↓ select · Enter info · s set · r rename · a add · e empty · d/Delete remove · Esc close";
3189
+ ? "↑/↓ select ←/→ page Enter info s set r rename a add e empty d/Delete remove Esc close"
3190
+ : "↑/↓ select Enter info s set r rename a add e empty d/Delete remove Esc close";
3191
3191
  const keyWidth = Math.min(32, Math.max(...pageItems.map((secret) => secret.key.length)));
3192
3192
  return e(Box, { flexDirection: "column", marginTop: 1 }, e(Text, { color: "cyan", bold: true }, fitToWidth(header, contentWidth)), ...pageItems.map((secret, index) => {
3193
3193
  const selected = index === state.selectedIndex;
@@ -3195,7 +3195,7 @@ function SecretsBrowser({ state, width }) {
3195
3195
  const prefix = `${absoluteIndex + 1}.`.padStart(String(state.secrets.length).length + 1);
3196
3196
  const reason = secret.requestReason ? ` reason=${JSON.stringify(secret.requestReason)}` : "";
3197
3197
  const restWidth = Math.max(0, contentWidth - prefix.length - keyWidth - 4);
3198
- const rest = fitToWidth(`${secret.status} · length=${secret.length}${reason}`, restWidth);
3198
+ const rest = fitToWidth(`${secret.status} length=${secret.length}${reason}`, restWidth);
3199
3199
  return e(Text, { key: secret.key, color: "white" }, e(Text, { color: selected ? "black" : "white", backgroundColor: selected ? "cyan" : undefined }, prefix), e(Text, { color: "gray" }, " "), e(Text, { color: secret.status === "set" ? "green" : "yellow" }, fitToWidth(secret.key, keyWidth).padEnd(keyWidth)), e(Text, { color: "gray" }, " "), e(Text, { color: selected ? "white" : "gray" }, rest));
3200
3200
  }), e(Text, { color: "gray" }, fitToWidth(footer, contentWidth)));
3201
3201
  }
@@ -3397,17 +3397,17 @@ function loginFormViewHeight(state) {
3397
3397
  function LoginFormView({ state, width }) {
3398
3398
  const contentWidth = Math.max(30, width);
3399
3399
  if (state.step === "provider") {
3400
- return e(Box, { flexDirection: "column", marginTop: 1 }, e(Text, { color: "cyan", bold: true }, fitToWidth(`Login: choose provider · saving to ${state.envPath}`, contentWidth)), ...state.providers.map((provider, index) => e(Text, { key: `provider-${provider}-${index}`, color: "white" }, e(Text, { color: index === state.selectedProviderIndex ? "black" : "white", backgroundColor: index === state.selectedProviderIndex ? "cyan" : undefined }, `${index + 1}.`.padStart(3)), e(Text, { color: "gray" }, " "), e(Text, { color: "cyan" }, provider))), e(Text, { color: "gray" }, fitToWidth("↑/↓ select · Enter edit config · Esc close", contentWidth)));
3400
+ return e(Box, { flexDirection: "column", marginTop: 1 }, e(Text, { color: "cyan", bold: true }, fitToWidth(`Login: choose provider saving to ${state.envPath}`, contentWidth)), ...state.providers.map((provider, index) => e(Text, { key: `provider-${provider}-${index}`, color: "white" }, e(Text, { color: index === state.selectedProviderIndex ? "black" : "white", backgroundColor: index === state.selectedProviderIndex ? "cyan" : undefined }, `${index + 1}.`.padStart(3)), e(Text, { color: "gray" }, " "), e(Text, { color: "cyan" }, provider))), e(Text, { color: "gray" }, fitToWidth("↑/↓ select Enter edit config Esc close", contentWidth)));
3401
3401
  }
3402
3402
  const fields = LOGIN_FIELD_DEFINITIONS[state.provider];
3403
3403
  const maxLabel = Math.max(...fields.map((field) => field.label.length));
3404
- return e(Box, { flexDirection: "column", marginTop: 1 }, e(Text, { color: "cyan", bold: true }, fitToWidth(`Login: ${state.provider} · ${state.envPath}`, contentWidth)), ...fields.map((field, index) => {
3404
+ return e(Box, { flexDirection: "column", marginTop: 1 }, e(Text, { color: "cyan", bold: true }, fitToWidth(`Login: ${state.provider} ${state.envPath}`, contentWidth)), ...fields.map((field, index) => {
3405
3405
  const selected = index === state.selectedFieldIndex;
3406
3406
  const rawValue = state.values[field.key] ?? "";
3407
3407
  const visibleValue = formatLoginFieldValue(field, rawValue, selected ? state.cursor : undefined);
3408
3408
  const placeholder = rawValue ? "" : (field.placeholder ? ` (${field.placeholder})` : "");
3409
3409
  return e(Text, { key: field.key, color: "white" }, e(Text, { color: selected ? "black" : "white", backgroundColor: selected ? "cyan" : undefined }, `${index + 1}.`.padStart(3)), e(Text, { color: field.required ? "yellow" : "gray" }, ` ${field.label.padEnd(maxLabel)} `), e(Text, { color: field.scope === "shared" ? "blue" : "gray" }, field.scope === "shared" ? "shared " : "provider "), e(Text, { color: rawValue ? "white" : "gray" }, fitToWidth(`${visibleValue}${placeholder}`, Math.max(8, contentWidth - maxLabel - 14))));
3410
- }), e(Text, { color: "gray" }, fitToWidth("↑/↓ field · ←/→ cursor · type edit · Tab cycle choices · Enter save · Esc back/cancel", contentWidth)), e(Text, { color: "gray" }, fitToWidth("Provider fields save as OPENAI_*; shared runtime fields save as MODEL_*.", contentWidth)));
3410
+ }), e(Text, { color: "gray" }, fitToWidth("↑/↓ field ←/→ cursor type edit Tab cycle choices Enter save Esc back/cancel", contentWidth)), e(Text, { color: "gray" }, fitToWidth("Provider fields save as OPENAI_*; shared runtime fields save as MODEL_*.", contentWidth)));
3411
3411
  }
3412
3412
  function formatLoginFieldValue(field, value, cursor) {
3413
3413
  const display = field.secret && value ? "•".repeat(Math.min(value.length, 24)) : value;
@@ -3515,14 +3515,14 @@ function stripEnvQuotes(value) {
3515
3515
  function formatSessionBrowserRow(session, absoluteIndex, width, running = false) {
3516
3516
  const numberPrefix = `${absoluteIndex + 1}.`.padStart(4);
3517
3517
  const title = session.title?.trim() || "(untitled)";
3518
- const runningTag = running ? " · running" : "";
3519
- const updated = session.updatedAt ? ` · ${formatSessionTimestamp(session.updatedAt)}` : "";
3520
- const messages = ` · ${session.messages} messages`;
3518
+ const runningTag = running ? " running" : "";
3519
+ const updated = session.updatedAt ? ` ${formatSessionTimestamp(session.updatedAt)}` : "";
3520
+ const messages = ` ${session.messages} messages`;
3521
3521
  const fixedParts = `${numberPrefix} ${runningTag}${updated}${messages}`;
3522
3522
  const idBudget = Math.max(12, Math.min(32, Math.floor(width * 0.28)));
3523
3523
  const id = truncateMiddle(session.sessionId, idBudget);
3524
3524
  const titleBudget = Math.max(8, width - fixedParts.length - id.length - 5);
3525
- const row = fitToWidth(`${numberPrefix} ${truncateMiddle(title, titleBudget)} · ${id}${runningTag}${updated}${messages}`, width);
3525
+ const row = fitToWidth(`${numberPrefix} ${truncateMiddle(title, titleBudget)} ${id}${runningTag}${updated}${messages}`, width);
3526
3526
  return { numberPrefix, rest: row.slice(numberPrefix.length) };
3527
3527
  }
3528
3528
  function formatSessionTimestamp(value) {
@@ -4109,13 +4109,13 @@ function formatImageGenerationToolResult(output, ok) {
4109
4109
  const lines = [`${mode === "edit" ? "edited" : "generated"} ${returnedImages ?? 0} image${returnedImages === 1 ? "" : "s"}`];
4110
4110
  const details = [provider, model, size, quality && quality !== "auto" ? quality : undefined, format].filter((value) => Boolean(value));
4111
4111
  if (details.length > 0)
4112
- lines.push(`${output.requested ? "requested: " : ""}${details.join(" · ")}`);
4112
+ lines.push(`${output.requested ? "requested: " : ""}${details.join(" ")}`);
4113
4113
  if (isRecord(output.actual)) {
4114
4114
  lines.push(`upstream-reported quality: ${String(output.actual.quality ?? "unreported")}`);
4115
4115
  if (Array.isArray(output.images))
4116
4116
  for (const image of output.images.filter(isRecord)) {
4117
4117
  if (typeof image.width === "number" && typeof image.height === "number")
4118
- lines.push(`actual image: ${image.width}x${image.height} · ${String(image.mimeType ?? "")}`);
4118
+ lines.push(`actual image: ${image.width}x${image.height} ${String(image.mimeType ?? "")}`);
4119
4119
  }
4120
4120
  }
4121
4121
  if (Array.isArray(output.warnings))
@@ -4254,7 +4254,7 @@ function formatWebSearchToolResult(output, ok) {
4254
4254
  return;
4255
4255
  const title = typeof item.title === "string" && item.title.trim() ? item.title.trim() : "Untitled";
4256
4256
  const url = typeof item.url === "string" ? item.url : "";
4257
- const published = typeof item.published === "string" ? ` · ${item.published}` : "";
4257
+ const published = typeof item.published === "string" ? ` ${item.published}` : "";
4258
4258
  lines.push(`[${index + 1}] ${title}${published}`);
4259
4259
  if (url)
4260
4260
  lines.push(url);
@@ -4632,7 +4632,7 @@ const STATUS_PHASE_MIN_DISPLAY_MS = 2000;
4632
4632
  const STATUS_SHIMMER_GAP_TICKS = 3;
4633
4633
  const STATUS_SHIMMER_RADIUS = 1;
4634
4634
  const STATUS_SHIMMER_COLOR = "whiteBright";
4635
- const STATUS_SEPARATOR = " · ";
4635
+ const STATUS_SEPARATOR = " ";
4636
4636
  const STATUS_BAR_RENDER_ROWS = 1;
4637
4637
  const BACKGROUND_TASK_STATUS_RENDER_ROWS = 1;
4638
4638
  const QUEUED_INPUT_RENDER_ROWS = 1;