@ashlr/hub 2.2.0 → 3.0.1
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/CHANGELOG.md +73 -0
- package/README.md +95 -8
- package/dist/api/plugin.d.ts +1 -0
- package/dist/cli/backlog.js +2 -0
- package/dist/cli/backlog.js.map +1 -1
- package/dist/cli/digest.d.ts +6 -0
- package/dist/cli/digest.js +127 -2
- package/dist/cli/digest.js.map +1 -1
- package/dist/cli/eval-fixtures.d.ts +18 -0
- package/dist/cli/eval-fixtures.js +38 -0
- package/dist/cli/eval-fixtures.js.map +1 -0
- package/dist/cli/eval.d.ts +56 -0
- package/dist/cli/eval.js +283 -0
- package/dist/cli/eval.js.map +1 -0
- package/dist/cli/fleet.d.ts +27 -0
- package/dist/cli/fleet.js +222 -0
- package/dist/cli/fleet.js.map +1 -0
- package/dist/cli/goal.d.ts +15 -0
- package/dist/cli/goal.js +91 -0
- package/dist/cli/goal.js.map +1 -0
- package/dist/cli/help.js +10 -3
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/inbox.d.ts +6 -0
- package/dist/cli/inbox.js +183 -8
- package/dist/cli/inbox.js.map +1 -1
- package/dist/cli/index.js +50 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/loop.d.ts +16 -0
- package/dist/cli/loop.js +66 -0
- package/dist/cli/loop.js.map +1 -0
- package/dist/cli/mcp.d.ts +12 -0
- package/dist/cli/mcp.js +148 -0
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/onboard.d.ts +16 -0
- package/dist/cli/onboard.js +71 -0
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/plugins.js +9 -8
- package/dist/cli/plugins.js.map +1 -1
- package/dist/cli/pulse.d.ts +10 -0
- package/dist/cli/pulse.js +261 -0
- package/dist/cli/pulse.js.map +1 -1
- package/dist/cli/run.js +21 -3
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/stack.d.ts +34 -0
- package/dist/cli/stack.js +221 -0
- package/dist/cli/stack.js.map +1 -0
- package/dist/cli/update.js +12 -5
- package/dist/cli/update.js.map +1 -1
- package/dist/core/daemon/loop.d.ts +10 -5
- package/dist/core/daemon/loop.js +167 -37
- package/dist/core/daemon/loop.js.map +1 -1
- package/dist/core/env-bridge.js +3 -2
- package/dist/core/env-bridge.js.map +1 -1
- package/dist/core/fleet/automerge-pass.d.ts +33 -0
- package/dist/core/fleet/automerge-pass.js +61 -0
- package/dist/core/fleet/automerge-pass.js.map +1 -0
- package/dist/core/fleet/quota.d.ts +70 -0
- package/dist/core/fleet/quota.js +198 -0
- package/dist/core/fleet/quota.js.map +1 -0
- package/dist/core/fleet/router.d.ts +46 -0
- package/dist/core/fleet/router.js +121 -0
- package/dist/core/fleet/router.js.map +1 -0
- package/dist/core/fleet/self.d.ts +58 -0
- package/dist/core/fleet/self.js +187 -0
- package/dist/core/fleet/self.js.map +1 -0
- package/dist/core/fleet/status.d.ts +54 -0
- package/dist/core/fleet/status.js +157 -0
- package/dist/core/fleet/status.js.map +1 -0
- package/dist/core/foundry/provenance.d.ts +78 -0
- package/dist/core/foundry/provenance.js +172 -0
- package/dist/core/foundry/provenance.js.map +1 -0
- package/dist/core/git.d.ts +13 -0
- package/dist/core/git.js +26 -0
- package/dist/core/git.js.map +1 -1
- package/dist/core/inbox/merge.d.ts +151 -0
- package/dist/core/inbox/merge.js +858 -0
- package/dist/core/inbox/merge.js.map +1 -0
- package/dist/core/inbox/store.js +10 -1
- package/dist/core/inbox/store.js.map +1 -1
- package/dist/core/integrations/markdown.d.ts +66 -0
- package/dist/core/integrations/markdown.js +132 -0
- package/dist/core/integrations/markdown.js.map +1 -0
- package/dist/core/integrations/secrets.d.ts +37 -0
- package/dist/core/integrations/secrets.js +67 -0
- package/dist/core/integrations/secrets.js.map +1 -0
- package/dist/core/integrations/stack.d.ts +47 -0
- package/dist/core/integrations/stack.js +107 -0
- package/dist/core/integrations/stack.js.map +1 -0
- package/dist/core/mcp-native-engineer.d.ts +123 -0
- package/dist/core/mcp-native-engineer.js +936 -0
- package/dist/core/mcp-native-engineer.js.map +1 -0
- package/dist/core/mcp-native.js +20 -42
- package/dist/core/mcp-native.js.map +1 -1
- package/dist/core/mcp-registry.js +2 -0
- package/dist/core/mcp-registry.js.map +1 -1
- package/dist/core/observability/codex-source.d.ts +53 -0
- package/dist/core/observability/codex-source.js +390 -0
- package/dist/core/observability/codex-source.js.map +1 -0
- package/dist/core/observability/estimate.d.ts +12 -0
- package/dist/core/observability/estimate.js +26 -0
- package/dist/core/observability/estimate.js.map +1 -1
- package/dist/core/observability/limits.d.ts +52 -0
- package/dist/core/observability/limits.js +316 -0
- package/dist/core/observability/limits.js.map +1 -0
- package/dist/core/observability/usage-source.js +3 -1
- package/dist/core/observability/usage-source.js.map +1 -1
- package/dist/core/portfolio/scanners.d.ts +1 -0
- package/dist/core/portfolio/scanners.js +40 -1
- package/dist/core/portfolio/scanners.js.map +1 -1
- package/dist/core/providers.js +4 -0
- package/dist/core/providers.js.map +1 -1
- package/dist/core/quality/health.js +1 -0
- package/dist/core/quality/health.js.map +1 -1
- package/dist/core/run/agent-loop.d.ts +8 -0
- package/dist/core/run/agent-loop.js +24 -14
- package/dist/core/run/agent-loop.js.map +1 -1
- package/dist/core/run/engine-registry.d.ts +48 -0
- package/dist/core/run/engine-registry.js +190 -0
- package/dist/core/run/engine-registry.js.map +1 -0
- package/dist/core/run/engines.d.ts +17 -3
- package/dist/core/run/engines.js +63 -44
- package/dist/core/run/engines.js.map +1 -1
- package/dist/core/run/learned-router.d.ts +121 -0
- package/dist/core/run/learned-router.js +374 -0
- package/dist/core/run/learned-router.js.map +1 -0
- package/dist/core/run/model-manager.js +3 -3
- package/dist/core/run/model-manager.js.map +1 -1
- package/dist/core/run/model-profile.d.ts +67 -0
- package/dist/core/run/model-profile.js +132 -0
- package/dist/core/run/model-profile.js.map +1 -0
- package/dist/core/run/orchestrator.d.ts +1 -1
- package/dist/core/run/orchestrator.js +642 -510
- package/dist/core/run/orchestrator.js.map +1 -1
- package/dist/core/run/prompts/budget.d.ts +25 -0
- package/dist/core/run/prompts/budget.js +51 -0
- package/dist/core/run/prompts/budget.js.map +1 -0
- package/dist/core/run/prompts/index.d.ts +14 -0
- package/dist/core/run/prompts/index.js +59 -0
- package/dist/core/run/prompts/index.js.map +1 -0
- package/dist/core/run/prompts/layers.d.ts +26 -0
- package/dist/core/run/prompts/layers.js +73 -0
- package/dist/core/run/prompts/layers.js.map +1 -0
- package/dist/core/run/prompts/roles.d.ts +23 -0
- package/dist/core/run/prompts/roles.js +48 -0
- package/dist/core/run/prompts/roles.js.map +1 -0
- package/dist/core/run/prompts/types.d.ts +38 -0
- package/dist/core/run/prompts/types.js +5 -0
- package/dist/core/run/prompts/types.js.map +1 -0
- package/dist/core/run/provider-client.d.ts +6 -24
- package/dist/core/run/provider-client.js +125 -61
- package/dist/core/run/provider-client.js.map +1 -1
- package/dist/core/run/router.js +8 -0
- package/dist/core/run/router.js.map +1 -1
- package/dist/core/run/sandboxed-engine.d.ts +66 -0
- package/dist/core/run/sandboxed-engine.js +262 -0
- package/dist/core/run/sandboxed-engine.js.map +1 -0
- package/dist/core/run/verify-commands.d.ts +83 -0
- package/dist/core/run/verify-commands.js +234 -0
- package/dist/core/run/verify-commands.js.map +1 -0
- package/dist/core/run/verify.d.ts +31 -1
- package/dist/core/run/verify.js +48 -0
- package/dist/core/run/verify.js.map +1 -1
- package/dist/core/sandbox/audit.d.ts +27 -0
- package/dist/core/sandbox/audit.js +34 -0
- package/dist/core/sandbox/audit.js.map +1 -1
- package/dist/core/sandbox/confine.d.ts +134 -0
- package/dist/core/sandbox/confine.js +370 -0
- package/dist/core/sandbox/confine.js.map +1 -0
- package/dist/core/types.d.ts +227 -5
- package/dist/core/web/api.js +77 -28
- package/dist/core/web/api.js.map +1 -1
- package/dist/core/web/control.d.ts +116 -0
- package/dist/core/web/control.js +307 -0
- package/dist/core/web/control.js.map +1 -0
- package/dist/core/web/public/app.js +512 -6
- package/dist/core/web/public/styles.css +468 -0
- package/package.json +3 -2
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* control.ts — M61: Mission Control aggregator.
|
|
3
|
+
*
|
|
4
|
+
* `buildControlSnapshot(cfg)` assembles a unified read-only snapshot for the
|
|
5
|
+
* Mission Control dashboard. Each section is independently guarded — a broken
|
|
6
|
+
* subsystem degrades ONLY that slice; the rest still resolves. Never throws.
|
|
7
|
+
*
|
|
8
|
+
* JSON contract (verbatim, frontend depends on this):
|
|
9
|
+
* ControlSnapshot.ts — ISO stamp
|
|
10
|
+
* ControlSnapshot.models — live local-model provider state
|
|
11
|
+
* ControlSnapshot.fleet — FleetStatus (reuses buildFleetStatus)
|
|
12
|
+
* ControlSnapshot.daemon — running/pid/lastTickAt/todaySpentUsd
|
|
13
|
+
* ControlSnapshot.usage — 7d rollup: totals + byProvider
|
|
14
|
+
* ControlSnapshot.limits — per-backend rate-window standing ([] when none)
|
|
15
|
+
* ControlSnapshot.subscriptionLimits — rolling-window usage + honest provider notes (M63)
|
|
16
|
+
* ControlSnapshot.logs — most-recent-first, capped 50
|
|
17
|
+
*/
|
|
18
|
+
import type { AshlrConfig } from '../types.js';
|
|
19
|
+
import { type FleetStatus } from '../fleet/status.js';
|
|
20
|
+
import { type UsageWindow, type ProviderLimitEntry } from '../observability/limits.js';
|
|
21
|
+
export interface ControlProviderEntry {
|
|
22
|
+
id: string;
|
|
23
|
+
kind: 'local' | 'cloud';
|
|
24
|
+
up: boolean;
|
|
25
|
+
baseUrl: string | null;
|
|
26
|
+
models: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface ControlModels {
|
|
29
|
+
activeProvider: string | null;
|
|
30
|
+
providers: ControlProviderEntry[];
|
|
31
|
+
}
|
|
32
|
+
export interface ControlDaemon {
|
|
33
|
+
running: boolean;
|
|
34
|
+
pid: number | null;
|
|
35
|
+
lastTickAt: string | null;
|
|
36
|
+
todaySpentUsd: number;
|
|
37
|
+
}
|
|
38
|
+
export interface ControlUsageByProvider {
|
|
39
|
+
provider: string;
|
|
40
|
+
tier: 'local' | 'cloud';
|
|
41
|
+
tokens: number;
|
|
42
|
+
costUsd: number;
|
|
43
|
+
sharePct: number;
|
|
44
|
+
}
|
|
45
|
+
export interface ControlUsage {
|
|
46
|
+
window: '7d';
|
|
47
|
+
totalTokens: number;
|
|
48
|
+
totalCostUsd: number;
|
|
49
|
+
localSavingsUsd: number;
|
|
50
|
+
byProvider: ControlUsageByProvider[];
|
|
51
|
+
}
|
|
52
|
+
export interface ControlLimit {
|
|
53
|
+
backend: string;
|
|
54
|
+
window: string;
|
|
55
|
+
max: number;
|
|
56
|
+
used: number;
|
|
57
|
+
standing: 'ok' | 'warn' | 'over' | 'unlimited';
|
|
58
|
+
}
|
|
59
|
+
export interface ControlSubscriptionLimits {
|
|
60
|
+
connected: boolean;
|
|
61
|
+
note: string;
|
|
62
|
+
windows: UsageWindow[];
|
|
63
|
+
providers: ProviderLimitEntry[];
|
|
64
|
+
}
|
|
65
|
+
export interface ControlLogEntry {
|
|
66
|
+
ts: string;
|
|
67
|
+
kind: 'tick' | 'merge' | 'info';
|
|
68
|
+
msg: string;
|
|
69
|
+
}
|
|
70
|
+
export interface ControlSecurityFinding {
|
|
71
|
+
/** Basename of the repo the finding came from. */
|
|
72
|
+
repo: string;
|
|
73
|
+
title: string;
|
|
74
|
+
severity: string;
|
|
75
|
+
/** The WorkItem source — always 'security' for binshield items. */
|
|
76
|
+
source: string;
|
|
77
|
+
}
|
|
78
|
+
export interface ControlSecurityCounts {
|
|
79
|
+
critical: number;
|
|
80
|
+
high: number;
|
|
81
|
+
medium: number;
|
|
82
|
+
low: number;
|
|
83
|
+
}
|
|
84
|
+
export interface ControlSecurity {
|
|
85
|
+
/**
|
|
86
|
+
* True when at least one security WorkItem was found in the cached backlog.
|
|
87
|
+
* False when the backlog is absent, empty, or has no security-source items.
|
|
88
|
+
*/
|
|
89
|
+
available: boolean;
|
|
90
|
+
findings: ControlSecurityFinding[];
|
|
91
|
+
counts: ControlSecurityCounts;
|
|
92
|
+
}
|
|
93
|
+
export interface ControlSnapshot {
|
|
94
|
+
ts: string;
|
|
95
|
+
models: ControlModels;
|
|
96
|
+
fleet: FleetStatus;
|
|
97
|
+
daemon: ControlDaemon;
|
|
98
|
+
usage: ControlUsage;
|
|
99
|
+
limits: ControlLimit[];
|
|
100
|
+
subscriptionLimits: ControlSubscriptionLimits;
|
|
101
|
+
logs: ControlLogEntry[];
|
|
102
|
+
/** M67: supply-chain / binshield security findings from cached backlog. */
|
|
103
|
+
security: ControlSecurity;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Aggregate security WorkItems from the persisted backlog (~/.ashlr/backlog.json).
|
|
107
|
+
* Reads cached data only — never shells out to binshield live so /api/control
|
|
108
|
+
* stays fast. Degrades gracefully to available:false when the backlog is absent.
|
|
109
|
+
* Never throws.
|
|
110
|
+
*/
|
|
111
|
+
export declare function buildSecurity(): ControlSecurity;
|
|
112
|
+
/**
|
|
113
|
+
* Assemble a full ControlSnapshot. Each section is independently guarded so a
|
|
114
|
+
* broken subsystem never causes the whole snapshot to fail. Never throws.
|
|
115
|
+
*/
|
|
116
|
+
export declare function buildControlSnapshot(cfg: AshlrConfig): Promise<ControlSnapshot>;
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* control.ts — M61: Mission Control aggregator.
|
|
3
|
+
*
|
|
4
|
+
* `buildControlSnapshot(cfg)` assembles a unified read-only snapshot for the
|
|
5
|
+
* Mission Control dashboard. Each section is independently guarded — a broken
|
|
6
|
+
* subsystem degrades ONLY that slice; the rest still resolves. Never throws.
|
|
7
|
+
*
|
|
8
|
+
* JSON contract (verbatim, frontend depends on this):
|
|
9
|
+
* ControlSnapshot.ts — ISO stamp
|
|
10
|
+
* ControlSnapshot.models — live local-model provider state
|
|
11
|
+
* ControlSnapshot.fleet — FleetStatus (reuses buildFleetStatus)
|
|
12
|
+
* ControlSnapshot.daemon — running/pid/lastTickAt/todaySpentUsd
|
|
13
|
+
* ControlSnapshot.usage — 7d rollup: totals + byProvider
|
|
14
|
+
* ControlSnapshot.limits — per-backend rate-window standing ([] when none)
|
|
15
|
+
* ControlSnapshot.subscriptionLimits — rolling-window usage + honest provider notes (M63)
|
|
16
|
+
* ControlSnapshot.logs — most-recent-first, capped 50
|
|
17
|
+
*/
|
|
18
|
+
import { buildFleetStatus } from '../fleet/status.js';
|
|
19
|
+
import { getProviderRegistry } from '../providers.js';
|
|
20
|
+
import { buildRollup, modelToProviderKey, LOCAL_PROVIDER_KEYS } from '../observability/rollup.js';
|
|
21
|
+
import { loadDaemonState } from '../daemon/state.js';
|
|
22
|
+
import { usesInWindow, evalQuota, windowToMs } from '../fleet/quota.js';
|
|
23
|
+
import { resolveUsageWindows } from '../observability/limits.js';
|
|
24
|
+
import { loadBacklog } from '../portfolio/backlog.js';
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Section builders — each is independently guarded
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
/** Safe fallback for the models section. */
|
|
29
|
+
function fallbackModels() {
|
|
30
|
+
return { activeProvider: null, providers: [] };
|
|
31
|
+
}
|
|
32
|
+
async function buildModels(cfg) {
|
|
33
|
+
try {
|
|
34
|
+
const registry = await getProviderRegistry(cfg);
|
|
35
|
+
const LOCAL_IDS = new Set(['lmstudio', 'ollama']);
|
|
36
|
+
const providers = registry.providers.map((ep) => ({
|
|
37
|
+
id: ep.id,
|
|
38
|
+
kind: LOCAL_IDS.has(ep.id) ? 'local' : 'cloud',
|
|
39
|
+
up: ep.up,
|
|
40
|
+
baseUrl: ep.url ?? null,
|
|
41
|
+
models: ep.models,
|
|
42
|
+
}));
|
|
43
|
+
return { activeProvider: registry.activeProvider, providers };
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return fallbackModels();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Safe fallback for the daemon section. */
|
|
50
|
+
function fallbackDaemon() {
|
|
51
|
+
return { running: false, pid: null, lastTickAt: null, todaySpentUsd: 0 };
|
|
52
|
+
}
|
|
53
|
+
function buildDaemon() {
|
|
54
|
+
try {
|
|
55
|
+
const ds = loadDaemonState();
|
|
56
|
+
return {
|
|
57
|
+
running: ds.running === true,
|
|
58
|
+
pid: typeof ds.pid === 'number' ? ds.pid : null,
|
|
59
|
+
lastTickAt: ds.lastTickAt ?? null,
|
|
60
|
+
todaySpentUsd: typeof ds.todaySpentUsd === 'number' ? ds.todaySpentUsd : 0,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return fallbackDaemon();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Safe fallback for the usage section. */
|
|
68
|
+
function fallbackUsage() {
|
|
69
|
+
return {
|
|
70
|
+
window: '7d',
|
|
71
|
+
totalTokens: 0,
|
|
72
|
+
totalCostUsd: 0,
|
|
73
|
+
localSavingsUsd: 0,
|
|
74
|
+
byProvider: [],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function buildUsage(cfg) {
|
|
78
|
+
try {
|
|
79
|
+
const rollup = buildRollup('7d', cfg);
|
|
80
|
+
// Aggregate byModel into byProvider buckets
|
|
81
|
+
const totalCostUsd = rollup.totals.estCostUsd;
|
|
82
|
+
const totalTokens = rollup.totals.tokensIn + rollup.totals.tokensOut;
|
|
83
|
+
// per-provider accumulators
|
|
84
|
+
const providerMap = new Map();
|
|
85
|
+
for (const mu of rollup.byModel) {
|
|
86
|
+
const provKey = modelToProviderKey(mu.model);
|
|
87
|
+
const tier = LOCAL_PROVIDER_KEYS.has(provKey) ? 'local' : 'cloud';
|
|
88
|
+
const tokens = mu.tokensIn + mu.tokensOut;
|
|
89
|
+
const existing = providerMap.get(provKey);
|
|
90
|
+
if (existing) {
|
|
91
|
+
existing.tokens += tokens;
|
|
92
|
+
existing.costUsd += mu.estCostUsd;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
providerMap.set(provKey, { tier, tokens, costUsd: mu.estCostUsd });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const byProvider = [];
|
|
99
|
+
for (const [provider, acc] of providerMap.entries()) {
|
|
100
|
+
const sharePct = totalCostUsd > 0
|
|
101
|
+
? Math.round((acc.costUsd / totalCostUsd) * 1000) / 10
|
|
102
|
+
: totalTokens > 0
|
|
103
|
+
? Math.round((acc.tokens / totalTokens) * 1000) / 10
|
|
104
|
+
: 0;
|
|
105
|
+
byProvider.push({ provider, tier: acc.tier, tokens: acc.tokens, costUsd: acc.costUsd, sharePct });
|
|
106
|
+
}
|
|
107
|
+
byProvider.sort((a, b) => b.costUsd - a.costUsd || b.tokens - a.tokens);
|
|
108
|
+
// Normalise shares to sum exactly to 100 when there is usage
|
|
109
|
+
if (byProvider.length > 0) {
|
|
110
|
+
const rawSum = byProvider.reduce((s, p) => s + p.sharePct, 0);
|
|
111
|
+
if (rawSum > 0) {
|
|
112
|
+
// Proportionally rescale so sum === 100
|
|
113
|
+
const scale = 100 / rawSum;
|
|
114
|
+
let running = 0;
|
|
115
|
+
for (let i = 0; i < byProvider.length - 1; i++) {
|
|
116
|
+
byProvider[i].sharePct = Math.round(byProvider[i].sharePct * scale * 10) / 10;
|
|
117
|
+
running += byProvider[i].sharePct;
|
|
118
|
+
}
|
|
119
|
+
// Last entry gets the remainder to guarantee exact 100 sum
|
|
120
|
+
byProvider[byProvider.length - 1].sharePct =
|
|
121
|
+
Math.round((100 - running) * 10) / 10;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// localSavingsUsd: what the local tokens would have cost if cloud-priced.
|
|
125
|
+
// We use a conservative $3/$15 estimate for what a cloud provider would charge,
|
|
126
|
+
// then subtract $0 (local cost). Simple heuristic: localTokens * $3/1M in-tokens.
|
|
127
|
+
let localSavingsUsd = 0;
|
|
128
|
+
for (const p of byProvider) {
|
|
129
|
+
if (p.tier === 'local' && p.tokens > 0) {
|
|
130
|
+
// $3/1M tokens — the conservative cloud input price
|
|
131
|
+
localSavingsUsd += (p.tokens / 1_000_000) * 3;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
localSavingsUsd = Math.round(localSavingsUsd * 10000) / 10000;
|
|
135
|
+
return { window: '7d', totalTokens, totalCostUsd, localSavingsUsd, byProvider };
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return fallbackUsage();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function buildLimits(cfg) {
|
|
142
|
+
try {
|
|
143
|
+
const rawLimits = cfg.foundry?.limits;
|
|
144
|
+
if (!rawLimits)
|
|
145
|
+
return [];
|
|
146
|
+
const result = [];
|
|
147
|
+
for (const [backend, limit] of Object.entries(rawLimits)) {
|
|
148
|
+
if (!limit)
|
|
149
|
+
continue;
|
|
150
|
+
const windowMs = windowToMs(limit.window);
|
|
151
|
+
const used = usesInWindow(backend, windowMs);
|
|
152
|
+
const standing = evalQuota(backend, cfg);
|
|
153
|
+
result.push({ backend, window: limit.window, max: limit.max, used, standing });
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function buildSubscriptionLimits(cfg) {
|
|
162
|
+
try {
|
|
163
|
+
const result = await resolveUsageWindows(cfg);
|
|
164
|
+
return {
|
|
165
|
+
connected: result.connected,
|
|
166
|
+
note: result.note,
|
|
167
|
+
windows: result.windows,
|
|
168
|
+
providers: result.providers,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return {
|
|
173
|
+
connected: false,
|
|
174
|
+
note: 'Usage window data unavailable.',
|
|
175
|
+
windows: [],
|
|
176
|
+
providers: [],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const LOG_CAP = 50;
|
|
181
|
+
function buildLogs(cap = LOG_CAP) {
|
|
182
|
+
try {
|
|
183
|
+
const ds = loadDaemonState();
|
|
184
|
+
const ticks = Array.isArray(ds.ticks) ? ds.ticks : [];
|
|
185
|
+
// ticks are oldest-first in the state; reverse for most-recent-first
|
|
186
|
+
const reversed = [...ticks].reverse();
|
|
187
|
+
const entries = [];
|
|
188
|
+
for (const tick of reversed) {
|
|
189
|
+
if (entries.length >= cap)
|
|
190
|
+
break;
|
|
191
|
+
// Merge event (if any merges happened this tick, emit a separate line first)
|
|
192
|
+
if (typeof tick.merged === 'number' && tick.merged > 0) {
|
|
193
|
+
entries.push({
|
|
194
|
+
ts: tick.ts,
|
|
195
|
+
kind: 'merge',
|
|
196
|
+
msg: `${tick.merged} proposal(s) auto-merged`,
|
|
197
|
+
});
|
|
198
|
+
if (entries.length >= cap)
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
// Tick event
|
|
202
|
+
const backendStr = tick.backends && Object.keys(tick.backends).length > 0
|
|
203
|
+
? ' backends=' + Object.entries(tick.backends).map(([k, v]) => `${k}:${v}`).join(',')
|
|
204
|
+
: '';
|
|
205
|
+
const spendStr = typeof tick.spentUsd === 'number'
|
|
206
|
+
? ` spend=$${tick.spentUsd.toFixed(4)}`
|
|
207
|
+
: '';
|
|
208
|
+
entries.push({
|
|
209
|
+
ts: tick.ts,
|
|
210
|
+
kind: 'tick',
|
|
211
|
+
msg: `tick reason=${tick.reason ?? 'ok'}${backendStr}${spendStr}`,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
return entries;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
// M67: Security builder — reads cached backlog, never re-scans live.
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
/** Safe fallback for the security section. */
|
|
224
|
+
function fallbackSecurity() {
|
|
225
|
+
return {
|
|
226
|
+
available: false,
|
|
227
|
+
findings: [],
|
|
228
|
+
counts: { critical: 0, high: 0, medium: 0, low: 0 },
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Aggregate security WorkItems from the persisted backlog (~/.ashlr/backlog.json).
|
|
233
|
+
* Reads cached data only — never shells out to binshield live so /api/control
|
|
234
|
+
* stays fast. Degrades gracefully to available:false when the backlog is absent.
|
|
235
|
+
* Never throws.
|
|
236
|
+
*/
|
|
237
|
+
export function buildSecurity() {
|
|
238
|
+
try {
|
|
239
|
+
const backlog = loadBacklog();
|
|
240
|
+
if (!backlog)
|
|
241
|
+
return fallbackSecurity();
|
|
242
|
+
const secItems = backlog.items.filter((item) => item.source === 'security');
|
|
243
|
+
if (secItems.length === 0)
|
|
244
|
+
return fallbackSecurity();
|
|
245
|
+
const counts = { critical: 0, high: 0, medium: 0, low: 0 };
|
|
246
|
+
const findings = [];
|
|
247
|
+
for (const item of secItems) {
|
|
248
|
+
// Severity is the third tag when tags = ['security', 'binshield', <sev>].
|
|
249
|
+
// Fall back to scanning all tags for a known severity keyword.
|
|
250
|
+
const tags = Array.isArray(item.tags) ? item.tags : [];
|
|
251
|
+
const sev = tags[2] ??
|
|
252
|
+
tags.find((t) => ['critical', 'high', 'medium', 'low'].includes(t)) ??
|
|
253
|
+
'low';
|
|
254
|
+
if (sev === 'critical')
|
|
255
|
+
counts.critical++;
|
|
256
|
+
else if (sev === 'high')
|
|
257
|
+
counts.high++;
|
|
258
|
+
else if (sev === 'medium')
|
|
259
|
+
counts.medium++;
|
|
260
|
+
else
|
|
261
|
+
counts.low++;
|
|
262
|
+
findings.push({
|
|
263
|
+
repo: item.repo.split('/').pop() ?? item.repo,
|
|
264
|
+
title: item.title,
|
|
265
|
+
severity: sev,
|
|
266
|
+
source: item.source,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
// Sort: critical first, then high, medium, low — same order as backlog display.
|
|
270
|
+
const SEV_ORDER = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
271
|
+
findings.sort((a, b) => (SEV_ORDER[a.severity] ?? 4) - (SEV_ORDER[b.severity] ?? 4));
|
|
272
|
+
return { available: true, findings, counts };
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return fallbackSecurity();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// Main export
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
/**
|
|
282
|
+
* Assemble a full ControlSnapshot. Each section is independently guarded so a
|
|
283
|
+
* broken subsystem never causes the whole snapshot to fail. Never throws.
|
|
284
|
+
*/
|
|
285
|
+
export async function buildControlSnapshot(cfg) {
|
|
286
|
+
const ts = new Date().toISOString();
|
|
287
|
+
const [models, fleet] = await Promise.all([
|
|
288
|
+
buildModels(cfg),
|
|
289
|
+
buildFleetStatus(cfg).catch(() => ({
|
|
290
|
+
generatedAt: ts,
|
|
291
|
+
daemon: { running: false, lastTickAt: null, todaySpentUsd: 0 },
|
|
292
|
+
backends: [],
|
|
293
|
+
queue: { backlogItems: 0 },
|
|
294
|
+
proposals: { pending: 0, frontierPending: 0, applied: 0 },
|
|
295
|
+
merges: { recent: 0 },
|
|
296
|
+
killed: false,
|
|
297
|
+
})),
|
|
298
|
+
]);
|
|
299
|
+
const daemon = buildDaemon();
|
|
300
|
+
const usage = buildUsage(cfg);
|
|
301
|
+
const limits = buildLimits(cfg);
|
|
302
|
+
const subscriptionLimits = await buildSubscriptionLimits(cfg);
|
|
303
|
+
const logs = buildLogs(LOG_CAP);
|
|
304
|
+
const security = buildSecurity();
|
|
305
|
+
return { ts, models, fleet, daemon, usage, limits, subscriptionLimits, logs, security };
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control.js","sourceRoot":"","sources":["../../../src/core/web/control.ts"],"names":[],"mappings":"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"}
|