praana 0.5.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/LICENSE +21 -0
- package/README.md +124 -0
- package/bin/praana.js +17 -0
- package/bin/pran.js +17 -0
- package/dist/app-banner.d.ts +11 -0
- package/dist/app-banner.js +161 -0
- package/dist/app-controller.d.ts +44 -0
- package/dist/app-controller.js +143 -0
- package/dist/app-identity.d.ts +18 -0
- package/dist/app-identity.js +52 -0
- package/dist/auto-compact.d.ts +16 -0
- package/dist/auto-compact.js +101 -0
- package/dist/cli-args.d.ts +14 -0
- package/dist/cli-args.js +69 -0
- package/dist/compile-classic.d.ts +21 -0
- package/dist/compile-classic.js +106 -0
- package/dist/compiler.d.ts +75 -0
- package/dist/compiler.js +406 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +433 -0
- package/dist/context-engine/activity-log.d.ts +9 -0
- package/dist/context-engine/activity-log.js +109 -0
- package/dist/context-engine/artifact-store.d.ts +32 -0
- package/dist/context-engine/artifact-store.js +272 -0
- package/dist/context-engine/bm25.d.ts +3 -0
- package/dist/context-engine/bm25.js +32 -0
- package/dist/context-engine/checkpoint.d.ts +34 -0
- package/dist/context-engine/checkpoint.js +430 -0
- package/dist/context-engine/classify.d.ts +3 -0
- package/dist/context-engine/classify.js +60 -0
- package/dist/context-engine/db.d.ts +73 -0
- package/dist/context-engine/db.js +505 -0
- package/dist/context-engine/distiller.d.ts +30 -0
- package/dist/context-engine/distiller.js +67 -0
- package/dist/context-engine/engine-compiler.d.ts +23 -0
- package/dist/context-engine/engine-compiler.js +297 -0
- package/dist/context-engine/error-tracker.d.ts +21 -0
- package/dist/context-engine/error-tracker.js +74 -0
- package/dist/context-engine/event-lineage.d.ts +26 -0
- package/dist/context-engine/event-lineage.js +120 -0
- package/dist/context-engine/extraction.d.ts +26 -0
- package/dist/context-engine/extraction.js +83 -0
- package/dist/context-engine/index.d.ts +82 -0
- package/dist/context-engine/index.js +238 -0
- package/dist/context-engine/scoring.d.ts +13 -0
- package/dist/context-engine/scoring.js +47 -0
- package/dist/context-engine/state-snapshot.d.ts +8 -0
- package/dist/context-engine/state-snapshot.js +50 -0
- package/dist/context-engine/summarize.d.ts +6 -0
- package/dist/context-engine/summarize.js +32 -0
- package/dist/context-engine/telemetry.d.ts +25 -0
- package/dist/context-engine/telemetry.js +64 -0
- package/dist/context-engine/turn-digest.d.ts +50 -0
- package/dist/context-engine/turn-digest.js +250 -0
- package/dist/context-engine/turn-ledger.d.ts +18 -0
- package/dist/context-engine/turn-ledger.js +184 -0
- package/dist/context-engine/turn-recorder.d.ts +24 -0
- package/dist/context-engine/turn-recorder.js +88 -0
- package/dist/context-engine/types.d.ts +201 -0
- package/dist/context-engine/types.js +4 -0
- package/dist/context-pressure.d.ts +19 -0
- package/dist/context-pressure.js +36 -0
- package/dist/distillers/generic.d.ts +14 -0
- package/dist/distillers/generic.js +93 -0
- package/dist/distillers/git-diff.d.ts +8 -0
- package/dist/distillers/git-diff.js +119 -0
- package/dist/distillers/index.d.ts +2 -0
- package/dist/distillers/index.js +16 -0
- package/dist/distillers/npm-test.d.ts +8 -0
- package/dist/distillers/npm-test.js +50 -0
- package/dist/distillers/rg-results.d.ts +8 -0
- package/dist/distillers/rg-results.js +28 -0
- package/dist/distillers/tsc-errors.d.ts +8 -0
- package/dist/distillers/tsc-errors.js +52 -0
- package/dist/event-log.d.ts +56 -0
- package/dist/event-log.js +214 -0
- package/dist/llm.d.ts +29 -0
- package/dist/llm.js +155 -0
- package/dist/logger.d.ts +94 -0
- package/dist/logger.js +287 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +54 -0
- package/dist/memory/confidence.d.ts +7 -0
- package/dist/memory/confidence.js +37 -0
- package/dist/memory/consolidation.d.ts +26 -0
- package/dist/memory/consolidation.js +166 -0
- package/dist/memory/db.d.ts +40 -0
- package/dist/memory/db.js +283 -0
- package/dist/memory/dedup.d.ts +6 -0
- package/dist/memory/dedup.js +50 -0
- package/dist/memory/embedder-factory.d.ts +3 -0
- package/dist/memory/embedder-factory.js +81 -0
- package/dist/memory/embeddings.d.ts +15 -0
- package/dist/memory/embeddings.js +67 -0
- package/dist/memory/index.d.ts +9 -0
- package/dist/memory/index.js +11 -0
- package/dist/memory/ollama-summarizer.d.ts +19 -0
- package/dist/memory/ollama-summarizer.js +72 -0
- package/dist/memory/openai-summarizer.d.ts +21 -0
- package/dist/memory/openai-summarizer.js +51 -0
- package/dist/memory/store.d.ts +61 -0
- package/dist/memory/store.js +502 -0
- package/dist/memory/summarizer-factory.d.ts +3 -0
- package/dist/memory/summarizer-factory.js +69 -0
- package/dist/memory/summarizer.d.ts +4 -0
- package/dist/memory/summarizer.js +112 -0
- package/dist/memory/types.d.ts +87 -0
- package/dist/memory/types.js +17 -0
- package/dist/model-context.d.ts +15 -0
- package/dist/model-context.js +212 -0
- package/dist/project-detector.d.ts +37 -0
- package/dist/project-detector.js +604 -0
- package/dist/render.d.ts +15 -0
- package/dist/render.js +46 -0
- package/dist/session.d.ts +118 -0
- package/dist/session.js +809 -0
- package/dist/skills/index.d.ts +69 -0
- package/dist/skills/index.js +885 -0
- package/dist/skills/types.d.ts +93 -0
- package/dist/skills/types.js +8 -0
- package/dist/slash-commands.d.ts +14 -0
- package/dist/slash-commands.js +301 -0
- package/dist/state-graph.d.ts +38 -0
- package/dist/state-graph.js +255 -0
- package/dist/status-bar.d.ts +54 -0
- package/dist/status-bar.js +184 -0
- package/dist/thinking-display.d.ts +21 -0
- package/dist/thinking-display.js +37 -0
- package/dist/tool-summary.d.ts +4 -0
- package/dist/tool-summary.js +67 -0
- package/dist/tools/index.d.ts +925 -0
- package/dist/tools/index.js +86 -0
- package/dist/tools/knowledge.d.ts +140 -0
- package/dist/tools/knowledge.js +260 -0
- package/dist/tools/memory.d.ts +39 -0
- package/dist/tools/memory.js +300 -0
- package/dist/tools/search-code.d.ts +134 -0
- package/dist/tools/search-code.js +390 -0
- package/dist/tools/system.d.ts +16 -0
- package/dist/tools/system.js +499 -0
- package/dist/tools/tool-def.d.ts +6 -0
- package/dist/tools/tool-def.js +3 -0
- package/dist/turn-control.d.ts +51 -0
- package/dist/turn-control.js +210 -0
- package/dist/turn.d.ts +20 -0
- package/dist/turn.js +624 -0
- package/dist/types.d.ts +233 -0
- package/dist/types.js +4 -0
- package/dist/ui/readline-ui.d.ts +2 -0
- package/dist/ui/readline-ui.js +176 -0
- package/dist/ui/tui/app.d.ts +13 -0
- package/dist/ui/tui/app.js +270 -0
- package/dist/ui/tui/busy-indicator.d.ts +2 -0
- package/dist/ui/tui/busy-indicator.js +13 -0
- package/dist/ui/tui/components/gutter-rule.d.ts +5 -0
- package/dist/ui/tui/components/gutter-rule.js +9 -0
- package/dist/ui/tui/components/inline-tool-row.d.ts +10 -0
- package/dist/ui/tui/components/inline-tool-row.js +8 -0
- package/dist/ui/tui/components/prompt-input.d.ts +20 -0
- package/dist/ui/tui/components/prompt-input.js +120 -0
- package/dist/ui/tui/components/system-line.d.ts +5 -0
- package/dist/ui/tui/components/system-line.js +6 -0
- package/dist/ui/tui/components/thinking-block.d.ts +11 -0
- package/dist/ui/tui/components/thinking-block.js +31 -0
- package/dist/ui/tui/components/toast-line.d.ts +4 -0
- package/dist/ui/tui/components/toast-line.js +8 -0
- package/dist/ui/tui/components/tool-result-line.d.ts +5 -0
- package/dist/ui/tui/components/tool-result-line.js +6 -0
- package/dist/ui/tui/components/turn-footer.d.ts +5 -0
- package/dist/ui/tui/components/turn-footer.js +7 -0
- package/dist/ui/tui/components/user-block.d.ts +6 -0
- package/dist/ui/tui/components/user-block.js +6 -0
- package/dist/ui/tui/logo-banner.d.ts +5 -0
- package/dist/ui/tui/logo-banner.js +8 -0
- package/dist/ui/tui/markdown-render.d.ts +16 -0
- package/dist/ui/tui/markdown-render.js +218 -0
- package/dist/ui/tui/palette.d.ts +12 -0
- package/dist/ui/tui/palette.js +13 -0
- package/dist/ui/tui/reasoning-summary.d.ts +12 -0
- package/dist/ui/tui/reasoning-summary.js +27 -0
- package/dist/ui/tui/reducer.d.ts +92 -0
- package/dist/ui/tui/reducer.js +260 -0
- package/dist/ui/tui/run.d.ts +3 -0
- package/dist/ui/tui/run.js +40 -0
- package/dist/ui/tui/sink.d.ts +4 -0
- package/dist/ui/tui/sink.js +89 -0
- package/dist/ui/tui/status-bar-view.d.ts +5 -0
- package/dist/ui/tui/status-bar-view.js +44 -0
- package/dist/ui/tui/terminal-height.d.ts +12 -0
- package/dist/ui/tui/terminal-height.js +20 -0
- package/dist/ui/tui/terminal-width.d.ts +2 -0
- package/dist/ui/tui/terminal-width.js +5 -0
- package/dist/ui/tui/tool-display.d.ts +23 -0
- package/dist/ui/tui/tool-display.js +217 -0
- package/dist/ui/tui/transcript-line.d.ts +12 -0
- package/dist/ui/tui/transcript-line.js +43 -0
- package/dist/ui/tui/transcript-replay.d.ts +12 -0
- package/dist/ui/tui/transcript-replay.js +117 -0
- package/dist/ui-events.d.ts +39 -0
- package/dist/ui-events.js +33 -0
- package/dist/ui.d.ts +77 -0
- package/dist/ui.js +179 -0
- package/package.json +73 -0
- package/praana.config.example.toml +231 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export type SkillResidency = "hot" | "warm" | "cold";
|
|
2
|
+
export type SkillSection = "planner" | "execution" | "recovery" | "examples";
|
|
3
|
+
export declare const ALL_SKILL_SECTIONS: SkillSection[];
|
|
4
|
+
export declare const SECTION_HEADINGS: Record<SkillSection, string>;
|
|
5
|
+
export interface SkillMetadata {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
license?: string;
|
|
9
|
+
compatibility?: string;
|
|
10
|
+
metadata?: Record<string, string>;
|
|
11
|
+
allowedTools?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SkillRecord {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
location: string;
|
|
17
|
+
directory: string;
|
|
18
|
+
body: string;
|
|
19
|
+
metadata: SkillMetadata;
|
|
20
|
+
}
|
|
21
|
+
export interface SkillSectionMapping {
|
|
22
|
+
planner?: string[];
|
|
23
|
+
execution?: string[];
|
|
24
|
+
recovery?: string[];
|
|
25
|
+
examples?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface SkillBudgetConfig {
|
|
28
|
+
priority?: "normal" | "high" | "low";
|
|
29
|
+
max_tokens?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface SkillAriaMeta {
|
|
32
|
+
tags?: string[];
|
|
33
|
+
trigger?: string;
|
|
34
|
+
synonyms?: string[];
|
|
35
|
+
neighbors?: string[];
|
|
36
|
+
sections?: SkillSectionMapping;
|
|
37
|
+
budget?: SkillBudgetConfig;
|
|
38
|
+
}
|
|
39
|
+
export type SkillsMetaFile = Record<string, SkillAriaMeta>;
|
|
40
|
+
export interface SkillIndexEntry {
|
|
41
|
+
id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
tags: string[];
|
|
45
|
+
trigger?: string;
|
|
46
|
+
synonyms?: string[];
|
|
47
|
+
neighbors?: string[];
|
|
48
|
+
/** Tokenized searchable text for BM25 */
|
|
49
|
+
searchText: string;
|
|
50
|
+
/** Parsed section boundaries from SKILL.md body */
|
|
51
|
+
sectionRanges?: Record<SkillSection, {
|
|
52
|
+
start: number;
|
|
53
|
+
end: number;
|
|
54
|
+
}>;
|
|
55
|
+
budgetPriority: "normal" | "high" | "low";
|
|
56
|
+
maxTokens: number;
|
|
57
|
+
}
|
|
58
|
+
export interface SkillRuntimeState {
|
|
59
|
+
entry: SkillIndexEntry;
|
|
60
|
+
residency: SkillResidency;
|
|
61
|
+
loadedSections: SkillSection[];
|
|
62
|
+
lastActiveTurn: number;
|
|
63
|
+
tokenCost: number;
|
|
64
|
+
/** Full body text cached from discovery */
|
|
65
|
+
body: string;
|
|
66
|
+
/** Directory path for resolving relative references */
|
|
67
|
+
directory: string;
|
|
68
|
+
}
|
|
69
|
+
export interface SkillRuntimeSnapshot {
|
|
70
|
+
hot: SkillRuntimeState[];
|
|
71
|
+
warm: SkillRuntimeState[];
|
|
72
|
+
tokenUsage: number;
|
|
73
|
+
tokenBudget: number;
|
|
74
|
+
}
|
|
75
|
+
export interface SkillsRuntimeConfig {
|
|
76
|
+
enabled: boolean;
|
|
77
|
+
max_token_budget_ratio: number;
|
|
78
|
+
active_skill_idle_turns: number;
|
|
79
|
+
warm_skill_eviction_turns: number;
|
|
80
|
+
max_depth: number;
|
|
81
|
+
/** Override search paths for discovery (testing only). */
|
|
82
|
+
searchPaths?: string[];
|
|
83
|
+
}
|
|
84
|
+
export interface SkillTelemetryEvent {
|
|
85
|
+
type: "skill_discovered" | "skill_matched" | "skill_loaded" | "skill_promoted" | "skill_demoted" | "skill_evicted" | "skill_hydrated" | "skill_budget_exceeded" | "skill_neighbor_boosted";
|
|
86
|
+
skill_id: string;
|
|
87
|
+
residency?: SkillResidency;
|
|
88
|
+
sections?: string[];
|
|
89
|
+
token_cost?: number;
|
|
90
|
+
score?: number;
|
|
91
|
+
prev_residency?: SkillResidency;
|
|
92
|
+
timestamp: number;
|
|
93
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Session } from "./session.js";
|
|
2
|
+
export type SlashCommandAction = "none" | "exit" | "refresh_status";
|
|
3
|
+
/** toast = ephemeral feedback below input; transcript = scrollback (default). */
|
|
4
|
+
export type SlashCommandDisplay = "transcript" | "toast";
|
|
5
|
+
export interface SlashCommandResult {
|
|
6
|
+
action: SlashCommandAction;
|
|
7
|
+
lines: string[];
|
|
8
|
+
display?: SlashCommandDisplay;
|
|
9
|
+
}
|
|
10
|
+
export declare function executeSlashCommand(input: string, session: Session, handlers: {
|
|
11
|
+
setModel: (m?: string) => void;
|
|
12
|
+
setThinking: (v: boolean) => void;
|
|
13
|
+
getThinking: () => boolean;
|
|
14
|
+
}): Promise<SlashCommandResult>;
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { EVENT_LOG_FILENAME, migrateLegacyEventLog } from "./event-log.js";
|
|
4
|
+
import { getHelpLines as bannerHelpLines } from "./app-banner.js";
|
|
5
|
+
import { explainUnitScore } from "./context-engine/engine-compiler.js";
|
|
6
|
+
import { resolveContextEngineConfig } from "./context-engine/index.js";
|
|
7
|
+
export async function executeSlashCommand(input, session, handlers) {
|
|
8
|
+
const parts = input.split(/\s+/);
|
|
9
|
+
const cmd = parts[0].toLowerCase();
|
|
10
|
+
const lines = [];
|
|
11
|
+
const result = (action = "none", display = "transcript") => ({
|
|
12
|
+
action,
|
|
13
|
+
lines,
|
|
14
|
+
display,
|
|
15
|
+
});
|
|
16
|
+
switch (cmd) {
|
|
17
|
+
case "/exit":
|
|
18
|
+
case "/quit": {
|
|
19
|
+
lines.push("Ending session...");
|
|
20
|
+
return result("exit", "toast");
|
|
21
|
+
}
|
|
22
|
+
case "/state": {
|
|
23
|
+
const objects = session.stateGraph.list();
|
|
24
|
+
if (objects.length === 0) {
|
|
25
|
+
lines.push("No state objects yet this session. Use remember() or create_task() to start tracking.");
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
lines.push(`State objects (${objects.length}):`);
|
|
29
|
+
for (const o of objects) {
|
|
30
|
+
const tierIcon = o.tier === "active" ? "●" : o.tier === "soft" ? "○" : "·";
|
|
31
|
+
lines.push(` ${tierIcon} ${o.id} [${o.kind}] ${o.tier}: ${o.summary}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
case "/stats": {
|
|
37
|
+
const stats = session.getMemoryStats();
|
|
38
|
+
const startedAt = new Date(session.getStartedAt()).toISOString();
|
|
39
|
+
const uptimeSec = Math.floor(session.getUptimeMs() / 1000);
|
|
40
|
+
const persistentCount = session.getPersistentMemoryEntryCount();
|
|
41
|
+
lines.push("", "Session:");
|
|
42
|
+
lines.push(` Session ID: ${session.id}`);
|
|
43
|
+
lines.push(` Turns: ${session.getTurnCount()}`);
|
|
44
|
+
lines.push(` Started at: ${startedAt}`);
|
|
45
|
+
lines.push(` Uptime: ${uptimeSec}s`);
|
|
46
|
+
const inTokens = session.getInputTokens();
|
|
47
|
+
const outTokens = session.getOutputTokens();
|
|
48
|
+
if (inTokens > 0 || outTokens > 0) {
|
|
49
|
+
lines.push(` Tokens (this boot): ${inTokens.toLocaleString()} in / ${outTokens.toLocaleString()} out`);
|
|
50
|
+
}
|
|
51
|
+
lines.push("", "Working memory (this session):");
|
|
52
|
+
lines.push(` Total: ${stats.total}`);
|
|
53
|
+
lines.push(` Active: ${stats.active}`);
|
|
54
|
+
lines.push(` Soft: ${stats.soft}`);
|
|
55
|
+
lines.push(` Hard: ${stats.hard}`);
|
|
56
|
+
const kindParts = Object.entries(stats.byKind)
|
|
57
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
58
|
+
.map(([kind, count]) => `${kind}:${count}`);
|
|
59
|
+
lines.push(` By kind: ${kindParts.length ? kindParts.join(", ") : "(none)"}`);
|
|
60
|
+
if (session.memoryEnabled) {
|
|
61
|
+
lines.push("", "Persistent memory (SQLite):");
|
|
62
|
+
lines.push(` Total memories: ${persistentCount ?? "(unavailable)"}`);
|
|
63
|
+
lines.push(` Memory DB: ${session.getMemoryDbPath() ?? "(unknown)"}`);
|
|
64
|
+
}
|
|
65
|
+
if (session.isContextEngineEnabled() && session.contextEngine) {
|
|
66
|
+
const telemetry = session.contextEngine.finalizeTelemetry(session.getTurnCount());
|
|
67
|
+
lines.push("", "Context engine telemetry:");
|
|
68
|
+
lines.push(` Artifacts: ${telemetry.artifactsProduced}`);
|
|
69
|
+
lines.push(` Retrievals: ${telemetry.stats.artifactRetrievals} (${(telemetry.retrievalRate * 100).toFixed(1)}%)`);
|
|
70
|
+
lines.push(` Distiller savings: ${Math.round(telemetry.stats.totalDistillerSavings)} tokens`);
|
|
71
|
+
lines.push(` Pressure events: ${telemetry.stats.pressureEvents}`);
|
|
72
|
+
lines.push(` Compaction triggers: ${telemetry.stats.compactionTriggers}`);
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case "/digest": {
|
|
77
|
+
if (session.digest) {
|
|
78
|
+
lines.push("", session.digest);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
lines.push("No digest available.");
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case "/events": {
|
|
86
|
+
const events = session.eventLog.readLast(20);
|
|
87
|
+
if (events.length === 0) {
|
|
88
|
+
lines.push("No events yet.");
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
lines.push(``, `Last ${events.length} events:`);
|
|
92
|
+
for (const ev of events) {
|
|
93
|
+
const time = new Date(ev.timestamp).toISOString().slice(11, 19);
|
|
94
|
+
const summary = ev.kind === "user_message"
|
|
95
|
+
? `User: ${ev.payload.text?.slice(0, 60)}`
|
|
96
|
+
: ev.kind === "agent_message"
|
|
97
|
+
? `Agent: ${ev.payload.text?.slice(0, 60)}`
|
|
98
|
+
: ev.kind === "tool_call"
|
|
99
|
+
? `Tool: ${ev.payload.tool ?? "?"}`
|
|
100
|
+
: ev.kind === "tool_result"
|
|
101
|
+
? `Result: ${JSON.stringify(ev.payload.result)?.slice(0, 60)}`
|
|
102
|
+
: ev.kind === "context_action"
|
|
103
|
+
? `Context: ${ev.payload.action}`
|
|
104
|
+
: ev.kind === "system_note" &&
|
|
105
|
+
ev.payload.type === "error"
|
|
106
|
+
? `Error: ${String(ev.payload.message).slice(0, 60)}`
|
|
107
|
+
: ev.kind;
|
|
108
|
+
lines.push(` ${time} ${ev.kind.padEnd(16)} ${summary}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case "/recall": {
|
|
114
|
+
const query = parts.slice(1).join(" ");
|
|
115
|
+
if (!query || !session.memoryEnabled || !session.memoryStore) {
|
|
116
|
+
lines.push("Usage: /recall <query> (requires memory enabled)");
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const recallResult = await session.memoryStore.recall(query, { limit: 20 });
|
|
121
|
+
if (recallResult.entries.length === 0) {
|
|
122
|
+
lines.push("No results found.");
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
lines.push(``, `Recall results for "${query}":`);
|
|
126
|
+
for (const e of recallResult.entries) {
|
|
127
|
+
lines.push(` - [${e.kind}] ${e.content.slice(0, 100)} (match: ${e.match.toFixed(2)} | conf: ${e.confidence.toFixed(2)})`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
lines.push(`Recall error: ${err.message}`);
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case "/sessions": {
|
|
137
|
+
const logDir = session.config.session.log_dir;
|
|
138
|
+
if (!existsSync(logDir)) {
|
|
139
|
+
lines.push("No sessions directory found.");
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
const dirs = readdirSync(logDir, { withFileTypes: true })
|
|
143
|
+
.filter((d) => d.isDirectory())
|
|
144
|
+
.sort((a, b) => b.name.localeCompare(a.name))
|
|
145
|
+
.slice(0, 15);
|
|
146
|
+
if (dirs.length === 0) {
|
|
147
|
+
lines.push("No sessions found.");
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
lines.push("", "Recent sessions:");
|
|
151
|
+
for (const d of dirs) {
|
|
152
|
+
const sessionDir = join(logDir, d.name);
|
|
153
|
+
migrateLegacyEventLog(sessionDir);
|
|
154
|
+
const eventsPath = join(sessionDir, EVENT_LOG_FILENAME);
|
|
155
|
+
const metaPath = join(logDir, d.name, "meta.json");
|
|
156
|
+
let events = 0;
|
|
157
|
+
let cwdLabel = "?";
|
|
158
|
+
let time = "?";
|
|
159
|
+
try {
|
|
160
|
+
const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
161
|
+
cwdLabel = meta.cwd?.split("/").pop() ?? meta.cwd ?? "?";
|
|
162
|
+
time = new Date(meta.started_at).toISOString().slice(0, 16).replace("T", " ");
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
/* ignore */
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const content = readFileSync(eventsPath, "utf-8");
|
|
169
|
+
events = content.split("\n").filter(Boolean).length;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
/* ignore */
|
|
173
|
+
}
|
|
174
|
+
const marker = d.name === session.id ? " ← current" : "";
|
|
175
|
+
lines.push(` ${time} ${d.name.slice(0, 12)}... ${String(events).padStart(4)} events ${cwdLabel}${marker}`);
|
|
176
|
+
}
|
|
177
|
+
lines.push("", "Resume with: aria resume <session-id>");
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case "/model": {
|
|
181
|
+
const model = parts[1];
|
|
182
|
+
if (!model) {
|
|
183
|
+
lines.push(`Current model: ${session.getModelOverride() ?? session.config.llm.model}`);
|
|
184
|
+
lines.push("Usage: /model <provider/model> (e.g., /model openai/gpt-4o)");
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
const trimmed = model.trim();
|
|
188
|
+
handlers.setModel(trimmed);
|
|
189
|
+
session.setModelOverride(trimmed);
|
|
190
|
+
const contextWindow = await session.refreshModelContextWindow(trimmed);
|
|
191
|
+
session.eventLog.append({
|
|
192
|
+
kind: "system_note",
|
|
193
|
+
actor: "kernel",
|
|
194
|
+
payload: {
|
|
195
|
+
type: "model_override",
|
|
196
|
+
model: trimmed,
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
lines.push(`Model switched to: ${model} (${contextWindow.toLocaleString()} ctx)`);
|
|
200
|
+
return result("refresh_status", "toast");
|
|
201
|
+
}
|
|
202
|
+
case "/debug": {
|
|
203
|
+
session.debug = !session.debug;
|
|
204
|
+
lines.push(`Debug mode: ${session.debug ? "ON" : "OFF"}` +
|
|
205
|
+
` (prompts saved to ${session.promptDir}` +
|
|
206
|
+
`${session.isContextEngineEnabled() ? ", scores to scores.jsonl" : ""})`);
|
|
207
|
+
return result("refresh_status", "toast");
|
|
208
|
+
}
|
|
209
|
+
case "/thinking": {
|
|
210
|
+
const arg = (parts[1] ?? "").toLowerCase();
|
|
211
|
+
if (!arg) {
|
|
212
|
+
lines.push(`Thinking: ${handlers.getThinking() ? "ON" : "OFF"}`);
|
|
213
|
+
lines.push("Usage: /thinking <on|off>");
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
if (arg === "on") {
|
|
217
|
+
handlers.setThinking(true);
|
|
218
|
+
lines.push("Thinking enabled.");
|
|
219
|
+
}
|
|
220
|
+
else if (arg === "off") {
|
|
221
|
+
handlers.setThinking(false);
|
|
222
|
+
lines.push("Thinking disabled.");
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
lines.push("Usage: /thinking <on|off>");
|
|
226
|
+
}
|
|
227
|
+
return result("refresh_status", "toast");
|
|
228
|
+
}
|
|
229
|
+
case "/incognito": {
|
|
230
|
+
const arg = (parts[1] ?? "").toLowerCase();
|
|
231
|
+
if (!arg) {
|
|
232
|
+
lines.push(`Incognito: ${session.isIncognito() ? "ON" : "OFF"}`);
|
|
233
|
+
lines.push("Usage: /incognito <on|off>");
|
|
234
|
+
return result("none", "toast");
|
|
235
|
+
}
|
|
236
|
+
if (arg === "on") {
|
|
237
|
+
await session.setIncognito(true);
|
|
238
|
+
lines.push("Incognito enabled — cross-session memory disabled.");
|
|
239
|
+
}
|
|
240
|
+
else if (arg === "off") {
|
|
241
|
+
await session.setIncognito(false);
|
|
242
|
+
lines.push(session.memoryEnabled
|
|
243
|
+
? "Incognito disabled — cross-session memory enabled."
|
|
244
|
+
: "Incognito disabled — memory remains unavailable (check config.memory.enabled).");
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
lines.push("Usage: /incognito <on|off>");
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
return result("refresh_status", "toast");
|
|
251
|
+
}
|
|
252
|
+
case "/clear":
|
|
253
|
+
case "/new": {
|
|
254
|
+
session.clearState();
|
|
255
|
+
session.eventLog.append({
|
|
256
|
+
kind: "system_note",
|
|
257
|
+
actor: "kernel",
|
|
258
|
+
payload: {
|
|
259
|
+
type: "state_reset",
|
|
260
|
+
cleared: "all",
|
|
261
|
+
command: cmd,
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
lines.push("State cleared. Starting fresh.");
|
|
265
|
+
return result("none", "toast");
|
|
266
|
+
}
|
|
267
|
+
case "/why": {
|
|
268
|
+
const unitId = parts.slice(1).join(" ").trim();
|
|
269
|
+
if (!unitId) {
|
|
270
|
+
lines.push("Usage: /why <unit-id> (e.g. /why art_abc123 or /why turn_3)");
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
if (!session.isContextEngineEnabled()) {
|
|
274
|
+
lines.push("Context engine is disabled. Enable it to use /why.");
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
const record = session.getCompileScoreRecord(unitId);
|
|
278
|
+
if (!record) {
|
|
279
|
+
lines.push(`No score record for "${unitId}" on the last compile.`);
|
|
280
|
+
lines.push("Run a turn with context_engine.enabled=true and debug mode for scores.jsonl.");
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
const engineConfig = resolveContextEngineConfig(session.config);
|
|
284
|
+
const bandBudget = record.band <= 4 ? 3000 : 2000;
|
|
285
|
+
const bandUsed = session
|
|
286
|
+
.getLastCompileScoreRecords()
|
|
287
|
+
.filter((r) => r.band === record.band && r.included)
|
|
288
|
+
.reduce((sum, r) => sum + r.tokens, 0);
|
|
289
|
+
lines.push(...explainUnitScore(unitId, session.getLastCompileScoreRecords(), session.getTurnCount(), session.getLastUserInput(), engineConfig.scoring, bandBudget, bandUsed));
|
|
290
|
+
lines.push(`Pressure: ${(session.getLastPressureRatio() * 100).toFixed(1)}% (${session.getLastPressureMode()})`);
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
case "/help": {
|
|
294
|
+
return { action: "none", lines: bannerHelpLines() };
|
|
295
|
+
}
|
|
296
|
+
default:
|
|
297
|
+
lines.push(`Unknown command: ${cmd}. Type /help for available commands.`);
|
|
298
|
+
return result("none", "toast");
|
|
299
|
+
}
|
|
300
|
+
return result();
|
|
301
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { StateObject, StateObjectKind, StateTier, StatePayload } from "./types.js";
|
|
2
|
+
export declare class StateGraph {
|
|
3
|
+
private objects;
|
|
4
|
+
private touchedTurn;
|
|
5
|
+
private turnCount;
|
|
6
|
+
clear(): void;
|
|
7
|
+
create(kind: StateObjectKind, payload: StatePayload): StateObject;
|
|
8
|
+
update(id: string, patch: Partial<StatePayload>): StateObject | null;
|
|
9
|
+
setTier(id: string, tier: StateTier): boolean;
|
|
10
|
+
retractObject(id: string): boolean;
|
|
11
|
+
get(id: string): StateObject | undefined;
|
|
12
|
+
/** All active objects; focused object first, then by created asc, id asc. */
|
|
13
|
+
getActive(): StateObject[];
|
|
14
|
+
/** Pin one task/object as focused; clears focus on all others. */
|
|
15
|
+
setFocus(id: string): boolean;
|
|
16
|
+
/** All soft + hard objects, sorted by updated desc. */
|
|
17
|
+
getPeripheral(): StateObject[];
|
|
18
|
+
/** All objects with summary. */
|
|
19
|
+
list(): Array<{
|
|
20
|
+
id: string;
|
|
21
|
+
kind: StateObjectKind;
|
|
22
|
+
tier: StateTier;
|
|
23
|
+
summary: string;
|
|
24
|
+
}>;
|
|
25
|
+
/** Full snapshot including retracted objects — for event logging and audit. */
|
|
26
|
+
snapshot(): StateObject[];
|
|
27
|
+
getTouchedTurn(id: string): number;
|
|
28
|
+
incrementTurn(): void;
|
|
29
|
+
getTurnCount(): number;
|
|
30
|
+
/**
|
|
31
|
+
* Auto-promote peripheral objects whose payload matches keywords in the query.
|
|
32
|
+
* Returns IDs of objects that were hydrated.
|
|
33
|
+
*/
|
|
34
|
+
autoHydrate(query: string): string[];
|
|
35
|
+
/** Rebuild state from context_action events during resume. */
|
|
36
|
+
replayAction(payload: Record<string, unknown>): void;
|
|
37
|
+
}
|
|
38
|
+
export declare function summarizePayloadFn(obj: StateObject): string;
|