@falkenslab/agent-kit 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -110
- package/assets/knowledge-plugin/.claude-plugin/plugin.json +1 -1
- package/assets/knowledge-plugin/commands/ingest.md +1 -1
- package/assets/knowledge-plugin/commands/lint.md +1 -1
- package/assets/knowledge-plugin/skills/knowledge-ingest/SKILL.md +13 -19
- package/assets/knowledge-plugin/skills/knowledge-lint/SKILL.md +18 -14
- package/assets/knowledge-plugin/skills/knowledge-query/SKILL.md +5 -5
- package/assets/knowledge-plugin-files/.claude-plugin/plugin.json +4 -0
- package/assets/knowledge-plugin-files/commands/ingest.md +7 -0
- package/assets/knowledge-plugin-files/commands/lint.md +5 -0
- package/assets/knowledge-plugin-files/commands/query.md +5 -0
- package/assets/knowledge-plugin-files/skills/knowledge-ingest/SKILL.md +46 -0
- package/assets/knowledge-plugin-files/skills/knowledge-lint/SKILL.md +26 -0
- package/assets/knowledge-plugin-files/skills/knowledge-query/SKILL.md +14 -0
- package/dist/core/agentSpec.d.ts +27 -2
- package/dist/core/extractText.d.ts +13 -0
- package/dist/core/extractText.js +147 -0
- package/dist/core/fileKnowledgeStore.d.ts +10 -0
- package/dist/core/fileKnowledgeStore.js +378 -0
- package/dist/core/hooks/fileScopeGate.d.ts +8 -0
- package/dist/core/hooks/fileScopeGate.js +20 -0
- package/dist/core/hooks/humanInput.d.ts +18 -0
- package/dist/core/hooks/humanInput.js +30 -2
- package/dist/core/hooks/planGate.js +14 -5
- package/dist/core/hooks/stepGate.js +6 -0
- package/dist/core/interaction.d.ts +20 -0
- package/dist/core/knowledge.d.ts +14 -4
- package/dist/core/knowledge.js +36 -6
- package/dist/core/knowledgeStore.d.ts +134 -0
- package/dist/core/knowledgeStore.js +84 -0
- package/dist/core/messages/de.js +65 -0
- package/dist/core/messages/en.d.ts +41 -0
- package/dist/core/messages/en.js +65 -0
- package/dist/core/messages/es.js +65 -0
- package/dist/core/messages/fr.js +65 -0
- package/dist/core/modeControl.d.ts +36 -0
- package/dist/core/modeControl.js +61 -0
- package/dist/core/session.d.ts +6 -31
- package/dist/core/session.js +76 -71
- package/dist/core/sources.d.ts +122 -0
- package/dist/core/sources.js +312 -0
- package/dist/core/todos.d.ts +23 -0
- package/dist/core/todos.js +33 -0
- package/dist/core/toolLabels.d.ts +1 -1
- package/dist/core/toolLabels.js +42 -2
- package/dist/core/tools/humanApproval.d.ts +9 -5
- package/dist/core/tools/humanApproval.js +39 -7
- package/dist/core/tools/knowledgeTools.d.ts +16 -0
- package/dist/core/tools/knowledgeTools.js +161 -0
- package/dist/core/tools/saveToSources.d.ts +27 -8
- package/dist/core/tools/saveToSources.js +203 -55
- package/dist/core/tools/time.d.ts +29 -0
- package/dist/core/tools/time.js +129 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +4 -1
- package/dist/tui/chatTui.js +14 -1
- package/dist/tui/consoleRenderer.js +16 -2
- package/dist/tui/ink/SessionView.js +72 -17
- package/dist/tui/ink/inkInteraction.d.ts +4 -2
- package/dist/tui/ink/inkInteraction.js +20 -2
- package/dist/tui/ink/progressView.d.ts +5 -1
- package/dist/tui/ink/runChatInk.d.ts +16 -1
- package/dist/tui/ink/runChatInk.js +7 -0
- package/dist/tui/ink/sessionModel.d.ts +10 -3
- package/dist/tui/ink/sessionModel.js +26 -4
- package/dist/tui/ink/toolGroup.d.ts +23 -2
- package/dist/tui/ink/toolGroup.js +17 -4
- package/dist/tui/terminalInteraction.js +2 -0
- package/package.json +31 -1
- /package/assets/{knowledge-plugin → knowledge-plugin-files}/skills/knowledge-pages/SKILL.md +0 -0
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
/** Built-in tools that only read, search, load a skill or
|
|
3
|
-
const READING_TOOLS = new Set(["Read", "Glob", "Grep", "WebFetch", "WebSearch", "Skill", "Agent"]);
|
|
4
|
-
/** The kit's own MCP tools
|
|
5
|
-
const ASKING_SERVERS = ["mcp__approvals__", "mcp__manualLogin__"];
|
|
2
|
+
/** Built-in tools that only read, search, load a skill, delegate or keep the task list (a subagent's own calls come through this gate too). */
|
|
3
|
+
const READING_TOOLS = new Set(["Read", "Glob", "Grep", "WebFetch", "WebSearch", "Skill", "Agent", "TodoWrite"]);
|
|
4
|
+
/** The kit's own MCP servers whose tools only ask a human (approvals, manual intervention) or only read (the date and time). */
|
|
5
|
+
const ASKING_SERVERS = ["mcp__approvals__", "mcp__manualLogin__", "mcp__time__"];
|
|
6
|
+
/** The kit's own MCP tools that only read, on servers that also have tools that write. */
|
|
7
|
+
const READING_KIT_TOOLS = new Set([
|
|
8
|
+
"mcp__sourceFiles__list_sources",
|
|
9
|
+
"mcp__sourceFiles__extract_text",
|
|
10
|
+
"mcp__knowledge__knowledge_index",
|
|
11
|
+
"mcp__knowledge__knowledge_search",
|
|
12
|
+
"mcp__knowledge__knowledge_read",
|
|
13
|
+
"mcp__knowledge__knowledge_check",
|
|
14
|
+
]);
|
|
6
15
|
/** Why a call is denied in plan mode, and what the model should do instead. */
|
|
7
16
|
const denial = "Plan mode: nothing can be changed until the user leaves plan mode. Keep reading and researching, then present the plan; the user switches out of plan mode when they want it carried out.";
|
|
8
17
|
/**
|
|
@@ -13,7 +22,7 @@ const denial = "Plan mode: nothing can be changed until the user leaves plan mod
|
|
|
13
22
|
export function checkPlanScope(scope, toolName, input) {
|
|
14
23
|
if (READING_TOOLS.has(toolName))
|
|
15
24
|
return undefined;
|
|
16
|
-
if (ASKING_SERVERS.some((prefix) => toolName.startsWith(prefix)))
|
|
25
|
+
if (ASKING_SERVERS.some((prefix) => toolName.startsWith(prefix)) || READING_KIT_TOOLS.has(toolName))
|
|
17
26
|
return undefined;
|
|
18
27
|
if (toolName === "Write" || toolName === "Edit") {
|
|
19
28
|
const target = typeof input.file_path === "string" && input.file_path !== "" ? path.resolve(scope.projectDir, input.file_path) : undefined;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { askForDecision } from "./humanInput.js";
|
|
2
2
|
import { t } from "../messages/index.js";
|
|
3
|
+
const SELF_ASKING_SERVERS = ["mcp__approvals__", "mcp__manualLogin__"];
|
|
4
|
+
const SELF_ASKING_TOOLS = new Set(["mcp__sourceFiles__request_file", "mcp__sourceFiles__retire_source", "mcp__knowledge__knowledge_retire", "TodoWrite"]);
|
|
3
5
|
/**
|
|
4
6
|
* PreToolUse hook for "interactive" mode: pauses before every action and asks for
|
|
5
7
|
* confirmation (by keyboard or by file, see humanInput.ts), like reviewing a plan step
|
|
@@ -14,6 +16,10 @@ export function createStepGate(runDir, isActive = () => true) {
|
|
|
14
16
|
if (!isActive())
|
|
15
17
|
return {};
|
|
16
18
|
const pre = input;
|
|
19
|
+
// A tool that asks the person itself (an approval, a question, the plan, a file, retiring
|
|
20
|
+
// a source) or only keeps the task list isn't asked about first: that would be asking to ask.
|
|
21
|
+
if (SELF_ASKING_SERVERS.some((prefix) => pre.tool_name.startsWith(prefix)) || SELF_ASKING_TOOLS.has(pre.tool_name))
|
|
22
|
+
return {};
|
|
17
23
|
const answer = await askForDecision(runDir, {
|
|
18
24
|
title: t().proposedAction,
|
|
19
25
|
lines: [t().toolLine(pre.tool_name), t().parametersLine(JSON.stringify(pre.tool_input, null, 2))],
|
|
@@ -4,6 +4,13 @@ export interface ApprovalPrompt {
|
|
|
4
4
|
lines: string[];
|
|
5
5
|
/** Terminal question text; defaults to the approve/reject one. */
|
|
6
6
|
question?: string;
|
|
7
|
+
/** The lines are markdown (a plan): a UI that can render it should. */
|
|
8
|
+
markdown?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** How `askChoice()` asks: the options to pick from, and whether several can be picked. */
|
|
11
|
+
export interface ChoiceSettings {
|
|
12
|
+
options: readonly string[];
|
|
13
|
+
multiple: boolean;
|
|
7
14
|
}
|
|
8
15
|
/**
|
|
9
16
|
* The UI side of a human-in-the-loop checkpoint: how a host shows the question and reads a
|
|
@@ -23,6 +30,19 @@ export interface InteractionPort {
|
|
|
23
30
|
askDecision(prompt: ApprovalPrompt, signal: AbortSignal): Promise<string>;
|
|
24
31
|
/** Waits until the person confirms they intervened by hand (e.g. logged in). */
|
|
25
32
|
askManualIntervention(prompt: ApprovalPrompt, signal: AbortSignal): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* A free-text answer (e.g. the path of a file the agent asked for), with case and spaces
|
|
35
|
+
* kept; "" for none. Optional: without it the kit asks through `askDecision()`, whose
|
|
36
|
+
* answer a plain terminal reads as text too.
|
|
37
|
+
*/
|
|
38
|
+
askText?(prompt: ApprovalPrompt, signal: AbortSignal): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* A choice between options. Resolves to the raw answer: the chosen options' numbers
|
|
41
|
+
* (1-based, comma-separated, "1" or "1,3") on the first line, and the person's own answer
|
|
42
|
+
* ("Other") on the lines after it, or alone. Optional: without it the kit asks through
|
|
43
|
+
* `askDecision()`, with the options numbered in the prompt.
|
|
44
|
+
*/
|
|
45
|
+
askChoice?(prompt: ApprovalPrompt, choice: ChoiceSettings, signal: AbortSignal): Promise<string>;
|
|
26
46
|
/** A one-way message for the person. */
|
|
27
47
|
notify(message: string): void;
|
|
28
48
|
}
|
package/dist/core/knowledge.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PageType } from "./knowledgeStore.js";
|
|
1
2
|
/**
|
|
2
3
|
* The built-in knowledge base (an "LLM wiki"): `sourcesDir` holds the originals, `knowledgeDir`
|
|
3
4
|
* is the wiki the agent writes and maintains, and the rules below plus the plugin's skills
|
|
@@ -6,10 +7,19 @@
|
|
|
6
7
|
* with its own page types (topics, activities...) opts out with `AgentSpec.knowledgeBase: false` and
|
|
7
8
|
* writes its own rules, or extends these.
|
|
8
9
|
*/
|
|
9
|
-
/**
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Absolute path of the plugin shipped with the kit, next to `dist/` (or `src/` under tsx):
|
|
12
|
+
* `assets/knowledge-plugin`, whose skills work through the `knowledge_*` tools, or with
|
|
13
|
+
* `"files"` `assets/knowledge-plugin-files`, whose skills work on the files (ADR-024).
|
|
14
|
+
*/
|
|
15
|
+
export declare function knowledgePluginRoot(variant?: "tools" | "files"): string;
|
|
11
16
|
/**
|
|
12
17
|
* The "Knowledge base" section appended to the system prompt: the layout and the working
|
|
13
|
-
* rules.
|
|
18
|
+
* rules. With `tools` (the kit's default since ADR-024), for a knowledge base reached through
|
|
19
|
+
* the `knowledge_*` tools, listing `pageTypes`; otherwise for one kept with the file tools,
|
|
20
|
+
* whose page templates live in the `knowledge-pages` skill.
|
|
14
21
|
*/
|
|
15
|
-
export declare function knowledgePromptSection(projectDir: string, knowledgeDir: string, sourcesDir?: string
|
|
22
|
+
export declare function knowledgePromptSection(projectDir: string, knowledgeDir: string, sourcesDir?: string, options?: {
|
|
23
|
+
tools?: boolean;
|
|
24
|
+
pageTypes?: readonly PageType[];
|
|
25
|
+
}): string;
|
package/dist/core/knowledge.js
CHANGED
|
@@ -8,26 +8,56 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
* with its own page types (topics, activities...) opts out with `AgentSpec.knowledgeBase: false` and
|
|
9
9
|
* writes its own rules, or extends these.
|
|
10
10
|
*/
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Absolute path of the plugin shipped with the kit, next to `dist/` (or `src/` under tsx):
|
|
13
|
+
* `assets/knowledge-plugin`, whose skills work through the `knowledge_*` tools, or with
|
|
14
|
+
* `"files"` `assets/knowledge-plugin-files`, whose skills work on the files (ADR-024).
|
|
15
|
+
*/
|
|
16
|
+
export function knowledgePluginRoot(variant = "tools") {
|
|
17
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "assets", variant === "files" ? "knowledge-plugin-files" : "knowledge-plugin");
|
|
14
18
|
}
|
|
15
19
|
/** A path as shown to the model: relative to the project, forward slashes, with a trailing slash. */
|
|
16
20
|
function shown(projectDir, dir) {
|
|
17
21
|
return `${path.relative(projectDir, dir).split(path.sep).join("/")}/`;
|
|
18
22
|
}
|
|
23
|
+
/** The originals' line of the prompt section, the same in both variants. */
|
|
24
|
+
function originalsLine(originals) {
|
|
25
|
+
return `- **Originals (read-only for you)**: \`${originals}\`. Never rewrite one; build pages *about* them. \`list_sources\` says which are new (not ingested yet), changed since their ingest or missing; add a file only with \`save_to_sources\`, \`download_to_sources\` or by asking the person (\`request_file\`), and take out a wrong or superseded one only with \`retire_source\`. \`Read\` reads PDFs and images; \`extract_text\` reads DOCX, PPTX (with speaker notes) and XLSX.\n`;
|
|
26
|
+
}
|
|
27
|
+
/** The section for a knowledge base reached through the `knowledge_*` tools (ADR-024). */
|
|
28
|
+
function toolsSection(originals, pageTypes) {
|
|
29
|
+
return `## Knowledge base
|
|
30
|
+
Your memory across sessions is an interlinked knowledge base of pages that you write and maintain yourself — a wiki, not a pile of notes. A future session only knows what is written there, so anything worth remembering must end up in a page, not just in this turn's reply. You reach it only through the \`knowledge_*\` tools. Write page content in the language you are using with the human.
|
|
31
|
+
|
|
32
|
+
### Layers
|
|
33
|
+
${originals ? originalsLine(originals) : ""}- **The knowledge base**: pages identified by type and slug (\`concept/spring-tides\`), plus the \`overview\`, a living synthesis of the whole. Page types: ${pageTypes.map((type) => `\`${type.type}\` (${type.description})`).join("; ")}.
|
|
34
|
+
- **The schema**: these rules plus the \`knowledge-ingest\`, \`knowledge-query\` and \`knowledge-lint\` skills. \`knowledge_create\` without content gives a type's template.
|
|
35
|
+
|
|
36
|
+
### Working rules
|
|
37
|
+
- Start from \`knowledge_search\` or \`knowledge_index\`, then \`knowledge_read\` only the pages the task needs.
|
|
38
|
+
- Link pages by id, \`[Spring tides](concept/spring-tides)\`; links must point to existing pages. The index and the backlinks ("linked from") are kept for you.
|
|
39
|
+
- Change a page with \`knowledge_edit\` (a fragment); \`knowledge_rewrite\` only to redo it whole. Pages are never deleted or renamed: \`knowledge_supersede\` one replaced by another; \`knowledge_retire\` one that was wrong.
|
|
40
|
+
- When an operation is done, \`knowledge_log\` it: \`ingest\`, \`query\`, \`lint\` or \`update\`, with the pages touched.
|
|
41
|
+
- Every claim must be traceable to a summary page, an original, or — clearly labelled as outside the knowledge base — the web.
|
|
42
|
+
- Contradictions are kept, not overwritten: record both versions with attribution in the affected pages.
|
|
43
|
+
- Short, focused, well-linked pages beat long ones: when a page mixes two things, split it.`;
|
|
44
|
+
}
|
|
19
45
|
/**
|
|
20
46
|
* The "Knowledge base" section appended to the system prompt: the layout and the working
|
|
21
|
-
* rules.
|
|
47
|
+
* rules. With `tools` (the kit's default since ADR-024), for a knowledge base reached through
|
|
48
|
+
* the `knowledge_*` tools, listing `pageTypes`; otherwise for one kept with the file tools,
|
|
49
|
+
* whose page templates live in the `knowledge-pages` skill.
|
|
22
50
|
*/
|
|
23
|
-
export function knowledgePromptSection(projectDir, knowledgeDir, sourcesDir) {
|
|
51
|
+
export function knowledgePromptSection(projectDir, knowledgeDir, sourcesDir, options = {}) {
|
|
24
52
|
const notes = shown(projectDir, knowledgeDir);
|
|
25
53
|
const originals = sourcesDir ? shown(projectDir, sourcesDir) : undefined;
|
|
54
|
+
if (options.tools)
|
|
55
|
+
return toolsSection(originals, options.pageTypes ?? []);
|
|
26
56
|
return `## Knowledge base (${notes})
|
|
27
57
|
\`${notes}\` is your memory across sessions, kept as an interlinked knowledge base of markdown pages that you write and maintain yourself — a wiki, not a pile of notes. A future session only knows what is written there, so anything worth remembering must end up in a page, not just in this turn's reply. Write page content in the language you are using with the human; file names stay lowercase ASCII with hyphens.
|
|
28
58
|
|
|
29
59
|
### Layers
|
|
30
|
-
${originals ?
|
|
60
|
+
${originals ? originalsLine(originals) : ""}- **The knowledge base**: \`${notes}\`, entirely yours to write.
|
|
31
61
|
- **The schema**: these rules plus the \`knowledge-pages\` skill (exact template of every page type — load it before creating a page) and the \`knowledge-ingest\`, \`knowledge-query\` and \`knowledge-lint\` skills.
|
|
32
62
|
|
|
33
63
|
### Layout
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The knowledge base as pages, not files (ADR-024): the agent reaches it only through the
|
|
3
|
+
* kit's `knowledge_*` tools, which sit on this interface, so the storage can change (markdown
|
|
4
|
+
* files today, a vector database tomorrow) without touching the tools, the prompt or the
|
|
5
|
+
* skills. A page is identified by its type and slug, `concept/bowline`, and links between
|
|
6
|
+
* pages use that id too: `[Bowline](concept/bowline)`.
|
|
7
|
+
*/
|
|
8
|
+
/** A kind of page: the kit's four, or one an agent declares (`AgentSpec.knowledgePageTypes`). */
|
|
9
|
+
export interface PageType {
|
|
10
|
+
/** Its name, lowercase: `concept`, `topic`. Page ids start with it. */
|
|
11
|
+
type: string;
|
|
12
|
+
/** Where a file store keeps its pages, relative to the knowledge folder; "" for the root. */
|
|
13
|
+
dir: string;
|
|
14
|
+
/** Its section in the index, e.g. "Concepts". */
|
|
15
|
+
indexSection: string;
|
|
16
|
+
/** What it holds and when to create one, in one line: told to the model. */
|
|
17
|
+
description: string;
|
|
18
|
+
/** The page's body skeleton (markdown, under its title), shown when one is created. */
|
|
19
|
+
template: string;
|
|
20
|
+
/** Frontmatter fields shown in the page's index line, e.g. `["mastery"]`. */
|
|
21
|
+
indexFields?: string[];
|
|
22
|
+
}
|
|
23
|
+
/** One page, as the store returns it. */
|
|
24
|
+
export interface KnowledgePage {
|
|
25
|
+
id: string;
|
|
26
|
+
type: string;
|
|
27
|
+
slug: string;
|
|
28
|
+
title: string;
|
|
29
|
+
/** Frontmatter fields besides type and title (aliases, file, url, updated, status...). */
|
|
30
|
+
fields: Record<string, string>;
|
|
31
|
+
/** The markdown body, links to other pages as ids. */
|
|
32
|
+
content: string;
|
|
33
|
+
/** The pages that link to this one. */
|
|
34
|
+
linkedFrom: string[];
|
|
35
|
+
}
|
|
36
|
+
/** A page's line in a listing. */
|
|
37
|
+
export interface PageInfo {
|
|
38
|
+
id: string;
|
|
39
|
+
type: string;
|
|
40
|
+
title: string;
|
|
41
|
+
/** One line: its `description` field, or its first sentence. */
|
|
42
|
+
description: string;
|
|
43
|
+
/** `active`, `superseded` or `retired`. */
|
|
44
|
+
status: string;
|
|
45
|
+
fields: Record<string, string>;
|
|
46
|
+
}
|
|
47
|
+
export interface SearchHit {
|
|
48
|
+
id: string;
|
|
49
|
+
title: string;
|
|
50
|
+
/** Where it matched, one line. */
|
|
51
|
+
snippet: string;
|
|
52
|
+
}
|
|
53
|
+
/** What `check()` finds: the mechanical problems, for the agent to fix or report. */
|
|
54
|
+
export interface CheckReport {
|
|
55
|
+
/** Links to pages that don't exist. */
|
|
56
|
+
brokenLinks: {
|
|
57
|
+
page: string;
|
|
58
|
+
target: string;
|
|
59
|
+
}[];
|
|
60
|
+
/** Pages nothing links to (summaries and syntheses aside, which the index reaches). */
|
|
61
|
+
orphans: string[];
|
|
62
|
+
/** Links to retired pages. */
|
|
63
|
+
linksToRetired: {
|
|
64
|
+
page: string;
|
|
65
|
+
target: string;
|
|
66
|
+
}[];
|
|
67
|
+
/** Summary pages whose original is gone from the sources folder. */
|
|
68
|
+
missingOriginals: {
|
|
69
|
+
page: string;
|
|
70
|
+
file: string;
|
|
71
|
+
}[];
|
|
72
|
+
}
|
|
73
|
+
/** A page to create. */
|
|
74
|
+
export interface NewPage {
|
|
75
|
+
type: string;
|
|
76
|
+
slug: string;
|
|
77
|
+
title: string;
|
|
78
|
+
content: string;
|
|
79
|
+
fields?: FieldChanges;
|
|
80
|
+
}
|
|
81
|
+
/** A change to a page's frontmatter fields: a string sets it, null removes it. */
|
|
82
|
+
export type FieldChanges = Record<string, string | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Where the knowledge base lives. The kit ships one over markdown files
|
|
85
|
+
* (`createFileKnowledgeStore()`); another one (a database, a vector store) implements this
|
|
86
|
+
* interface and is passed with `AgentSpec.knowledgeStore`. Pages are never deleted or renamed:
|
|
87
|
+
* their ids are what links point to.
|
|
88
|
+
*/
|
|
89
|
+
export interface KnowledgeStore {
|
|
90
|
+
/** The page types it holds, the kit's and the agent's. */
|
|
91
|
+
types(): readonly PageType[];
|
|
92
|
+
/** Every page but the retired ones. */
|
|
93
|
+
list(): Promise<PageInfo[]>;
|
|
94
|
+
/** A page, retired ones included; `null` if there's none. */
|
|
95
|
+
read(id: string): Promise<KnowledgePage | null>;
|
|
96
|
+
/** A new page; fails if the id exists or a link points nowhere. Returns its id. */
|
|
97
|
+
create(type: string, slug: string, title: string, content: string, fields?: FieldChanges): Promise<string>;
|
|
98
|
+
/**
|
|
99
|
+
* Several new pages at once, whose links may point to each other (a summary and the
|
|
100
|
+
* concepts it feeds): all are created, or none. Returns their ids.
|
|
101
|
+
*/
|
|
102
|
+
createMany(pages: readonly NewPage[]): Promise<string[]>;
|
|
103
|
+
/** Replaces the one occurrence of `oldText` in a page's body; fails if it's missing or appears more than once. */
|
|
104
|
+
edit(id: string, oldText: string, newText: string, fields?: FieldChanges): Promise<void>;
|
|
105
|
+
/** Replaces a page's whole body, keeping its id. */
|
|
106
|
+
rewrite(id: string, content: string, fields?: FieldChanges): Promise<void>;
|
|
107
|
+
/** Marks a page superseded by another, with a notice at its top. */
|
|
108
|
+
supersede(id: string, by: string, reason?: string): Promise<void>;
|
|
109
|
+
/** Takes a page out of the index and the search (it's kept, and can be restored). */
|
|
110
|
+
retire(id: string, reason: string): Promise<void>;
|
|
111
|
+
/** Pages matching words of `query` in their title, aliases or body, best first. */
|
|
112
|
+
search(query: string, limit?: number): Promise<SearchHit[]>;
|
|
113
|
+
/** The catalog: every active or superseded page, one line each, by section. */
|
|
114
|
+
index(): Promise<string>;
|
|
115
|
+
/** Adds an entry to the operation log, dated today. */
|
|
116
|
+
log(operation: string, what: string, pages?: readonly string[]): Promise<void>;
|
|
117
|
+
/** The mechanical problems. */
|
|
118
|
+
check(): Promise<CheckReport>;
|
|
119
|
+
/** The overview: a living synthesis of the whole knowledge base ("" if none yet). */
|
|
120
|
+
overview(): Promise<string>;
|
|
121
|
+
/** Replaces the overview. */
|
|
122
|
+
writeOverview(content: string): Promise<void>;
|
|
123
|
+
}
|
|
124
|
+
/** The kit's page types (ADR-008). */
|
|
125
|
+
export declare const BUILT_IN_PAGE_TYPES: readonly PageType[];
|
|
126
|
+
/** Whether `slug` is lowercase ASCII words joined by hyphens. */
|
|
127
|
+
export declare function isSlug(slug: string): boolean;
|
|
128
|
+
/** `type/slug` split, or null when it isn't one. */
|
|
129
|
+
export declare function parseId(id: string): {
|
|
130
|
+
type: string;
|
|
131
|
+
slug: string;
|
|
132
|
+
} | null;
|
|
133
|
+
/** The ids every `[text](id)` link in `markdown` points to (links that look like page ids). */
|
|
134
|
+
export declare function linkedIds(markdown: string): string[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The knowledge base as pages, not files (ADR-024): the agent reaches it only through the
|
|
3
|
+
* kit's `knowledge_*` tools, which sit on this interface, so the storage can change (markdown
|
|
4
|
+
* files today, a vector database tomorrow) without touching the tools, the prompt or the
|
|
5
|
+
* skills. A page is identified by its type and slug, `concept/bowline`, and links between
|
|
6
|
+
* pages use that id too: `[Bowline](concept/bowline)`.
|
|
7
|
+
*/
|
|
8
|
+
/** The kit's page types (ADR-008). */
|
|
9
|
+
export const BUILT_IN_PAGE_TYPES = [
|
|
10
|
+
{
|
|
11
|
+
type: "summary",
|
|
12
|
+
dir: "summaries",
|
|
13
|
+
indexSection: "Summaries",
|
|
14
|
+
description: "One per ingested source: what it says, its key points and the pages it feeds. Fields: file (the original, relative to sources/) or url; ingested.",
|
|
15
|
+
template: `## Summary
|
|
16
|
+
<Two to four paragraphs: what it actually says.>
|
|
17
|
+
|
|
18
|
+
## Key points
|
|
19
|
+
- <Claims, definitions or figures likely to be needed later, quoted literally when exact wording matters.>
|
|
20
|
+
|
|
21
|
+
## Pages it feeds
|
|
22
|
+
- [<Concept or entity>](concept/<slug>)
|
|
23
|
+
|
|
24
|
+
## New or surprising
|
|
25
|
+
- <What this source adds to what the knowledge base already had.>
|
|
26
|
+
|
|
27
|
+
## Contradictions
|
|
28
|
+
- <Conflicts with other pages, linked.>`,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: "concept",
|
|
32
|
+
dir: "concepts",
|
|
33
|
+
indexSection: "Concepts",
|
|
34
|
+
description: "One idea per page: its definition, explanation, connections and sources. Fields: aliases (other names, comma-separated).",
|
|
35
|
+
template: `<Definition in one or two sentences.>
|
|
36
|
+
|
|
37
|
+
## Explanation
|
|
38
|
+
<How it works, at the depth the sources give.>
|
|
39
|
+
|
|
40
|
+
## Connections
|
|
41
|
+
- Requires: [<Concept>](concept/<slug>)
|
|
42
|
+
- Related: [<Concept>](concept/<slug>) - how
|
|
43
|
+
|
|
44
|
+
## Sources
|
|
45
|
+
- [<Summary>](summary/<slug>) - what it says about this
|
|
46
|
+
|
|
47
|
+
## Contradictions and open questions
|
|
48
|
+
- "<Source A> says X; <source B> says Y" - both attributed.`,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
type: "entity",
|
|
52
|
+
dir: "entities",
|
|
53
|
+
indexSection: "Entities",
|
|
54
|
+
description: "A concrete thing: a system, component, organization or document (a person only as a public role). Fields: kind, aliases.",
|
|
55
|
+
template: `<What it is, one or two sentences.>
|
|
56
|
+
|
|
57
|
+
## Facts
|
|
58
|
+
- <Attributed facts, each linking the summary it comes from.>
|
|
59
|
+
|
|
60
|
+
## Connections
|
|
61
|
+
- [<Concept or entity>](concept/<slug>) - how`,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: "synthesis",
|
|
65
|
+
dir: "syntheses",
|
|
66
|
+
indexSection: "Syntheses",
|
|
67
|
+
description: "An answer worth keeping: a comparison, an analysis, a report. Fields: question.",
|
|
68
|
+
template: `<The answer, with links to every page it draws on.>`,
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
const SLUG = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
72
|
+
/** Whether `slug` is lowercase ASCII words joined by hyphens. */
|
|
73
|
+
export function isSlug(slug) {
|
|
74
|
+
return SLUG.test(slug);
|
|
75
|
+
}
|
|
76
|
+
/** `type/slug` split, or null when it isn't one. */
|
|
77
|
+
export function parseId(id) {
|
|
78
|
+
const match = /^([a-z][a-z0-9-]*)\/([a-z0-9]+(?:-[a-z0-9]+)*)$/.exec(id.trim());
|
|
79
|
+
return match ? { type: match[1], slug: match[2] } : null;
|
|
80
|
+
}
|
|
81
|
+
/** The ids every `[text](id)` link in `markdown` points to (links that look like page ids). */
|
|
82
|
+
export function linkedIds(markdown) {
|
|
83
|
+
return [...markdown.matchAll(/\]\(([a-z][a-z0-9-]*\/[a-z0-9]+(?:-[a-z0-9]+)*)(?:#[^)]*)?\)/g)].map((m) => m[1]);
|
|
84
|
+
}
|
package/dist/core/messages/de.js
CHANGED
|
@@ -54,6 +54,29 @@ export const de = {
|
|
|
54
54
|
parametersLine: (parameters) => `Parameter: ${parameters}`,
|
|
55
55
|
approvalTitle: "Vor dem Veröffentlichen ist eine menschliche Bestätigung nötig",
|
|
56
56
|
summaryLine: (summary) => `Zusammenfassung: ${summary}`,
|
|
57
|
+
noAnswer: "(keine Antwort)",
|
|
58
|
+
textAnswerHint: "Antwort eingeben",
|
|
59
|
+
textAnswerKeys: "Enter zum Senden · Esc für keine Antwort",
|
|
60
|
+
fileRequestTitle: "Der Agent bittet um eine Datei",
|
|
61
|
+
fileRequestQuestion: "Pfad der Datei (hierher ziehen), oder Enter, wenn du sie nicht hast: ",
|
|
62
|
+
retireTitle: "Eine Quelle zurückziehen?",
|
|
63
|
+
retirePageTitle: "Eine Seite der Wissensbasis zurückziehen?",
|
|
64
|
+
choiceQuestion: (multiple) => (multiple ? "Nummern durch Kommas getrennt, oder deine eigene Antwort: " : "Nummer, oder deine eigene Antwort: "),
|
|
65
|
+
otherOption: "Andere (eigene Antwort eingeben)",
|
|
66
|
+
choiceKeys: (multiple) => (multiple ? "Leertaste markiert · Enter sendet" : "↑/↓ wählen · Enter sendet"),
|
|
67
|
+
questionTitle: "Der Agent fragt",
|
|
68
|
+
planTitle: "Der Plan, zur Freigabe",
|
|
69
|
+
runPlan: "Ausführen",
|
|
70
|
+
keepPlanning: "Weiter planen",
|
|
71
|
+
cancelPlan: "Abbrechen",
|
|
72
|
+
planCommentQuestion: "Was soll sich ändern? (Enter zum Überspringen): ",
|
|
73
|
+
retireLines: (source, why, reason, replacedBy) => [
|
|
74
|
+
`Quelle: ${source}`,
|
|
75
|
+
why === "wrong" ? "Warum: sie ist falsch; ihre Zusammenfassung wird zurückgezogen" : "Warum: sie wird ersetzt; ihre Zusammenfassung wird als ersetzt markiert",
|
|
76
|
+
`Grund: ${reason}`,
|
|
77
|
+
...(replacedBy ? [`Ersetzt durch: ${replacedBy}`] : []),
|
|
78
|
+
"Sie wird nach sources/.agent-kit/retired/ verschoben, nicht gelöscht.",
|
|
79
|
+
],
|
|
57
80
|
toolPhrases: {
|
|
58
81
|
Read: ["hat {n} Datei gelesen", "hat {n} Dateien gelesen"],
|
|
59
82
|
Write: ["hat {n} Datei geschrieben", "hat {n} Dateien geschrieben"],
|
|
@@ -66,16 +89,40 @@ export const de = {
|
|
|
66
89
|
Skill: ["hat {n} Skill verwendet", "hat {n} Skills verwendet"],
|
|
67
90
|
Agent: ["hat {n} Subagenten gestartet", "hat {n} Subagenten gestartet"],
|
|
68
91
|
Task: ["hat {n} Subagenten gestartet", "hat {n} Subagenten gestartet"],
|
|
92
|
+
mcp__time__current_time: ["Uhrzeit abgefragt", "Uhrzeit {n}-mal abgefragt"],
|
|
93
|
+
mcp__time__date_math: ["Daten berechnet", "Daten {n}-mal berechnet"],
|
|
94
|
+
mcp__sourceFiles__list_sources: ["Quellen geprüft", "Quellen {n}-mal geprüft"],
|
|
95
|
+
mcp__sourceFiles__extract_text: ["{n} Dokument gelesen", "{n} Dokumente gelesen"],
|
|
96
|
+
mcp__sourceFiles__save_to_sources: ["{n} Quelle gespeichert", "{n} Quellen gespeichert"],
|
|
97
|
+
mcp__sourceFiles__download_to_sources: ["{n} Quelle heruntergeladen", "{n} Quellen heruntergeladen"],
|
|
98
|
+
mcp__sourceFiles__request_file: ["um {n} Datei gebeten", "um {n} Dateien gebeten"],
|
|
99
|
+
mcp__sourceFiles__retire_source: ["{n} Quelle zurückgezogen", "{n} Quellen zurückgezogen"],
|
|
100
|
+
mcp__knowledge__knowledge_index: ["Index gelesen", "Index {n}-mal gelesen"],
|
|
101
|
+
mcp__knowledge__knowledge_search: ["Wissensbasis durchsucht", "Wissensbasis {n}-mal durchsucht"],
|
|
102
|
+
mcp__knowledge__knowledge_read: ["{n} Seite gelesen", "{n} Seiten gelesen"],
|
|
103
|
+
mcp__knowledge__knowledge_create: ["{n} Seite angelegt", "{n} Seiten angelegt"],
|
|
104
|
+
mcp__knowledge__knowledge_edit: ["{n} Seite bearbeitet", "{n} Seiten bearbeitet"],
|
|
105
|
+
mcp__knowledge__knowledge_rewrite: ["{n} Seite neu geschrieben", "{n} Seiten neu geschrieben"],
|
|
106
|
+
mcp__knowledge__knowledge_supersede: ["{n} Seite ersetzt", "{n} Seiten ersetzt"],
|
|
107
|
+
mcp__knowledge__knowledge_retire: ["{n} Seite zurückgezogen", "{n} Seiten zurückgezogen"],
|
|
108
|
+
mcp__knowledge__knowledge_log: ["Protokoll aktualisiert", "Protokoll {n}-mal aktualisiert"],
|
|
109
|
+
mcp__knowledge__knowledge_check: ["Wissensbasis geprüft", "Wissensbasis {n}-mal geprüft"],
|
|
110
|
+
mcp__approvals__ask_human: ["{n} Frage gestellt", "{n} Fragen gestellt"],
|
|
111
|
+
mcp__approvals__present_plan: ["Plan vorgelegt", "Plan {n}-mal vorgelegt"],
|
|
69
112
|
},
|
|
70
113
|
otherTools: ["hat {n} Werkzeug verwendet", "hat {n} Werkzeuge verwendet"],
|
|
71
114
|
noOutput: "(keine Ausgabe)",
|
|
72
115
|
error: "Fehler",
|
|
116
|
+
toolFailed: "Konnte nicht abgeschlossen werden",
|
|
73
117
|
moreResultLines: (count) => `(+${count} ${plural(count, "Zeile", "Zeilen")})`,
|
|
74
118
|
earlierCalls: (count) => `… ${count} frühere`,
|
|
119
|
+
moreTodos: (count) => `… ${count} weitere ${plural(count, "Aufgabe", "Aufgaben")}`,
|
|
75
120
|
labels: {
|
|
76
121
|
askingApproval: (summary) => `Bittet um menschliche Genehmigung: ${summary}`,
|
|
77
122
|
waitingManual: "Wartet auf einen manuellen Eingriff",
|
|
78
123
|
savingToSources: (destination) => `Speichert eine Datei in sources/${destination}`,
|
|
124
|
+
checkingTime: "Datum und Uhrzeit abfragen",
|
|
125
|
+
calculatingDates: "Daten berechnen",
|
|
79
126
|
reading: (file) => `Liest ${file}`,
|
|
80
127
|
writing: (file) => `Schreibt in ${file}`,
|
|
81
128
|
editing: (file) => `Bearbeitet ${file}`,
|
|
@@ -91,6 +138,24 @@ export const de = {
|
|
|
91
138
|
searchingWeb: (query) => `Sucht im Web nach "${query}"`,
|
|
92
139
|
applyingSkill: (skill) => `Wendet den Skill "${skill}" an`,
|
|
93
140
|
aSkill: "einen Skill",
|
|
141
|
+
updatingTasks: "Aufgabenliste aktualisieren",
|
|
142
|
+
listingSources: "Quellen prüfen",
|
|
143
|
+
extractingText: (source) => `${source} lesen`,
|
|
144
|
+
downloading: (url) => `${url} in die Quellen herunterladen`,
|
|
145
|
+
requestingFile: (description) => `Um eine Datei bitten: ${description}`,
|
|
146
|
+
retiringSource: (source) => `Quelle ${source} zurückziehen`,
|
|
147
|
+
knowledgeIndex: "Index der Wissensbasis lesen",
|
|
148
|
+
knowledgeSearch: (query) => `Wissensbasis nach "${query}" durchsuchen`,
|
|
149
|
+
knowledgeRead: (page) => `${page} lesen`,
|
|
150
|
+
knowledgeCreate: (page) => `${page} anlegen`,
|
|
151
|
+
knowledgeEdit: (page) => `${page} bearbeiten`,
|
|
152
|
+
knowledgeRewrite: (page) => `${page} neu schreiben`,
|
|
153
|
+
knowledgeSupersede: (page) => `${page} als ersetzt markieren`,
|
|
154
|
+
knowledgeRetire: (page) => `${page} zurückziehen`,
|
|
155
|
+
knowledgeLog: "Protokoll der Wissensbasis aktualisieren",
|
|
156
|
+
knowledgeCheck: "Wissensbasis prüfen",
|
|
157
|
+
askingHuman: (question) => `Frage: ${question}`,
|
|
158
|
+
presentingPlan: "Plan vorlegen",
|
|
94
159
|
},
|
|
95
160
|
auth: {
|
|
96
161
|
noToken: "Es wurde kein Claude-Authentifizierungstoken gefunden",
|
|
@@ -51,16 +51,39 @@ export interface Messages {
|
|
|
51
51
|
parametersLine(parameters: string): string;
|
|
52
52
|
approvalTitle: string;
|
|
53
53
|
summaryLine(summary: string): string;
|
|
54
|
+
noAnswer: string;
|
|
55
|
+
textAnswerHint: string;
|
|
56
|
+
textAnswerKeys: string;
|
|
57
|
+
fileRequestTitle: string;
|
|
58
|
+
fileRequestQuestion: string;
|
|
59
|
+
retireTitle: string;
|
|
60
|
+
retirePageTitle: string;
|
|
61
|
+
choiceQuestion(multiple: boolean): string;
|
|
62
|
+
otherOption: string;
|
|
63
|
+
choiceKeys(multiple: boolean): string;
|
|
64
|
+
questionTitle: string;
|
|
65
|
+
planTitle: string;
|
|
66
|
+
runPlan: string;
|
|
67
|
+
keepPlanning: string;
|
|
68
|
+
cancelPlan: string;
|
|
69
|
+
planCommentQuestion: string;
|
|
70
|
+
retireLines(source: string, why: "wrong" | "replaced", reason: string, replacedBy?: string): string[];
|
|
54
71
|
toolPhrases: Record<string, ToolPhrase>;
|
|
55
72
|
otherTools: ToolPhrase;
|
|
56
73
|
noOutput: string;
|
|
57
74
|
error: string;
|
|
75
|
+
/** A failed tool call when results are hidden (`toolDetail: "calls"`): no tool output, just that it failed. */
|
|
76
|
+
toolFailed: string;
|
|
58
77
|
moreResultLines(count: number): string;
|
|
59
78
|
earlierCalls(count: number): string;
|
|
79
|
+
/** Tasks of the task list left out of the view. */
|
|
80
|
+
moreTodos(count: number): string;
|
|
60
81
|
labels: {
|
|
61
82
|
askingApproval(summary: string): string;
|
|
62
83
|
waitingManual: string;
|
|
63
84
|
savingToSources(destination: string): string;
|
|
85
|
+
checkingTime: string;
|
|
86
|
+
calculatingDates: string;
|
|
64
87
|
reading(file: string): string;
|
|
65
88
|
writing(file: string): string;
|
|
66
89
|
editing(file: string): string;
|
|
@@ -76,6 +99,24 @@ export interface Messages {
|
|
|
76
99
|
searchingWeb(query: string): string;
|
|
77
100
|
applyingSkill(skill: string): string;
|
|
78
101
|
aSkill: string;
|
|
102
|
+
updatingTasks: string;
|
|
103
|
+
listingSources: string;
|
|
104
|
+
extractingText(source: string): string;
|
|
105
|
+
downloading(url: string): string;
|
|
106
|
+
requestingFile(description: string): string;
|
|
107
|
+
retiringSource(source: string): string;
|
|
108
|
+
knowledgeIndex: string;
|
|
109
|
+
knowledgeSearch(query: string): string;
|
|
110
|
+
knowledgeRead(page: string): string;
|
|
111
|
+
knowledgeCreate(page: string): string;
|
|
112
|
+
knowledgeEdit(page: string): string;
|
|
113
|
+
knowledgeRewrite(page: string): string;
|
|
114
|
+
knowledgeSupersede(page: string): string;
|
|
115
|
+
knowledgeRetire(page: string): string;
|
|
116
|
+
knowledgeLog: string;
|
|
117
|
+
knowledgeCheck: string;
|
|
118
|
+
askingHuman(question: string): string;
|
|
119
|
+
presentingPlan: string;
|
|
79
120
|
};
|
|
80
121
|
auth: {
|
|
81
122
|
noToken: string;
|