@alisio/core 0.1.0-alpha.8 → 0.1.0
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/README.md +52 -7
- package/dist/agents/active.d.ts +99 -0
- package/dist/agents/active.js +218 -0
- package/dist/agents/capabilities.d.ts +26 -0
- package/dist/agents/capabilities.js +120 -0
- package/dist/agents/create-agent-skill.d.ts +11 -0
- package/dist/agents/create-agent-skill.js +60 -0
- package/dist/agents/definitions.d.ts +88 -0
- package/dist/agents/definitions.js +404 -0
- package/dist/agents/draft.d.ts +41 -0
- package/dist/agents/draft.js +133 -0
- package/dist/agents/service.d.ts +57 -0
- package/dist/agents/service.js +86 -0
- package/dist/agents/templates.d.ts +8 -0
- package/dist/agents/templates.js +102 -0
- package/dist/analysis/capabilities.d.ts +48 -0
- package/dist/analysis/capabilities.js +90 -0
- package/dist/analysis/data/csv.d.ts +46 -0
- package/dist/analysis/data/csv.js +240 -0
- package/dist/analysis/data/datasets.d.ts +132 -0
- package/dist/analysis/data/datasets.js +441 -0
- package/dist/analysis/data/describe.d.ts +27 -0
- package/dist/analysis/data/describe.js +103 -0
- package/dist/analysis/data/engine-client.d.ts +58 -0
- package/dist/analysis/data/engine-client.js +304 -0
- package/dist/analysis/data/engine-entry.d.ts +1 -0
- package/dist/analysis/data/engine-entry.js +59 -0
- package/dist/analysis/data/engine-source.d.ts +4 -0
- package/dist/analysis/data/engine-source.js +6 -0
- package/dist/analysis/data/engine-types.d.ts +86 -0
- package/dist/analysis/data/engine-types.js +7 -0
- package/dist/analysis/data/infer.d.ts +42 -0
- package/dist/analysis/data/infer.js +118 -0
- package/dist/analysis/data/ingest-worker.d.ts +17 -0
- package/dist/analysis/data/ingest-worker.js +365 -0
- package/dist/analysis/data/json.d.ts +19 -0
- package/dist/analysis/data/json.js +44 -0
- package/dist/analysis/data/query-worker.d.ts +12 -0
- package/dist/analysis/data/query-worker.js +75 -0
- package/dist/analysis/data/rows.d.ts +39 -0
- package/dist/analysis/data/rows.js +120 -0
- package/dist/analysis/data/sql-guard.d.ts +20 -0
- package/dist/analysis/data/sql-guard.js +129 -0
- package/dist/analysis/data/stats.d.ts +18 -0
- package/dist/analysis/data/stats.js +77 -0
- package/dist/analysis/install-hints.d.ts +33 -0
- package/dist/analysis/install-hints.js +144 -0
- package/dist/analysis/janitor.d.ts +60 -0
- package/dist/analysis/janitor.js +264 -0
- package/dist/analysis/jobs.d.ts +94 -0
- package/dist/analysis/jobs.js +165 -0
- package/dist/analysis/oci.d.ts +129 -0
- package/dist/analysis/oci.js +330 -0
- package/dist/analysis/python/sources.d.ts +2 -0
- package/dist/analysis/python/sources.js +10 -0
- package/dist/analysis/requirements.d.ts +32 -0
- package/dist/analysis/requirements.js +73 -0
- package/dist/analysis/rerun.d.ts +40 -0
- package/dist/analysis/rerun.js +136 -0
- package/dist/analysis/runtime-manager.d.ts +146 -0
- package/dist/analysis/runtime-manager.js +472 -0
- package/dist/analysis/status.d.ts +21 -0
- package/dist/analysis/status.js +52 -0
- package/dist/application.d.ts +118 -3
- package/dist/application.js +510 -19
- package/dist/artifacts/kinds.d.ts +35 -0
- package/dist/artifacts/kinds.js +177 -0
- package/dist/artifacts/publisher.d.ts +7 -0
- package/dist/artifacts/publisher.js +29 -0
- package/dist/artifacts/store.d.ts +119 -0
- package/dist/artifacts/store.js +581 -0
- package/dist/background/janitor.d.ts +22 -0
- package/dist/background/janitor.js +62 -0
- package/dist/background/mirror.d.ts +14 -0
- package/dist/background/mirror.js +41 -0
- package/dist/background/notify.d.ts +58 -0
- package/dist/background/notify.js +172 -0
- package/dist/background/output.d.ts +46 -0
- package/dist/background/output.js +179 -0
- package/dist/background/service.d.ts +137 -0
- package/dist/background/service.js +410 -0
- package/dist/background/store.d.ts +103 -0
- package/dist/background/store.js +195 -0
- package/dist/changelog/data.d.ts +6 -0
- package/dist/changelog/data.js +293 -0
- package/dist/changelog/index.d.ts +5 -0
- package/dist/changelog/index.js +7 -0
- package/dist/changelog/parse.d.ts +53 -0
- package/dist/changelog/parse.js +160 -0
- package/dist/commands/builtins.d.ts +10 -0
- package/dist/commands/builtins.js +161 -0
- package/dist/commands/catalog.d.ts +86 -0
- package/dist/commands/catalog.js +304 -0
- package/dist/config.d.ts +252 -5
- package/dist/config.js +514 -13
- package/dist/core/compaction.js +13 -2
- package/dist/core/contracts.d.ts +180 -3
- package/dist/core/opt-in.d.ts +12 -0
- package/dist/core/opt-in.js +12 -0
- package/dist/core/output-limit.d.ts +34 -0
- package/dist/core/output-limit.js +39 -0
- package/dist/core/run-stats.d.ts +16 -0
- package/dist/core/run-stats.js +8 -0
- package/dist/core/runner.d.ts +152 -4
- package/dist/core/runner.js +792 -138
- package/dist/core/timeout.d.ts +15 -0
- package/dist/core/timeout.js +61 -0
- package/dist/core/truncation.d.ts +30 -0
- package/dist/core/truncation.js +83 -0
- package/dist/goal/blockers.d.ts +45 -0
- package/dist/goal/blockers.js +51 -0
- package/dist/goal/budget.d.ts +24 -0
- package/dist/goal/budget.js +53 -0
- package/dist/goal/command.d.ts +36 -0
- package/dist/goal/command.js +98 -0
- package/dist/goal/format.d.ts +19 -0
- package/dist/goal/format.js +102 -0
- package/dist/goal/host.d.ts +29 -0
- package/dist/goal/host.js +42 -0
- package/dist/goal/index.d.ts +9 -0
- package/dist/goal/index.js +9 -0
- package/dist/goal/machine.d.ts +186 -0
- package/dist/goal/machine.js +344 -0
- package/dist/goal/prompts.d.ts +10 -0
- package/dist/goal/prompts.js +75 -0
- package/dist/goal/service.d.ts +113 -0
- package/dist/goal/service.js +273 -0
- package/dist/goal/store.d.ts +59 -0
- package/dist/goal/store.js +184 -0
- package/dist/index.d.ts +51 -6
- package/dist/index.js +49 -4
- package/dist/mcp/connector.js +38 -6
- package/dist/mcp/rich.d.ts +41 -0
- package/dist/mcp/rich.js +362 -0
- package/dist/permissions/modes.d.ts +72 -0
- package/dist/permissions/modes.js +98 -0
- package/dist/plan/exit-plan.d.ts +25 -0
- package/dist/plan/exit-plan.js +130 -0
- package/dist/plan/state.d.ts +102 -0
- package/dist/plan/state.js +165 -0
- package/dist/plugins/host.d.ts +39 -1
- package/dist/plugins/host.js +150 -9
- package/dist/providers/settings.d.ts +15 -0
- package/dist/providers/settings.js +38 -0
- package/dist/reload.d.ts +75 -0
- package/dist/reload.js +204 -0
- package/dist/resources/context.d.ts +5 -0
- package/dist/resources/context.js +13 -1
- package/dist/runtime/access.d.ts +62 -0
- package/dist/runtime/access.js +115 -0
- package/dist/runtime/blobs.d.ts +51 -0
- package/dist/runtime/blobs.js +177 -0
- package/dist/runtime/diff.d.ts +23 -0
- package/dist/runtime/diff.js +154 -0
- package/dist/runtime/ids.d.ts +8 -0
- package/dist/runtime/ids.js +32 -0
- package/dist/runtime/paths.d.ts +11 -0
- package/dist/runtime/paths.js +17 -1
- package/dist/runtime/process.d.ts +22 -0
- package/dist/runtime/process.js +100 -15
- package/dist/runtime/sqlite.d.ts +2 -0
- package/dist/runtime/sqlite.js +18 -0
- package/dist/runtime/store.d.ts +91 -3
- package/dist/runtime/store.js +465 -11
- package/dist/runtime/zip.d.ts +24 -0
- package/dist/runtime/zip.js +126 -0
- package/dist/sessions/children.js +17 -1
- package/dist/sessions/side-questions.d.ts +57 -0
- package/dist/sessions/side-questions.js +161 -0
- package/dist/startup/screen.js +6 -5
- package/dist/tools/analysis.d.ts +37 -0
- package/dist/tools/analysis.js +573 -0
- package/dist/tools/artifacts.d.ts +14 -0
- package/dist/tools/artifacts.js +143 -0
- package/dist/tools/background.d.ts +7 -0
- package/dist/tools/background.js +165 -0
- package/dist/tools/data.d.ts +7 -0
- package/dist/tools/data.js +160 -0
- package/dist/tools/execute.d.ts +5 -0
- package/dist/tools/execute.js +15 -3
- package/dist/tools/goal.d.ts +19 -0
- package/dist/tools/goal.js +126 -0
- package/dist/tools/search.d.ts +17 -3
- package/dist/tools/search.js +153 -0
- package/dist/tools/standard.d.ts +4 -1
- package/dist/tools/standard.js +99 -18
- package/dist/version.d.ts +5 -3
- package/dist/version.js +35 -6
- package/package.json +2 -2
|
@@ -87,6 +87,7 @@ export class ChildSessions {
|
|
|
87
87
|
...(spec.maxTurns ? { maxTurns: spec.maxTurns } : {}),
|
|
88
88
|
...(spec.timeoutMs ? { timeoutMs: spec.timeoutMs } : {}),
|
|
89
89
|
...(spec.maxTokens ? { maxTokens: spec.maxTokens } : {}),
|
|
90
|
+
...(spec.maxOutputTokens ? { maxOutputTokens: spec.maxOutputTokens } : {}),
|
|
90
91
|
};
|
|
91
92
|
const child = this.o.store.createChild({
|
|
92
93
|
...(spec.id ? { id: spec.id } : {}),
|
|
@@ -147,6 +148,10 @@ export class ChildSessions {
|
|
|
147
148
|
write: caps.write,
|
|
148
149
|
process: caps.process,
|
|
149
150
|
external: root.external && !caps.readOnly,
|
|
151
|
+
// --allow-analysis carries to children whose process permission is not narrowed.
|
|
152
|
+
...(root.analysis && !caps.readOnly && (spec.permission?.process ?? "allow") === "allow"
|
|
153
|
+
? { analysis: true }
|
|
154
|
+
: {}),
|
|
150
155
|
},
|
|
151
156
|
approvals: caps.approvals,
|
|
152
157
|
label: this.label(id),
|
|
@@ -154,12 +159,23 @@ export class ChildSessions {
|
|
|
154
159
|
context: this.o.contextFor(session.workspace),
|
|
155
160
|
...(spec.maxTurns ? { maxTurns: spec.maxTurns } : {}),
|
|
156
161
|
...(spec.maxTokens ? { maxTokens: spec.maxTokens } : {}),
|
|
162
|
+
...(spec.maxOutputTokens ? { maxOutputTokens: spec.maxOutputTokens } : {}),
|
|
157
163
|
...(spec.timeoutMs ? { timeoutMs: spec.timeoutMs } : {}),
|
|
158
164
|
});
|
|
159
165
|
usage.input += result.usage.input;
|
|
160
166
|
usage.output += result.usage.output;
|
|
167
|
+
// A child that hit its turn limit still produced a usable partial result: it completes
|
|
168
|
+
// with a turnsExceeded marker instead of failing, so orchestration treats the text as
|
|
169
|
+
// partial output. state "failed" stays reserved for real errors/aborts.
|
|
170
|
+
const turnsExceeded = result.status === "turns-exceeded";
|
|
161
171
|
this.o.store.updateSession(id, { status: "completed", usage });
|
|
162
|
-
return {
|
|
172
|
+
return {
|
|
173
|
+
id,
|
|
174
|
+
status: "completed",
|
|
175
|
+
text: result.text,
|
|
176
|
+
usage,
|
|
177
|
+
...(turnsExceeded ? { turnsExceeded: true } : {}),
|
|
178
|
+
};
|
|
163
179
|
}
|
|
164
180
|
catch (error) {
|
|
165
181
|
const aborted = this.cancelled.has(id) || signals.some((s) => s.aborted);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/btw` side questions: a question about a session answered by one separate, tool-less model
|
|
3
|
+
* call that sees the session's active history, without becoming part of the conversation.
|
|
4
|
+
*
|
|
5
|
+
* Guarantees: nothing is written to `messages`, `tool_calls`, `runs`, the durable `events` or the
|
|
6
|
+
* session usage, and the session lock is never claimed, so a side question may run while a run
|
|
7
|
+
* is active (it has its own abort signal). The only thing persisted is this service's own
|
|
8
|
+
* history, in `plugin_state` under the reserved namespace `core:btw` (plugin ids cannot contain
|
|
9
|
+
* `:`, so no plugin can read or overwrite it), keyed by session id and capped to the newest
|
|
10
|
+
* `SIDE_QUESTION_HISTORY_LIMIT` entries.
|
|
11
|
+
*/
|
|
12
|
+
import type { Message, SideQuestionEntry } from "@alisio/sdk";
|
|
13
|
+
import type { AgentRunner } from "../core/runner.ts";
|
|
14
|
+
export type { SideQuestionEntry };
|
|
15
|
+
/** `plugin_state.plugin` value of the side-question history (never a valid plugin id). */
|
|
16
|
+
export declare const SIDE_QUESTIONS_NAMESPACE = "core:btw";
|
|
17
|
+
export declare const SIDE_QUESTION_HISTORY_LIMIT = 20;
|
|
18
|
+
export declare const SIDE_QUESTION_MAX_CHARS = 4000;
|
|
19
|
+
/** The line every surface prints for `/btw` without a question and without any history. */
|
|
20
|
+
export declare const SIDE_QUESTION_USAGE = "Usage: /btw <question>";
|
|
21
|
+
export declare const SIDE_QUESTION_DESCRIPTION = "Ask a side question about the current session without adding to the conversation.";
|
|
22
|
+
export declare const SIDE_QUESTION_INSTRUCTIONS: string;
|
|
23
|
+
interface StateStore {
|
|
24
|
+
getState(plugin: string, key: string): unknown;
|
|
25
|
+
setState(plugin: string, key: string, value: unknown): void;
|
|
26
|
+
}
|
|
27
|
+
export interface SideQuestionsOptions {
|
|
28
|
+
runner: Pick<AgentRunner, "sideContext">;
|
|
29
|
+
/** Where the history lives (the SQLite store's `plugin_state`). */
|
|
30
|
+
state: StateStore;
|
|
31
|
+
now?: () => number;
|
|
32
|
+
id?: () => string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The transcript lines for the side call, newest kept first: when the whole history does not fit
|
|
36
|
+
* `budget` characters, the oldest messages are dropped (and counted in a leading marker). The
|
|
37
|
+
* newest message alone is clipped from its start if it is still too large.
|
|
38
|
+
*/
|
|
39
|
+
export declare function sideTranscript(messages: Message[], budget: number): string;
|
|
40
|
+
export declare class SideQuestions {
|
|
41
|
+
private readonly options;
|
|
42
|
+
private readonly now;
|
|
43
|
+
private readonly newId;
|
|
44
|
+
constructor(options: SideQuestionsOptions);
|
|
45
|
+
/** The session's side questions, oldest first (newest last). */
|
|
46
|
+
history(sessionId: string): SideQuestionEntry[];
|
|
47
|
+
/**
|
|
48
|
+
* Answers `question` about the session with one tool-less call of the session's model and
|
|
49
|
+
* records it in the history. Throws on an empty or oversized question, on cancellation (the
|
|
50
|
+
* signal's reason) and on provider failures (nothing is recorded then).
|
|
51
|
+
*/
|
|
52
|
+
ask(sessionId: string, question: string, options?: {
|
|
53
|
+
signal?: AbortSignal;
|
|
54
|
+
}): Promise<SideQuestionEntry>;
|
|
55
|
+
}
|
|
56
|
+
/** Plain Markdown for one entry (`position` is 1-based): readline, API callers and `/btw`. */
|
|
57
|
+
export declare function formatSideQuestion(entry: SideQuestionEntry, position: number, total: number): string;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { serializeForSummary } from "../core/compaction.js";
|
|
2
|
+
/** `plugin_state.plugin` value of the side-question history (never a valid plugin id). */
|
|
3
|
+
export const SIDE_QUESTIONS_NAMESPACE = "core:btw";
|
|
4
|
+
export const SIDE_QUESTION_HISTORY_LIMIT = 20;
|
|
5
|
+
export const SIDE_QUESTION_MAX_CHARS = 4_000;
|
|
6
|
+
/** The line every surface prints for `/btw` without a question and without any history. */
|
|
7
|
+
export const SIDE_QUESTION_USAGE = "Usage: /btw <question>";
|
|
8
|
+
export const SIDE_QUESTION_DESCRIPTION = "Ask a side question about the current session without adding to the conversation.";
|
|
9
|
+
/** Per-message clip of the transcript the side call sees (as in compaction summaries). */
|
|
10
|
+
const MAX_ITEM_CHARS = 4_000;
|
|
11
|
+
export const SIDE_QUESTION_INSTRUCTIONS = [
|
|
12
|
+
"The user is asking a quick side question (/btw) about the session transcript below.",
|
|
13
|
+
"It is NOT part of the conversation: answer it directly and concisely from the transcript and",
|
|
14
|
+
"your general knowledge. You have no tools in this reply, so do not take or promise any",
|
|
15
|
+
"action, do not continue the task and do not call tools; if the transcript does not contain",
|
|
16
|
+
"the answer, say so briefly.",
|
|
17
|
+
].join(" ");
|
|
18
|
+
/**
|
|
19
|
+
* The transcript lines for the side call, newest kept first: when the whole history does not fit
|
|
20
|
+
* `budget` characters, the oldest messages are dropped (and counted in a leading marker). The
|
|
21
|
+
* newest message alone is clipped from its start if it is still too large.
|
|
22
|
+
*/
|
|
23
|
+
export function sideTranscript(messages, budget) {
|
|
24
|
+
const lines = [];
|
|
25
|
+
let used = 0;
|
|
26
|
+
let omitted = 0;
|
|
27
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
28
|
+
const message = messages[i];
|
|
29
|
+
const text = serializeForSummary([message], MAX_ITEM_CHARS);
|
|
30
|
+
if (used + text.length + 1 > budget) {
|
|
31
|
+
if (lines.length)
|
|
32
|
+
omitted = i + 1;
|
|
33
|
+
else {
|
|
34
|
+
// Even the newest message alone is too large: keep its end (the most recent part).
|
|
35
|
+
lines.push(text.slice(Math.max(0, text.length - budget)));
|
|
36
|
+
omitted = i;
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
lines.unshift(text);
|
|
41
|
+
used += text.length + 1;
|
|
42
|
+
}
|
|
43
|
+
if (omitted > 0)
|
|
44
|
+
lines.unshift(`[${omitted} earlier messages omitted to fit the context budget]`);
|
|
45
|
+
return lines.join("\n");
|
|
46
|
+
}
|
|
47
|
+
const isEntry = (value) => !!value &&
|
|
48
|
+
typeof value === "object" &&
|
|
49
|
+
typeof value.id === "string" &&
|
|
50
|
+
typeof value.question === "string" &&
|
|
51
|
+
typeof value.answer === "string";
|
|
52
|
+
export class SideQuestions {
|
|
53
|
+
options;
|
|
54
|
+
now;
|
|
55
|
+
newId;
|
|
56
|
+
constructor(options) {
|
|
57
|
+
this.options = options;
|
|
58
|
+
this.now = options.now ?? Date.now;
|
|
59
|
+
this.newId = options.id ?? (() => crypto.randomUUID());
|
|
60
|
+
}
|
|
61
|
+
/** The session's side questions, oldest first (newest last). */
|
|
62
|
+
history(sessionId) {
|
|
63
|
+
let stored;
|
|
64
|
+
try {
|
|
65
|
+
stored = this.options.state.getState(SIDE_QUESTIONS_NAMESPACE, sessionId);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
return Array.isArray(stored) ? stored.filter(isEntry) : [];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Answers `question` about the session with one tool-less call of the session's model and
|
|
74
|
+
* records it in the history. Throws on an empty or oversized question, on cancellation (the
|
|
75
|
+
* signal's reason) and on provider failures (nothing is recorded then).
|
|
76
|
+
*/
|
|
77
|
+
async ask(sessionId, question, options = {}) {
|
|
78
|
+
const text = question.trim();
|
|
79
|
+
if (!text)
|
|
80
|
+
throw new Error(SIDE_QUESTION_USAGE);
|
|
81
|
+
if (text.length > SIDE_QUESTION_MAX_CHARS)
|
|
82
|
+
throw new Error(`Side questions are limited to ${SIDE_QUESTION_MAX_CHARS} characters`);
|
|
83
|
+
const side = await this.options.runner.sideContext(sessionId);
|
|
84
|
+
const signal = AbortSignal.any([
|
|
85
|
+
AbortSignal.timeout(side.timeoutMs),
|
|
86
|
+
...(options.signal ? [options.signal] : []),
|
|
87
|
+
]);
|
|
88
|
+
signal.throwIfAborted();
|
|
89
|
+
const instructions = `${side.instructions}\n\n${SIDE_QUESTION_INSTRUCTIONS}`;
|
|
90
|
+
// The request must fit both the char budget and (when known) the model window, leaving room
|
|
91
|
+
// for the answer; ~3 chars per token keeps a conservative margin over the usual ~4.
|
|
92
|
+
const windowChars = side.contextWindow
|
|
93
|
+
? Math.max(0, side.contextWindow - side.maxOutputTokens) * 3
|
|
94
|
+
: Number.POSITIVE_INFINITY;
|
|
95
|
+
const budget = Math.max(2_000, Math.min(side.maxContextChars, windowChars) - instructions.length - text.length - 200);
|
|
96
|
+
const transcript = sideTranscript(side.messages, budget);
|
|
97
|
+
const prompt = transcript
|
|
98
|
+
? `<transcript>\n${transcript}\n</transcript>\n\nSide question: ${text}`
|
|
99
|
+
: `(The session has no messages yet.)\n\nSide question: ${text}`;
|
|
100
|
+
let answer = "";
|
|
101
|
+
let completed = false;
|
|
102
|
+
let truncated = false;
|
|
103
|
+
let usage = { input: 0, output: 0 };
|
|
104
|
+
try {
|
|
105
|
+
for await (const event of side.provider.stream({
|
|
106
|
+
instructions,
|
|
107
|
+
messages: [{ role: "user", text: prompt }],
|
|
108
|
+
tools: [],
|
|
109
|
+
maxOutputTokens: side.maxOutputTokens,
|
|
110
|
+
signal,
|
|
111
|
+
model: side.model,
|
|
112
|
+
sessionId,
|
|
113
|
+
...(side.reasoningEffort ? { reasoningEffort: side.reasoningEffort } : {}),
|
|
114
|
+
})) {
|
|
115
|
+
signal.throwIfAborted();
|
|
116
|
+
if (event.type === "text_delta")
|
|
117
|
+
answer += event.delta;
|
|
118
|
+
else if (event.type === "completed") {
|
|
119
|
+
completed = true;
|
|
120
|
+
truncated = event.message.truncated === true;
|
|
121
|
+
answer = event.message.text || answer;
|
|
122
|
+
if (event.usage)
|
|
123
|
+
usage = { input: event.usage.input, output: event.usage.output };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (signal.aborted)
|
|
129
|
+
throw signal.reason ?? error;
|
|
130
|
+
throw new Error(`Side question failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
131
|
+
}
|
|
132
|
+
signal.throwIfAborted();
|
|
133
|
+
if (!completed)
|
|
134
|
+
throw new Error("Side question failed: the provider did not complete");
|
|
135
|
+
answer = answer.trim();
|
|
136
|
+
if (!answer)
|
|
137
|
+
throw new Error("Side question failed: the model returned an empty answer");
|
|
138
|
+
const entry = {
|
|
139
|
+
id: this.newId(),
|
|
140
|
+
question: text,
|
|
141
|
+
answer,
|
|
142
|
+
model: side.model,
|
|
143
|
+
usage,
|
|
144
|
+
createdAt: this.now(),
|
|
145
|
+
...(truncated ? { truncated: true } : {}),
|
|
146
|
+
};
|
|
147
|
+
const next = [...this.history(sessionId), entry].slice(-SIDE_QUESTION_HISTORY_LIMIT);
|
|
148
|
+
this.options.state.setState(SIDE_QUESTIONS_NAMESPACE, sessionId, next);
|
|
149
|
+
return entry;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Plain Markdown for one entry (`position` is 1-based): readline, API callers and `/btw`. */
|
|
153
|
+
export function formatSideQuestion(entry, position, total) {
|
|
154
|
+
return [
|
|
155
|
+
`**btw ${position}/${total}** · ${entry.question.replace(/\s+/g, " ")}`,
|
|
156
|
+
"",
|
|
157
|
+
entry.answer,
|
|
158
|
+
"",
|
|
159
|
+
`_${entry.model} · ${entry.usage.input} in · ${entry.usage.output} out tokens${entry.truncated ? " · truncated" : ""}_`,
|
|
160
|
+
].join("\n");
|
|
161
|
+
}
|
package/dist/startup/screen.js
CHANGED
|
@@ -42,6 +42,7 @@ export function welcomeSection(ctx) {
|
|
|
42
42
|
export function infoSection(ctx, width) {
|
|
43
43
|
const t = ctx.terminal;
|
|
44
44
|
const label = sgr(t.color, "2");
|
|
45
|
+
const pad = " ".repeat(2);
|
|
45
46
|
const rows = [];
|
|
46
47
|
if (ctx.model)
|
|
47
48
|
rows.push(["model", ctx.model]);
|
|
@@ -54,9 +55,9 @@ export function infoSection(ctx, width) {
|
|
|
54
55
|
rows.push(["plugins", plugins ? `${plugins} loaded` : "none"]);
|
|
55
56
|
const labelWidth = Math.min(12, Math.max(...rows.map(([l]) => l.length)) + 1);
|
|
56
57
|
return rows.map(([l, v]) => {
|
|
57
|
-
const room = Math.max(1, width - labelWidth - 1);
|
|
58
|
+
const room = Math.max(1, width - labelWidth - 1 - 4);
|
|
58
59
|
const value = l === "cwd" ? shortenPath(v, room) : truncate(v, room);
|
|
59
|
-
return `${label(padEnd(l, labelWidth))} ${value}`;
|
|
60
|
+
return `${pad}${label(padEnd(l, labelWidth))} ${value}${pad}`;
|
|
60
61
|
});
|
|
61
62
|
}
|
|
62
63
|
export function pluginsSection(ctx) {
|
|
@@ -72,12 +73,12 @@ export function pluginsSection(ctx) {
|
|
|
72
73
|
.filter((p) => !p.categories?.includes("model-provider"))
|
|
73
74
|
.map((p) => `${p.id}${p.builtin ? " (builtin)" : ""}`),
|
|
74
75
|
];
|
|
75
|
-
return [
|
|
76
|
+
return [` ${sgr(t.color, "2")("with")} ${names.join(", ")} `];
|
|
76
77
|
}
|
|
77
78
|
export function tipsSection(ctx) {
|
|
78
79
|
const t = ctx.terminal;
|
|
79
80
|
const bullet = sgr(t.color, "33")(glyph(t, "›", ">"));
|
|
80
|
-
return ctx.tips.map((tip) =>
|
|
81
|
+
return ctx.tips.map((tip) => ` ${bullet} Tip: ${tip} `);
|
|
81
82
|
}
|
|
82
83
|
export function mascotSection(ctx) {
|
|
83
84
|
return [ctx.mascot.render({ terminal: ctx.terminal, version: ctx.version })].flat();
|
|
@@ -110,7 +111,7 @@ export const DefaultStartupScreen = {
|
|
|
110
111
|
...pluginsSection(ctx),
|
|
111
112
|
];
|
|
112
113
|
const body = side ? composeSideBySide(mascot, info, columns) : [...mascot, ...info];
|
|
113
|
-
const rule = sgr(ctx.terminal.color, "2")(glyph(ctx.terminal, "─", "-").repeat(
|
|
114
|
+
const rule = sgr(ctx.terminal.color, "2")(glyph(ctx.terminal, "─", "-").repeat(columns - 2));
|
|
114
115
|
return [...body, "", ...tipsSection(ctx), rule].map((line) => truncate(line, columns));
|
|
115
116
|
},
|
|
116
117
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { DatasetService } from "../analysis/data/datasets.ts";
|
|
2
|
+
import type { AnalysisJobs } from "../analysis/jobs.ts";
|
|
3
|
+
import type { OciRuntime } from "../analysis/oci.ts";
|
|
4
|
+
import type { AnalysisRerun } from "../analysis/rerun.ts";
|
|
5
|
+
import { type AnalysisRuntimeManager } from "../analysis/runtime-manager.ts";
|
|
6
|
+
import { type ArtifactStore } from "../artifacts/store.ts";
|
|
7
|
+
import type { ToolRegistry } from "../core/registry.ts";
|
|
8
|
+
export declare const NOT_SANDBOXED = "Managed Python is not a sandbox: the script runs with your user permissions and can read your files and use the network.";
|
|
9
|
+
export interface AnalysisLimits {
|
|
10
|
+
timeoutMs: number;
|
|
11
|
+
maxLogBytes: number;
|
|
12
|
+
}
|
|
13
|
+
export interface AnalysisToolDeps {
|
|
14
|
+
store: ArtifactStore;
|
|
15
|
+
jobs: AnalysisJobs;
|
|
16
|
+
/** Discovery (`interpreter`) and, for the optional extras, `hasExtras` / `installExtras`. */
|
|
17
|
+
runtime: Pick<AnalysisRuntimeManager, "interpreter"> & Partial<Pick<AnalysisRuntimeManager, "hasExtras" | "installExtras">>;
|
|
18
|
+
/** Container mode (`analysis.runtime: "oci"`), read when each call starts. */
|
|
19
|
+
oci?: {
|
|
20
|
+
mode(): "managed" | "oci";
|
|
21
|
+
runtime(): OciRuntime;
|
|
22
|
+
};
|
|
23
|
+
/** Rerun of an earlier execution (`rerunOf`). */
|
|
24
|
+
rerun?: AnalysisRerun;
|
|
25
|
+
/** Datasets of the session: `inputs: [{ datasetId }]` copies the dataset's SQLite file. */
|
|
26
|
+
datasets?: DatasetService;
|
|
27
|
+
rootOf: (sessionId: string) => string;
|
|
28
|
+
limits: AnalysisLimits;
|
|
29
|
+
/** Startup facts for the description (stat only; no process was launched). */
|
|
30
|
+
startup: {
|
|
31
|
+
candidates: boolean;
|
|
32
|
+
extras: string[];
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** `48 KB`, `1.2 MB`. */
|
|
36
|
+
export declare function formatBytes(bytes: number): string;
|
|
37
|
+
export declare function registerAnalysisTools(registry: ToolRegistry, deps: AnalysisToolDeps): void;
|