@akanjs/cli 3.0.0-beta.17 → 3.0.0-beta.18

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.
Files changed (133) hide show
  1. package/.build-stamp +1 -1
  2. package/{CodeAgent-gjqnc2mg.js → CodeAgent-0035exh3.js} +2 -2
  3. package/{CodeTui-nd9hqvrw.js → CodeTui-eweg1hep.js} +205 -34
  4. package/{agent.command-n664dtcv.js → agent.command-65zqfkg0.js} +6 -6
  5. package/akanCode.js +5 -3
  6. package/{application.command-t5542jte.js → application.command-2wcj5da3.js} +18 -11
  7. package/{applicationBuildRunner-x4gbfn7y.js → applicationBuildRunner-m0hhgwsx.js} +6 -5
  8. package/{applicationReleasePackager-z61ep017.js → applicationReleasePackager-vykfzgx3.js} +1 -1
  9. package/buildBatch.proc.js +2 -2
  10. package/{capacitorApp-shv3ajh5.js → capacitorApp-2daqhb5h.js} +2 -2
  11. package/{cloud.command-dk5tj39k.js → cloud.command-960bgbf4.js} +8 -8
  12. package/{cloud.script-ch3xrw3s.js → cloud.script-qhcnqt1n.js} +8 -8
  13. package/{code.command-88sebgnn.js → code.command-4feh3ef7.js} +6 -6
  14. package/{context.command-pqsm5jrk.js → context.command-kzehkx48.js} +14 -14
  15. package/context.runner-z0rrcz7b.js +22 -0
  16. package/{devTui-gy6mendg.js → devTui-ffjsarqa.js} +3 -3
  17. package/{devTuiView-y1548wy6.js → devTuiView-1q1mdgrv.js} +1 -1
  18. package/{guideline.command-rpc2emw8.js → guideline.command-3w2g20x4.js} +8 -13
  19. package/guidelines/conventions/conventions.instruction.md +37 -22
  20. package/guidelines/queryRule/queryRule.instruction.md +1 -1
  21. package/guidelines/ssrRule/ssrRule.instruction.md +4 -2
  22. package/guidelines/transportRule/transportRule.instruction.md +10 -8
  23. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +4 -3
  24. package/incrementalBuilder.proc.js +1 -1
  25. package/{index-bzakk0c2.js → index-14zrtgfa.js} +5 -3
  26. package/{index-57p9p179.js → index-3hpxeys1.js} +6 -5
  27. package/{index-sn7dnzq4.js → index-4r42ext5.js} +1 -1
  28. package/{index-3mg4h788.js → index-6q589y9t.js} +2 -2
  29. package/index-9dp031by.js +12 -0
  30. package/{index-p4p9t45x.js → index-bwxpk2cj.js} +4 -18
  31. package/{index-g9zghs4h.js → index-cjw1sj1x.js} +12 -12
  32. package/{index-te0y1c0m.js → index-d9fjz06h.js} +12 -7
  33. package/{index-4n4821gp.js → index-dw943k93.js} +4 -4
  34. package/{index-4cvpzkq6.js → index-ef228gzf.js} +3 -3
  35. package/{index-3cymrzsb.js → index-erfc1x40.js} +17 -3
  36. package/{index-ns128c4q.js → index-h94faz96.js} +13 -20
  37. package/index-jd01kj5r.js +656 -0
  38. package/{index-2sq06vv0.js → index-jwexzh42.js} +200 -54
  39. package/{index-kvzjda3v.js → index-m41ptvat.js} +5 -5
  40. package/{index-qh7brn20.js → index-mt2154s2.js} +6 -2
  41. package/{index-xjc7gg65.js → index-pn8mhpps.js} +23 -33
  42. package/{index-vpx68e4x.js → index-q9c3c0hy.js} +2 -2
  43. package/{index-v17gj504.js → index-rpgxs245.js} +2 -2
  44. package/{index-twq9p2sp.js → index-s5rhm04y.js} +0 -6
  45. package/{index-p0tew3fq.js → index-sbfk9daf.js} +8 -3
  46. package/{index-n8kt2wh6.js → index-wcg582a8.js} +5 -5
  47. package/{index-6na0sd2b.js → index-ycy302an.js} +5 -2
  48. package/{index-qhtj9y6j.js → index-yw6g3bbv.js} +74 -21
  49. package/{index-2pm1j01n.js → index-zmj143x7.js} +4 -4
  50. package/{index-zn8qgeqx.js → index-zq0mr3hh.js} +1 -1
  51. package/index.js +21 -21
  52. package/{library.command-m8p2r1dh.js → library.command-fp0nhr62.js} +3 -3
  53. package/{localRegistry.command-yppdqrxv.js → localRegistry.command-8y0ecxb9.js} +7 -7
  54. package/{module.command-mfzvqt0n.js → module.command-kqkn48t2.js} +5 -5
  55. package/{package.command-cgp2p2v5.js → package.command-qverjh22.js} +4 -4
  56. package/package.json +2 -2
  57. package/{page.command-taenb02b.js → page.command-94bwhd0g.js} +3 -3
  58. package/{primitive.command-7kpncmkk.js → primitive.command-2ydvtah2.js} +6 -6
  59. package/{prompter-9mn3kp36.js → prompter-1f8d9pcc.js} +1 -1
  60. package/{quality.command-1ar94hrw.js → quality.command-fa0gth4p.js} +3 -4
  61. package/{repair.command-n08t6j8p.js → repair.command-4qng2hpm.js} +5 -5
  62. package/{routeSourceValidator-apyqw7wk.js → routeSourceValidator-7ycnfz0e.js} +0 -6
  63. package/{scalar.command-mq8qfp4t.js → scalar.command-pb2y95sh.js} +4 -4
  64. package/skills/akan-code/SKILL.md +122 -0
  65. package/skills/akan-module/SKILL.md +2 -2
  66. package/skills/akan-store/SKILL.md +6 -2
  67. package/{subspace.command-jqv5n79w.js → subspace.command-vkxmwp74.js} +4 -4
  68. package/templates/__scalar/__model__/__model__.abstract.md.template +8 -0
  69. package/templates/appSample/lib/__scalar/workHistory/workHistory.abstract.ts +8 -39
  70. package/templates/appSample/lib/_noti/noti.abstract.ts +6 -29
  71. package/templates/appSample/lib/task/task.abstract.ts +12 -32
  72. package/templates/appSample/lib/task/task.signal.spec.ts +15 -18
  73. package/templates/appSample/lib/task/task.signal.test.ts +14 -0
  74. package/templates/appSample/lib/task/task.signal.ts +1 -1
  75. package/templates/appSample/srvkit/AuthGuard.ts +4 -1
  76. package/templates/appSample/srvkit/SessionInternalArg.ts +3 -1
  77. package/templates/crudPages/[__model__Id]/edit/page.tsx +2 -1
  78. package/templates/crudPages/[__model__Id]/page.tsx +2 -1
  79. package/templates/crudPages/new/page.tsx +2 -1
  80. package/templates/crudPages/page.tsx +2 -1
  81. package/templates/crudSinglePage/page.tsx +2 -1
  82. package/templates/module/__model__.signal.ts +12 -4
  83. package/templates/pkgRoot/tsconfig.json.template +2 -7
  84. package/templates/service/__model__.abstract.md.template +8 -0
  85. package/{tunnel.command-ht2es78c.js → tunnel.command-02cvp9nf.js} +2 -2
  86. package/{workflow.command-tvz4nm9n.js → workflow.command-132txnrh.js} +9 -9
  87. package/{workspace.command-txv1yv5e.js → workspace.command-d5wkswek.js} +21 -21
  88. package/context.runner-bys6ykcp.js +0 -22
  89. package/guidelines/agentRule/agentRule.generate.json +0 -31
  90. package/guidelines/componentRule/componentRule.generate.json +0 -31
  91. package/guidelines/conventions/conventions.generate.json +0 -25
  92. package/guidelines/cssRule/cssRule.generate.json +0 -31
  93. package/guidelines/docPageRule/docPageRule.generate.json +0 -31
  94. package/guidelines/docPageRule/docPageRule.instruction.md +0 -25
  95. package/guidelines/docSyncRule/docSyncRule.generate.json +0 -31
  96. package/guidelines/docSyncRule/docSyncRule.instruction.md +0 -25
  97. package/guidelines/enumConstant/enumConstant.generate.json +0 -31
  98. package/guidelines/enumConstant/enumConstant.instruction.md +0 -28
  99. package/guidelines/fieldRule/fieldRule.generate.json +0 -31
  100. package/guidelines/framework/framework.generate.json +0 -32
  101. package/guidelines/mcpRule/mcpRule.generate.json +0 -35
  102. package/guidelines/modelConstant/modelConstant.generate.json +0 -32
  103. package/guidelines/modelDictionary/modelDictionary.generate.json +0 -32
  104. package/guidelines/modelDocument/modelDocument.generate.json +0 -31
  105. package/guidelines/modelService/modelService.generate.json +0 -31
  106. package/guidelines/modelSignal/modelSignal.generate.json +0 -31
  107. package/guidelines/modelStore/modelStore.generate.json +0 -31
  108. package/guidelines/modelTemplate/modelTemplate.generate.json +0 -31
  109. package/guidelines/modelUnit/modelUnit.generate.json +0 -31
  110. package/guidelines/modelUtil/modelUtil.generate.json +0 -31
  111. package/guidelines/modelView/modelView.generate.json +0 -31
  112. package/guidelines/modelZone/modelZone.generate.json +0 -31
  113. package/guidelines/moduleCodegen/moduleCodegen.generate.json +0 -31
  114. package/guidelines/moduleCodegen/moduleCodegen.instruction.md +0 -28
  115. package/guidelines/moduleOverview/moduleOverview.generate.json +0 -31
  116. package/guidelines/queryRule/queryRule.generate.json +0 -31
  117. package/guidelines/recipeRule/recipeRule.generate.json +0 -31
  118. package/guidelines/runtimeRule/runtimeRule.generate.json +0 -25
  119. package/guidelines/scalarConstant/scalarConstant.generate.json +0 -32
  120. package/guidelines/scalarDictionary/scalarDictionary.generate.json +0 -32
  121. package/guidelines/scalarModule/scalarModule.generate.json +0 -31
  122. package/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -31
  123. package/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +0 -25
  124. package/guidelines/ssrRule/ssrRule.generate.json +0 -31
  125. package/guidelines/transportRule/transportRule.generate.json +0 -31
  126. package/guidelines/utilUiUsage/utilUiUsage.generate.json +0 -31
  127. package/guidelines/utilUiUsage/utilUiUsage.instruction.md +0 -25
  128. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +0 -24
  129. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +0 -34
  130. package/index-qt8dqgnf.js +0 -250
  131. package/templates/__scalar/__model__/__model__.abstract.md +0 -28
  132. package/templates/module/__model__.abstract.md +0 -28
  133. package/templates/service/__model__.abstract.md +0 -28
@@ -1,31 +0,0 @@
1
- {
2
- "title": "Transport Rule",
3
- "description": "How a call reaches an Akan signal — guards across HTTP and websocket, socket identity and cleanup, binary pubsub frames, and mutation HTTP verbs",
4
- "group": "core",
5
- "codegenPriority": 4,
6
- "deprecated": false,
7
- "scans": [
8
- {
9
- "type": "example",
10
- "description": "Guard classes and their scope markers",
11
- "path": "{apps,libs}/*/srvkit/guards.ts",
12
- "sample": 2
13
- },
14
- {
15
- "type": "example",
16
- "description": "Signal endpoints declaring guards, pubsub, and message handlers",
17
- "path": "{apps,libs}/*/lib/*/*.signal.ts",
18
- "sample": 4
19
- }
20
- ],
21
- "update": {
22
- "filePath": "./transportRule.instruction.md",
23
- "contents": ["guards across transports", "signal body types", "binary pubsub", "mutation HTTP verbs"],
24
- "rules": [
25
- "Use current Akan APIs only",
26
- "State the rule and the reason it exists, never restate a type signature",
27
- "Say what leaks or breaks when a rule is ignored",
28
- "Keep it workspace-neutral — no app or repo names"
29
- ]
30
- }
31
- }
@@ -1,31 +0,0 @@
1
- {
2
- "title": "Util UI Usage",
3
- "description": "Utility UI usage rules",
4
- "group": "core",
5
- "docsSource": "apps/akan/page/(docs)/references/ui/core.tsx",
6
- "codegenPriority": 3,
7
- "deprecated": false,
8
- "scans": [
9
- {
10
- "type": "docs",
11
- "description": "Current docs source for Util UI Usage",
12
- "path": "apps/akan/page/(docs)/references/ui/core.tsx"
13
- },
14
- {
15
- "type": "example",
16
- "description": "Existing Akan implementation examples",
17
- "path": "{apps,libs}/*/lib/**/*.ts",
18
- "sample": 4
19
- }
20
- ],
21
- "update": {
22
- "filePath": "./utilUiUsage.instruction.md",
23
- "contents": ["purpose", "file ownership", "current API patterns", "codegen rules", "validation checklist"],
24
- "rules": [
25
- "Use current Akan APIs only",
26
- "Keep output parseable for codegen",
27
- "Include ownership boundaries and review checklist"
28
- ]
29
- },
30
- "page": "apps/akan/page/(docs)/references/ui/core.tsx"
31
- }
@@ -1,25 +0,0 @@
1
- # Util UI Usage Guideline
2
-
3
- ## Purpose
4
- Use utility UI components for common application interactions, layout helpers, scrolling, loading, and small display patterns.
5
-
6
- ## Ownership
7
- - Utility UI is for cross-domain layout and interaction helpers.
8
- - Module-specific controls still belong in Model.Util.
9
- - Docs pages may use utility UI for scroll sections and navigation.
10
-
11
- ## Current Akan Patterns
12
- - Prefer existing utility components before adding custom layout code.
13
- - Keep imported utility UI usage close to nearby docs and app examples.
14
- - Forward className and preserve composition.
15
-
16
- ## Codegen Rules
17
- - Do not make utility UI carry model-specific business behavior.
18
- - Do not duplicate util components in each module.
19
- - Do not use utility components without checking expected props.
20
-
21
- ## Review Checklist
22
- - The instruction points to current docs pages, not removed docs routes.
23
- - Generated examples use current Akan builder APIs and scanner-friendly filenames.
24
- - The output contract tells the model which file paths to return.
25
- - The guide avoids broad framework essays when a concrete file rule is better.
@@ -1,24 +0,0 @@
1
- {
2
- "title": "Workspace Onboarding",
3
- "description": "Product-workspace orientation — layout, decision matrix, workflow recipes, and query gotchas",
4
- "group": "core",
5
- "codegenPriority": 2,
6
- "deprecated": false,
7
- "scans": [],
8
- "update": {
9
- "filePath": "./workspaceOnboarding.instruction.md",
10
- "contents": [
11
- "workspace layout and generated files",
12
- "agent workflow and common commands",
13
- "where-do-I-put-this decision matrix",
14
- "workflow recipes",
15
- "modeling and query gotchas"
16
- ],
17
- "rules": [
18
- "Use current Akan APIs only",
19
- "Write for someone building a product on Akan, not for someone changing Akan",
20
- "Refer to the app as <%= appName %>; the renderer substitutes the workspace's first app",
21
- "Do not repeat a rule that the conventions guideline already states"
22
- ]
23
- }
24
- }
@@ -1,34 +0,0 @@
1
- {
2
- "title": "Workspace Recipes",
3
- "description": "Worked step-by-step recipes for common Akan changes, plus the auto-generated signal/service/store/document API reference",
4
- "group": "core",
5
- "codegenPriority": 5,
6
- "deprecated": false,
7
- "scans": [
8
- {
9
- "type": "example",
10
- "description": "Module files a recipe walks through",
11
- "path": "{apps,libs}/*/lib/*/*.{constant,document,service,signal,store}.ts",
12
- "sample": 5
13
- }
14
- ],
15
- "update": {
16
- "filePath": "./workspaceRecipes.instruction.md",
17
- "contents": [
18
- "add a field",
19
- "inject a dependency",
20
- "create a slice",
21
- "create a mutation",
22
- "internal triggers",
23
- "insights",
24
- "migrating the LLM adaptor and the removed --ai commands",
25
- "auto-generated API reference"
26
- ],
27
- "rules": [
28
- "Use current Akan APIs only",
29
- "Every recipe names the files to edit and the order to edit them in",
30
- "Keep the <%= appName %> placeholder so the rendered guide names this workspace's app",
31
- "Never duplicate a rule that workspaceOnboarding already states — link to it instead"
32
- ]
33
- }
34
- }
package/index-qt8dqgnf.js DELETED
@@ -1,250 +0,0 @@
1
- // @bun
2
- // pkgs/@akanjs/devkit/codeAgent/agent/SubagentPool.ts
3
- import { codeAgentReadOnlyBuiltins } from "akanjs/common";
4
- import { Type } from "typebox";
5
- var maxResultChars = 8000;
6
- var tickMs = 1000;
7
-
8
- class SubagentPool2 {
9
- static kinds = {
10
- explore: {
11
- readOnly: true,
12
- desc: "reads, searches and reports back. It cannot write a file or run a command."
13
- },
14
- code: {
15
- readOnly: false,
16
- desc: "makes the change itself, with the same tools as this session."
17
- }
18
- };
19
- static defaultKind = "explore";
20
- #options;
21
- #children = new Map;
22
- #running = 0;
23
- #spent = 0;
24
- #ticker = null;
25
- constructor(options) {
26
- this.#options = options;
27
- }
28
- static extensionFor(options) {
29
- if (!options.parent.tools.subagent)
30
- return;
31
- if (options.depth >= options.parent.tools.subagent.maxDepth)
32
- return;
33
- const pool = new SubagentPool2(options);
34
- return { name: "akan-subagent", factory: (pi) => pool.#register(pi) };
35
- }
36
- static toolName = "task";
37
- #register(pi) {
38
- pi.registerTool({
39
- name: SubagentPool2.toolName,
40
- label: "Task",
41
- description: "Run a focused sub-agent on one self-contained question and get back its answer. Use it for searching and reading that would otherwise fill this conversation \u2014 the sub-agent's own reading does not come back, only its answer. Give it everything it needs: it cannot see this conversation.",
42
- promptSnippet: "task: run a sub-agent on one self-contained question and get back only its answer",
43
- parameters: Type.Object({
44
- description: Type.String({ description: "Three to five words naming the task, for the activity log." }),
45
- prompt: Type.String({
46
- description: "The complete instruction. The sub-agent sees nothing of this conversation."
47
- }),
48
- type: Type.Optional(Type.Union(Object.entries(SubagentPool2.kinds).map(([kind, spec]) => Type.Literal(kind, { description: spec.desc })), { description: `What the sub-agent may do. Defaults to ${SubagentPool2.defaultKind}.` }))
49
- }),
50
- execute: async (id, params, signal) => {
51
- const kind = params.type ?? SubagentPool2.defaultKind;
52
- const refusal = this.#refuse();
53
- if (refusal)
54
- return { content: [{ type: "text", text: refusal }], details: undefined, isError: true };
55
- this.#running += 1;
56
- this.#children.set(id, { kind, description: params.description, startedAt: Date.now() });
57
- this.#report();
58
- this.#options.onNotice?.(`${kind} sub-agent \xB7 ${params.description}`);
59
- try {
60
- const text = await this.#run(id, kind, params.prompt, signal);
61
- return { content: [{ type: "text", text }], details: undefined };
62
- } finally {
63
- this.#running -= 1;
64
- this.#children.delete(id);
65
- this.#report();
66
- }
67
- }
68
- });
69
- }
70
- #refuse() {
71
- const budget = this.#options.parent.tools.subagent;
72
- if (!budget)
73
- 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.#spent >= budget.budget)
77
- return `The sub-agent token budget (${budget.budget}) is spent. Do the rest of this work yourself.`;
78
- return;
79
- }
80
- static childOf(parent, kind) {
81
- const budget = parent.tools.subagent;
82
- return {
83
- ...parent,
84
- name: `${parent.name}:${kind}`,
85
- tools: {
86
- ...parent.tools,
87
- builtin: SubagentPool2.kinds[kind].readOnly ? parent.tools.builtin.filter((tool) => codeAgentReadOnlyBuiltins.includes(tool)) : parent.tools.builtin,
88
- subagent: budget ? { ...budget, maxDepth: budget.maxDepth } : false
89
- },
90
- session: { store: "memory", crossSession: false },
91
- ui: { canPrompt: false },
92
- context: { projectFiles: false, skills: parent.context.skills }
93
- };
94
- }
95
- #report() {
96
- const onAgents = this.#options.onAgents;
97
- if (!onAgents)
98
- return;
99
- onAgents([...this.#children].map(([id, child]) => ({
100
- id,
101
- kind: child.kind,
102
- description: child.description,
103
- startedAt: child.startedAt,
104
- tokens: child.agent?.tokensUsed ?? 0
105
- })));
106
- if (this.#children.size && !this.#ticker) {
107
- this.#ticker = setInterval(() => this.#report(), tickMs);
108
- this.#ticker.unref?.();
109
- } else if (!this.#children.size && this.#ticker) {
110
- clearInterval(this.#ticker);
111
- this.#ticker = null;
112
- }
113
- }
114
- async#run(id, kind, prompt, signal) {
115
- const { CodeAgent } = await import("./CodeAgent-gjqnc2mg.js");
116
- const budget = this.#options.parent.tools.subagent;
117
- const child = SubagentPool2.childOf(this.#options.parent, kind);
118
- const agent = await CodeAgent.create({
119
- workspace: this.#options.workspace,
120
- cwd: this.#options.cwd,
121
- profile: child,
122
- apps: [],
123
- depth: this.#options.depth + 1
124
- });
125
- const running = this.#children.get(id);
126
- if (running)
127
- running.agent = agent;
128
- const abort = () => void agent.abort();
129
- signal?.addEventListener("abort", abort, { once: true });
130
- try {
131
- let answer = "";
132
- agent.on((event) => {
133
- if (event.type === "message" && event.role === "assistant")
134
- answer = event.text;
135
- });
136
- await agent.prompt(prompt);
137
- await agent.waitForIdle();
138
- this.#spent += agent.tokensUsed;
139
- const ceiling = budget ? budget.budget : 0;
140
- this.#options.onNotice?.(`${kind} sub-agent finished, ${agent.tokensUsed} tokens (${this.#spent} of ${ceiling} spent)`);
141
- return answer.length > maxResultChars ? `${answer.slice(0, maxResultChars)}
142
- \u2026(truncated)` : answer || "(no answer)";
143
- } finally {
144
- signal?.removeEventListener("abort", abort);
145
- agent.dispose();
146
- }
147
- }
148
- }
149
-
150
- // pkgs/@akanjs/devkit/codeAgent/agent/akanCodePaths.ts
151
- import { existsSync } from "fs";
152
- import { homedir } from "os";
153
- import path from "path";
154
- var builtinSkillsDir = () => {
155
- const candidates = [path.join(import.meta.dir, "skills"), path.join(import.meta.dir, "..", "skills")];
156
- return candidates.find((candidate) => existsSync(candidate));
157
- };
158
- var akanCodePaths2 = {
159
- workspaceDir: (workspaceRoot) => path.join(workspaceRoot, ".akan", "code"),
160
- sessionsDir: (workspaceRoot) => path.join(workspaceRoot, ".akan", "code", "sessions"),
161
- extensionsDir: (workspaceRoot) => path.join(workspaceRoot, ".akan", "code", "extensions"),
162
- skillsDir: (workspaceRoot) => path.join(workspaceRoot, ".akan", "code", "skills"),
163
- mailDir: (workspaceRoot) => path.join(workspaceRoot, ".akan", "code", "mail"),
164
- builtinSkillsDir,
165
- mcpFile: (workspaceRoot) => path.join(workspaceRoot, ".akan", "code", "mcp.json"),
166
- globalDir: () => path.join(homedir(), ".akan", "code"),
167
- authFile: () => path.join(homedir(), ".akan", "code", "auth.json"),
168
- modelsFile: () => path.join(homedir(), ".akan", "code", "models.json")
169
- };
170
-
171
- // pkgs/@akanjs/devkit/codeAgent/tools/McpServerConfig.ts
172
- import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "fs";
173
- import path2 from "path";
174
- class McpServerConfig {
175
- static file(workspaceRoot) {
176
- return akanCodePaths2.mcpFile(workspaceRoot);
177
- }
178
- static read(workspaceRoot) {
179
- const entries = Object.entries(McpServerConfig.#parse(workspaceRoot).map);
180
- return entries.filter(([, entry]) => !entry.disabled).map(([name, entry]) => McpServerConfig.#refOf(name, entry));
181
- }
182
- static declared(workspaceRoot) {
183
- return Object.entries(McpServerConfig.#parse(workspaceRoot).map).map(([name, entry]) => ({
184
- ref: McpServerConfig.#refOf(name, entry),
185
- disabled: !!entry.disabled
186
- }));
187
- }
188
- static add(workspaceRoot, name, target) {
189
- const [head, ...rest] = target;
190
- if (!head)
191
- throw new Error("Give the server a command to run, or a url to reach.");
192
- const entry = /^https?:\/\//.test(head) ? { url: head } : { command: head, args: rest };
193
- const { file, key, map } = McpServerConfig.#parse(workspaceRoot);
194
- const next = { ...map, [name]: entry };
195
- mkdirSync(path2.dirname(file), { recursive: true });
196
- writeFileSync(file, `${JSON.stringify({ [key]: next }, null, 2)}
197
- `);
198
- return McpServerConfig.#refOf(name, entry);
199
- }
200
- static remove(workspaceRoot, name) {
201
- const { file, key, map } = McpServerConfig.#parse(workspaceRoot);
202
- if (!(name in map))
203
- return false;
204
- const next = { ...map };
205
- delete next[name];
206
- writeFileSync(file, `${JSON.stringify({ [key]: next }, null, 2)}
207
- `);
208
- return true;
209
- }
210
- static #refOf(name, entry) {
211
- return {
212
- name,
213
- transport: entry.url ? "http" : "stdio",
214
- ...entry.command ? { command: entry.command } : {},
215
- ...entry.args ? { args: entry.args } : {},
216
- ...entry.url ? { url: entry.url } : {},
217
- ...entry.env ? { env: entry.env } : {}
218
- };
219
- }
220
- static targetOf(ref) {
221
- return ref.url ?? [ref.command, ...ref.args ?? []].filter(Boolean).join(" ");
222
- }
223
- static problem(workspaceRoot) {
224
- const file = McpServerConfig.file(workspaceRoot);
225
- if (!existsSync2(file))
226
- return;
227
- try {
228
- JSON.parse(readFileSync(file, "utf8"));
229
- return;
230
- } catch (error) {
231
- return `${file} is not valid JSON \u2014 ${String(error)}`;
232
- }
233
- }
234
- static #parse(workspaceRoot) {
235
- const file = McpServerConfig.file(workspaceRoot);
236
- const empty = { file, key: "mcpServers", map: {} };
237
- if (!existsSync2(file))
238
- return empty;
239
- try {
240
- const parsed = JSON.parse(readFileSync(file, "utf8"));
241
- if (parsed.servers && !parsed.mcpServers)
242
- return { file, key: "servers", map: parsed.servers };
243
- return { ...empty, map: parsed.mcpServers ?? {} };
244
- } catch {
245
- return empty;
246
- }
247
- }
248
- }
249
-
250
- export { SubagentPool2, akanCodePaths2, McpServerConfig };
@@ -1,28 +0,0 @@
1
- # Scalar Abstract
2
-
3
- ## Purpose
4
-
5
- Describe the embedded value object or reusable data concept this scalar owns.
6
-
7
- ## Domain Rules
8
-
9
- - Keep durable validation and meaning rules here.
10
- - Avoid repeating field types that are already clear in the constant file.
11
-
12
- ## Data Meaning
13
-
14
- Explain the meaning of the scalar fields and when this scalar should be used.
15
-
16
- ## Workflows
17
-
18
- Describe lifecycle or normalization behavior when relevant.
19
-
20
- ## Agent Notes
21
-
22
- - Read this abstract before changing the scalar.
23
- - Update this file when validation meaning, public behavior, or reuse rules change.
24
- - Do not update this file for formatting-only, import-only, or style-only changes.
25
-
26
- ## Related Modules
27
-
28
- - None yet.
@@ -1,28 +0,0 @@
1
- # Module Abstract
2
-
3
- ## Purpose
4
-
5
- Describe the business concept this module owns.
6
-
7
- ## Domain Rules
8
-
9
- - Keep durable business invariants here.
10
- - Avoid repeating field types that are already clear in the constant file.
11
-
12
- ## Data Meaning
13
-
14
- Explain the meaning of important data only when the code does not make the intent obvious.
15
-
16
- ## Workflows
17
-
18
- Describe create, update, approval, deletion, state transition, or other business flows.
19
-
20
- ## Agent Notes
21
-
22
- - Read this abstract before changing the module.
23
- - Update this file when business invariants, workflows, or public behavior change.
24
- - Do not update this file for formatting-only, import-only, or style-only changes.
25
-
26
- ## Related Modules
27
-
28
- - None yet.
@@ -1,28 +0,0 @@
1
- # Service Abstract
2
-
3
- ## Purpose
4
-
5
- Describe the business workflow or integration this service owns.
6
-
7
- ## Domain Rules
8
-
9
- - Keep durable business invariants here.
10
- - Avoid repeating implementation details already clear in the service or signal files.
11
-
12
- ## Data Meaning
13
-
14
- Explain important input, output, and state meanings only when the code does not make the intent obvious.
15
-
16
- ## Workflows
17
-
18
- Describe the service workflows, background jobs, external calls, or state transitions.
19
-
20
- ## Agent Notes
21
-
22
- - Read this abstract before changing the service module.
23
- - Keep business behavior in service code and expose callable actions through signals.
24
- - Update this file when business invariants, workflows, or public behavior change.
25
-
26
- ## Related Modules
27
-
28
- - None yet.