@akanjs/devkit 3.0.0-beta.14 → 3.0.0-beta.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/codeAgent/agent/AkanAuthStorageBackend.ts +105 -0
- package/codeAgent/agent/AkanCodeServices.ts +104 -0
- package/codeAgent/agent/CodeAgent.ts +543 -0
- package/codeAgent/agent/CodeAgentAsks.ts +87 -0
- package/codeAgent/agent/CodeAgentEventMapper.ts +260 -0
- package/codeAgent/agent/CodeAgentGate.ts +119 -0
- package/codeAgent/agent/CodeAgentRpcHost.ts +96 -0
- package/codeAgent/agent/CodeAgentStreamPrinter.ts +93 -0
- package/codeAgent/agent/CodeAgentUi.ts +52 -0
- package/codeAgent/agent/CodeMailbox.ts +175 -0
- package/codeAgent/agent/CodeSessionFork.ts +71 -0
- package/codeAgent/agent/CodeSessionIndex.ts +104 -0
- package/codeAgent/agent/SubagentPool.ts +173 -0
- package/codeAgent/agent/akanCodeModel.ts +81 -0
- package/codeAgent/agent/akanCodePaths.ts +31 -0
- package/codeAgent/agent/akanSystemPrompt.ts +49 -0
- package/codeAgent/agent/codeAgentContract.test.ts +529 -0
- package/codeAgent/agent/codeMailbox.test.ts +80 -0
- package/codeAgent/agent/codeSessionFork.test.ts +60 -0
- package/codeAgent/agent/codeSessionIndex.test.ts +72 -0
- package/codeAgent/agent/consoleToStderr.ts +18 -0
- package/codeAgent/feedback/DevLogFeedback.ts +97 -0
- package/codeAgent/feedback/PreviewChrome.ts +106 -0
- package/codeAgent/feedback/PreviewFeedback.ts +53 -0
- package/codeAgent/feedback/PreviewView.ts +107 -0
- package/codeAgent/feedback/TurnFeedback.ts +113 -0
- package/codeAgent/feedback/VerifyFeedback.ts +46 -0
- package/codeAgent/feedback/previewChrome.test.ts +73 -0
- package/codeAgent/index.ts +43 -0
- package/codeAgent/skills/akan-debug/SKILL.md +42 -0
- package/codeAgent/skills/akan-deps/SKILL.md +50 -0
- package/codeAgent/skills/akan-err/SKILL.md +39 -0
- package/codeAgent/skills/akan-module/SKILL.md +45 -0
- package/codeAgent/skills/akan-scaffold/SKILL.md +76 -0
- package/codeAgent/skills/akan-scalar/SKILL.md +52 -0
- package/codeAgent/skills/akan-service/SKILL.md +34 -0
- package/codeAgent/skills/akan-store/SKILL.md +63 -0
- package/codeAgent/skills/akan-ui/SKILL.md +63 -0
- package/codeAgent/skills/akan-validate/SKILL.md +44 -0
- package/codeAgent/tools/AkanCli.ts +62 -0
- package/codeAgent/tools/AkanCodePlugins.ts +135 -0
- package/codeAgent/tools/AkanEditScope.ts +58 -0
- package/codeAgent/tools/AkanEnvKeys.ts +56 -0
- package/codeAgent/tools/AkanToolPack.ts +114 -0
- package/codeAgent/tools/AkanVerifier.ts +55 -0
- package/codeAgent/tools/MailToolPack.ts +85 -0
- package/codeAgent/tools/McpClient.ts +162 -0
- package/codeAgent/tools/McpToolPack.ts +134 -0
- package/codeAgent/tools/SessionToolPack.ts +101 -0
- package/codeAgent/tools/WebToolPack.ts +153 -0
- package/codeAgent/tools/akanCodePlugins.test.ts +476 -0
- package/index.ts +2 -0
- package/package.json +5 -2
- package/stripAnsi.ts +3 -0
- package/testHelpers.ts +179 -0
package/testHelpers.ts
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { AppExecutor, LibExecutor, ModuleExecutor, PkgExecutor, WorkspaceExecutor } from "@akanjs/devkit/executors";
|
|
5
|
+
export interface CallRecord {
|
|
6
|
+
name: string;
|
|
7
|
+
args: unknown[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const createCallRecorder = () => {
|
|
11
|
+
const calls: CallRecord[] = [];
|
|
12
|
+
return {
|
|
13
|
+
calls,
|
|
14
|
+
/**
|
|
15
|
+
* `Returns` lets one recorder stand in for methods that return a value. Nothing is produced — the
|
|
16
|
+
* stub resolves to `undefined`, so use it only where the code under test does not read the result;
|
|
17
|
+
* a test that needs the value should return it from its own closure instead.
|
|
18
|
+
*/
|
|
19
|
+
record<Returns = void>(name: string, ...args: unknown[]): Returns {
|
|
20
|
+
calls.push({ name, args });
|
|
21
|
+
return undefined as unknown as Returns;
|
|
22
|
+
},
|
|
23
|
+
names() {
|
|
24
|
+
return calls.map((call) => call.name);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const createFakeSpinner = (recorder = createCallRecorder()) => ({
|
|
30
|
+
succeed: (message?: string) => recorder.record("spinner.succeed", message),
|
|
31
|
+
fail: (message?: string) => recorder.record("spinner.fail", message),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const createFakeExecutor = <Extra extends object = object>(
|
|
35
|
+
name: string,
|
|
36
|
+
extra: Extra = {} as Extra,
|
|
37
|
+
recorder = createCallRecorder(),
|
|
38
|
+
) =>
|
|
39
|
+
({
|
|
40
|
+
name,
|
|
41
|
+
cwdPath: `/workspace/${name}`,
|
|
42
|
+
workspaceRoot: "/workspace",
|
|
43
|
+
spinning: (message: string) => {
|
|
44
|
+
recorder.record(`${name}.spinning`, message);
|
|
45
|
+
return createFakeSpinner(recorder);
|
|
46
|
+
},
|
|
47
|
+
spawn: async (...args: unknown[]) => {
|
|
48
|
+
recorder.record(`${name}.spawn`, ...args);
|
|
49
|
+
return "";
|
|
50
|
+
},
|
|
51
|
+
exec: async (...args: unknown[]) => {
|
|
52
|
+
recorder.record(`${name}.exec`, ...args);
|
|
53
|
+
return "";
|
|
54
|
+
},
|
|
55
|
+
scan: async (...args: unknown[]) => {
|
|
56
|
+
recorder.record(`${name}.scan`, ...args);
|
|
57
|
+
return { name };
|
|
58
|
+
},
|
|
59
|
+
scanSync: async (...args: unknown[]) => {
|
|
60
|
+
recorder.record(`${name}.scanSync`, ...args);
|
|
61
|
+
return { name };
|
|
62
|
+
},
|
|
63
|
+
...extra,
|
|
64
|
+
}) as Extra & {
|
|
65
|
+
name: string;
|
|
66
|
+
cwdPath: string;
|
|
67
|
+
workspaceRoot: string;
|
|
68
|
+
spinning: (message: string) => ReturnType<typeof createFakeSpinner>;
|
|
69
|
+
spawn: (...args: unknown[]) => Promise<string>;
|
|
70
|
+
exec: (...args: unknown[]) => Promise<string>;
|
|
71
|
+
scan: (...args: unknown[]) => Promise<{ name: string }>;
|
|
72
|
+
scanSync: (...args: unknown[]) => Promise<{ name: string }>;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const makeCliTempWorkspace = async () => {
|
|
76
|
+
const root = await mkdtemp(path.join(os.tmpdir(), "akan-cli-"));
|
|
77
|
+
await mkdir(root, { recursive: true });
|
|
78
|
+
await writeText(path.join(root, ".gitignore"), "");
|
|
79
|
+
await writeText(
|
|
80
|
+
path.join(root, ".env"),
|
|
81
|
+
["AKAN_PUBLIC_REPO_NAME=repo", "AKAN_PUBLIC_SERVE_DOMAIN=localhost", "AKAN_PUBLIC_ENV=local", ""].join("\n"),
|
|
82
|
+
);
|
|
83
|
+
const workspace = new WorkspaceExecutor({ workspaceRoot: root, repoName: "repo" });
|
|
84
|
+
return { root, workspace };
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const cleanupCliTempWorkspace = async (root: string) => {
|
|
88
|
+
await rm(root, { recursive: true, force: true });
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const writeText = async (filePath: string, content: string) => {
|
|
92
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
93
|
+
await writeFile(filePath, content);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const writeJson = async (filePath: string, value: object) => {
|
|
97
|
+
await writeText(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const createTempApp = async (appName = "demo") => {
|
|
101
|
+
const { root, workspace } = await makeCliTempWorkspace();
|
|
102
|
+
await writeJson(path.join(root, "package.json"), {
|
|
103
|
+
name: "repo",
|
|
104
|
+
version: "1.0.0",
|
|
105
|
+
description: "repo",
|
|
106
|
+
dependencies: {
|
|
107
|
+
react: "19.0.0",
|
|
108
|
+
"react-dom": "19.0.0",
|
|
109
|
+
"react-server-dom-webpack": "19.0.0",
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
await writeJson(path.join(root, "tsconfig.json"), {
|
|
113
|
+
compilerOptions: { target: "ESNext", paths: {} },
|
|
114
|
+
references: [],
|
|
115
|
+
});
|
|
116
|
+
await writeJson(path.join(root, "apps", appName, "tsconfig.json"), {
|
|
117
|
+
compilerOptions: { target: "ESNext", paths: {} },
|
|
118
|
+
});
|
|
119
|
+
await writeJson(path.join(root, "apps", appName, "package.json"), {
|
|
120
|
+
name: appName,
|
|
121
|
+
version: "1.0.0",
|
|
122
|
+
description: appName,
|
|
123
|
+
dependencies: {},
|
|
124
|
+
devDependencies: {},
|
|
125
|
+
});
|
|
126
|
+
await writeText(path.join(root, "apps", appName, "akan.config.ts"), "export default {};\n");
|
|
127
|
+
await mkdir(path.join(root, "apps", appName, "lib", "__scalar"), { recursive: true });
|
|
128
|
+
const app = AppExecutor.from(workspace, appName);
|
|
129
|
+
return { root, workspace, app };
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const createTempLib = async (libName = "shared") => {
|
|
133
|
+
const { root, workspace } = await makeCliTempWorkspace();
|
|
134
|
+
await writeJson(path.join(root, "package.json"), {
|
|
135
|
+
name: "repo",
|
|
136
|
+
version: "1.0.0",
|
|
137
|
+
description: "repo",
|
|
138
|
+
dependencies: {},
|
|
139
|
+
devDependencies: {},
|
|
140
|
+
});
|
|
141
|
+
await writeJson(path.join(root, "tsconfig.json"), {
|
|
142
|
+
compilerOptions: { target: "ESNext", paths: {} },
|
|
143
|
+
references: [],
|
|
144
|
+
});
|
|
145
|
+
const lib = LibExecutor.from(workspace, libName);
|
|
146
|
+
return { root, workspace, lib };
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const createTempPackage = async (pkgName = "@sample/tool") => {
|
|
150
|
+
const { root, workspace } = await makeCliTempWorkspace();
|
|
151
|
+
await writeJson(path.join(root, "package.json"), {
|
|
152
|
+
name: "repo",
|
|
153
|
+
version: "1.0.0",
|
|
154
|
+
description: "repo",
|
|
155
|
+
dependencies: { lodash: "4.0.0" },
|
|
156
|
+
devDependencies: { typescript: "6.0.0" },
|
|
157
|
+
});
|
|
158
|
+
await writeJson(path.join(root, "tsconfig.json"), {
|
|
159
|
+
compilerOptions: { target: "ESNext", paths: {} },
|
|
160
|
+
});
|
|
161
|
+
await writeJson(path.join(root, "pkgs", pkgName, "package.json"), {
|
|
162
|
+
name: pkgName,
|
|
163
|
+
version: "0.1.0",
|
|
164
|
+
description: "tool",
|
|
165
|
+
exports: {},
|
|
166
|
+
});
|
|
167
|
+
await writeJson(path.join(root, "pkgs", pkgName, "tsconfig.json"), {
|
|
168
|
+
compilerOptions: { target: "ESNext", paths: {} },
|
|
169
|
+
});
|
|
170
|
+
await writeText(path.join(root, "pkgs", pkgName, "index.ts"), 'import "lodash";\nexport const value = 1;\n');
|
|
171
|
+
const pkg = PkgExecutor.from(workspace, pkgName);
|
|
172
|
+
return { root, workspace, pkg };
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export const createTempModule = async (moduleName = "post") => {
|
|
176
|
+
const { root, workspace, app } = await createTempApp("demo");
|
|
177
|
+
const module = ModuleExecutor.from(app, moduleName);
|
|
178
|
+
return { root, workspace, app, module };
|
|
179
|
+
};
|