@kinqs/brainrouter-cli 0.3.4 → 0.3.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/.env.example +55 -48
- package/README.md +102 -142
- package/bin/cli.cjs +71 -0
- package/dist/agent/agent.d.ts +212 -2
- package/dist/agent/agent.js +430 -40
- package/dist/cli/banner.d.ts +60 -0
- package/dist/cli/banner.js +199 -0
- package/dist/cli/cliPrompt.d.ts +69 -0
- package/dist/cli/cliPrompt.js +287 -0
- package/dist/cli/commands/_helpers.js +6 -6
- package/dist/cli/commands/guard.js +75 -10
- package/dist/cli/commands/mcp.d.ts +17 -0
- package/dist/cli/commands/mcp.js +121 -0
- package/dist/cli/commands/memory.js +2 -2
- package/dist/cli/commands/obs.js +22 -22
- package/dist/cli/commands/session.js +13 -5
- package/dist/cli/commands/ui.js +97 -45
- package/dist/cli/commands/workflow.d.ts +18 -0
- package/dist/cli/commands/workflow.js +314 -43
- package/dist/cli/repl.js +219 -132
- package/dist/cli/spinner.d.ts +34 -0
- package/dist/cli/spinner.js +36 -0
- package/dist/cli/statusline.d.ts +67 -0
- package/dist/cli/statusline.js +204 -0
- package/dist/cli/theme.d.ts +79 -0
- package/dist/cli/theme.js +106 -0
- package/dist/cli/whereView.d.ts +81 -0
- package/dist/cli/whereView.js +245 -0
- package/dist/config/config.d.ts +40 -0
- package/dist/config/config.js +45 -73
- package/dist/index.js +81 -14
- package/dist/memory/briefing.d.ts +10 -0
- package/dist/memory/briefing.js +69 -1
- package/dist/prompt/breadthHint.d.ts +5 -0
- package/dist/prompt/breadthHint.js +44 -0
- package/dist/prompt/systemPrompt.d.ts +34 -0
- package/dist/prompt/systemPrompt.js +124 -108
- package/dist/runtime/dangerousCommand.d.ts +53 -0
- package/dist/runtime/dangerousCommand.js +105 -0
- package/dist/runtime/mcpClient.d.ts +38 -1
- package/dist/runtime/mcpClient.js +91 -3
- package/dist/state/goalStore.d.ts +98 -17
- package/dist/state/goalStore.js +132 -42
- package/dist/state/preferencesStore.d.ts +67 -3
- package/dist/state/preferencesStore.js +84 -1
- package/dist/state/workflowArtifacts.d.ts +63 -2
- package/dist/state/workflowArtifacts.js +120 -8
- package/dist/tests/_helpers.d.ts +31 -0
- package/dist/tests/_helpers.js +91 -0
- package/package.json +5 -4
package/dist/agent/agent.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { McpClientWrapper } from '../runtime/mcpClient.js';
|
|
2
2
|
import type { LLMConfig } from '../config/config.js';
|
|
3
3
|
import type { AccessMode } from '../orchestration/roles.js';
|
|
4
|
+
import { type RecalledRecord } from '../memory/briefing.js';
|
|
5
|
+
import { type EffortLevel } from '../state/preferencesStore.js';
|
|
4
6
|
export interface RunTurnCallbacks {
|
|
5
7
|
onStatusUpdate: (status: string) => void;
|
|
6
8
|
onToolStart: (name: string, args: Record<string, any>) => void;
|
|
@@ -77,6 +79,12 @@ export interface ChatCompletionPayload {
|
|
|
77
79
|
};
|
|
78
80
|
}>;
|
|
79
81
|
tool_choice?: 'auto';
|
|
82
|
+
/**
|
|
83
|
+
* OpenAI Chat Completions reasoning slot — accepted by gpt-5 / o-series.
|
|
84
|
+
* Only set when the user has chosen a non-default `/effort` AND the
|
|
85
|
+
* endpoint+model combo accepts the field (see `supportsReasoningEffortField`).
|
|
86
|
+
*/
|
|
87
|
+
reasoning_effort?: EffortLevel;
|
|
80
88
|
}
|
|
81
89
|
export interface AgentOptions {
|
|
82
90
|
workspaceRoot: string;
|
|
@@ -131,6 +139,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
131
139
|
url?: undefined;
|
|
132
140
|
maxResults?: undefined;
|
|
133
141
|
patch?: undefined;
|
|
142
|
+
question?: undefined;
|
|
143
|
+
header?: undefined;
|
|
144
|
+
options?: undefined;
|
|
145
|
+
multiSelect?: undefined;
|
|
134
146
|
explanation?: undefined;
|
|
135
147
|
plan?: undefined;
|
|
136
148
|
proof?: undefined;
|
|
@@ -163,6 +175,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
163
175
|
url?: undefined;
|
|
164
176
|
maxResults?: undefined;
|
|
165
177
|
patch?: undefined;
|
|
178
|
+
question?: undefined;
|
|
179
|
+
header?: undefined;
|
|
180
|
+
options?: undefined;
|
|
181
|
+
multiSelect?: undefined;
|
|
166
182
|
explanation?: undefined;
|
|
167
183
|
plan?: undefined;
|
|
168
184
|
proof?: undefined;
|
|
@@ -198,6 +214,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
198
214
|
url?: undefined;
|
|
199
215
|
maxResults?: undefined;
|
|
200
216
|
patch?: undefined;
|
|
217
|
+
question?: undefined;
|
|
218
|
+
header?: undefined;
|
|
219
|
+
options?: undefined;
|
|
220
|
+
multiSelect?: undefined;
|
|
201
221
|
explanation?: undefined;
|
|
202
222
|
plan?: undefined;
|
|
203
223
|
proof?: undefined;
|
|
@@ -227,6 +247,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
227
247
|
url?: undefined;
|
|
228
248
|
maxResults?: undefined;
|
|
229
249
|
patch?: undefined;
|
|
250
|
+
question?: undefined;
|
|
251
|
+
header?: undefined;
|
|
252
|
+
options?: undefined;
|
|
253
|
+
multiSelect?: undefined;
|
|
230
254
|
explanation?: undefined;
|
|
231
255
|
plan?: undefined;
|
|
232
256
|
proof?: undefined;
|
|
@@ -259,6 +283,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
259
283
|
url?: undefined;
|
|
260
284
|
maxResults?: undefined;
|
|
261
285
|
patch?: undefined;
|
|
286
|
+
question?: undefined;
|
|
287
|
+
header?: undefined;
|
|
288
|
+
options?: undefined;
|
|
289
|
+
multiSelect?: undefined;
|
|
262
290
|
explanation?: undefined;
|
|
263
291
|
plan?: undefined;
|
|
264
292
|
proof?: undefined;
|
|
@@ -288,6 +316,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
288
316
|
url?: undefined;
|
|
289
317
|
maxResults?: undefined;
|
|
290
318
|
patch?: undefined;
|
|
319
|
+
question?: undefined;
|
|
320
|
+
header?: undefined;
|
|
321
|
+
options?: undefined;
|
|
322
|
+
multiSelect?: undefined;
|
|
291
323
|
explanation?: undefined;
|
|
292
324
|
plan?: undefined;
|
|
293
325
|
proof?: undefined;
|
|
@@ -317,6 +349,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
317
349
|
url?: undefined;
|
|
318
350
|
maxResults?: undefined;
|
|
319
351
|
patch?: undefined;
|
|
352
|
+
question?: undefined;
|
|
353
|
+
header?: undefined;
|
|
354
|
+
options?: undefined;
|
|
355
|
+
multiSelect?: undefined;
|
|
320
356
|
explanation?: undefined;
|
|
321
357
|
plan?: undefined;
|
|
322
358
|
proof?: undefined;
|
|
@@ -346,6 +382,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
346
382
|
command?: undefined;
|
|
347
383
|
maxResults?: undefined;
|
|
348
384
|
patch?: undefined;
|
|
385
|
+
question?: undefined;
|
|
386
|
+
header?: undefined;
|
|
387
|
+
options?: undefined;
|
|
388
|
+
multiSelect?: undefined;
|
|
349
389
|
explanation?: undefined;
|
|
350
390
|
plan?: undefined;
|
|
351
391
|
proof?: undefined;
|
|
@@ -378,6 +418,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
378
418
|
command?: undefined;
|
|
379
419
|
url?: undefined;
|
|
380
420
|
patch?: undefined;
|
|
421
|
+
question?: undefined;
|
|
422
|
+
header?: undefined;
|
|
423
|
+
options?: undefined;
|
|
424
|
+
multiSelect?: undefined;
|
|
381
425
|
explanation?: undefined;
|
|
382
426
|
plan?: undefined;
|
|
383
427
|
proof?: undefined;
|
|
@@ -407,6 +451,68 @@ export declare const LOCAL_TOOLS: ({
|
|
|
407
451
|
command?: undefined;
|
|
408
452
|
url?: undefined;
|
|
409
453
|
maxResults?: undefined;
|
|
454
|
+
question?: undefined;
|
|
455
|
+
header?: undefined;
|
|
456
|
+
options?: undefined;
|
|
457
|
+
multiSelect?: undefined;
|
|
458
|
+
explanation?: undefined;
|
|
459
|
+
plan?: undefined;
|
|
460
|
+
proof?: undefined;
|
|
461
|
+
reason?: undefined;
|
|
462
|
+
needed?: undefined;
|
|
463
|
+
};
|
|
464
|
+
required: string[];
|
|
465
|
+
};
|
|
466
|
+
} | {
|
|
467
|
+
name: string;
|
|
468
|
+
description: string;
|
|
469
|
+
inputSchema: {
|
|
470
|
+
type: string;
|
|
471
|
+
properties: {
|
|
472
|
+
question: {
|
|
473
|
+
type: string;
|
|
474
|
+
description: string;
|
|
475
|
+
};
|
|
476
|
+
header: {
|
|
477
|
+
type: string;
|
|
478
|
+
description: string;
|
|
479
|
+
};
|
|
480
|
+
options: {
|
|
481
|
+
type: string;
|
|
482
|
+
description: string;
|
|
483
|
+
minItems: number;
|
|
484
|
+
maxItems: number;
|
|
485
|
+
items: {
|
|
486
|
+
type: string;
|
|
487
|
+
properties: {
|
|
488
|
+
label: {
|
|
489
|
+
type: string;
|
|
490
|
+
description: string;
|
|
491
|
+
};
|
|
492
|
+
description: {
|
|
493
|
+
type: string;
|
|
494
|
+
description: string;
|
|
495
|
+
};
|
|
496
|
+
};
|
|
497
|
+
required: string[];
|
|
498
|
+
};
|
|
499
|
+
};
|
|
500
|
+
multiSelect: {
|
|
501
|
+
type: string;
|
|
502
|
+
description: string;
|
|
503
|
+
};
|
|
504
|
+
path?: undefined;
|
|
505
|
+
startLine?: undefined;
|
|
506
|
+
endLine?: undefined;
|
|
507
|
+
content?: undefined;
|
|
508
|
+
targetContent?: undefined;
|
|
509
|
+
replacementContent?: undefined;
|
|
510
|
+
query?: undefined;
|
|
511
|
+
pattern?: undefined;
|
|
512
|
+
command?: undefined;
|
|
513
|
+
url?: undefined;
|
|
514
|
+
maxResults?: undefined;
|
|
515
|
+
patch?: undefined;
|
|
410
516
|
explanation?: undefined;
|
|
411
517
|
plan?: undefined;
|
|
412
518
|
proof?: undefined;
|
|
@@ -454,6 +560,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
454
560
|
url?: undefined;
|
|
455
561
|
maxResults?: undefined;
|
|
456
562
|
patch?: undefined;
|
|
563
|
+
question?: undefined;
|
|
564
|
+
header?: undefined;
|
|
565
|
+
options?: undefined;
|
|
566
|
+
multiSelect?: undefined;
|
|
457
567
|
proof?: undefined;
|
|
458
568
|
reason?: undefined;
|
|
459
569
|
needed?: undefined;
|
|
@@ -482,6 +592,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
482
592
|
url?: undefined;
|
|
483
593
|
maxResults?: undefined;
|
|
484
594
|
patch?: undefined;
|
|
595
|
+
question?: undefined;
|
|
596
|
+
header?: undefined;
|
|
597
|
+
options?: undefined;
|
|
598
|
+
multiSelect?: undefined;
|
|
485
599
|
explanation?: undefined;
|
|
486
600
|
plan?: undefined;
|
|
487
601
|
reason?: undefined;
|
|
@@ -515,6 +629,10 @@ export declare const LOCAL_TOOLS: ({
|
|
|
515
629
|
url?: undefined;
|
|
516
630
|
maxResults?: undefined;
|
|
517
631
|
patch?: undefined;
|
|
632
|
+
question?: undefined;
|
|
633
|
+
header?: undefined;
|
|
634
|
+
options?: undefined;
|
|
635
|
+
multiSelect?: undefined;
|
|
518
636
|
explanation?: undefined;
|
|
519
637
|
plan?: undefined;
|
|
520
638
|
proof?: undefined;
|
|
@@ -575,6 +693,28 @@ export declare class Agent {
|
|
|
575
693
|
private recalledRecordIds;
|
|
576
694
|
private recalledRecords;
|
|
577
695
|
private lastBriefingSources;
|
|
696
|
+
/**
|
|
697
|
+
* 10b: latest MCP tool inventory captured by `listTools()` calls. Used by
|
|
698
|
+
* `createSystemMessage` to decide whether the BrainRouter memory section
|
|
699
|
+
* should render — when `memory_recall` is missing from this list (the
|
|
700
|
+
* cloud brain is offline), the prompt swaps to a brain-offline notice so
|
|
701
|
+
* the model doesn't try to call tools that aren't there. Undefined until
|
|
702
|
+
* the first successful list; treated as "assume online" by the prompt
|
|
703
|
+
* builder until then (back-compat for callers that don't list pre-turn).
|
|
704
|
+
*/
|
|
705
|
+
private lastKnownMcpTools?;
|
|
706
|
+
/**
|
|
707
|
+
* 9b: gated recall state. `recallHasFiredThisSession` flips to true on the
|
|
708
|
+
* first successful briefing injection so subsequent turns can skip the
|
|
709
|
+
* fresh recall pull unless a gated trigger fires. `recallNextTurnIsPost-
|
|
710
|
+
* Compaction` is set by `compactHistory()` to force the next turn through
|
|
711
|
+
* the full briefing path (compaction just dropped the prior briefing as
|
|
712
|
+
* collateral; replay it once so the model isn't blind). Both are
|
|
713
|
+
* cleared on `loadHistory` / `fork` / `bootstrapSession` so a fresh
|
|
714
|
+
* session re-pulls.
|
|
715
|
+
*/
|
|
716
|
+
private recallHasFiredThisSession;
|
|
717
|
+
private recallNextTurnIsPostCompaction;
|
|
578
718
|
private roleOverlay?;
|
|
579
719
|
private accessMode;
|
|
580
720
|
private silent;
|
|
@@ -708,9 +848,30 @@ export declare class Agent {
|
|
|
708
848
|
* Idempotent: calling this with a tag that isn't present is a no-op.
|
|
709
849
|
*/
|
|
710
850
|
removeTaggedSystemMessage(tag: string): void;
|
|
851
|
+
/**
|
|
852
|
+
* Zero the in-process counters that back `/tokens`. Call this on any
|
|
853
|
+
* conceptual session boundary (`/resume`, `fork`) — otherwise the parent
|
|
854
|
+
* row keeps accumulating across the switch and "this session" no longer
|
|
855
|
+
* matches the displayed sessionKey.
|
|
856
|
+
*/
|
|
857
|
+
resetSessionCounters(): void;
|
|
711
858
|
/** Fork the current chat history into a fresh sessionKey. Returns the new key. */
|
|
712
859
|
fork(newSessionKey: string): string;
|
|
713
860
|
private bootstrapSession;
|
|
861
|
+
/**
|
|
862
|
+
* Public, callback-free wrapper around bootstrapSession for slash commands
|
|
863
|
+
* that mutate per-session state (notably `/goal`) BEFORE any runTurn has
|
|
864
|
+
* fired. Without this, the FIRST `/goal` of a session writes goal.json
|
|
865
|
+
* under the deterministic fallback sessionKey ("brainrouter-cli:<path>")
|
|
866
|
+
* because bootstrap hasn't happened yet, but every subsequent runTurn
|
|
867
|
+
* reads from the MCP-resolved UUID sessionKey — split-brain that left
|
|
868
|
+
* the agent reading a stale goal from a different directory.
|
|
869
|
+
*
|
|
870
|
+
* Idempotent: returns immediately if already initialized. Tolerates
|
|
871
|
+
* missing MCP — falls back to the deterministic key the same way
|
|
872
|
+
* bootstrapSession does.
|
|
873
|
+
*/
|
|
874
|
+
ensureInitialized(): Promise<void>;
|
|
714
875
|
private createSystemMessage;
|
|
715
876
|
private injectRecallContext;
|
|
716
877
|
/** Inspectable summary of the most recent memory briefing. Used by the `/briefing` slash command. */
|
|
@@ -718,6 +879,13 @@ export declare class Agent {
|
|
|
718
879
|
sources: string[];
|
|
719
880
|
recordIds: string[];
|
|
720
881
|
};
|
|
882
|
+
/**
|
|
883
|
+
* Snapshot of the records produced by the most recent pre-turn briefing.
|
|
884
|
+
* `/where` surfaces a few of these to give the user a sense of what the
|
|
885
|
+
* agent is leaning on right now. Returns a shallow copy so callers can't
|
|
886
|
+
* mutate the agent's internal state.
|
|
887
|
+
*/
|
|
888
|
+
getRecalledRecords(): RecalledRecord[];
|
|
721
889
|
/** One-line summary of any new contradiction surfaced after the last capture, or undefined if none. */
|
|
722
890
|
private lastContradictionWarning?;
|
|
723
891
|
takeContradictionWarning(): string | undefined;
|
|
@@ -757,8 +925,50 @@ export declare function getToolSummary(name: string, args: Record<string, any>,
|
|
|
757
925
|
* the terminal. Returns undefined when no useful preview is available.
|
|
758
926
|
*/
|
|
759
927
|
export declare function getToolPreview(name: string, args: Record<string, any>, result: string): string | undefined;
|
|
760
|
-
|
|
761
|
-
|
|
928
|
+
/**
|
|
929
|
+
* Heuristic for "does this model accept the OpenAI Chat Completions
|
|
930
|
+
* `reasoning_effort` field?". The signal that actually matters is the
|
|
931
|
+
* **model name**, not the endpoint hostname — modern OpenAI-compatible
|
|
932
|
+
* servers (LM Studio 0.3.29+, Ollama, vLLM, OpenRouter, OpenAI itself)
|
|
933
|
+
* all accept the field on /v1/chat/completions for the reasoning-capable
|
|
934
|
+
* model classes below, and silently ignore it for everything else. So a
|
|
935
|
+
* `gpt-oss-20b` served from localhost via LM Studio gets the same
|
|
936
|
+
* treatment as `gpt-5` on `api.openai.com`.
|
|
937
|
+
*
|
|
938
|
+
* Borrowed shape from openai-node's `ReasoningEffort` enum
|
|
939
|
+
* (openSrc/openai-node/src/resources/shared.ts) — `low|medium|high` map
|
|
940
|
+
* straight through to the provider field across OpenAI, DeepSeek,
|
|
941
|
+
* LM Studio, Ollama, and OpenRouter's pass-through. Anthropic models
|
|
942
|
+
* (`claude-*`) use a different field shape (`thinking: { budget_tokens }`)
|
|
943
|
+
* and a different endpoint (`/v1/messages`), so they're intentionally
|
|
944
|
+
* skipped here — brainrouter would need a separate provider adapter to
|
|
945
|
+
* forward into Anthropic's native API.
|
|
946
|
+
*/
|
|
947
|
+
/**
|
|
948
|
+
* 9b: resolve the recall-gating mode for this process. `BRAINROUTER_RECALL_MODE`
|
|
949
|
+
* env var beats everything; unset defaults to `gated`. Anything outside the
|
|
950
|
+
* three valid values falls back to `gated` (defensive — better to be helpful
|
|
951
|
+
* than crash on a typo). Re-resolved each turn so users can flip with
|
|
952
|
+
* `export BRAINROUTER_RECALL_MODE=always` mid-session via a /run command.
|
|
953
|
+
*/
|
|
954
|
+
export declare function resolveRecallMode(): 'always' | 'gated' | 'off';
|
|
955
|
+
/**
|
|
956
|
+
* 9b: cheap local heuristic for "the user message names something specific
|
|
957
|
+
* memory might have history on." Counts entity-shaped tokens: proper nouns
|
|
958
|
+
* (capitalized words that aren't sentence-starting), file paths (anything
|
|
959
|
+
* with `/` or `\\` or a `.<ext>` suffix), and identifier-shaped tokens (`camelCase`
|
|
960
|
+
* / `snake_case` / `PascalCase` longer than 4 chars). Crude but the bar is
|
|
961
|
+
* "is recall plausibly worth it?" — false positives waste a recall call,
|
|
962
|
+
* false negatives waste an ask. Tunable threshold via the caller.
|
|
963
|
+
*/
|
|
964
|
+
export declare function countEntityTokens(text: string): number;
|
|
965
|
+
export declare function supportsReasoningEffortField(config: LLMConfig): boolean;
|
|
966
|
+
export interface BuildPayloadOptions {
|
|
967
|
+
/** Reasoning-depth preference, when provider supports it. `medium` is a no-op. */
|
|
968
|
+
effort?: EffortLevel;
|
|
969
|
+
}
|
|
970
|
+
export declare function buildChatCompletionPayload(config: LLMConfig, messages: any[], tools: any[], options?: BuildPayloadOptions): ChatCompletionPayload;
|
|
971
|
+
export declare function callOpenAI(config: LLMConfig, messages: any[], tools: any[], options?: BuildPayloadOptions): Promise<{
|
|
762
972
|
content: any;
|
|
763
973
|
toolCalls: any;
|
|
764
974
|
usage: any;
|