omegon 0.6.3 → 0.6.4
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 +12 -10
- package/bin/omegon.mjs +40 -0
- package/bin/pi.mjs +5 -26
- package/extensions/00-secrets/index.ts +146 -39
- package/extensions/01-auth/auth.ts +1 -1
- package/extensions/01-auth/index.ts +3 -3
- package/extensions/auto-compact.ts +1 -1
- package/extensions/bootstrap/deps.ts +42 -0
- package/extensions/bootstrap/index.ts +326 -110
- package/extensions/chronos/index.ts +1 -1
- package/extensions/cleave/dispatcher.ts +6 -6
- package/extensions/cleave/index.ts +6 -6
- package/extensions/cleave/planner.ts +1 -1
- package/extensions/cleave/worktree.ts +1 -1
- package/extensions/core-renderers.ts +24 -84
- package/extensions/dashboard/footer.ts +184 -40
- package/extensions/dashboard/git.ts +2 -2
- package/extensions/dashboard/index.ts +4 -4
- package/extensions/dashboard/overlay-data.ts +5 -5
- package/extensions/dashboard/overlay.ts +5 -5
- package/extensions/dashboard/render-utils.ts +1 -1
- package/extensions/dashboard/types.ts +15 -0
- package/extensions/defaults.ts +4 -12
- package/extensions/design-tree/dashboard-state.ts +6 -6
- package/extensions/design-tree/design-card.ts +3 -3
- package/extensions/design-tree/index.ts +64 -44
- package/extensions/design-tree/types.ts +4 -2
- package/extensions/distill.ts +1 -1
- package/extensions/effort/index.ts +137 -10
- package/extensions/lib/model-routing.ts +304 -32
- package/extensions/lib/operator-fallback.ts +1 -1
- package/extensions/lib/operator-profile.ts +1 -1
- package/extensions/lib/provider-env.ts +163 -0
- package/extensions/{sci-ui.ts → lib/sci-ui.ts} +119 -2
- package/extensions/{shared-state.ts → lib/shared-state.ts} +13 -9
- package/extensions/lib/slash-command-bridge.ts +1 -1
- package/extensions/{types.d.ts → lib/types.d.ts} +3 -3
- package/extensions/local-inference/index.ts +1 -1
- package/extensions/mcp-bridge/index.ts +1 -1
- package/extensions/model-budget.ts +10 -10
- package/extensions/offline-driver.ts +11 -4
- package/extensions/openspec/archive-gate.ts +1 -1
- package/extensions/openspec/branch-cleanup.ts +1 -1
- package/extensions/openspec/dashboard-state.ts +3 -3
- package/extensions/openspec/index.ts +5 -5
- package/extensions/project-memory/factstore.ts +5 -11
- package/extensions/project-memory/index.ts +48 -34
- package/extensions/project-memory/package.json +1 -1
- package/extensions/project-memory/sci-renderers.ts +1 -1
- package/extensions/render/index.ts +1 -1
- package/extensions/session-log.ts +1 -1
- package/extensions/spinner-verbs.ts +1 -1
- package/extensions/style.ts +1 -1
- package/extensions/terminal-title.ts +3 -3
- package/extensions/tool-profile/index.ts +1 -1
- package/extensions/vault/index.ts +1 -1
- package/extensions/version-check.ts +13 -9
- package/extensions/view/index.ts +4 -4
- package/extensions/web-search/index.ts +5 -2
- package/extensions/web-ui/index.ts +1 -1
- package/extensions/web-ui/state.ts +1 -1
- package/package.json +8 -7
- package/scripts/preinstall.sh +19 -3
- package/scripts/publish-pi-mono.sh +92 -0
- package/skills/pi-extensions/SKILL.md +2 -2
- package/skills/pi-tui/SKILL.md +17 -17
- package/skills/typescript/SKILL.md +1 -1
- package/themes/alpharius.json +7 -6
- /package/extensions/{debug.ts → lib/debug.ts} +0 -0
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* NOTE: All classes use explicit field declarations (not constructor parameter
|
|
15
15
|
* properties) to remain compatible with Node.js strip-only TypeScript mode.
|
|
16
16
|
*/
|
|
17
|
-
import { truncateToWidth, visibleWidth } from "@
|
|
18
|
-
import type { Theme } from "@
|
|
17
|
+
import { truncateToWidth, visibleWidth } from "@styrene-lab/pi-tui";
|
|
18
|
+
import type { Theme } from "@styrene-lab/pi-coding-agent";
|
|
19
19
|
|
|
20
20
|
export interface SciComponent {
|
|
21
21
|
render(width: number): string[];
|
|
@@ -302,3 +302,120 @@ export function sciExpanded(lines: string[], footer: string, theme: Theme): SciE
|
|
|
302
302
|
export function sciBanner(glyph: string, label: string, lines: string[], theme: Theme): SciBanner {
|
|
303
303
|
return new SciBanner(glyph, label, lines, theme);
|
|
304
304
|
}
|
|
305
|
+
|
|
306
|
+
// ─── SciExitCard ─────────────────────────────────────────────────────────
|
|
307
|
+
//
|
|
308
|
+
// ── ⏛ session:end ──────────────────────────────────────────────────
|
|
309
|
+
// │ main · clean ◈ 80 nodes · 69 implemented
|
|
310
|
+
// │ 📋 2 active changes 🧠 1462 facts (+3) · 94% indexed
|
|
311
|
+
// ╰──────────────────────────────────────────────────────────────────
|
|
312
|
+
|
|
313
|
+
export interface ExitCardData {
|
|
314
|
+
branch?: string;
|
|
315
|
+
dirtyCount?: number;
|
|
316
|
+
designNodes?: number;
|
|
317
|
+
designImplemented?: number;
|
|
318
|
+
designDecided?: number;
|
|
319
|
+
designExploring?: number;
|
|
320
|
+
openspecActive?: string[];
|
|
321
|
+
factCount: number;
|
|
322
|
+
factDelta: number;
|
|
323
|
+
embeddingPct?: number;
|
|
324
|
+
embeddingAvailable: boolean;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export class SciExitCard implements SciComponent {
|
|
328
|
+
data: ExitCardData;
|
|
329
|
+
theme: Theme;
|
|
330
|
+
|
|
331
|
+
constructor(data: ExitCardData, theme: Theme) {
|
|
332
|
+
this.data = data;
|
|
333
|
+
this.theme = theme;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
render(width: number): string[] {
|
|
337
|
+
const th = this.theme;
|
|
338
|
+
const d = this.data;
|
|
339
|
+
const innerW = Math.max(1, width - 4);
|
|
340
|
+
|
|
341
|
+
// Header
|
|
342
|
+
const label = ` ${th.fg("accent", "⏛")} ${th.fg("muted", "session:end")} `;
|
|
343
|
+
const labelVw = visibleWidth(label);
|
|
344
|
+
const headerFill = Math.max(0, width - labelVw - 2);
|
|
345
|
+
const header = th.fg("dim", "──") + label + th.fg("dim", "─".repeat(headerFill));
|
|
346
|
+
const pipe = th.fg("dim", " │");
|
|
347
|
+
|
|
348
|
+
const lines: string[] = [truncateToWidth(header, width)];
|
|
349
|
+
|
|
350
|
+
// Row 1: git + design tree (two columns)
|
|
351
|
+
const gitPart = d.branch
|
|
352
|
+
? th.fg("success", d.branch) +
|
|
353
|
+
th.fg("dim", " · ") +
|
|
354
|
+
(d.dirtyCount && d.dirtyCount > 0
|
|
355
|
+
? th.fg("warning", `${d.dirtyCount} dirty`)
|
|
356
|
+
: th.fg("muted", "clean"))
|
|
357
|
+
: null;
|
|
358
|
+
|
|
359
|
+
const dtPart = d.designNodes && d.designNodes > 0
|
|
360
|
+
? th.fg("accent", "◈") + " " +
|
|
361
|
+
th.fg("muted", `${d.designNodes} nodes`) +
|
|
362
|
+
th.fg("dim", " · ") +
|
|
363
|
+
th.fg("success", `${d.designImplemented ?? 0}✓`) +
|
|
364
|
+
(d.designDecided ? th.fg("dim", " · ") + th.fg("muted", `${d.designDecided}●`) : "") +
|
|
365
|
+
(d.designExploring ? th.fg("dim", " · ") + th.fg("accent", `${d.designExploring}◐`) : "")
|
|
366
|
+
: null;
|
|
367
|
+
|
|
368
|
+
if (gitPart && dtPart) {
|
|
369
|
+
const gitVw = visibleWidth(gitPart);
|
|
370
|
+
const dtVw = visibleWidth(dtPart);
|
|
371
|
+
const gap = Math.max(2, innerW - gitVw - dtVw);
|
|
372
|
+
lines.push(truncateToWidth(pipe + " " + gitPart + " ".repeat(gap) + dtPart, width));
|
|
373
|
+
} else if (gitPart) {
|
|
374
|
+
lines.push(truncateToWidth(pipe + " " + gitPart, width));
|
|
375
|
+
} else if (dtPart) {
|
|
376
|
+
lines.push(truncateToWidth(pipe + " " + dtPart, width));
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Row 2: openspec + memory (two columns)
|
|
380
|
+
const osPart = d.openspecActive && d.openspecActive.length > 0
|
|
381
|
+
? th.fg("muted", `${d.openspecActive.length} active`) +
|
|
382
|
+
th.fg("dim", " ─ ") +
|
|
383
|
+
th.fg("muted", d.openspecActive.slice(0, 3).join(", ")) +
|
|
384
|
+
(d.openspecActive.length > 3 ? th.fg("dim", `…+${d.openspecActive.length - 3}`) : "")
|
|
385
|
+
: null;
|
|
386
|
+
|
|
387
|
+
const deltaStr = d.factDelta > 0
|
|
388
|
+
? th.fg("success", ` +${d.factDelta}`)
|
|
389
|
+
: d.factDelta < 0
|
|
390
|
+
? th.fg("warning", ` ${d.factDelta}`)
|
|
391
|
+
: "";
|
|
392
|
+
const idxStr = d.embeddingAvailable && d.embeddingPct !== undefined
|
|
393
|
+
? th.fg("dim", " · ") + th.fg("muted", `${d.embeddingPct}% indexed`)
|
|
394
|
+
: !d.embeddingAvailable
|
|
395
|
+
? th.fg("dim", " · ") + th.fg("muted", "semantic off")
|
|
396
|
+
: "";
|
|
397
|
+
const memPart = th.fg("accent", "⌗") + " " +
|
|
398
|
+
th.fg("muted", `${d.factCount} facts`) + deltaStr + idxStr;
|
|
399
|
+
|
|
400
|
+
if (osPart) {
|
|
401
|
+
const osVw = visibleWidth(osPart);
|
|
402
|
+
const memVw = visibleWidth(memPart);
|
|
403
|
+
const gap = Math.max(2, innerW - osVw - memVw);
|
|
404
|
+
lines.push(truncateToWidth(pipe + " " + osPart + " ".repeat(gap) + memPart, width));
|
|
405
|
+
} else {
|
|
406
|
+
lines.push(truncateToWidth(pipe + " " + memPart, width));
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Footer rule
|
|
410
|
+
const footerFill = Math.max(0, width - 5);
|
|
411
|
+
lines.push(th.fg("dim", " ╰" + "─".repeat(footerFill)));
|
|
412
|
+
|
|
413
|
+
return lines;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
invalidate(): void {}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export function sciExitCard(data: ExitCardData, theme: Theme): SciExitCard {
|
|
420
|
+
return new SciExitCard(data, theme);
|
|
421
|
+
}
|
|
@@ -12,13 +12,13 @@ import type {
|
|
|
12
12
|
OpenSpecDashboardState,
|
|
13
13
|
CleaveState,
|
|
14
14
|
RecoveryDashboardState,
|
|
15
|
-
} from "
|
|
15
|
+
} from "../dashboard/types.ts";
|
|
16
16
|
|
|
17
|
-
import type { EffortState } from "
|
|
18
|
-
import type { ProviderRoutingPolicy } from "./
|
|
19
|
-
import type { MemoryInjectionMetrics } from "
|
|
20
|
-
import type { LifecycleMemoryMessage } from "
|
|
21
|
-
import { getDefaultPolicy } from "./
|
|
17
|
+
import type { EffortState } from "../effort/types.ts";
|
|
18
|
+
import type { ProviderRoutingPolicy } from "./model-routing.ts";
|
|
19
|
+
import type { MemoryInjectionMetrics } from "../project-memory/injection-metrics.ts";
|
|
20
|
+
import type { LifecycleMemoryMessage } from "../project-memory/types.ts";
|
|
21
|
+
import { getDefaultPolicy } from "./model-routing.ts";
|
|
22
22
|
|
|
23
23
|
export type RecoveryFailureClassification =
|
|
24
24
|
| "transient_server_error"
|
|
@@ -68,10 +68,10 @@ export type {
|
|
|
68
68
|
CleaveStatus,
|
|
69
69
|
DashboardMode,
|
|
70
70
|
DashboardState,
|
|
71
|
-
} from "
|
|
71
|
+
} from "../dashboard/types.ts";
|
|
72
72
|
|
|
73
73
|
// Re-export routing types for consumer convenience
|
|
74
|
-
export type { ProviderRoutingPolicy, ResolvedTierModel, ModelTier, ProviderName } from "./
|
|
74
|
+
export type { ProviderRoutingPolicy, ResolvedTierModel, ModelTier, ProviderName } from "./model-routing.ts";
|
|
75
75
|
|
|
76
76
|
// Re-export effort types for consumer convenience
|
|
77
77
|
export type {
|
|
@@ -81,7 +81,7 @@ export type {
|
|
|
81
81
|
EffortModelTier,
|
|
82
82
|
EffortName,
|
|
83
83
|
ThinkingLevel,
|
|
84
|
-
} from "
|
|
84
|
+
} from "../effort/types.ts";
|
|
85
85
|
|
|
86
86
|
/** Event channel fired by producers after writing dashboard state. */
|
|
87
87
|
export const DASHBOARD_UPDATE_EVENT = "dashboard:update" as const;
|
|
@@ -131,6 +131,10 @@ interface SharedState {
|
|
|
131
131
|
|
|
132
132
|
/** Per-request retry ledger for bounded recovery decisions across core and extension-driven retries. */
|
|
133
133
|
recoveryRetryCounts?: Record<string, number>;
|
|
134
|
+
|
|
135
|
+
/** Set by bootstrap when first-run is detected. Other extensions should suppress
|
|
136
|
+
* redundant "no providers" warnings when this is true — bootstrap handles guidance. */
|
|
137
|
+
bootstrapPending?: boolean;
|
|
134
138
|
}
|
|
135
139
|
|
|
136
140
|
// Initialize once on first import, reuse thereafter via global symbol.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import type { Static } from "@sinclair/typebox";
|
|
3
|
-
import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext, RegisteredCommand, ToolDefinition } from "@
|
|
3
|
+
import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext, RegisteredCommand, ToolDefinition } from "@styrene-lab/pi-coding-agent";
|
|
4
4
|
|
|
5
5
|
export const SIDE_EFFECT_CLASSES = [
|
|
6
6
|
"read",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import "@
|
|
2
|
-
import type { SlashCommandBridgeMetadata, SlashCommandBridgeResult, SlashCommandExecutionContext } from "./
|
|
1
|
+
import "@styrene-lab/pi-coding-agent";
|
|
2
|
+
import type { SlashCommandBridgeMetadata, SlashCommandBridgeResult, SlashCommandExecutionContext } from "./slash-command-bridge.js";
|
|
3
3
|
|
|
4
|
-
declare module "@
|
|
4
|
+
declare module "@styrene-lab/pi-coding-agent" {
|
|
5
5
|
interface RegisteredCommand {
|
|
6
6
|
bridge?: SlashCommandBridgeMetadata;
|
|
7
7
|
structuredExecutor?: (args: string, ctx: SlashCommandExecutionContext) => Promise<SlashCommandBridgeResult>;
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { execSync, spawn, type ChildProcess } from "node:child_process";
|
|
24
|
-
import type { ExtensionAPI } from "@
|
|
24
|
+
import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
|
|
25
25
|
import { Type } from "@sinclair/typebox";
|
|
26
26
|
import { StringEnum } from "../lib/typebox-helpers";
|
|
27
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @secret GITHUB_TOKEN "GitHub personal access token for MCP server auth (Scribe, etc.)"
|
|
2
2
|
|
|
3
|
-
import type { ExtensionAPI } from "@
|
|
3
|
+
import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
|
|
4
4
|
import { Type } from "@sinclair/typebox";
|
|
5
5
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
6
6
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { createHash } from "node:crypto";
|
|
21
|
-
import type { ExtensionAPI, ExtensionContext } from "@
|
|
22
|
-
import type { ImageContent, Model, TextContent } from "@
|
|
23
|
-
import { DASHBOARD_UPDATE_EVENT, sharedState } from "./shared-state.ts";
|
|
24
|
-
import type { RecoveryEvent, RecoveryFailureClassification } from "./shared-state.ts";
|
|
21
|
+
import type { ExtensionAPI, ExtensionContext } from "@styrene-lab/pi-coding-agent";
|
|
22
|
+
import type { ImageContent, Model, TextContent } from "@styrene-lab/pi-ai";
|
|
23
|
+
import { DASHBOARD_UPDATE_EVENT, sharedState } from "./lib/shared-state.ts";
|
|
24
|
+
import type { RecoveryEvent, RecoveryFailureClassification } from "./lib/shared-state.ts";
|
|
25
25
|
import type { RecoveryAction, RecoveryCooldownSummary, RecoveryDashboardState, RecoveryTarget } from "./dashboard/types.ts";
|
|
26
26
|
import { tierConfig } from "./effort/tiers.ts";
|
|
27
27
|
import type { EffortLevel } from "./effort/types.ts";
|
|
28
|
-
import { clampThinkingLevel, classifyUpstreamFailure, getDefaultPolicy, getTierDisplayLabel, resolveTier, type CapabilityRuntimeState, type ModelTier, type RegistryModel, type UpstreamFailureClassification } from "./lib/model-routing.ts";
|
|
28
|
+
import { clampThinkingLevel, classifyUpstreamFailure, getDefaultPolicy, getViableModels, getTierDisplayLabel, resolveTier, type CapabilityRuntimeState, type ModelTier, type RegistryModel, type UpstreamFailureClassification } from "./lib/model-routing.ts";
|
|
29
29
|
import { writeLastUsedModel } from "./lib/model-preferences.ts";
|
|
30
30
|
import { loadOperatorRuntimeState, readOperatorProfile, toCapabilityProfile, toCapabilityRuntimeState } from "./lib/operator-profile.ts";
|
|
31
31
|
import { buildFallbackGuidance, explainTierResolutionFailure, planRecoveryForModel, recordTransientFailureForModel, type RecoveryPlan } from "./lib/operator-fallback.ts";
|
|
@@ -420,7 +420,7 @@ async function applyRecoveryPlan(
|
|
|
420
420
|
}
|
|
421
421
|
|
|
422
422
|
async function switchTo(tier: TierName, pi: ExtensionAPI, ctx: ExtensionContext): Promise<RegistryModel | null> {
|
|
423
|
-
const all = ctx.modelRegistry
|
|
423
|
+
const all = getViableModels(ctx.modelRegistry);
|
|
424
424
|
const { policy, profile, runtimeState } = getResolverInputs(ctx);
|
|
425
425
|
const resolved = resolveTier(tier, all, policy, runtimeState, profile);
|
|
426
426
|
if (!resolved) return null;
|
|
@@ -443,7 +443,7 @@ function currentTierName(ctx: ExtensionContext): TierName | null {
|
|
|
443
443
|
const model = ctx.model;
|
|
444
444
|
if (!model) return null;
|
|
445
445
|
// Resolve the current model against the registry using the shared resolver
|
|
446
|
-
const all = ctx.modelRegistry
|
|
446
|
+
const all = getViableModels(ctx.modelRegistry);
|
|
447
447
|
const { policy, profile, runtimeState } = getResolverInputs(ctx);
|
|
448
448
|
for (const tier of ["gloriana", "victory", "retribution", "local"] as TierName[]) {
|
|
449
449
|
const resolved = resolveTier(tier, all, policy, runtimeState, profile);
|
|
@@ -498,7 +498,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
498
498
|
|
|
499
499
|
const persistedRuntimeState = recordTransientFailureForModel(ctx.cwd, ctx.model, errorMessage);
|
|
500
500
|
const { policy, profile } = getResolverInputs(ctx);
|
|
501
|
-
const models = ctx.modelRegistry
|
|
501
|
+
const models = getViableModels(ctx.modelRegistry);
|
|
502
502
|
const runtimeState = persistedRuntimeState ?? toCapabilityRuntimeState(loadOperatorRuntimeState(ctx.cwd));
|
|
503
503
|
const plan = planRecoveryForModel(ctx.model, errorMessage, models, policy, profile, runtimeState ?? {}, Date.now());
|
|
504
504
|
const guidance = buildFallbackGuidance(ctx.model, models, policy, profile, runtimeState ?? {}, Date.now());
|
|
@@ -659,7 +659,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
659
659
|
const { policy, profile, runtimeState } = getResolverInputs(ctx);
|
|
660
660
|
const failure = explainTierResolutionFailure(
|
|
661
661
|
tier,
|
|
662
|
-
ctx.modelRegistry
|
|
662
|
+
getViableModels(ctx.modelRegistry),
|
|
663
663
|
policy,
|
|
664
664
|
profile,
|
|
665
665
|
runtimeState,
|
|
@@ -739,7 +739,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
739
739
|
const { policy, profile, runtimeState } = getResolverInputs(ctx);
|
|
740
740
|
const failure = explainTierResolutionFailure(
|
|
741
741
|
tier,
|
|
742
|
-
ctx.modelRegistry
|
|
742
|
+
getViableModels(ctx.modelRegistry),
|
|
743
743
|
policy,
|
|
744
744
|
profile,
|
|
745
745
|
runtimeState,
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
// @config LOCAL_INFERENCE_URL "Ollama / OpenAI-compatible inference server URL" [default: http://localhost:11434]
|
|
2
2
|
|
|
3
|
-
import type { ExtensionAPI } from "@
|
|
4
|
-
import { Text } from "@
|
|
3
|
+
import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
|
|
4
|
+
import { Text } from "@styrene-lab/pi-tui";
|
|
5
5
|
import { Type } from "@sinclair/typebox";
|
|
6
6
|
import {
|
|
7
7
|
KNOWN_MODELS,
|
|
8
8
|
PREFERRED_ORDER,
|
|
9
9
|
PREFERRED_ORDER_CODE,
|
|
10
10
|
} from "./lib/local-models.ts";
|
|
11
|
+
import { filterDeprecated, type RegistryModel } from "./lib/model-routing.ts";
|
|
11
12
|
|
|
12
13
|
// Re-export so existing importers (effort, cleave) continue to work.
|
|
13
14
|
export { PREFERRED_ORDER, PREFERRED_ORDER_CODE };
|
|
@@ -204,7 +205,7 @@ export async function restoreCloudDriver(
|
|
|
204
205
|
|
|
205
206
|
// If no saved model, find the best available gloriana-class model by prefix
|
|
206
207
|
if (!modelId) {
|
|
207
|
-
const all = ctx.modelRegistry.
|
|
208
|
+
const all = filterDeprecated(ctx.modelRegistry.getAvailable() as unknown as RegistryModel[]);
|
|
208
209
|
const topTier = all
|
|
209
210
|
.filter((m: any) => m.provider === "anthropic" && m.id.startsWith("claude-opus"))
|
|
210
211
|
.sort((a: any, b: any) => b.id.localeCompare(a.id));
|
|
@@ -284,7 +285,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
284
285
|
parts.push("🏠 Ollama: not running");
|
|
285
286
|
}
|
|
286
287
|
|
|
287
|
-
|
|
288
|
+
// Suppress noisy status during first-run — bootstrap handles guidance
|
|
289
|
+
// Suppress the "unreachable" warning during first-run (bootstrap handles it),
|
|
290
|
+
// but always show success status so the operator sees their provider state.
|
|
291
|
+
const { sharedState } = await import("./lib/shared-state.ts");
|
|
292
|
+
if (anthropicOk || !sharedState.bootstrapPending) {
|
|
293
|
+
ctx.ui.notify(parts.join(" | "), anthropicOk ? "info" : "warning");
|
|
294
|
+
}
|
|
288
295
|
|
|
289
296
|
// Save starting cloud model
|
|
290
297
|
const current = ctx.model;
|
|
@@ -154,7 +154,7 @@ export function transitionDesignNodesOnArchive(cwd: string, changeName: string):
|
|
|
154
154
|
const transitioned: string[] = [];
|
|
155
155
|
|
|
156
156
|
for (const node of resolveBoundDesignNodes(cwd, changeName)) {
|
|
157
|
-
const transitionable = node.status === "implementing" || node.status === "decided";
|
|
157
|
+
const transitionable = node.status === "implementing" || node.status === "decided" || node.status === "resolved";
|
|
158
158
|
if (!transitionable) continue;
|
|
159
159
|
const sections = getNodeSections(node);
|
|
160
160
|
writeNodeDocument({ ...node, status: "implemented" }, sections);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
|
|
2
2
|
|
|
3
|
-
import { sharedState, DASHBOARD_UPDATE_EVENT } from "../shared-state.ts";
|
|
4
|
-
import { debug } from "../debug.ts";
|
|
3
|
+
import { sharedState, DASHBOARD_UPDATE_EVENT } from "../lib/shared-state.ts";
|
|
4
|
+
import { debug } from "../lib/debug.ts";
|
|
5
5
|
import { listChanges } from "./spec.ts";
|
|
6
6
|
import { buildLifecycleSummary } from "./lifecycle.ts";
|
|
7
7
|
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
* openspec_manage — Agent-callable change lifecycle operations
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import type { ExtensionAPI, ExtensionContext } from "@
|
|
21
|
+
import type { ExtensionAPI, ExtensionContext } from "@styrene-lab/pi-coding-agent";
|
|
22
22
|
import { Type } from "@sinclair/typebox";
|
|
23
23
|
import { StringEnum } from "../lib/typebox-helpers.ts";
|
|
24
|
-
import { Text } from "@
|
|
25
|
-
import { sciCall, sciLoading, sciOk, sciErr, sciExpanded } from "../sci-ui.ts";
|
|
26
|
-
import { sciBanner } from "../sci-ui.ts";
|
|
24
|
+
import { Text } from "@styrene-lab/pi-tui";
|
|
25
|
+
import { sciCall, sciLoading, sciOk, sciErr, sciExpanded } from "../lib/sci-ui.ts";
|
|
26
|
+
import { sciBanner } from "../lib/sci-ui.ts";
|
|
27
27
|
import * as fs from "node:fs";
|
|
28
28
|
import * as path from "node:path";
|
|
29
29
|
import { getSharedBridge, buildSlashCommandResult, type BridgedSlashCommand, type SlashCommandExecutionContext } from "../lib/slash-command-bridge.ts";
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
import { scanDesignDocs } from "../design-tree/tree.ts";
|
|
64
64
|
import { emitDesignTreeState } from "../design-tree/dashboard-state.ts";
|
|
65
65
|
import { emitArchiveCandidates, emitReconcileCandidates } from "./lifecycle-emitter.ts";
|
|
66
|
-
import { sharedState } from "../shared-state.ts";
|
|
66
|
+
import { sharedState } from "../lib/shared-state.ts";
|
|
67
67
|
|
|
68
68
|
interface AssessmentState {
|
|
69
69
|
record: AssessmentRecord | null;
|
|
@@ -1428,10 +1428,6 @@ export class FactStore {
|
|
|
1428
1428
|
created_at: fact.created_at,
|
|
1429
1429
|
source: fact.source,
|
|
1430
1430
|
content_hash: fact.content_hash,
|
|
1431
|
-
confidence: fact.confidence,
|
|
1432
|
-
last_reinforced: fact.last_reinforced,
|
|
1433
|
-
reinforcement_count: fact.reinforcement_count,
|
|
1434
|
-
decay_rate: fact.decay_rate,
|
|
1435
1431
|
supersedes: fact.supersedes,
|
|
1436
1432
|
}));
|
|
1437
1433
|
}
|
|
@@ -1449,10 +1445,6 @@ export class FactStore {
|
|
|
1449
1445
|
target_fact_id: edge.target_fact_id,
|
|
1450
1446
|
relation: edge.relation,
|
|
1451
1447
|
description: edge.description,
|
|
1452
|
-
confidence: edge.confidence,
|
|
1453
|
-
last_reinforced: edge.last_reinforced,
|
|
1454
|
-
reinforcement_count: edge.reinforcement_count,
|
|
1455
|
-
decay_rate: edge.decay_rate,
|
|
1456
1448
|
source_mind: edge.source_mind,
|
|
1457
1449
|
target_mind: edge.target_mind,
|
|
1458
1450
|
}));
|
|
@@ -1497,9 +1489,11 @@ export class FactStore {
|
|
|
1497
1489
|
// Map from imported fact ID → local fact ID (for edge remapping)
|
|
1498
1490
|
const factIdMap = new Map<string, string>();
|
|
1499
1491
|
|
|
1500
|
-
// Pre-dedup: merge=union in git can produce multiple lines with the same id
|
|
1501
|
-
//
|
|
1502
|
-
//
|
|
1492
|
+
// Pre-dedup: merge=union in git can produce multiple lines with the same id.
|
|
1493
|
+
// Legacy exports may differ in volatile scoring metadata
|
|
1494
|
+
// (reinforcement_count, last_reinforced); newer stable exports may be byte-identical
|
|
1495
|
+
// apart from line duplication. Prefer the record with stronger legacy metadata when
|
|
1496
|
+
// present, otherwise keep the first durable record encountered.
|
|
1503
1497
|
const dedupedRecords: any[] = [];
|
|
1504
1498
|
const seenById = new Map<string, number>(); // id → index in dedupedRecords
|
|
1505
1499
|
for (const line of jsonl.split("\n")) {
|
|
@@ -42,12 +42,13 @@
|
|
|
42
42
|
|
|
43
43
|
import * as path from "node:path";
|
|
44
44
|
import * as os from "node:os";
|
|
45
|
-
import type { ExtensionAPI, ExtensionContext, ExtensionCommandContext, SessionMessageEntry } from "@
|
|
46
|
-
import { DynamicBorder } from "@
|
|
45
|
+
import type { ExtensionAPI, ExtensionContext, ExtensionCommandContext, SessionMessageEntry } from "@styrene-lab/pi-coding-agent";
|
|
46
|
+
import { DynamicBorder } from "@styrene-lab/pi-coding-agent";
|
|
47
47
|
import { sciCall, sciOk, sciErr, sciExpanded, sciLoading } from "./sci-renderers.ts";
|
|
48
|
+
import { sciExitCard, type ExitCardData } from "../lib/sci-ui.ts";
|
|
48
49
|
import { StringEnum } from "../lib/typebox-helpers";
|
|
49
50
|
import { Type } from "@sinclair/typebox";
|
|
50
|
-
import { Container, type SelectItem, SelectList, Text } from "@
|
|
51
|
+
import { Container, type SelectItem, SelectList, Text } from "@styrene-lab/pi-tui";
|
|
51
52
|
import { FactStore, parseExtractionOutput, GLOBAL_DECAY, type MindRecord, type Fact } from "./factstore.ts";
|
|
52
53
|
import { embed, isEmbeddingAvailable, resolveEmbeddingProvider, MODEL_DIMS, type EmbeddingProvider } from "./embeddings.ts";
|
|
53
54
|
import { DEFAULT_CONFIG, type MemoryConfig, type LifecycleMemoryCandidate } from "./types.ts";
|
|
@@ -68,8 +69,8 @@ import {
|
|
|
68
69
|
import { runExtractionV2, runGlobalExtraction, killActiveExtraction, killAllSubprocesses, generateEpisode, generateEpisodeDirect, generateEpisodeWithFallback, buildTemplateEpisode, runSectionPruningPass, type SessionTelemetry } from "./extraction-v2.ts";
|
|
69
70
|
import { migrateToFactStore, needsMigration, markMigrated } from "./migration.ts";
|
|
70
71
|
import { SECTIONS } from "./template.ts";
|
|
71
|
-
import { serializeConversation, convertToLlm } from "@
|
|
72
|
-
import { sharedState } from "../shared-state.ts";
|
|
72
|
+
import { serializeConversation, convertToLlm } from "@styrene-lab/pi-coding-agent";
|
|
73
|
+
import { sharedState } from "../lib/shared-state.ts";
|
|
73
74
|
import {
|
|
74
75
|
ingestLifecycleCandidate,
|
|
75
76
|
ingestLifecycleCandidatesBatch,
|
|
@@ -81,6 +82,7 @@ import {
|
|
|
81
82
|
resolveTier,
|
|
82
83
|
getTierDisplayLabel,
|
|
83
84
|
getDefaultPolicy,
|
|
85
|
+
getViableModels,
|
|
84
86
|
type ModelTier,
|
|
85
87
|
type RegistryModel
|
|
86
88
|
} from "../lib/model-routing.ts";
|
|
@@ -881,13 +883,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
881
883
|
.slice(0, 10);
|
|
882
884
|
|
|
883
885
|
// Merge: recent episodes + recency window + core sections (deduplicated)
|
|
886
|
+
// Budget-capped to prevent context overflow on large fact stores.
|
|
887
|
+
const STARTUP_MAX_CHARS = 12_000; // ~3K tokens — leaves room for system prompt + design-tree
|
|
888
|
+
let startupChars = 0;
|
|
884
889
|
const startupFactIds = new Set<string>();
|
|
885
890
|
const startupFacts: typeof allFacts = [];
|
|
886
891
|
for (const f of [...coreFacts, ...archFacts, ...recentFacts]) {
|
|
887
|
-
if (
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
892
|
+
if (startupFactIds.has(f.id)) continue;
|
|
893
|
+
const cost = f.content.length + 20;
|
|
894
|
+
if (startupChars + cost > STARTUP_MAX_CHARS) break;
|
|
895
|
+
startupFacts.push(f);
|
|
896
|
+
startupFactIds.add(f.id);
|
|
897
|
+
startupChars += cost;
|
|
891
898
|
}
|
|
892
899
|
|
|
893
900
|
if (recentEpisodes.length > 0 || startupFacts.length > 0) {
|
|
@@ -1062,7 +1069,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1062
1069
|
return await tryLocalCompaction(localModel, prep, customInstructions, combinedSignal);
|
|
1063
1070
|
} else {
|
|
1064
1071
|
// Use cloud model via model registry
|
|
1065
|
-
const all = ctx.modelRegistry
|
|
1072
|
+
const all = getViableModels(ctx.modelRegistry);
|
|
1066
1073
|
const policy = sharedState.routingPolicy ?? getDefaultPolicy();
|
|
1067
1074
|
const resolved = resolveTier(tier, all, policy);
|
|
1068
1075
|
|
|
@@ -3305,6 +3312,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
3305
3312
|
},
|
|
3306
3313
|
});
|
|
3307
3314
|
|
|
3315
|
+
pi.registerMessageRenderer("session-exit", (_message, _options, theme) => {
|
|
3316
|
+
const data = (_message.details ?? {}) as ExitCardData;
|
|
3317
|
+
return sciExitCard(data, theme);
|
|
3318
|
+
});
|
|
3319
|
+
|
|
3308
3320
|
pi.registerCommand("exit", {
|
|
3309
3321
|
description: "Run memory extraction and exit gracefully (avoids /reload terminal corruption)",
|
|
3310
3322
|
handler: async (_args, ctx) => {
|
|
@@ -3391,22 +3403,28 @@ export default function (pi: ExtensionAPI) {
|
|
|
3391
3403
|
exitEpisodeDone = true;
|
|
3392
3404
|
}
|
|
3393
3405
|
|
|
3394
|
-
// Build session-end
|
|
3395
|
-
const
|
|
3406
|
+
// Build session-end card data
|
|
3407
|
+
const exitData: ExitCardData = {
|
|
3408
|
+
factCount: factsAfter,
|
|
3409
|
+
factDelta: delta,
|
|
3410
|
+
embeddingAvailable,
|
|
3411
|
+
};
|
|
3396
3412
|
|
|
3397
3413
|
// Git state
|
|
3398
3414
|
try {
|
|
3399
3415
|
const branchResult = await pi.exec("git", ["branch", "--show-current"], { timeout: 3_000, cwd: ctx.cwd });
|
|
3400
3416
|
const statusResult = await pi.exec("git", ["status", "--short"], { timeout: 3_000, cwd: ctx.cwd });
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
summaryLines.push(`🔀 ${branchName}${dirtyCount > 0 ? ` · ${dirtyCount} dirty` : " · clean"}`);
|
|
3417
|
+
exitData.branch = branchResult.stdout.trim();
|
|
3418
|
+
exitData.dirtyCount = statusResult.stdout.trim().split("\n").filter(Boolean).length;
|
|
3404
3419
|
} catch { /* ignore */ }
|
|
3405
3420
|
|
|
3406
3421
|
// Design tree
|
|
3407
3422
|
const dt = sharedState.designTree;
|
|
3408
3423
|
if (dt && dt.nodeCount > 0) {
|
|
3409
|
-
|
|
3424
|
+
exitData.designNodes = dt.nodeCount;
|
|
3425
|
+
exitData.designImplemented = dt.implementedCount;
|
|
3426
|
+
exitData.designDecided = dt.decidedCount;
|
|
3427
|
+
exitData.designExploring = dt.exploringCount;
|
|
3410
3428
|
}
|
|
3411
3429
|
|
|
3412
3430
|
// OpenSpec
|
|
@@ -3414,30 +3432,26 @@ export default function (pi: ExtensionAPI) {
|
|
|
3414
3432
|
if (os && os.changes.length > 0) {
|
|
3415
3433
|
const active = os.changes.filter(c => c.stage !== "archived");
|
|
3416
3434
|
if (active.length > 0) {
|
|
3417
|
-
|
|
3435
|
+
exitData.openspecActive = active.map(c => c.name);
|
|
3418
3436
|
}
|
|
3419
3437
|
}
|
|
3420
3438
|
|
|
3421
|
-
//
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
? ` · ${coveragePct}% indexed`
|
|
3426
|
-
: " · semantic search off";
|
|
3427
|
-
const memLine = delta > 0
|
|
3428
|
-
? `🧠 ${factsAfter} facts (+${delta} new)${embeddingInfo}`
|
|
3429
|
-
: `🧠 ${factsAfter} facts${embeddingInfo}`;
|
|
3430
|
-
summaryLines.push(memLine);
|
|
3431
|
-
|
|
3432
|
-
if (summaryLines.length > 0) {
|
|
3433
|
-
ctx.ui.notify(summaryLines.join("\n"), "info");
|
|
3434
|
-
await new Promise(r => setTimeout(r, 300));
|
|
3439
|
+
// Embedding coverage
|
|
3440
|
+
if (store && embeddingAvailable) {
|
|
3441
|
+
const vecCount = store.countFactVectors(mind);
|
|
3442
|
+
exitData.embeddingPct = factsAfter > 0 ? Math.round((vecCount / factsAfter) * 100) : 100;
|
|
3435
3443
|
}
|
|
3436
3444
|
|
|
3437
|
-
|
|
3445
|
+
// Render as a proper sci-ui card in the conversation
|
|
3446
|
+
pi.sendMessage({
|
|
3447
|
+
customType: "session-exit",
|
|
3448
|
+
content: "Session ended.",
|
|
3449
|
+
details: exitData,
|
|
3450
|
+
display: true,
|
|
3451
|
+
});
|
|
3438
3452
|
|
|
3439
|
-
//
|
|
3440
|
-
await new Promise(r => setTimeout(r,
|
|
3453
|
+
// Let the card render before shutdown tears down the TUI
|
|
3454
|
+
await new Promise(r => setTimeout(r, 500));
|
|
3441
3455
|
|
|
3442
3456
|
// ctx.shutdown() is fire-and-forget internally (sets shutdownRequested flag
|
|
3443
3457
|
// and calls void this.shutdown() in interactive mode). We must keep this
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* Re-exports the shared sci-ui primitives and adds memory-specific
|
|
5
5
|
* formatting helpers for structured card rendering.
|
|
6
6
|
*/
|
|
7
|
-
export { sciCall, sciOk, sciErr, sciExpanded, sciLoading } from "../sci-ui.ts";
|
|
7
|
+
export { sciCall, sciOk, sciErr, sciExpanded, sciLoading } from "../lib/sci-ui.ts";
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
composeNativeDiagram,
|
|
46
46
|
rasterizeSvgToPng,
|
|
47
47
|
} from "./native-diagrams/index.ts";
|
|
48
|
-
import type { ExtensionAPI } from "@
|
|
48
|
+
import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
|
|
49
49
|
import { Type } from "@sinclair/typebox";
|
|
50
50
|
|
|
51
51
|
// ---------------------------------------------------------------------------
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import { existsSync, readFileSync } from "node:fs";
|
|
14
14
|
import { join, basename } from "node:path";
|
|
15
|
-
import type { ExtensionAPI } from "@
|
|
15
|
+
import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
|
|
16
16
|
|
|
17
17
|
const SESSION_LOG_HEADER = `# Session Log
|
|
18
18
|
|
package/extensions/style.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Subcommands: (none), palette, d2, excalidraw, check <file>
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { ExtensionAPI } from "@
|
|
8
|
+
import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
|
|
9
9
|
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
// Palette data — single source of truth
|