@akanjs/cli 3.0.0-beta.19 → 3.0.0-beta.20
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-6cm97kay.js → CodeAgent-awv258wb.js} +2 -2
- package/{CodeTui-za4jsm41.js → CodeTui-1nqh35ez.js} +20 -22
- package/TunnelShare-scf4e4pd.js +9 -0
- package/{agent.command-e0wpbbyg.js → agent.command-1s9ag7sb.js} +8 -9
- package/akanCode.js +4 -4
- package/{application.command-8wyxqc8q.js → application.command-49hwy6va.js} +25 -56
- package/{applicationBuildRunner-n9gzaxd0.js → applicationBuildRunner-ybyp97pv.js} +33 -59
- package/{applicationReleasePackager-vpggfqgq.js → applicationReleasePackager-esnrphw8.js} +40 -60
- package/buildBatch.proc.js +19 -24
- package/{capacitorApp-q3z0qht0.js → capacitorApp-1synz4en.js} +3 -4
- package/{cloud.command-4zwa5dsx.js → cloud.command-d7rqtzt9.js} +16 -26
- package/cloud.script-bkbpcr96.js +19 -0
- package/{code.command-468c9d7s.js → code.command-nn48xzej.js} +22 -37
- package/context.command-s3mcmvpa.js +48 -0
- package/context.runner-k99nb5pk.js +21 -0
- package/{dependencyScanner-0z2h2tks.js → dependencyScanner-ye2e6pdz.js} +2 -2
- package/{devTui-ffjsarqa.js → devTui-q7k7bakd.js} +5 -9
- package/fileSys-5ngz93ga.js +9 -0
- package/{guideline.command-vhw13pqr.js → guideline.command-sct4qnt5.js} +4 -5
- package/guidelines/conventions/conventions.instruction.md +5 -1
- package/guidelines/mcpRule/mcpRule.instruction.md +7 -5
- package/incrementalBuilder.proc.js +30 -48
- package/{index-s5rhm04y.js → index-0bq14vr1.js} +1 -1
- package/{index-10dkrrww.js → index-13ffe9wp.js} +4 -4
- package/{index-srmay5jw.js → index-22d57v4c.js} +84 -67
- package/{index-53176s7j.js → index-31yr441d.js} +10 -17
- package/index-3hx1z96c.js +87 -0
- package/{index-4m929vvn.js → index-3sq321ak.js} +10 -18
- package/{index-bhtmj233.js → index-3t7g9e4r.js} +41 -78
- package/{index-q0y2jq9j.js → index-5b6tavv3.js} +6 -3
- package/{index-47pj3aee.js → index-5e0n4hqx.js} +11 -12
- package/{index-7ep8qtvp.js → index-5pc1qrbv.js} +5 -8
- package/{index-esk82rvk.js → index-8mna0947.js} +34 -71
- package/{index-sq2dzkzm.js → index-8sf7wmdr.js} +6 -6
- package/{index-crmeqnmf.js → index-9d9bgcx4.js} +283 -722
- package/{index-bwf965h6.js → index-ahemdr5n.js} +6 -6
- package/{index-ab0c38ea.js → index-as7xmyz8.js} +20 -20
- package/{index-bc88j1ry.js → index-axzjaqve.js} +94 -142
- package/{index-3d9y066c.js → index-bjwxs904.js} +9 -8
- package/{index-667w0yah.js → index-c6eggbee.js} +2 -5
- package/{index-a1w6934z.js → index-ddxvdd1p.js} +169 -305
- package/{index-92zztqy1.js → index-dy0jx9ay.js} +2 -17
- package/{index-22xtgmhn.js → index-dzf3r49a.js} +1 -1
- package/{index-89hy31kf.js → index-fgq75haa.js} +172 -287
- package/{index-by5gpp8x.js → index-hj6w4ka1.js} +2 -1
- package/{index-hwkygn9s.js → index-khpfpcsd.js} +302 -33
- package/{index-vqx8bdxz.js → index-mxav6j3c.js} +78 -231
- package/{index-2446k7b4.js → index-myhc3c1j.js} +512 -588
- package/{index-3jrp517k.js → index-nv5976x3.js} +45 -128
- package/{index-zqgj2rt2.js → index-przybvy5.js} +69 -147
- package/{index-n3cv0tm4.js → index-smme4r47.js} +1 -1
- package/{index-qdgzsnhg.js → index-w2zdcw3k.js} +110 -231
- package/{index-14zrtgfa.js → index-wa5jbxj1.js} +6 -39
- package/{index-bftkz6cp.js → index-ww4z397j.js} +198 -555
- package/{index-kwaq3n9n.js → index-xqjwd384.js} +4 -7
- package/{index-txr7dj2g.js → index-xqpzbab5.js} +106 -240
- package/{index-e4v6vhxq.js → index-xsjh6nzh.js} +178 -165
- package/{index-18zybgkc.js → index-ygn77a5w.js} +47 -99
- package/{index-9d6nvkz2.js → index-ztp3e73t.js} +79 -35
- package/index.js +23 -24
- package/{library.command-cqr175dy.js → library.command-1gx04jgn.js} +4 -5
- package/{localRegistry.command-49z55qqz.js → localRegistry.command-zndxj1q6.js} +21 -42
- package/{module.command-9p8mm3b0.js → module.command-3waddk95.js} +6 -7
- package/{package.command-wxyz909t.js → package.command-zrc7br1y.js} +5 -6
- package/package.json +2 -2
- package/{page.command-gsrsfqqs.js → page.command-vpjgardh.js} +4 -5
- package/{primitive.command-ns1mptje.js → primitive.command-sz84tk4t.js} +9 -20
- package/{prompter-1f8d9pcc.js → prompter-ptaa3nk0.js} +2 -2
- package/{quality.command-e76k2q9k.js → quality.command-g869hafs.js} +129 -363
- package/{recipeScanner-fpagtgc1.js → recipeScanner-4b69ybe0.js} +1 -1
- package/{repair.command-pkrsm3cw.js → repair.command-chsnjvvv.js} +11 -35
- package/{scalar.command-0cpt3fc8.js → scalar.command-2v21newx.js} +5 -6
- package/skills/akan-code/SKILL.md +12 -4
- package/{subspace.command-fktpwp0g.js → subspace.command-ckcbwfp1.js} +39 -58
- package/templates/appSample/srvkit/{AuthGuard.ts → guards.ts} +3 -3
- package/templates/appSample/srvkit/{SessionInternalArg.ts → internalArgs.ts} +3 -3
- package/templates/client.ts +7 -30
- package/templates/lib/__lib/lib.dictionary.ts +0 -2
- package/templates/lib/__lib/lib.document.ts +0 -2
- package/templates/lib/sig.ts +8 -30
- package/templates/server.ts +0 -2
- package/{tunnel.command-d5jy9gk8.js → tunnel.command-kd2yr4fx.js} +5 -6
- package/{typeChecker-3xgrzc2v.js → typeChecker-px49mezc.js} +1 -1
- package/typecheck.proc.js +1 -1
- package/workflow.command-44252cqv.js +79 -0
- package/{workspace.command-gv84eh1p.js → workspace.command-fqcztt5p.js} +72 -107
- package/TunnelShare-2j6s511d.js +0 -9
- package/cloud.script-fwx3vb34.js +0 -20
- package/context.command-dsnw0jby.js +0 -80
- package/context.runner-rs4rj15d.js +0 -22
- package/devTuiView-1q1mdgrv.js +0 -9
- package/getDirname-dr3jz1xg.js +0 -7
- package/index-6wwzs1bc.js +0 -7
- package/workflow.command-6tkcysmx.js +0 -105
|
@@ -7,24 +7,25 @@ import {
|
|
|
7
7
|
isScannedRootEntry,
|
|
8
8
|
AppExecutor,
|
|
9
9
|
LibExecutor
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-9d9bgcx4.js";
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
} from "./index-
|
|
12
|
+
FileSys2
|
|
13
|
+
} from "./index-5b6tavv3.js";
|
|
14
14
|
import {
|
|
15
15
|
collectRecipeSources2,
|
|
16
16
|
scanRecipes2,
|
|
17
17
|
findInlineRecipeDuplicates2
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-hj6w4ka1.js";
|
|
19
19
|
import {
|
|
20
|
+
workflowPathsForPlan,
|
|
20
21
|
workflowRunArtifactPath,
|
|
21
22
|
workflowSyncDir
|
|
22
|
-
} from "./index-
|
|
23
|
+
} from "./index-myhc3c1j.js";
|
|
23
24
|
|
|
24
25
|
// pkgs/@akanjs/devkit/akanContext.ts
|
|
25
26
|
import { readdir } from "fs/promises";
|
|
26
27
|
import path from "path";
|
|
27
|
-
import { capitalize } from "akanjs/common";
|
|
28
|
+
import { capitalize, isRecord } from "akanjs/common";
|
|
28
29
|
var guidelineResourceUri = (name) => `akan://guidelines/${name}`;
|
|
29
30
|
var staticResourceList = [
|
|
30
31
|
{ uri: "akan://docs/framework", name: "Akan framework guide", mimeType: "text/markdown" },
|
|
@@ -52,16 +53,13 @@ var akanMcpInstallConfigPaths = {
|
|
|
52
53
|
var cursorWorkspaceFolder = "$" + "{workspaceFolder}";
|
|
53
54
|
var claudeProjectDir = "$CLAUDE_PROJECT_DIR";
|
|
54
55
|
var akanMcpCommand = (mode, { cd } = {}) => cd ? `cd "${cd}" && akan mcp --mode ${mode}` : `akan mcp --mode ${mode}`;
|
|
55
|
-
var
|
|
56
|
+
var bashMcpServer = (mode, cd) => ({
|
|
56
57
|
type: "stdio",
|
|
57
58
|
command: "bash",
|
|
58
|
-
args: ["-lc", akanMcpCommand(mode, { cd
|
|
59
|
-
});
|
|
60
|
-
var createAkanClaudeMcpServer = (mode = "readonly") => ({
|
|
61
|
-
type: "stdio",
|
|
62
|
-
command: "bash",
|
|
63
|
-
args: ["-lc", akanMcpCommand(mode, { cd: claudeProjectDir })]
|
|
59
|
+
args: ["-lc", akanMcpCommand(mode, { cd })]
|
|
64
60
|
});
|
|
61
|
+
var createAkanCursorMcpServer = (mode = "readonly") => bashMcpServer(mode, cursorWorkspaceFolder);
|
|
62
|
+
var createAkanClaudeMcpServer = (mode = "readonly") => bashMcpServer(mode, claudeProjectDir);
|
|
65
63
|
var createAkanMcpServer = (target, mode = "readonly") => target === "cursor" ? createAkanCursorMcpServer(mode) : createAkanClaudeMcpServer(mode);
|
|
66
64
|
var akanCursorMcpServer = createAkanCursorMcpServer();
|
|
67
65
|
var codexMcpServerTableHeader = "[mcp_servers.akan]";
|
|
@@ -164,41 +162,13 @@ var moduleShapeFiles = (module) => {
|
|
|
164
162
|
];
|
|
165
163
|
};
|
|
166
164
|
var constantFieldNames = (content) => [...content.matchAll(/\b([A-Za-z_$][\w$]*)\s*:\s*field\(/g)].map((match) => match[1]).filter(Boolean);
|
|
167
|
-
var safeReadDir = async (dirPath) => {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
};
|
|
174
|
-
var safeReadText = async (filePath) => {
|
|
175
|
-
try {
|
|
176
|
-
return await FileSys.readText(filePath);
|
|
177
|
-
} catch {
|
|
178
|
-
return null;
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
var safeReadJson = async (filePath) => {
|
|
182
|
-
try {
|
|
183
|
-
return await FileSys.readJson(filePath);
|
|
184
|
-
} catch {
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
var isWorkflowPlan = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && value.mode === "plan";
|
|
189
|
-
var isWorkflowApplyReport = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && (value.mode === "apply" || value.mode === "dry-run");
|
|
165
|
+
var safeReadDir = async (dirPath) => (await readdir(dirPath, { withFileTypes: true }).catch(() => [])).sort((a, b) => a.name.localeCompare(b.name));
|
|
166
|
+
var safeReadText = (filePath) => FileSys2.readText(filePath).catch(() => null);
|
|
167
|
+
var safeReadJson = (filePath) => FileSys2.readJson(filePath).catch(() => null);
|
|
168
|
+
var isWorkflowPlan = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && value.mode === "plan" && ("inputs" in value) && isRecord(value.inputs) && ("predictedChanges" in value) && Array.isArray(value.predictedChanges) && value.predictedChanges.every((change) => isRecord(change) && typeof change.target === "string");
|
|
169
|
+
var isPathList = (value) => Array.isArray(value) && value.every((file) => isRecord(file) && typeof file.path === "string");
|
|
170
|
+
var isWorkflowApplyReport = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && (value.mode === "apply" || value.mode === "dry-run") && ("changedFiles" in value) && isPathList(value.changedFiles) && ("generatedFiles" in value) && isPathList(value.generatedFiles) && ("plan" in value) && isWorkflowPlan(value.plan);
|
|
190
171
|
var isWorkflowRunArtifact = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1;
|
|
191
|
-
var planInputString = (plan, key) => {
|
|
192
|
-
const value = plan.inputs[key];
|
|
193
|
-
return typeof value === "string" ? value : "";
|
|
194
|
-
};
|
|
195
|
-
var expandWorkflowTarget = (target, plan) => {
|
|
196
|
-
const app = planInputString(plan, "app");
|
|
197
|
-
const module = planInputString(plan, "module");
|
|
198
|
-
const moduleClass = module ? capitalize(module) : "<Module>";
|
|
199
|
-
return target.replace(/^\*\//, app ? `apps/${app}/` : "").replaceAll("<module>", module || "<module>").replaceAll("<Module>", moduleClass);
|
|
200
|
-
};
|
|
201
|
-
var workflowPathsForPlan = (plan) => plan.predictedChanges.map((change) => expandWorkflowTarget(change.target, plan));
|
|
202
172
|
var workflowPathsForArtifact = (artifact) => {
|
|
203
173
|
if (isWorkflowPlan(artifact))
|
|
204
174
|
return workflowPathsForPlan(artifact);
|
|
@@ -209,7 +179,7 @@ var workflowPathsForArtifact = (artifact) => {
|
|
|
209
179
|
...workflowPathsForPlan(artifact.plan)
|
|
210
180
|
];
|
|
211
181
|
}
|
|
212
|
-
if ("mode" in artifact && artifact.mode === "validate" && artifact.plan)
|
|
182
|
+
if ("mode" in artifact && artifact.mode === "validate" && isWorkflowPlan(artifact.plan))
|
|
213
183
|
return workflowPathsForPlan(artifact.plan);
|
|
214
184
|
return [];
|
|
215
185
|
};
|
|
@@ -310,13 +280,13 @@ var getSysModules = async (workspace, sys, {
|
|
|
310
280
|
const serviceName = entry.name.replace(/^_+/, "");
|
|
311
281
|
if (moduleFilter && moduleFilter !== serviceName && moduleFilter !== entry.name)
|
|
312
282
|
continue;
|
|
313
|
-
if (!await
|
|
283
|
+
if (!await FileSys2.fileExists(path.join(libPath, entry.name, `${serviceName}.service.ts`)))
|
|
314
284
|
continue;
|
|
315
285
|
modules.push(await createModuleContext(workspace, sys, "service", entry.name, serviceName, includeAbstractContent));
|
|
316
286
|
} else {
|
|
317
287
|
if (moduleFilter && moduleFilter !== entry.name)
|
|
318
288
|
continue;
|
|
319
|
-
if (!await
|
|
289
|
+
if (!await FileSys2.fileExists(path.join(libPath, entry.name, `${entry.name}.constant.ts`)))
|
|
320
290
|
continue;
|
|
321
291
|
modules.push(await createModuleContext(workspace, sys, "domain", entry.name, entry.name, includeAbstractContent));
|
|
322
292
|
}
|
|
@@ -327,7 +297,7 @@ var getSysModules = async (workspace, sys, {
|
|
|
327
297
|
continue;
|
|
328
298
|
if (moduleFilter && moduleFilter !== entry.name)
|
|
329
299
|
continue;
|
|
330
|
-
if (!await
|
|
300
|
+
if (!await FileSys2.fileExists(path.join(scalarRoot, entry.name, `${entry.name}.constant.ts`)))
|
|
331
301
|
continue;
|
|
332
302
|
modules.push(await createModuleContext(workspace, sys, "scalar", entry.name, entry.name, includeAbstractContent));
|
|
333
303
|
}
|
|
@@ -339,7 +309,7 @@ var getSysContext = async (workspace, type, name, options) => {
|
|
|
339
309
|
type,
|
|
340
310
|
name,
|
|
341
311
|
path: `${type}s/${name}`,
|
|
342
|
-
hasConfig: await
|
|
312
|
+
hasConfig: await FileSys2.fileExists(path.join(sys.cwdPath, "akan.config.ts")),
|
|
343
313
|
modules: await getSysModules(workspace, sys, {
|
|
344
314
|
includeAbstractContent: options.includeAbstractContent,
|
|
345
315
|
module: options.module
|
|
@@ -411,62 +381,46 @@ class AkanContextAnalyzer {
|
|
|
411
381
|
repairAction("generated", "akan repair generated --app <app-or-lib>", "Refresh generated Akan files.", true),
|
|
412
382
|
repairAction("format", "akan repair format --target <app-or-lib-or-pkg>", "Run the formatter/linter repair path.", true)
|
|
413
383
|
];
|
|
384
|
+
const report = (diagnostic, action) => {
|
|
385
|
+
diagnostics.push({ ...diagnostic, repairActions: [action] });
|
|
386
|
+
repairActions.push(action);
|
|
387
|
+
};
|
|
414
388
|
for (const sys of [...context.apps, ...context.libs]) {
|
|
415
389
|
const sysPath = path.join(workspace.workspaceRoot, sys.path);
|
|
416
390
|
for (const entry of await safeReadDir(sysPath)) {
|
|
417
391
|
if (!isScannedRootEntry(sys.type, entry.name))
|
|
418
392
|
continue;
|
|
419
393
|
const allowed = entry.isDirectory() ? rootAllowedDirs[sys.type].has(entry.name) : rootAllowedFiles[sys.type].has(entry.name);
|
|
420
|
-
if (!allowed)
|
|
421
|
-
|
|
422
|
-
diagnostics.push({
|
|
394
|
+
if (!allowed)
|
|
395
|
+
report({
|
|
423
396
|
severity: "error",
|
|
424
397
|
code: `${sys.type}-root-unknown-entry`,
|
|
425
398
|
path: `${sys.path}/${entry.name}`,
|
|
426
|
-
message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in ${sys.type} root: ${sys.path}/${entry.name}
|
|
427
|
-
|
|
428
|
-
});
|
|
429
|
-
repairActions.push(action);
|
|
430
|
-
}
|
|
399
|
+
message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in ${sys.type} root: ${sys.path}/${entry.name}`
|
|
400
|
+
}, repairAction("module-shape", `akan repair module-shape --app ${sys.name}`, `Review ${sys.type} root shape and remove or move the unknown entry.`, false));
|
|
431
401
|
}
|
|
432
402
|
}
|
|
433
403
|
const agentDrift = await AkanContextAnalyzer.#agentGuideDrift(workspace);
|
|
434
|
-
if (agentDrift)
|
|
435
|
-
|
|
436
|
-
diagnostics.push({
|
|
437
|
-
severity: "warning",
|
|
438
|
-
code: agentDrift.code,
|
|
439
|
-
path: "AGENTS.md",
|
|
440
|
-
message: agentDrift.message,
|
|
441
|
-
repairActions: [action]
|
|
442
|
-
});
|
|
443
|
-
repairActions.push(action);
|
|
444
|
-
}
|
|
404
|
+
if (agentDrift)
|
|
405
|
+
report({ severity: "warning", code: agentDrift.code, path: "AGENTS.md", message: agentDrift.message }, repairAction("generated", "akan agent install agents-md", agentDrift.hint, true));
|
|
445
406
|
for (const sys of [...context.apps, ...context.libs]) {
|
|
446
407
|
for (const module of sys.modules) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
408
|
+
const moduleShapeCommand = `akan repair module-shape --app ${sys.name} --module ${module.name}`;
|
|
409
|
+
if (!module.abstract.exists)
|
|
410
|
+
report({
|
|
450
411
|
severity: strict ? "error" : "warning",
|
|
451
412
|
code: "module-abstract-missing",
|
|
452
413
|
path: module.abstract.path,
|
|
453
|
-
message: `${capitalize(module.kind)} module ${sys.name}:${module.name} should include ${module.abstract.path}
|
|
454
|
-
|
|
455
|
-
});
|
|
456
|
-
repairActions.push(action);
|
|
457
|
-
}
|
|
414
|
+
message: `${capitalize(module.kind)} module ${sys.name}:${module.name} should include ${module.abstract.path}`
|
|
415
|
+
}, repairAction("module-shape", moduleShapeCommand, "Create the missing module abstract or inspect required source files.", false));
|
|
458
416
|
const missingFiles = moduleShapeFiles(module).filter((filename) => !module.files.includes(filename));
|
|
459
|
-
if (missingFiles.length)
|
|
460
|
-
|
|
461
|
-
diagnostics.push({
|
|
417
|
+
if (missingFiles.length)
|
|
418
|
+
report({
|
|
462
419
|
severity: "error",
|
|
463
420
|
code: "module-shape-invalid",
|
|
464
421
|
path: module.path,
|
|
465
|
-
message: `${capitalize(module.kind)} module ${sys.name}:${module.name} is missing required files: ${missingFiles.join(", ")}
|
|
466
|
-
|
|
467
|
-
});
|
|
468
|
-
repairActions.push(action);
|
|
469
|
-
}
|
|
422
|
+
message: `${capitalize(module.kind)} module ${sys.name}:${module.name} is missing required files: ${missingFiles.join(", ")}`
|
|
423
|
+
}, repairAction("module-shape", moduleShapeCommand, "Review missing required module source files.", false));
|
|
470
424
|
if (module.kind !== "service" && module.files.includes(`${module.name}.dictionary.ts`)) {
|
|
471
425
|
const constantPath = path.join(workspace.workspaceRoot, module.path, `${module.name}.constant.ts`);
|
|
472
426
|
const dictionaryPath = path.join(workspace.workspaceRoot, module.path, `${module.name}.dictionary.ts`);
|
|
@@ -478,15 +432,12 @@ class AkanContextAnalyzer {
|
|
|
478
432
|
for (const fieldName of constantFieldNames(constantContent)) {
|
|
479
433
|
if (new RegExp(`\\b${fieldName}\\s*:`).test(dictionaryContent))
|
|
480
434
|
continue;
|
|
481
|
-
|
|
482
|
-
diagnostics.push({
|
|
435
|
+
report({
|
|
483
436
|
severity: "warning",
|
|
484
437
|
code: "dictionary-label-missing",
|
|
485
438
|
path: `${module.path}/${module.name}.dictionary.ts`,
|
|
486
|
-
message: `Dictionary labels for ${sys.name}:${module.name}.${fieldName} were not found
|
|
487
|
-
|
|
488
|
-
});
|
|
489
|
-
repairActions.push(action);
|
|
439
|
+
message: `Dictionary labels for ${sys.name}:${module.name}.${fieldName} were not found.`
|
|
440
|
+
}, repairAction("dictionary", `akan repair dictionary --app ${sys.name} --module ${module.name}`, "Add missing dictionary labels for source constant fields.", false));
|
|
490
441
|
}
|
|
491
442
|
}
|
|
492
443
|
}
|
|
@@ -554,19 +505,16 @@ class AkanContextAnalyzer {
|
|
|
554
505
|
const pushIndexDiagnostic = (indexPath, missing, stale, repairCommand) => {
|
|
555
506
|
if (missing.length === 0 && stale.length === 0)
|
|
556
507
|
return;
|
|
557
|
-
const action = repairAction("generated", repairCommand, "Regenerate the recipe index from the scanned recipes.", true);
|
|
558
508
|
const parts = [
|
|
559
509
|
missing.length > 0 ? `${missing.length} declared but unlisted (${missing.slice(0, 5).join(", ")})` : "",
|
|
560
510
|
stale.length > 0 ? `${stale.length} listed but gone (${stale.slice(0, 5).join(", ")})` : ""
|
|
561
511
|
].filter(Boolean);
|
|
562
|
-
|
|
512
|
+
report({
|
|
563
513
|
severity: "error",
|
|
564
514
|
code: "recipe-index-stale",
|
|
565
515
|
path: indexPath,
|
|
566
|
-
message: `${indexPath} recipe index is out of date \u2014 ${parts.join("; ")}. Agents read this list as authoritative
|
|
567
|
-
|
|
568
|
-
});
|
|
569
|
-
repairActions.push(action);
|
|
516
|
+
message: `${indexPath} recipe index is out of date \u2014 ${parts.join("; ")}. Agents read this list as authoritative.`
|
|
517
|
+
}, repairAction("generated", repairCommand, "Regenerate the recipe index from the scanned recipes.", true));
|
|
570
518
|
};
|
|
571
519
|
const frameworkDeclared = declaredByImport.get("akanjs/ui") ?? new Set;
|
|
572
520
|
if (frameworkDeclared.size > 0) {
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
ConfigLock
|
|
4
|
+
} from "./index-3hx1z96c.js";
|
|
5
|
+
|
|
2
6
|
// pkgs/@akanjs/devkit/codeAgent/agent/SubagentPool.ts
|
|
3
7
|
import { codeAgentReadOnlyBuiltins } from "akanjs/common";
|
|
4
8
|
import { Type } from "typebox";
|
|
@@ -19,11 +23,11 @@ class SubagentPool2 {
|
|
|
19
23
|
static defaultKind = "explore";
|
|
20
24
|
#options;
|
|
21
25
|
#children = new Map;
|
|
22
|
-
#
|
|
23
|
-
#spent = 0;
|
|
26
|
+
#spend;
|
|
24
27
|
#ticker = null;
|
|
25
28
|
constructor(options) {
|
|
26
29
|
this.#options = options;
|
|
30
|
+
this.#spend = options.spend ?? { tokens: 0, running: 0 };
|
|
27
31
|
}
|
|
28
32
|
static extensionFor(options) {
|
|
29
33
|
if (!options.parent.tools.subagent)
|
|
@@ -52,7 +56,7 @@ class SubagentPool2 {
|
|
|
52
56
|
const refusal = this.#refuse();
|
|
53
57
|
if (refusal)
|
|
54
58
|
return { content: [{ type: "text", text: refusal }], details: undefined, isError: true };
|
|
55
|
-
this.#running += 1;
|
|
59
|
+
this.#spend.running += 1;
|
|
56
60
|
this.#children.set(id, { kind, description: params.description, startedAt: Date.now() });
|
|
57
61
|
this.#report();
|
|
58
62
|
this.#options.onNotice?.(`${kind} sub-agent \xB7 ${params.description}`);
|
|
@@ -60,7 +64,7 @@ class SubagentPool2 {
|
|
|
60
64
|
const text = await this.#run(id, kind, params.prompt, signal);
|
|
61
65
|
return { content: [{ type: "text", text }], details: undefined };
|
|
62
66
|
} finally {
|
|
63
|
-
this.#running -= 1;
|
|
67
|
+
this.#spend.running -= 1;
|
|
64
68
|
this.#children.delete(id);
|
|
65
69
|
this.#report();
|
|
66
70
|
}
|
|
@@ -71,9 +75,9 @@ class SubagentPool2 {
|
|
|
71
75
|
const budget = this.#options.parent.tools.subagent;
|
|
72
76
|
if (!budget)
|
|
73
77
|
return "Sub-agents are disabled by this profile.";
|
|
74
|
-
if (this.#running >= budget.maxConcurrent)
|
|
75
|
-
return `Too many sub-agents are already running (limit ${budget.maxConcurrent}). Wait for one to finish.`;
|
|
76
|
-
if (this.#
|
|
78
|
+
if (this.#spend.running >= budget.maxConcurrent)
|
|
79
|
+
return `Too many sub-agents are already running (limit ${budget.maxConcurrent} at once, counted across the whole task tree). ${this.#children.size ? "Wait for one of yours to finish, or do" : "Do"} this part yourself.`;
|
|
80
|
+
if (this.#spend.tokens >= budget.budget)
|
|
77
81
|
return `The sub-agent token budget (${budget.budget}) is spent. Do the rest of this work yourself.`;
|
|
78
82
|
return;
|
|
79
83
|
}
|
|
@@ -112,7 +116,7 @@ class SubagentPool2 {
|
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
118
|
async#run(id, kind, prompt, signal) {
|
|
115
|
-
const { CodeAgent } = await import("./CodeAgent-
|
|
119
|
+
const { CodeAgent } = await import("./CodeAgent-awv258wb.js");
|
|
116
120
|
const budget = this.#options.parent.tools.subagent;
|
|
117
121
|
const child = SubagentPool2.childOf(this.#options.parent, kind);
|
|
118
122
|
const agent = await CodeAgent.create({
|
|
@@ -120,28 +124,43 @@ class SubagentPool2 {
|
|
|
120
124
|
cwd: this.#options.cwd,
|
|
121
125
|
profile: child,
|
|
122
126
|
apps: [],
|
|
123
|
-
depth: this.#options.depth + 1
|
|
127
|
+
depth: this.#options.depth + 1,
|
|
128
|
+
subagentSpend: this.#spend
|
|
124
129
|
});
|
|
125
130
|
const running = this.#children.get(id);
|
|
126
131
|
if (running)
|
|
127
132
|
running.agent = agent;
|
|
128
|
-
|
|
133
|
+
let stopped = false;
|
|
134
|
+
const abort = () => {
|
|
135
|
+
stopped = true;
|
|
136
|
+
agent.abort();
|
|
137
|
+
};
|
|
129
138
|
signal?.addEventListener("abort", abort, { once: true });
|
|
139
|
+
if (signal?.aborted)
|
|
140
|
+
stopped = true;
|
|
141
|
+
let finished = false;
|
|
130
142
|
try {
|
|
131
143
|
let answer = "";
|
|
132
144
|
agent.on((event) => {
|
|
133
145
|
if (event.type === "message" && event.role === "assistant")
|
|
134
146
|
answer = event.text;
|
|
147
|
+
if (event.type === "turn_start" && stopped)
|
|
148
|
+
agent.abort();
|
|
135
149
|
});
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
if (!stopped) {
|
|
151
|
+
await agent.prompt(prompt);
|
|
152
|
+
await agent.waitForIdle();
|
|
153
|
+
}
|
|
154
|
+
finished = true;
|
|
141
155
|
return answer.length > maxResultChars ? `${answer.slice(0, maxResultChars)}
|
|
142
156
|
\u2026(truncated)` : answer || "(no answer)";
|
|
143
157
|
} finally {
|
|
144
158
|
signal?.removeEventListener("abort", abort);
|
|
159
|
+
const tokens = agent.tokensUsed;
|
|
160
|
+
this.#spend.tokens += tokens;
|
|
161
|
+
const outcome = stopped ? "stopped" : finished ? "finished" : "failed";
|
|
162
|
+
const ceiling = budget ? budget.budget : 0;
|
|
163
|
+
this.#options.onNotice?.(`${kind} sub-agent ${outcome}, ${tokens} tokens (${this.#spend.tokens} of ${ceiling} spent)`);
|
|
145
164
|
agent.dispose();
|
|
146
165
|
}
|
|
147
166
|
}
|
|
@@ -207,8 +226,9 @@ class McpServerConfig {
|
|
|
207
226
|
`);
|
|
208
227
|
return McpServerConfig.#refOf(name, entry);
|
|
209
228
|
}
|
|
210
|
-
static remove(workspaceRoot, name) {
|
|
211
|
-
|
|
229
|
+
static remove(workspaceRoot, name, only) {
|
|
230
|
+
const candidates = McpServerConfig.files(workspaceRoot).filter(({ scope }) => !only || scope === only);
|
|
231
|
+
for (const { scope } of candidates.reverse()) {
|
|
212
232
|
const { file, key, map } = McpServerConfig.#parse(workspaceRoot, scope);
|
|
213
233
|
if (!(name in map))
|
|
214
234
|
continue;
|
|
@@ -270,6 +290,9 @@ class McpTokenStore {
|
|
|
270
290
|
static file() {
|
|
271
291
|
return akanCodePaths2.mcpAuthFile();
|
|
272
292
|
}
|
|
293
|
+
static lockFile() {
|
|
294
|
+
return `${McpTokenStore.file()}.lock`;
|
|
295
|
+
}
|
|
273
296
|
static read(name) {
|
|
274
297
|
return McpTokenStore.#all()[name];
|
|
275
298
|
}
|
|
@@ -539,30 +562,54 @@ class McpOAuthLoopback {
|
|
|
539
562
|
|
|
540
563
|
// pkgs/@akanjs/devkit/codeAgent/tools/McpSignIn.ts
|
|
541
564
|
class McpSignIn {
|
|
565
|
+
static #refreshing = new Map;
|
|
542
566
|
static async token(ref, onNotice) {
|
|
543
567
|
const stored = McpTokenStore.read(ref.name);
|
|
544
568
|
if (!stored)
|
|
545
569
|
return;
|
|
546
570
|
if (!McpTokenStore.isExpired(stored))
|
|
547
571
|
return stored.accessToken;
|
|
572
|
+
return await McpSignIn.#refreshOnce(ref, stored, onNotice);
|
|
573
|
+
}
|
|
574
|
+
static async retryToken(ref, refused, onNotice) {
|
|
575
|
+
const stored = McpTokenStore.read(ref.name);
|
|
576
|
+
if (!stored)
|
|
577
|
+
return;
|
|
578
|
+
if (stored.accessToken !== refused && !McpTokenStore.isExpired(stored))
|
|
579
|
+
return stored.accessToken;
|
|
580
|
+
return await McpSignIn.#refreshOnce(ref, stored, onNotice);
|
|
581
|
+
}
|
|
582
|
+
static async#refreshOnce(ref, stored, onNotice) {
|
|
583
|
+
const key = `${ref.name}
|
|
584
|
+
${stored.refreshToken}`;
|
|
585
|
+
let pending = McpSignIn.#refreshing.get(key);
|
|
586
|
+
if (!pending) {
|
|
587
|
+
pending = McpSignIn.#refreshed(ref, stored, onNotice).finally(() => McpSignIn.#refreshing.delete(key));
|
|
588
|
+
McpSignIn.#refreshing.set(key, pending);
|
|
589
|
+
}
|
|
590
|
+
return await pending;
|
|
591
|
+
}
|
|
592
|
+
static async#refreshed(ref, stored, onNotice) {
|
|
548
593
|
if (!stored.refreshToken)
|
|
549
594
|
return;
|
|
550
595
|
try {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
596
|
+
return await ConfigLock.run(McpTokenStore.lockFile(), async () => {
|
|
597
|
+
const current = McpTokenStore.read(ref.name);
|
|
598
|
+
if (!current)
|
|
599
|
+
return;
|
|
600
|
+
if (current.accessToken !== stored.accessToken && !McpTokenStore.isExpired(current))
|
|
601
|
+
return current.accessToken;
|
|
602
|
+
const server = {
|
|
603
|
+
issuer: current.issuer,
|
|
604
|
+
authorizationEndpoint: "",
|
|
605
|
+
tokenEndpoint: current.tokenEndpoint,
|
|
606
|
+
resource: current.resource
|
|
607
|
+
};
|
|
608
|
+
const tokens = await McpOAuth.refresh(server, current);
|
|
609
|
+
const { expiresAt: _spent, ...grant } = current;
|
|
610
|
+
McpTokenStore.write(ref.name, { ...grant, ...tokens });
|
|
611
|
+
return tokens.accessToken;
|
|
564
612
|
});
|
|
565
|
-
return tokens.accessToken;
|
|
566
613
|
} catch (error) {
|
|
567
614
|
onNotice?.(`MCP server "${ref.name}" needs signing in again \u2014 ${String(error)}`);
|
|
568
615
|
return;
|
|
@@ -597,10 +644,7 @@ class McpSignIn {
|
|
|
597
644
|
clientId: client.clientId,
|
|
598
645
|
...client.clientSecret ? { clientSecret: client.clientSecret } : {},
|
|
599
646
|
redirectUri,
|
|
600
|
-
|
|
601
|
-
...tokens.refreshToken ? { refreshToken: tokens.refreshToken } : {},
|
|
602
|
-
...tokens.expiresAt ? { expiresAt: tokens.expiresAt } : {},
|
|
603
|
-
...tokens.scope ? { scope: tokens.scope } : {}
|
|
647
|
+
...tokens
|
|
604
648
|
};
|
|
605
649
|
McpTokenStore.write(ref.name, auth);
|
|
606
650
|
return auth;
|
package/index.js
CHANGED
|
@@ -4,35 +4,34 @@ import {
|
|
|
4
4
|
getTargetMetas,
|
|
5
5
|
getTargetCommandNames,
|
|
6
6
|
runCommands
|
|
7
|
-
} from "./index-
|
|
8
|
-
import"./index-
|
|
9
|
-
import"./index-
|
|
10
|
-
import"./index-6wwzs1bc.js";
|
|
7
|
+
} from "./index-w2zdcw3k.js";
|
|
8
|
+
import"./index-5b6tavv3.js";
|
|
9
|
+
import"./index-9d9bgcx4.js";
|
|
11
10
|
|
|
12
11
|
// pkgs/@akanjs/cli/commandManifest.ts
|
|
13
12
|
import path from "path";
|
|
14
13
|
|
|
15
14
|
// pkgs/@akanjs/cli/commandModules.ts
|
|
16
15
|
var commandModules = {
|
|
17
|
-
workspace: async () => (await import("./workspace.command-
|
|
18
|
-
agent: async () => (await import("./agent.command-
|
|
19
|
-
code: async () => (await import("./code.command-
|
|
20
|
-
application: async () => (await import("./application.command-
|
|
21
|
-
library: async () => (await import("./library.command-
|
|
22
|
-
localRegistry: async () => (await import("./localRegistry.command-
|
|
23
|
-
package: async () => (await import("./package.command-
|
|
24
|
-
module: async () => (await import("./module.command-
|
|
25
|
-
page: async () => (await import("./page.command-
|
|
26
|
-
context: async () => (await import("./context.command-
|
|
27
|
-
cloud: async () => (await import("./cloud.command-
|
|
28
|
-
subspace: async () => (await import("./subspace.command-
|
|
29
|
-
guideline: async () => (await import("./guideline.command-
|
|
30
|
-
scalar: async () => (await import("./scalar.command-
|
|
31
|
-
primitive: async () => (await import("./primitive.command-
|
|
32
|
-
quality: async () => (await import("./quality.command-
|
|
33
|
-
repair: async () => (await import("./repair.command-
|
|
34
|
-
workflow: async () => (await import("./workflow.command-
|
|
35
|
-
tunnel: async () => (await import("./tunnel.command-
|
|
16
|
+
workspace: async () => (await import("./workspace.command-fqcztt5p.js")).WorkspaceCommand,
|
|
17
|
+
agent: async () => (await import("./agent.command-1s9ag7sb.js")).AgentCommand,
|
|
18
|
+
code: async () => (await import("./code.command-nn48xzej.js")).CodeCommand,
|
|
19
|
+
application: async () => (await import("./application.command-49hwy6va.js")).ApplicationCommand,
|
|
20
|
+
library: async () => (await import("./library.command-1gx04jgn.js")).LibraryCommand,
|
|
21
|
+
localRegistry: async () => (await import("./localRegistry.command-zndxj1q6.js")).LocalRegistryCommand,
|
|
22
|
+
package: async () => (await import("./package.command-zrc7br1y.js")).PackageCommand,
|
|
23
|
+
module: async () => (await import("./module.command-3waddk95.js")).ModuleCommand,
|
|
24
|
+
page: async () => (await import("./page.command-vpjgardh.js")).PageCommand,
|
|
25
|
+
context: async () => (await import("./context.command-s3mcmvpa.js")).ContextCommand,
|
|
26
|
+
cloud: async () => (await import("./cloud.command-d7rqtzt9.js")).CloudCommand,
|
|
27
|
+
subspace: async () => (await import("./subspace.command-ckcbwfp1.js")).SubspaceCommand,
|
|
28
|
+
guideline: async () => (await import("./guideline.command-sct4qnt5.js")).GuidelineCommand,
|
|
29
|
+
scalar: async () => (await import("./scalar.command-2v21newx.js")).ScalarCommand,
|
|
30
|
+
primitive: async () => (await import("./primitive.command-sz84tk4t.js")).PrimitiveCommand,
|
|
31
|
+
quality: async () => (await import("./quality.command-g869hafs.js")).QualityCommand,
|
|
32
|
+
repair: async () => (await import("./repair.command-chsnjvvv.js")).RepairCommand,
|
|
33
|
+
workflow: async () => (await import("./workflow.command-44252cqv.js")).WorkflowCommand,
|
|
34
|
+
tunnel: async () => (await import("./tunnel.command-kd2yr4fx.js")).TunnelCommand
|
|
36
35
|
};
|
|
37
36
|
var commandModuleIds = Object.keys(commandModules);
|
|
38
37
|
|
|
@@ -70,4 +69,4 @@ class CommandManifest {
|
|
|
70
69
|
// pkgs/@akanjs/cli/index.ts
|
|
71
70
|
var ids = CommandManifest.resolve(await CommandManifest.read(), process.argv) ?? commandModuleIds;
|
|
72
71
|
var commands = await Promise.all(ids.map(async (id) => await commandModules[id]()));
|
|
73
|
-
runCommands(...commands);
|
|
72
|
+
await runCommands(...commands);
|
|
@@ -3,13 +3,12 @@ import {
|
|
|
3
3
|
Lib,
|
|
4
4
|
Workspace,
|
|
5
5
|
command
|
|
6
|
-
} from "./index-
|
|
7
|
-
import"./index-
|
|
8
|
-
import"./index-
|
|
9
|
-
import"./index-6wwzs1bc.js";
|
|
6
|
+
} from "./index-w2zdcw3k.js";
|
|
7
|
+
import"./index-5b6tavv3.js";
|
|
8
|
+
import"./index-9d9bgcx4.js";
|
|
10
9
|
import {
|
|
11
10
|
LibraryScript
|
|
12
|
-
} from "./index-
|
|
11
|
+
} from "./index-5pc1qrbv.js";
|
|
13
12
|
|
|
14
13
|
// pkgs/@akanjs/cli/library/library.command.ts
|
|
15
14
|
class LibraryCommand extends command("library", [LibraryScript], ({ public: target }) => ({
|