gsd-pi 2.72.0-dev.3159350 → 2.72.0-dev.4f3264a
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/dist/resources/extensions/async-jobs/await-tool.js +4 -7
- package/dist/resources/extensions/async-jobs/job-manager.js +3 -28
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +26 -27
- package/dist/resources/extensions/gsd/auto/loop.js +1 -84
- package/dist/resources/extensions/gsd/auto-observability.js +54 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +0 -6
- package/dist/resources/extensions/gsd/auto.js +19 -25
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -9
- package/dist/resources/extensions/gsd/commands-handlers.js +1 -4
- package/dist/resources/extensions/gsd/context-injector.js +1 -1
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +7 -3
- package/dist/resources/extensions/gsd/file-watcher.js +80 -0
- package/dist/resources/extensions/gsd/gsd-db.js +5 -47
- package/dist/resources/extensions/gsd/key-manager.js +0 -2
- package/dist/resources/extensions/gsd/preferences-skills.js +34 -2
- package/dist/resources/extensions/gsd/preferences-types.js +0 -15
- package/dist/resources/extensions/gsd/preferences.js +3 -16
- package/dist/resources/extensions/gsd/prompt-loader.js +1 -4
- package/dist/resources/extensions/gsd/rtk-status.js +43 -0
- package/dist/resources/extensions/gsd/state.js +1 -21
- package/dist/resources/extensions/gsd/write-intercept.js +1 -10
- package/dist/resources/extensions/ollama/index.js +5 -4
- package/dist/resources/extensions/ollama/ollama-client.js +6 -35
- package/dist/resources/extensions/ollama/ollama-discovery.js +6 -32
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +3 -3
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
- package/dist/web/standalone/.next/server/chunks/2331.js +16 -16
- package/dist/web/standalone/.next/server/chunks/4741.js +12 -12
- package/dist/web/standalone/.next/server/chunks/5822.js +2 -2
- package/dist/web/standalone/.next/server/chunks/63.js +8 -8
- package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
- package/dist/web/standalone/.next/server/functions-config-manifest.json +9 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +2 -29
- package/dist/web/standalone/.next/server/middleware.js +12 -4
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/package.json +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +0 -1
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/models.custom.d.ts +0 -105
- package/packages/pi-ai/dist/models.custom.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.custom.js +0 -97
- package/packages/pi-ai/dist/models.custom.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +140 -648
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +364 -861
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +0 -105
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +1 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/env-api-keys.ts +0 -1
- package/packages/pi-ai/src/models.custom.ts +0 -98
- package/packages/pi-ai/src/models.generated.ts +364 -861
- package/packages/pi-ai/src/models.test.ts +0 -135
- package/packages/pi-ai/src/types.ts +0 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +0 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/src/core/model-resolver.ts +0 -1
- package/src/resources/extensions/async-jobs/await-tool.test.ts +7 -40
- package/src/resources/extensions/async-jobs/await-tool.ts +4 -7
- package/src/resources/extensions/async-jobs/job-manager.ts +3 -33
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +26 -27
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +2 -20
- package/src/resources/extensions/gsd/auto/loop.ts +1 -89
- package/src/resources/extensions/gsd/auto-observability.ts +72 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +0 -7
- package/src/resources/extensions/gsd/auto.ts +20 -25
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -8
- package/src/resources/extensions/gsd/commands-handlers.ts +1 -5
- package/src/resources/extensions/gsd/context-injector.ts +1 -1
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +8 -4
- package/src/resources/extensions/gsd/file-watcher.ts +100 -0
- package/src/resources/extensions/gsd/gsd-db.ts +5 -52
- package/src/resources/extensions/gsd/key-manager.ts +0 -2
- package/src/resources/extensions/gsd/preferences-skills.ts +36 -2
- package/src/resources/extensions/gsd/preferences-types.ts +0 -16
- package/src/resources/extensions/gsd/preferences.ts +6 -19
- package/src/resources/extensions/gsd/prompt-loader.ts +1 -6
- package/src/resources/extensions/gsd/rtk-status.ts +53 -0
- package/src/resources/extensions/gsd/state.ts +0 -20
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +0 -74
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +0 -63
- package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -53
- package/src/resources/extensions/gsd/write-intercept.ts +1 -10
- package/src/resources/extensions/ollama/index.ts +5 -4
- package/src/resources/extensions/ollama/ollama-client.ts +6 -35
- package/src/resources/extensions/ollama/ollama-discovery.ts +6 -37
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +0 -54
- package/dist/resources/extensions/gsd/definition-io.js +0 -15
- package/dist/web/standalone/.next/server/edge-runtime-webpack.js +0 -2
- package/packages/pi-ai/dist/models.generated.test.d.ts +0 -2
- package/packages/pi-ai/dist/models.generated.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/models.generated.test.js +0 -334
- package/packages/pi-ai/dist/models.generated.test.js.map +0 -1
- package/packages/pi-ai/src/models.generated.test.ts +0 -373
- package/src/resources/extensions/gsd/definition-io.ts +0 -18
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +0 -27
- package/src/resources/extensions/gsd/tests/block-db-writes.test.ts +0 -63
- package/src/resources/extensions/gsd/tests/definition-io.test.ts +0 -57
- package/src/resources/extensions/gsd/tests/doctor-heal-fixable-warnings.test.ts +0 -14
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +0 -104
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +0 -54
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +0 -34
- package/src/resources/extensions/gsd/tests/preferences-formatting.test.ts +0 -87
- package/src/resources/extensions/gsd/tests/prompt-loader-working-directory.test.ts +0 -19
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +0 -97
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +0 -41
- /package/dist/web/standalone/.next/static/{eR2tLKungpmiiOyUIhqjF → vr6Pbde48w4rMUplqDdh_}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{eR2tLKungpmiiOyUIhqjF → vr6Pbde48w4rMUplqDdh_}/_ssgManifest.js +0 -0
|
@@ -121,25 +121,6 @@ function openRawDb(path) {
|
|
|
121
121
|
return new Database(path);
|
|
122
122
|
}
|
|
123
123
|
const SCHEMA_VERSION = 14;
|
|
124
|
-
function indexExists(db, name) {
|
|
125
|
-
return !!db.prepare("SELECT 1 as present FROM sqlite_master WHERE type = 'index' AND name = ?").get(name);
|
|
126
|
-
}
|
|
127
|
-
function dedupeVerificationEvidenceRows(db) {
|
|
128
|
-
db.exec(`
|
|
129
|
-
DELETE FROM verification_evidence
|
|
130
|
-
WHERE rowid NOT IN (
|
|
131
|
-
SELECT MIN(rowid)
|
|
132
|
-
FROM verification_evidence
|
|
133
|
-
GROUP BY task_id, slice_id, milestone_id, command, verdict
|
|
134
|
-
)
|
|
135
|
-
`);
|
|
136
|
-
}
|
|
137
|
-
function ensureVerificationEvidenceDedupIndex(db) {
|
|
138
|
-
if (indexExists(db, "idx_verification_evidence_dedup"))
|
|
139
|
-
return;
|
|
140
|
-
dedupeVerificationEvidenceRows(db);
|
|
141
|
-
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_verification_evidence_dedup ON verification_evidence(task_id, slice_id, milestone_id, command, verdict)");
|
|
142
|
-
}
|
|
143
124
|
function initSchema(db, fileBacked) {
|
|
144
125
|
if (fileBacked)
|
|
145
126
|
db.exec("PRAGMA journal_mode=WAL");
|
|
@@ -377,7 +358,7 @@ function initSchema(db, fileBacked) {
|
|
|
377
358
|
db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
|
|
378
359
|
db.exec("CREATE INDEX IF NOT EXISTS idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status)");
|
|
379
360
|
db.exec("CREATE INDEX IF NOT EXISTS idx_verification_evidence_task ON verification_evidence(milestone_id, slice_id, task_id)");
|
|
380
|
-
|
|
361
|
+
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_verification_evidence_dedup ON verification_evidence(task_id, slice_id, milestone_id, command, verdict)");
|
|
381
362
|
// v14 index — slice dependency lookups
|
|
382
363
|
db.exec("CREATE INDEX IF NOT EXISTS idx_slice_deps_target ON slice_dependencies(milestone_id, depends_on_slice_id)");
|
|
383
364
|
db.exec(`CREATE VIEW IF NOT EXISTS active_decisions AS SELECT * FROM decisions WHERE superseded_by IS NULL`);
|
|
@@ -687,7 +668,7 @@ function migrateSchema(db) {
|
|
|
687
668
|
db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
|
|
688
669
|
db.exec("CREATE INDEX IF NOT EXISTS idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status)");
|
|
689
670
|
db.exec("CREATE INDEX IF NOT EXISTS idx_verification_evidence_task ON verification_evidence(milestone_id, slice_id, task_id)");
|
|
690
|
-
|
|
671
|
+
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_verification_evidence_dedup ON verification_evidence(task_id, slice_id, milestone_id, command, verdict)");
|
|
691
672
|
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
692
673
|
":version": 13,
|
|
693
674
|
":applied_at": new Date().toISOString(),
|
|
@@ -1353,29 +1334,6 @@ export function setSliceSummaryMd(milestoneId, sliceId, summaryMd, uatMd) {
|
|
|
1353
1334
|
currentDb.prepare(`UPDATE slices SET full_summary_md = :summary_md, full_uat_md = :uat_md WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId, ":summary_md": summaryMd, ":uat_md": uatMd });
|
|
1354
1335
|
}
|
|
1355
1336
|
function rowToTask(row) {
|
|
1356
|
-
const parseTaskArray = (value) => {
|
|
1357
|
-
if (Array.isArray(value)) {
|
|
1358
|
-
return value.filter((entry) => typeof entry === "string");
|
|
1359
|
-
}
|
|
1360
|
-
if (typeof value !== "string")
|
|
1361
|
-
return [];
|
|
1362
|
-
const trimmed = value.trim();
|
|
1363
|
-
if (!trimmed)
|
|
1364
|
-
return [];
|
|
1365
|
-
try {
|
|
1366
|
-
const parsed = JSON.parse(trimmed);
|
|
1367
|
-
if (Array.isArray(parsed)) {
|
|
1368
|
-
return parsed.filter((entry) => typeof entry === "string");
|
|
1369
|
-
}
|
|
1370
|
-
if (typeof parsed === "string" && parsed.trim()) {
|
|
1371
|
-
return [parsed.trim()];
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
catch {
|
|
1375
|
-
// Older/corrupt DB rows may contain raw comma-separated paths instead of JSON arrays.
|
|
1376
|
-
}
|
|
1377
|
-
return trimmed.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
1378
|
-
};
|
|
1379
1337
|
return {
|
|
1380
1338
|
milestone_id: row["milestone_id"],
|
|
1381
1339
|
slice_id: row["slice_id"],
|
|
@@ -1395,10 +1353,10 @@ function rowToTask(row) {
|
|
|
1395
1353
|
full_summary_md: row["full_summary_md"],
|
|
1396
1354
|
description: row["description"] ?? "",
|
|
1397
1355
|
estimate: row["estimate"] ?? "",
|
|
1398
|
-
files:
|
|
1356
|
+
files: JSON.parse(row["files"] || "[]"),
|
|
1399
1357
|
verify: row["verify"] ?? "",
|
|
1400
|
-
inputs:
|
|
1401
|
-
expected_output:
|
|
1358
|
+
inputs: JSON.parse(row["inputs"] || "[]"),
|
|
1359
|
+
expected_output: JSON.parse(row["expected_output"] || "[]"),
|
|
1402
1360
|
observability_impact: row["observability_impact"] ?? "",
|
|
1403
1361
|
full_plan_md: row["full_plan_md"] ?? "",
|
|
1404
1362
|
sequence: row["sequence"] ?? 0,
|
|
@@ -26,8 +26,6 @@ export const PROVIDER_REGISTRY = [
|
|
|
26
26
|
{ id: "custom-openai", label: "Custom (OpenAI-compat)", category: "llm", envVar: "CUSTOM_OPENAI_API_KEY" },
|
|
27
27
|
{ id: "cerebras", label: "Cerebras", category: "llm", envVar: "CEREBRAS_API_KEY" },
|
|
28
28
|
{ id: "azure-openai-responses", label: "Azure OpenAI", category: "llm", envVar: "AZURE_OPENAI_API_KEY" },
|
|
29
|
-
{ id: "alibaba-coding-plan", label: "Alibaba Coding Plan", category: "llm", envVar: "ALIBABA_API_KEY", dashboardUrl: "bailian.console.aliyun.com" },
|
|
30
|
-
{ id: "alibaba-dashscope", label: "Alibaba DashScope", category: "llm", envVar: "DASHSCOPE_API_KEY", dashboardUrl: "dashscope.console.aliyun.com" },
|
|
31
29
|
// Tool Keys
|
|
32
30
|
{ id: "context7", label: "Context7 Docs", category: "tool", envVar: "CONTEXT7_API_KEY", dashboardUrl: "context7.com/dashboard" },
|
|
33
31
|
{ id: "jina", label: "Jina Page Extract", category: "tool", envVar: "JINA_API_KEY", dashboardUrl: "jina.ai/api" },
|
|
@@ -9,6 +9,7 @@ import { homedir } from "node:os";
|
|
|
9
9
|
import { isAbsolute, join } from "node:path";
|
|
10
10
|
import { statSync } from "node:fs";
|
|
11
11
|
import { validatePreferences } from "./preferences-validation.js";
|
|
12
|
+
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
12
13
|
/**
|
|
13
14
|
* Known skill directories, in priority order.
|
|
14
15
|
* Searches both the skills.sh ecosystem directory (~/.agents/skills/) and
|
|
@@ -129,5 +130,36 @@ export function resolveAllSkillReferences(preferences, cwd) {
|
|
|
129
130
|
}
|
|
130
131
|
return { resolutions, warnings };
|
|
131
132
|
}
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Format a skill reference for the system prompt.
|
|
135
|
+
* If resolved, shows the path so the agent knows exactly where to read.
|
|
136
|
+
* If unresolved, marks it clearly.
|
|
137
|
+
*/
|
|
138
|
+
export function formatSkillRef(ref, resolutions) {
|
|
139
|
+
const resolution = resolutions.get(ref);
|
|
140
|
+
if (!resolution || resolution.method === "unresolved") {
|
|
141
|
+
return `${ref} (⚠ not found — check skill name or path)`;
|
|
142
|
+
}
|
|
143
|
+
// For absolute paths where SKILL.md is just appended, don't clutter the output
|
|
144
|
+
if (resolution.method === "absolute-path" || resolution.method === "absolute-dir") {
|
|
145
|
+
return ref;
|
|
146
|
+
}
|
|
147
|
+
// For bare names resolved from skill directories, show the resolved path
|
|
148
|
+
return `${ref} → \`${resolution.resolvedPath}\``;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Resolve the skill discovery mode from effective preferences.
|
|
152
|
+
* Defaults to "suggest" -- skills are identified during research but not installed automatically.
|
|
153
|
+
*/
|
|
154
|
+
export function resolveSkillDiscoveryMode() {
|
|
155
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
156
|
+
return prefs?.preferences.skill_discovery ?? "suggest";
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Resolve the skill staleness threshold in days.
|
|
160
|
+
* Returns 0 if disabled, default 60 if not configured.
|
|
161
|
+
*/
|
|
162
|
+
export function resolveSkillStalenessDays() {
|
|
163
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
164
|
+
return prefs?.preferences.skill_staleness_days ?? 60;
|
|
165
|
+
}
|
|
@@ -92,18 +92,3 @@ export const KNOWN_UNIT_TYPES = [
|
|
|
92
92
|
"discuss-milestone", "discuss-slice", "worktree-merge",
|
|
93
93
|
];
|
|
94
94
|
export const SKILL_ACTIONS = new Set(["use", "prefer", "avoid"]);
|
|
95
|
-
/**
|
|
96
|
-
* Format a skill reference for the system prompt.
|
|
97
|
-
* If resolved, shows the path so the agent knows exactly where to read.
|
|
98
|
-
* If unresolved, marks it clearly.
|
|
99
|
-
*/
|
|
100
|
-
export function formatSkillRef(ref, resolutions) {
|
|
101
|
-
const resolution = resolutions.get(ref);
|
|
102
|
-
if (!resolution || resolution.method === "unresolved") {
|
|
103
|
-
return `${ref} (⚠ not found — check skill name or path)`;
|
|
104
|
-
}
|
|
105
|
-
if (resolution.method === "absolute-path" || resolution.method === "absolute-dir") {
|
|
106
|
-
return ref;
|
|
107
|
-
}
|
|
108
|
-
return `${ref} → \`${resolution.resolvedPath}\``;
|
|
109
|
-
}
|
|
@@ -17,23 +17,13 @@ import { parse as parseYaml } from "yaml";
|
|
|
17
17
|
import { normalizeStringArray } from "../shared/format-utils.js";
|
|
18
18
|
import { logWarning } from "./workflow-logger.js";
|
|
19
19
|
import { resolveProfileDefaults as _resolveProfileDefaults } from "./preferences-models.js";
|
|
20
|
-
import { KNOWN_PREFERENCE_KEYS, MODE_DEFAULTS,
|
|
20
|
+
import { KNOWN_PREFERENCE_KEYS, MODE_DEFAULTS, } from "./preferences-types.js";
|
|
21
21
|
import { validatePreferences } from "./preferences-validation.js";
|
|
22
|
+
import { formatSkillRef } from "./preferences-skills.js";
|
|
22
23
|
// ─── Re-exports: validation ─────────────────────────────────────────────────
|
|
23
24
|
export { validatePreferences } from "./preferences-validation.js";
|
|
24
25
|
// ─── Re-exports: skills ─────────────────────────────────────────────────────
|
|
25
|
-
export { resolveAllSkillReferences } from "./preferences-skills.js";
|
|
26
|
-
// These lived in preferences-skills.ts but imported loadEffectiveGSDPreferences
|
|
27
|
-
// back from this file, creating a circular dependency. Moved here since they
|
|
28
|
-
// are trivial wrappers over loadEffectiveGSDPreferences.
|
|
29
|
-
export function resolveSkillDiscoveryMode() {
|
|
30
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
31
|
-
return prefs?.preferences.skill_discovery ?? "suggest";
|
|
32
|
-
}
|
|
33
|
-
export function resolveSkillStalenessDays() {
|
|
34
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
35
|
-
return prefs?.preferences.skill_staleness_days ?? 60;
|
|
36
|
-
}
|
|
26
|
+
export { resolveAllSkillReferences, resolveSkillDiscoveryMode, resolveSkillStalenessDays, } from "./preferences-skills.js";
|
|
37
27
|
// ─── Re-exports: models ─────────────────────────────────────────────────────
|
|
38
28
|
export { resolveModelForUnit, resolveModelWithFallbacksForUnit, getNextFallbackModel, isTransientNetworkError, validateModelId, updatePreferencesModels, resolveDynamicRoutingConfig, resolveAutoSupervisorConfig, resolveProfileDefaults, resolveEffectiveProfile, resolveInlineLevel, resolveContextSelection, resolveSearchProviderFromPreferences, } from "./preferences-models.js";
|
|
39
29
|
// ─── Path Constants & Getters ───────────────────────────────────────────────
|
|
@@ -314,9 +304,6 @@ function mergePreferences(base, override) {
|
|
|
314
304
|
github: (base.github || override.github)
|
|
315
305
|
? { ...(base.github ?? {}), ...(override.github ?? {}) }
|
|
316
306
|
: undefined,
|
|
317
|
-
experimental: (base.experimental || override.experimental)
|
|
318
|
-
? { ...(base.experimental ?? {}), ...(override.experimental ?? {}) }
|
|
319
|
-
: undefined,
|
|
320
307
|
service_tier: override.service_tier ?? base.service_tier,
|
|
321
308
|
forensics_dedup: override.forensics_dedup ?? base.forensics_dedup,
|
|
322
309
|
show_token_cost: override.show_token_cost ?? base.show_token_cost,
|
|
@@ -132,13 +132,10 @@ export function loadPrompt(name, vars = {}) {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
for (const [key, value] of Object.entries(effectiveVars)) {
|
|
135
|
-
const safeValue = key === "workingDirectory" && typeof value === "string"
|
|
136
|
-
? value.replaceAll("\\", "/")
|
|
137
|
-
: value;
|
|
138
135
|
// Use split/join instead of replaceAll to avoid JavaScript's special
|
|
139
136
|
// replacement patterns ($', $`, $&) being interpreted in the value.
|
|
140
137
|
// See: https://github.com/gsd-build/gsd-2/issues/2968
|
|
141
|
-
content = content.split(`{{${key}}}`).join(
|
|
138
|
+
content = content.split(`{{${key}}}`).join(value);
|
|
142
139
|
}
|
|
143
140
|
return content.trim();
|
|
144
141
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ensureRtkSessionBaseline, formatRtkSavingsLabel, getRtkSessionSavings, } from "../shared/rtk-session-stats.js";
|
|
2
|
+
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
3
|
+
const STATUS_KEY = "gsd-rtk";
|
|
4
|
+
const REFRESH_INTERVAL_MS = 30_000;
|
|
5
|
+
let refreshTimer = null;
|
|
6
|
+
function clearTimer() {
|
|
7
|
+
if (refreshTimer) {
|
|
8
|
+
clearInterval(refreshTimer);
|
|
9
|
+
refreshTimer = null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function isRtkEnabledInPrefs() {
|
|
13
|
+
return loadEffectiveGSDPreferences()?.preferences.experimental?.rtk === true;
|
|
14
|
+
}
|
|
15
|
+
function updateStatus(ctx) {
|
|
16
|
+
if (!ctx.hasUI)
|
|
17
|
+
return;
|
|
18
|
+
if (!isRtkEnabledInPrefs())
|
|
19
|
+
return;
|
|
20
|
+
const basePath = ctx.cwd;
|
|
21
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
22
|
+
ensureRtkSessionBaseline(basePath, sessionId);
|
|
23
|
+
const savings = getRtkSessionSavings(basePath, sessionId);
|
|
24
|
+
ctx.ui.setStatus(STATUS_KEY, formatRtkSavingsLabel(savings) ?? undefined);
|
|
25
|
+
}
|
|
26
|
+
export function startRtkStatusUpdates(ctx) {
|
|
27
|
+
clearTimer();
|
|
28
|
+
if (!isRtkEnabledInPrefs()) {
|
|
29
|
+
// Ensure any previously set status is cleared (e.g. preference was toggled off)
|
|
30
|
+
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
updateStatus(ctx);
|
|
34
|
+
if (!ctx.hasUI)
|
|
35
|
+
return;
|
|
36
|
+
refreshTimer = setInterval(() => {
|
|
37
|
+
updateStatus(ctx);
|
|
38
|
+
}, REFRESH_INTERVAL_MS);
|
|
39
|
+
}
|
|
40
|
+
export function stopRtkStatusUpdates(ctx) {
|
|
41
|
+
clearTimer();
|
|
42
|
+
ctx?.ui.setStatus(STATUS_KEY, undefined);
|
|
43
|
+
}
|
|
@@ -13,7 +13,7 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
|
13
13
|
import { debugCount, debugTime } from './debug-logger.js';
|
|
14
14
|
import { logWarning, logError } from './workflow-logger.js';
|
|
15
15
|
import { extractVerdict } from './verdict-parser.js';
|
|
16
|
-
import { isDbAvailable, wasDbOpenAttempted, getAllMilestones, getMilestone, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, insertMilestone, insertSlice, insertTask,
|
|
16
|
+
import { isDbAvailable, wasDbOpenAttempted, getAllMilestones, getMilestone, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, insertMilestone, insertSlice, insertTask, updateTaskStatus, getPendingGateCountForTurn, } from './gsd-db.js';
|
|
17
17
|
/**
|
|
18
18
|
* A "ghost" milestone directory contains only META.json (and no substantive
|
|
19
19
|
* files like CONTEXT, CONTEXT-DRAFT, ROADMAP, or SUMMARY). These appear when
|
|
@@ -286,26 +286,6 @@ function reconcileDiskToDb(basePath) {
|
|
|
286
286
|
depends: s.depends, demo: s.demo,
|
|
287
287
|
});
|
|
288
288
|
}
|
|
289
|
-
// Reconcile stale *existing* slice rows (#3599): a slice row may exist in
|
|
290
|
-
// the DB with status "pending" even though disk artifacts (SUMMARY) prove
|
|
291
|
-
// completion — the same class of desync that task-level reconciliation
|
|
292
|
-
// (further below) already handles. Without this, the dependency resolver
|
|
293
|
-
// builds doneSliceIds from stale DB rows and downstream slices stay blocked
|
|
294
|
-
// forever with "No slice eligible".
|
|
295
|
-
for (const dbSlice of dbSlices) {
|
|
296
|
-
if (isStatusDone(dbSlice.status))
|
|
297
|
-
continue;
|
|
298
|
-
const summaryPath = resolveSliceFile(basePath, mid, dbSlice.id, "SUMMARY");
|
|
299
|
-
if (summaryPath) {
|
|
300
|
-
try {
|
|
301
|
-
updateSliceStatus(mid, dbSlice.id, "complete");
|
|
302
|
-
logWarning("reconcile", `slice ${mid}/${dbSlice.id} status reconciled from "${dbSlice.status}" to "complete" (#3599)`, { mid, sid: dbSlice.id });
|
|
303
|
-
}
|
|
304
|
-
catch (e) {
|
|
305
|
-
logError("reconcile", `failed to update slice ${dbSlice.id}`, { sid: dbSlice.id, error: e.message });
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
289
|
}
|
|
310
290
|
return allMilestones;
|
|
311
291
|
}
|
|
@@ -22,9 +22,6 @@ const BLOCKED_PATTERNS = [
|
|
|
22
22
|
/(^|[/\\])\.gsd[/\\]STATE\.md$/i,
|
|
23
23
|
// Also match resolved symlink paths under ~/.gsd/projects/ (Pitfall #6)
|
|
24
24
|
/(^|[/\\])\.gsd[/\\]projects[/\\][^/\\]+[/\\]STATE\.md$/i,
|
|
25
|
-
// gsd.db and WAL/SHM files — single-writer WAL connection managed by engine (#3625)
|
|
26
|
-
/(^|[/\\])\.gsd[/\\]gsd\.db(-wal|-shm)?$/i,
|
|
27
|
-
/(^|[/\\])\.gsd[/\\]projects[/\\][^/\\]+[/\\]gsd\.db(-wal|-shm)?$/i,
|
|
28
25
|
];
|
|
29
26
|
/**
|
|
30
27
|
* Bash command patterns that target STATE.md.
|
|
@@ -41,12 +38,6 @@ const BASH_STATE_PATTERNS = [
|
|
|
41
38
|
/\bsed\b.*-i.*STATE\.md/i,
|
|
42
39
|
// dd output to STATE.md
|
|
43
40
|
/\bdd\b.*of=\S*STATE\.md/i,
|
|
44
|
-
// Direct DB access via sqlite3/sql.js/better-sqlite3 targeting gsd.db (#3625)
|
|
45
|
-
/\b(sqlite3|sql\.js|better-sqlite3|node:sqlite)\b.*gsd\.db/i,
|
|
46
|
-
/\bgsd\.db\b.*\b(sqlite3|sql\.js|better-sqlite3)\b/i,
|
|
47
|
-
// Shell writes targeting gsd.db files
|
|
48
|
-
/[>|]+\s*\S*gsd\.db/i,
|
|
49
|
-
/\b(cp|mv|dd)\b.*gsd\.db/i,
|
|
50
41
|
];
|
|
51
42
|
/**
|
|
52
43
|
* Tests whether the given file path matches a blocked authoritative .gsd/ state file.
|
|
@@ -84,7 +75,7 @@ function matchesBlockedPattern(path) {
|
|
|
84
75
|
* Error message returned when an agent attempts to directly write an authoritative .gsd/ state file.
|
|
85
76
|
* Directs the agent to use engine tool calls instead.
|
|
86
77
|
*/
|
|
87
|
-
export const BLOCKED_WRITE_ERROR = `Direct writes to .gsd/STATE.md
|
|
78
|
+
export const BLOCKED_WRITE_ERROR = `Direct writes to .gsd/STATE.md are blocked. Use engine tool calls instead:
|
|
88
79
|
- To complete a task: call gsd_complete_task(milestone_id, slice_id, task_id, summary)
|
|
89
80
|
- To complete a slice: call gsd_complete_slice(milestone_id, slice_id, summary, uat_result)
|
|
90
81
|
- To save a decision: call gsd_save_decision(scope, decision, choice, rationale)
|
|
@@ -59,12 +59,13 @@ async function probeAndRegister(pi) {
|
|
|
59
59
|
return false;
|
|
60
60
|
}
|
|
61
61
|
const baseUrl = client.getOllamaHost();
|
|
62
|
-
// Use authMode "apiKey" (#3440).
|
|
63
|
-
//
|
|
64
|
-
//
|
|
62
|
+
// Use authMode "apiKey" with a dummy key (#3440).
|
|
63
|
+
// authMode "none" requires a custom streamSimple handler, but Ollama uses
|
|
64
|
+
// the standard OpenAI-compatible streaming endpoint. Ollama ignores the
|
|
65
|
+
// Authorization header so the dummy key is harmless.
|
|
65
66
|
pi.registerProvider("ollama", {
|
|
66
67
|
authMode: "apiKey",
|
|
67
|
-
apiKey:
|
|
68
|
+
apiKey: "ollama",
|
|
68
69
|
baseUrl,
|
|
69
70
|
api: "ollama-chat",
|
|
70
71
|
streamSimple: streamOllamaChat,
|
|
@@ -15,34 +15,11 @@ export function getOllamaHost() {
|
|
|
15
15
|
return host;
|
|
16
16
|
return `http://${host}`;
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Get auth headers for Ollama API requests.
|
|
20
|
-
* For cloud endpoints (OLLAMA_HOST pointing to ollama.com or remote instances),
|
|
21
|
-
* OLLAMA_API_KEY is used as a Bearer token. Local Ollama ignores the header.
|
|
22
|
-
*/
|
|
23
|
-
function getAuthHeaders() {
|
|
24
|
-
const apiKey = process.env.OLLAMA_API_KEY;
|
|
25
|
-
if (!apiKey)
|
|
26
|
-
return {};
|
|
27
|
-
return { Authorization: `Bearer ${apiKey}` };
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Merge auth headers into request options.
|
|
31
|
-
*/
|
|
32
|
-
function withAuth(options = {}) {
|
|
33
|
-
const authHeaders = getAuthHeaders();
|
|
34
|
-
if (Object.keys(authHeaders).length === 0)
|
|
35
|
-
return options;
|
|
36
|
-
return {
|
|
37
|
-
...options,
|
|
38
|
-
headers: { ...authHeaders, ...(options.headers || {}) },
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
18
|
async function fetchWithTimeout(url, options = {}, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
42
19
|
const controller = new AbortController();
|
|
43
20
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
44
21
|
try {
|
|
45
|
-
return await fetch(url,
|
|
22
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
46
23
|
}
|
|
47
24
|
finally {
|
|
48
25
|
clearTimeout(timeout);
|
|
@@ -50,16 +27,10 @@ async function fetchWithTimeout(url, options = {}, timeoutMs = REQUEST_TIMEOUT_M
|
|
|
50
27
|
}
|
|
51
28
|
/**
|
|
52
29
|
* Check if Ollama is running and reachable.
|
|
53
|
-
* For cloud endpoints (OLLAMA_HOST pointing to ollama.com), uses /api/tags
|
|
54
|
-
* as the probe since the root endpoint may not be available.
|
|
55
30
|
*/
|
|
56
31
|
export async function isRunning() {
|
|
57
32
|
try {
|
|
58
|
-
const
|
|
59
|
-
const isCloud = host.includes("ollama.com") || host.includes("cloud");
|
|
60
|
-
const probeUrl = isCloud ? `${host}/api/tags` : `${host}/`;
|
|
61
|
-
const timeout = isCloud ? REQUEST_TIMEOUT_MS : PROBE_TIMEOUT_MS;
|
|
62
|
-
const response = await fetchWithTimeout(probeUrl, isCloud ? { method: "GET" } : {}, timeout);
|
|
33
|
+
const response = await fetchWithTimeout(`${getOllamaHost()}/`, {}, PROBE_TIMEOUT_MS);
|
|
63
34
|
return response.ok;
|
|
64
35
|
}
|
|
65
36
|
catch {
|
|
@@ -121,12 +92,12 @@ export async function getRunningModels() {
|
|
|
121
92
|
* Returns when the pull is complete.
|
|
122
93
|
*/
|
|
123
94
|
export async function pullModel(name, onProgress, signal) {
|
|
124
|
-
const response = await fetch(`${getOllamaHost()}/api/pull`,
|
|
95
|
+
const response = await fetch(`${getOllamaHost()}/api/pull`, {
|
|
125
96
|
method: "POST",
|
|
126
97
|
headers: { "Content-Type": "application/json" },
|
|
127
98
|
body: JSON.stringify({ name, stream: true }),
|
|
128
99
|
signal,
|
|
129
|
-
})
|
|
100
|
+
});
|
|
130
101
|
if (!response.ok) {
|
|
131
102
|
const text = await response.text();
|
|
132
103
|
throw new Error(`Ollama /api/pull returned ${response.status}: ${text}`);
|
|
@@ -143,12 +114,12 @@ export async function pullModel(name, onProgress, signal) {
|
|
|
143
114
|
* Returns an async generator yielding each NDJSON response chunk.
|
|
144
115
|
*/
|
|
145
116
|
export async function* chat(request, signal) {
|
|
146
|
-
const response = await fetch(`${getOllamaHost()}/api/chat`,
|
|
117
|
+
const response = await fetch(`${getOllamaHost()}/api/chat`, {
|
|
147
118
|
method: "POST",
|
|
148
119
|
headers: { "Content-Type": "application/json" },
|
|
149
120
|
body: JSON.stringify(request),
|
|
150
121
|
signal,
|
|
151
|
-
})
|
|
122
|
+
});
|
|
152
123
|
if (!response.ok) {
|
|
153
124
|
const text = await response.text();
|
|
154
125
|
throw new Error(`Ollama /api/chat returned ${response.status}: ${text}`);
|
|
@@ -6,40 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Returns models in the format expected by pi.registerProvider().
|
|
8
8
|
*/
|
|
9
|
-
import { listModels
|
|
9
|
+
import { listModels } from "./ollama-client.js";
|
|
10
10
|
import { estimateContextFromParams, formatModelSize, getModelCapabilities, humanizeModelName, } from "./model-capabilities.js";
|
|
11
|
-
/**
|
|
12
|
-
* Extract context window from /api/show model_info.
|
|
13
|
-
* Keys follow the pattern "{architecture}.context_length" (e.g. "llama.context_length").
|
|
14
|
-
*/
|
|
15
|
-
function extractContextFromModelInfo(modelInfo) {
|
|
16
|
-
for (const [key, value] of Object.entries(modelInfo)) {
|
|
17
|
-
if (key.endsWith(".context_length") && typeof value === "number" && value > 0) {
|
|
18
|
-
return value;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
11
|
const ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
24
|
-
|
|
12
|
+
function enrichModel(info) {
|
|
25
13
|
const caps = getModelCapabilities(info.name);
|
|
26
14
|
const parameterSize = info.details?.parameter_size ?? "";
|
|
27
|
-
//
|
|
28
|
-
let showContextWindow;
|
|
29
|
-
if (caps.contextWindow === undefined) {
|
|
30
|
-
try {
|
|
31
|
-
const showData = await deps.showModel(info.name);
|
|
32
|
-
showContextWindow = extractContextFromModelInfo(showData.model_info);
|
|
33
|
-
}
|
|
34
|
-
catch (err) {
|
|
35
|
-
// non-fatal: fall through to estimate
|
|
36
|
-
if (process.env.GSD_DEBUG)
|
|
37
|
-
console.warn(`[ollama] /api/show failed for ${info.name}:`, err instanceof Error ? err.message : String(err));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
// Determine context window: known table > /api/show > estimate from param size > default
|
|
15
|
+
// Determine context window: known table > estimate from param size > default
|
|
41
16
|
const contextWindow = caps.contextWindow ??
|
|
42
|
-
showContextWindow ??
|
|
43
17
|
(parameterSize ? estimateContextFromParams(parameterSize) : 8192);
|
|
44
18
|
// Determine max tokens: known table > fraction of context > default
|
|
45
19
|
const maxTokens = caps.maxTokens ?? Math.min(Math.floor(contextWindow / 4), 16384);
|
|
@@ -64,11 +38,11 @@ async function enrichModel(info, deps) {
|
|
|
64
38
|
/**
|
|
65
39
|
* Discover all locally available Ollama models with enriched capabilities.
|
|
66
40
|
*/
|
|
67
|
-
export async function discoverModels(
|
|
68
|
-
const tags = await
|
|
41
|
+
export async function discoverModels() {
|
|
42
|
+
const tags = await listModels();
|
|
69
43
|
if (!tags.models || tags.models.length === 0)
|
|
70
44
|
return [];
|
|
71
|
-
return
|
|
45
|
+
return tags.models.map(enrichModel);
|
|
72
46
|
}
|
|
73
47
|
/**
|
|
74
48
|
* Format a discovered model for display in model list.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
vr6Pbde48w4rMUplqDdh_
|
|
@@ -4,43 +4,43 @@
|
|
|
4
4
|
"/api/boot/route": "/api/boot",
|
|
5
5
|
"/api/bridge-terminal/resize/route": "/api/bridge-terminal/resize",
|
|
6
6
|
"/api/bridge-terminal/input/route": "/api/bridge-terminal/input",
|
|
7
|
-
"/api/
|
|
7
|
+
"/api/bridge-terminal/stream/route": "/api/bridge-terminal/stream",
|
|
8
8
|
"/api/dev-mode/route": "/api/dev-mode",
|
|
9
|
-
"/api/
|
|
9
|
+
"/api/cleanup/route": "/api/cleanup",
|
|
10
10
|
"/api/doctor/route": "/api/doctor",
|
|
11
|
+
"/api/captures/route": "/api/captures",
|
|
11
12
|
"/api/export-data/route": "/api/export-data",
|
|
12
|
-
"/api/browse-directories/route": "/api/browse-directories",
|
|
13
13
|
"/api/forensics/route": "/api/forensics",
|
|
14
|
+
"/api/browse-directories/route": "/api/browse-directories",
|
|
14
15
|
"/api/git/route": "/api/git",
|
|
15
16
|
"/api/history/route": "/api/history",
|
|
16
17
|
"/api/hooks/route": "/api/hooks",
|
|
17
|
-
"/api/experimental/route": "/api/experimental",
|
|
18
|
-
"/api/bridge-terminal/stream/route": "/api/bridge-terminal/stream",
|
|
19
18
|
"/api/inspect/route": "/api/inspect",
|
|
20
19
|
"/api/knowledge/route": "/api/knowledge",
|
|
21
|
-
"/api/
|
|
20
|
+
"/api/experimental/route": "/api/experimental",
|
|
22
21
|
"/api/live-state/route": "/api/live-state",
|
|
22
|
+
"/api/notifications/route": "/api/notifications",
|
|
23
23
|
"/api/preferences/route": "/api/preferences",
|
|
24
24
|
"/api/recovery/route": "/api/recovery",
|
|
25
25
|
"/api/onboarding/route": "/api/onboarding",
|
|
26
|
-
"/api/session/browser/route": "/api/session/browser",
|
|
27
26
|
"/api/projects/route": "/api/projects",
|
|
27
|
+
"/api/session/browser/route": "/api/session/browser",
|
|
28
|
+
"/api/session/events/route": "/api/session/events",
|
|
28
29
|
"/api/session/command/route": "/api/session/command",
|
|
29
|
-
"/api/files/route": "/api/files",
|
|
30
30
|
"/api/settings-data/route": "/api/settings-data",
|
|
31
|
+
"/api/files/route": "/api/files",
|
|
31
32
|
"/api/shutdown/route": "/api/shutdown",
|
|
32
33
|
"/api/session/manage/route": "/api/session/manage",
|
|
33
|
-
"/api/session/events/route": "/api/session/events",
|
|
34
34
|
"/api/skill-health/route": "/api/skill-health",
|
|
35
35
|
"/api/steer/route": "/api/steer",
|
|
36
36
|
"/api/terminal/input/route": "/api/terminal/input",
|
|
37
|
-
"/api/switch-root/route": "/api/switch-root",
|
|
38
37
|
"/api/terminal/resize/route": "/api/terminal/resize",
|
|
38
|
+
"/api/switch-root/route": "/api/switch-root",
|
|
39
39
|
"/api/terminal/sessions/route": "/api/terminal/sessions",
|
|
40
40
|
"/api/terminal/stream/route": "/api/terminal/stream",
|
|
41
|
+
"/api/undo/route": "/api/undo",
|
|
41
42
|
"/api/terminal/upload/route": "/api/terminal/upload",
|
|
42
43
|
"/api/visualizer/route": "/api/visualizer",
|
|
43
|
-
"/api/undo/route": "/api/undo",
|
|
44
44
|
"/api/update/route": "/api/update",
|
|
45
45
|
"/api/remote-questions/route": "/api/remote-questions",
|
|
46
46
|
"/page": "/"
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
],
|
|
5
5
|
"devFiles": [],
|
|
6
6
|
"lowPriorityFiles": [
|
|
7
|
-
"static/
|
|
8
|
-
"static/
|
|
7
|
+
"static/vr6Pbde48w4rMUplqDdh_/_buildManifest.js",
|
|
8
|
+
"static/vr6Pbde48w4rMUplqDdh_/_ssgManifest.js"
|
|
9
9
|
],
|
|
10
10
|
"rootMainFiles": [
|
|
11
11
|
"static/chunks/webpack-b868033a5834586d.js",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"dynamicRoutes": {},
|
|
79
79
|
"notFoundRoutes": [],
|
|
80
80
|
"preview": {
|
|
81
|
-
"previewModeId": "
|
|
82
|
-
"previewModeSigningKey": "
|
|
83
|
-
"previewModeEncryptionKey": "
|
|
81
|
+
"previewModeId": "056d72cb497176b59eacca17d28d85f2",
|
|
82
|
+
"previewModeSigningKey": "69bb7934dcb0a09b7069cfd9f5466dfaae71acefd3f1ca3f7ba908a007b77a71",
|
|
83
|
+
"previewModeEncryptionKey": "65843937e372e058af890aefb5c0878ad985c4b4575d4624c0491b7aa3e3b9a6"
|
|
84
84
|
}
|
|
85
85
|
}
|