scream-code 0.14.8 → 0.14.9
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/{app-CJCkJpo_.mjs → app-2Dd57a5d.mjs} +166 -14
- package/dist/{dispatch-usl5yQnT.mjs → dispatch-1ojfKMwf.mjs} +324 -116
- package/dist/{dispatch-DVJhr5Rj.mjs → dispatch-CJPpI4gm.mjs} +1 -1
- package/dist/main.mjs +1 -1
- package/dist/{src-DCp4eCi5.mjs → src-h6ZExh4A.mjs} +1 -1
- package/dist/{src-BH9W5k24.mjs → src-tDEINaMV.mjs} +196 -17
- package/dist/{text-input-dialog-B0yHChBj.mjs → text-input-dialog-BUXAKycx.mjs} +40 -14
- package/dist/{text-input-dialog-B9uwX1Uy.mjs → text-input-dialog-Dr42qLMU.mjs} +1 -1
- package/package.json +1 -1
|
@@ -4,9 +4,9 @@ import { dirname as __cjsShimDirname } from 'node:path';
|
|
|
4
4
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
5
5
|
const __dirname = __cjsShimDirname(__filename);
|
|
6
6
|
import { i as __require, o as __toESM, r as __exportAll, t as __commonJSMin } from "./chunk-D90kvbyJ.mjs";
|
|
7
|
-
import { C as join$1, D as resolve$1, E as relative$1, S as isAbsolute$1, T as parse$7, a as isSupportedFile, b as basename$1, i as ingestFile, r as ingestDirectory, t as multiSearch, w as normalize, x as dirname$2, y as KnowledgeStore } from "./src-
|
|
7
|
+
import { C as join$1, D as resolve$1, E as relative$1, S as isAbsolute$1, T as parse$7, a as isSupportedFile, b as basename$1, i as ingestFile, r as ingestDirectory, t as multiSearch, w as normalize, x as dirname$2, y as KnowledgeStore } from "./src-tDEINaMV.mjs";
|
|
8
8
|
import { t as require_base64_js } from "./base64-js-DzVmk6Nb.mjs";
|
|
9
|
-
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-
|
|
9
|
+
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-BUXAKycx.mjs";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
11
|
import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
12
12
|
import * as fs$1 from "node:fs/promises";
|
|
@@ -53192,12 +53192,15 @@ function createFastEmbedEngine(cacheDir) {
|
|
|
53192
53192
|
engineCache.set(key, engine);
|
|
53193
53193
|
return engine;
|
|
53194
53194
|
}
|
|
53195
|
+
/** Stable identity of the model used by every engine created here. */
|
|
53196
|
+
const EMBEDDING_MODEL_NAME = "bge-small-zh-v1.5";
|
|
53195
53197
|
function createFastEmbedEngineImpl(cacheDir) {
|
|
53196
53198
|
let embedder = null;
|
|
53197
53199
|
let initPromise = null;
|
|
53198
53200
|
let loadFailed = false;
|
|
53199
53201
|
let lastError;
|
|
53200
53202
|
return {
|
|
53203
|
+
modelName: EMBEDDING_MODEL_NAME,
|
|
53201
53204
|
get available() {
|
|
53202
53205
|
return embedder !== null && !loadFailed;
|
|
53203
53206
|
},
|
|
@@ -53595,7 +53598,7 @@ var MemoryMemoStore = class MemoryMemoStore {
|
|
|
53595
53598
|
CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
53596
53599
|
memory_id TEXT PRIMARY KEY REFERENCES memos(id) ON DELETE CASCADE,
|
|
53597
53600
|
embedding_json TEXT NOT NULL,
|
|
53598
|
-
model TEXT NOT NULL DEFAULT '
|
|
53601
|
+
model TEXT NOT NULL DEFAULT '${EMBEDDING_MODEL_NAME}',
|
|
53599
53602
|
created_at INTEGER NOT NULL
|
|
53600
53603
|
);
|
|
53601
53604
|
|
|
@@ -53901,7 +53904,7 @@ var MemoryMemoStore = class MemoryMemoStore {
|
|
|
53901
53904
|
const now = Date.now();
|
|
53902
53905
|
this.db.exec("BEGIN TRANSACTION");
|
|
53903
53906
|
try {
|
|
53904
|
-
for (let i = 0; i < pending.length; i++) insert.run(pending[i].id, JSON.stringify([...vectors[i]]),
|
|
53907
|
+
for (let i = 0; i < pending.length; i++) insert.run(pending[i].id, JSON.stringify([...vectors[i]]), EMBEDDING_MODEL_NAME, now);
|
|
53905
53908
|
this.db.exec("COMMIT");
|
|
53906
53909
|
} catch (error) {
|
|
53907
53910
|
this.db.exec("ROLLBACK");
|
|
@@ -54910,7 +54913,7 @@ var KnowledgeLookupTool = class {
|
|
|
54910
54913
|
const llm = { generate: async (systemPrompt, userPrompt) => {
|
|
54911
54914
|
return this.agent.generateText(systemPrompt, userPrompt);
|
|
54912
54915
|
} };
|
|
54913
|
-
const { multiSearchWithTrace } = await import("./src-
|
|
54916
|
+
const { multiSearchWithTrace } = await import("./src-h6ZExh4A.mjs");
|
|
54914
54917
|
const { results, trace } = await multiSearchWithTrace(store, llm, query, { topK });
|
|
54915
54918
|
if (results.length === 0) return {
|
|
54916
54919
|
isError: false,
|
|
@@ -64668,7 +64671,7 @@ function renderPrompt(template, vars) {
|
|
|
64668
64671
|
}
|
|
64669
64672
|
//#endregion
|
|
64670
64673
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/skill-tool.md
|
|
64671
|
-
var skill_tool_default = "Invoke a registered skill from the current skill listing. BLOCKING REQUIREMENT: when a skill from the listing matches the user's request, you MUST call this tool (not free-form text). Do NOT call the same skill repeatedly inside one turn — recursive depth is capped at {{ MAX_SKILL_QUERY_DEPTH }}.\n\n## Currently model-invocable skills\n{{ AVAILABLE_SKILLS }}\nThis list is a construction-time snapshot; for the live catalog inspect the skill registry.\n\n## Matching guide\n\n- A skill matches when the user's request involves the scenarios/trigger conditions listed in the skill's \"When to use\" line.\n- Look for: (a) keywords in the user's request that match the skill's trigger phrases, (b) the task type or scenario described in the skill's \"When to use\", (c) similar requests the skill was designed for.\n- If a skill seems relevant, invoke it first — if it doesn't fit, you can always fall back to doing it yourself.";
|
|
64674
|
+
var skill_tool_default = "Invoke a registered skill from the current skill listing. BLOCKING REQUIREMENT: when a skill from the listing matches the user's request, you MUST call this tool (not free-form text). Do NOT call the same skill repeatedly inside one turn — recursive depth is capped at {{ MAX_SKILL_QUERY_DEPTH }}.\n\n## Currently model-invocable skills\n{{ AVAILABLE_SKILLS }}\nThis list is a construction-time snapshot; for the live catalog inspect the skill registry.\n\n**Not for inventory questions**: when the user asks what you have — in any wording (skills / plugins / capabilities / MCP / tools) — answer with **InspectOwnAssets** (the full read-only catalog), not this listing. To find or install new capabilities, use **ManagePlugin**. This listing exists for **invocation**: when one of the skills above matches the task at hand.\n\n## Matching guide\n\n- A skill matches when the user's request involves the scenarios/trigger conditions listed in the skill's \"When to use\" line.\n- Look for: (a) keywords in the user's request that match the skill's trigger phrases, (b) the task type or scenario described in the skill's \"When to use\", (c) similar requests the skill was designed for.\n- If a skill seems relevant, invoke it first — if it doesn't fit, you can always fall back to doing it yourself.";
|
|
64672
64675
|
/** Max skills to list inline in the tool description; rest are summarized. */
|
|
64673
64676
|
const MAX_INLINE_SKILLS = 15;
|
|
64674
64677
|
/** Max description length per skill line. */
|
|
@@ -72402,10 +72405,10 @@ async function findExistingRg(shareDir) {
|
|
|
72402
72405
|
source: "share-bin-cached"
|
|
72403
72406
|
};
|
|
72404
72407
|
}
|
|
72405
|
-
let downloadPromise;
|
|
72408
|
+
let downloadPromise$1;
|
|
72406
72409
|
async function downloadRgWithLock(shareDir) {
|
|
72407
|
-
if (downloadPromise !== void 0) return downloadPromise;
|
|
72408
|
-
downloadPromise = (async () => {
|
|
72410
|
+
if (downloadPromise$1 !== void 0) return downloadPromise$1;
|
|
72411
|
+
downloadPromise$1 = (async () => {
|
|
72409
72412
|
try {
|
|
72410
72413
|
const existing = await findExistingRg(shareDir);
|
|
72411
72414
|
if (existing) return existing;
|
|
@@ -72414,10 +72417,10 @@ async function downloadRgWithLock(shareDir) {
|
|
|
72414
72417
|
source: "share-bin-downloaded"
|
|
72415
72418
|
};
|
|
72416
72419
|
} finally {
|
|
72417
|
-
downloadPromise = void 0;
|
|
72420
|
+
downloadPromise$1 = void 0;
|
|
72418
72421
|
}
|
|
72419
72422
|
})();
|
|
72420
|
-
return downloadPromise;
|
|
72423
|
+
return downloadPromise$1;
|
|
72421
72424
|
}
|
|
72422
72425
|
function rgBinaryName() {
|
|
72423
72426
|
return process.platform === "win32" ? "rg.exe" : "rg";
|
|
@@ -75402,7 +75405,7 @@ function messageOf(error) {
|
|
|
75402
75405
|
}
|
|
75403
75406
|
//#endregion
|
|
75404
75407
|
//#region ../../packages/agent-core/src/tools/builtin/plugin/manage-plugin.md
|
|
75405
|
-
var manage_plugin_default = "Manage this product's own plugins. Plugins are the vehicle for add-on capabilities: each one can contribute skills, MCP servers, shell hooks, and — only after an explicit activate — code that runs in this process.\n\nUse this tool in two situations: (a) a task needs a capability you do not currently have — exhaust your existing tools first and add a plugin only when the gap is real; (b) the user asks you to find, install, configure, inspect, or clean up a capability (e.g. \"install something that can render mermaid\", \"
|
|
75408
|
+
var manage_plugin_default = "Manage this product's own plugins. Plugins are the vehicle for add-on capabilities: each one can contribute skills, MCP servers, shell hooks, and — only after an explicit activate — code that runs in this process.\n\nUse this tool in two situations: (a) a task needs a capability you do not currently have — exhaust your existing tools first and add a plugin only when the gap is real; (b) the user asks you to find, install, configure, inspect, or clean up a capability (e.g. \"install something that can render mermaid\", \"disable the plugin I no longer use\"). In both cases, remove or disable additions again when the work is done unless the capability is broadly reusable.\n\n**Not for inventory questions**: when the user asks what you have — in any wording (skills / plugins / capabilities / MCP / tools / 技能 / 插件 / 能力) — answer with **InspectOwnAssets** (the read-only inventory: every skill package on disk with live `invocable` status, plus MCP declarations). `{\"action\":\"list\"}` here is the **plugin management view**: a pre-change check of the plugin table before installing or modifying, not the answer to \"what can you do\".\n\nChoose the lightest vehicle that solves the problem, in this order: a skill (prompt instructions — safest, no code, no process), an MCP server (an external process), a code plugin (runs in this process — the most powerful, needs its own approved `activate`).\n\n## Workflow\n\n1. `{\"action\":\"list\"}` — see what is already installed before adding anything. To confirm the gap is real, start from an `InspectOwnAssets` inventory (what exists on disk and what is invocable), then check this table for an existing plugin that already covers it. Do not grow a second plugin that duplicates an existing capability; enable, disable, or extend the one you already have.\n2. `{\"action\":\"marketplace\",\"query\":\"pdf\"}` — browse the catalog for a matching capability. Pass `source` to read a different catalog. `tier` is a display label only; judge an entry by its description and source. Entries whose origin previously produced a tripped plugin carry `quarantined: true`.\n3. `{\"action\":\"precheck\",\"source\":\"https://github.com/owner/repo\"}` — free read-only origin check before installing anything external that you have not vetted in this session: it reports past incidents recorded by the plugin center's immune memory (`quarantined:true` + the reason). Surface such a warning to the user BEFORE asking for the install approval.\n4. If nothing in the catalog fits and precheck is clean, you may search the web (`WebSearch` / `FetchURL`) and evaluate a repository yourself: read its README and manifest, prefer a pinned branch/tag/commit URL over a moving default, and check that it does something you cannot already do.\n5. To **make a capability yourself**: if the user invoked `/make-skill`, use the `MakeSkillPlan` → `MakeSkillApply` pair (it produces a valid skill package and registers it into this table automatically). Otherwise build a plugin directory by hand (a `scream.plugin.json` manifest plus your SKILL.md under `skills/`) and register it with `register_generated` — that route lands in this table, hot-applies the same turn, and stays manageable here (disable/remove/circuit). Writing a plain SKILL.md into the user skills directory is also a legitimate skill, but it does NOT appear in this table and cannot be managed with this tool.\n6. `{\"action\":\"install\",\"source\":\"https://github.com/owner/repo/tree/v1.2.0\"}` — install from a local path, a GitHub URL, or a zip URL. **Installing never executes code.** The plugin's files are copied and its record is registered; a manifest `entryPoint` stays dormant until step 8.\n7. `{\"action\":\"install\",\"source\":\"...\",\"upgrade\":true}` — same-name refresh: backs up the current files (single slot under `plugins/backups/<id>/`), swaps in the new ones, and reloads; `from`/`to` versions and any downgrade warning are reported. If activation then fails, `rollback` restores the previous files in one approved step.\n8. `{\"action\":\"enable\",\"id\":\"...\"}` / `{\"action\":\"disable\",\"id\":\"...\"}` / `{\"action\":\"set_mcp_enabled\",\"id\":\"...\",\"server\":\"...\",\"enabled\":false}` — turn contributed capabilities on and off.\n9. `{\"action\":\"activate\",\"id\":\"...\"}` — the only action that runs a plugin's code entry point in this process. Skip it for skill-only and MCP-only plugins; they need no activation.\n10. `{\"action\":\"info\",\"id\":\"...\"}` / `{\"action\":\"check\"}` — inspect one record in full, or the health of the table. Each entry also carries `usage: {calls, okCalls, okRate, lastUsedAt}` from this machine: zero calls since install marks it as a cleanup candidate; high usage with a high okRate is worth keeping when you must choose.\n11. `{\"action\":\"reset\",\"id\":\"...\"}` — recover a circuit-tripped or manually disabled plugin: clears its failure ledger, re-derives the record from disk, enables it, and hot-applies its capabilities. It never runs code — a code plugin still needs its own approved `activate`.\n12. `{\"action\":\"rollback\",\"id\":\"...\"}` — restore the pre-upgrade backup taken by step 7 in one approved step.\n13. `{\"action\":\"reload\"}` — re-read the plugin table from disk and get an added/removed/error summary.\n14. `{\"action\":\"remove\",\"id\":\"...\"}` (or `disable` to keep the record) — retreat once the capability is no longer wanted.\n\n## Circuit breaker (limbs that fail get pulled, the loop never dies)\n\nPlugin-owned capabilities are counted per plugin: every failed tool call (in-process plugin tools and plugin MCP servers) and every faulty event handler. A success clears the streak; three consecutive failures trip the breaker, and the failing result arrives with a `[circuit]` advisory: the plugin was marked with the reason, disabled persistently, its code deactivated, and its tools, MCP servers, skills, and hooks pulled from every live session. Nothing retries automatically — read the state with `check` (each plugin carries `circuit: {failures, tripped}`), then `reset` to give it another chance or `remove` to let it go. User-configured MCP servers and built-in tools are never charged to anyone's breaker.\n\nEvery trip ALSO writes the origin into the plugin center's immune memory (quarantine ledger): future `precheck`/`install`/`marketplace` calls for the same repository will surface that history before anything is executed again, even across sessions — and even if the broken plugin was removed afterwards.\n\nChanges are hot-applied to the running session wherever the host supports it: mutating results carry a `sync` report (`{ok, applied[], failed[]}`) naming exactly what landed — `skills.inject`, `mcp.add`/`mcp.remove`, tool teardown. An `install` deliberately reports no `mcp.add`: installing never starts a plugin's MCP process; that waits for an approved `enable`/`activate`/`reload`. Treat `sync.failed` as advisory (the mutation itself already succeeded) and re-check with `info`/`check` rather than re-running the mutation. Reload before judging whether a change landed.\n\n## Registration of your own output\n\n`{\"action\":\"register_generated\",\"source\":\"/abs/path/to/generated/plugin\"}` registers a plugin directory you produced locally, without a copy step. It refuses any manifest that declares an `entryPoint`: this action is normally auto-approved and must never become a route to running code. For a code plugin, use `install` and then `activate`.\n\n## Approval contract\n\n- Read-only actions (`list`, `info`, `check`, `marketplace`) run without prompting.\n- Every mutating action (`install`, `register_generated`, `enable`, `disable`, `set_mcp_enabled`, `activate`, `deactivate`, `remove`, `reset`, `reload`) requires the user's approval. State what you are about to do and why in one line, then call the tool — never describe a plugin change you have not made.\n- The approval prompt for `install` and `register_generated` shows the full source string, and a session grant applies to that exact source only.\n- `activate` is the step that executes third-party code; treat it as its own decision, made after you have read what the plugin does.\n- A rejected approval is an answer, not a retry cue. Report the refusal and continue without the capability.\n\n## Output\n\nEvery action returns a JSON string. Success is a compact result object; failure is\n`{\"error\":{\"code\",\"message\",\"next\"}}` with `isError: true`. Follow `next` rather than\nguessing at a repair — it names the call that resolves the problem.\n";
|
|
75406
75409
|
//#endregion
|
|
75407
75410
|
//#region ../../packages/agent-core/src/tools/builtin/plugin/manage-plugin.ts
|
|
75408
75411
|
/** Every action this tool understands. */
|
|
@@ -77139,7 +77142,7 @@ function describeError(error) {
|
|
|
77139
77142
|
}
|
|
77140
77143
|
//#endregion
|
|
77141
77144
|
//#region ../../packages/agent-core/src/tools/builtin/state/inspect-own-assets.md
|
|
77142
|
-
var inspect_own_assets_default = "Use this tool to inspect the agent's own persistent assets: skills, MCP server declarations, configuration files, the memory store, and the knowledge base. It reports what exists, where it lives, and whether it looks valid.\n\n**When to use:**\n- The user asks \"what skills do you have?\", \"show me your mcp config\", \"how is your memory set up?\", \"where is your knowledge base?\"\n- Auditing your own configuration and data (e.g. checking whether mcp.json parses, whether skill frontmatter is intact)\n\nYou must NOT modify any of these assets unless the user explicitly asks you to — this tool is strictly read-only.\n\n**When NOT to use:**\n- Reading the user's workspace files — use `read` / `glob` / `grep` instead\n- Writing or editing anything — this tool is strictly read-only\n\n**How to use:**\n- Call with no arguments (or `scope: \"all\"`) to inspect everything\n- Narrow with `scope: \"skills\"` / `\"mcp\"` / `\"config\"` / `\"memory\"` / `\"knowledge\"` to inspect a single category\n\nThis tool never writes, creates, or modifies any file.\n";
|
|
77145
|
+
var inspect_own_assets_default = "Use this tool to inspect the agent's own persistent assets: skills, MCP server declarations, configuration files, the memory store, and the knowledge base. It reports what exists, where it lives, and whether it looks valid.\n\n**When to use:**\n- The user asks \"what skills do you have?\", \"show me your mcp config\", \"how is your memory set up?\", \"where is your knowledge base?\"\n- Auditing your own configuration and data (e.g. checking whether mcp.json parses, whether skill frontmatter is intact)\n\n**Inventory questions — this tool is the single answering view.** When the user asks what you have, in ANY wording (skills / plugins / capabilities / MCP / tools / 技能 / 插件 / 能力), treat it as one intent and answer from this inventory: it reports the skill packages in the three standard skill scopes (user, plugin-managed, project) with live `invocable` status from the skill registry, plus MCP declarations. Skills discovered from non-standard locations (nested directories, `.agents/skills`) may not appear here. Pair it with the system-prompt skills section for the \"callable right now\" view. Division of labor: **InspectOwnAssets = inventory (read-only)**, **ManagePlugin = changes (install/enable/remove)**, **Skill tool = invocation**.\n\nYou must NOT modify any of these assets unless the user explicitly asks you to — this tool is strictly read-only.\n\n**When NOT to use:**\n- Reading the user's workspace files — use `read` / `glob` / `grep` instead\n- Writing or editing anything — this tool is strictly read-only\n\n**How to use:**\n- Call with no arguments (or `scope: \"all\"`) to inspect everything\n- Narrow with `scope: \"skills\"` / `\"mcp\"` / `\"config\"` / `\"memory\"` / `\"knowledge\"` to inspect a single category\n\nThis tool never writes, creates, or modifies any file.\n";
|
|
77143
77146
|
const InspectOwnAssetsInputSchema = z.object({ scope: z.enum([
|
|
77144
77147
|
"all",
|
|
77145
77148
|
"skills",
|
|
@@ -77232,17 +77235,20 @@ async function listSkills(dir) {
|
|
|
77232
77235
|
if (!await isSkillDir(join$1(dir, entry.name))) continue;
|
|
77233
77236
|
const skillMd = join$1(dir, entry.name, "SKILL.md");
|
|
77234
77237
|
const fm = await checkFrontmatter(skillMd);
|
|
77238
|
+
const skillName = await readSkillName(skillMd) ?? entry.name;
|
|
77235
77239
|
out.push({
|
|
77236
|
-
name:
|
|
77240
|
+
name: skillName,
|
|
77237
77241
|
path: skillMd,
|
|
77238
77242
|
kind: "dir",
|
|
77239
77243
|
frontmatter: fm
|
|
77240
77244
|
});
|
|
77241
77245
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
77242
77246
|
if (DOCUMENTATION_MARKDOWN_LOWER.has(entry.name.toLowerCase())) continue;
|
|
77247
|
+
const path = join$1(dir, entry.name);
|
|
77248
|
+
const skillName = await readSkillName(path) ?? entry.name.slice(0, -3);
|
|
77243
77249
|
out.push({
|
|
77244
|
-
name:
|
|
77245
|
-
path
|
|
77250
|
+
name: skillName,
|
|
77251
|
+
path,
|
|
77246
77252
|
kind: "flat",
|
|
77247
77253
|
frontmatter: "ok"
|
|
77248
77254
|
});
|
|
@@ -77250,8 +77256,12 @@ async function listSkills(dir) {
|
|
|
77250
77256
|
}
|
|
77251
77257
|
return out.toSorted((a, b) => a.name.localeCompare(b.name));
|
|
77252
77258
|
}
|
|
77253
|
-
function
|
|
77254
|
-
return
|
|
77259
|
+
function buildInvocableNameSet(agent) {
|
|
77260
|
+
return new Set((agent.skills?.registry.listInvocableSkills() ?? []).map((s) => s.name));
|
|
77261
|
+
}
|
|
77262
|
+
function formatSkillEntry(entry, invocable) {
|
|
77263
|
+
const origin = entry.plugin === void 0 ? "" : ` — plugin: ${entry.plugin}`;
|
|
77264
|
+
return `- ${entry.name} — ${entry.kind === "dir" ? "dir" : "flat"} — ${entry.frontmatter} — ${invocable ? "invocable" : "not invocable"}${origin} — \`${entry.path}\``;
|
|
77255
77265
|
}
|
|
77256
77266
|
async function inspectConfig(home, userHome) {
|
|
77257
77267
|
const items = [
|
|
@@ -77267,27 +77277,66 @@ async function inspectConfig(home, userHome) {
|
|
|
77267
77277
|
}
|
|
77268
77278
|
return lines.join("\n");
|
|
77269
77279
|
}
|
|
77270
|
-
async function inspectSkills(home, userHome, cwd) {
|
|
77280
|
+
async function inspectSkills(home, userHome, cwd, agent) {
|
|
77271
77281
|
const { userDir, projectDir } = await resolveSkillInstallPaths({
|
|
77272
77282
|
userHomeDir: userHome,
|
|
77273
77283
|
workDir: cwd
|
|
77274
77284
|
});
|
|
77285
|
+
const invocableNames = buildInvocableNameSet(agent);
|
|
77275
77286
|
const sections = ["## Skills", ""];
|
|
77287
|
+
let invocableCount = 0;
|
|
77288
|
+
let totalCount = 0;
|
|
77289
|
+
const isInvocable = (entry) => invocableNames.has(entry.name) || entry.plugin !== void 0 && invocableNames.has(`${entry.plugin}:${entry.name}`);
|
|
77290
|
+
const track = (entry, invocable) => {
|
|
77291
|
+
totalCount++;
|
|
77292
|
+
if (invocable) invocableCount++;
|
|
77293
|
+
return formatSkillEntry(entry, invocable);
|
|
77294
|
+
};
|
|
77276
77295
|
const userEntries = await listSkills(userDir);
|
|
77277
77296
|
sections.push(`User skills (${userDir}): ${userEntries.length === 0 ? "none" : ""}`);
|
|
77278
|
-
sections.push(...userEntries.
|
|
77297
|
+
sections.push(...userEntries.map((e) => track(e, isInvocable(e))));
|
|
77279
77298
|
const extraDir = join$1(home, "plugins", "managed");
|
|
77280
77299
|
const extraEntries = await listManagedSkills(extraDir);
|
|
77281
77300
|
sections.push("");
|
|
77282
77301
|
sections.push(`Plugin-managed skills (${extraDir}): ${extraEntries.length === 0 ? "none" : ""}`);
|
|
77283
|
-
sections.push(...extraEntries.
|
|
77302
|
+
sections.push(...extraEntries.map((e) => track(e, isInvocable(e))));
|
|
77284
77303
|
const projectEntries = await listSkills(projectDir);
|
|
77285
77304
|
sections.push("");
|
|
77286
77305
|
sections.push(`Project skills (${projectDir}): ${projectEntries.length === 0 ? "none" : ""}`);
|
|
77287
|
-
sections.push(...projectEntries.
|
|
77306
|
+
sections.push(...projectEntries.map((e) => track(e, isInvocable(e))));
|
|
77307
|
+
sections.push("");
|
|
77308
|
+
sections.push(`Invocable now: ${invocableCount}/${totalCount} (against the live skill registry; entries marked "not invocable" exist on disk but are disabled, shadowed, renamed, or broken)`);
|
|
77288
77309
|
return sections.join("\n");
|
|
77289
77310
|
}
|
|
77290
77311
|
/**
|
|
77312
|
+
* Extracts the skill name from SKILL.md frontmatter (best effort) so the
|
|
77313
|
+
* inventory name matches what the skill registry holds; returns null when
|
|
77314
|
+
* frontmatter is missing or has no name line.
|
|
77315
|
+
*/
|
|
77316
|
+
async function readSkillName(path) {
|
|
77317
|
+
let handle;
|
|
77318
|
+
try {
|
|
77319
|
+
handle = await open(path, "r");
|
|
77320
|
+
const buffer = Buffer.alloc(FRONTMATTER_READ_LIMIT);
|
|
77321
|
+
const { bytesRead } = await handle.read(buffer, 0, FRONTMATTER_READ_LIMIT, 0);
|
|
77322
|
+
const head = buffer.subarray(0, bytesRead).toString("utf-8").split("\n").slice(0, 25);
|
|
77323
|
+
if (head[0]?.trim() !== "---") return null;
|
|
77324
|
+
for (const line of head.slice(1)) {
|
|
77325
|
+
if (line.trim() === "---") break;
|
|
77326
|
+
const m = /^name\s*:\s*(.+)$/.exec(line);
|
|
77327
|
+
if (m !== null) {
|
|
77328
|
+
const value = m[1].trim().replaceAll(/^["']|["']$/g, "");
|
|
77329
|
+
return value.length > 0 ? value : null;
|
|
77330
|
+
}
|
|
77331
|
+
}
|
|
77332
|
+
return null;
|
|
77333
|
+
} catch {
|
|
77334
|
+
return null;
|
|
77335
|
+
} finally {
|
|
77336
|
+
await handle?.close().catch(() => {});
|
|
77337
|
+
}
|
|
77338
|
+
}
|
|
77339
|
+
/**
|
|
77291
77340
|
* List plugin-managed skills: each `<dir>/SKILL.md` under a managed plugin
|
|
77292
77341
|
* directory is a skill entry (Extra source, mirroring plugin/manager.ts).
|
|
77293
77342
|
*/
|
|
@@ -77304,11 +77353,13 @@ async function listManagedSkills(managedDir) {
|
|
|
77304
77353
|
const skillMd = join$1(managedDir, plugin.name, "SKILL.md");
|
|
77305
77354
|
if (!await isSkillDir(join$1(managedDir, plugin.name))) continue;
|
|
77306
77355
|
const fm = await checkFrontmatter(skillMd);
|
|
77356
|
+
const skillName = await readSkillName(skillMd) ?? plugin.name;
|
|
77307
77357
|
out.push({
|
|
77308
|
-
name:
|
|
77358
|
+
name: skillName,
|
|
77309
77359
|
path: skillMd,
|
|
77310
77360
|
kind: "dir",
|
|
77311
|
-
frontmatter: fm
|
|
77361
|
+
frontmatter: fm,
|
|
77362
|
+
plugin: plugin.name
|
|
77312
77363
|
});
|
|
77313
77364
|
}
|
|
77314
77365
|
return out.toSorted((a, b) => a.name.localeCompare(b.name));
|
|
@@ -77404,7 +77455,7 @@ var InspectOwnAssetsTool = class {
|
|
|
77404
77455
|
const scope = args.scope ?? "all";
|
|
77405
77456
|
const sections = [];
|
|
77406
77457
|
if (scope === "all" || scope === "config") sections.push(await inspectConfig(home, userHome));
|
|
77407
|
-
if (scope === "all" || scope === "skills") sections.push(await inspectSkills(home, userHome, cwd));
|
|
77458
|
+
if (scope === "all" || scope === "skills") sections.push(await inspectSkills(home, userHome, cwd, this.agent));
|
|
77408
77459
|
if (scope === "all" || scope === "mcp") sections.push(await inspectMcp(home, cwd));
|
|
77409
77460
|
if (scope === "all" || scope === "memory") sections.push(await inspectMemory(home));
|
|
77410
77461
|
if (scope === "all" || scope === "knowledge") sections.push(await inspectKnowledge(home));
|
|
@@ -125389,6 +125440,92 @@ const PULSE_WAVE_FRAMES = [
|
|
|
125389
125440
|
}
|
|
125390
125441
|
];
|
|
125391
125442
|
//#endregion
|
|
125443
|
+
//#region src/tui/commands/knowledge-store.ts
|
|
125444
|
+
let knowledgeStoreInstance;
|
|
125445
|
+
let embeddingEngineInstance;
|
|
125446
|
+
let embeddingStatus = "idle";
|
|
125447
|
+
function getEmbeddingCacheDir() {
|
|
125448
|
+
const dir = join(getDataDir(), "cache", "fastembed");
|
|
125449
|
+
mkdirSync(dir, { recursive: true });
|
|
125450
|
+
return dir;
|
|
125451
|
+
}
|
|
125452
|
+
/** Subdirectory fastembed uses for the BGESmallZH model inside the cache dir. */
|
|
125453
|
+
const EMBEDDING_MODEL_DIR = "fast-bge-small-zh-v1.5";
|
|
125454
|
+
/**
|
|
125455
|
+
* Whether the embedding model has been downloaded to the local cache.
|
|
125456
|
+
* Checks the ONNX weights plus the config and tokenizer sidecars — all
|
|
125457
|
+
* required for FlagEmbedding.init to load without network access (a missing
|
|
125458
|
+
* tokenizer would trigger a network fetch and violate the warm-up's
|
|
125459
|
+
* offline-load guarantee).
|
|
125460
|
+
*/
|
|
125461
|
+
function isEmbeddingModelCached() {
|
|
125462
|
+
const modelDir = join(getEmbeddingCacheDir(), EMBEDDING_MODEL_DIR);
|
|
125463
|
+
return existsSync(join(modelDir, "model_optimized.onnx")) && existsSync(join(modelDir, "config.json")) && existsSync(join(modelDir, "tokenizer.json"));
|
|
125464
|
+
}
|
|
125465
|
+
async function getKnowledgeStore() {
|
|
125466
|
+
if (knowledgeStoreInstance === void 0) {
|
|
125467
|
+
knowledgeStoreInstance = new KnowledgeStore(getDataDir());
|
|
125468
|
+
await knowledgeStoreInstance.init();
|
|
125469
|
+
embeddingEngineInstance = createFastEmbedEngine(getEmbeddingCacheDir());
|
|
125470
|
+
knowledgeStoreInstance.setEmbeddingEngine(embeddingEngineInstance);
|
|
125471
|
+
}
|
|
125472
|
+
return knowledgeStoreInstance;
|
|
125473
|
+
}
|
|
125474
|
+
function getEmbeddingStatus() {
|
|
125475
|
+
return embeddingStatus;
|
|
125476
|
+
}
|
|
125477
|
+
/**
|
|
125478
|
+
* Manually trigger the embedding model download/load.
|
|
125479
|
+
* Only mutates embeddingStatus; the actual download is delegated to
|
|
125480
|
+
* EmbeddingEngine.ensureReady() and saves the model to the shared cache dir.
|
|
125481
|
+
* Returns { ok: true } on success, or { ok: false, error } on failure.
|
|
125482
|
+
* Concurrent calls join the in-flight download and share its result instead
|
|
125483
|
+
* of failing — the startup warm-up and a user-initiated download must never
|
|
125484
|
+
* race into a spurious "download already in progress" error.
|
|
125485
|
+
*/
|
|
125486
|
+
async function startManualEmbeddingDownload() {
|
|
125487
|
+
if (embeddingEngineInstance === void 0) return {
|
|
125488
|
+
ok: false,
|
|
125489
|
+
error: "embedding engine not initialized"
|
|
125490
|
+
};
|
|
125491
|
+
if (embeddingEngineInstance.available) {
|
|
125492
|
+
embeddingStatus = "ready";
|
|
125493
|
+
return {
|
|
125494
|
+
ok: true,
|
|
125495
|
+
alreadyReady: true
|
|
125496
|
+
};
|
|
125497
|
+
}
|
|
125498
|
+
if (downloadPromise !== void 0) return downloadPromise;
|
|
125499
|
+
embeddingStatus = "downloading";
|
|
125500
|
+
downloadPromise = performDownload().finally(() => {
|
|
125501
|
+
downloadPromise = void 0;
|
|
125502
|
+
});
|
|
125503
|
+
return downloadPromise;
|
|
125504
|
+
}
|
|
125505
|
+
let downloadPromise;
|
|
125506
|
+
async function performDownload() {
|
|
125507
|
+
try {
|
|
125508
|
+
let ok = await embeddingEngineInstance.ensureReady();
|
|
125509
|
+
let error = ok ? void 0 : embeddingEngineInstance.lastError;
|
|
125510
|
+
if (!ok) {
|
|
125511
|
+
clearEmbeddingModelCache(getEmbeddingCacheDir());
|
|
125512
|
+
ok = await embeddingEngineInstance.ensureReady();
|
|
125513
|
+
error = ok ? void 0 : embeddingEngineInstance.lastError;
|
|
125514
|
+
}
|
|
125515
|
+
embeddingStatus = ok ? "ready" : "failed";
|
|
125516
|
+
return {
|
|
125517
|
+
ok,
|
|
125518
|
+
error
|
|
125519
|
+
};
|
|
125520
|
+
} catch (error) {
|
|
125521
|
+
embeddingStatus = "failed";
|
|
125522
|
+
return {
|
|
125523
|
+
ok: false,
|
|
125524
|
+
error: error instanceof Error ? error.message : String(error)
|
|
125525
|
+
};
|
|
125526
|
+
}
|
|
125527
|
+
}
|
|
125528
|
+
//#endregion
|
|
125392
125529
|
//#region src/tui/commands/experimental-flags.ts
|
|
125393
125530
|
let snapshot = {};
|
|
125394
125531
|
/** Replace the cached flag snapshot. Call once after fetching via `harness.getExperimentalFlags()`. */
|
|
@@ -126698,31 +126835,16 @@ function getWireTypeOptions() {
|
|
|
126698
126835
|
}
|
|
126699
126836
|
function getThinkingOptions() {
|
|
126700
126837
|
return [
|
|
126701
|
-
|
|
126702
|
-
|
|
126703
|
-
|
|
126704
|
-
|
|
126705
|
-
|
|
126706
|
-
|
|
126707
|
-
|
|
126708
|
-
|
|
126709
|
-
|
|
126710
|
-
|
|
126711
|
-
label: t("prompts.thinking_medium")
|
|
126712
|
-
},
|
|
126713
|
-
{
|
|
126714
|
-
value: "high",
|
|
126715
|
-
label: t("prompts.thinking_high")
|
|
126716
|
-
},
|
|
126717
|
-
{
|
|
126718
|
-
value: "xhigh",
|
|
126719
|
-
label: t("prompts.thinking_xhigh")
|
|
126720
|
-
},
|
|
126721
|
-
{
|
|
126722
|
-
value: "max",
|
|
126723
|
-
label: t("prompts.thinking_max")
|
|
126724
|
-
}
|
|
126725
|
-
];
|
|
126838
|
+
"off",
|
|
126839
|
+
"low",
|
|
126840
|
+
"medium",
|
|
126841
|
+
"high",
|
|
126842
|
+
"xhigh",
|
|
126843
|
+
"max"
|
|
126844
|
+
].map((level) => ({
|
|
126845
|
+
value: level,
|
|
126846
|
+
label: level
|
|
126847
|
+
}));
|
|
126726
126848
|
}
|
|
126727
126849
|
function getImageOptions() {
|
|
126728
126850
|
return [{
|
|
@@ -131469,7 +131591,7 @@ async function guidedGoalSetup(host) {
|
|
|
131469
131591
|
host.showNotice(t("goal.storm_breaker"), t("goal.conflict_loop"));
|
|
131470
131592
|
return;
|
|
131471
131593
|
}
|
|
131472
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
131594
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-Dr42qLMU.mjs");
|
|
131473
131595
|
const initialDesc = await promptText(host, TextInputDialogComponent, {
|
|
131474
131596
|
title: t("goal.setup_title_initial"),
|
|
131475
131597
|
subtitle: t("goal.setup_desc_hint"),
|
|
@@ -131490,7 +131612,7 @@ async function guidedGoalSetup(host) {
|
|
|
131490
131612
|
await showGoalConfigWizard(host, session, confirmed.trim() || objective, false);
|
|
131491
131613
|
}
|
|
131492
131614
|
async function showGoalConfigWizard(host, session, objective, replace) {
|
|
131493
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
131615
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-Dr42qLMU.mjs");
|
|
131494
131616
|
const turnInput = await promptNumber(host, TextInputDialogComponent, {
|
|
131495
131617
|
title: t("goal.wizard_title", { objective }),
|
|
131496
131618
|
subtitle: t("goal.budget_turns_hint"),
|
|
@@ -138296,7 +138418,7 @@ function buildRoleAdditionalText(prefs) {
|
|
|
138296
138418
|
if (items.length === 0 && (doNot === void 0 || doNot.length === 0) && !hasToolPriority) return "";
|
|
138297
138419
|
lines.push("", ...items);
|
|
138298
138420
|
if (doNot !== void 0 && doNot.length > 0) lines.push("", "## Do NOT (explicit prohibitions — NEVER do these)", doNot);
|
|
138299
|
-
if (hasToolPriority) lines.push("", "## Tool priority (set via /like — HIGHEST PRIORITY)", prefs.toolPriority === "skill" ? "For every user request: (1) first analyze the intent, (2) then identify whether any installed skill matches THIS request, (3) if one matches, invoke the Skill tool with it as your FIRST action — before MCP tools or doing it yourself, (4) if none matches, proceed with MCP tools or solve it yourself.
|
|
138421
|
+
if (hasToolPriority) lines.push("", "## Tool priority (set via /like — HIGHEST PRIORITY)", prefs.toolPriority === "skill" ? "For every user request: (1) first analyze the intent, (2) then identify whether any installed skill matches THIS request, (3) if one matches, invoke the Skill tool with it as your FIRST action — before MCP tools or doing it yourself, (4) if none matches, proceed with MCP tools or solve it yourself. When the user asks what you have (skills / plugins / capabilities, any wording), answer from an InspectOwnAssets inventory; the skills section of the system prompt is the authoritative view of what is invocable right now." : "For every user request: (1) first analyze the intent, (2) then identify whether any available MCP tool matches THIS request, (3) if one matches, use it as your FIRST action — before the Skill tool or doing it yourself, (4) if none matches, proceed with the Skill tool or solve it yourself.");
|
|
138300
138422
|
lines.push("", t("like.priority"));
|
|
138301
138423
|
return lines.join("\n");
|
|
138302
138424
|
}
|
|
@@ -138426,65 +138548,6 @@ function openUrl(url) {
|
|
|
138426
138548
|
execFile(command[0], command[1], () => {});
|
|
138427
138549
|
}
|
|
138428
138550
|
//#endregion
|
|
138429
|
-
//#region src/tui/commands/knowledge-store.ts
|
|
138430
|
-
let knowledgeStoreInstance;
|
|
138431
|
-
let embeddingEngineInstance;
|
|
138432
|
-
let embeddingStatus = "idle";
|
|
138433
|
-
function getEmbeddingCacheDir() {
|
|
138434
|
-
const dir = join(getDataDir(), "cache", "fastembed");
|
|
138435
|
-
mkdirSync(dir, { recursive: true });
|
|
138436
|
-
return dir;
|
|
138437
|
-
}
|
|
138438
|
-
async function getKnowledgeStore() {
|
|
138439
|
-
if (knowledgeStoreInstance === void 0) {
|
|
138440
|
-
knowledgeStoreInstance = new KnowledgeStore(getDataDir());
|
|
138441
|
-
await knowledgeStoreInstance.init();
|
|
138442
|
-
embeddingEngineInstance = createFastEmbedEngine(getEmbeddingCacheDir());
|
|
138443
|
-
knowledgeStoreInstance.setEmbeddingEngine(embeddingEngineInstance);
|
|
138444
|
-
}
|
|
138445
|
-
return knowledgeStoreInstance;
|
|
138446
|
-
}
|
|
138447
|
-
function getEmbeddingStatus() {
|
|
138448
|
-
return embeddingStatus;
|
|
138449
|
-
}
|
|
138450
|
-
/**
|
|
138451
|
-
* Manually trigger the embedding model download/load.
|
|
138452
|
-
* Only mutates embeddingStatus; the actual download is delegated to
|
|
138453
|
-
* EmbeddingEngine.ensureReady() and saves the model to the shared cache dir.
|
|
138454
|
-
* Returns { ok: true } on success, or { ok: false, error } on failure.
|
|
138455
|
-
* Concurrent calls while a download is already in flight are ignored.
|
|
138456
|
-
*/
|
|
138457
|
-
async function startManualEmbeddingDownload() {
|
|
138458
|
-
if (embeddingEngineInstance === void 0) return {
|
|
138459
|
-
ok: false,
|
|
138460
|
-
error: "embedding engine not initialized"
|
|
138461
|
-
};
|
|
138462
|
-
if (embeddingStatus === "downloading") return {
|
|
138463
|
-
ok: false,
|
|
138464
|
-
error: "download already in progress"
|
|
138465
|
-
};
|
|
138466
|
-
if (embeddingEngineInstance.available) {
|
|
138467
|
-
embeddingStatus = "ready";
|
|
138468
|
-
return {
|
|
138469
|
-
ok: true,
|
|
138470
|
-
alreadyReady: true
|
|
138471
|
-
};
|
|
138472
|
-
}
|
|
138473
|
-
embeddingStatus = "downloading";
|
|
138474
|
-
let ok = await embeddingEngineInstance.ensureReady();
|
|
138475
|
-
let error = ok ? void 0 : embeddingEngineInstance.lastError;
|
|
138476
|
-
if (!ok) {
|
|
138477
|
-
clearEmbeddingModelCache(getEmbeddingCacheDir());
|
|
138478
|
-
ok = await embeddingEngineInstance.ensureReady();
|
|
138479
|
-
error = ok ? void 0 : embeddingEngineInstance.lastError;
|
|
138480
|
-
}
|
|
138481
|
-
embeddingStatus = ok ? "ready" : "failed";
|
|
138482
|
-
return {
|
|
138483
|
-
ok,
|
|
138484
|
-
error
|
|
138485
|
-
};
|
|
138486
|
-
}
|
|
138487
|
-
//#endregion
|
|
138488
138551
|
//#region src/tui/commands/knowledge-web.ts
|
|
138489
138552
|
/**
|
|
138490
138553
|
* /knowledge web — 知识图谱可视化
|
|
@@ -140174,6 +140237,7 @@ async function handleIngest(host) {
|
|
|
140174
140237
|
}
|
|
140175
140238
|
const store = await getKnowledgeStore();
|
|
140176
140239
|
const llm = makeLlmCaller(host);
|
|
140240
|
+
if (!await ensureEmbeddingReadyInteractive(host)) return;
|
|
140177
140241
|
const spinner = host.showProgressSpinner(t("knowledge.ingesting"));
|
|
140178
140242
|
try {
|
|
140179
140243
|
if (stats.isDirectory()) {
|
|
@@ -140184,21 +140248,35 @@ async function handleIngest(host) {
|
|
|
140184
140248
|
ok: result.failed === 0,
|
|
140185
140249
|
label: t("knowledge.batch_done")
|
|
140186
140250
|
});
|
|
140251
|
+
const coverage = await store.embeddingCoverage();
|
|
140252
|
+
const syncLine = t("knowledge.sync_counts", {
|
|
140253
|
+
created: String(result.created),
|
|
140254
|
+
updated: String(result.updated),
|
|
140255
|
+
unchanged: String(result.unchanged)
|
|
140256
|
+
});
|
|
140187
140257
|
if (result.failed > 0) {
|
|
140188
140258
|
const summary = [
|
|
140189
140259
|
t("knowledge.succeeded", { count: String(result.succeeded) }),
|
|
140260
|
+
syncLine,
|
|
140190
140261
|
t("knowledge.failed", { count: String(result.failed) }),
|
|
140191
140262
|
t("knowledge.ingest_summary", {
|
|
140192
140263
|
chunks: String(result.totalChunks),
|
|
140193
140264
|
events: String(result.totalEvents),
|
|
140194
140265
|
entities: String(result.totalEntities)
|
|
140195
140266
|
}),
|
|
140267
|
+
t("knowledge.vector_coverage", {
|
|
140268
|
+
embedded: String(coverage.embedded),
|
|
140269
|
+
total: String(coverage.total)
|
|
140270
|
+
}),
|
|
140196
140271
|
"",
|
|
140197
140272
|
t("knowledge.failed_files"),
|
|
140198
140273
|
...result.errors.map((e) => ` • ${basename(e.filePath)}: ${e.message}`)
|
|
140199
140274
|
].join("\n");
|
|
140200
140275
|
host.showNotice(t("knowledge.batch_partial"), summary);
|
|
140201
|
-
} else host.showNotice(t("knowledge.batch_done"), `${
|
|
140276
|
+
} else host.showNotice(t("knowledge.batch_done"), `${syncLine}\n${result.totalChunks} chunks, ${result.totalEvents} events, ${result.totalEntities} entities\n${t("knowledge.vector_coverage", {
|
|
140277
|
+
embedded: String(coverage.embedded),
|
|
140278
|
+
total: String(coverage.total)
|
|
140279
|
+
})}`);
|
|
140202
140280
|
} else {
|
|
140203
140281
|
if (!isSupportedFile(filePath)) {
|
|
140204
140282
|
spinner.stop({
|
|
@@ -140211,11 +140289,19 @@ async function handleIngest(host) {
|
|
|
140211
140289
|
const result = await ingestFile(store, llm, filePath, (progress) => {
|
|
140212
140290
|
spinner.setLabel(formatProgress(progress));
|
|
140213
140291
|
});
|
|
140292
|
+
const outcomeLabel = result.outcome === "unchanged" ? t("knowledge.ingest_unchanged") : result.outcome === "updated" ? t("knowledge.ingest_updated") : t("knowledge.ingest_done");
|
|
140214
140293
|
spinner.stop({
|
|
140215
140294
|
ok: true,
|
|
140216
|
-
label:
|
|
140295
|
+
label: outcomeLabel
|
|
140217
140296
|
});
|
|
140218
|
-
host.showNotice(
|
|
140297
|
+
if (result.outcome === "unchanged") host.showNotice(outcomeLabel, `${t("knowledge.file_label")}: ${basename(filePath)}`);
|
|
140298
|
+
else {
|
|
140299
|
+
const coverage = await store.embeddingCoverage();
|
|
140300
|
+
host.showNotice(outcomeLabel, `${t("knowledge.file_label")}: ${basename(filePath)}\nchunks: ${result.chunkCount}\nevents: ${result.eventCount}\nentities: ${result.entityCount}\n${t("knowledge.vector_coverage", {
|
|
140301
|
+
embedded: String(coverage.embedded),
|
|
140302
|
+
total: String(coverage.total)
|
|
140303
|
+
})}`);
|
|
140304
|
+
}
|
|
140219
140305
|
}
|
|
140220
140306
|
} catch (error) {
|
|
140221
140307
|
spinner.stop({
|
|
@@ -140225,6 +140311,31 @@ async function handleIngest(host) {
|
|
|
140225
140311
|
throw error;
|
|
140226
140312
|
}
|
|
140227
140313
|
}
|
|
140314
|
+
/**
|
|
140315
|
+
* Ensure the shared embedding engine is ready before a vector-dependent
|
|
140316
|
+
* operation. Returns true when ready; otherwise shows an error (missing
|
|
140317
|
+
* download) or attempts a cached-model load and reports the outcome.
|
|
140318
|
+
*/
|
|
140319
|
+
async function ensureEmbeddingReadyInteractive(host) {
|
|
140320
|
+
const engine = (await getKnowledgeStore()).getEmbeddingEngine();
|
|
140321
|
+
if (engine !== void 0 && engine.available) return true;
|
|
140322
|
+
if (!isEmbeddingModelCached()) {
|
|
140323
|
+
host.showError(t("knowledge.model_missing"));
|
|
140324
|
+
return false;
|
|
140325
|
+
}
|
|
140326
|
+
const spinner = host.showProgressSpinner(t("knowledge.loading_model"));
|
|
140327
|
+
const { ok, error } = await startManualEmbeddingDownload();
|
|
140328
|
+
spinner.stop({
|
|
140329
|
+
ok,
|
|
140330
|
+
label: ok ? t("kw.embedding_ready") : t("kw.embedding_failed")
|
|
140331
|
+
});
|
|
140332
|
+
if (!ok) {
|
|
140333
|
+
const detail = [t("knowledge.download_model_retry_hint"), error].filter(Boolean).join("\n");
|
|
140334
|
+
host.showNotice(t("knowledge.model_load_failed"), detail);
|
|
140335
|
+
return false;
|
|
140336
|
+
}
|
|
140337
|
+
return true;
|
|
140338
|
+
}
|
|
140228
140339
|
async function handleList(host) {
|
|
140229
140340
|
const store = await getKnowledgeStore();
|
|
140230
140341
|
const docs = await store.listDocuments();
|
|
@@ -140374,6 +140485,97 @@ async function handleDelete(host) {
|
|
|
140374
140485
|
if (await store.deleteSource(sourceId)) host.showNotice(t("knowledge.deleted"), t("knowledge.doc_removed"));
|
|
140375
140486
|
else host.showError(t("knowledge.delete_fail_not_found"));
|
|
140376
140487
|
}
|
|
140488
|
+
function pickSourceToReembed(host, sources) {
|
|
140489
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
140490
|
+
const options = sources.map((s) => ({
|
|
140491
|
+
value: s.id,
|
|
140492
|
+
label: s.name,
|
|
140493
|
+
description: s.filePath ?? void 0
|
|
140494
|
+
}));
|
|
140495
|
+
const picker = new ChoicePickerComponent({
|
|
140496
|
+
title: t("knowledge.reembed_pick"),
|
|
140497
|
+
options,
|
|
140498
|
+
colors: host.state.theme.colors,
|
|
140499
|
+
onSelect: (value) => {
|
|
140500
|
+
host.restoreEditor();
|
|
140501
|
+
resolve(value);
|
|
140502
|
+
},
|
|
140503
|
+
onCancel: () => {
|
|
140504
|
+
host.restoreEditor();
|
|
140505
|
+
resolve(void 0);
|
|
140506
|
+
}
|
|
140507
|
+
});
|
|
140508
|
+
host.mountEditorReplacement(picker);
|
|
140509
|
+
return promise;
|
|
140510
|
+
}
|
|
140511
|
+
function confirmReembedSource(host, source) {
|
|
140512
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
140513
|
+
const options = [{
|
|
140514
|
+
value: "cancel",
|
|
140515
|
+
label: t("common.cancel")
|
|
140516
|
+
}, {
|
|
140517
|
+
value: "confirm",
|
|
140518
|
+
label: t("knowledge.reembed"),
|
|
140519
|
+
description: t("knowledge.reembed_confirm_desc")
|
|
140520
|
+
}];
|
|
140521
|
+
const picker = new ChoicePickerComponent({
|
|
140522
|
+
title: t("knowledge.reembed_confirm_name", { name: source.name }),
|
|
140523
|
+
options,
|
|
140524
|
+
colors: host.state.theme.colors,
|
|
140525
|
+
onSelect: (value) => {
|
|
140526
|
+
host.restoreEditor();
|
|
140527
|
+
resolve(value === "confirm");
|
|
140528
|
+
},
|
|
140529
|
+
onCancel: () => {
|
|
140530
|
+
host.restoreEditor();
|
|
140531
|
+
resolve(false);
|
|
140532
|
+
}
|
|
140533
|
+
});
|
|
140534
|
+
host.mountEditorReplacement(picker);
|
|
140535
|
+
return promise;
|
|
140536
|
+
}
|
|
140537
|
+
async function handleReembed(host) {
|
|
140538
|
+
const store = await getKnowledgeStore();
|
|
140539
|
+
const sources = await store.listSources();
|
|
140540
|
+
if (sources.length === 0) {
|
|
140541
|
+
host.showNotice(t("knowledge.empty"), t("knowledge.reembed_none"));
|
|
140542
|
+
return;
|
|
140543
|
+
}
|
|
140544
|
+
const sourceId = await pickSourceToReembed(host, sources);
|
|
140545
|
+
if (sourceId === void 0) return;
|
|
140546
|
+
const source = sources.find((s) => s.id === sourceId);
|
|
140547
|
+
if (source === void 0) return;
|
|
140548
|
+
if (!await confirmReembedSource(host, source)) {
|
|
140549
|
+
host.showNotice(t("knowledge.cancelled"));
|
|
140550
|
+
return;
|
|
140551
|
+
}
|
|
140552
|
+
if (!await ensureEmbeddingReadyInteractive(host)) return;
|
|
140553
|
+
const engine = store.getEmbeddingEngine();
|
|
140554
|
+
if (engine === void 0) {
|
|
140555
|
+
host.showError(t("knowledge.model_missing"));
|
|
140556
|
+
return;
|
|
140557
|
+
}
|
|
140558
|
+
const spinner = host.showProgressSpinner(t("knowledge.reembed"));
|
|
140559
|
+
try {
|
|
140560
|
+
const counts = await store.reembedSource(sourceId, engine);
|
|
140561
|
+
spinner.stop({
|
|
140562
|
+
ok: true,
|
|
140563
|
+
label: t("knowledge.reembed_done")
|
|
140564
|
+
});
|
|
140565
|
+
host.showNotice(t("knowledge.reembed_done"), t("knowledge.reembed_summary", {
|
|
140566
|
+
chunks: String(counts.chunks),
|
|
140567
|
+
events: String(counts.events),
|
|
140568
|
+
entities: String(counts.entities),
|
|
140569
|
+
relations: String(counts.relations)
|
|
140570
|
+
}));
|
|
140571
|
+
} catch (error) {
|
|
140572
|
+
spinner.stop({
|
|
140573
|
+
ok: false,
|
|
140574
|
+
label: t("knowledge.reembed")
|
|
140575
|
+
});
|
|
140576
|
+
throw error;
|
|
140577
|
+
}
|
|
140578
|
+
}
|
|
140377
140579
|
async function handleDownloadModel(host) {
|
|
140378
140580
|
await getKnowledgeStore();
|
|
140379
140581
|
const spinner = host.showProgressSpinner(t("kw.embedding_downloading"));
|
|
@@ -140455,6 +140657,11 @@ async function handleKnowledgeCommand(host, _args) {
|
|
|
140455
140657
|
description: t("knowledge.delete_desc"),
|
|
140456
140658
|
tone: "danger"
|
|
140457
140659
|
},
|
|
140660
|
+
{
|
|
140661
|
+
value: "reembed",
|
|
140662
|
+
label: "🔁 " + t("knowledge.reembed"),
|
|
140663
|
+
description: t("knowledge.reembed_desc")
|
|
140664
|
+
},
|
|
140458
140665
|
{
|
|
140459
140666
|
value: "stats",
|
|
140460
140667
|
label: "📊 " + t("knowledge.stats"),
|
|
@@ -140480,6 +140687,7 @@ async function handleKnowledgeCommand(host, _args) {
|
|
|
140480
140687
|
else if (value === "list") await handleList(host);
|
|
140481
140688
|
else if (value === "search") await handleSearch(host);
|
|
140482
140689
|
else if (value === "delete") await handleDelete(host);
|
|
140690
|
+
else if (value === "reembed") await handleReembed(host);
|
|
140483
140691
|
else if (value === "stats") await handleStats(host);
|
|
140484
140692
|
else if (value === "web") await handleWeb(host);
|
|
140485
140693
|
} catch (error) {
|
|
@@ -141127,4 +141335,4 @@ async function handleBuiltInSlashCommand(host, name, args) {
|
|
|
141127
141335
|
}
|
|
141128
141336
|
}
|
|
141129
141337
|
//#endregion
|
|
141130
|
-
export { handleTitleCommand as $, isTodoItemShape as $t, renderDiffLinesClustered as A,
|
|
141338
|
+
export { handleTitleCommand as $, isTodoItemShape as $t, renderDiffLinesClustered as A, getInputHistoryFile as An, ENABLE_TERMINAL_FOCUS_REPORTING as At, BackgroundAgentStatusComponent as B, ScreamHarness as Bn, TERMINAL_THEME_LIGHT as Bt, handleRevokeCommand as C, PULSE_WAVE_FRAMES as Cn, createThemeStyles as Ct, toggleEmptySessionHint as D, saveTuiConfig as Dn, parseOsc11BackgroundTheme as Dt, isTurnElapsedEnabled as E, loadTuiConfig as En, detectTerminalTheme as Et, estimateTokens as F, CLI_USER_AGENT_PRODUCT as Fn, OSC11_RESPONSE_PREFIX_NO_ESC as Ft, getBreathingFrame as G, log as Gn, handleSearchCommand as Gt, AgentGroupComponent as H, resolveScreamHome as Hn, isStreaming as Ht, getSharedSpeedTracker as I, PRODUCT_NAME as In, QUERY_TERMINAL_THEME as It, refineGoal as J, isOrphanedToolCallError as Jn, printableChar as Jt, resetBreathingClock as K, resolveGlobalLogPath as Kn, handleConnectCommand as Kt, SkillActivationComponent as L, DEFAULT_CATALOG_URL as Ln, TERMINAL_FOCUS_IN as Lt, langFromPath as M, detectInstallSource as Mn, OSC11_QUERY as Mt, CachedContainer as N, CLI_COMMAND_NAME as Nn, OSC11_RESPONSE as Nt, ToolCallComponent as O, detectShellEnvironment as On, DISABLE_TERMINAL_FOCUS_REPORTING as Ot, ThinkingComponent as P, CLI_UI_MODE as Pn, OSC11_RESPONSE_PREFIX as Pt, handleInitCommand as Q, formatErrorMessage as Qt, ReadGroupComponent as R, fetchCatalog as Rn, TERMINAL_FOCUS_OUT as Rt, getDaemonInstructions as S, PIXEL_PULSE_FRAMES as Sn, createMarkdownTheme as St, isEmptySessionHintDismissed as T, TuiLikePreferencesSchema as Tn, getColorPalette as Tt, WelcomeComponent as U, MemoryMemoStore as Un, FooterComponent as Ut, AssistantMessageComponent as V, MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE as Vn, isBusy as Vt, BREATHE_CYCLE_MS as W, flushDiagnosticLogs as Wn, handleTraceCommand as Wt, handleExportMdCommand as X, SCREAM_ERROR_INFO as Xn, appendStreamingArgsPreview as Xt, handleExportDebugZipCommand as Y, ErrorCodes as Yn, STATUS_BULLET as Yt, handleForkCommand as Z, argsRecord as Zt, refreshUpdateCache as _, isExperimentalFlagEnabled as _n, clearInfoPanelState as _t, handleExtensionCommand as a, EMPTY_SESSION_HINT_URL as an, handleEditorCommand as at, readJsonlFile as b, isEmbeddingModelCached as bn, resolveThemeSync as bt, hasDispose as c, SESSION_TIPS as cn, handlePlanCommand as ct, formatMemoryMemoForInjection as d, getCtrlDHint as dn, handleYoloCommand as dt, parseStreamingArgs as en, toTerminalHyperlink as et, handleMemoryCommand as f, getLlmNotSetMessage as fn, showModelPicker as ft, selectUpdateTarget as g, sortSlashCommands as gn, supportsBalance as gt, handleUpdateCommand as h, BUILTIN_SLASH_COMMANDS as hn, refreshProviderBalance as ht, buildRoleAdditionalText as i, CHARS_PER_TOKEN as in, handleCompactCommand as it, highlightLines as j, getLogDir as jn, ENABLE_TERMINAL_THEME_REPORTING as jt, renderDiffLines as k, getDataDir as kn, DISABLE_TERMINAL_THEME_REPORTING as kt, isPlanExpandable as l, TIP_ROTATION_INTERVAL_MS as ln, handleThemeCommand as lt, handleMcpCommand as m, buildSkillSlashCommands as mn, showSettingsSelector as mt, clearEvalPanelState as n, stringValue as nn, getModelCycleLevel as nt, handleSkillCommand as o, EXIT_CONFIRM_WINDOW_MS as on, handleFusionPlanCommand as ot, handleChannelCommand as p, getNoActiveSessionMessage as pn, showPermissionPicker as pt, clearGoalState as q, isScreamError as qn, handleLogoutCommand as qt, openUrl as r, truncateErrorMessage as rn, handleAutoCommand as rt, disposeChildren as s, MAIN_AGENT_ID$1 as sn, handleModelCommand as st, dispatchInput as t, serializeToolResultOutput as tn, changeThinkingLevel as tt, MoonLoader as u, getCtrlCHint as un, handleWolfpackCommand as ut, readUpdateCache as v, setExperimentalFlags as vn, showStatusReport as vt, UserMessageComponent as w, TuiConfigParseError as wn, contrastTextHex as wt, handleCcCommand as x, startManualEmbeddingDownload as xn, createEditorTheme as xt, appendJsonlLine as y, getKnowledgeStore as yn, showUsage as yt, parseReadGroupOutput as z, saveCatalogCache as zn, TERMINAL_THEME_DARK as zt };
|