@vascend/talos 0.1.4 → 0.1.6
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/LICENSE +22 -0
- package/README.md +37 -12
- package/dist/core/agent.d.ts +16 -3
- package/dist/core/agent.js +170 -70
- package/dist/core/background.d.ts +10 -3
- package/dist/core/background.js +55 -9
- package/dist/core/bootstrap.js +1 -0
- package/dist/core/compaction.js +1 -1
- package/dist/core/config-storage.d.ts +5 -0
- package/dist/core/config-storage.js +83 -0
- package/dist/core/config.d.ts +11 -2
- package/dist/core/config.js +24 -8
- package/dist/core/context-ledger.js +2 -1
- package/dist/core/context-policy.d.ts +1 -1
- package/dist/core/context-policy.js +10 -7
- package/dist/core/credentials.js +29 -30
- package/dist/core/effort.d.ts +1 -1
- package/dist/core/effort.js +5 -1
- package/dist/core/execution-guidance.d.ts +1 -1
- package/dist/core/execution-guidance.js +2 -0
- package/dist/core/file-coordination.d.ts +3 -0
- package/dist/core/file-coordination.js +28 -0
- package/dist/core/file-lease-store.d.ts +3 -0
- package/dist/core/file-lease-store.js +28 -12
- package/dist/core/fusion.d.ts +24 -0
- package/dist/core/fusion.js +80 -0
- package/dist/core/model-limits.d.ts +1 -0
- package/dist/core/model-limits.js +5 -1
- package/dist/core/permission-queue.js +15 -15
- package/dist/core/request-plan.js +4 -3
- package/dist/core/session-naming.d.ts +3 -0
- package/dist/core/session-naming.js +47 -0
- package/dist/core/session-usage.js +4 -1
- package/dist/core/session.d.ts +5 -2
- package/dist/core/session.js +22 -7
- package/dist/core/settings.d.ts +2 -0
- package/dist/core/settings.js +5 -16
- package/dist/core/step-policy.d.ts +18 -0
- package/dist/core/step-policy.js +6 -0
- package/dist/core/storage-health.d.ts +24 -0
- package/dist/core/storage-health.js +72 -0
- package/dist/core/tool-artifacts.d.ts +2 -0
- package/dist/core/tool-artifacts.js +21 -3
- package/dist/core/tool-result-index.js +29 -33
- package/dist/core/tool-result-store.js +6 -5
- package/dist/core/types.d.ts +26 -2
- package/dist/core/user-inbox.d.ts +9 -0
- package/dist/core/user-inbox.js +22 -3
- package/dist/core/user-input.js +1 -1
- package/dist/fusion/autopilot-fast.d.ts +59 -0
- package/dist/fusion/autopilot-fast.js +213 -0
- package/dist/fusion/autopilot.d.ts +75 -0
- package/dist/fusion/autopilot.js +308 -0
- package/dist/fusion/focus.d.ts +30 -0
- package/dist/fusion/focus.js +122 -0
- package/dist/fusion/gate.d.ts +30 -0
- package/dist/fusion/gate.js +95 -0
- package/dist/fusion/jev.d.ts +71 -0
- package/dist/fusion/jev.js +164 -0
- package/dist/fusion/receipts.d.ts +25 -0
- package/dist/fusion/receipts.js +34 -0
- package/dist/fusion/route.d.ts +25 -0
- package/dist/fusion/route.js +84 -0
- package/dist/fusion/run.d.ts +4 -0
- package/dist/fusion/run.js +186 -0
- package/dist/horizon/engine.d.ts +20 -1
- package/dist/horizon/engine.js +57 -0
- package/dist/horizon/index.d.ts +2 -2
- package/dist/horizon/index.js +1 -1
- package/dist/horizon/types.d.ts +29 -0
- package/dist/index.js +12 -0
- package/dist/providers/anthropic-oauth.d.ts +8 -3
- package/dist/providers/anthropic-oauth.js +13 -10
- package/dist/providers/anthropic.d.ts +9 -2
- package/dist/providers/anthropic.js +64 -21
- package/dist/providers/cli-models.d.ts +30 -0
- package/dist/providers/cli-models.js +194 -0
- package/dist/providers/model-effort.js +1 -1
- package/dist/providers/openai-oauth.d.ts +8 -3
- package/dist/providers/openai-oauth.js +9 -3
- package/dist/providers/openrouter-manual-fallback.d.ts +3 -1
- package/dist/providers/openrouter-manual-fallback.js +20 -20
- package/dist/providers/registry.js +3 -2
- package/dist/providers/retry.d.ts +3 -0
- package/dist/providers/retry.js +44 -1
- package/dist/remote/cifratura.d.ts +12 -0
- package/dist/remote/cifratura.js +66 -0
- package/dist/remote/index.d.ts +15 -0
- package/dist/remote/index.js +65 -0
- package/dist/remote/relay-client.d.ts +58 -0
- package/dist/remote/relay-client.js +315 -0
- package/dist/remote/sessione-remota.d.ts +60 -0
- package/dist/remote/sessione-remota.js +266 -0
- package/dist/sdk.d.ts +7 -2
- package/dist/sdk.js +3 -1
- package/dist/tools/builtin.js +41 -20
- package/dist/tools/capabilities.d.ts +3 -1
- package/dist/tools/capabilities.js +5 -2
- package/dist/tools/computer-use.js +2 -1
- package/dist/tools/pagination.js +1 -1
- package/dist/tools/program.js +34 -21
- package/dist/tools/team-tools.js +11 -6
- package/dist/tui/account-entry.js +14 -9
- package/dist/tui/agent-label.d.ts +2 -0
- package/dist/tui/agent-label.js +5 -0
- package/dist/tui/agent-sessions-screen.d.ts +35 -0
- package/dist/tui/agent-sessions-screen.js +178 -0
- package/dist/tui/agent-sessions.d.ts +53 -0
- package/dist/tui/agent-sessions.js +236 -0
- package/dist/tui/bottom-input.d.ts +57 -2
- package/dist/tui/bottom-input.js +449 -54
- package/dist/tui/branding.js +8 -4
- package/dist/tui/capability-lists.d.ts +10 -0
- package/dist/tui/capability-lists.js +41 -0
- package/dist/tui/command-output-registry.js +4 -0
- package/dist/tui/command-transcript.d.ts +1 -1
- package/dist/tui/command-transcript.js +17 -21
- package/dist/tui/commands.js +6 -2
- package/dist/tui/compaction-status.d.ts +7 -0
- package/dist/tui/compaction-status.js +39 -0
- package/dist/tui/config-recovery.d.ts +12 -0
- package/dist/tui/config-recovery.js +54 -0
- package/dist/tui/context-meter.d.ts +3 -0
- package/dist/tui/context-meter.js +35 -8
- package/dist/tui/diff.d.ts +9 -0
- package/dist/tui/diff.js +43 -19
- package/dist/tui/fusion-menu.d.ts +5 -0
- package/dist/tui/fusion-menu.js +89 -0
- package/dist/tui/i18n-catalog.js +351 -2
- package/dist/tui/live-command.d.ts +1 -0
- package/dist/tui/live-command.js +9 -0
- package/dist/tui/live-output.d.ts +1 -0
- package/dist/tui/live-output.js +11 -0
- package/dist/tui/logo.js +3 -0
- package/dist/tui/model-details.js +13 -12
- package/dist/tui/model-picker.d.ts +2 -0
- package/dist/tui/model-picker.js +59 -0
- package/dist/tui/model-selection.js +19 -10
- package/dist/tui/native-scrollback.d.ts +2 -1
- package/dist/tui/native-scrollback.js +31 -6
- package/dist/tui/prompt-queue-store.d.ts +1 -0
- package/dist/tui/prompt-queue-store.js +4 -0
- package/dist/tui/prompt-queue.d.ts +3 -0
- package/dist/tui/prompt-queue.js +19 -1
- package/dist/tui/provider-label.d.ts +2 -0
- package/dist/tui/provider-label.js +9 -0
- package/dist/tui/provider-menu.js +25 -24
- package/dist/tui/queue-screen.js +2 -1
- package/dist/tui/queued-questions.js +2 -4
- package/dist/tui/quick-help.d.ts +1 -1
- package/dist/tui/quick-help.js +3 -0
- package/dist/tui/remote-command.d.ts +7 -0
- package/dist/tui/remote-command.js +79 -0
- package/dist/tui/repl.d.ts +11 -2
- package/dist/tui/repl.js +457 -327
- package/dist/tui/review-store.d.ts +8 -1
- package/dist/tui/review-store.js +64 -11
- package/dist/tui/review-team.js +4 -3
- package/dist/tui/runtime-error.d.ts +2 -0
- package/dist/tui/runtime-error.js +26 -0
- package/dist/tui/scrollback-archive.d.ts +16 -0
- package/dist/tui/scrollback-archive.js +90 -0
- package/dist/tui/selector-mouse.d.ts +1 -0
- package/dist/tui/selector-mouse.js +1 -1
- package/dist/tui/selector.d.ts +11 -0
- package/dist/tui/selector.js +28 -4
- package/dist/tui/session-controls.d.ts +26 -0
- package/dist/tui/session-controls.js +65 -0
- package/dist/tui/session-naming-notice.d.ts +14 -0
- package/dist/tui/session-naming-notice.js +59 -0
- package/dist/tui/session-picker.d.ts +2 -0
- package/dist/tui/session-picker.js +32 -0
- package/dist/tui/session-replay.d.ts +1 -0
- package/dist/tui/session-replay.js +101 -32
- package/dist/tui/session-transcript-layout.d.ts +9 -0
- package/dist/tui/session-transcript-layout.js +41 -0
- package/dist/tui/startup.js +63 -33
- package/dist/tui/status-line.d.ts +1 -1
- package/dist/tui/status-line.js +20 -12
- package/dist/tui/storage-warning.d.ts +2 -0
- package/dist/tui/storage-warning.js +35 -0
- package/dist/tui/talos-art-data.d.ts +1 -0
- package/dist/tui/talos-art-data.js +2 -0
- package/dist/tui/talos-art.d.ts +1 -0
- package/dist/tui/talos-art.js +9 -0
- package/dist/tui/task-labels.d.ts +1 -0
- package/dist/tui/task-labels.js +8 -0
- package/dist/tui/terminal-text.d.ts +2 -1
- package/dist/tui/terminal-text.js +28 -2
- package/dist/tui/theme.js +2 -2
- package/dist/tui/tool-presentation.d.ts +3 -0
- package/dist/tui/tool-presentation.js +98 -0
- package/dist/tui/tool-style.js +4 -0
- package/dist/tui/transcript-store.d.ts +25 -0
- package/dist/tui/transcript-store.js +151 -0
- package/dist/tui/usage-footer.d.ts +1 -1
- package/dist/tui/usage-footer.js +3 -1
- package/dist/tui/vascend-id.d.ts +49 -0
- package/dist/tui/vascend-id.js +321 -0
- package/dist/tui/web-login-screen.js +4 -3
- package/dist/tui/web-login.d.ts +7 -15
- package/dist/tui/web-login.js +38 -78
- package/dist/tui/worker-transcripts.d.ts +31 -0
- package/dist/tui/worker-transcripts.js +91 -0
- package/dist/vascend/candidate-collector.d.ts +6 -5
- package/dist/vascend/candidate-collector.js +44 -43
- package/dist/vascend/context-feedback-loop.js +2 -0
- package/dist/vascend/context-lint.js +32 -2
- package/dist/vascend/context-market-selection.js +12 -5
- package/dist/vascend/context-pack-render.js +10 -4
- package/dist/vascend/context-packet-mirrors.d.ts +8 -0
- package/dist/vascend/context-packet-mirrors.js +24 -0
- package/dist/vascend/context-plan-events.d.ts +4 -0
- package/dist/vascend/context-plan-events.js +44 -0
- package/dist/vascend/context-snapshot.d.ts +1 -0
- package/dist/vascend/context-snapshot.js +8 -5
- package/dist/vascend/context-store-reader.d.ts +20 -0
- package/dist/vascend/context-store-reader.js +46 -0
- package/dist/vascend/context-window-compiler.d.ts +1 -0
- package/dist/vascend/context-window-compiler.js +1 -0
- package/dist/vascend/file-lock.d.ts +1 -0
- package/dist/vascend/file-lock.js +26 -0
- package/dist/vascend/granular-kingdom.d.ts +1 -0
- package/dist/vascend/granular-kingdom.js +52 -17
- package/dist/vascend/kingdom-bus.d.ts +1 -0
- package/dist/vascend/kingdom-bus.js +3 -0
- package/dist/vascend/kingdom-channel.d.ts +2 -0
- package/dist/vascend/kingdom-channel.js +3 -0
- package/dist/vascend/kingdom-live.d.ts +32 -4
- package/dist/vascend/kingdom-live.js +149 -13
- package/dist/vascend/kingdom-run.d.ts +5 -1
- package/dist/vascend/kingdom-run.js +6 -2
- package/dist/vascend/kingdom.d.ts +3 -0
- package/dist/vascend/kingdom.js +22 -11
- package/dist/vascend/memory-packet.d.ts +2 -1
- package/dist/vascend/memory-packet.js +31 -44
- package/dist/vascend/memory-store.d.ts +1 -0
- package/dist/vascend/memory-store.js +12 -4
- package/dist/vascend/plan-store.d.ts +3 -1
- package/dist/vascend/plan-store.js +6 -4
- package/dist/vascend/room-memory.d.ts +13 -2
- package/dist/vascend/room-memory.js +48 -6
- package/dist/vascend/runtime.d.ts +3 -11
- package/dist/vascend/runtime.js +11 -123
- package/dist/vascend/session-search.js +2 -0
- package/dist/vascend/team-session.js +3 -2
- package/dist/vascend/vision.d.ts +3 -1
- package/dist/vascend/vision.js +6 -4
- package/dist/vascend/worker-session.d.ts +20 -0
- package/dist/vascend/worker-session.js +83 -0
- package/package.json +2 -2
package/dist/tools/program.js
CHANGED
|
@@ -64,11 +64,12 @@ const BRIDGE_DENYLIST = new Set([
|
|
|
64
64
|
// ---------------------------------------------------------------------------
|
|
65
65
|
const KERNEL_SOURCE = `"use strict";
|
|
66
66
|
const util = require("node:util");
|
|
67
|
+
const { AsyncLocalStorage } = require("node:async_hooks");
|
|
68
|
+
const executionScope = new AsyncLocalStorage();
|
|
67
69
|
let buf = "";
|
|
68
70
|
let seq = 0;
|
|
69
71
|
const pending = new Map();
|
|
70
72
|
const state = {};
|
|
71
|
-
let inputData = {};
|
|
72
73
|
|
|
73
74
|
function send(msg) { process.stdout.write(JSON.stringify(msg) + "\\n"); }
|
|
74
75
|
|
|
@@ -80,10 +81,12 @@ function render(value) {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
function callTool(name, args, structured = false) {
|
|
84
|
+
const scope = executionScope.getStore();
|
|
85
|
+
if (!scope?.active) return Promise.reject(new Error("programma gia' concluso"));
|
|
83
86
|
return new Promise((resolve, reject) => {
|
|
84
87
|
seq += 1;
|
|
85
88
|
pending.set(seq, { resolve, reject, structured });
|
|
86
|
-
send({ t: "call", seq, name, args: args === undefined ? {} : args });
|
|
89
|
+
send({ t: "call", id: scope.id, seq, name, args: args === undefined ? {} : args });
|
|
87
90
|
});
|
|
88
91
|
}
|
|
89
92
|
|
|
@@ -92,7 +95,7 @@ function callTool(name, args, structured = false) {
|
|
|
92
95
|
const tools = new Proxy({}, {
|
|
93
96
|
get(_t, prop) {
|
|
94
97
|
if (typeof prop !== "string" || prop === "then" || prop === "toJSON") return undefined;
|
|
95
|
-
if (prop === "$data") return
|
|
98
|
+
if (prop === "$data") return executionScope.getStore()?.data ?? {};
|
|
96
99
|
if (prop === "$result") return (name, args) => callTool(name, args, true);
|
|
97
100
|
return (args) => callTool(prop, args);
|
|
98
101
|
},
|
|
@@ -100,24 +103,31 @@ const tools = new Proxy({}, {
|
|
|
100
103
|
|
|
101
104
|
const fakeConsole = {};
|
|
102
105
|
for (const level of ["log", "info", "warn", "error", "debug", "trace"]) {
|
|
103
|
-
fakeConsole[level] = (...parts) =>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
fakeConsole[level] = (...parts) => {
|
|
107
|
+
const scope = executionScope.getStore();
|
|
108
|
+
if (scope?.active) send({
|
|
109
|
+
t: "log", id: scope.id,
|
|
110
|
+
line: parts.map((p) => (typeof p === "string" ? p : render(p))).join(" "),
|
|
111
|
+
});
|
|
112
|
+
};
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
async function execute(msg) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
const scope = { id: msg.id, data: msg.data ?? {}, active: true };
|
|
117
|
+
return executionScope.run(scope, async () => {
|
|
118
|
+
const AsyncFunction = (async () => {}).constructor;
|
|
119
|
+
try {
|
|
120
|
+
// require/process oscurati: e' un invito a passare dai tool (che portano i
|
|
121
|
+
// permessi), non un confine di sicurezza — il confine e' la conferma utente.
|
|
122
|
+
const fn = new AsyncFunction("tools", "state", "console", "require", "process", msg.code);
|
|
123
|
+
const value = await fn(tools, state, fakeConsole, undefined, undefined);
|
|
124
|
+
send({ t: "done", id: msg.id, value: render(value) });
|
|
125
|
+
} catch (err) {
|
|
126
|
+
send({ t: "done", id: msg.id, error: err instanceof Error ? (err.stack || err.message) : String(err) });
|
|
127
|
+
} finally {
|
|
128
|
+
scope.active = false;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
121
131
|
}
|
|
122
132
|
|
|
123
133
|
process.stdin.setEncoding("utf8");
|
|
@@ -255,7 +265,7 @@ class ProgramKernel {
|
|
|
255
265
|
}
|
|
256
266
|
async onMessage(msg) {
|
|
257
267
|
const cur = this.current;
|
|
258
|
-
if (!cur)
|
|
268
|
+
if (!cur || Number(msg["id"]) !== cur.id)
|
|
259
269
|
return;
|
|
260
270
|
if (msg["t"] === "log") {
|
|
261
271
|
this.appendLog(cur, String(msg["line"] ?? ""));
|
|
@@ -307,8 +317,11 @@ class ProgramKernel {
|
|
|
307
317
|
cur.logsTruncatedLines += 1;
|
|
308
318
|
return;
|
|
309
319
|
}
|
|
310
|
-
cur.
|
|
311
|
-
cur.
|
|
320
|
+
const remaining = Math.max(0, MAX_LOG_CHARS - cur.logChars - 1);
|
|
321
|
+
cur.logs.push(line.slice(0, remaining));
|
|
322
|
+
cur.logChars += Math.min(line.length, remaining) + 1;
|
|
323
|
+
if (line.length > remaining)
|
|
324
|
+
cur.logsTruncatedLines += 1;
|
|
312
325
|
}
|
|
313
326
|
send(msg) {
|
|
314
327
|
try {
|
package/dist/tools/team-tools.js
CHANGED
|
@@ -257,7 +257,7 @@ export const teamWaitTool = {
|
|
|
257
257
|
const combacia = (m) => (!from || addressKey(m.from) === from) && (!contains || m.text.toLowerCase().includes(contains));
|
|
258
258
|
const canale = bus(ctx);
|
|
259
259
|
for (;;) {
|
|
260
|
-
if (ctx.signal.aborted)
|
|
260
|
+
if (ctx.signal.aborted || ctx.waitInterrupted?.())
|
|
261
261
|
return "attesa interrotta";
|
|
262
262
|
const msgs = canale.inbox(id, me, combacia);
|
|
263
263
|
if (msgs.length)
|
|
@@ -323,20 +323,25 @@ export const teamReportTool = {
|
|
|
323
323
|
const richiesti = Number(input["timeout_s"]);
|
|
324
324
|
const secondi = Number.isFinite(richiesti) ? Math.min(WAIT_MAX_S, Math.max(1, richiesti)) : WAIT_DEFAULT_S;
|
|
325
325
|
const deadline = Date.now() + secondi * 1000;
|
|
326
|
+
// Keep the original target even if a newer team appears during the wait.
|
|
327
|
+
const selected = () => teamById(team.sessionId, team.id) ?? team;
|
|
326
328
|
while (Date.now() < deadline) {
|
|
327
|
-
if (ctx.signal.aborted)
|
|
328
|
-
return reportResult("attesa interrotta; il lavoro del team non viene cancellato",
|
|
329
|
-
const current =
|
|
329
|
+
if (ctx.signal.aborted || ctx.waitInterrupted?.())
|
|
330
|
+
return reportResult("attesa interrotta; il lavoro del team non viene cancellato", selected());
|
|
331
|
+
const current = selected();
|
|
330
332
|
if (current?.done)
|
|
331
333
|
return finished(current);
|
|
332
334
|
try {
|
|
333
335
|
await sleep(Math.min(250, Math.max(1, deadline - Date.now())), ctx.signal);
|
|
334
336
|
}
|
|
335
337
|
catch {
|
|
336
|
-
return reportResult("attesa interrotta; il lavoro del team non viene cancellato",
|
|
338
|
+
return reportResult("attesa interrotta; il lavoro del team non viene cancellato", selected());
|
|
337
339
|
}
|
|
338
340
|
}
|
|
339
|
-
|
|
341
|
+
const current = selected();
|
|
342
|
+
if (current.done)
|
|
343
|
+
return finished(current);
|
|
344
|
+
return reportResult(`non hanno ancora finito dopo ${secondi}s: ${pendingMembers(current).join(", ")}. Richiama team_report piu' tardi.`, current);
|
|
340
345
|
},
|
|
341
346
|
};
|
|
342
347
|
export const teamTools = [
|
|
@@ -3,7 +3,8 @@ import { stdin, stdout } from "node:process";
|
|
|
3
3
|
import { tr } from "./i18n.js";
|
|
4
4
|
import { initializeLanguage, onboardingLanguage } from "./language-preference.js";
|
|
5
5
|
import { leggiOnboarding, salvaOnboarding, serveTermini, TESTI, consensoAffermativo, TERMINI_VERSIONE, LINK_TERMINI, LINK_PRIVACY } from "./onboarding.js";
|
|
6
|
-
import { decisioneCancello,
|
|
6
|
+
import { decisioneCancello, statoSessione, valutaLicenzaLocale, rimuoviTokenVascend, rinnovaProvaOffline } from "./vascend-login.js";
|
|
7
|
+
import { rimuoviSessione, salvaSessione, tokenAgente } from "./vascend-id.js";
|
|
7
8
|
import { startWebLogin, waitForWebLogin, WebLoginError } from "./web-login.js";
|
|
8
9
|
import { showWebLoginScreen } from "./web-login-screen.js";
|
|
9
10
|
import { CliCancelled } from "../core/cli-cancelled.js";
|
|
@@ -14,12 +15,16 @@ export async function enterAccount(env, theme) {
|
|
|
14
15
|
// requires a verified session and current account permissions.
|
|
15
16
|
if (env["TALOS_NO_LOGIN"] === "1")
|
|
16
17
|
return "";
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
// Token per l'agente dalla sessione Vascend ID, rinnovato se serve. Il vecchio
|
|
19
|
+
// token del backend agentico non vale piu': chi lo aveva rifa' l'accesso.
|
|
20
|
+
const esito = await tokenAgente(env);
|
|
21
|
+
const saved = esito.token;
|
|
22
|
+
const session = saved ? await statoSessione(env, saved)
|
|
23
|
+
: esito.errore === "rete" ? { stato: "irraggiungibile" } : null;
|
|
19
24
|
if (!stdin.isTTY || !stdout.isTTY || env["TALOS_HOST_PROFILE"]?.toLowerCase() === "horizon")
|
|
20
25
|
return "";
|
|
21
26
|
const offline = session?.stato === "irraggiungibile" ? valutaLicenzaLocale(env) : null;
|
|
22
|
-
const decision = decisioneCancello(saved, session, offline);
|
|
27
|
+
const decision = decisioneCancello(saved || (esito.errore === "rete" ? "offline" : ""), session, offline);
|
|
23
28
|
let tier = decision.tier;
|
|
24
29
|
let token = saved;
|
|
25
30
|
const note = () => tr("Account connesso", "Account connected") +
|
|
@@ -38,18 +43,18 @@ export async function enterAccount(env, theme) {
|
|
|
38
43
|
const write = (text) => { stdout.write(` ${text}\n`); };
|
|
39
44
|
try {
|
|
40
45
|
if (decision.azione === "login") {
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
rimuoviSessione(env);
|
|
47
|
+
rimuoviTokenVascend(env);
|
|
43
48
|
stdout.write(`\n ${tr("Preparazione dell'accesso a Talos...", "Preparing Talos sign-in...")}`);
|
|
44
49
|
const grant = await startWebLogin(env, language, {}, abort.signal)
|
|
45
50
|
.finally(() => { stdout.write(env.TERM === "dumb" ? "\n" : "\r\x1b[2K"); });
|
|
46
51
|
const finish = showWebLoginScreen(grant, abort, { env, theme });
|
|
47
52
|
try {
|
|
48
|
-
const account = await waitForWebLogin(env, grant, {}, abort.signal);
|
|
49
|
-
if (!
|
|
53
|
+
const account = await waitForWebLogin(env, grant, language, {}, abort.signal);
|
|
54
|
+
if (!salvaSessione(env, account))
|
|
50
55
|
throw new Error(TESTI[language].tokenNonSalvabile);
|
|
51
56
|
token = account.token;
|
|
52
|
-
tier =
|
|
57
|
+
tier = undefined;
|
|
53
58
|
finish(true);
|
|
54
59
|
write(TESTI[language].benvenuto(account.email));
|
|
55
60
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AgentSession, AgentSessions } from "./agent-sessions.js";
|
|
2
|
+
import type { QueueStyle } from "./queue-screen.js";
|
|
3
|
+
import type { ScreenKey, TerminalScreen } from "./terminal-screen.js";
|
|
4
|
+
export declare function sessionDuration(ms: number): string;
|
|
5
|
+
export declare class AgentSessionsScreen implements TerminalScreen {
|
|
6
|
+
private readonly store;
|
|
7
|
+
private readonly style;
|
|
8
|
+
private readonly onDelete?;
|
|
9
|
+
private selected;
|
|
10
|
+
private active;
|
|
11
|
+
private offset;
|
|
12
|
+
private pageSize;
|
|
13
|
+
private maxOffset;
|
|
14
|
+
private follow;
|
|
15
|
+
private readonly transcript;
|
|
16
|
+
focused: boolean;
|
|
17
|
+
private deleteConfirmation?;
|
|
18
|
+
constructor(store: AgentSessions, style?: QueueStyle, onDelete?: ((session: AgentSession) => {
|
|
19
|
+
ok: boolean;
|
|
20
|
+
error?: string;
|
|
21
|
+
}) | undefined);
|
|
22
|
+
private deleteSelected;
|
|
23
|
+
get session(): AgentSession;
|
|
24
|
+
conversation(width: number, height: number): readonly string[];
|
|
25
|
+
get selectedId(): string;
|
|
26
|
+
get activeId(): string;
|
|
27
|
+
get available(): boolean;
|
|
28
|
+
returnToMain(): void;
|
|
29
|
+
sync(): void;
|
|
30
|
+
private select;
|
|
31
|
+
key(_text: string, key: ScreenKey): "close" | void;
|
|
32
|
+
scroll(delta: number): void;
|
|
33
|
+
preview(width: number, maxRows?: number): readonly string[];
|
|
34
|
+
render(width: number, height: number): readonly string[];
|
|
35
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { tr } from "./i18n.js";
|
|
2
|
+
import { PLAIN_QUEUE_STYLE } from "./queue-screen.js";
|
|
3
|
+
import { fitLine, oneLine, terminalWidth } from "./terminal-text.js";
|
|
4
|
+
import { SessionTranscriptLayout } from "./session-transcript-layout.js";
|
|
5
|
+
import { agentLabel } from "./agent-label.js";
|
|
6
|
+
export function sessionDuration(ms) {
|
|
7
|
+
const seconds = Math.floor(Math.max(0, ms) / 1000);
|
|
8
|
+
return seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
9
|
+
}
|
|
10
|
+
function tokenCount(n) {
|
|
11
|
+
return n < 1000 ? String(n) : n < 1_000_000 ? `${(n / 1000).toFixed(1)}k` : `${(n / 1_000_000).toFixed(1)}m`;
|
|
12
|
+
}
|
|
13
|
+
function metrics(session) {
|
|
14
|
+
const total = session.inputTokens + session.outputTokens;
|
|
15
|
+
return `${sessionDuration(session.elapsedMs)} · ${session.usageMissing ? "≥" : ""}${session.usageKnown ? tokenCount(total) : "—"} tokens`;
|
|
16
|
+
}
|
|
17
|
+
// One selector is shared by the chat strip and the worker viewport. Moving the
|
|
18
|
+
// cursor never switches the viewed session until Enter confirms the selection.
|
|
19
|
+
export class AgentSessionsScreen {
|
|
20
|
+
store;
|
|
21
|
+
style;
|
|
22
|
+
onDelete;
|
|
23
|
+
selected = "main";
|
|
24
|
+
active = "main";
|
|
25
|
+
offset = 0;
|
|
26
|
+
pageSize = 1;
|
|
27
|
+
maxOffset = 0;
|
|
28
|
+
follow = true;
|
|
29
|
+
transcript = new SessionTranscriptLayout();
|
|
30
|
+
focused = false;
|
|
31
|
+
deleteConfirmation;
|
|
32
|
+
constructor(store, style = PLAIN_QUEUE_STYLE, onDelete) {
|
|
33
|
+
this.store = store;
|
|
34
|
+
this.style = style;
|
|
35
|
+
this.onDelete = onDelete;
|
|
36
|
+
}
|
|
37
|
+
deleteSelected() {
|
|
38
|
+
const session = this.store.get(this.selectedId);
|
|
39
|
+
if (!session || session.id === "main" || !this.onDelete)
|
|
40
|
+
return;
|
|
41
|
+
if (session.running && (this.deleteConfirmation?.id !== session.id || this.deleteConfirmation.until < Date.now())) {
|
|
42
|
+
this.deleteConfirmation = { id: session.id, until: Date.now() + 3000 };
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
this.deleteConfirmation = undefined;
|
|
46
|
+
const result = this.onDelete(session);
|
|
47
|
+
if (result.ok) {
|
|
48
|
+
this.store.delete(session.id);
|
|
49
|
+
this.sync();
|
|
50
|
+
}
|
|
51
|
+
else
|
|
52
|
+
this.store.notify(session.id, result.error ?? tr("Eliminazione non riuscita", "Deletion failed"));
|
|
53
|
+
}
|
|
54
|
+
get session() { return this.store.get(this.activeId); }
|
|
55
|
+
conversation(width, height) {
|
|
56
|
+
const session = this.session;
|
|
57
|
+
const lines = this.store.conversations.layout(session.id, width)
|
|
58
|
+
?? this.transcript.lines(session.id, [session.goal, ...session.transcript], Math.max(2, width - 2));
|
|
59
|
+
this.pageSize = Math.max(1, height);
|
|
60
|
+
this.maxOffset = Math.max(0, lines.length - this.pageSize);
|
|
61
|
+
this.offset = this.follow ? this.maxOffset : Math.min(this.offset, this.maxOffset);
|
|
62
|
+
return lines.slice(this.offset, this.offset + this.pageSize);
|
|
63
|
+
}
|
|
64
|
+
get selectedId() { this.sync(); return this.selected; }
|
|
65
|
+
get activeId() { this.sync(); return this.active; }
|
|
66
|
+
get available() { return this.store.hasAgents; }
|
|
67
|
+
returnToMain() {
|
|
68
|
+
this.active = "main";
|
|
69
|
+
this.selected = "main";
|
|
70
|
+
this.focused = false;
|
|
71
|
+
this.follow = true;
|
|
72
|
+
this.offset = 0;
|
|
73
|
+
}
|
|
74
|
+
sync() {
|
|
75
|
+
this.transcript.retain(new Set(this.store.list().map(s => s.id)));
|
|
76
|
+
if (!this.store.get(this.active)?.live)
|
|
77
|
+
this.returnToMain();
|
|
78
|
+
if (!this.store.get(this.selected)?.live)
|
|
79
|
+
this.selected = this.active;
|
|
80
|
+
if (!this.available)
|
|
81
|
+
this.focused = false;
|
|
82
|
+
if (this.deleteConfirmation && (!this.focused || this.deleteConfirmation.id !== this.selected || this.deleteConfirmation.until < Date.now())) {
|
|
83
|
+
this.deleteConfirmation = undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
select(delta) {
|
|
87
|
+
this.sync();
|
|
88
|
+
const sessions = this.store.list();
|
|
89
|
+
const index = sessions.findIndex(s => s.id === this.selected);
|
|
90
|
+
this.selected = sessions[Math.max(0, Math.min(sessions.length - 1, index + delta))].id;
|
|
91
|
+
this.focused = true;
|
|
92
|
+
}
|
|
93
|
+
key(_text, key) {
|
|
94
|
+
this.sync();
|
|
95
|
+
if (key.name === "delete" && this.focused) {
|
|
96
|
+
this.deleteSelected();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this.deleteConfirmation = undefined;
|
|
100
|
+
if (key.name === "up" || key.name === "down")
|
|
101
|
+
this.select(key.name === "up" ? -1 : 1);
|
|
102
|
+
else if (key.name === "return" || key.name === "enter") {
|
|
103
|
+
this.active = this.selected;
|
|
104
|
+
this.follow = true;
|
|
105
|
+
this.offset = 0;
|
|
106
|
+
if (this.active === "main") {
|
|
107
|
+
this.focused = false;
|
|
108
|
+
return "close";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else if (key.name === "pageup" || key.name === "pagedown") {
|
|
112
|
+
this.scroll(key.name === "pageup" ? -this.pageSize : this.pageSize);
|
|
113
|
+
}
|
|
114
|
+
else if (key.name === "end") {
|
|
115
|
+
this.follow = true;
|
|
116
|
+
this.offset = this.maxOffset;
|
|
117
|
+
}
|
|
118
|
+
else if (key.name === "home") {
|
|
119
|
+
this.follow = false;
|
|
120
|
+
this.offset = 0;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
scroll(delta) {
|
|
124
|
+
this.offset = Math.max(0, Math.min(this.maxOffset, this.offset + delta));
|
|
125
|
+
this.follow = this.offset === this.maxOffset;
|
|
126
|
+
}
|
|
127
|
+
preview(width, maxRows = 5) {
|
|
128
|
+
this.sync();
|
|
129
|
+
if (!this.available)
|
|
130
|
+
return [];
|
|
131
|
+
const sessions = this.store.list();
|
|
132
|
+
const capacity = Math.max(1, maxRows - 1);
|
|
133
|
+
const index = Math.max(0, sessions.findIndex(s => s.id === this.selected));
|
|
134
|
+
const start = Math.max(0, Math.min(index - Math.floor(capacity / 2), sessions.length - capacity));
|
|
135
|
+
const deletion = this.onDelete && this.selected !== "main"
|
|
136
|
+
? this.deleteConfirmation ? tr("[Canc: conferma stop ed elimina]", "[Del: confirm stop and delete]")
|
|
137
|
+
: tr("[Canc: elimina sessione]", "[Del: delete session]") : "";
|
|
138
|
+
const help = this.focused
|
|
139
|
+
? `${deletion ? deletion + " · " : ""}${tr("↑↓ seleziona · Invio apri", "↑↓ select · Enter open")}`
|
|
140
|
+
: tr("↓ sessioni · Alt+A seleziona", "↓ sessions · Alt+A select");
|
|
141
|
+
const range = sessions.length > capacity ? ` [${start + 1}–${Math.min(sessions.length, start + capacity)}/${sessions.length}]` : "";
|
|
142
|
+
const rows = [this.style.muted(fitLine(` ${help}${range}`, width - 1))];
|
|
143
|
+
for (const s of sessions.slice(start, start + capacity)) {
|
|
144
|
+
const indicator = this.focused && s.id === this.selected ? ">" : " ";
|
|
145
|
+
const name = ` ${indicator} ${s.id === this.active ? "*" : " "} ${oneLine(agentLabel(s.actor))}`;
|
|
146
|
+
const tail = ` ${metrics(s)}`;
|
|
147
|
+
const room = Math.max(1, width - 1 - terminalWidth(tail));
|
|
148
|
+
const activity = s.activity ? ` ${oneLine(s.activity)}` : "";
|
|
149
|
+
const label = fitLine(name + activity, room);
|
|
150
|
+
const row = width < 36 ? fitLine(`${name} ${metrics(s)}`, width - 1)
|
|
151
|
+
: label + " ".repeat(Math.max(0, room - terminalWidth(label))) + tail;
|
|
152
|
+
rows.push(s.id === this.selected && this.focused ? this.style.selected(row) : (this.style.text ?? this.style.muted)(row));
|
|
153
|
+
}
|
|
154
|
+
return rows;
|
|
155
|
+
}
|
|
156
|
+
render(width, height) {
|
|
157
|
+
this.sync();
|
|
158
|
+
const h = Math.max(1, height), w = Math.max(1, width - 2);
|
|
159
|
+
const session = this.store.get(this.active);
|
|
160
|
+
const heading = this.style.heading(fitLine(` ${tr("Sessione", "Session")} · ${oneLine(agentLabel(session.actor))} · ${metrics(session)}`, width - 1));
|
|
161
|
+
const list = this.preview(width, Math.min(6, Math.max(2, Math.floor(h / 3))));
|
|
162
|
+
const help = this.style.muted(fitLine(tr("↑↓ seleziona · Invio apri · seleziona principale per tornare · PgSu/PgGiù output", "↑↓ select · Enter open · select main to return · PgUp/PgDn output"), width - 1));
|
|
163
|
+
const head = [heading, ...list, ""];
|
|
164
|
+
const usage = session.usageKnown
|
|
165
|
+
? `Input: ${tokenCount(session.inputTokens)} · Output: ${tokenCount(session.outputTokens)}`
|
|
166
|
+
: tr("Token non ancora comunicati dal provider.", "Tokens not yet reported by the provider.");
|
|
167
|
+
const blocks = [session.goal, usage, ...session.transcript].filter(Boolean);
|
|
168
|
+
const lines = this.transcript.lines(session.id, blocks.length ? blocks : [tr("In attesa di attività…", "Waiting for activity…")], w);
|
|
169
|
+
this.pageSize = Math.max(1, h - head.length - 1);
|
|
170
|
+
this.maxOffset = Math.max(0, lines.length - this.pageSize);
|
|
171
|
+
this.offset = this.follow ? this.maxOffset : Math.min(this.offset, this.maxOffset);
|
|
172
|
+
const body = lines.slice(this.offset, this.offset + this.pageSize).map(line => " " + line);
|
|
173
|
+
const rows = [...head, ...body];
|
|
174
|
+
while (rows.length < h - 1)
|
|
175
|
+
rows.push("");
|
|
176
|
+
return [...rows.slice(0, Math.max(0, h - 1)), help].map(row => fitLine(row, width - 1));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ContextLedger } from "../core/context-ledger.js";
|
|
2
|
+
import { WorkerTranscripts } from "./worker-transcripts.js";
|
|
3
|
+
import type { AgentEvent } from "../core/types.js";
|
|
4
|
+
import type { SessionUsageRecord } from "../core/session-usage.js";
|
|
5
|
+
export interface AgentSession {
|
|
6
|
+
readonly kingdomId?: string;
|
|
7
|
+
readonly context?: ContextLedger;
|
|
8
|
+
readonly compacting?: boolean;
|
|
9
|
+
readonly compactingAt?: number;
|
|
10
|
+
readonly notice?: string;
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly actor: string;
|
|
13
|
+
readonly goal: string;
|
|
14
|
+
readonly activity: string;
|
|
15
|
+
readonly live: boolean;
|
|
16
|
+
readonly running: boolean;
|
|
17
|
+
readonly startedAt?: number;
|
|
18
|
+
readonly elapsedMs: number;
|
|
19
|
+
readonly inputTokens: number;
|
|
20
|
+
readonly outputTokens: number;
|
|
21
|
+
readonly usageKnown: boolean;
|
|
22
|
+
readonly usageMissing: boolean;
|
|
23
|
+
readonly transcript: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
export declare class AgentSessions {
|
|
26
|
+
readonly conversations: WorkerTranscripts;
|
|
27
|
+
private sessions;
|
|
28
|
+
private actors;
|
|
29
|
+
private seenUsage;
|
|
30
|
+
private deleted;
|
|
31
|
+
private listeners;
|
|
32
|
+
private messageListeners;
|
|
33
|
+
onMessage(listener: (id: string, messageId: string) => void): () => void;
|
|
34
|
+
subscribe(listener: () => void): () => void;
|
|
35
|
+
private changed;
|
|
36
|
+
reset(): void;
|
|
37
|
+
restoreMain(history: {
|
|
38
|
+
records: readonly SessionUsageRecord[];
|
|
39
|
+
incomplete: boolean;
|
|
40
|
+
}): void;
|
|
41
|
+
list(now?: number): readonly AgentSession[];
|
|
42
|
+
get(id: string, now?: number): AgentSession | undefined;
|
|
43
|
+
get hasAgents(): boolean;
|
|
44
|
+
private snapshot;
|
|
45
|
+
/** Remove only the live UI session, never files or persisted team reports. */
|
|
46
|
+
delete(id: string): boolean;
|
|
47
|
+
notify(id: string, notice: string): void;
|
|
48
|
+
begin(goal: string, at?: number): void;
|
|
49
|
+
finish(at?: number): void;
|
|
50
|
+
private stop;
|
|
51
|
+
private log;
|
|
52
|
+
record(event: AgentEvent, at?: number, actor?: string): void;
|
|
53
|
+
}
|