@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
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// Una sessione di controllo remoto: il ponte fra l'agente di Talos e il relay.
|
|
2
|
+
//
|
|
3
|
+
// Verso il telefono (eventi, cifrati, direzione "ev"):
|
|
4
|
+
// message {role: "user"|"assistant", text}
|
|
5
|
+
// delta {text} testo mentre il modello scrive
|
|
6
|
+
// tool_call {id, name, input, parent?} parent: chiamata che la contiene
|
|
7
|
+
// tool_result {id, error, output, parent?}
|
|
8
|
+
// permission {id, action, detail} Talos chiede un'approvazione
|
|
9
|
+
// status {state, label?, permission?: {id, outcome, by}}
|
|
10
|
+
// end {}
|
|
11
|
+
// Dal telefono (comandi, cifrati, direzione "cmd"): il contenuto porta anche
|
|
12
|
+
// il proprio cid e l'ora (ts, ms), cosi' il relay non puo' riusarlo ne'
|
|
13
|
+
// spostarlo su un altro comando.
|
|
14
|
+
// message {text} come se fosse scritto nella TUI (mai un "/")
|
|
15
|
+
// interrupt {text?} con testo: consegna subito; senza: stop
|
|
16
|
+
// stop {}
|
|
17
|
+
// approve {permission} deny {permission}
|
|
18
|
+
//
|
|
19
|
+
// Gli eventi si cifrano e si accodano in ordine (una catena di promesse): il
|
|
20
|
+
// seq del relay e' contiguo e non deve mai saltare.
|
|
21
|
+
import { hostname } from "node:os";
|
|
22
|
+
import { basename } from "node:path";
|
|
23
|
+
import { randomBytes } from "node:crypto";
|
|
24
|
+
import { CifraturaError, cifra, decifra, nuovaChiave } from "./cifratura.js";
|
|
25
|
+
import { RelayHost } from "./relay-client.js";
|
|
26
|
+
export const VIEWER_URL = "https://vascend.it/remoto";
|
|
27
|
+
const MAX_TESTO = 64_000;
|
|
28
|
+
const MAX_ANTEPRIMA = 4_000;
|
|
29
|
+
const RITMO_DELTA_MS = 120;
|
|
30
|
+
const FINESTRA_COMANDI_MS = 10 * 60_000;
|
|
31
|
+
function tronca(testo, max) {
|
|
32
|
+
return testo.length <= max ? testo : `${testo.slice(0, max)}\n[... ${testo.length - max} caratteri non inviati]`;
|
|
33
|
+
}
|
|
34
|
+
function anteprimaInput(input) {
|
|
35
|
+
try {
|
|
36
|
+
return tronca(JSON.stringify(input) ?? "", MAX_ANTEPRIMA);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return "";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export class SessioneRemota {
|
|
43
|
+
relay;
|
|
44
|
+
chiave;
|
|
45
|
+
link;
|
|
46
|
+
mani;
|
|
47
|
+
now;
|
|
48
|
+
catena = Promise.resolve();
|
|
49
|
+
delta = "";
|
|
50
|
+
timerDelta = null;
|
|
51
|
+
risposta = "";
|
|
52
|
+
viewer = 0;
|
|
53
|
+
permessi = new Map();
|
|
54
|
+
constructor(relay, chiave, link, mani, now) {
|
|
55
|
+
this.relay = relay;
|
|
56
|
+
this.chiave = chiave;
|
|
57
|
+
this.link = link;
|
|
58
|
+
this.mani = mani;
|
|
59
|
+
this.now = now;
|
|
60
|
+
}
|
|
61
|
+
static async avvia(opts) {
|
|
62
|
+
const { chiave, testo } = await nuovaChiave();
|
|
63
|
+
let sessione = null;
|
|
64
|
+
const relay = await RelayHost.apri(opts.base, {
|
|
65
|
+
title: basename(opts.cwd) || "Talos",
|
|
66
|
+
agent: "talos",
|
|
67
|
+
device: hostname().slice(0, 80),
|
|
68
|
+
}, {
|
|
69
|
+
...opts.relayDeps,
|
|
70
|
+
token: opts.token,
|
|
71
|
+
onStato: opts.onStato,
|
|
72
|
+
onPresenza: (n) => { if (sessione)
|
|
73
|
+
sessione.viewer = n; opts.onPresenza?.(n); },
|
|
74
|
+
onComando: (c) => sessione ? sessione.comando(c) : Promise.resolve(),
|
|
75
|
+
});
|
|
76
|
+
const link = `${VIEWER_URL}#s=${relay.sessione}&k=${testo}`;
|
|
77
|
+
sessione = new SessioneRemota(relay, chiave, link, opts.mani, opts.now ?? Date.now);
|
|
78
|
+
sessione.stato({ state: "idle" });
|
|
79
|
+
return sessione;
|
|
80
|
+
}
|
|
81
|
+
get id() { return this.relay.sessione; }
|
|
82
|
+
statoRelay() { return this.relay.statoAttuale(); }
|
|
83
|
+
dispositivi() { return this.viewer; }
|
|
84
|
+
// --- dall'agente al telefono --------------------------------------------------
|
|
85
|
+
// Adattatore per gli eventi dell'agente di Talos.
|
|
86
|
+
osserva(event) {
|
|
87
|
+
switch (event.type) {
|
|
88
|
+
case "turn_start":
|
|
89
|
+
this.statoAgente("thinking");
|
|
90
|
+
return;
|
|
91
|
+
case "text":
|
|
92
|
+
this.testo(event.delta);
|
|
93
|
+
return;
|
|
94
|
+
case "tool_call":
|
|
95
|
+
this.chiamataTool({ id: event.call.id, name: event.call.name, input: event.call.input, parent: event.parentId });
|
|
96
|
+
return;
|
|
97
|
+
case "tool_result":
|
|
98
|
+
this.risultatoTool({ id: event.result.callId, error: event.result.isError, output: event.result.output ?? "", parent: event.parentId });
|
|
99
|
+
return;
|
|
100
|
+
case "status":
|
|
101
|
+
this.statoAgente("working", event.label);
|
|
102
|
+
return;
|
|
103
|
+
case "turn_end":
|
|
104
|
+
this.rispostaCompleta();
|
|
105
|
+
return;
|
|
106
|
+
case "done":
|
|
107
|
+
this.rispostaCompleta();
|
|
108
|
+
this.statoAgente("idle");
|
|
109
|
+
return;
|
|
110
|
+
case "error":
|
|
111
|
+
this.rispostaCompleta();
|
|
112
|
+
this.statoAgente("error", event.message);
|
|
113
|
+
return;
|
|
114
|
+
default: return;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// --- API generica: per chi non ha gli eventi di Talos (l'IDE con Claude,
|
|
118
|
+
// Codex e gli altri motori traduce i suoi eventi in queste chiamate) -------
|
|
119
|
+
// Un pezzo della risposta mentre il modello scrive.
|
|
120
|
+
testo(delta) {
|
|
121
|
+
if (!delta)
|
|
122
|
+
return;
|
|
123
|
+
this.risposta += delta;
|
|
124
|
+
this.delta += delta;
|
|
125
|
+
if (this.delta.length >= 2_048)
|
|
126
|
+
this.svuotaDelta();
|
|
127
|
+
else if (!this.timerDelta)
|
|
128
|
+
this.timerDelta = setTimeout(() => this.svuotaDelta(), RITMO_DELTA_MS);
|
|
129
|
+
}
|
|
130
|
+
// Fine della risposta in corso: diventa un messaggio completo.
|
|
131
|
+
rispostaCompleta() {
|
|
132
|
+
this.chiudiRisposta();
|
|
133
|
+
}
|
|
134
|
+
chiamataTool(c) {
|
|
135
|
+
this.chiudiRisposta();
|
|
136
|
+
this.evento("tool_call", {
|
|
137
|
+
id: c.id, name: tronca(c.name, 200), input: typeof c.input === "string" ? tronca(c.input, MAX_ANTEPRIMA) : anteprimaInput(c.input),
|
|
138
|
+
...(c.parent ? { parent: c.parent } : {}),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
risultatoTool(r) {
|
|
142
|
+
this.evento("tool_result", {
|
|
143
|
+
id: r.id, error: r.error, output: tronca(r.output, MAX_ANTEPRIMA), ...(r.parent ? { parent: r.parent } : {}),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
statoAgente(state, label) {
|
|
147
|
+
this.stato(label ? { state, label: tronca(label, state === "error" ? 500 : 200) } : { state });
|
|
148
|
+
}
|
|
149
|
+
messaggioUtente(testo) {
|
|
150
|
+
this.chiudiRisposta();
|
|
151
|
+
this.evento("message", { role: "user", text: tronca(testo, MAX_TESTO) });
|
|
152
|
+
}
|
|
153
|
+
// Richiesta di permesso in gara con la TUI: vince la prima risposta. La TUI
|
|
154
|
+
// riceve un segnale che si annulla quando risponde il telefono (e viceversa).
|
|
155
|
+
async permessoConGara(azione, dettaglio, signal, tui) {
|
|
156
|
+
const id = randomBytes(12).toString("hex");
|
|
157
|
+
const locale = new AbortController();
|
|
158
|
+
const entrambi = AbortSignal.any([signal, locale.signal]);
|
|
159
|
+
const dalTelefono = new Promise((resolve) => {
|
|
160
|
+
this.permessi.set(id, (valore) => resolve({ valore, da: "remote" }));
|
|
161
|
+
entrambi.addEventListener("abort", () => this.permessi.delete(id), { once: true });
|
|
162
|
+
});
|
|
163
|
+
this.chiudiRisposta();
|
|
164
|
+
this.evento("permission", { id, action: tronca(azione, 200), detail: tronca(dettaglio, MAX_ANTEPRIMA) });
|
|
165
|
+
this.stato({ state: "waiting", label: tronca(azione, 200) });
|
|
166
|
+
let esito;
|
|
167
|
+
try {
|
|
168
|
+
esito = await Promise.race([tui(entrambi).then((valore) => ({ valore, da: "talos" })), dalTelefono]);
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
locale.abort();
|
|
172
|
+
this.permessi.delete(id);
|
|
173
|
+
}
|
|
174
|
+
const outcome = signal.aborted ? "cancelled" : esito.valore ? "allowed" : "denied";
|
|
175
|
+
this.stato({ state: "working", permission: { id, outcome, by: esito.da } });
|
|
176
|
+
return esito.valore;
|
|
177
|
+
}
|
|
178
|
+
// Fine: ultimo stato, "end", poi la sessione si chiude per tutti.
|
|
179
|
+
async chiudi() {
|
|
180
|
+
this.chiudiRisposta();
|
|
181
|
+
for (const risolvi of this.permessi.values())
|
|
182
|
+
risolvi(false);
|
|
183
|
+
this.permessi.clear();
|
|
184
|
+
this.evento("end", {});
|
|
185
|
+
await this.catena;
|
|
186
|
+
await this.relay.chiudi();
|
|
187
|
+
}
|
|
188
|
+
// --- dal telefono all'agente --------------------------------------------------
|
|
189
|
+
async comando(c) {
|
|
190
|
+
if (!c.b)
|
|
191
|
+
return;
|
|
192
|
+
let dati;
|
|
193
|
+
try {
|
|
194
|
+
const v = await decifra(this.chiave, this.relay.sessione, "cmd", c.b);
|
|
195
|
+
if (!v || typeof v !== "object" || Array.isArray(v))
|
|
196
|
+
return;
|
|
197
|
+
dati = v;
|
|
198
|
+
}
|
|
199
|
+
catch (e) {
|
|
200
|
+
if (e instanceof CifraturaError)
|
|
201
|
+
return; // non viene da un dispositivo abbinato
|
|
202
|
+
throw e;
|
|
203
|
+
}
|
|
204
|
+
// Il contenuto cifrato deve riguardare proprio questo comando e essere recente.
|
|
205
|
+
const ts = Number(dati["ts"]);
|
|
206
|
+
if (dati["cid"] !== c.cid || !Number.isFinite(ts) || Math.abs(this.now() - ts) > FINESTRA_COMANDI_MS)
|
|
207
|
+
return;
|
|
208
|
+
const testo = typeof dati["text"] === "string" ? dati["text"].slice(0, MAX_TESTO) : "";
|
|
209
|
+
switch (c.k) {
|
|
210
|
+
case "message":
|
|
211
|
+
if (testo.trim() && !this.mani.invia(testo, false))
|
|
212
|
+
this.stato({ state: "working", label: "comando non accettato" });
|
|
213
|
+
return;
|
|
214
|
+
case "interrupt":
|
|
215
|
+
if (testo.trim())
|
|
216
|
+
this.mani.invia(testo, true);
|
|
217
|
+
else
|
|
218
|
+
this.mani.ferma();
|
|
219
|
+
return;
|
|
220
|
+
case "stop":
|
|
221
|
+
this.mani.ferma();
|
|
222
|
+
return;
|
|
223
|
+
case "approve":
|
|
224
|
+
case "deny": {
|
|
225
|
+
const id = typeof dati["permission"] === "string" ? dati["permission"] : "";
|
|
226
|
+
this.permessi.get(id)?.(c.k === "approve");
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
default:
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// --- invio ordinato -----------------------------------------------------------
|
|
234
|
+
svuotaDelta() {
|
|
235
|
+
if (this.timerDelta) {
|
|
236
|
+
clearTimeout(this.timerDelta);
|
|
237
|
+
this.timerDelta = null;
|
|
238
|
+
}
|
|
239
|
+
if (!this.delta)
|
|
240
|
+
return;
|
|
241
|
+
const testo = this.delta;
|
|
242
|
+
this.delta = "";
|
|
243
|
+
this.accoda("delta", { text: testo });
|
|
244
|
+
}
|
|
245
|
+
chiudiRisposta() {
|
|
246
|
+
this.svuotaDelta();
|
|
247
|
+
const testo = this.risposta.trim();
|
|
248
|
+
this.risposta = "";
|
|
249
|
+
if (testo)
|
|
250
|
+
this.accoda("message", { role: "assistant", text: tronca(testo, MAX_TESTO) });
|
|
251
|
+
}
|
|
252
|
+
stato(dati) {
|
|
253
|
+
this.accoda("status", dati);
|
|
254
|
+
}
|
|
255
|
+
evento(k, dati) {
|
|
256
|
+
this.svuotaDelta();
|
|
257
|
+
this.accoda(k, dati);
|
|
258
|
+
}
|
|
259
|
+
accoda(k, dati) {
|
|
260
|
+
const sessione = this.relay.sessione;
|
|
261
|
+
this.catena = this.catena
|
|
262
|
+
.then(() => cifra(this.chiave, sessione, "ev", dati))
|
|
263
|
+
.then((b) => { this.relay.invia(k, b); })
|
|
264
|
+
.catch(() => { });
|
|
265
|
+
}
|
|
266
|
+
}
|
package/dist/sdk.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export { bootstrap } from "./core/bootstrap.js";
|
|
2
2
|
export type { Harness } from "./core/bootstrap.js";
|
|
3
|
+
export type { FusionConfig, FusionGateMode, FusionAvailability } from "./core/fusion.js";
|
|
4
|
+
export { DEFAULT_FUSION, fusionAvailability, isPaidTier, parseFusion } from "./core/fusion.js";
|
|
5
|
+
export type { StepDirective, StepPolicy } from "./core/step-policy.js";
|
|
6
|
+
export { createJevClient, isDevChannel, parseJevResponse, resolveJevTransport } from "./fusion/jev.js";
|
|
7
|
+
export type { JevAnswer, JevClient, JevOutcome, JevQuestion, JevResult, JevTransport } from "./fusion/jev.js";
|
|
3
8
|
export { runTurn } from "./core/agent.js";
|
|
4
9
|
export type { AgentDeps } from "./core/agent.js";
|
|
5
10
|
export { FileCoordinationHub, fileActor, formatFileConflicts, withFileActor } from "./core/file-coordination.js";
|
|
@@ -52,8 +57,8 @@ export { buildArchitectureMap, renderArchitectureMap, scanArchitectureMap, } fro
|
|
|
52
57
|
export type { ArchDependency, ArchEntryPoint, ArchExternal, ArchHotspot, ArchModuleStat, ArchSourceFile, ArchitectureMap, } from "./vascend/architecture-map.js";
|
|
53
58
|
export { doctorExitCode, renderDoctorReport, runDoctor } from "./core/doctor.js";
|
|
54
59
|
export type { DoctorCheck, DoctorReport, DoctorStatus } from "./core/doctor.js";
|
|
55
|
-
export { HORIZON_CAPABILITIES, HorizonContextUnavailableError, HorizonEngine, HorizonMainTeam, needsGuideArbitration, HorizonSessionNotFoundError, HorizonStateError, routeWorkerModels, } from "./horizon/index.js";
|
|
56
|
-
export type { HorizonCapabilityDescriptor, HorizonContextStatus, HorizonEngineOptions, HorizonEngineState, HorizonModelCatalog, HorizonModelDescriptor, HorizonModelInspectionOptions, HorizonProviderDescriptor, HorizonRuntime, HorizonSessionListItem, HorizonSessionSnapshot, HorizonTurn, HorizonTurnInput, HorizonTurnOptions, HorizonTurnResult, HorizonTurnStatus, HorizonVibeStatus, } from "./horizon/index.js";
|
|
60
|
+
export { HORIZON_CAPABILITIES, HorizonContextUnavailableError, HorizonFusionUnavailableError, HorizonEngine, HorizonMainTeam, needsGuideArbitration, HorizonSessionNotFoundError, HorizonStateError, routeWorkerModels, } from "./horizon/index.js";
|
|
61
|
+
export type { HorizonCapabilityDescriptor, HorizonContextStatus, HorizonEngineOptions, HorizonEngineState, HorizonModelCatalog, HorizonModelDescriptor, HorizonModelInspectionOptions, HorizonProviderDescriptor, HorizonRuntime, HorizonSessionListItem, HorizonSessionSnapshot, HorizonTurn, HorizonTurnInput, HorizonTurnOptions, HorizonTurnResult, HorizonTurnStatus, HorizonVibeStatus, HorizonFusionStatus, } from "./horizon/index.js";
|
|
57
62
|
export type { HorizonGuideCooperation, HorizonGuideDecision, HorizonGuideDecisionRecord, HorizonGuideDecisionRequest, HorizonGuidePlan, HorizonGuideTask, HorizonGuideVerdict, HorizonMainExchange, HorizonMainRef, HorizonMainTeamConfig, HorizonMainTeamEvent, HorizonMainTeamResult, HorizonMainTeamTurn, HorizonTeamRef, HorizonAgentPurpose, } from "./horizon/index.js";
|
|
58
63
|
export type { AgentEvent, EventSink, Message, ContentPart, Tool, ToolDef, ToolRegistrationDef, RegisteredTool, ToolHandler, ToolHandlerOutput, ToolContext, ImagePart, Provider, ModelTurn, CompletionRequest, } from "./core/types.js";
|
|
59
64
|
export type { Extension, ExtensionApi, SlashCommand, } from "./extensions/types.js";
|
package/dist/sdk.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// (es. il processo main di vascend-terminal). Quattro modalita' condividono
|
|
3
3
|
// lo stesso nucleo: TUI, print, RPC e questo SDK.
|
|
4
4
|
export { bootstrap } from "./core/bootstrap.js";
|
|
5
|
+
export { DEFAULT_FUSION, fusionAvailability, isPaidTier, parseFusion } from "./core/fusion.js";
|
|
6
|
+
export { createJevClient, isDevChannel, parseJevResponse, resolveJevTransport } from "./fusion/jev.js";
|
|
5
7
|
export { runTurn } from "./core/agent.js";
|
|
6
8
|
export { FileCoordinationHub, fileActor, formatFileConflicts, withFileActor } from "./core/file-coordination.js";
|
|
7
9
|
// Casella dei messaggi scritti mentre l'agente lavora: un host che usa runTurn
|
|
@@ -53,7 +55,7 @@ export { buildArchitectureMap, renderArchitectureMap, scanArchitectureMap, } fro
|
|
|
53
55
|
// Diagnostica ambiente (stessa del comando `talos --doctor`).
|
|
54
56
|
export { doctorExitCode, renderDoctorReport, runDoctor } from "./core/doctor.js";
|
|
55
57
|
// Horizon: facade headless stabile per l'embedding in Vascend Terminal.
|
|
56
|
-
export { HORIZON_CAPABILITIES, HorizonContextUnavailableError, HorizonEngine, HorizonMainTeam, needsGuideArbitration, HorizonSessionNotFoundError, HorizonStateError, routeWorkerModels, } from "./horizon/index.js";
|
|
58
|
+
export { HORIZON_CAPABILITIES, HorizonContextUnavailableError, HorizonFusionUnavailableError, HorizonEngine, HorizonMainTeam, needsGuideArbitration, HorizonSessionNotFoundError, HorizonStateError, routeWorkerModels, } from "./horizon/index.js";
|
|
57
59
|
// Modulo Cowork: workspace condivisi collaborativi su engine Talos (desktop).
|
|
58
60
|
export { CoworkManager, localIdentity, CoworkStore, CoworkSyncChannel, CoworkEngine, createCoworkIpc, createCoworkClient, } from "./cowork/index.js";
|
|
59
61
|
// Kingdoms Mode osservabile e INTERROGABILE dall'host: scrivere a un singolo
|
package/dist/tools/builtin.js
CHANGED
|
@@ -286,8 +286,10 @@ function runBashSpawn(command, ctx, options) {
|
|
|
286
286
|
mgr.clearForeground(task.id);
|
|
287
287
|
resolvePromise(isError ? toolError(msg) : msg);
|
|
288
288
|
};
|
|
289
|
-
child.stdout?.
|
|
290
|
-
child.stderr?.
|
|
289
|
+
child.stdout?.setEncoding("utf8");
|
|
290
|
+
child.stderr?.setEncoding("utf8");
|
|
291
|
+
child.stdout?.on("data", (text) => mgr.appendOutput(task.id, text));
|
|
292
|
+
child.stderr?.on("data", (text) => mgr.appendOutput(task.id, text));
|
|
291
293
|
child.on("error", (err) => {
|
|
292
294
|
mgr.finishTask(task.id, "failed");
|
|
293
295
|
finish(`errore esecuzione: ${err.message}`, true);
|
|
@@ -308,7 +310,7 @@ function runBashSpawn(command, ctx, options) {
|
|
|
308
310
|
finish(`comando in background [${task.id}]: ${command.length > 60 ? command.slice(0, 57) + "..." : command}\n` +
|
|
309
311
|
`Continua a girare. Leggi l'output con bash_output id="${task.id}".`);
|
|
310
312
|
};
|
|
311
|
-
mgr.setForeground({ taskId: task.id, background: detach });
|
|
313
|
+
mgr.setForeground({ taskId: task.id, sessionId: ctx.sessionId, background: detach });
|
|
312
314
|
// Un agente non puo' decidere di interrompere un tool mentre ne attende il
|
|
313
315
|
// risultato. Una breve attesa evita un secondo giro per i comandi rapidi;
|
|
314
316
|
// oltre il limite bash_output permette di osservare e terminare il task.
|
|
@@ -330,12 +332,18 @@ function runBashSpawn(command, ctx, options) {
|
|
|
330
332
|
export const bashOutputTool = {
|
|
331
333
|
name: "bash_output",
|
|
332
334
|
description: "Monitora e gestisce un comando shell in background. Passa `id` (es. \"bg1\") per " +
|
|
333
|
-
"
|
|
335
|
+
"attendere il risultato finale senza polling del modello; l'attesa e' interrompibile. " +
|
|
336
|
+
"`wait: false` legge subito stato/output (utile per server persistenti); senza id elenca i task. " +
|
|
337
|
+
"`timeout_seconds` limita esplicitamente l'attesa; omettilo per attendere il completamento. " +
|
|
338
|
+
"`kill: true` interrompe subito il processo.",
|
|
334
339
|
schema: {
|
|
335
340
|
type: "object",
|
|
336
341
|
properties: {
|
|
337
342
|
id: { type: "string", description: "id del task (es. bg1)" },
|
|
338
343
|
kill: { type: "boolean", description: "se true termina il task" },
|
|
344
|
+
wait: { type: "boolean", description: "default true: attende il completamento; false: legge subito, per server persistenti o diagnosi" },
|
|
345
|
+
timeout_seconds: { type: "number", minimum: 0, maximum: 3600,
|
|
346
|
+
description: "Limite opzionale dell'attesa in secondi; omesso attende il risultato finale, 0 legge subito" },
|
|
339
347
|
},
|
|
340
348
|
},
|
|
341
349
|
handler: async (input, ctx) => {
|
|
@@ -353,6 +361,13 @@ export const bashOutputTool = {
|
|
|
353
361
|
return toolError(`task non trovato: ${id}`);
|
|
354
362
|
if (input["kill"] === true)
|
|
355
363
|
return mgr.kill(id) ? `terminato ${id}` : `${id} non e' piu' in esecuzione`;
|
|
364
|
+
if (input["wait"] !== false && t.status === "running") {
|
|
365
|
+
const timeout = input["timeout_seconds"];
|
|
366
|
+
const timeoutMs = typeof timeout === "number" && Number.isFinite(timeout)
|
|
367
|
+
? Math.min(3600, Math.max(0, timeout)) * 1000 : undefined;
|
|
368
|
+
await mgr.waitForTask(id, ctx.signal, { timeoutMs, interrupted: ctx.waitInterrupted });
|
|
369
|
+
ctx.signal.throwIfAborted();
|
|
370
|
+
}
|
|
356
371
|
const head = `${t.id} [${t.status}${t.exitCode != null ? ` · uscita ${t.exitCode}` : ""}] ${t.command}`;
|
|
357
372
|
const output = `${head}\n${clamp(t.output) || "(nessun output)"}`;
|
|
358
373
|
return t.status === "failed" || t.status === "killed" ? toolError(output) : output;
|
|
@@ -367,7 +382,7 @@ const READ_FINESTRA_BYTES = 2_000_000;
|
|
|
367
382
|
const READ_SCAN_MAX_BYTES = 16_000_000;
|
|
368
383
|
const READ_CHUNK_BYTES = 262_144;
|
|
369
384
|
// Un read senza limit su un file grande ritorna comunque una finestra finita.
|
|
370
|
-
const READ_RIGHE_DEFAULT_GRANDI =
|
|
385
|
+
const READ_RIGHE_DEFAULT_GRANDI = 200;
|
|
371
386
|
// Lettura incrementale per righe di un file grande: chunk da 256KB, decoder
|
|
372
387
|
// streaming (i confini multi-byte non si spezzano), respiro periodico per
|
|
373
388
|
// l'event loop, stop appena la finestra richiesta e' completa.
|
|
@@ -437,14 +452,14 @@ async function leggiFinestra(abs, rel, taglia, offset, limit, ctx) {
|
|
|
437
452
|
export const readTool = {
|
|
438
453
|
name: "read_file",
|
|
439
454
|
execution: "parallel",
|
|
440
|
-
description: "Legge un file di testo (path libero). Per
|
|
455
|
+
description: "Legge un file di testo (path libero), default 200 righe. Per scegliere una porzione usa " +
|
|
441
456
|
"`offset` (riga di partenza, 1-based) e `limit` (numero di righe): NON serve bash/head/cat.",
|
|
442
457
|
schema: {
|
|
443
458
|
type: "object",
|
|
444
459
|
properties: {
|
|
445
460
|
path: { type: "string" },
|
|
446
461
|
offset: { type: "number", description: "riga di partenza (1-based), default 1" },
|
|
447
|
-
limit: { type: "number", description: "numero massimo di righe da leggere" },
|
|
462
|
+
limit: { type: "number", description: "numero massimo di righe da leggere (default 200)" },
|
|
448
463
|
},
|
|
449
464
|
required: ["path"],
|
|
450
465
|
},
|
|
@@ -461,8 +476,10 @@ export const readTool = {
|
|
|
461
476
|
mode: "viewing", others: conflicts, at: Date.now(),
|
|
462
477
|
});
|
|
463
478
|
}
|
|
464
|
-
const offset = typeof input["offset"] === "number" && input["offset"]
|
|
465
|
-
|
|
479
|
+
const offset = typeof input["offset"] === "number" && Number.isFinite(input["offset"]) && input["offset"] > 0
|
|
480
|
+
? Math.max(1, Math.floor(input["offset"])) : 1;
|
|
481
|
+
const limit = typeof input["limit"] === "number" && Number.isFinite(input["limit"]) && input["limit"] > 0
|
|
482
|
+
? Math.max(1, Math.floor(input["limit"])) : READ_RIGHE_DEFAULT_GRANDI;
|
|
466
483
|
// I file grandi non si leggono mai integrali: finestra incrementale.
|
|
467
484
|
const taglia = (await stat(abs)).size;
|
|
468
485
|
const notaPresenza = conflicts.length
|
|
@@ -471,14 +488,13 @@ export const readTool = {
|
|
|
471
488
|
if (taglia > READ_FINESTRA_BYTES)
|
|
472
489
|
return await leggiFinestra(abs, rel, taglia, offset, limit, ctx) + notaPresenza;
|
|
473
490
|
const full = await readFile(abs, "utf8");
|
|
474
|
-
if (offset <= 1 && limit <= 0)
|
|
475
|
-
return paginate(full, `file ${rel}`, ctx) + notaPresenza;
|
|
476
491
|
// Lettura parziale per righe (stile Claude Code): porzione [offset, offset+limit).
|
|
477
492
|
const lines = full.split("\n");
|
|
478
493
|
const start = Math.min(offset - 1, lines.length);
|
|
479
494
|
const slice = limit > 0 ? lines.slice(start, start + limit) : lines.slice(start);
|
|
480
495
|
const note = start + slice.length < lines.length || start > 0
|
|
481
|
-
? `\n[righe ${start + 1}-${start + slice.length} di ${lines.length}
|
|
496
|
+
? `\n[righe ${start + 1}-${start + slice.length} di ${lines.length}`
|
|
497
|
+
+ (start + slice.length < lines.length ? `; continua con read_file offset=${start + slice.length + 1} limit=${limit}` : "") + "]"
|
|
482
498
|
: "";
|
|
483
499
|
return paginate(slice.join("\n"), `file ${rel}`, ctx) + note + notaPresenza;
|
|
484
500
|
}
|
|
@@ -487,11 +503,11 @@ export const readTool = {
|
|
|
487
503
|
}
|
|
488
504
|
},
|
|
489
505
|
};
|
|
490
|
-
function acquireFileWrite(ctx, abs) {
|
|
506
|
+
async function acquireFileWrite(ctx, abs) {
|
|
491
507
|
const coordination = ctx.fileCoordination;
|
|
492
508
|
if (!coordination)
|
|
493
509
|
return "";
|
|
494
|
-
const outcome = coordination.hub.
|
|
510
|
+
const outcome = await coordination.hub.acquireAsync(abs, coordination.actor, ctx.signal);
|
|
495
511
|
if (!outcome.ok) {
|
|
496
512
|
coordination.emit?.({
|
|
497
513
|
phase: "blocked", path: abs, actor: coordination.actor,
|
|
@@ -519,10 +535,10 @@ function validateFileWrite(ctx, lease) {
|
|
|
519
535
|
return `conflitto file sopraggiunto: ${formatFileConflicts(conflicts)}. `
|
|
520
536
|
+ "La scrittura e' stata annullata senza sovrascrivere il lavoro concorrente.";
|
|
521
537
|
}
|
|
522
|
-
function releaseFileWrite(ctx, lease) {
|
|
538
|
+
async function releaseFileWrite(ctx, lease) {
|
|
523
539
|
if (typeof lease === "string" || !ctx.fileCoordination)
|
|
524
540
|
return;
|
|
525
|
-
ctx.fileCoordination.hub.
|
|
541
|
+
await ctx.fileCoordination.hub.releaseAsync(lease);
|
|
526
542
|
ctx.fileCoordination.emit?.({
|
|
527
543
|
phase: "released", path: lease.path, actor: lease.actor,
|
|
528
544
|
mode: "writing", others: [], at: Date.now(),
|
|
@@ -587,7 +603,7 @@ export const writeTool = {
|
|
|
587
603
|
}
|
|
588
604
|
const abs = await safePath(ctx.cwd, rel, ctx.fsRoots);
|
|
589
605
|
ctx.signal.throwIfAborted();
|
|
590
|
-
const lease = acquireFileWrite(ctx, abs);
|
|
606
|
+
const lease = await acquireFileWrite(ctx, abs);
|
|
591
607
|
if (typeof lease === "string" && lease)
|
|
592
608
|
return { output: lease, isError: true };
|
|
593
609
|
const append = input["append"] === true;
|
|
@@ -615,7 +631,7 @@ export const writeTool = {
|
|
|
615
631
|
return `${append ? "accodato" : "scritto"}: ${rel}${notaNul}`;
|
|
616
632
|
}
|
|
617
633
|
finally {
|
|
618
|
-
releaseFileWrite(ctx, lease);
|
|
634
|
+
await releaseFileWrite(ctx, lease);
|
|
619
635
|
}
|
|
620
636
|
}
|
|
621
637
|
catch (err) {
|
|
@@ -755,7 +771,7 @@ export const editTool = {
|
|
|
755
771
|
}
|
|
756
772
|
const abs = await safePath(ctx.cwd, rel, ctx.fsRoots);
|
|
757
773
|
ctx.signal.throwIfAborted();
|
|
758
|
-
const lease = acquireFileWrite(ctx, abs);
|
|
774
|
+
const lease = await acquireFileWrite(ctx, abs);
|
|
759
775
|
if (typeof lease === "string" && lease)
|
|
760
776
|
return { output: lease, isError: true };
|
|
761
777
|
try {
|
|
@@ -793,7 +809,7 @@ export const editTool = {
|
|
|
793
809
|
return `modificato: ${rel}${hint}${notaNul}`;
|
|
794
810
|
}
|
|
795
811
|
finally {
|
|
796
|
-
releaseFileWrite(ctx, lease);
|
|
812
|
+
await releaseFileWrite(ctx, lease);
|
|
797
813
|
}
|
|
798
814
|
}
|
|
799
815
|
catch (err) {
|
|
@@ -862,6 +878,7 @@ export const recallTool = {
|
|
|
862
878
|
properties: {
|
|
863
879
|
query: { type: "string", description: "Testo da cercare nelle attivita archiviate" },
|
|
864
880
|
rooms: { type: "array", items: { type: "string" }, description: "Id attivita da recuperare integralmente" },
|
|
881
|
+
attachments: { type: "boolean", description: "Con rooms: recupera le immagini originali del checkpoint come input visivo, on demand. Senza questa opzione restituisce solo l'indice." },
|
|
865
882
|
files: { type: "array", items: { type: "string" }, description: "Path: restituisce le attivita che hanno toccato quei file (traversata del grafo)" },
|
|
866
883
|
expand: { type: "boolean", description: "Se true, apre gruppi e liste fino alle singole attivita" },
|
|
867
884
|
domains: { type: "array", items: { type: "string" }, description: "Domini memoria: rooms, plan, notes, skills, vision, assets, decisions, contracts, sessions (conversazioni passate)" },
|
|
@@ -893,6 +910,10 @@ export const recallTool = {
|
|
|
893
910
|
const found = wantsRooms && mem.count() ? input["expand"] === true ? mem.expandRooms(rooms) : mem.byRooms(rooms) : [];
|
|
894
911
|
if (!found.length)
|
|
895
912
|
return `nessuna attivita trovata per: ${rooms.join(", ")}`;
|
|
913
|
+
if (input["attachments"] === true) {
|
|
914
|
+
const media = mem.attachmentMedia(rooms);
|
|
915
|
+
return { output: found.map(r => r.body).join('\n\n---\n\n') + `\nAllegati visivi recuperati: ${media.length}.` + (media.length ? '' : ' Originali non disponibili; non dedurre dettagli visivi dal riepilogo.'), media };
|
|
916
|
+
}
|
|
896
917
|
return paginate(found.map((r) => r.body).join("\n\n---\n\n"), "attivita", ctx);
|
|
897
918
|
}
|
|
898
919
|
// TRAVERSATA DEL GRAFO: "chi ha gia' messo le mani su questo file?".
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare const PROTOCOL_TOOLS: ReadonlySet<string>;
|
|
2
2
|
export declare const NATIVE_CALL_TOOLS: ReadonlySet<string>;
|
|
3
|
+
/** Desktop consent option; hosts and Fusion recognize the consent question by it. */
|
|
4
|
+
export declare const COMPUTER_USE_CONSENT = "Consenti accesso al desktop";
|
|
3
5
|
export declare const BUILTIN_CAPABILITIES: Readonly<Record<string, readonly string[]>>;
|
|
4
6
|
export declare const BUILTIN_CONTINUATIONS: Readonly<Record<string, readonly string[]>>;
|
|
5
|
-
export declare const COMPACT_TOOL_GUIDANCE = "Tool protocol: resolve and execute\nAll operation names mentioned elsewhere (bash, read_file, vascend_plan, ask_user, etc.)\nare internal tools. Use execute to call them; only tools in the native list can be\ncalled at top level. Interpret the user's language yourself and emit stable capability\nIDs; never translate file paths, search patterns or user data to discover a tool.\nresolve({capabilities:[\"process.run\",\"files.edit\"]}) returns exact tools, full input\ncontracts, continuations and a catalog revision. Reuse that revision and the contracts\nuntil stale_contract; do not resolve again for tools you already know.\nFamilies: files, process, output, plan, memory, user, workspace, code, web, image,\nskills, team, branches, market. resolve({namespace:\"files\"}) lists that family's\noperations; resolve({namespace:\"tools\"}) lists all installed tools in pages, including\nextensions. resolve({names:[\"read_file\",\"output_page\"]}) gets known names in one call.\nCommon capabilities: files.read/write/edit/search/find/list, process.run/observe,\nplan.create/update/inspect/note, user.ask, memory.recall, output.read.\nFor one operation: execute({mode:\"call\",revision,tool:\"read_file\",args:{path:\"src/a.ts\"}}).\nPrefer call mode for shell scripts and file edits. Use write_file/edit_file for UTF-8\nsource changes. In Python always specify encoding=\"utf-8\" when reading/writing text.\nFor sequences, pass payloads in data: execute({mode:\"program\",revision,data:{path:\"src/a.ts\"},code:\"return await tools.read_file({path:tools.$data.path});\"}).\nKeep scripts, file content and multiline text in data, never inside JavaScript\nstring literals; tools.$data contains this invocation's data, default {}.\nPrograms have tools, state, console and await; state persists per session, return emits\nthe result. Tools return text; tools.$result(name,args) also returns structuredContent,\ncontent and isError. Keep intermediate data in state and return only useful evidence.\nAwait dependent writes and approvals sequentially; use bounded Promise.allSettled for\nindependent work and inspect every outcome. Do not repeat a completed action on error.\nPrefer process.run with bash for rg, rg --files and git.
|
|
7
|
+
export declare const COMPACT_TOOL_GUIDANCE = "Tool protocol: resolve and execute\nAll operation names mentioned elsewhere (bash, read_file, vascend_plan, ask_user, etc.)\nare internal tools. Use execute to call them; only tools in the native list can be\ncalled at top level. Interpret the user's language yourself and emit stable capability\nIDs; never translate file paths, search patterns or user data to discover a tool.\nresolve({capabilities:[\"process.run\",\"files.edit\"]}) returns exact tools, full input\ncontracts, continuations and a catalog revision. Reuse that revision and the contracts\nuntil stale_contract; do not resolve again for tools you already know.\nFamilies: files, process, output, plan, memory, user, workspace, code, web, image,\nskills, team, branches, market. resolve({namespace:\"files\"}) lists that family's\noperations; resolve({namespace:\"tools\"}) lists all installed tools in pages, including\nextensions. resolve({names:[\"read_file\",\"output_page\"]}) gets known names in one call.\nCommon capabilities: files.read/write/edit/search/find/list, process.run/observe,\nplan.create/update/inspect/note, user.ask, memory.recall, output.read.\nFor one operation: execute({mode:\"call\",revision,tool:\"read_file\",args:{path:\"src/a.ts\"}}).\nPrefer call mode for shell scripts and file edits. Use write_file/edit_file for UTF-8\nsource changes. In Python always specify encoding=\"utf-8\" when reading/writing text.\nFor sequences, pass payloads in data: execute({mode:\"program\",revision,data:{path:\"src/a.ts\"},code:\"return await tools.read_file({path:tools.$data.path});\"}).\nKeep scripts, file content and multiline text in data, never inside JavaScript\nstring literals; tools.$data contains this invocation's data, default {}.\nPrograms have tools, state, console and await; state persists per session, return emits\nthe result. Tools return text; tools.$result(name,args) also returns structuredContent,\ncontent and isError. Keep intermediate data in state and return only useful evidence.\nAwait dependent writes and approvals sequentially; use bounded Promise.allSettled for\nindependent work and inspect every outcome. Do not repeat a completed action on error.\nPrefer process.run with bash for rg, rg --files and git. Collect a background result\nwith one bash_output call through execute: it waits locally for the final exit status.\nUse wait=false for persistent server snapshots, not repeated polling. Unknown or unavailable\ncapabilities require catalog inspection or independent work, never invented tool names.\nThe revision checks catalog freshness, not permission. All existing permission gates\nstill apply. Tools marked native must be called directly, including for images or\nincremental computer control when their contract requires it.";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Local operational metadata. These declarations never confer permissions.
|
|
2
2
|
export const PROTOCOL_TOOLS = new Set(["resolve", "execute"]);
|
|
3
3
|
export const NATIVE_CALL_TOOLS = new Set(["computer_control", "computer_batch"]);
|
|
4
|
+
/** Desktop consent option; hosts and Fusion recognize the consent question by it. */
|
|
5
|
+
export const COMPUTER_USE_CONSENT = "Consenti accesso al desktop";
|
|
4
6
|
export const BUILTIN_CAPABILITIES = {
|
|
5
7
|
read_file: ["files.read"], write_file: ["files.write"], edit_file: ["files.edit"],
|
|
6
8
|
grep: ["files.search"], glob: ["files.find"], list_dir: ["files.list"], file_activity: ["files.activity"],
|
|
@@ -47,8 +49,9 @@ the result. Tools return text; tools.$result(name,args) also returns structuredC
|
|
|
47
49
|
content and isError. Keep intermediate data in state and return only useful evidence.
|
|
48
50
|
Await dependent writes and approvals sequentially; use bounded Promise.allSettled for
|
|
49
51
|
independent work and inspect every outcome. Do not repeat a completed action on error.
|
|
50
|
-
Prefer process.run with bash for rg, rg --files and git.
|
|
51
|
-
with bash_output through execute
|
|
52
|
+
Prefer process.run with bash for rg, rg --files and git. Collect a background result
|
|
53
|
+
with one bash_output call through execute: it waits locally for the final exit status.
|
|
54
|
+
Use wait=false for persistent server snapshots, not repeated polling. Unknown or unavailable
|
|
52
55
|
capabilities require catalog inspection or independent work, never invented tool names.
|
|
53
56
|
The revision checks catalog freshness, not permission. All existing permission gates
|
|
54
57
|
still apply. Tools marked native must be called directly, including for images or
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { isAbsolute } from "node:path";
|
|
4
|
+
import { COMPUTER_USE_CONSENT } from "./capabilities.js";
|
|
4
5
|
import { captureComputerDesktop } from "./computer-capture.js";
|
|
5
6
|
import { normalizeMcpToolResult } from "../mcp/protocol.js";
|
|
6
7
|
import { posixComputerTools } from "./computer-posix.js";
|
|
7
8
|
const require = createRequire(import.meta.url);
|
|
8
|
-
const CONSENT =
|
|
9
|
+
const CONSENT = COMPUTER_USE_CONSENT;
|
|
9
10
|
const unavailable = (output) => ({ output, isError: true });
|
|
10
11
|
/** Standalone desktop tools. Loading definitions does not access the desktop. */
|
|
11
12
|
export function registerComputerUse(registry, env, options = {}) {
|
package/dist/tools/pagination.js
CHANGED
|
@@ -4,7 +4,7 @@ import { ToolOutputStore } from "../core/tool-result-store.js";
|
|
|
4
4
|
// mostra la prima pagina e si conserva il resto, recuperabile dal modello con il
|
|
5
5
|
// tool output_page quando lo ritiene utile. Niente perdita di informazione.
|
|
6
6
|
// Store di processo (in-memory), con eviction per non accumulare.
|
|
7
|
-
const PAGE_CHARS =
|
|
7
|
+
const PAGE_CHARS = 8_000; // circa 2k token; dettagli ulteriori solo su richiesta
|
|
8
8
|
const MAX_STORED = 5_000_000; // tetto per entry (5MB): oltre, si tronca a monte
|
|
9
9
|
const MAX_ENTRIES = 24; // quante uscite lunghe tenere
|
|
10
10
|
class PageStore {
|