@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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runner,
|
|
4
4
|
script
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-w2zdcw3k.js";
|
|
6
6
|
import {
|
|
7
7
|
AGENT_BLOCK_START,
|
|
8
8
|
AGENT_BLOCK_END,
|
|
@@ -13,17 +13,17 @@ import {
|
|
|
13
13
|
CLAUDE_COMMENT_RULE,
|
|
14
14
|
AppExecutor,
|
|
15
15
|
LibExecutor
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-9d9bgcx4.js";
|
|
17
17
|
import {
|
|
18
18
|
collectRecipeSources2,
|
|
19
19
|
scanRecipes2
|
|
20
|
-
} from "./index-
|
|
20
|
+
} from "./index-hj6w4ka1.js";
|
|
21
21
|
import {
|
|
22
22
|
AkanContextAnalyzer
|
|
23
|
-
} from "./index-
|
|
23
|
+
} from "./index-ygn77a5w.js";
|
|
24
24
|
import {
|
|
25
25
|
Prompter2
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-0bq14vr1.js";
|
|
27
27
|
|
|
28
28
|
// pkgs/@akanjs/cli/agent/agent.script.ts
|
|
29
29
|
import { Logger as Logger2 } from "akanjs/common";
|
|
@@ -126,7 +126,7 @@ var renderManagedBlock = async (workspace) => {
|
|
|
126
126
|
const block = `## Workspace
|
|
127
127
|
|
|
128
128
|
- Repo: ${context.repoName}
|
|
129
|
-
- Apps: ${
|
|
129
|
+
- Apps: ${appNames.join(", ") || "none"}
|
|
130
130
|
- Libraries: ${context.libs.map((lib) => lib.name).join(", ") || "none"}
|
|
131
131
|
- Packages: ${context.pkgs.map((pkg) => pkg.name).join(", ") || "none"}
|
|
132
132
|
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runner,
|
|
4
4
|
script
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-w2zdcw3k.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
} from "./index-
|
|
7
|
+
FileSys2
|
|
8
|
+
} from "./index-5b6tavv3.js";
|
|
9
9
|
import {
|
|
10
10
|
PkgExecutor
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-9d9bgcx4.js";
|
|
12
12
|
import {
|
|
13
13
|
TypeScriptDependencyScanner2
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-3t7g9e4r.js";
|
|
15
15
|
|
|
16
16
|
// pkgs/@akanjs/cli/package/package.runner.ts
|
|
17
17
|
import path2 from "path";
|
|
@@ -112,7 +112,7 @@ class PackageRunner extends runner("package") {
|
|
|
112
112
|
"create-akan-workspace"
|
|
113
113
|
];
|
|
114
114
|
async version(workspace, { log = true } = {}) {
|
|
115
|
-
const pkgJson = process.env.USE_AKANJS_PKGS === "true" ? await
|
|
115
|
+
const pkgJson = process.env.USE_AKANJS_PKGS === "true" ? await FileSys2.readJson(`${workspace?.workspaceRoot ?? process.cwd()}/pkgs/akanjs/package.json`) : await this.#getInstalledPackageJson();
|
|
116
116
|
const version = pkgJson.name === "akanjs" ? pkgJson.version : pkgJson.dependencies?.akanjs ?? pkgJson.version;
|
|
117
117
|
if (log)
|
|
118
118
|
Logger.rawLog(`akanjs@${version}`);
|
|
@@ -129,7 +129,7 @@ class PackageRunner extends runner("package") {
|
|
|
129
129
|
for (const packageJsonPath of packageJsonCandidates) {
|
|
130
130
|
if (!await Bun.file(packageJsonPath).exists())
|
|
131
131
|
continue;
|
|
132
|
-
const packageJson = await
|
|
132
|
+
const packageJson = await FileSys2.readJson(packageJsonPath);
|
|
133
133
|
if (packageJson.name === "akanjs" || packageJson.name === "@akanjs/cli")
|
|
134
134
|
return packageJson;
|
|
135
135
|
}
|
|
@@ -149,8 +149,7 @@ class PackageRunner extends runner("package") {
|
|
|
149
149
|
await pkg.workspace.unsetPkgTsPaths(pkg.name);
|
|
150
150
|
}
|
|
151
151
|
async scanSync(pkg) {
|
|
152
|
-
|
|
153
|
-
return scanResult;
|
|
152
|
+
return await pkg.scan();
|
|
154
153
|
}
|
|
155
154
|
async buildPackage(pkg) {
|
|
156
155
|
await $`rm -rf ${pkg.dist.cwdPath}`;
|
|
@@ -184,8 +183,9 @@ class PackageRunner extends runner("package") {
|
|
|
184
183
|
const forcedRuntimeDevDeps = packageRuntimeDevDependencies[pkg.name] ?? [];
|
|
185
184
|
const [rootPackageJson, pkgJson] = await Promise.all([pkg.workspace.getPackageJson(), pkg.getPackageJson()]);
|
|
186
185
|
const optionalPeerDeps = new Set(Object.entries(pkgJson.peerDependenciesMeta ?? {}).filter(([, meta]) => meta.optional).map(([dep]) => dep));
|
|
187
|
-
const
|
|
188
|
-
const
|
|
186
|
+
const isShipped = (dep) => !optionalPeerDeps.has(dep) && !bundledRuntimeDeps.has(dep);
|
|
187
|
+
const packageRuntimeDeps = [...new Set([...npmDeps, ...forcedRuntimeDeps])].filter(isShipped);
|
|
188
|
+
const packageRuntimeDevDeps = [...new Set([...npmDevDeps, ...forcedRuntimeDevDeps])].filter(isShipped);
|
|
189
189
|
const rootDeps = {
|
|
190
190
|
...rootPackageJson.overrides,
|
|
191
191
|
...rootPackageJson.dependencies,
|
|
@@ -209,6 +209,7 @@ class PackageRunner extends runner("package") {
|
|
|
209
209
|
});
|
|
210
210
|
} else {
|
|
211
211
|
await pkg.dist.cp(pkg.cwdPath, pkg.dist.cwdPath);
|
|
212
|
+
await $`rm -rf ${pkg.dist.cwdPath}/local`;
|
|
212
213
|
await Promise.all([
|
|
213
214
|
pkg.generateDistPackageJson(packageRuntimeDeps, packageRuntimeDevDeps),
|
|
214
215
|
pkg.generateTsconfigJson()
|
|
@@ -282,7 +283,7 @@ class PackageRunner extends runner("package") {
|
|
|
282
283
|
if (!await Bun.file(distPackageJsonPath).exists()) {
|
|
283
284
|
throw new Error(`[package] dist package not found for ${pkg.name}. Run build-package first.`);
|
|
284
285
|
}
|
|
285
|
-
const pkgJson = await
|
|
286
|
+
const pkgJson = await FileSys2.readJson(distPackageJsonPath);
|
|
286
287
|
if (pkgJson.name !== pkg.name) {
|
|
287
288
|
throw new Error(`[package] dist package name mismatch: expected ${pkg.name}, got ${pkgJson.name ?? "(missing)"}`);
|
|
288
289
|
}
|
|
@@ -291,12 +292,9 @@ class PackageRunner extends runner("package") {
|
|
|
291
292
|
if (pkgJson.publishConfig?.access !== "public") {
|
|
292
293
|
throw new Error(`[package] ${pkg.name} must publish with publishConfig.access=public`);
|
|
293
294
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (!await Bun.file(`${pkg.dist.cwdPath}/README.ko.md`).exists()) {
|
|
298
|
-
throw new Error(`[package] README.ko.md is missing from dist package ${pkg.name}`);
|
|
299
|
-
}
|
|
295
|
+
for (const readme of ["README.md", "README.ko.md"])
|
|
296
|
+
if (!await Bun.file(`${pkg.dist.cwdPath}/${readme}`).exists())
|
|
297
|
+
throw new Error(`[package] ${readme} is missing from dist package ${pkg.name}`);
|
|
300
298
|
const binEntries = typeof pkgJson.bin === "string" ? [pkgJson.bin] : Object.values(pkgJson.bin ?? {});
|
|
301
299
|
if (binEntries.some((binPath) => binPath.endsWith(".ts"))) {
|
|
302
300
|
throw new Error(`[package] ${pkg.name} dist bin entries must not point at TypeScript sources`);
|
|
@@ -313,6 +311,9 @@ class PackageRunner extends runner("package") {
|
|
|
313
311
|
cwd: pkg.workspace.workspaceRoot
|
|
314
312
|
});
|
|
315
313
|
const [packResult] = JSON.parse(packOutput);
|
|
314
|
+
const localFiles = (packResult?.files ?? []).filter((file) => file.path?.startsWith("local/"));
|
|
315
|
+
if (localFiles.length > 0)
|
|
316
|
+
throw new Error(`[package] ${pkg.name} would publish ${localFiles.length} test-run files under local/`);
|
|
316
317
|
return {
|
|
317
318
|
name: pkg.name,
|
|
318
319
|
version: pkgJson.version,
|
|
@@ -329,9 +330,8 @@ class PackageRunner extends runner("package") {
|
|
|
329
330
|
peerExportsMaps.set(pkg.name, await PackageExportsMap.from(pkg.dist.cwdPath));
|
|
330
331
|
}
|
|
331
332
|
const results = [];
|
|
332
|
-
for (const pkg of pkgs)
|
|
333
|
+
for (const pkg of pkgs)
|
|
333
334
|
results.push(await this.verifyDistPackage(pkg, { peerExportsMaps }));
|
|
334
|
-
}
|
|
335
335
|
return results;
|
|
336
336
|
}
|
|
337
337
|
async#copyPackageReadmes(pkg) {
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
getDefaultHostConfig,
|
|
4
4
|
GlobalConfig,
|
|
5
5
|
CloudApi
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-22d57v4c.js";
|
|
7
7
|
import {
|
|
8
8
|
runner
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-w2zdcw3k.js";
|
|
10
10
|
import {
|
|
11
11
|
WorkspaceExecutor,
|
|
12
12
|
AppExecutor
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-9d9bgcx4.js";
|
|
14
14
|
import {
|
|
15
15
|
openBrowser
|
|
16
16
|
} from "./index-9dp031by.js";
|
|
@@ -145,6 +145,15 @@ class BunTestReport {
|
|
|
145
145
|
class PlatformTestTarget {
|
|
146
146
|
static installIdleMs = 5 * 60000;
|
|
147
147
|
static testIdleMs = 2 * 60000;
|
|
148
|
+
static gitIdentityEnv = {
|
|
149
|
+
GIT_AUTHOR_NAME: "akan-test",
|
|
150
|
+
GIT_AUTHOR_EMAIL: "akan-test@localhost",
|
|
151
|
+
GIT_COMMITTER_NAME: "akan-test",
|
|
152
|
+
GIT_COMMITTER_EMAIL: "akan-test@localhost",
|
|
153
|
+
GIT_CONFIG_COUNT: "1",
|
|
154
|
+
GIT_CONFIG_KEY_0: "init.defaultBranch",
|
|
155
|
+
GIT_CONFIG_VALUE_0: "main"
|
|
156
|
+
};
|
|
148
157
|
tolerateScriptFailures = [];
|
|
149
158
|
async run(context) {
|
|
150
159
|
const startedAt = performance.now();
|
|
@@ -204,6 +213,19 @@ class PlatformTestTarget {
|
|
|
204
213
|
#logPath(context, name) {
|
|
205
214
|
return path2.join(context.logDir, this.platform, `${name}.log`);
|
|
206
215
|
}
|
|
216
|
+
static async spawnText(command, stdin) {
|
|
217
|
+
const proc = Bun.spawn(command, {
|
|
218
|
+
stdin: stdin === undefined ? "ignore" : new Response(stdin),
|
|
219
|
+
stdout: "pipe",
|
|
220
|
+
stderr: "pipe"
|
|
221
|
+
});
|
|
222
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
223
|
+
new Response(proc.stdout).text(),
|
|
224
|
+
new Response(proc.stderr).text(),
|
|
225
|
+
proc.exited
|
|
226
|
+
]);
|
|
227
|
+
return { stdout, stderr, exitCode };
|
|
228
|
+
}
|
|
207
229
|
}
|
|
208
230
|
|
|
209
231
|
// pkgs/@akanjs/devkit/platformTest/LinuxDockerTarget.ts
|
|
@@ -227,12 +249,13 @@ class LinuxDockerTarget extends PlatformTestTarget {
|
|
|
227
249
|
return `akan-test-linux:bun-${Bun.version}-${Bun.hash(LinuxDockerTarget.dockerfile).toString(16).slice(0, 8)}`;
|
|
228
250
|
}
|
|
229
251
|
async prepare(context) {
|
|
230
|
-
if ((await LinuxDockerTarget
|
|
252
|
+
if ((await LinuxDockerTarget.spawnText(["docker", "info"])).exitCode !== 0)
|
|
231
253
|
throw new Error("Docker is not running \u2014 start Docker Desktop, or leave linux out of --platforms");
|
|
232
254
|
await this.#ensureImage();
|
|
233
255
|
const container = `akan-test-${context.runId}`;
|
|
234
256
|
const cpus = this.#config.cpus ?? Math.max(2, Math.floor(os.availableParallelism() / 2));
|
|
235
|
-
const started = await LinuxDockerTarget
|
|
257
|
+
const started = await LinuxDockerTarget.spawnText([
|
|
258
|
+
"docker",
|
|
236
259
|
"run",
|
|
237
260
|
"-d",
|
|
238
261
|
"--rm",
|
|
@@ -264,50 +287,34 @@ class LinuxDockerTarget extends PlatformTestTarget {
|
|
|
264
287
|
const container = this.#container;
|
|
265
288
|
if (!container)
|
|
266
289
|
throw new Error("the linux container is not running");
|
|
267
|
-
return await new IdleWatchedProcess([
|
|
290
|
+
return await new IdleWatchedProcess([
|
|
291
|
+
"docker",
|
|
292
|
+
"exec",
|
|
293
|
+
...Object.entries(PlatformTestTarget.gitIdentityEnv).flatMap(([key, value]) => ["-e", `${key}=${value}`]),
|
|
294
|
+
container,
|
|
295
|
+
"sh",
|
|
296
|
+
"-c",
|
|
297
|
+
command
|
|
298
|
+
], {
|
|
268
299
|
logPath,
|
|
269
300
|
idleMs,
|
|
270
301
|
onIdle: async () => {
|
|
271
|
-
await LinuxDockerTarget
|
|
302
|
+
await LinuxDockerTarget.spawnText(["docker", "exec", container, "pkill", "-9", "bun"]);
|
|
272
303
|
}
|
|
273
304
|
}).run();
|
|
274
305
|
}
|
|
275
306
|
async cleanup() {
|
|
276
307
|
if (this.#container)
|
|
277
|
-
await LinuxDockerTarget
|
|
308
|
+
await LinuxDockerTarget.spawnText(["docker", "rm", "-f", this.#container]);
|
|
278
309
|
this.#container = null;
|
|
279
310
|
}
|
|
280
311
|
async#ensureImage() {
|
|
281
|
-
if ((await LinuxDockerTarget
|
|
312
|
+
if ((await LinuxDockerTarget.spawnText(["docker", "image", "inspect", this.image])).exitCode === 0)
|
|
282
313
|
return;
|
|
283
|
-
const built = await LinuxDockerTarget
|
|
314
|
+
const built = await LinuxDockerTarget.spawnText(["docker", "build", "-t", this.image, "-"], LinuxDockerTarget.dockerfile);
|
|
284
315
|
if (built.exitCode !== 0)
|
|
285
316
|
throw new Error(`building ${this.image} failed: ${built.stderr.trim().slice(-400)}`);
|
|
286
317
|
}
|
|
287
|
-
static #gitIdentityEnv() {
|
|
288
|
-
return Object.entries({
|
|
289
|
-
GIT_AUTHOR_NAME: "akan-test",
|
|
290
|
-
GIT_AUTHOR_EMAIL: "akan-test@localhost",
|
|
291
|
-
GIT_COMMITTER_NAME: "akan-test",
|
|
292
|
-
GIT_COMMITTER_EMAIL: "akan-test@localhost",
|
|
293
|
-
GIT_CONFIG_COUNT: "1",
|
|
294
|
-
GIT_CONFIG_KEY_0: "init.defaultBranch",
|
|
295
|
-
GIT_CONFIG_VALUE_0: "main"
|
|
296
|
-
}).flatMap(([key, value]) => ["-e", `${key}=${value}`]);
|
|
297
|
-
}
|
|
298
|
-
static async#docker(args, stdin) {
|
|
299
|
-
const proc = Bun.spawn(["docker", ...args], {
|
|
300
|
-
stdin: stdin === undefined ? "ignore" : new Response(stdin),
|
|
301
|
-
stdout: "pipe",
|
|
302
|
-
stderr: "pipe"
|
|
303
|
-
});
|
|
304
|
-
const [stdout, stderr, exitCode] = await Promise.all([
|
|
305
|
-
new Response(proc.stdout).text(),
|
|
306
|
-
new Response(proc.stderr).text(),
|
|
307
|
-
proc.exited
|
|
308
|
-
]);
|
|
309
|
-
return { stdout, stderr, exitCode };
|
|
310
|
-
}
|
|
311
318
|
}
|
|
312
319
|
|
|
313
320
|
// pkgs/@akanjs/devkit/platformTest/TestSnapshot.ts
|
|
@@ -433,7 +440,7 @@ class WindowsSshTarget extends PlatformTestTarget {
|
|
|
433
440
|
[context.snapshot.tarPath, "src.tar"],
|
|
434
441
|
[context.envPath, "env"]
|
|
435
442
|
]) {
|
|
436
|
-
const copied = await WindowsSshTarget
|
|
443
|
+
const copied = await WindowsSshTarget.spawnText([
|
|
437
444
|
...this.#scpBase(),
|
|
438
445
|
local,
|
|
439
446
|
this.#remoteScpPath(`${runDir}\\${remoteName}`)
|
|
@@ -454,13 +461,7 @@ class WindowsSshTarget extends PlatformTestTarget {
|
|
|
454
461
|
"$ProgressPreference = 'SilentlyContinue'",
|
|
455
462
|
"[Console]::OutputEncoding = [Text.Encoding]::UTF8",
|
|
456
463
|
"'PID=' + $PID",
|
|
457
|
-
|
|
458
|
-
"$env:GIT_AUTHOR_EMAIL = 'akan-test@localhost'",
|
|
459
|
-
"$env:GIT_COMMITTER_NAME = 'akan-test'",
|
|
460
|
-
"$env:GIT_COMMITTER_EMAIL = 'akan-test@localhost'",
|
|
461
|
-
"$env:GIT_CONFIG_COUNT = '1'",
|
|
462
|
-
"$env:GIT_CONFIG_KEY_0 = 'init.defaultBranch'",
|
|
463
|
-
"$env:GIT_CONFIG_VALUE_0 = 'main'",
|
|
464
|
+
...Object.entries(PlatformTestTarget.gitIdentityEnv).map(([key, value]) => `$env:${key} = '${value}'`),
|
|
464
465
|
`Set-Location -LiteralPath '${runDir}\\w'`,
|
|
465
466
|
`cmd /c "${command} 2>&1"`,
|
|
466
467
|
"exit $LASTEXITCODE"
|
|
@@ -493,11 +494,11 @@ class WindowsSshTarget extends PlatformTestTarget {
|
|
|
493
494
|
const vm = this.#config.utmVm;
|
|
494
495
|
if (!vm || !existsSync(WindowsSshTarget.utmctlPath))
|
|
495
496
|
throw new Error(`cannot reach ${this.#config.user}@${this.#host} over ssh`);
|
|
496
|
-
const status = (await WindowsSshTarget
|
|
497
|
+
const status = (await WindowsSshTarget.spawnText([WindowsSshTarget.utmctlPath, "status", vm])).stdout.trim();
|
|
497
498
|
if (status !== "started")
|
|
498
|
-
await WindowsSshTarget
|
|
499
|
+
await WindowsSshTarget.spawnText([WindowsSshTarget.utmctlPath, "start", vm]);
|
|
499
500
|
for (let attempt = 0;attempt < 24; attempt++) {
|
|
500
|
-
const addresses = (await WindowsSshTarget
|
|
501
|
+
const addresses = (await WindowsSshTarget.spawnText([WindowsSshTarget.utmctlPath, "ip-address", vm])).stdout;
|
|
501
502
|
const ipv4 = addresses.split(/\s+/).find((address) => /^\d+\.\d+\.\d+\.\d+$/.test(address));
|
|
502
503
|
if (ipv4)
|
|
503
504
|
this.#host = ipv4;
|
|
@@ -531,16 +532,7 @@ class WindowsSshTarget extends PlatformTestTarget {
|
|
|
531
532
|
return `${this.#config.user}@${this.#host}:/${windowsPath.replaceAll("\\", "/")}`;
|
|
532
533
|
}
|
|
533
534
|
async#ssh(script) {
|
|
534
|
-
return await WindowsSshTarget
|
|
535
|
-
}
|
|
536
|
-
static async#run(command) {
|
|
537
|
-
const proc = Bun.spawn(command, { stdin: "ignore", stdout: "pipe", stderr: "pipe" });
|
|
538
|
-
const [stdout, stderr, exitCode] = await Promise.all([
|
|
539
|
-
new Response(proc.stdout).text(),
|
|
540
|
-
new Response(proc.stderr).text(),
|
|
541
|
-
proc.exited
|
|
542
|
-
]);
|
|
543
|
-
return { stdout, stderr, exitCode };
|
|
535
|
+
return await WindowsSshTarget.spawnText([...this.#sshBase(), script]);
|
|
544
536
|
}
|
|
545
537
|
}
|
|
546
538
|
|
|
@@ -699,26 +691,20 @@ class CloudRunner extends runner("cloud") {
|
|
|
699
691
|
NPM_CONFIG_REGISTRY: getNpmRegistryUrl(registryUrl)
|
|
700
692
|
} : process.env;
|
|
701
693
|
}
|
|
694
|
+
async#ask(message, validate) {
|
|
695
|
+
return (await input({ message, validate })).trim();
|
|
696
|
+
}
|
|
702
697
|
async#addRemoteEnvServer() {
|
|
703
|
-
const name =
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
message: "Remote server SSH port (optional): ",
|
|
714
|
-
validate: (value) => {
|
|
715
|
-
const trimmed = value.trim();
|
|
716
|
-
if (!trimmed)
|
|
717
|
-
return true;
|
|
718
|
-
const port = Number(trimmed);
|
|
719
|
-
return Number.isInteger(port) && port > 0 ? true : "SSH port must be a positive integer";
|
|
720
|
-
}
|
|
721
|
-
})).trim();
|
|
698
|
+
const name = await this.#ask("Remote server name: ", (value) => !!value.trim() || "Remote server name is required");
|
|
699
|
+
const host = await this.#ask("Remote server host: ", (value) => !!value.trim() || "Remote server host is required");
|
|
700
|
+
const username = await this.#ask("Remote server username (optional): ") || undefined;
|
|
701
|
+
const portInput = await this.#ask("Remote server SSH port (optional): ", (value) => {
|
|
702
|
+
const trimmed = value.trim();
|
|
703
|
+
if (!trimmed)
|
|
704
|
+
return true;
|
|
705
|
+
const port = Number(trimmed);
|
|
706
|
+
return Number.isInteger(port) && port > 0 ? true : "SSH port must be a positive integer";
|
|
707
|
+
});
|
|
722
708
|
const config = {
|
|
723
709
|
host,
|
|
724
710
|
...username ? { username } : {},
|
|
@@ -737,10 +723,7 @@ class CloudRunner extends runner("cloud") {
|
|
|
737
723
|
const selectedName = await select({
|
|
738
724
|
message: "Select the remote env server",
|
|
739
725
|
choices: [
|
|
740
|
-
...serverEntries.map((
|
|
741
|
-
name: `${name} (${config.username ? `${config.username}@` : ""}${config.host}${config.port ? `:${config.port}` : ""})`,
|
|
742
|
-
value: name
|
|
743
|
-
})),
|
|
726
|
+
...serverEntries.map((entry) => this.#serverChoice(entry)),
|
|
744
727
|
{ name: "Add new remote server", value: addRemoteEnvServerValue },
|
|
745
728
|
{ name: "Remove remote server", value: removeRemoteEnvServerValue }
|
|
746
729
|
]
|
|
@@ -759,34 +742,22 @@ class CloudRunner extends runner("cloud") {
|
|
|
759
742
|
async#removeRemoteEnvServer(serverEntries) {
|
|
760
743
|
const selectedName = await select({
|
|
761
744
|
message: "Select the remote env server to remove",
|
|
762
|
-
choices: serverEntries.map((
|
|
763
|
-
name: `${name} (${config.username ? `${config.username}@` : ""}${config.host}${config.port ? `:${config.port}` : ""})`,
|
|
764
|
-
value: name
|
|
765
|
-
}))
|
|
745
|
+
choices: serverEntries.map((entry) => this.#serverChoice(entry))
|
|
766
746
|
});
|
|
767
|
-
|
|
768
|
-
message: `Remove remote env server "${selectedName}"?`,
|
|
769
|
-
default: false
|
|
770
|
-
});
|
|
771
|
-
if (!shouldRemove)
|
|
747
|
+
if (!await confirm({ message: `Remove remote env server "${selectedName}"?`, default: false }))
|
|
772
748
|
return;
|
|
773
749
|
await GlobalConfig.removeRemoteEnvServer(selectedName);
|
|
774
750
|
Logger.info(`Removed remote env server "${selectedName}"`);
|
|
775
751
|
}
|
|
752
|
+
#serverChoice([name, config]) {
|
|
753
|
+
return { name: `${name} (${this.#getSshTarget(config)}${config.port ? `:${config.port}` : ""})`, value: name };
|
|
754
|
+
}
|
|
776
755
|
async#getRemoteEnvServerWithUsername() {
|
|
777
756
|
const remoteServer = await this.#selectRemoteEnvServer();
|
|
778
757
|
if (remoteServer.config.username)
|
|
779
758
|
return remoteServer;
|
|
780
|
-
const username =
|
|
781
|
-
|
|
782
|
-
})).trim();
|
|
783
|
-
return {
|
|
784
|
-
...remoteServer,
|
|
785
|
-
config: {
|
|
786
|
-
...remoteServer.config,
|
|
787
|
-
...username ? { username } : {}
|
|
788
|
-
}
|
|
789
|
-
};
|
|
759
|
+
const username = await this.#ask(`SSH username for ${remoteServer.config.host} (optional): `);
|
|
760
|
+
return { ...remoteServer, config: { ...remoteServer.config, ...username ? { username } : {} } };
|
|
790
761
|
}
|
|
791
762
|
#getRemoteEnvArchivePath() {
|
|
792
763
|
return `${this.#getRemoteEnvArchiveDir()}/env.tar`;
|
|
@@ -796,7 +767,7 @@ class CloudRunner extends runner("cloud") {
|
|
|
796
767
|
return `~/secrets/${repoName}`;
|
|
797
768
|
}
|
|
798
769
|
#getScpTarget(config, remotePath) {
|
|
799
|
-
return `${config
|
|
770
|
+
return `${this.#getSshTarget(config)}:${remotePath}`;
|
|
800
771
|
}
|
|
801
772
|
#getSshTarget(config) {
|
|
802
773
|
return `${config.username ? `${config.username}@` : ""}${config.host}`;
|
|
@@ -808,9 +779,8 @@ class CloudRunner extends runner("cloud") {
|
|
|
808
779
|
return [...config.port ? ["-p", config.port.toString()] : [], this.#getSshTarget(config), command];
|
|
809
780
|
}
|
|
810
781
|
async login(host, workspace) {
|
|
811
|
-
const
|
|
812
|
-
const
|
|
813
|
-
const self = config.auth ? await cloudApi.getRemoteSelf() : null;
|
|
782
|
+
const cloudApi = await CloudApi.fromHost(workspace, host);
|
|
783
|
+
const self = await cloudApi.getRemoteSelf();
|
|
814
784
|
if (self) {
|
|
815
785
|
Logger.rawLog(chalk2.green(`
|
|
816
786
|
\u2713 Already logged in akan cloud as ${self.nickname}
|
|
@@ -844,7 +814,7 @@ ${chalk2.green("\u27A4")} Authentication Required`));
|
|
|
844
814
|
const accessToken = await cloudApi.getRemoteAuthToken(remoteId);
|
|
845
815
|
const self = await cloudApi.getRemoteSelf();
|
|
846
816
|
if (accessToken && self) {
|
|
847
|
-
await GlobalConfig.setHostConfig({ host:
|
|
817
|
+
await GlobalConfig.setHostConfig({ host: cloudApi.host, auth: { accessToken, self } });
|
|
848
818
|
Logger.rawLog(chalk2.green(`\r\u2713 Authentication successful!`));
|
|
849
819
|
Logger.rawLog(chalk2.green.bold(`
|
|
850
820
|
\u2728 Welcome aboard, ${self.nickname ?? "anonymous"}!`));
|
|
@@ -927,11 +897,12 @@ ${run.format(results)}
|
|
|
927
897
|
}
|
|
928
898
|
async#askWindowsTestTarget() {
|
|
929
899
|
Logger.info("No Windows test target is configured yet; it is saved to ~/.akan/config.json once entered.");
|
|
930
|
-
const
|
|
931
|
-
const
|
|
932
|
-
const
|
|
933
|
-
const
|
|
934
|
-
const
|
|
900
|
+
const required = (value) => !!value.trim();
|
|
901
|
+
const host = await this.#ask("Windows host (ip or name): ", required);
|
|
902
|
+
const user = await this.#ask("SSH user: ", required);
|
|
903
|
+
const identityFile = await this.#ask("SSH private key path: ", required);
|
|
904
|
+
const knownHostsFile = await this.#ask("known_hosts file (optional): ");
|
|
905
|
+
const utmVm = await this.#ask("UTM VM name, to start it and find its ip (optional): ");
|
|
935
906
|
return {
|
|
936
907
|
host,
|
|
937
908
|
user,
|
|
@@ -951,35 +922,22 @@ ${run.format(results)}
|
|
|
951
922
|
const isOfficialRelease = !devPatchVersion;
|
|
952
923
|
const targetVersionPrefix = isOfficialRelease ? `${majorVersion}.${minorVersion}` : `${majorVersion}.${minorVersion}.${patchVersion}`;
|
|
953
924
|
const tag = distTag ?? (isOfficialRelease ? "latest" : patchVersion.split("-").at(1) ?? "dev");
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
const latestPatch = latestPublishedVersion.startsWith(prefix) ? parseInt(latestPublishedVersion.split(".").at(-1) ?? "-1") : -1;
|
|
958
|
-
const nextVersion = `${prefix}.${latestPatch + 1}`;
|
|
959
|
-
return { nextVersion, latestPublishedVersion };
|
|
960
|
-
} catch {
|
|
961
|
-
return { nextVersion: `${prefix}.0`, latestPublishedVersion: null };
|
|
962
|
-
}
|
|
963
|
-
};
|
|
964
|
-
const { nextVersion, latestPublishedVersion } = await getNextVersion(targetVersionPrefix, tag);
|
|
925
|
+
const latestPublishedVersion = await getLatestPackageVersion("akanjs", tag, registry).catch(() => null);
|
|
926
|
+
const latestPatch = latestPublishedVersion?.startsWith(targetVersionPrefix) ? parseInt(latestPublishedVersion.split(".").at(-1) ?? "-1") : -1;
|
|
927
|
+
const nextVersion = `${targetVersionPrefix}.${latestPatch + 1}`;
|
|
965
928
|
Logger.info(`Latest published version of akanjs: ${latestPublishedVersion ?? "none"}`);
|
|
966
929
|
Logger.info(`Next version of akanjs: ${nextVersion}`);
|
|
967
930
|
for (const library of akanPkgs) {
|
|
968
931
|
const packageJson = await workspace.readJson(`pkgs/${library}/package.json`);
|
|
969
|
-
const
|
|
970
|
-
await workspace.writeFile(`pkgs/${library}/package.json`,
|
|
932
|
+
const newPackageJson = this.#normalizeAkanPackageJson(packageJson, library, nextVersion);
|
|
933
|
+
await workspace.writeFile(`pkgs/${library}/package.json`, JSON.stringify(newPackageJson, null, 2));
|
|
971
934
|
const distPackageJson = await workspace.readJson(`dist/pkgs/${library}/package.json`);
|
|
972
935
|
const newDistPackageJson = this.#normalizeAkanPackageJson(distPackageJson, library, nextVersion);
|
|
973
936
|
await workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
|
|
974
937
|
}
|
|
975
|
-
if (confirmPublish) {
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
});
|
|
979
|
-
if (!isDeployConfirmed) {
|
|
980
|
-
Logger.error("Deployment cancelled");
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
938
|
+
if (confirmPublish && !await confirm({ message: "Are you sure you want to deploy the libraries?" })) {
|
|
939
|
+
Logger.error("Deployment cancelled");
|
|
940
|
+
return;
|
|
983
941
|
}
|
|
984
942
|
if (!registry) {
|
|
985
943
|
Logger.info("Logging in to npm...");
|
|
@@ -1015,14 +973,12 @@ ${run.format(results)}
|
|
|
1015
973
|
const rootPackageJson = await workspace.getPackageJson();
|
|
1016
974
|
if (!rootPackageJson.dependencies)
|
|
1017
975
|
throw new Error("No dependencies found in package.json");
|
|
1018
|
-
|
|
1019
|
-
rootPackageJson.dependencies
|
|
1020
|
-
|
|
1021
|
-
rootPackageJson.devDependencies
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
if (rootPackageJson.devDependencies?.["@akanjs/devkit"])
|
|
1025
|
-
rootPackageJson.devDependencies["@akanjs/devkit"] = latestPublishedVersion;
|
|
976
|
+
for (const name of ["akanjs", "@akanjs/devkit"]) {
|
|
977
|
+
if (rootPackageJson.dependencies[name])
|
|
978
|
+
rootPackageJson.dependencies[name] = latestPublishedVersion;
|
|
979
|
+
if (rootPackageJson.devDependencies?.[name])
|
|
980
|
+
rootPackageJson.devDependencies[name] = latestPublishedVersion;
|
|
981
|
+
}
|
|
1026
982
|
await workspace.setPackageJson(rootPackageJson);
|
|
1027
983
|
await workspace.spawn("bun", ["install", ...this.#getRegistryArgs(registryUrl)], {
|
|
1028
984
|
env: this.#getRegistryEnv(registryUrl)
|
|
@@ -1065,9 +1021,7 @@ ${run.format(results)}
|
|
|
1065
1021
|
cwd: workspace.workspaceRoot,
|
|
1066
1022
|
stdio: "inherit"
|
|
1067
1023
|
});
|
|
1068
|
-
await workspace.spawn("tar", ["-xf", envArchivePath], {
|
|
1069
|
-
cwd: workspace.workspaceRoot
|
|
1070
|
-
});
|
|
1024
|
+
await workspace.spawn("tar", ["-xf", envArchivePath], { cwd: workspace.workspaceRoot });
|
|
1071
1025
|
await workspace.remove(envArchivePath);
|
|
1072
1026
|
} catch (error) {
|
|
1073
1027
|
throw new Error(`Failed to download env archive from remote server "${remoteServer.name}"`, { cause: error });
|
|
@@ -1109,9 +1063,7 @@ ${run.format(results)}
|
|
|
1109
1063
|
await workspace.remove(archivePath);
|
|
1110
1064
|
if (envFilePaths.length === 0)
|
|
1111
1065
|
throw new Error(scope ? `No environment files found to archive for ${appNames.join(", ") || "(no apps)"}` : "No environment files found to archive");
|
|
1112
|
-
await workspace.spawn("tar", ["-cf", archivePath, ...envFilePaths], {
|
|
1113
|
-
cwd: workspace.workspaceRoot
|
|
1114
|
-
});
|
|
1066
|
+
await workspace.spawn("tar", ["-cf", archivePath, ...envFilePaths], { cwd: workspace.workspaceRoot });
|
|
1115
1067
|
Logger.info(`Archived ${envFilePaths.length} environment files to ${archivePath}`);
|
|
1116
1068
|
return { files: envFilePaths, path: archivePath };
|
|
1117
1069
|
}
|
|
@@ -14,25 +14,26 @@ class LibSource {
|
|
|
14
14
|
const relative = file.slice(this.#prefix.length);
|
|
15
15
|
return !LibSource.unhashedDirs.includes(relative.split("/")[0] ?? "");
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
if (file !== `${this.#prefix}package.json`)
|
|
20
|
-
return content;
|
|
21
|
-
const manifest = JSON.parse(content);
|
|
17
|
+
static unstamped(manifestContent) {
|
|
18
|
+
const manifest = JSON.parse(manifestContent);
|
|
22
19
|
delete manifest[LibSource.manifestKey];
|
|
23
20
|
return JSON.stringify(manifest);
|
|
24
21
|
}
|
|
25
|
-
async
|
|
26
|
-
const files = (await this.#lib.workspace.listGitFiles([`libs/${this.#lib.name}`], { untracked: true })).filter((file) => this.#isHashed(file));
|
|
22
|
+
static async hashFiles(files, manifestFile, read) {
|
|
27
23
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
28
24
|
for (const file of files) {
|
|
25
|
+
const content = await read(file);
|
|
29
26
|
hasher.update(file);
|
|
30
27
|
hasher.update("\x00");
|
|
31
|
-
hasher.update(
|
|
28
|
+
hasher.update(file === manifestFile ? LibSource.unstamped(content) : content);
|
|
32
29
|
hasher.update("\x00");
|
|
33
30
|
}
|
|
34
31
|
return hasher.digest("hex").slice(0, 32);
|
|
35
32
|
}
|
|
33
|
+
async computeHash() {
|
|
34
|
+
const files = (await this.#lib.workspace.listGitFiles([`libs/${this.#lib.name}`], { untracked: true })).filter((file) => this.#isHashed(file));
|
|
35
|
+
return await LibSource.hashFiles(files, `${this.#prefix}package.json`, (file) => this.#lib.workspace.readFile(file));
|
|
36
|
+
}
|
|
36
37
|
async read() {
|
|
37
38
|
const manifest = await this.#lib.getPackageJson();
|
|
38
39
|
const akan = manifest[LibSource.manifestKey];
|
|
@@ -59,12 +59,8 @@ class CodeAgentStreamPrinter2 {
|
|
|
59
59
|
return;
|
|
60
60
|
this.#streaming = true;
|
|
61
61
|
return this.#write(chalk.dim(event.text));
|
|
62
|
-
case "message":
|
|
63
|
-
return;
|
|
64
62
|
case "tool_start":
|
|
65
63
|
return this.#line(chalk.cyan(`\u2192 ${event.tool.title}`));
|
|
66
|
-
case "tool_progress":
|
|
67
|
-
return;
|
|
68
64
|
case "tool_end":
|
|
69
65
|
return this.#line(CodeAgentStreamPrinter2.#toolEnd(event));
|
|
70
66
|
case "session":
|
|
@@ -73,11 +69,12 @@ class CodeAgentStreamPrinter2 {
|
|
|
73
69
|
if (event.stopReason === "truncated")
|
|
74
70
|
return this.#line(chalk.yellow(codeAgentEventLabel(event)));
|
|
75
71
|
return;
|
|
72
|
+
case "message":
|
|
73
|
+
case "tool_progress":
|
|
76
74
|
case "turn_start":
|
|
77
75
|
case "idle":
|
|
78
76
|
case "queue":
|
|
79
77
|
case "context":
|
|
80
|
-
return;
|
|
81
78
|
case "subagent":
|
|
82
79
|
return;
|
|
83
80
|
case "question":
|