ispbills-icli 8.4.1 → 8.4.2
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/package.json +1 -1
- package/src/client.js +3 -1
- package/src/tui/app.js +18 -4
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -78,7 +78,9 @@ export function parsePartialPlan(raw) {
|
|
|
78
78
|
*/
|
|
79
79
|
export async function streamChat(cfg, messages, options = {}) {
|
|
80
80
|
const { onEvent = () => {}, signal, context = {} } = options;
|
|
81
|
-
|
|
81
|
+
// Always identify ourselves as the icli client so the backend can route
|
|
82
|
+
// away from type=connect (which requires an interactive browser terminal).
|
|
83
|
+
const body = JSON.stringify({ messages, context: { ...context, client: 'icli' } });
|
|
82
84
|
|
|
83
85
|
const doFetch = (token) =>
|
|
84
86
|
fetch(`${cfg.url}/api/v1/ai/chat/stream`, {
|
package/src/tui/app.js
CHANGED
|
@@ -96,9 +96,11 @@ export function App({ cfg, display = {}, onExternal, onExit, initialQuestion })
|
|
|
96
96
|
}, []);
|
|
97
97
|
|
|
98
98
|
const runTurn = useCallback(async (question, opts = {}) => {
|
|
99
|
-
const { depth = 0, archive = null, label = '' } = opts;
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
const { depth = 0, archive = null, label = '', synthetic = false } = opts;
|
|
100
|
+
if (!synthetic) {
|
|
101
|
+
push({ type: 'user', text: question });
|
|
102
|
+
log(`\n${glyphs.prompt} ${question}\n`);
|
|
103
|
+
}
|
|
102
104
|
convo.current.push({ role: 'user', content: question });
|
|
103
105
|
setBusy(true);
|
|
104
106
|
setHint('');
|
|
@@ -136,7 +138,19 @@ export function App({ cfg, display = {}, onExternal, onExit, initialQuestion })
|
|
|
136
138
|
// so it stays in history instead of vanishing with the live region.
|
|
137
139
|
if (s.status.length) push({ type: 'activity', status: s.status });
|
|
138
140
|
if (type === 'plan') { push({ type: 'plan', reply }); log('[plan] ' + (reply.summary || '')); }
|
|
139
|
-
else if (type === 'connect') {
|
|
141
|
+
else if (type === 'connect') {
|
|
142
|
+
push({ type: 'connect', reply }); log('[connect] ' + (reply.device?.kind || ''));
|
|
143
|
+
// The icli has no interactive terminal — send a synthetic session-event
|
|
144
|
+
// so the backend continues to the plan/answer (rule 4). Depth-guard to
|
|
145
|
+
// prevent a loop if the backend keeps emitting connect (shouldn't happen).
|
|
146
|
+
if (depth < 2) {
|
|
147
|
+
const dev = reply.device || {};
|
|
148
|
+
const goal = convo.current.filter((m) => m.role === 'user').slice(-1)[0]?.content || '';
|
|
149
|
+
const sessionEvent = `[session-event] Terminal session opened on ${dev.kind || 'device'} id=${dev.id || '?'} proto=${dev.proto || 'ssh'}. vendor=auto. OPERATOR GOAL: ${goal}`;
|
|
150
|
+
setLive(null); setBusy(false); abortRef.current = null;
|
|
151
|
+
return runTurn(sessionEvent, { depth: depth + 1, synthetic: true });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
140
154
|
else if (type === 'prompt' || type === 'choice') { push({ type: 'assistant', text: text || reply.question || '' }); log(text || reply.question || ''); }
|
|
141
155
|
else { push({ type: 'assistant', text: text || '(no response)' }); log(text || ''); }
|
|
142
156
|
if (text) convo.current.push({ role: 'assistant', content: text });
|