@akanjs/cli 3.0.0-beta.16 → 3.0.0-beta.17
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/.build-stamp +1 -1
- package/{CodeAgent-zgccwajm.js → CodeAgent-gjqnc2mg.js} +2 -2
- package/{CodeTui-993tx7gf.js → CodeTui-nd9hqvrw.js} +196 -11
- package/akanCode.js +9 -9
- package/{cloud.command-4x35k1z6.js → cloud.command-dk5tj39k.js} +2 -2
- package/{cloud.script-3k8nbbpn.js → cloud.script-ch3xrw3s.js} +2 -2
- package/{code.command-mrfb7a1g.js → code.command-88sebgnn.js} +5 -5
- package/{index-5405kc0x.js → index-2sq06vv0.js} +169 -199
- package/{index-sxg87a8f.js → index-bzakk0c2.js} +160 -96
- package/{index-wfwknnje.js → index-jwrpsrg3.js} +8 -6
- package/{index-zg0v1zte.js → index-n8kt2wh6.js} +1 -1
- package/{index-018dszb3.js → index-p0tew3fq.js} +2 -0
- package/index-qt8dqgnf.js +250 -0
- package/index.js +6 -6
- package/{localRegistry.command-tt00nwwg.js → localRegistry.command-yppdqrxv.js} +1 -1
- package/{package.command-8sy6jjwy.js → package.command-cgp2p2v5.js} +1 -1
- package/package.json +8 -6
- package/{subspace.command-x9897gj4.js → subspace.command-jqv5n79w.js} +1 -1
- package/{workspace.command-ayqa1rgt.js → workspace.command-txv1yv5e.js} +2 -2
- package/index-jgrnpt6y.js +0 -121
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
SubagentPool2
|
|
4
|
-
|
|
3
|
+
SubagentPool2,
|
|
4
|
+
akanCodePaths2,
|
|
5
|
+
McpServerConfig
|
|
6
|
+
} from "./index-qt8dqgnf.js";
|
|
5
7
|
import {
|
|
6
8
|
stripAnsi
|
|
7
9
|
} from "./index-7md2g9vw.js";
|
|
@@ -9,7 +11,7 @@ import {
|
|
|
9
11
|
akanCodeModel2,
|
|
10
12
|
akanCodeModelSupportsImages2,
|
|
11
13
|
akanCodeModelWarnings2
|
|
12
|
-
} from "./index-
|
|
14
|
+
} from "./index-jwrpsrg3.js";
|
|
13
15
|
|
|
14
16
|
// pkgs/@akanjs/devkit/codeAgent/agent/CodeAgent.ts
|
|
15
17
|
import {
|
|
@@ -639,31 +641,12 @@ class MailToolPack2 {
|
|
|
639
641
|
}
|
|
640
642
|
|
|
641
643
|
// pkgs/@akanjs/devkit/codeAgent/tools/McpToolPack.ts
|
|
642
|
-
import {
|
|
643
|
-
|
|
644
|
+
import {
|
|
645
|
+
codeAgentClip,
|
|
646
|
+
codeAgentOutputChars
|
|
647
|
+
} from "akanjs/common";
|
|
644
648
|
import { Type as Type3 } from "typebox";
|
|
645
649
|
|
|
646
|
-
// pkgs/@akanjs/devkit/codeAgent/agent/akanCodePaths.ts
|
|
647
|
-
import { existsSync as existsSync4 } from "fs";
|
|
648
|
-
import { homedir as homedir2 } from "os";
|
|
649
|
-
import path4 from "path";
|
|
650
|
-
var builtinSkillsDir = () => {
|
|
651
|
-
const candidates = [path4.join(import.meta.dir, "skills"), path4.join(import.meta.dir, "..", "skills")];
|
|
652
|
-
return candidates.find((candidate) => existsSync4(candidate));
|
|
653
|
-
};
|
|
654
|
-
var akanCodePaths2 = {
|
|
655
|
-
workspaceDir: (workspaceRoot) => path4.join(workspaceRoot, ".akan", "code"),
|
|
656
|
-
sessionsDir: (workspaceRoot) => path4.join(workspaceRoot, ".akan", "code", "sessions"),
|
|
657
|
-
extensionsDir: (workspaceRoot) => path4.join(workspaceRoot, ".akan", "code", "extensions"),
|
|
658
|
-
skillsDir: (workspaceRoot) => path4.join(workspaceRoot, ".akan", "code", "skills"),
|
|
659
|
-
mailDir: (workspaceRoot) => path4.join(workspaceRoot, ".akan", "code", "mail"),
|
|
660
|
-
builtinSkillsDir,
|
|
661
|
-
mcpFile: (workspaceRoot) => path4.join(workspaceRoot, ".akan", "code", "mcp.json"),
|
|
662
|
-
globalDir: () => path4.join(homedir2(), ".akan", "code"),
|
|
663
|
-
authFile: () => path4.join(homedir2(), ".akan", "code", "auth.json"),
|
|
664
|
-
modelsFile: () => path4.join(homedir2(), ".akan", "code", "models.json")
|
|
665
|
-
};
|
|
666
|
-
|
|
667
650
|
// pkgs/@akanjs/devkit/codeAgent/tools/McpClient.ts
|
|
668
651
|
var protocolVersion = "2025-06-18";
|
|
669
652
|
|
|
@@ -804,29 +787,34 @@ class McpClient2 {
|
|
|
804
787
|
|
|
805
788
|
// pkgs/@akanjs/devkit/codeAgent/tools/McpToolPack.ts
|
|
806
789
|
class McpToolPack2 {
|
|
807
|
-
#options;
|
|
808
790
|
#clients = [];
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
791
|
+
#status = [];
|
|
792
|
+
constructor() {}
|
|
812
793
|
static async connect(options) {
|
|
813
794
|
const refs = McpToolPack2.#refs(options);
|
|
814
795
|
if (!refs.length)
|
|
815
796
|
return;
|
|
816
|
-
const pack = new McpToolPack2
|
|
797
|
+
const pack = new McpToolPack2;
|
|
817
798
|
for (const ref of refs) {
|
|
799
|
+
const base = { name: ref.name, transport: ref.transport, target: McpServerConfig.targetOf(ref) };
|
|
818
800
|
try {
|
|
819
801
|
const client = await new McpClient2(ref).connect();
|
|
820
|
-
|
|
802
|
+
const tools = await client.listTools();
|
|
803
|
+
pack.#clients.push({ client, tools });
|
|
804
|
+
pack.#status.push({ ...base, tools: tools.map((tool) => McpToolPack2.#nameOf(ref.name, tool.name)) });
|
|
821
805
|
} catch (error) {
|
|
822
806
|
options.onNotice?.(`MCP server "${ref.name}" is unavailable: ${String(error)}`);
|
|
807
|
+
pack.#status.push({ ...base, tools: [], error: String(error) });
|
|
823
808
|
}
|
|
824
809
|
}
|
|
825
|
-
return pack
|
|
810
|
+
return pack;
|
|
826
811
|
}
|
|
827
812
|
get toolNames() {
|
|
828
813
|
return this.#clients.flatMap(({ client, tools }) => tools.map((tool) => McpToolPack2.#nameOf(client.ref.name, tool.name)));
|
|
829
814
|
}
|
|
815
|
+
get status() {
|
|
816
|
+
return this.#status;
|
|
817
|
+
}
|
|
830
818
|
extension() {
|
|
831
819
|
return { name: "akan-mcp", factory: (pi) => this.#register(pi) };
|
|
832
820
|
}
|
|
@@ -863,29 +851,7 @@ class McpToolPack2 {
|
|
|
863
851
|
if (options.profile.tools.mcp === "off")
|
|
864
852
|
return [];
|
|
865
853
|
const declared = Array.isArray(options.profile.tools.mcp) ? options.profile.tools.mcp : [];
|
|
866
|
-
return [...
|
|
867
|
-
}
|
|
868
|
-
static #fromFile(workspaceRoot) {
|
|
869
|
-
const file = akanCodePaths2.mcpFile(workspaceRoot);
|
|
870
|
-
if (!existsSync5(file))
|
|
871
|
-
return [];
|
|
872
|
-
try {
|
|
873
|
-
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
874
|
-
const entries = Object.entries(parsed.mcpServers ?? parsed.servers ?? {});
|
|
875
|
-
return entries.filter(([, entry]) => !entry.disabled).map(([name, entry]) => {
|
|
876
|
-
const transport = entry.url ? "http" : "stdio";
|
|
877
|
-
return {
|
|
878
|
-
name,
|
|
879
|
-
transport,
|
|
880
|
-
...entry.command ? { command: entry.command } : {},
|
|
881
|
-
...entry.args ? { args: entry.args } : {},
|
|
882
|
-
...entry.url ? { url: entry.url } : {},
|
|
883
|
-
...entry.env ? { env: entry.env } : {}
|
|
884
|
-
};
|
|
885
|
-
});
|
|
886
|
-
} catch {
|
|
887
|
-
return [];
|
|
888
|
-
}
|
|
854
|
+
return [...McpServerConfig.read(options.workspaceRoot), ...declared];
|
|
889
855
|
}
|
|
890
856
|
}
|
|
891
857
|
|
|
@@ -1098,6 +1064,7 @@ class AkanCodePlugins2 {
|
|
|
1098
1064
|
...options.onNotice ? { onNotice: options.onNotice } : {}
|
|
1099
1065
|
});
|
|
1100
1066
|
const dispose = () => mcp?.close();
|
|
1067
|
+
const mcpStatus = mcp?.status ?? [];
|
|
1101
1068
|
const web = new WebToolPack2({ profile: options.profile });
|
|
1102
1069
|
const webExtension = web.extension();
|
|
1103
1070
|
const sessions = new SessionToolPack2({
|
|
@@ -1113,6 +1080,7 @@ class AkanCodePlugins2 {
|
|
|
1113
1080
|
return {
|
|
1114
1081
|
extensions: [mcp?.extension(), webExtension, sessionExtension, mailExtension].filter((entry) => !!entry),
|
|
1115
1082
|
toolNames: [...mcp?.toolNames ?? [], ...web.names(), ...sessions.names(), ...mail.names()],
|
|
1083
|
+
mcp: mcpStatus,
|
|
1116
1084
|
dispose
|
|
1117
1085
|
};
|
|
1118
1086
|
const readOnly = !options.profile.tools.builtin.includes("write");
|
|
@@ -1127,7 +1095,8 @@ class AkanCodePlugins2 {
|
|
|
1127
1095
|
cwd: options.cwd,
|
|
1128
1096
|
parent: options.profile,
|
|
1129
1097
|
depth: options.depth,
|
|
1130
|
-
...options.onNotice ? { onNotice: options.onNotice } : {}
|
|
1098
|
+
...options.onNotice ? { onNotice: options.onNotice } : {},
|
|
1099
|
+
...options.onAgents ? { onAgents: options.onAgents } : {}
|
|
1131
1100
|
});
|
|
1132
1101
|
if (subagent)
|
|
1133
1102
|
extensions.push(subagent);
|
|
@@ -1155,6 +1124,7 @@ class AkanCodePlugins2 {
|
|
|
1155
1124
|
...sessions.names(),
|
|
1156
1125
|
...mail.names()
|
|
1157
1126
|
],
|
|
1127
|
+
mcp: mcpStatus,
|
|
1158
1128
|
dispose
|
|
1159
1129
|
};
|
|
1160
1130
|
}
|
|
@@ -1184,36 +1154,31 @@ class AkanCodePlugins2 {
|
|
|
1184
1154
|
}
|
|
1185
1155
|
|
|
1186
1156
|
// pkgs/@akanjs/devkit/codeAgent/agent/AkanCodeServices.ts
|
|
1187
|
-
import { existsSync as
|
|
1188
|
-
import {
|
|
1189
|
-
AuthStorage,
|
|
1190
|
-
ModelRegistry,
|
|
1191
|
-
SessionManager as SessionManager2,
|
|
1192
|
-
SettingsManager
|
|
1193
|
-
} from "@earendil-works/pi-coding-agent";
|
|
1157
|
+
import { existsSync as existsSync7, mkdirSync } from "fs";
|
|
1158
|
+
import { ModelRuntime, SessionManager as SessionManager2, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
1194
1159
|
|
|
1195
1160
|
// pkgs/@akanjs/devkit/codeAgent/tools/AkanEnvKeys.ts
|
|
1196
|
-
import { existsSync as
|
|
1197
|
-
import
|
|
1161
|
+
import { existsSync as existsSync4, readFileSync } from "fs";
|
|
1162
|
+
import path4 from "path";
|
|
1198
1163
|
|
|
1199
1164
|
class AkanEnvKeys2 {
|
|
1200
|
-
static apply(
|
|
1165
|
+
static async apply(runtime, workspaceRoot) {
|
|
1201
1166
|
const applied = [];
|
|
1202
1167
|
for (const [name, value] of AkanEnvKeys2.#entries(workspaceRoot)) {
|
|
1203
1168
|
const provider = AkanEnvKeys2.#providerOf(name);
|
|
1204
1169
|
if (!provider || !value)
|
|
1205
1170
|
continue;
|
|
1206
|
-
|
|
1171
|
+
await runtime.setRuntimeApiKey(provider, value);
|
|
1207
1172
|
applied.push(provider);
|
|
1208
1173
|
}
|
|
1209
1174
|
return applied;
|
|
1210
1175
|
}
|
|
1211
1176
|
static #entries(workspaceRoot) {
|
|
1212
1177
|
const fromProcess = Object.entries(process.env).filter(([, value]) => typeof value === "string");
|
|
1213
|
-
const file =
|
|
1214
|
-
if (!
|
|
1178
|
+
const file = path4.join(workspaceRoot, ".env");
|
|
1179
|
+
if (!existsSync4(file))
|
|
1215
1180
|
return fromProcess;
|
|
1216
|
-
const fromFile =
|
|
1181
|
+
const fromFile = readFileSync(file, "utf8").split(`
|
|
1217
1182
|
`).map((line) => line.trim()).filter((line) => line && !line.startsWith("#") && line.includes("=")).map((line) => {
|
|
1218
1183
|
const index = line.indexOf("=");
|
|
1219
1184
|
return [
|
|
@@ -1229,89 +1194,82 @@ class AkanEnvKeys2 {
|
|
|
1229
1194
|
}
|
|
1230
1195
|
}
|
|
1231
1196
|
|
|
1232
|
-
// pkgs/@akanjs/devkit/codeAgent/agent/
|
|
1233
|
-
import {
|
|
1234
|
-
|
|
1235
|
-
existsSync as existsSync7,
|
|
1236
|
-
mkdirSync,
|
|
1237
|
-
openSync,
|
|
1238
|
-
readFileSync as readFileSync3,
|
|
1239
|
-
renameSync,
|
|
1240
|
-
unlinkSync,
|
|
1241
|
-
writeFileSync
|
|
1242
|
-
} from "fs";
|
|
1243
|
-
import path6 from "path";
|
|
1197
|
+
// pkgs/@akanjs/devkit/codeAgent/agent/AkanContextFiles.ts
|
|
1198
|
+
import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
|
|
1199
|
+
import path5 from "path";
|
|
1244
1200
|
|
|
1245
|
-
class
|
|
1246
|
-
#
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
this.#write(next);
|
|
1258
|
-
return result;
|
|
1259
|
-
} finally {
|
|
1260
|
-
this.#release();
|
|
1201
|
+
class AkanContextFiles {
|
|
1202
|
+
static #frontmatter = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
1203
|
+
static extend(base, options) {
|
|
1204
|
+
const seen = new Set(base.map((file) => file.path));
|
|
1205
|
+
const contents = new Set(base.map((file) => file.content.trim()));
|
|
1206
|
+
const added = [];
|
|
1207
|
+
for (const file of [...AkanContextFiles.#claude(base), ...AkanContextFiles.#cursor(options)]) {
|
|
1208
|
+
if (seen.has(file.path) || contents.has(file.content.trim()) || !file.content.trim())
|
|
1209
|
+
continue;
|
|
1210
|
+
seen.add(file.path);
|
|
1211
|
+
contents.add(file.content.trim());
|
|
1212
|
+
added.push(file);
|
|
1261
1213
|
}
|
|
1214
|
+
return [...base, ...added];
|
|
1262
1215
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1216
|
+
static #claude(base) {
|
|
1217
|
+
const files = [];
|
|
1218
|
+
for (const file of base) {
|
|
1219
|
+
if (!/^AGENTS\.(md|MD)$/.test(path5.basename(file.path)))
|
|
1220
|
+
continue;
|
|
1221
|
+
for (const name of ["CLAUDE.md", "CLAUDE.MD"]) {
|
|
1222
|
+
const candidate = path5.join(path5.dirname(file.path), name);
|
|
1223
|
+
const content = AkanContextFiles.#read(candidate);
|
|
1224
|
+
if (content !== undefined)
|
|
1225
|
+
files.push({ path: candidate, content });
|
|
1226
|
+
}
|
|
1272
1227
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
const
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
}
|
|
1286
|
-
#acquire() {
|
|
1287
|
-
mkdirSync(path6.dirname(this.#lockPath), { recursive: true, mode: 448 });
|
|
1288
|
-
const deadline = Date.now() + 5000;
|
|
1289
|
-
for (;; ) {
|
|
1290
|
-
try {
|
|
1291
|
-
closeSync(openSync(this.#lockPath, "wx"));
|
|
1292
|
-
return;
|
|
1293
|
-
} catch {
|
|
1294
|
-
if (this.#lockIsStale() || Date.now() > deadline) {
|
|
1295
|
-
try {
|
|
1296
|
-
unlinkSync(this.#lockPath);
|
|
1297
|
-
} catch {}
|
|
1228
|
+
return files;
|
|
1229
|
+
}
|
|
1230
|
+
static #cursor(options) {
|
|
1231
|
+
const files = [];
|
|
1232
|
+
const roots = [...new Set([options.workspaceRoot, options.cwd])];
|
|
1233
|
+
for (const root of roots) {
|
|
1234
|
+
const legacy = AkanContextFiles.#read(path5.join(root, ".cursorrules"));
|
|
1235
|
+
if (legacy !== undefined)
|
|
1236
|
+
files.push({ path: path5.join(root, ".cursorrules"), content: legacy });
|
|
1237
|
+
for (const file of AkanContextFiles.#mdcFiles(path5.join(root, ".cursor", "rules"))) {
|
|
1238
|
+
const raw = AkanContextFiles.#read(file);
|
|
1239
|
+
if (raw === undefined)
|
|
1298
1240
|
continue;
|
|
1299
|
-
|
|
1300
|
-
|
|
1241
|
+
const body = AkanContextFiles.#applied(raw);
|
|
1242
|
+
if (body !== undefined)
|
|
1243
|
+
files.push({ path: file, content: body });
|
|
1301
1244
|
}
|
|
1302
1245
|
}
|
|
1246
|
+
return files;
|
|
1247
|
+
}
|
|
1248
|
+
static #applied(raw) {
|
|
1249
|
+
const match = AkanContextFiles.#frontmatter.exec(raw);
|
|
1250
|
+
if (!match)
|
|
1251
|
+
return raw;
|
|
1252
|
+
if (!/^\s*alwaysApply\s*:\s*true\s*$/m.test(match[1] ?? ""))
|
|
1253
|
+
return;
|
|
1254
|
+
return raw.slice(match[0].length);
|
|
1303
1255
|
}
|
|
1304
|
-
#
|
|
1256
|
+
static #mdcFiles(dir) {
|
|
1257
|
+
if (!existsSync5(dir))
|
|
1258
|
+
return [];
|
|
1305
1259
|
try {
|
|
1306
|
-
return
|
|
1260
|
+
return readdirSync(dir, { recursive: true, withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".mdc")).map((entry) => path5.join(entry.parentPath ?? dir, entry.name)).sort();
|
|
1307
1261
|
} catch {
|
|
1308
|
-
return
|
|
1262
|
+
return [];
|
|
1309
1263
|
}
|
|
1310
1264
|
}
|
|
1311
|
-
#
|
|
1265
|
+
static #read(file) {
|
|
1312
1266
|
try {
|
|
1313
|
-
|
|
1314
|
-
|
|
1267
|
+
if (!existsSync5(file) || !statSync2(file).isFile())
|
|
1268
|
+
return;
|
|
1269
|
+
return readFileSync2(file, "utf8").replace(/^\uFEFF/, "");
|
|
1270
|
+
} catch {
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1315
1273
|
}
|
|
1316
1274
|
}
|
|
1317
1275
|
|
|
@@ -1339,26 +1297,26 @@ var akanSystemPrompt2 = (profile) => {
|
|
|
1339
1297
|
};
|
|
1340
1298
|
|
|
1341
1299
|
// pkgs/@akanjs/devkit/codeAgent/agent/CodeSessionIndex.ts
|
|
1342
|
-
import { existsSync as
|
|
1343
|
-
import
|
|
1300
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
|
|
1301
|
+
import path6 from "path";
|
|
1344
1302
|
|
|
1345
1303
|
class CodeSessionIndex2 {
|
|
1346
1304
|
static readLimit = 512 * 1024;
|
|
1347
1305
|
static list(dir, limit = 30) {
|
|
1348
|
-
if (!
|
|
1306
|
+
if (!existsSync6(dir))
|
|
1349
1307
|
return [];
|
|
1350
|
-
const files =
|
|
1308
|
+
const files = readdirSync2(dir).filter((entry) => entry.endsWith(".jsonl")).map((entry) => path6.join(dir, entry)).map((file) => ({ file, updatedAt: CodeSessionIndex2.#mtime(file) })).sort((left, right) => right.updatedAt - left.updatedAt).slice(0, limit);
|
|
1351
1309
|
return files.map((entry) => CodeSessionIndex2.#read(entry.file, entry.updatedAt)).filter((entry) => !!entry);
|
|
1352
1310
|
}
|
|
1353
1311
|
static fileOf(dir, id) {
|
|
1354
|
-
if (!
|
|
1312
|
+
if (!existsSync6(dir))
|
|
1355
1313
|
return;
|
|
1356
|
-
const match =
|
|
1357
|
-
return match ?
|
|
1314
|
+
const match = readdirSync2(dir).find((entry) => entry.endsWith(`${id}.jsonl`) || entry === `${id}.jsonl`);
|
|
1315
|
+
return match ? path6.join(dir, match) : undefined;
|
|
1358
1316
|
}
|
|
1359
1317
|
static #mtime(file) {
|
|
1360
1318
|
try {
|
|
1361
|
-
return
|
|
1319
|
+
return statSync3(file).mtimeMs;
|
|
1362
1320
|
} catch {
|
|
1363
1321
|
return 0;
|
|
1364
1322
|
}
|
|
@@ -1389,9 +1347,9 @@ class CodeSessionIndex2 {
|
|
|
1389
1347
|
}
|
|
1390
1348
|
static #lines(file) {
|
|
1391
1349
|
try {
|
|
1392
|
-
if (
|
|
1350
|
+
if (statSync3(file).size > CodeSessionIndex2.readLimit)
|
|
1393
1351
|
return [];
|
|
1394
|
-
return
|
|
1352
|
+
return readFileSync3(file, "utf8").split(`
|
|
1395
1353
|
`).filter((line) => !!line.trim());
|
|
1396
1354
|
} catch {
|
|
1397
1355
|
return [];
|
|
@@ -1419,20 +1377,20 @@ class AkanCodeServices2 {
|
|
|
1419
1377
|
quietStartup: true
|
|
1420
1378
|
});
|
|
1421
1379
|
}
|
|
1422
|
-
static
|
|
1423
|
-
|
|
1424
|
-
const
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
return
|
|
1380
|
+
static async runtime(workspaceRoot) {
|
|
1381
|
+
mkdirSync(akanCodePaths2.globalDir(), { recursive: true, mode: 448 });
|
|
1382
|
+
const runtime = await ModelRuntime.create({
|
|
1383
|
+
authPath: akanCodePaths2.authFile(),
|
|
1384
|
+
modelsPath: akanCodePaths2.modelsFile()
|
|
1385
|
+
});
|
|
1386
|
+
await AkanEnvKeys2.apply(runtime, workspaceRoot);
|
|
1387
|
+
return runtime;
|
|
1430
1388
|
}
|
|
1431
1389
|
static sessions(workspaceRoot, cwd, profile, resume) {
|
|
1432
1390
|
if (profile.session.store !== "file")
|
|
1433
1391
|
return SessionManager2.inMemory(cwd);
|
|
1434
1392
|
const dir = akanCodePaths2.sessionsDir(workspaceRoot);
|
|
1435
|
-
|
|
1393
|
+
mkdirSync(dir, { recursive: true });
|
|
1436
1394
|
const manager = SessionManager2.create(cwd, dir);
|
|
1437
1395
|
if (!resume)
|
|
1438
1396
|
return manager;
|
|
@@ -1446,16 +1404,19 @@ class AkanCodeServices2 {
|
|
|
1446
1404
|
if (!profile.context.skills)
|
|
1447
1405
|
return [];
|
|
1448
1406
|
const workspace = akanCodePaths2.skillsDir(workspaceRoot);
|
|
1449
|
-
return [akanCodePaths2.builtinSkillsDir(),
|
|
1407
|
+
return [akanCodePaths2.builtinSkillsDir(), existsSync7(workspace) ? workspace : undefined].filter((dir) => !!dir);
|
|
1450
1408
|
}
|
|
1451
1409
|
static resourceOptions(options) {
|
|
1452
|
-
const present = (dir) =>
|
|
1410
|
+
const present = (dir) => existsSync7(dir) ? [dir] : [];
|
|
1453
1411
|
return {
|
|
1454
1412
|
noExtensions: true,
|
|
1455
1413
|
noSkills: true,
|
|
1456
1414
|
noPromptTemplates: true,
|
|
1457
1415
|
noThemes: true,
|
|
1458
1416
|
noContextFiles: !options.profile.context.projectFiles,
|
|
1417
|
+
agentsFilesOverride: ({ agentsFiles }) => ({
|
|
1418
|
+
agentsFiles: options.profile.context.projectFiles ? AkanContextFiles.extend(agentsFiles, { workspaceRoot: options.workspaceRoot, cwd: options.cwd }) : agentsFiles
|
|
1419
|
+
}),
|
|
1459
1420
|
appendSystemPrompt: [akanSystemPrompt2(options.profile)],
|
|
1460
1421
|
additionalExtensionPaths: present(akanCodePaths2.extensionsDir(options.workspaceRoot)),
|
|
1461
1422
|
additionalSkillPaths: AkanCodeServices2.#skillPaths(options.profile, options.workspaceRoot),
|
|
@@ -1733,7 +1694,7 @@ class CodeAgentEventMapper2 {
|
|
|
1733
1694
|
}
|
|
1734
1695
|
|
|
1735
1696
|
// pkgs/@akanjs/devkit/codeAgent/agent/CodeAgentGate.ts
|
|
1736
|
-
import
|
|
1697
|
+
import path7 from "path";
|
|
1737
1698
|
var writeTools = new Set(["write", "edit"]);
|
|
1738
1699
|
var commandTools = new Set(["bash"]);
|
|
1739
1700
|
|
|
@@ -1772,9 +1733,9 @@ class CodeAgentGate2 {
|
|
|
1772
1733
|
return `The command names "${hit}", which the profile's deny list covers. Ask the user for the value instead of reading the file.`;
|
|
1773
1734
|
}
|
|
1774
1735
|
#deniedReason(target) {
|
|
1775
|
-
const absolute =
|
|
1776
|
-
const relative =
|
|
1777
|
-
if (relative.startsWith("..") ||
|
|
1736
|
+
const absolute = path7.isAbsolute(target) ? target : path7.resolve(this.#profile.paths.root, target);
|
|
1737
|
+
const relative = path7.relative(this.#profile.paths.root, absolute);
|
|
1738
|
+
if (relative.startsWith("..") || path7.isAbsolute(relative))
|
|
1778
1739
|
return `Path is outside the agent root (${this.#profile.paths.root}).`;
|
|
1779
1740
|
if (this.#deny.some((glob) => glob.match(absolute) || glob.match(relative)))
|
|
1780
1741
|
return "Path is on the profile's deny list (secrets and environment files are never readable).";
|
|
@@ -1864,15 +1825,15 @@ class CodeAgentUi2 {
|
|
|
1864
1825
|
// pkgs/@akanjs/devkit/codeAgent/agent/CodeMailbox.ts
|
|
1865
1826
|
import {
|
|
1866
1827
|
appendFileSync,
|
|
1867
|
-
existsSync as
|
|
1868
|
-
mkdirSync as
|
|
1869
|
-
readdirSync as
|
|
1870
|
-
readFileSync as
|
|
1828
|
+
existsSync as existsSync8,
|
|
1829
|
+
mkdirSync as mkdirSync2,
|
|
1830
|
+
readdirSync as readdirSync3,
|
|
1831
|
+
readFileSync as readFileSync4,
|
|
1871
1832
|
rmSync,
|
|
1872
|
-
statSync as
|
|
1873
|
-
writeFileSync
|
|
1833
|
+
statSync as statSync4,
|
|
1834
|
+
writeFileSync
|
|
1874
1835
|
} from "fs";
|
|
1875
|
-
import
|
|
1836
|
+
import path8 from "path";
|
|
1876
1837
|
|
|
1877
1838
|
class CodeMailbox2 {
|
|
1878
1839
|
static staleMs = 20000;
|
|
@@ -1892,11 +1853,11 @@ class CodeMailbox2 {
|
|
|
1892
1853
|
this.#name = name;
|
|
1893
1854
|
}
|
|
1894
1855
|
get inbox() {
|
|
1895
|
-
return
|
|
1856
|
+
return path8.join(this.#dir, "inbox", `${this.#id}.jsonl`);
|
|
1896
1857
|
}
|
|
1897
1858
|
open(cwd, onMail) {
|
|
1898
|
-
|
|
1899
|
-
|
|
1859
|
+
mkdirSync2(path8.join(this.#dir, "live"), { recursive: true });
|
|
1860
|
+
mkdirSync2(path8.join(this.#dir, "inbox"), { recursive: true });
|
|
1900
1861
|
this.#read = CodeMailbox2.#lines(this.inbox).length;
|
|
1901
1862
|
this.beat(cwd);
|
|
1902
1863
|
this.#beat = setInterval(() => this.beat(cwd), CodeMailbox2.beatMs);
|
|
@@ -1913,7 +1874,7 @@ class CodeMailbox2 {
|
|
|
1913
1874
|
this.#beat = null;
|
|
1914
1875
|
this.#poll = null;
|
|
1915
1876
|
try {
|
|
1916
|
-
rmSync(
|
|
1877
|
+
rmSync(path8.join(this.#dir, "live", `${this.#id}.json`), { force: true });
|
|
1917
1878
|
} catch {}
|
|
1918
1879
|
}
|
|
1919
1880
|
rename(name, cwd) {
|
|
@@ -1923,15 +1884,15 @@ class CodeMailbox2 {
|
|
|
1923
1884
|
beat(cwd) {
|
|
1924
1885
|
const peer = { id: this.#id, name: this.#name, cwd, pid: process.pid, at: Date.now() };
|
|
1925
1886
|
try {
|
|
1926
|
-
|
|
1887
|
+
writeFileSync(path8.join(this.#dir, "live", `${this.#id}.json`), JSON.stringify(peer));
|
|
1927
1888
|
} catch {}
|
|
1928
1889
|
}
|
|
1929
1890
|
peers() {
|
|
1930
|
-
const dir =
|
|
1931
|
-
if (!
|
|
1891
|
+
const dir = path8.join(this.#dir, "live");
|
|
1892
|
+
if (!existsSync8(dir))
|
|
1932
1893
|
return [];
|
|
1933
1894
|
const now = Date.now();
|
|
1934
|
-
return
|
|
1895
|
+
return readdirSync3(dir).filter((entry) => entry.endsWith(".json")).map((entry) => CodeMailbox2.#peer(path8.join(dir, entry))).filter((peer) => !!peer && peer.id !== this.#id && now - peer.at < CodeMailbox2.staleMs).sort((left, right) => right.at - left.at);
|
|
1935
1896
|
}
|
|
1936
1897
|
find(target) {
|
|
1937
1898
|
const needle = target.trim().toLowerCase();
|
|
@@ -1949,8 +1910,8 @@ class CodeMailbox2 {
|
|
|
1949
1910
|
throw new Error(`Too many messages: ${CodeMailbox2.sendsPerMinute} a minute is the ceiling.`);
|
|
1950
1911
|
this.#sent.push(now);
|
|
1951
1912
|
const mail = { at: now, from: this.#id, fromName: this.#name, text };
|
|
1952
|
-
|
|
1953
|
-
appendFileSync(
|
|
1913
|
+
mkdirSync2(path8.join(this.#dir, "inbox"), { recursive: true });
|
|
1914
|
+
appendFileSync(path8.join(this.#dir, "inbox", `${to}.jsonl`), `${JSON.stringify(mail)}
|
|
1954
1915
|
`);
|
|
1955
1916
|
}
|
|
1956
1917
|
#drain() {
|
|
@@ -1963,15 +1924,15 @@ class CodeMailbox2 {
|
|
|
1963
1924
|
}
|
|
1964
1925
|
static #peer(file) {
|
|
1965
1926
|
try {
|
|
1966
|
-
const peer = JSON.parse(
|
|
1967
|
-
return typeof peer.id === "string" ? { ...peer, at: peer.at ||
|
|
1927
|
+
const peer = JSON.parse(readFileSync4(file, "utf8"));
|
|
1928
|
+
return typeof peer.id === "string" ? { ...peer, at: peer.at || statSync4(file).mtimeMs } : undefined;
|
|
1968
1929
|
} catch {
|
|
1969
1930
|
return;
|
|
1970
1931
|
}
|
|
1971
1932
|
}
|
|
1972
1933
|
static #lines(file) {
|
|
1973
1934
|
try {
|
|
1974
|
-
return
|
|
1935
|
+
return readFileSync4(file, "utf8").split(`
|
|
1975
1936
|
`).filter((line) => !!line.trim());
|
|
1976
1937
|
} catch {
|
|
1977
1938
|
return [];
|
|
@@ -1988,15 +1949,15 @@ class CodeMailbox2 {
|
|
|
1988
1949
|
|
|
1989
1950
|
// pkgs/@akanjs/devkit/codeAgent/agent/CodeSessionFork.ts
|
|
1990
1951
|
import { randomBytes } from "crypto";
|
|
1991
|
-
import { readFileSync as
|
|
1992
|
-
import
|
|
1952
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
1953
|
+
import path9 from "path";
|
|
1993
1954
|
import { codeAgentSessionName } from "akanjs/common";
|
|
1994
1955
|
class CodeSessionFork2 {
|
|
1995
1956
|
static fork(dir, id, name) {
|
|
1996
1957
|
const source = CodeSessionIndex2.fileOf(dir, id);
|
|
1997
1958
|
if (!source)
|
|
1998
1959
|
throw new Error(`No stored session ${id} in ${dir}`);
|
|
1999
|
-
const lines =
|
|
1960
|
+
const lines = readFileSync5(source, "utf8").split(`
|
|
2000
1961
|
`).filter((line) => !!line.trim());
|
|
2001
1962
|
if (!lines.length)
|
|
2002
1963
|
throw new Error(`Session ${id} has nothing in it to fork`);
|
|
@@ -2009,8 +1970,8 @@ class CodeSessionFork2 {
|
|
|
2009
1970
|
first.id = forked;
|
|
2010
1971
|
first.timestamp = at.toISOString();
|
|
2011
1972
|
records.push(CodeSessionFork2.#named(records, name ?? CodeSessionFork2.#nameOf(records), at));
|
|
2012
|
-
const file =
|
|
2013
|
-
|
|
1973
|
+
const file = path9.join(dir, `${at.toISOString().replace(/[:.]/g, "-")}_${forked}.jsonl`);
|
|
1974
|
+
writeFileSync2(file, `${records.map((record) => JSON.stringify(record)).join(`
|
|
2014
1975
|
`)}
|
|
2015
1976
|
`);
|
|
2016
1977
|
return { id: forked, file };
|
|
@@ -2052,6 +2013,8 @@ class CodeAgent2 {
|
|
|
2052
2013
|
#disposed = false;
|
|
2053
2014
|
#sessionDir;
|
|
2054
2015
|
#mailbox;
|
|
2016
|
+
#mcp = [];
|
|
2017
|
+
#workspaceRoot = "";
|
|
2055
2018
|
#replay = [];
|
|
2056
2019
|
#replayFrom = 0;
|
|
2057
2020
|
#lastContextTokens;
|
|
@@ -2064,9 +2027,8 @@ class CodeAgent2 {
|
|
|
2064
2027
|
const cwd = options.cwd ?? workspaceRoot;
|
|
2065
2028
|
const agent = new CodeAgent2(options.profile);
|
|
2066
2029
|
const settingsManager = AkanCodeServices2.settings();
|
|
2067
|
-
const
|
|
2068
|
-
const
|
|
2069
|
-
const model = await akanCodeModel2(modelRegistry, options.model);
|
|
2030
|
+
const modelRuntime = await AkanCodeServices2.runtime(workspaceRoot);
|
|
2031
|
+
const model = await akanCodeModel2(modelRuntime, options.model);
|
|
2070
2032
|
const compaction = DEFAULT_COMPACTION_SETTINGS;
|
|
2071
2033
|
const modelWarnings = akanCodeModelWarnings2(model, compaction.reserveTokens + compaction.keepRecentTokens);
|
|
2072
2034
|
const akan = await AkanCodePlugins2.build({
|
|
@@ -2078,7 +2040,8 @@ class CodeAgent2 {
|
|
|
2078
2040
|
depth: options.depth ?? 0,
|
|
2079
2041
|
currentSessionId: () => agent.sessionId,
|
|
2080
2042
|
mailbox: () => agent.#mailbox,
|
|
2081
|
-
onNotice: (message) => agent.#emit({ type: "notice", level: "warning", message })
|
|
2043
|
+
onNotice: (message) => agent.#emit({ type: "notice", level: "warning", message }),
|
|
2044
|
+
onAgents: (agents) => agent.#emit({ type: "subagent", agents })
|
|
2082
2045
|
});
|
|
2083
2046
|
const resourceLoader = new DefaultResourceLoader({
|
|
2084
2047
|
cwd,
|
|
@@ -2095,8 +2058,7 @@ class CodeAgent2 {
|
|
|
2095
2058
|
const { session } = await createAgentSession({
|
|
2096
2059
|
cwd,
|
|
2097
2060
|
agentDir: akanCodePaths2.globalDir(),
|
|
2098
|
-
|
|
2099
|
-
modelRegistry,
|
|
2061
|
+
modelRuntime,
|
|
2100
2062
|
settingsManager,
|
|
2101
2063
|
resourceLoader,
|
|
2102
2064
|
model,
|
|
@@ -2106,6 +2068,8 @@ class CodeAgent2 {
|
|
|
2106
2068
|
customTools: options.customTools
|
|
2107
2069
|
});
|
|
2108
2070
|
agent.#disposePlugins = akan.dispose;
|
|
2071
|
+
agent.#mcp = akan.mcp;
|
|
2072
|
+
agent.#workspaceRoot = workspaceRoot;
|
|
2109
2073
|
if (options.profile.session.store === "file")
|
|
2110
2074
|
agent.#sessionDir = akanCodePaths2.sessionsDir(workspaceRoot);
|
|
2111
2075
|
await agent.#attach(session, options.mode ?? "print");
|
|
@@ -2125,6 +2089,12 @@ class CodeAgent2 {
|
|
|
2125
2089
|
sessions() {
|
|
2126
2090
|
return this.#sessionDir ? CodeSessionIndex2.list(this.#sessionDir) : [];
|
|
2127
2091
|
}
|
|
2092
|
+
get workspaceRoot() {
|
|
2093
|
+
return this.#workspaceRoot;
|
|
2094
|
+
}
|
|
2095
|
+
mcpServers() {
|
|
2096
|
+
return this.#mcp;
|
|
2097
|
+
}
|
|
2128
2098
|
peers() {
|
|
2129
2099
|
return this.#mailbox?.peers() ?? [];
|
|
2130
2100
|
}
|
|
@@ -2281,7 +2251,7 @@ Continue the task.`);
|
|
|
2281
2251
|
}
|
|
2282
2252
|
async setModel(ref) {
|
|
2283
2253
|
const session = this.#require();
|
|
2284
|
-
const model = await akanCodeModel2(session.
|
|
2254
|
+
const model = await akanCodeModel2(session.modelRuntime, ref);
|
|
2285
2255
|
if (!model)
|
|
2286
2256
|
throw new Error(`Unknown model: ${ref.provider}/${ref.id}`);
|
|
2287
2257
|
await session.setModel(model);
|
|
@@ -2431,4 +2401,4 @@ Continue the task.`);
|
|
|
2431
2401
|
}
|
|
2432
2402
|
}
|
|
2433
2403
|
|
|
2434
|
-
export { AkanEditScope2, DevLogFeedback2, PreviewChrome2, PreviewView2, PreviewFeedback2, TurnFeedback2, AkanCli2, AkanVerifier2, VerifyFeedback2, AkanToolPack2, MailToolPack2,
|
|
2404
|
+
export { AkanEditScope2, DevLogFeedback2, PreviewChrome2, PreviewView2, PreviewFeedback2, TurnFeedback2, AkanCli2, AkanVerifier2, VerifyFeedback2, AkanToolPack2, MailToolPack2, McpClient2, McpToolPack2, SessionToolPack2, WebToolPack2, AkanCodePlugins2, AkanEnvKeys2, akanSystemPrompt2, CodeSessionIndex2, AkanCodeServices2, CodeAgentAsks2, CodeAgentEventMapper2, CodeAgentGate2, CodeAgentUi2, CodeMailbox2, CodeSessionFork2, CodeAgent2 };
|