@semalt-ai/code 1.8.3 → 1.8.5
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/.claude/settings.local.json +3 -1
- package/CLAUDE.md +4 -1
- package/TECHNICAL_DEBT.md +66 -0
- package/index.js +23 -9
- package/lib/agent.js +407 -129
- package/lib/api.js +105 -39
- package/lib/args.js +22 -0
- package/lib/commands.js +367 -132
- package/lib/config.js +14 -0
- package/lib/constants.js +1 -1
- package/lib/debug.js +106 -0
- package/lib/permissions.js +9 -8
- package/lib/proc.js +96 -0
- package/lib/prompts.js +8 -10
- package/lib/tool_specs.js +14 -7
- package/lib/tools.js +299 -118
- package/lib/ui/chat-history.js +37 -8
- package/lib/ui/create-ui.js +63 -38
- package/lib/ui/diff.js +4 -3
- package/lib/ui/format.js +321 -0
- package/lib/ui/input-field.js +134 -59
- package/lib/ui/layout.js +0 -2
- package/lib/ui/messages.js +44 -0
- package/lib/ui/select.js +114 -0
- package/lib/ui/status-bar.js +135 -28
- package/lib/ui/stream.js +8 -12
- package/lib/ui/terminal.js +12 -4
- package/lib/ui/theme.js +25 -4
- package/lib/ui/utils.js +94 -27
- package/lib/ui/writer.js +391 -45
- package/lib/ui.js +6 -6
- package/package.json +1 -1
- package/lib/ui/legacy.js +0 -130
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
"Bash(python3 *)",
|
|
16
16
|
"Read(//tmp/**)",
|
|
17
17
|
"Bash(sed -i \"s/addMessage\\('>>> AI MSG 2'.*$/addMessage\\('>>> AI MSG 2', ['response body 2a', 'response body 2b']\\);\\\\nfor \\(let k = 3; k <= 8; k++\\) { addMessage\\('>>> USER MSG ' + k, ['line body ' + k]\\); addMessage\\('>>> AI MSG ' + k, ['response body ' + k + 'a', 'response body ' + k + 'b']\\); }/\" scroll-capture.js)",
|
|
18
|
-
"Bash(echo \"exit=$?\")"
|
|
18
|
+
"Bash(echo \"exit=$?\")",
|
|
19
|
+
"Bash(echo \"---grep done, exit=$?---\")",
|
|
20
|
+
"Bash(grep *)"
|
|
19
21
|
]
|
|
20
22
|
}
|
|
21
23
|
}
|
package/CLAUDE.md
CHANGED
|
@@ -87,7 +87,10 @@ semalt-code config [set <key> <val>] # show or update config keys
|
|
|
87
87
|
--dashboard-url <url> dashboard base URL (overrides config)
|
|
88
88
|
--default-model <name> set default model in config
|
|
89
89
|
--show-think display model reasoning (thinking) content
|
|
90
|
-
--debug
|
|
90
|
+
--debug inline debug: per-iteration debug block in chat history (TUI-safe)
|
|
91
|
+
--debug-file <path> extended debug: per-iteration block + raw SSE chunks
|
|
92
|
+
+ request body dumps written to <path>, nothing to stdout.
|
|
93
|
+
Mutually exclusive with --debug.
|
|
91
94
|
--allow-fs auto-approve all filesystem operations
|
|
92
95
|
--allow-exec auto-approve shell command execution
|
|
93
96
|
--allow-net auto-approve network operations
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
## Activity region in-place update breaks when a modal is open
|
|
2
|
+
|
|
3
|
+
When a modal occupies screen lines below an active activity bubble, the
|
|
4
|
+
activity region's redraw mechanism appears to fall back to scrollback
|
|
5
|
+
append per tick instead of in-place rewrite. Surfaced via the `ask_user`
|
|
6
|
+
ticking-timer bug; mitigated by making `ask_user` a static bubble.
|
|
7
|
+
|
|
8
|
+
Latent: any future long-running tool that opens a modal concurrently
|
|
9
|
+
(none today) will reproduce the fragmentation. Fix likely involves
|
|
10
|
+
making the activity region modal-aware in `lib/ui/writer.js` — when a
|
|
11
|
+
modal region is active, route activity updates through a path that
|
|
12
|
+
clears modal, redraws activity, redraws modal — or reserves activity
|
|
13
|
+
above the modal in a way that survives modal lifecycle.
|
|
14
|
+
|
|
15
|
+
Not blocking. Revisit if a second use-case appears.
|
|
16
|
+
|
|
17
|
+
## `cmdShell` and `chatStream` write to stdout bypassing the writer
|
|
18
|
+
|
|
19
|
+
Several call sites currently emit directly to `process.stdout.write`
|
|
20
|
+
without going through `lib/ui/writer.js`:
|
|
21
|
+
|
|
22
|
+
- `lib/commands.js` (`cmdShell`)
|
|
23
|
+
- `lib/api.js` (streaming output path)
|
|
24
|
+
|
|
25
|
+
These were flagged during the Phase 2 writer audit and annotated as
|
|
26
|
+
`// audit: allowed` because they need to interleave with synchronous
|
|
27
|
+
writes from `StreamRenderer`. Routing them through the writer today
|
|
28
|
+
would require buffering or sequencing changes that don't compose with
|
|
29
|
+
how `StreamRenderer` flushes content per chunk.
|
|
30
|
+
|
|
31
|
+
Resolves when: `StreamRenderer` itself is migrated to write through
|
|
32
|
+
the writer. After that, the bypass annotations can be removed and
|
|
33
|
+
these call sites become normal `writer.scrollback(...)` calls.
|
|
34
|
+
|
|
35
|
+
Not blocking. The audit annotation makes the bypass intentional and
|
|
36
|
+
greppable. Revisit when `StreamRenderer` migration is on the table.
|
|
37
|
+
|
|
38
|
+
## Tool result storage: single `content` field used for both model and UI
|
|
39
|
+
|
|
40
|
+
Storage (PHP backend, MySQL `messages` table) holds one `content` field
|
|
41
|
+
per tool result. The full payload is required for the model on
|
|
42
|
+
subsequent turns, but the UI needs a compact summary (e.g. `net · GET
|
|
43
|
+
https://... · 200 · 256 KB`).
|
|
44
|
+
|
|
45
|
+
Today this is handled UI-side: `summarizeToolResult` in
|
|
46
|
+
`lib/ui/format.js` runs read-side heuristics on the raw `content` every
|
|
47
|
+
time `/history` renders. Heuristics cover HTTP, exec, file ops, with
|
|
48
|
+
a fallback for unknown shapes. They work in practice but are a
|
|
49
|
+
compromise — any tool whose output format drifts will fall through to
|
|
50
|
+
the generic fallback until the heuristic is updated.
|
|
51
|
+
|
|
52
|
+
Full fix: storage holds both `content` (full, model-bound) and
|
|
53
|
+
`display` (pre-rendered summary, UI-bound). Summary is generated
|
|
54
|
+
write-side at tool execution time, when the live activity bubble
|
|
55
|
+
already produces the right string — that string just needs to be
|
|
56
|
+
captured and persisted alongside the full content.
|
|
57
|
+
|
|
58
|
+
Resolves when: backend schema migration for native function calling
|
|
59
|
+
lands (Phase 2.2 of the native-tools plan, which already touches the
|
|
60
|
+
`messages` table). Adding a `display` column in the same migration is
|
|
61
|
+
cheap; doing it as a separate migration later is not. When this lands,
|
|
62
|
+
`summarizeToolResult` becomes unnecessary for new tool results; it
|
|
63
|
+
stays only as a fallback for legacy rows lacking `display`.
|
|
64
|
+
|
|
65
|
+
Not blocking — current heuristics cover all 33 tools' output shapes.
|
|
66
|
+
Track until Phase 2.2 lands.
|
package/index.js
CHANGED
|
@@ -18,6 +18,7 @@ const { createCommands } = require('./lib/commands');
|
|
|
18
18
|
const { parseArgs } = require('./lib/args');
|
|
19
19
|
const { CONFIG_PATH } = require('./lib/constants');
|
|
20
20
|
const { AUDIT_LOG } = require('./lib/audit');
|
|
21
|
+
const writer = require('./lib/ui/writer');
|
|
21
22
|
|
|
22
23
|
// Install process-wide signal handlers so every exit path (normal, SIGINT,
|
|
23
24
|
// SIGHUP, SIGTERM, uncaught exception) restores the terminal. Safe to call
|
|
@@ -48,7 +49,7 @@ if (_argv.includes('--allow-all')) {
|
|
|
48
49
|
const _readonly = _argv.includes('--readonly');
|
|
49
50
|
|
|
50
51
|
const permissionManager = createPermissionManager(ui, { allowedTiers: _allowedTiers, readonly: _readonly });
|
|
51
|
-
const { agentExecShell, agentExecFile } = createToolExecutor(permissionManager, ui, getConfig);
|
|
52
|
+
const { agentExecShell, agentExecFile, describePermission } = createToolExecutor(permissionManager, ui, getConfig);
|
|
52
53
|
const apiClient = createApiClient({
|
|
53
54
|
getConfig,
|
|
54
55
|
saveConfig: (nextConfig) => {
|
|
@@ -65,6 +66,8 @@ const { runAgentLoop } = createAgentRunner({
|
|
|
65
66
|
}),
|
|
66
67
|
agentExecShell,
|
|
67
68
|
agentExecFile,
|
|
69
|
+
describePermission,
|
|
70
|
+
permissionManager,
|
|
68
71
|
ui,
|
|
69
72
|
getConfig,
|
|
70
73
|
});
|
|
@@ -90,7 +93,7 @@ async function main() {
|
|
|
90
93
|
const command = rawArgs[0];
|
|
91
94
|
|
|
92
95
|
if (command === '--help' || command === '-h') {
|
|
93
|
-
|
|
96
|
+
writer.scrollback(`
|
|
94
97
|
Semalt.AI — Self-hosted AI Coding Assistant
|
|
95
98
|
|
|
96
99
|
Usage: semalt-code [command] [options]
|
|
@@ -118,7 +121,12 @@ Options:
|
|
|
118
121
|
--dashboard-url <url> Dashboard URL (init)
|
|
119
122
|
--default-model <name> Default model (init)
|
|
120
123
|
--show-think Display model reasoning (thinking) content
|
|
121
|
-
--debug
|
|
124
|
+
--debug Inline debug output: per-iteration debug block in the
|
|
125
|
+
chat history. TUI-safe; no per-chunk noise.
|
|
126
|
+
--debug-file <path> Extended debug to file: per-iteration block PLUS raw
|
|
127
|
+
SSE chunks, request body dumps, accumulator state,
|
|
128
|
+
and other high-volume traces. Nothing prints to stdout
|
|
129
|
+
— the TUI stays clean. Mutually exclusive with --debug.
|
|
122
130
|
--allow-fs Auto-approve all filesystem operations
|
|
123
131
|
--allow-exec Auto-approve shell command execution
|
|
124
132
|
--allow-net Auto-approve network operations
|
|
@@ -130,11 +138,13 @@ Options:
|
|
|
130
138
|
|
|
131
139
|
Config: ${CONFIG_PATH}
|
|
132
140
|
`);
|
|
141
|
+
await writer.flush();
|
|
133
142
|
return;
|
|
134
143
|
}
|
|
135
144
|
|
|
136
145
|
if (command === '--version' || command === '-v') {
|
|
137
|
-
|
|
146
|
+
writer.scrollback(PACKAGE_JSON.version);
|
|
147
|
+
await writer.flush();
|
|
138
148
|
return;
|
|
139
149
|
}
|
|
140
150
|
|
|
@@ -170,20 +180,22 @@ Config: ${CONFIG_PATH}
|
|
|
170
180
|
try {
|
|
171
181
|
const entry = JSON.parse(line);
|
|
172
182
|
const icon = entry.approved ? `${ui.FG_GREEN}✓${ui.RST}` : `${ui.FG_RED}✗${ui.RST}`;
|
|
173
|
-
|
|
183
|
+
writer.scrollback(`${icon} ${line}`);
|
|
174
184
|
} catch {
|
|
175
|
-
|
|
185
|
+
writer.scrollback(line);
|
|
176
186
|
}
|
|
177
187
|
}
|
|
178
188
|
} catch {
|
|
179
|
-
|
|
189
|
+
writer.scrollback('No audit log found.');
|
|
180
190
|
}
|
|
191
|
+
await writer.flush();
|
|
181
192
|
} else if (command === 'config') {
|
|
182
193
|
const sub = rawArgs[1];
|
|
183
194
|
if (sub === 'set') {
|
|
184
195
|
const key = rawArgs[2];
|
|
185
196
|
const value = rawArgs[3];
|
|
186
197
|
if (!key || value === undefined) {
|
|
198
|
+
// audit: allowed — pre-UI argparse usage error to stderr; exits immediately.
|
|
187
199
|
process.stderr.write(`Usage: semalt-code config set <key> <value>\n`);
|
|
188
200
|
process.exit(1);
|
|
189
201
|
}
|
|
@@ -194,11 +206,12 @@ Config: ${CONFIG_PATH}
|
|
|
194
206
|
parsed = value;
|
|
195
207
|
}
|
|
196
208
|
configSet(key, parsed);
|
|
197
|
-
|
|
209
|
+
writer.scrollback(`Set ${key} = ${JSON.stringify(parsed)}`);
|
|
198
210
|
} else {
|
|
199
211
|
// default: "show" or bare "config"
|
|
200
|
-
|
|
212
|
+
writer.scrollback(configShow());
|
|
201
213
|
}
|
|
214
|
+
await writer.flush();
|
|
202
215
|
} else {
|
|
203
216
|
const { opts } = parseArgs(rawArgs);
|
|
204
217
|
await commands.cmdChat(opts);
|
|
@@ -209,6 +222,7 @@ main().catch((error) => {
|
|
|
209
222
|
// Tear down the TUI synchronously so the error message lands below the
|
|
210
223
|
// last scrollback line, not on top of a still-rendered live region.
|
|
211
224
|
try { ui.teardownTerminal(); } catch {}
|
|
225
|
+
// audit: allowed — fatal error message to stderr after writer teardown.
|
|
212
226
|
process.stderr.write(`\n ${ui.FG_RED}✗ Fatal: ${error.message}${ui.RST}\n\n`);
|
|
213
227
|
process.exit(1);
|
|
214
228
|
});
|