@kernel.chat/kbot 3.99.31 → 3.99.34
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 +14 -1
- package/dist/agents/security-agent.d.ts +31 -0
- package/dist/agents/security-agent.js +180 -0
- package/dist/agents/security-rules.d.ts +35 -0
- package/dist/agents/security-rules.js +206 -0
- package/dist/agents/specialists.d.ts +6 -0
- package/dist/agents/specialists.js +45 -0
- package/dist/architect.js +5 -0
- package/dist/auth.js +1 -1
- package/dist/channels/matrix.d.ts +4 -0
- package/dist/channels/matrix.js +28 -0
- package/dist/channels/office.d.ts +78 -0
- package/dist/channels/office.js +169 -0
- package/dist/channels/registry.d.ts +8 -0
- package/dist/channels/registry.js +38 -0
- package/dist/channels/signal.d.ts +4 -0
- package/dist/channels/signal.js +29 -0
- package/dist/channels/slack.d.ts +4 -0
- package/dist/channels/slack.js +97 -0
- package/dist/channels/teams.d.ts +4 -0
- package/dist/channels/teams.js +29 -0
- package/dist/channels/telegram.d.ts +4 -0
- package/dist/channels/telegram.js +28 -0
- package/dist/channels/types.d.ts +50 -0
- package/dist/channels/types.js +13 -0
- package/dist/channels/whatsapp.d.ts +4 -0
- package/dist/channels/whatsapp.js +28 -0
- package/dist/cli.js +81 -0
- package/dist/computer-use-coordinator.d.ts +44 -0
- package/dist/computer-use-coordinator.js +0 -0
- package/dist/file-library.d.ts +76 -0
- package/dist/file-library.js +269 -0
- package/dist/ide/mcp-server.js +4 -4
- package/dist/managed-agents-anthropic.d.ts +90 -0
- package/dist/managed-agents-anthropic.js +123 -0
- package/dist/plugins-integrity.d.ts +72 -0
- package/dist/plugins-integrity.js +153 -0
- package/dist/plugins.d.ts +13 -2
- package/dist/plugins.js +87 -10
- package/dist/setup-editor.d.ts +28 -0
- package/dist/setup-editor.js +222 -0
- package/dist/tools/anthropic-managed-agents-tools.d.ts +22 -0
- package/dist/tools/anthropic-managed-agents-tools.js +191 -0
- package/dist/tools/channel-tools.d.ts +4 -0
- package/dist/tools/channel-tools.js +80 -0
- package/dist/tools/computer-coordinator-tools.d.ts +13 -0
- package/dist/tools/computer-coordinator-tools.js +104 -0
- package/dist/tools/computer.js +463 -299
- package/dist/tools/file-library-tools.d.ts +12 -0
- package/dist/tools/file-library-tools.js +191 -0
- package/dist/tools/image-thoughtful.d.ts +31 -0
- package/dist/tools/image-thoughtful.js +233 -0
- package/dist/tools/index.js +1 -0
- package/dist/tools/matrix.js +3 -3
- package/dist/tools/redblue.js +2 -2
- package/dist/tools/security-agent-tools.d.ts +34 -0
- package/dist/tools/security-agent-tools.js +30 -0
- package/dist/tools/security-hunt.js +1 -1
- package/dist/tools/subagent.js +2 -2
- package/dist/tools/swarm-2026-04.d.ts +2 -0
- package/dist/tools/swarm-2026-04.js +91 -0
- package/dist/tools/visa-payments.js +1 -1
- package/dist/tools/workspace-agent-tools.d.ts +19 -0
- package/dist/tools/workspace-agent-tools.js +191 -0
- package/dist/workspace-agents.d.ts +132 -0
- package/dist/workspace-agents.js +379 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -156,6 +156,87 @@ async function main() {
|
|
|
156
156
|
printInfo(' kbot ide mcp — VS Code, Cursor, Windsurf, Zed, Neovim');
|
|
157
157
|
printInfo(' kbot ide acp — IntelliJ, WebStorm, PyCharm, GoLand, Android Studio');
|
|
158
158
|
});
|
|
159
|
+
// ── one-shot editor installers (Harrison-class onboarding) ──────────────
|
|
160
|
+
// Wires kbot's MCP servers into editor settings.json + (Claude Code only)
|
|
161
|
+
// copies the kbot skill into the project. Idempotent. No manual JSON edits.
|
|
162
|
+
const printSetupResult = (label, r) => {
|
|
163
|
+
printSuccess(`${label}: ${r.configPath}`);
|
|
164
|
+
if (r.mcpAdded.length > 0)
|
|
165
|
+
printInfo(` + added MCP servers: ${r.mcpAdded.join(', ')}`);
|
|
166
|
+
if (r.mcpAlreadyPresent.length > 0)
|
|
167
|
+
printInfo(` · already present: ${r.mcpAlreadyPresent.join(', ')}`);
|
|
168
|
+
if (r.skillCopied)
|
|
169
|
+
printInfo(` + skill copied: ${r.skillCopied}`);
|
|
170
|
+
if (r.skillAlreadyPresent)
|
|
171
|
+
printWarn(` · skill exists (use --force to overwrite): ${r.skillAlreadyPresent}`);
|
|
172
|
+
};
|
|
173
|
+
program
|
|
174
|
+
.command('setup-claude-code')
|
|
175
|
+
.description('Wire kbot into Claude Code (~/.claude/settings.json) + copy skill into project')
|
|
176
|
+
.option('-f, --force', 'Overwrite existing project skill if present')
|
|
177
|
+
.action(async (opts) => {
|
|
178
|
+
const { setupClaudeCode } = await import('./setup-editor.js');
|
|
179
|
+
try {
|
|
180
|
+
const r = setupClaudeCode({ force: opts.force });
|
|
181
|
+
printSetupResult('Claude Code', r);
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
printError(`setup-claude-code failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
185
|
+
process.exitCode = 1;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
program
|
|
189
|
+
.command('setup-cursor')
|
|
190
|
+
.description('Wire kbot into Cursor settings.json (mcp.servers)')
|
|
191
|
+
.option('-f, --force', 'Reserved for parity (Cursor has no skill copy step)')
|
|
192
|
+
.action(async (opts) => {
|
|
193
|
+
const { setupCursor } = await import('./setup-editor.js');
|
|
194
|
+
try {
|
|
195
|
+
const r = setupCursor({ force: opts.force });
|
|
196
|
+
printSetupResult('Cursor', r);
|
|
197
|
+
}
|
|
198
|
+
catch (e) {
|
|
199
|
+
printError(`setup-cursor failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
200
|
+
process.exitCode = 1;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
program
|
|
204
|
+
.command('setup-zed')
|
|
205
|
+
.description('Wire kbot into Zed settings.json (assistant.mcpServers — best-effort shape)')
|
|
206
|
+
.option('-f, --force', 'Reserved for parity')
|
|
207
|
+
.action(async (opts) => {
|
|
208
|
+
const { setupZed } = await import('./setup-editor.js');
|
|
209
|
+
try {
|
|
210
|
+
const r = setupZed({ force: opts.force });
|
|
211
|
+
printSetupResult('Zed', r);
|
|
212
|
+
}
|
|
213
|
+
catch (e) {
|
|
214
|
+
printError(`setup-zed failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
215
|
+
process.exitCode = 1;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
program
|
|
219
|
+
.command('setup-all')
|
|
220
|
+
.description('Run setup-claude-code, setup-cursor, and setup-zed in one shot')
|
|
221
|
+
.option('-f, --force', 'Overwrite existing project skill if present')
|
|
222
|
+
.action(async (opts) => {
|
|
223
|
+
const { setupClaudeCode, setupCursor, setupZed } = await import('./setup-editor.js');
|
|
224
|
+
let failed = 0;
|
|
225
|
+
const run = (label, fn) => {
|
|
226
|
+
try {
|
|
227
|
+
printSetupResult(label, fn());
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
failed++;
|
|
231
|
+
printError(`${label} failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
run('Claude Code', () => setupClaudeCode({ force: opts.force }));
|
|
235
|
+
run('Cursor', () => setupCursor({ force: opts.force }));
|
|
236
|
+
run('Zed', () => setupZed({ force: opts.force }));
|
|
237
|
+
if (failed > 0)
|
|
238
|
+
process.exitCode = 1;
|
|
239
|
+
});
|
|
159
240
|
program
|
|
160
241
|
.command('byok')
|
|
161
242
|
.description('Bring Your Own Key — configure your LLM API key (20 providers)')
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface AgentRegistration {
|
|
2
|
+
apps: string[];
|
|
3
|
+
windowIds?: string[];
|
|
4
|
+
}
|
|
5
|
+
export interface LockRecord {
|
|
6
|
+
agentId: string;
|
|
7
|
+
pid: number;
|
|
8
|
+
ts: number;
|
|
9
|
+
windowIds?: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface ClaimResult {
|
|
12
|
+
granted: boolean;
|
|
13
|
+
app: string;
|
|
14
|
+
heldBy?: string;
|
|
15
|
+
since?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface CoordinatorStatus {
|
|
18
|
+
apps: Record<string, {
|
|
19
|
+
heldBy: string;
|
|
20
|
+
since: number;
|
|
21
|
+
} | null>;
|
|
22
|
+
agents: Array<{
|
|
23
|
+
id: string;
|
|
24
|
+
apps: string[];
|
|
25
|
+
claimed: string[];
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
export declare class Coordinator {
|
|
29
|
+
private root;
|
|
30
|
+
private agents;
|
|
31
|
+
/** in-memory mirror of which apps this coordinator instance has claimed */
|
|
32
|
+
private claimed;
|
|
33
|
+
constructor(root?: string);
|
|
34
|
+
private lockPath;
|
|
35
|
+
private readLock;
|
|
36
|
+
private isStale;
|
|
37
|
+
register(agentId: string, reg: AgentRegistration): void;
|
|
38
|
+
claim(agentId: string, app: string): ClaimResult;
|
|
39
|
+
release(agentId: string, app: string): boolean;
|
|
40
|
+
unregister(agentId: string): string[];
|
|
41
|
+
status(): CoordinatorStatus;
|
|
42
|
+
}
|
|
43
|
+
export declare function createCoordinator(root?: string): Coordinator;
|
|
44
|
+
//# sourceMappingURL=computer-use-coordinator.d.ts.map
|
|
Binary file
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Library — local-first per-user file store.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors ChatGPT's File Library: auto-saves uploaded and created files,
|
|
5
|
+
* lists, searches by name/content, fetches by id. Content-addressed (sha256).
|
|
6
|
+
*
|
|
7
|
+
* Storage layout:
|
|
8
|
+
* <root>/index.json — atomic JSON index of entries
|
|
9
|
+
* <root>/blobs/<id> — raw file bytes (id = sha256 of contents)
|
|
10
|
+
*
|
|
11
|
+
* Default root: ~/.kbot/files (overridable via KBOT_FILE_LIBRARY_ROOT or ctor opt).
|
|
12
|
+
*/
|
|
13
|
+
export declare const MAX_FILE_BYTES: number;
|
|
14
|
+
export type FileSource = "user-upload" | "agent-output" | "tool-output";
|
|
15
|
+
export interface FileEntry {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
mimeType: string;
|
|
19
|
+
size: number;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
source: FileSource;
|
|
22
|
+
tags: string[];
|
|
23
|
+
path: string;
|
|
24
|
+
}
|
|
25
|
+
export interface AddFileInput {
|
|
26
|
+
name: string;
|
|
27
|
+
mimeType: string;
|
|
28
|
+
source: FileSource;
|
|
29
|
+
content?: string;
|
|
30
|
+
buffer?: Buffer;
|
|
31
|
+
tags?: string[];
|
|
32
|
+
}
|
|
33
|
+
export interface ListOptions {
|
|
34
|
+
limit?: number;
|
|
35
|
+
since?: string | Date;
|
|
36
|
+
tag?: string;
|
|
37
|
+
}
|
|
38
|
+
export type SearchMode = "name" | "content" | "both";
|
|
39
|
+
export interface SearchOptions {
|
|
40
|
+
query: string;
|
|
41
|
+
mode: SearchMode;
|
|
42
|
+
}
|
|
43
|
+
export interface FileLibraryOptions {
|
|
44
|
+
root?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare class FileLibrary {
|
|
47
|
+
private readonly root;
|
|
48
|
+
private readonly blobsDir;
|
|
49
|
+
private readonly indexPath;
|
|
50
|
+
private writeLock;
|
|
51
|
+
constructor(opts?: FileLibraryOptions);
|
|
52
|
+
getRoot(): string;
|
|
53
|
+
private ensureDirs;
|
|
54
|
+
private readIndex;
|
|
55
|
+
/**
|
|
56
|
+
* Atomic write: serialize → write to <indexPath>.tmp.<rand> → rename.
|
|
57
|
+
*/
|
|
58
|
+
private writeIndexAtomic;
|
|
59
|
+
/**
|
|
60
|
+
* Run a read-modify-write of the index under the writeLock so concurrent
|
|
61
|
+
* mutations don't lose updates. The mutator may return a fresh IndexFile
|
|
62
|
+
* (or undefined to skip the write).
|
|
63
|
+
*/
|
|
64
|
+
private mutateIndex;
|
|
65
|
+
addFile(input: AddFileInput): Promise<FileEntry>;
|
|
66
|
+
listFiles(opts?: ListOptions): Promise<FileEntry[]>;
|
|
67
|
+
getFile(id: string): Promise<{
|
|
68
|
+
entry: FileEntry;
|
|
69
|
+
buffer: Buffer;
|
|
70
|
+
} | null>;
|
|
71
|
+
removeFile(id: string): Promise<boolean>;
|
|
72
|
+
searchFiles(opts: SearchOptions): Promise<FileEntry[]>;
|
|
73
|
+
}
|
|
74
|
+
export declare function getDefaultFileLibrary(): FileLibrary;
|
|
75
|
+
export declare function _resetDefaultFileLibrary(): void;
|
|
76
|
+
//# sourceMappingURL=file-library.d.ts.map
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Library — local-first per-user file store.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors ChatGPT's File Library: auto-saves uploaded and created files,
|
|
5
|
+
* lists, searches by name/content, fetches by id. Content-addressed (sha256).
|
|
6
|
+
*
|
|
7
|
+
* Storage layout:
|
|
8
|
+
* <root>/index.json — atomic JSON index of entries
|
|
9
|
+
* <root>/blobs/<id> — raw file bytes (id = sha256 of contents)
|
|
10
|
+
*
|
|
11
|
+
* Default root: ~/.kbot/files (overridable via KBOT_FILE_LIBRARY_ROOT or ctor opt).
|
|
12
|
+
*/
|
|
13
|
+
import { createHash } from "node:crypto";
|
|
14
|
+
import { promises as fs } from "node:fs";
|
|
15
|
+
import * as os from "node:os";
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
export const MAX_FILE_BYTES = 50 * 1024 * 1024; // 50 MB
|
|
18
|
+
const TEXT_MIME_PREFIXES = ["text/"];
|
|
19
|
+
const TEXT_MIME_EXACT = new Set([
|
|
20
|
+
"application/json",
|
|
21
|
+
"application/yaml",
|
|
22
|
+
"application/x-yaml",
|
|
23
|
+
"application/xml",
|
|
24
|
+
"application/javascript",
|
|
25
|
+
"application/typescript",
|
|
26
|
+
]);
|
|
27
|
+
function isTextMime(mimeType) {
|
|
28
|
+
const m = mimeType.toLowerCase();
|
|
29
|
+
if (TEXT_MIME_EXACT.has(m))
|
|
30
|
+
return true;
|
|
31
|
+
return TEXT_MIME_PREFIXES.some((p) => m.startsWith(p));
|
|
32
|
+
}
|
|
33
|
+
function defaultRoot() {
|
|
34
|
+
const env = process.env.KBOT_FILE_LIBRARY_ROOT;
|
|
35
|
+
if (env && env.length > 0)
|
|
36
|
+
return env;
|
|
37
|
+
return path.join(os.homedir(), ".kbot", "files");
|
|
38
|
+
}
|
|
39
|
+
export class FileLibrary {
|
|
40
|
+
root;
|
|
41
|
+
blobsDir;
|
|
42
|
+
indexPath;
|
|
43
|
+
writeLock = Promise.resolve();
|
|
44
|
+
constructor(opts = {}) {
|
|
45
|
+
this.root = opts.root ?? defaultRoot();
|
|
46
|
+
this.blobsDir = path.join(this.root, "blobs");
|
|
47
|
+
this.indexPath = path.join(this.root, "index.json");
|
|
48
|
+
}
|
|
49
|
+
getRoot() {
|
|
50
|
+
return this.root;
|
|
51
|
+
}
|
|
52
|
+
async ensureDirs() {
|
|
53
|
+
await fs.mkdir(this.blobsDir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
async readIndex() {
|
|
56
|
+
try {
|
|
57
|
+
const raw = await fs.readFile(this.indexPath, "utf8");
|
|
58
|
+
const parsed = JSON.parse(raw);
|
|
59
|
+
if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) {
|
|
60
|
+
return { version: 1, entries: [] };
|
|
61
|
+
}
|
|
62
|
+
return parsed;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const e = err;
|
|
66
|
+
if (e.code === "ENOENT")
|
|
67
|
+
return { version: 1, entries: [] };
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Atomic write: serialize → write to <indexPath>.tmp.<rand> → rename.
|
|
73
|
+
*/
|
|
74
|
+
async writeIndexAtomic(idx) {
|
|
75
|
+
await this.ensureDirs();
|
|
76
|
+
const tmp = `${this.indexPath}.tmp.${process.pid}.${Date.now()}.${Math.random()
|
|
77
|
+
.toString(36)
|
|
78
|
+
.slice(2, 10)}`;
|
|
79
|
+
const data = JSON.stringify(idx, null, 2);
|
|
80
|
+
await fs.writeFile(tmp, data, { encoding: "utf8" });
|
|
81
|
+
await fs.rename(tmp, this.indexPath);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Run a read-modify-write of the index under the writeLock so concurrent
|
|
85
|
+
* mutations don't lose updates. The mutator may return a fresh IndexFile
|
|
86
|
+
* (or undefined to skip the write).
|
|
87
|
+
*/
|
|
88
|
+
async mutateIndex(fn) {
|
|
89
|
+
const run = async () => {
|
|
90
|
+
const idx = await this.readIndex();
|
|
91
|
+
const out = await fn(idx);
|
|
92
|
+
if (out.next)
|
|
93
|
+
await this.writeIndexAtomic(out.next);
|
|
94
|
+
return out.result;
|
|
95
|
+
};
|
|
96
|
+
const next = this.writeLock.then(run, run);
|
|
97
|
+
// Don't poison the lock chain on error.
|
|
98
|
+
this.writeLock = next.then(() => undefined, () => undefined);
|
|
99
|
+
return next;
|
|
100
|
+
}
|
|
101
|
+
async addFile(input) {
|
|
102
|
+
if (!input.name || input.name.trim().length === 0) {
|
|
103
|
+
throw new Error("file-library: name is required");
|
|
104
|
+
}
|
|
105
|
+
if (!input.mimeType) {
|
|
106
|
+
throw new Error("file-library: mimeType is required");
|
|
107
|
+
}
|
|
108
|
+
if (input.content === undefined && input.buffer === undefined) {
|
|
109
|
+
throw new Error("file-library: provide content or buffer");
|
|
110
|
+
}
|
|
111
|
+
if (input.content !== undefined && input.buffer !== undefined) {
|
|
112
|
+
throw new Error("file-library: provide content OR buffer, not both");
|
|
113
|
+
}
|
|
114
|
+
const buf = input.buffer !== undefined
|
|
115
|
+
? input.buffer
|
|
116
|
+
: Buffer.from(input.content, "utf8");
|
|
117
|
+
if (buf.byteLength > MAX_FILE_BYTES) {
|
|
118
|
+
throw new Error(`file-library: file exceeds 50 MB cap (${buf.byteLength} bytes > ${MAX_FILE_BYTES})`);
|
|
119
|
+
}
|
|
120
|
+
const id = createHash("sha256").update(buf).digest("hex");
|
|
121
|
+
await this.ensureDirs();
|
|
122
|
+
const blobPath = path.join(this.blobsDir, id);
|
|
123
|
+
// Write blob if not already present (content-addressed dedup).
|
|
124
|
+
try {
|
|
125
|
+
await fs.access(blobPath);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
const tmp = `${blobPath}.tmp.${process.pid}.${Date.now()}`;
|
|
129
|
+
await fs.writeFile(tmp, buf);
|
|
130
|
+
await fs.rename(tmp, blobPath);
|
|
131
|
+
}
|
|
132
|
+
const entry = {
|
|
133
|
+
id,
|
|
134
|
+
name: input.name,
|
|
135
|
+
mimeType: input.mimeType,
|
|
136
|
+
size: buf.byteLength,
|
|
137
|
+
createdAt: new Date().toISOString(),
|
|
138
|
+
source: input.source,
|
|
139
|
+
tags: [...(input.tags ?? [])],
|
|
140
|
+
path: blobPath,
|
|
141
|
+
};
|
|
142
|
+
return this.mutateIndex((idx) => {
|
|
143
|
+
// If an entry with this id already exists, replace it (latest metadata wins,
|
|
144
|
+
// since the blob bytes are identical by id).
|
|
145
|
+
const filtered = idx.entries.filter((e) => e.id !== id);
|
|
146
|
+
filtered.push(entry);
|
|
147
|
+
return { next: { version: 1, entries: filtered }, result: entry };
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async listFiles(opts = {}) {
|
|
151
|
+
const idx = await this.readIndex();
|
|
152
|
+
let entries = idx.entries.slice();
|
|
153
|
+
if (opts.tag) {
|
|
154
|
+
const tag = opts.tag;
|
|
155
|
+
entries = entries.filter((e) => e.tags.includes(tag));
|
|
156
|
+
}
|
|
157
|
+
if (opts.since !== undefined) {
|
|
158
|
+
const sinceMs = opts.since instanceof Date
|
|
159
|
+
? opts.since.getTime()
|
|
160
|
+
: new Date(opts.since).getTime();
|
|
161
|
+
if (!Number.isNaN(sinceMs)) {
|
|
162
|
+
entries = entries.filter((e) => new Date(e.createdAt).getTime() >= sinceMs);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Newest first.
|
|
166
|
+
entries.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
167
|
+
if (typeof opts.limit === "number" && opts.limit >= 0) {
|
|
168
|
+
entries = entries.slice(0, opts.limit);
|
|
169
|
+
}
|
|
170
|
+
return entries;
|
|
171
|
+
}
|
|
172
|
+
async getFile(id) {
|
|
173
|
+
const idx = await this.readIndex();
|
|
174
|
+
const entry = idx.entries.find((e) => e.id === id);
|
|
175
|
+
if (!entry)
|
|
176
|
+
return null;
|
|
177
|
+
try {
|
|
178
|
+
const buffer = await fs.readFile(entry.path);
|
|
179
|
+
return { entry, buffer };
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
const e = err;
|
|
183
|
+
if (e.code === "ENOENT")
|
|
184
|
+
return null;
|
|
185
|
+
throw err;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async removeFile(id) {
|
|
189
|
+
const removedEntry = await this.mutateIndex((idx) => {
|
|
190
|
+
const entry = idx.entries.find((e) => e.id === id);
|
|
191
|
+
if (!entry)
|
|
192
|
+
return { result: null };
|
|
193
|
+
const remaining = idx.entries.filter((e) => e.id !== id);
|
|
194
|
+
return {
|
|
195
|
+
next: { version: 1, entries: remaining },
|
|
196
|
+
result: entry,
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
if (!removedEntry)
|
|
200
|
+
return false;
|
|
201
|
+
try {
|
|
202
|
+
await fs.unlink(removedEntry.path);
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
const e = err;
|
|
206
|
+
if (e.code !== "ENOENT")
|
|
207
|
+
throw err;
|
|
208
|
+
}
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
async searchFiles(opts) {
|
|
212
|
+
const q = (opts.query ?? "").toLowerCase();
|
|
213
|
+
if (q.length === 0)
|
|
214
|
+
return [];
|
|
215
|
+
const idx = await this.readIndex();
|
|
216
|
+
const entries = idx.entries;
|
|
217
|
+
const matchName = (e) => e.name.toLowerCase().includes(q);
|
|
218
|
+
const matchContent = async (e) => {
|
|
219
|
+
if (!isTextMime(e.mimeType))
|
|
220
|
+
return false;
|
|
221
|
+
try {
|
|
222
|
+
const buf = await fs.readFile(e.path);
|
|
223
|
+
return buf.toString("utf8").toLowerCase().includes(q);
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
const ne = err;
|
|
227
|
+
if (ne.code === "ENOENT")
|
|
228
|
+
return false;
|
|
229
|
+
throw err;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
const seen = new Set();
|
|
233
|
+
const out = [];
|
|
234
|
+
if (opts.mode === "name" || opts.mode === "both") {
|
|
235
|
+
for (const e of entries) {
|
|
236
|
+
if (matchName(e) && !seen.has(e.id)) {
|
|
237
|
+
seen.add(e.id);
|
|
238
|
+
out.push(e);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (opts.mode === "content" || opts.mode === "both") {
|
|
243
|
+
for (const e of entries) {
|
|
244
|
+
if (seen.has(e.id))
|
|
245
|
+
continue;
|
|
246
|
+
// eslint-disable-next-line no-await-in-loop
|
|
247
|
+
const hit = await matchContent(e);
|
|
248
|
+
if (hit) {
|
|
249
|
+
seen.add(e.id);
|
|
250
|
+
out.push(e);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
out.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
255
|
+
return out;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Singleton helper for default root usage.
|
|
259
|
+
let _default = null;
|
|
260
|
+
export function getDefaultFileLibrary() {
|
|
261
|
+
if (!_default)
|
|
262
|
+
_default = new FileLibrary();
|
|
263
|
+
return _default;
|
|
264
|
+
}
|
|
265
|
+
// Reset the cached default — primarily for tests that mutate env.
|
|
266
|
+
export function _resetDefaultFileLibrary() {
|
|
267
|
+
_default = null;
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=file-library.js.map
|
package/dist/ide/mcp-server.js
CHANGED
|
@@ -54,7 +54,7 @@ export async function startMcpServer(config = {}) {
|
|
|
54
54
|
const staticTools = [
|
|
55
55
|
{
|
|
56
56
|
name: 'kbot_chat',
|
|
57
|
-
description: 'Send a natural language message to kbot and receive a
|
|
57
|
+
description: 'Send a natural language message to the kbot CLI and receive a response from one of its built-in specialist roles (saved prompt configurations such as coder, researcher, writer, analyst, guardian — invoked manually by the user). kbot routes to the best-fit role based on message intent, or you can force a specific role via the agent parameter. Use this tool when you need AI-assisted help for coding, research, writing, analysis, security review, or general developer tasks. Do not use this for direct file operations (use kbot_read_file, kbot_edit_file, kbot_write_file instead) or shell commands (use kbot_bash instead). Each call is stateless -- conversation history is not preserved between calls. Returns the response text, plus optional thinking traces and tool-use results if sub-tools were invoked.',
|
|
58
58
|
inputSchema: {
|
|
59
59
|
type: 'object',
|
|
60
60
|
properties: {
|
|
@@ -137,7 +137,7 @@ export async function startMcpServer(config = {}) {
|
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
name: 'kbot_status',
|
|
140
|
-
description: 'Retrieve kbot runtime status as a JSON object. Returns the active specialist
|
|
140
|
+
description: 'Retrieve kbot runtime status as a JSON object. Returns the active specialist role (saved prompt configuration), pattern-cache statistics (patterns, solutions, knowledge entries, total messages processed), session count, and registered tool count. Use this tool to verify kbot is properly configured, check which role is active, or monitor cached-pattern progress. Do not use this for project-specific status (use kbot_bash with "git status" instead). Read-only operation with no side effects.',
|
|
141
141
|
inputSchema: {
|
|
142
142
|
type: 'object',
|
|
143
143
|
properties: {},
|
|
@@ -145,7 +145,7 @@ export async function startMcpServer(config = {}) {
|
|
|
145
145
|
},
|
|
146
146
|
{
|
|
147
147
|
name: 'kbot_agent',
|
|
148
|
-
description: 'Switch the active specialist
|
|
148
|
+
description: 'Switch the active specialist role (saved prompt configuration) for subsequent kbot_chat calls, or list all available roles when called without arguments. Use this tool to optimize responses by selecting the right specialist prompt -- e.g., switch to "guardian" before a security review, or "researcher" before a deep-dive investigation. Do not use this if you only need to route a single message (pass the agent parameter to kbot_chat instead). Side effects: when an ID is provided, changes the active role used by all future kbot_chat calls in this session.',
|
|
149
149
|
inputSchema: {
|
|
150
150
|
type: 'object',
|
|
151
151
|
properties: {
|
|
@@ -177,7 +177,7 @@ export async function startMcpServer(config = {}) {
|
|
|
177
177
|
},
|
|
178
178
|
{
|
|
179
179
|
name: 'kbot_plan',
|
|
180
|
-
description: 'Generate and optionally execute
|
|
180
|
+
description: 'Generate, and optionally execute, a multi-step plan for a complex task. The planner analyzes the task, breaks it into ordered subtasks, selects appropriate tools for each step, executes them sequentially, and retries failed steps with adjusted parameters. Use this tool for complex multi-file refactors, full-stack feature implementations, research-then-implement workflows, or any task requiring coordination of multiple tools. Do not use this for simple single-step operations (use the specific tool directly). Side effects: depends on plan steps -- may read/write files, run shell commands, make API calls. Set auto_approve=false (default) to review the generated plan before any execution begins; auto_approve=true is opt-in.',
|
|
181
181
|
inputSchema: {
|
|
182
182
|
type: 'object',
|
|
183
183
|
properties: {
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Managed Agents client (April 2026 launch).
|
|
3
|
+
*
|
|
4
|
+
* Hosted long-horizon agent platform. This module is a STANDALONE backend
|
|
5
|
+
* that workspace agents can route through when ANTHROPIC_API_KEY is set.
|
|
6
|
+
* Wiring into ./workspace-agents.ts happens in a follow-up pass.
|
|
7
|
+
*
|
|
8
|
+
* Beta header: `anthropic-beta: managed-agents-2026-04-01` is sent on every
|
|
9
|
+
* request.
|
|
10
|
+
*
|
|
11
|
+
* SPEC: best-effort, refine when official docs published.
|
|
12
|
+
* Endpoint shape mirrors the public beta announcement; refine when the
|
|
13
|
+
* official OpenAPI spec lands.
|
|
14
|
+
*/
|
|
15
|
+
export interface CreateSessionInput {
|
|
16
|
+
mission: string;
|
|
17
|
+
allowedTools?: string[];
|
|
18
|
+
model?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface CreateSessionOutput {
|
|
21
|
+
session_id: string;
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface SendTurnInput {
|
|
25
|
+
sessionId: string;
|
|
26
|
+
input: string;
|
|
27
|
+
}
|
|
28
|
+
export interface SendTurnOutput {
|
|
29
|
+
output: string;
|
|
30
|
+
tool_calls?: unknown[];
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
export interface SessionState {
|
|
34
|
+
session_id: string;
|
|
35
|
+
mission?: string;
|
|
36
|
+
status?: string;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
export interface ListSessionsOutput {
|
|
40
|
+
sessions: SessionState[];
|
|
41
|
+
[key: string]: unknown;
|
|
42
|
+
}
|
|
43
|
+
export interface MemoryReadInput {
|
|
44
|
+
sessionId: string;
|
|
45
|
+
key?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface MemoryWriteInput {
|
|
48
|
+
sessionId: string;
|
|
49
|
+
key: string;
|
|
50
|
+
value: unknown;
|
|
51
|
+
}
|
|
52
|
+
export interface MemoryAck {
|
|
53
|
+
ok: boolean;
|
|
54
|
+
[key: string]: unknown;
|
|
55
|
+
}
|
|
56
|
+
export declare class AnthropicManagedAgentsError extends Error {
|
|
57
|
+
readonly status: number;
|
|
58
|
+
readonly body: string;
|
|
59
|
+
constructor(message: string, status: number, body: string);
|
|
60
|
+
}
|
|
61
|
+
export interface AnthropicManagedAgentsClientOptions {
|
|
62
|
+
/** Override the API key (default: process.env.ANTHROPIC_API_KEY). */
|
|
63
|
+
apiKey?: string;
|
|
64
|
+
/** Override the base URL (default: https://api.anthropic.com/v1). */
|
|
65
|
+
baseUrl?: string;
|
|
66
|
+
/** Override fetch (used by tests). */
|
|
67
|
+
fetchImpl?: typeof fetch;
|
|
68
|
+
}
|
|
69
|
+
export declare class AnthropicManagedAgentsClient {
|
|
70
|
+
private readonly apiKey;
|
|
71
|
+
private readonly baseUrl;
|
|
72
|
+
private readonly fetchImpl;
|
|
73
|
+
constructor(opts?: AnthropicManagedAgentsClientOptions);
|
|
74
|
+
createSession(input: CreateSessionInput): Promise<CreateSessionOutput>;
|
|
75
|
+
sendTurn(input: SendTurnInput): Promise<SendTurnOutput>;
|
|
76
|
+
getSession(input: {
|
|
77
|
+
sessionId: string;
|
|
78
|
+
}): Promise<SessionState>;
|
|
79
|
+
listSessions(): Promise<ListSessionsOutput>;
|
|
80
|
+
closeSession(input: {
|
|
81
|
+
sessionId: string;
|
|
82
|
+
}): Promise<{
|
|
83
|
+
ok: boolean;
|
|
84
|
+
[key: string]: unknown;
|
|
85
|
+
}>;
|
|
86
|
+
memoryRead(input: MemoryReadInput): Promise<unknown>;
|
|
87
|
+
memoryWrite(input: MemoryWriteInput): Promise<MemoryAck>;
|
|
88
|
+
private request;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=managed-agents-anthropic.d.ts.map
|