ispbills-icli 8.4.0 → 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 +8 -2
- 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`, {
|
|
@@ -153,6 +155,10 @@ export async function streamChat(cfg, messages, options = {}) {
|
|
|
153
155
|
|
|
154
156
|
const reply = finalResult?.reply ?? {};
|
|
155
157
|
const meta = finalResult?._meta ?? {};
|
|
156
|
-
|
|
158
|
+
// Prefer whichever is longer: the final parsed reply.text or the text we
|
|
159
|
+
// streamed live. Guards against any server-side cap silently shortening the
|
|
160
|
+
// committed answer below what the operator already saw stream by.
|
|
161
|
+
const finalText = reply.text || '';
|
|
162
|
+
const text = finalText.length >= answerText.length ? finalText : answerText;
|
|
157
163
|
return { reply, text, meta };
|
|
158
164
|
}
|
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 });
|