@bubblebrain-ai/bubble 0.0.34 → 0.0.36
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 +27 -7
- package/dist/agent/abort-errors.d.ts +2 -2
- package/dist/agent/budget-ledger.d.ts +4 -45
- package/dist/agent/budget-ledger.js +5 -75
- package/dist/agent/categories.d.ts +66 -2
- package/dist/agent/categories.js +120 -19
- package/dist/agent/child-runner.d.ts +1 -3
- package/dist/agent/child-runner.js +6 -37
- package/dist/agent/discovery-barrier.js +1 -1
- package/dist/agent/profiles.d.ts +1 -2
- package/dist/agent/profiles.js +25 -14
- package/dist/agent/routing-catalog.d.ts +113 -0
- package/dist/agent/routing-catalog.js +240 -0
- package/dist/agent/subagent-control.d.ts +5 -12
- package/dist/agent/subagent-control.js +0 -2
- package/dist/agent/subagent-store.d.ts +1 -1
- package/dist/agent/subagent-store.js +1 -3
- package/dist/agent/workflow/control.d.ts +21 -0
- package/dist/agent/workflow/control.js +50 -8
- package/dist/agent/workflow/runtime.d.ts +15 -2
- package/dist/agent/workflow/runtime.js +112 -30
- package/dist/agent.d.ts +82 -48
- package/dist/agent.js +360 -232
- package/dist/approval/controller.js +28 -0
- package/dist/approval/tool-helper.js +2 -0
- package/dist/approval/types.d.ts +21 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +2 -1
- package/dist/config.d.ts +5 -3
- package/dist/config.js +10 -5
- package/dist/context/compact-llm.d.ts +2 -2
- package/dist/external-runtime/grok-acp.d.ts +56 -0
- package/dist/external-runtime/grok-acp.js +386 -0
- package/dist/external-runtime/grok-binary.d.ts +25 -0
- package/dist/external-runtime/grok-binary.js +108 -0
- package/dist/external-runtime/grok-errors.d.ts +7 -0
- package/dist/external-runtime/grok-errors.js +15 -0
- package/dist/external-runtime/grok-input-policy.d.ts +58 -0
- package/dist/external-runtime/grok-input-policy.js +52 -0
- package/dist/external-runtime/grok-ndjson.d.ts +14 -0
- package/dist/external-runtime/grok-ndjson.js +193 -0
- package/dist/external-runtime/grok-network.d.ts +15 -0
- package/dist/external-runtime/grok-network.js +81 -0
- package/dist/external-runtime/grok-preflight.d.ts +28 -0
- package/dist/external-runtime/grok-preflight.js +194 -0
- package/dist/external-runtime/grok-process.d.ts +26 -0
- package/dist/external-runtime/grok-process.js +184 -0
- package/dist/external-runtime/grok-profile.d.ts +32 -0
- package/dist/external-runtime/grok-profile.js +419 -0
- package/dist/external-runtime/grok-provider.d.ts +31 -0
- package/dist/external-runtime/grok-provider.js +41 -0
- package/dist/external-runtime/grok-runtime.d.ts +91 -0
- package/dist/external-runtime/grok-runtime.js +882 -0
- package/dist/external-runtime/index.d.ts +13 -0
- package/dist/external-runtime/index.js +13 -0
- package/dist/external-runtime/session-policy.d.ts +11 -0
- package/dist/external-runtime/session-policy.js +30 -0
- package/dist/external-runtime/types.d.ts +65 -0
- package/dist/external-runtime/types.js +1 -0
- package/dist/feishu/agent-host/approval-card.js +21 -0
- package/dist/feishu/agent-host/run-driver.js +19 -3
- package/dist/feishu/serve.js +1 -0
- package/dist/goal/tools.d.ts +6 -3
- package/dist/goal/tools.js +7 -19
- package/dist/main.js +114 -28
- package/dist/memory/db.d.ts +2 -0
- package/dist/memory/db.js +10 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.js +1 -0
- package/dist/memory/phase1.js +14 -2
- package/dist/memory/phase2.js +21 -2
- package/dist/memory/prompts.js +1 -1
- package/dist/memory/session-policy.d.ts +25 -0
- package/dist/memory/session-policy.js +55 -0
- package/dist/memory/storage.d.ts +1 -0
- package/dist/memory/storage.js +13 -0
- package/dist/model-catalog.d.ts +18 -0
- package/dist/model-catalog.js +92 -52
- package/dist/model-config.d.ts +3 -1
- package/dist/model-config.js +11 -0
- package/dist/oauth/grok.d.ts +25 -0
- package/dist/oauth/grok.js +218 -0
- package/dist/oauth/index.d.ts +1 -0
- package/dist/oauth/index.js +1 -0
- package/dist/oauth/storage.d.ts +9 -0
- package/dist/oauth/storage.js +25 -0
- package/dist/orchestrator/default-hooks.js +23 -7
- package/dist/prompt/compose.d.ts +3 -0
- package/dist/prompt/compose.js +3 -0
- package/dist/prompt/delegation.d.ts +1 -1
- package/dist/prompt/delegation.js +41 -8
- package/dist/prompt/environment.js +0 -4
- package/dist/prompt/reminders.d.ts +0 -1
- package/dist/prompt/reminders.js +1 -11
- package/dist/prompt/routing.d.ts +14 -0
- package/dist/prompt/routing.js +71 -0
- package/dist/prompt/runtime.js +1 -1
- package/dist/prompt/task-reminders.d.ts +20 -0
- package/dist/prompt/task-reminders.js +73 -1
- package/dist/provider-ai-sdk.js +2 -2
- package/dist/provider-grok.d.ts +26 -0
- package/dist/provider-grok.js +59 -0
- package/dist/provider-openai-codex.d.ts +17 -1
- package/dist/provider-openai-codex.js +101 -29
- package/dist/provider-registry.d.ts +72 -0
- package/dist/provider-registry.js +336 -59
- package/dist/provider-transform.d.ts +1 -1
- package/dist/provider-transform.js +35 -17
- package/dist/provider.d.ts +3 -0
- package/dist/provider.js +14 -0
- package/dist/session-types.d.ts +19 -1
- package/dist/session.d.ts +1 -0
- package/dist/session.js +4 -0
- package/dist/slash-commands/commands.js +224 -14
- package/dist/slash-commands/types.d.ts +14 -1
- package/dist/system-prompt.d.ts +2 -0
- package/dist/tools/agent-lifecycle.d.ts +1 -9
- package/dist/tools/agent-lifecycle.js +42 -272
- package/dist/tools/bash.js +1 -1
- package/dist/tools/child-tools.js +2 -0
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js +7 -5
- package/dist/tools/lsp.js +1 -0
- package/dist/tools/memory.d.ts +7 -2
- package/dist/tools/memory.js +28 -43
- package/dist/tools/server.js +4 -0
- package/dist/tools/tool-search.d.ts +1 -1
- package/dist/tools/tool-search.js +23 -3
- package/dist/tui/model-switch.d.ts +7 -0
- package/dist/tui/model-switch.js +15 -5
- package/dist/tui-ink/app.d.ts +3 -1
- package/dist/tui-ink/app.js +672 -243
- package/dist/tui-ink/approval/approval-dialog.js +37 -1
- package/dist/tui-ink/approval/diff-view.js +4 -4
- package/dist/tui-ink/approval/select.js +2 -2
- package/dist/tui-ink/composer-buffer.d.ts +55 -0
- package/dist/tui-ink/composer-buffer.js +317 -0
- package/dist/tui-ink/feedback-dialog.js +2 -2
- package/dist/tui-ink/feishu-setup-picker.js +3 -3
- package/dist/tui-ink/footer.d.ts +1 -0
- package/dist/tui-ink/footer.js +7 -2
- package/dist/tui-ink/input-box.d.ts +36 -7
- package/dist/tui-ink/input-box.js +229 -157
- package/dist/tui-ink/markdown.js +11 -9
- package/dist/tui-ink/message-list.d.ts +5 -1
- package/dist/tui-ink/message-list.js +15 -2
- package/dist/tui-ink/model-picker.d.ts +61 -4
- package/dist/tui-ink/model-picker.js +464 -128
- package/dist/tui-ink/paste-operation-tracker.d.ts +13 -0
- package/dist/tui-ink/paste-operation-tracker.js +25 -0
- package/dist/tui-ink/plan-confirm.js +1 -1
- package/dist/tui-ink/run.d.ts +3 -0
- package/dist/tui-ink/run.js +1 -1
- package/dist/tui-ink/subagent-view.d.ts +34 -1
- package/dist/tui-ink/subagent-view.js +82 -1
- package/dist/tui-ink/theme.d.ts +19 -2
- package/dist/tui-ink/theme.js +25 -8
- package/dist/tui-ink/welcome.d.ts +3 -2
- package/dist/tui-ink/welcome.js +10 -6
- package/dist/types.d.ts +8 -31
- package/dist/types.js +1 -1
- package/dist/variant/thinking-level.d.ts +2 -2
- package/dist/variant/thinking-level.js +2 -1
- package/dist/variant/variant-resolver.d.ts +22 -0
- package/dist/variant/variant-resolver.js +43 -0
- package/package.json +6 -2
- package/dist/tools/task.d.ts +0 -2
- package/dist/tools/task.js +0 -58
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./grok-errors.js";
|
|
3
|
+
export * from "./grok-network.js";
|
|
4
|
+
export * from "./grok-provider.js";
|
|
5
|
+
export * from "./grok-input-policy.js";
|
|
6
|
+
export * from "./session-policy.js";
|
|
7
|
+
export * from "./grok-binary.js";
|
|
8
|
+
export * from "./grok-profile.js";
|
|
9
|
+
export * from "./grok-preflight.js";
|
|
10
|
+
export * from "./grok-process.js";
|
|
11
|
+
export * from "./grok-ndjson.js";
|
|
12
|
+
export * from "./grok-acp.js";
|
|
13
|
+
export * from "./grok-runtime.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./grok-errors.js";
|
|
3
|
+
export * from "./grok-network.js";
|
|
4
|
+
export * from "./grok-provider.js";
|
|
5
|
+
export * from "./grok-input-policy.js";
|
|
6
|
+
export * from "./session-policy.js";
|
|
7
|
+
export * from "./grok-binary.js";
|
|
8
|
+
export * from "./grok-profile.js";
|
|
9
|
+
export * from "./grok-preflight.js";
|
|
10
|
+
export * from "./grok-process.js";
|
|
11
|
+
export * from "./grok-ndjson.js";
|
|
12
|
+
export * from "./grok-acp.js";
|
|
13
|
+
export * from "./grok-runtime.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ExternalRuntimeManager } from "./types.js";
|
|
2
|
+
export type ExternalRuntimeBindingKind = "none" | "grok" | "unsupported";
|
|
3
|
+
/**
|
|
4
|
+
* Treat every persisted external-runtime marker as non-native. Known aliases
|
|
5
|
+
* normalize to Grok; malformed or future IDs stay fail-closed instead of
|
|
6
|
+
* falling through to Bubble's native agent/tool path.
|
|
7
|
+
*/
|
|
8
|
+
export declare function classifyExternalRuntimeBinding(binding: unknown): ExternalRuntimeBindingKind;
|
|
9
|
+
export declare function stopExternalRuntimeForSessionSwitch(runtime: ExternalRuntimeManager | undefined, sessionId?: string): Promise<void>;
|
|
10
|
+
/** Never replay a Grok-owned transcript through Bubble's native print path. */
|
|
11
|
+
export declare function shouldRejectGrokSessionInPrintMode(externalRuntimeBinding: unknown, printMode: boolean): boolean;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { isGrokSubscriptionProviderId } from "./grok-provider.js";
|
|
2
|
+
/**
|
|
3
|
+
* Treat every persisted external-runtime marker as non-native. Known aliases
|
|
4
|
+
* normalize to Grok; malformed or future IDs stay fail-closed instead of
|
|
5
|
+
* falling through to Bubble's native agent/tool path.
|
|
6
|
+
*/
|
|
7
|
+
export function classifyExternalRuntimeBinding(binding) {
|
|
8
|
+
if (binding === undefined)
|
|
9
|
+
return "none";
|
|
10
|
+
const id = typeof binding === "string"
|
|
11
|
+
? binding
|
|
12
|
+
: binding !== null && typeof binding === "object" && "id" in binding
|
|
13
|
+
? binding.id
|
|
14
|
+
: undefined;
|
|
15
|
+
return typeof id === "string" && isGrokSubscriptionProviderId(id)
|
|
16
|
+
? "grok"
|
|
17
|
+
: "unsupported";
|
|
18
|
+
}
|
|
19
|
+
export async function stopExternalRuntimeForSessionSwitch(runtime, sessionId) {
|
|
20
|
+
if (!runtime) {
|
|
21
|
+
throw new Error("The external runtime manager is unavailable; the current session was not changed.");
|
|
22
|
+
}
|
|
23
|
+
if (sessionId)
|
|
24
|
+
await runtime.cancel(sessionId);
|
|
25
|
+
await runtime.dispose();
|
|
26
|
+
}
|
|
27
|
+
/** Never replay a Grok-owned transcript through Bubble's native print path. */
|
|
28
|
+
export function shouldRejectGrokSessionInPrintMode(externalRuntimeBinding, printMode) {
|
|
29
|
+
return printMode && classifyExternalRuntimeBinding(externalRuntimeBinding) !== "none";
|
|
30
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { AgentEvent } from "../types.js";
|
|
2
|
+
import type { ThinkingLevel } from "../types.js";
|
|
3
|
+
export type ExternalRuntimeState = "unavailable" | "signed_out" | "ready" | "running" | "failed" | "disposed";
|
|
4
|
+
export interface ExternalRuntimeCapabilities {
|
|
5
|
+
chat: boolean;
|
|
6
|
+
tools: boolean;
|
|
7
|
+
memory: boolean;
|
|
8
|
+
subagents: boolean;
|
|
9
|
+
plan: boolean;
|
|
10
|
+
web: boolean;
|
|
11
|
+
sessionLoad: boolean;
|
|
12
|
+
workspace: boolean;
|
|
13
|
+
modelControl: boolean;
|
|
14
|
+
reasoningControl: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface ExternalRuntimeBinaryInfo {
|
|
17
|
+
path: string;
|
|
18
|
+
version: string;
|
|
19
|
+
sha256: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ExternalRuntimeStatus {
|
|
22
|
+
provider: "grok";
|
|
23
|
+
state: ExternalRuntimeState;
|
|
24
|
+
capabilities: ExternalRuntimeCapabilities;
|
|
25
|
+
binary?: ExternalRuntimeBinaryInfo;
|
|
26
|
+
sessionId?: string;
|
|
27
|
+
/** A deliberately terse, credential-free diagnostic suitable for the TUI. */
|
|
28
|
+
message?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface ExternalRuntimeSession {
|
|
31
|
+
id: string;
|
|
32
|
+
provider: "grok";
|
|
33
|
+
modelId?: string;
|
|
34
|
+
reasoningEffort?: ThinkingLevel;
|
|
35
|
+
}
|
|
36
|
+
export interface ExternalRuntimeModel {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
reasoningLevels: ThinkingLevel[];
|
|
40
|
+
defaultReasoningLevel: ThinkingLevel;
|
|
41
|
+
}
|
|
42
|
+
export interface ExternalRuntimeModelSelection {
|
|
43
|
+
modelId?: string;
|
|
44
|
+
reasoningEffort: ThinkingLevel;
|
|
45
|
+
}
|
|
46
|
+
export interface ExternalRuntimeRunOptions {
|
|
47
|
+
sessionId?: string;
|
|
48
|
+
signal?: AbortSignal;
|
|
49
|
+
/** Lets callers invalidate late ACP notifications after a UI generation swap. */
|
|
50
|
+
generation?: number;
|
|
51
|
+
}
|
|
52
|
+
export interface ExternalRuntimeManager {
|
|
53
|
+
inspect(): Promise<ExternalRuntimeStatus>;
|
|
54
|
+
login(signal?: AbortSignal, onBrowserOpened?: () => void): Promise<void>;
|
|
55
|
+
logout(): Promise<void>;
|
|
56
|
+
newSession(): Promise<ExternalRuntimeSession>;
|
|
57
|
+
loadSession(id: string): Promise<ExternalRuntimeSession>;
|
|
58
|
+
hydrateSession(id: string, modelId?: string, reasoningEffort?: ThinkingLevel): Promise<ExternalRuntimeSession>;
|
|
59
|
+
listModels(): Promise<ExternalRuntimeModel[]>;
|
|
60
|
+
getModelSelection(): ExternalRuntimeModelSelection;
|
|
61
|
+
setModel(modelId: string, reasoningEffort?: ThinkingLevel): Promise<ExternalRuntimeModelSelection>;
|
|
62
|
+
run(prompt: string, options?: ExternalRuntimeRunOptions): AsyncIterable<AgentEvent>;
|
|
63
|
+
cancel(sessionId?: string): Promise<void>;
|
|
64
|
+
dispose(): Promise<void>;
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -55,6 +55,27 @@ export function formatApprovalRequest(req) {
|
|
|
55
55
|
"\n该 profile 来自仓库本地 `.bubble/agents`,其 prompt 会驱动一个子代理。仅在信任该仓库时批准。",
|
|
56
56
|
].join("\n"),
|
|
57
57
|
};
|
|
58
|
+
case "external_tool":
|
|
59
|
+
return {
|
|
60
|
+
title: `外部工具:${req.title}`,
|
|
61
|
+
body: [
|
|
62
|
+
`**kind:** \`${truncate(req.kind, 80)}\``,
|
|
63
|
+
req.locations?.length
|
|
64
|
+
? `**paths:** ${req.locations.map((location) => `\`${truncate(location.path, PATH_PREVIEW_MAX)}\``).join(", ")}`
|
|
65
|
+
: "",
|
|
66
|
+
req.rawInput === undefined
|
|
67
|
+
? ""
|
|
68
|
+
: `\n**input:**\n\`\`\`json\n${truncate(safeJson(req.rawInput), CONTENT_PREVIEW_MAX)}\n\`\`\``,
|
|
69
|
+
].filter(Boolean).join("\n"),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function safeJson(value) {
|
|
74
|
+
try {
|
|
75
|
+
return JSON.stringify(value, null, 2);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return "[unserializable input]";
|
|
58
79
|
}
|
|
59
80
|
}
|
|
60
81
|
function truncate(s, max) {
|
|
@@ -19,11 +19,13 @@ import { BashAllowlist } from "../../approval/session-cache.js";
|
|
|
19
19
|
import { getLspService } from "../../lsp/index.js";
|
|
20
20
|
import { ExternalHookController } from "../../hooks/index.js";
|
|
21
21
|
import { buildSystemPrompt } from "../../system-prompt.js";
|
|
22
|
+
import { createRoutableModelIndex, createRoutingSnapshotAccessor } from "../../agent/routing-catalog.js";
|
|
23
|
+
import { buildModelRoutingPrompt } from "../../prompt/routing.js";
|
|
22
24
|
import { FileStateTracker } from "../../tools/file-state.js";
|
|
23
25
|
import { buildToolPromptOptions, createAllTools } from "../../tools/index.js";
|
|
24
26
|
import { displayModel, encodeModel, decodeModel } from "../../provider-registry.js";
|
|
25
27
|
import { buildMemoryPrompt, recordMemoryCitations } from "../../memory/index.js";
|
|
26
|
-
import { getDefaultThinkingLevel } from "../../provider-transform.js";
|
|
28
|
+
import { getAvailableThinkingLevels, getDefaultThinkingLevel, normalizeThinkingLevel } from "../../provider-transform.js";
|
|
27
29
|
import { createSessionTitleUpdater } from "../../session-title.js";
|
|
28
30
|
import { applyCardBudget } from "../card/budget.js";
|
|
29
31
|
import { renderCard } from "../card/renderer.js";
|
|
@@ -87,9 +89,16 @@ export class RunDriver {
|
|
|
87
89
|
const { provider, providerId, model } = await this.resolveProvider(session, promptCacheKey);
|
|
88
90
|
const skills = this.opts.deps.skillRegistry.summaries();
|
|
89
91
|
const memoryPrompt = buildMemoryPrompt(session.cwd);
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
+
const modelId = decodeModel(model).modelId;
|
|
93
|
+
const configuredThinkingLevel = this.opts.deps.userConfig.getDefaultThinkingLevel();
|
|
94
|
+
const thinkingLevel = configuredThinkingLevel !== undefined
|
|
95
|
+
? normalizeThinkingLevel(configuredThinkingLevel, getAvailableThinkingLevels(providerId, modelId))
|
|
96
|
+
: getDefaultThinkingLevel(providerId, modelId);
|
|
92
97
|
const initialMode = session.permissionMode;
|
|
98
|
+
// Routing accessor built before the prompt (design §1.5): the prompt is
|
|
99
|
+
// composed before the Agent exists, same ordering constraint as main.ts.
|
|
100
|
+
const agentRouting = this.opts.deps.userConfig.getAgentRouting();
|
|
101
|
+
const routingSnapshotAccessor = createRoutingSnapshotAccessor(this.opts.deps.providerRegistry, () => this.opts.deps.userConfig.getAgentCategories(), () => agentRouting);
|
|
93
102
|
const systemPrompt = buildSystemPrompt({
|
|
94
103
|
agentName: "Bubble",
|
|
95
104
|
configuredProvider: providerId || "none",
|
|
@@ -100,6 +109,9 @@ export class RunDriver {
|
|
|
100
109
|
workingDir: session.cwd,
|
|
101
110
|
...buildToolPromptOptions(tools.filter((tool) => !tool.deferred)),
|
|
102
111
|
memoryPrompt,
|
|
112
|
+
modelRoutingPrompt: providerId && modelId
|
|
113
|
+
? buildModelRoutingPrompt(routingSnapshotAccessor({ providerId, model: modelId }), agentRouting)
|
|
114
|
+
: undefined,
|
|
103
115
|
});
|
|
104
116
|
const budgetLedger = new BudgetLedger();
|
|
105
117
|
let sessionTitleUpdater;
|
|
@@ -140,6 +152,9 @@ export class RunDriver {
|
|
|
140
152
|
memoryPrompt,
|
|
141
153
|
fileStateTracker,
|
|
142
154
|
agentCategories: this.opts.deps.userConfig.getAgentCategories(),
|
|
155
|
+
agentRouting,
|
|
156
|
+
routingSnapshot: routingSnapshotAccessor,
|
|
157
|
+
routableModels: createRoutableModelIndex(this.opts.deps.providerRegistry),
|
|
143
158
|
subagents: this.opts.deps.userConfig.getSubagents(),
|
|
144
159
|
providerFactory: (route) => this.opts.deps.createProviderForRoute(route, promptCacheKey),
|
|
145
160
|
externalHooks: hookController,
|
|
@@ -175,6 +190,7 @@ export class RunDriver {
|
|
|
175
190
|
agent.messages = [{ role: "system", content: systemPrompt }, ...history];
|
|
176
191
|
if (agent.mode === "plan")
|
|
177
192
|
agent.injectModeReminder();
|
|
193
|
+
agent.injectDeferredToolsReminder();
|
|
178
194
|
}
|
|
179
195
|
}
|
|
180
196
|
// 4. Build RunState + stream the card.
|
package/dist/feishu/serve.js
CHANGED
|
@@ -98,6 +98,7 @@ export async function serveFeishu(opts = {}) {
|
|
|
98
98
|
promptCacheKey,
|
|
99
99
|
protocol: providerRegistry.getConfigured().find((provider) => provider.id === providerId)?.protocol,
|
|
100
100
|
openAICodexAuth: providerRegistry.createOpenAICodexAuthAdapter(providerId),
|
|
101
|
+
grokAuth: providerRegistry.createGrokAuthAdapter(providerId),
|
|
101
102
|
});
|
|
102
103
|
const createProviderForRoute = async (route, promptCacheKey) => {
|
|
103
104
|
const target = providerRegistry.getConfigured().find((p) => p.id === route.providerId);
|
package/dist/goal/tools.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Model-facing goal
|
|
2
|
+
* Model-facing goal tool: update_goal.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* It writes the shared GoalStore so the model's completion/blocked signal
|
|
5
5
|
* stops the TUI's auto-continuation loop. The user sets goals via `/goal`, so
|
|
6
|
-
* there is intentionally no model-facing create_goal tool
|
|
6
|
+
* there is intentionally no model-facing create_goal tool — and no read tool:
|
|
7
|
+
* the goal engine already injects the objective plus budget state into every
|
|
8
|
+
* goal turn's prompt, so a get_goal call could only return what the model was
|
|
9
|
+
* just told.
|
|
7
10
|
*/
|
|
8
11
|
import type { ToolRegistryEntry } from "../types.js";
|
|
9
12
|
import type { GoalStore } from "./store.js";
|
package/dist/goal/tools.js
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Model-facing goal
|
|
2
|
+
* Model-facing goal tool: update_goal.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* It writes the shared GoalStore so the model's completion/blocked signal
|
|
5
5
|
* stops the TUI's auto-continuation loop. The user sets goals via `/goal`, so
|
|
6
|
-
* there is intentionally no model-facing create_goal tool
|
|
6
|
+
* there is intentionally no model-facing create_goal tool — and no read tool:
|
|
7
|
+
* the goal engine already injects the objective plus budget state into every
|
|
8
|
+
* goal turn's prompt, so a get_goal call could only return what the model was
|
|
9
|
+
* just told.
|
|
7
10
|
*/
|
|
8
|
-
import { goalSummaryText } from "./format.js";
|
|
9
11
|
const UPDATE_GOAL_DESCRIPTION = `Update the active thread goal's status. Use this tool only to mark the goal achieved or genuinely blocked; it returns an error if there is no active goal.
|
|
10
12
|
Set status to "complete" only when the objective has actually been achieved and no required work remains — never merely because the budget is nearly exhausted or you are stopping.
|
|
11
13
|
Set status to "blocked" only when the same blocking condition has repeated for at least three consecutive goal turns (counting the original turn and automatic continuations) and you cannot make meaningful progress without user input or an external-state change. Do not use "blocked" because work is hard, slow, uncertain, or incomplete.
|
|
12
14
|
You cannot pause, resume, or set a budget through this tool; those are controlled by the user.`;
|
|
13
15
|
export function createGoalTools(store) {
|
|
14
|
-
const getGoal = {
|
|
15
|
-
name: "get_goal",
|
|
16
|
-
description: "Get the current thread goal: objective, status, turns and tokens used, and remaining token budget. Returns an error if there is no goal.",
|
|
17
|
-
parameters: { type: "object", properties: {}, required: [], additionalProperties: false },
|
|
18
|
-
readOnly: true,
|
|
19
|
-
effect: "read",
|
|
20
|
-
promptSnippet: "Inspect the active goal's status and remaining token budget.",
|
|
21
|
-
async execute() {
|
|
22
|
-
const goal = store.snapshot();
|
|
23
|
-
if (!goal)
|
|
24
|
-
return { content: "No active goal.", isError: true };
|
|
25
|
-
return { content: goalSummaryText(goal) };
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
16
|
const updateGoal = {
|
|
29
17
|
name: "update_goal",
|
|
30
18
|
description: UPDATE_GOAL_DESCRIPTION,
|
|
@@ -66,5 +54,5 @@ export function createGoalTools(store) {
|
|
|
66
54
|
};
|
|
67
55
|
},
|
|
68
56
|
};
|
|
69
|
-
return [
|
|
57
|
+
return [updateGoal];
|
|
70
58
|
}
|
package/dist/main.js
CHANGED
|
@@ -9,11 +9,13 @@ import { parseArgs, printHelp } from "./cli.js";
|
|
|
9
9
|
import { effectiveThemeModeForTerminal, shouldProbeTerminalTheme, UserConfig } from "./config.js";
|
|
10
10
|
import { createProviderInstance, createUnavailableProvider } from "./provider.js";
|
|
11
11
|
import { resolveConfiguredModel } from "./model-selection.js";
|
|
12
|
-
import { getDefaultThinkingLevel } from "./provider-transform.js";
|
|
12
|
+
import { getAvailableThinkingLevels, getDefaultThinkingLevel, normalizeThinkingLevel } from "./provider-transform.js";
|
|
13
13
|
import { ProviderRegistry, displayModel, encodeModel, decodeModel } from "./provider-registry.js";
|
|
14
14
|
import { SessionManager } from "./session.js";
|
|
15
15
|
import { createSessionTitleUpdater } from "./session-title.js";
|
|
16
16
|
import { buildSystemPrompt } from "./system-prompt.js";
|
|
17
|
+
import { createRoutableModelIndex, createRoutingSnapshotAccessor } from "./agent/routing-catalog.js";
|
|
18
|
+
import { buildModelRoutingPrompt } from "./prompt/routing.js";
|
|
17
19
|
import { SkillRegistry } from "./skills/registry.js";
|
|
18
20
|
import { buildToolPromptOptions, createAllTools } from "./tools/index.js";
|
|
19
21
|
import { FileStateTracker } from "./tools/file-state.js";
|
|
@@ -25,12 +27,14 @@ import { ExternalHookController } from "./hooks/index.js";
|
|
|
25
27
|
import { getLspService } from "./lsp/index.js";
|
|
26
28
|
import { loadMcpConfig } from "./mcp/config.js";
|
|
27
29
|
import { McpManager } from "./mcp/manager.js";
|
|
30
|
+
import { normalizeInheritedThinkingLevel } from "./variant/variant-resolver.js";
|
|
28
31
|
import { QuestionController } from "./question/index.js";
|
|
29
|
-
import { buildMemoryPrompt, formatMemoryStartupResult, recordMemoryCitations, runMemoryPhase2, runMemoryStartupPipeline, startMemoryStartupTask, } from "./memory/index.js";
|
|
32
|
+
import { buildMemoryPrompt, formatMemoryStartupResult, purgeUnsafeMemorySources, recordMemoryCitations, runMemoryPhase2, runMemoryStartupPipeline, startMemoryStartupTask, } from "./memory/index.js";
|
|
30
33
|
import { basename } from "node:path";
|
|
31
34
|
import { normalizeSingleLine, truncateVisual } from "./text-display.js";
|
|
32
35
|
import { BUBBLE_WORDMARK } from "./tui/wordmark.js";
|
|
33
36
|
import { configureDebugTrace, summarizeAgentEventForTrace, summarizeTraceMessage, traceEvent, } from "./debug-trace.js";
|
|
37
|
+
import { shouldRejectGrokSessionInPrintMode } from "./external-runtime/session-policy.js";
|
|
34
38
|
async function main() {
|
|
35
39
|
const args = parseArgs(process.argv.slice(2));
|
|
36
40
|
if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
@@ -88,6 +92,7 @@ async function main() {
|
|
|
88
92
|
promptCacheKey: sessionPromptCacheKey,
|
|
89
93
|
protocol: defaultProvider.protocol,
|
|
90
94
|
openAICodexAuth: registry.createOpenAICodexAuthAdapter(defaultProvider.id),
|
|
95
|
+
grokAuth: registry.createGrokAuthAdapter(defaultProvider.id),
|
|
91
96
|
})
|
|
92
97
|
: createUnavailableProvider(unavailableProviderMessage);
|
|
93
98
|
const createProvider = (providerId, apiKey, baseURL) => createProviderInstance({
|
|
@@ -98,6 +103,7 @@ async function main() {
|
|
|
98
103
|
promptCacheKey: sessionPromptCacheKey,
|
|
99
104
|
protocol: registry.getConfigured().find((provider) => provider.id === providerId)?.protocol,
|
|
100
105
|
openAICodexAuth: registry.createOpenAICodexAuthAdapter(providerId),
|
|
106
|
+
grokAuth: registry.createGrokAuthAdapter(providerId),
|
|
101
107
|
});
|
|
102
108
|
const createProviderForRoute = async (route) => {
|
|
103
109
|
const providerId = route.providerId;
|
|
@@ -156,7 +162,7 @@ async function main() {
|
|
|
156
162
|
};
|
|
157
163
|
const lspService = getLspService(args.cwd, settingsManager.getMerged().lsp);
|
|
158
164
|
const fileStateTracker = new FileStateTracker(args.cwd);
|
|
159
|
-
// Shared between the goal
|
|
165
|
+
// Shared between the goal tool (model-facing update_goal) and the
|
|
160
166
|
// TUI's auto-continuation engine / status-line indicator.
|
|
161
167
|
const goalStore = new GoalStore();
|
|
162
168
|
const tools = createAllTools(args.cwd, skillRegistry, {
|
|
@@ -178,6 +184,7 @@ async function main() {
|
|
|
178
184
|
console.error(chalk.yellow(`[mcp:${d.scope}] ${d.path}: ${d.message}`));
|
|
179
185
|
}
|
|
180
186
|
const mcpManager = new McpManager({ servers: mcpLoaded.servers });
|
|
187
|
+
let externalRuntime;
|
|
181
188
|
if (mcpLoaded.servers.length > 0) {
|
|
182
189
|
await mcpManager.start();
|
|
183
190
|
// Only surface failures at startup. Successful connections would push the
|
|
@@ -206,8 +213,19 @@ async function main() {
|
|
|
206
213
|
// ignore — we're exiting anyway
|
|
207
214
|
}
|
|
208
215
|
};
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
const shutdownExternalRuntime = async () => {
|
|
217
|
+
try {
|
|
218
|
+
await externalRuntime?.dispose();
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
// ignore — we're exiting anyway
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const shutdownSidecars = async () => {
|
|
225
|
+
await Promise.allSettled([shutdownMcp(), shutdownExternalRuntime()]);
|
|
226
|
+
};
|
|
227
|
+
process.once("SIGINT", () => { void shutdownSidecars().then(() => process.exit(130)); });
|
|
228
|
+
process.once("SIGTERM", () => { void shutdownSidecars().then(() => process.exit(143)); });
|
|
211
229
|
// Session management:
|
|
212
230
|
// - default: always start a fresh session
|
|
213
231
|
// - --resume --session <name>: restore the named session
|
|
@@ -235,12 +253,20 @@ async function main() {
|
|
|
235
253
|
const pickerThemeMode = effectiveThemeModeForTerminal(themeConfig, preResolvedTheme);
|
|
236
254
|
const pickerResolvedTheme = pickerThemeMode === "auto" ? preResolvedTheme : pickerThemeMode;
|
|
237
255
|
const { runSessionPicker } = await import("./tui-ink/run-session-picker.js");
|
|
256
|
+
const { canvasBackgroundFor } = await import("./tui-ink/theme.js");
|
|
257
|
+
// Same rule as the main TUI: a forced theme mismatching the terminal
|
|
258
|
+
// paints its canvas so its foregrounds stay readable.
|
|
259
|
+
const pickerCanvas = themeConfig.overrides?.background
|
|
260
|
+
? undefined
|
|
261
|
+
: canvasBackgroundFor(pickerThemeMode, pickerResolvedTheme, preResolvedTheme);
|
|
238
262
|
const picked = await runSessionPicker({
|
|
239
263
|
currentCwd: args.cwd,
|
|
240
264
|
currentSessions,
|
|
241
265
|
allSessions,
|
|
242
266
|
resolvedTheme: pickerResolvedTheme,
|
|
243
|
-
themeOverrides:
|
|
267
|
+
themeOverrides: pickerCanvas
|
|
268
|
+
? { ...themeConfig.overrides, background: pickerCanvas }
|
|
269
|
+
: themeConfig.overrides,
|
|
244
270
|
});
|
|
245
271
|
if (picked) {
|
|
246
272
|
sessionManager = new SessionManager(picked);
|
|
@@ -288,15 +314,30 @@ async function main() {
|
|
|
288
314
|
activeProviderId = "";
|
|
289
315
|
}
|
|
290
316
|
const initialThinkingLevel = activeModel
|
|
291
|
-
?
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
317
|
+
? args.thinkingLevel !== undefined
|
|
318
|
+
? normalizeThinkingLevel(args.thinkingLevel, getAvailableThinkingLevels(activeProviderId, effectiveModelId))
|
|
319
|
+
: sessionThinkingLevel !== undefined
|
|
320
|
+
? normalizeInheritedThinkingLevel(activeProviderId, effectiveModelId, sessionThinkingLevel)
|
|
321
|
+
: configuredThinkingLevel !== undefined
|
|
322
|
+
? normalizeThinkingLevel(configuredThinkingLevel, getAvailableThinkingLevels(activeProviderId, effectiveModelId))
|
|
323
|
+
: getDefaultThinkingLevel(activeProviderId, effectiveModelId)
|
|
324
|
+
: (args.thinkingLevel ?? sessionThinkingLevel ?? configuredThinkingLevel ?? "off");
|
|
296
325
|
const restoredTodos = sessionManager?.getTodos() ?? [];
|
|
297
326
|
const initialMode = args.mode ?? "default";
|
|
298
327
|
const skillSummaries = skillRegistry.summaries();
|
|
328
|
+
// This synchronous provenance gate must run before buildMemoryPrompt: the
|
|
329
|
+
// background startup pipeline is too late once text has entered the native
|
|
330
|
+
// provider's system prompt.
|
|
331
|
+
purgeUnsafeMemorySources(args.cwd);
|
|
299
332
|
const memoryPrompt = buildMemoryPrompt(args.cwd);
|
|
333
|
+
// Routing snapshot accessor (model-routing design §1.5): built before the
|
|
334
|
+
// system prompt because startup composes the prompt before the Agent exists;
|
|
335
|
+
// the same accessor is then handed to the Agent constructor.
|
|
336
|
+
const agentRouting = userConfig.getAgentRouting();
|
|
337
|
+
const routingSnapshotAccessor = createRoutingSnapshotAccessor(registry, () => userConfig.getAgentCategories(), () => agentRouting);
|
|
338
|
+
const initialRoutingParent = activeProviderId && activeModel
|
|
339
|
+
? { providerId: activeProviderId, model: decodeModel(activeModel).modelId }
|
|
340
|
+
: undefined;
|
|
300
341
|
const systemPrompt = buildSystemPrompt({
|
|
301
342
|
agentName: "Bubble",
|
|
302
343
|
configuredProvider: activeProviderId || "none",
|
|
@@ -307,6 +348,9 @@ async function main() {
|
|
|
307
348
|
workingDir: args.cwd,
|
|
308
349
|
...buildToolPromptOptions(tools.filter((tool) => !tool.deferred)),
|
|
309
350
|
memoryPrompt,
|
|
351
|
+
modelRoutingPrompt: initialRoutingParent
|
|
352
|
+
? buildModelRoutingPrompt(routingSnapshotAccessor(initialRoutingParent), agentRouting)
|
|
353
|
+
: undefined,
|
|
310
354
|
});
|
|
311
355
|
const traceInfo = configureDebugTrace({
|
|
312
356
|
cwd: args.cwd,
|
|
@@ -381,6 +425,9 @@ async function main() {
|
|
|
381
425
|
memoryPrompt,
|
|
382
426
|
fileStateTracker,
|
|
383
427
|
agentCategories: userConfig.getAgentCategories(),
|
|
428
|
+
agentRouting,
|
|
429
|
+
routingSnapshot: routingSnapshotAccessor,
|
|
430
|
+
routableModels: createRoutableModelIndex(registry),
|
|
384
431
|
subagents: userConfig.getSubagents(),
|
|
385
432
|
providerFactory: createProviderForRoute,
|
|
386
433
|
externalHooks: hookController,
|
|
@@ -418,20 +465,26 @@ async function main() {
|
|
|
418
465
|
// not perform an ad-hoc extraction of the just-finished session.
|
|
419
466
|
};
|
|
420
467
|
const shutdownRuntime = async () => {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
468
|
+
try {
|
|
469
|
+
await hookController.runEvent({
|
|
470
|
+
eventName: "SessionEnd",
|
|
471
|
+
cwd: args.cwd,
|
|
472
|
+
sessionId: sessionManager?.getSessionFile(),
|
|
473
|
+
agentRole: "driver",
|
|
474
|
+
target: "session",
|
|
475
|
+
payload: {
|
|
476
|
+
providerId: agent.providerId,
|
|
477
|
+
model: agent.apiModel,
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
catch {
|
|
482
|
+
// Shutdown must still release child processes when a hook fails.
|
|
483
|
+
}
|
|
432
484
|
const results = await Promise.allSettled([
|
|
433
485
|
flushMemory(),
|
|
434
486
|
shutdownMcp(),
|
|
487
|
+
shutdownExternalRuntime(),
|
|
435
488
|
lspService.shutdown(),
|
|
436
489
|
]);
|
|
437
490
|
for (const result of results) {
|
|
@@ -472,12 +525,18 @@ async function main() {
|
|
|
472
525
|
if (agent.mode === "plan") {
|
|
473
526
|
agent.injectModeReminder();
|
|
474
527
|
}
|
|
528
|
+
agent.injectDeferredToolsReminder();
|
|
475
529
|
console.log(chalk.dim(`Resumed session: ${sessionManager.getSessionFile()}`));
|
|
476
530
|
}
|
|
477
531
|
}
|
|
478
532
|
try {
|
|
479
533
|
// Print mode: single prompt, then exit
|
|
480
534
|
if (args.print || args.prompt) {
|
|
535
|
+
if (shouldRejectGrokSessionInPrintMode(sessionManager?.getMetadata().externalRuntime, true)) {
|
|
536
|
+
console.error(chalk.red("Error: Grok subscription sessions are interactive. Resume this workspace session in the TUI, or start a fresh native session for --print."));
|
|
537
|
+
process.exitCode = 1;
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
481
540
|
const prompt = args.prompt || (await readPipedStdin()) || "";
|
|
482
541
|
if (!prompt) {
|
|
483
542
|
console.error(chalk.red("Error: No prompt provided."));
|
|
@@ -535,9 +594,8 @@ async function main() {
|
|
|
535
594
|
try {
|
|
536
595
|
const next = new SessionManager(sessionFile);
|
|
537
596
|
const history = next.getMessages();
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
sessionTitleUpdater = createSessionTitleUpdater({
|
|
597
|
+
const nextPromptCacheKey = next.getOrCreatePromptCacheKey();
|
|
598
|
+
const nextTitleUpdater = createSessionTitleUpdater({
|
|
541
599
|
sessionManager: next,
|
|
542
600
|
complete: (messages, completeOptions) => agent.complete(messages, completeOptions),
|
|
543
601
|
});
|
|
@@ -550,9 +608,26 @@ async function main() {
|
|
|
550
608
|
// Keep the live system/meta head (mode reminders survive the switch),
|
|
551
609
|
// mirroring the /rewind history-replacement pattern.
|
|
552
610
|
const head = agent.messages.filter((m) => m.role === "system" || m.role === "meta");
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
611
|
+
const nextMessages = [...head, ...history];
|
|
612
|
+
const nextTodos = next.getTodos();
|
|
613
|
+
// Commit only after every file read/write and reconstruction step has
|
|
614
|
+
// succeeded. Callers can safely prepare candidate sessions without a
|
|
615
|
+
// failed switch rebinding persistence or replacing the live history.
|
|
616
|
+
sessionManager = next;
|
|
617
|
+
sessionPromptCacheKey = nextPromptCacheKey;
|
|
618
|
+
sessionTitleUpdater = nextTitleUpdater;
|
|
619
|
+
agent.messages = nextMessages;
|
|
620
|
+
// These update only live in-memory/UI mirrors after the persistence
|
|
621
|
+
// commit. A best-effort callback failure must not report the switch as
|
|
622
|
+
// rolled back after the outer session binding has already changed.
|
|
623
|
+
try {
|
|
624
|
+
agent.setTodos(nextTodos);
|
|
625
|
+
}
|
|
626
|
+
catch { /* candidate already committed */ }
|
|
627
|
+
try {
|
|
628
|
+
agent.resetContextUsageAnchor();
|
|
629
|
+
}
|
|
630
|
+
catch { /* derived counter only */ }
|
|
556
631
|
return { manager: next };
|
|
557
632
|
}
|
|
558
633
|
catch (error) {
|
|
@@ -579,6 +654,16 @@ async function main() {
|
|
|
579
654
|
runMemorySummary,
|
|
580
655
|
runMemoryRefresh,
|
|
581
656
|
};
|
|
657
|
+
// Grok Subscription is a first-class interactive provider target. Manager
|
|
658
|
+
// construction is deliberately lazy: it does not inspect, spawn, or reach
|
|
659
|
+
// the network until the user selects Grok or runs /login grok. Print,
|
|
660
|
+
// Feishu, help, and version paths return before this import.
|
|
661
|
+
const { createGrokRuntimeManager } = await import("./external-runtime/grok-runtime.js");
|
|
662
|
+
externalRuntime = createGrokRuntimeManager({
|
|
663
|
+
workspace: args.cwd,
|
|
664
|
+
approvalController,
|
|
665
|
+
getPermissionMode: () => agentRef?.mode ?? "default",
|
|
666
|
+
});
|
|
582
667
|
const { startStartupUpdateCheck } = await import("./update/index.js");
|
|
583
668
|
const updateCheck = await startStartupUpdateCheck();
|
|
584
669
|
const updateNotice = updateCheck.notice;
|
|
@@ -591,6 +676,7 @@ async function main() {
|
|
|
591
676
|
onThemeModeChange: (mode) => userConfig.setThemeMode(mode),
|
|
592
677
|
updateNotice: updateNotice ?? undefined,
|
|
593
678
|
updateNoticeRefresh: updateCheck.refreshed,
|
|
679
|
+
externalRuntime,
|
|
594
680
|
});
|
|
595
681
|
const exitWallMs = summary?.wallMs;
|
|
596
682
|
if (sessionManager) {
|
package/dist/memory/db.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export declare class MemoryDatabase {
|
|
|
40
40
|
};
|
|
41
41
|
finishPhase1Job(sessionFile: string, ok: boolean, error?: string): void;
|
|
42
42
|
listStage1Outputs(limit?: number): Stage1Output[];
|
|
43
|
+
listAllStage1Outputs(): Stage1Output[];
|
|
44
|
+
deleteStage1Output(sessionFile: string): boolean;
|
|
43
45
|
listPreviouslySelectedNotIn(sessionFiles: string[]): Stage1Output[];
|
|
44
46
|
markSelectedForPhase2(outputs: Stage1Output[]): void;
|
|
45
47
|
recordUsage(sessionFiles: string[], now?: Date): number;
|
package/dist/memory/db.js
CHANGED
|
@@ -95,6 +95,16 @@ export class MemoryDatabase {
|
|
|
95
95
|
LIMIT ?
|
|
96
96
|
`).all(limit).map((row) => mapStage1(row));
|
|
97
97
|
}
|
|
98
|
+
listAllStage1Outputs() {
|
|
99
|
+
return this.db.prepare(`
|
|
100
|
+
SELECT * FROM memory_stage1_outputs
|
|
101
|
+
ORDER BY usage_count DESC, COALESCE(last_usage, generated_at) DESC, source_updated_at DESC
|
|
102
|
+
`).all().map((row) => mapStage1(row));
|
|
103
|
+
}
|
|
104
|
+
deleteStage1Output(sessionFile) {
|
|
105
|
+
return (this.db.prepare("DELETE FROM memory_stage1_outputs WHERE session_file = ?")
|
|
106
|
+
.run(sessionFile).changes ?? 0) > 0;
|
|
107
|
+
}
|
|
98
108
|
listPreviouslySelectedNotIn(sessionFiles) {
|
|
99
109
|
if (sessionFiles.length === 0) {
|
|
100
110
|
return this.db.prepare("SELECT * FROM memory_stage1_outputs WHERE selected_for_phase2 = 1")
|
package/dist/memory/index.d.ts
CHANGED
package/dist/memory/index.js
CHANGED