@akanjs/cli 3.0.0-beta.28 → 3.0.0-beta.29
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-7acv4ah8.js → CodeAgent-86q8d13j.js} +2 -2
- package/{CodeTui-9tkh34mj.js → CodeTui-r8tgxsyb.js} +1 -1
- package/akanCode.js +2 -2
- package/{application.command-xpnkyx4z.js → application.command-712jd2z8.js} +2 -2
- package/{applicationBuildRunner-w4917tje.js → applicationBuildRunner-ez37p161.js} +1 -1
- package/{cloud.command-7yd624qd.js → cloud.command-8eegwcsc.js} +3 -3
- package/{cloud.script-25vzkz7b.js → cloud.script-55s1cmz9.js} +3 -3
- package/{code.command-fpx4gzmy.js → code.command-n0c2tyzx.js} +4 -4
- package/{context.command-snn1k5q3.js → context.command-vxf6d7q2.js} +3 -3
- package/{context.runner-nzaf8c98.js → context.runner-70r2fmty.js} +2 -2
- package/guidelines/conventions/conventions.instruction.md +3 -3
- package/guidelines/runtimeRule/runtimeRule.instruction.md +28 -19
- package/{index-vt64c067.js → index-16k7m3cs.js} +1 -1
- package/{index-tfe3711h.js → index-1hs6jrys.js} +70 -23
- package/{index-n9704w6y.js → index-2yvy9ztj.js} +1 -1
- package/{index-52n8xr63.js → index-8ej6r02m.js} +1 -1
- package/{index-9j0kykc6.js → index-g44da4r2.js} +1 -1
- package/{index-ewbek95g.js → index-krwz9ek9.js} +3 -3
- package/{index-0ej0sr6m.js → index-n9gxx7bp.js} +38 -17
- package/index.js +7 -7
- package/{localRegistry.command-f39yk7be.js → localRegistry.command-7dd85czz.js} +2 -2
- package/package.json +3 -3
- package/{subspace.command-0e53tvxk.js → subspace.command-683qxcw9.js} +1 -1
- package/{workspace.command-wypqk2zb.js → workspace.command-jxdm0wrb.js} +5 -5
- package/README.ko.md +0 -72
- package/README.md +0 -88
package/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
17c8586a89cd04b60d3d62ff58838eecd420ba14c959958abb0d7baf5bd6628c
|
package/akanCode.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
CodeMailbox2,
|
|
29
29
|
CodeSessionFork2,
|
|
30
30
|
CodeAgent2
|
|
31
|
-
} from "./index-
|
|
31
|
+
} from "./index-krwz9ek9.js";
|
|
32
32
|
import {
|
|
33
33
|
akanCodeDefaultModel2,
|
|
34
34
|
akanCodeModel2,
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
import {
|
|
40
40
|
SubagentPool2,
|
|
41
41
|
akanCodePaths2
|
|
42
|
-
} from "./index-
|
|
42
|
+
} from "./index-8ej6r02m.js";
|
|
43
43
|
import"./index-7md2g9vw.js";
|
|
44
44
|
import {
|
|
45
45
|
CodeAgentRpcHost2
|
|
@@ -11,12 +11,12 @@ import"./index-52w0fvh8.js";
|
|
|
11
11
|
import"./index-r8gp8zk3.js";
|
|
12
12
|
import {
|
|
13
13
|
getMobileTargetChoices
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-1hs6jrys.js";
|
|
15
15
|
import"./index-48k96p55.js";
|
|
16
16
|
import"./index-qtz88kh0.js";
|
|
17
17
|
import {
|
|
18
18
|
ApplicationScript
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-n9gxx7bp.js";
|
|
20
20
|
import"./index-7md2g9vw.js";
|
|
21
21
|
import"./index-nbg9bfnr.js";
|
|
22
22
|
|
|
@@ -34,7 +34,7 @@ var createServerEnvPlugin = ({ envDir, environment, environments }) => {
|
|
|
34
34
|
build.onLoad({ filter }, async (args) => {
|
|
35
35
|
const name = path.basename(args.path, ".ts").slice("env.server.".length);
|
|
36
36
|
const { exports } = new Bun.Transpiler({ loader: "ts" }).scan(await Bun.file(args.path).text());
|
|
37
|
-
const message = `env/env.server.${name}.ts is not in this build: \`akan build\` bundles the server env of AKAN_PUBLIC_ENV=${environment} alone, the environment its image runs.
|
|
37
|
+
const message = `env/env.server.${name}.ts is not in this build: \`akan build\` bundles the server env of AKAN_PUBLIC_ENV=${environment} alone, the environment its image runs. To run ${name}, build for it: AKAN_PUBLIC_ENV=${name} in the workspace's .env, which outranks the shell, or --env ${name} on a desktop or mobile build.`;
|
|
38
38
|
return {
|
|
39
39
|
loader: "js",
|
|
40
40
|
contents: [
|
|
@@ -12,15 +12,15 @@ import {
|
|
|
12
12
|
PlatformTestRun
|
|
13
13
|
} from "./index-rrt9pnb4.js";
|
|
14
14
|
import"./index-48k96p55.js";
|
|
15
|
+
import"./index-1hs6jrys.js";
|
|
15
16
|
import"./index-qtz88kh0.js";
|
|
16
|
-
import"./index-
|
|
17
|
-
import"./index-tfe3711h.js";
|
|
17
|
+
import"./index-n9gxx7bp.js";
|
|
18
18
|
import"./index-7md2g9vw.js";
|
|
19
19
|
import"./index-2ahj896a.js";
|
|
20
20
|
import"./index-k7809wmg.js";
|
|
21
21
|
import {
|
|
22
22
|
CloudScript2
|
|
23
|
-
} from "./index-
|
|
23
|
+
} from "./index-g44da4r2.js";
|
|
24
24
|
import"./index-nbg9bfnr.js";
|
|
25
25
|
|
|
26
26
|
// pkgs/@akanjs/cli/cloud/cloud.command.ts
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
CloudScript2
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-g44da4r2.js";
|
|
5
5
|
import"./index-rrt9pnb4.js";
|
|
6
6
|
import"./index-k7809wmg.js";
|
|
7
|
-
import"./index-
|
|
7
|
+
import"./index-n9gxx7bp.js";
|
|
8
8
|
import"./index-nbg9bfnr.js";
|
|
9
9
|
import"./index-qtz88kh0.js";
|
|
10
|
-
import"./index-
|
|
10
|
+
import"./index-1hs6jrys.js";
|
|
11
11
|
import"./index-94s080qm.js";
|
|
12
12
|
import"./index-b68zfsvz.js";
|
|
13
13
|
import"./index-7md2g9vw.js";
|
|
@@ -19,7 +19,7 @@ class CodeRunner extends runner("code") {
|
|
|
19
19
|
async serve(options, listen) {
|
|
20
20
|
await import("./consoleToStderr-h5bryj94.js");
|
|
21
21
|
const [{ CodeAgent }, { CodeAgentRpcHost }, { CodeAgentRpcListener }] = await Promise.all([
|
|
22
|
-
import("./CodeAgent-
|
|
22
|
+
import("./CodeAgent-86q8d13j.js"),
|
|
23
23
|
import("./CodeAgentRpcHost-p7h6n2hp.js"),
|
|
24
24
|
import("./CodeAgentRpcListener-7p7z5dd7.js")
|
|
25
25
|
]);
|
|
@@ -34,8 +34,8 @@ class CodeRunner extends runner("code") {
|
|
|
34
34
|
}
|
|
35
35
|
async tui(options, seed) {
|
|
36
36
|
const [{ CodeAgent }, { CodeTui }] = await Promise.all([
|
|
37
|
-
import("./CodeAgent-
|
|
38
|
-
import("./CodeTui-
|
|
37
|
+
import("./CodeAgent-86q8d13j.js"),
|
|
38
|
+
import("./CodeTui-r8tgxsyb.js")
|
|
39
39
|
]);
|
|
40
40
|
const agentOptions = await CodeRunner.#agentOptions(options, false);
|
|
41
41
|
let resume = options.resume;
|
|
@@ -60,7 +60,7 @@ class CodeRunner extends runner("code") {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
async run(prompt, options) {
|
|
63
|
-
const { CodeAgent } = await import("./CodeAgent-
|
|
63
|
+
const { CodeAgent } = await import("./CodeAgent-86q8d13j.js");
|
|
64
64
|
const agent = await CodeAgent.create(await CodeRunner.#agentOptions(options, false));
|
|
65
65
|
const printer = new CodeAgentStreamPrinter2({ json: options.json, thinking: options.thinking });
|
|
66
66
|
agent.on((event) => printer.print(event));
|
|
@@ -8,8 +8,8 @@ import"./index-r8gp8zk3.js";
|
|
|
8
8
|
import"./index-hj6w4ka1.js";
|
|
9
9
|
import"./index-2s2e5qnd.js";
|
|
10
10
|
import"./index-0pqzrbpr.js";
|
|
11
|
-
import"./index-
|
|
12
|
-
import"./index-
|
|
11
|
+
import"./index-16k7m3cs.js";
|
|
12
|
+
import"./index-1hs6jrys.js";
|
|
13
13
|
import"./index-zzvvc845.js";
|
|
14
14
|
import"./index-2z30v4k5.js";
|
|
15
15
|
import"./index-ss828r32.js";
|
|
@@ -19,7 +19,7 @@ import"./index-2ctqegdm.js";
|
|
|
19
19
|
import"./index-h9ed99ax.js";
|
|
20
20
|
import {
|
|
21
21
|
ContextScript
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-2yvy9ztj.js";
|
|
23
23
|
|
|
24
24
|
// pkgs/@akanjs/cli/context/context.command.ts
|
|
25
25
|
class ContextCommand extends command("context", [ContextScript], ({ public: target }) => ({
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
ContextRunner2
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-16k7m3cs.js";
|
|
5
5
|
import"./index-h9ed99ax.js";
|
|
6
6
|
import"./index-2ctqegdm.js";
|
|
7
7
|
import"./index-20r2g1t3.js";
|
|
8
8
|
import"./index-2z30v4k5.js";
|
|
9
9
|
import"./index-genegfnt.js";
|
|
10
10
|
import"./index-ss828r32.js";
|
|
11
|
-
import"./index-
|
|
11
|
+
import"./index-1hs6jrys.js";
|
|
12
12
|
import"./index-0pqzrbpr.js";
|
|
13
13
|
import"./index-2s2e5qnd.js";
|
|
14
14
|
import"./index-zzvvc845.js";
|
|
@@ -356,9 +356,9 @@ Full contract: `get_guideline` with `runtimeRule`, or `akan guideline show runti
|
|
|
356
356
|
that builds itself at install goes in `trustedDependencies`, which the image honours too. Carry a static LGPL ffmpeg: a `--enable-nonfree` build may
|
|
357
357
|
not be redistributed. A file the user picks with `filePicker.pickFiles({ forServer: true })` reaches it as a
|
|
358
358
|
grant, never a copy or a path: `NativeFile.resolve(grant, "read")` in `akanjs/server` asks the shell for it.
|
|
359
|
-
What it carries is readable on the user's computer — `private
|
|
360
|
-
`--env` and
|
|
361
|
-
`AKAN_APP_DIR`, never `process.cwd()`.
|
|
359
|
+
What it carries is readable on the user's computer — `private/` (each lib's too, under `private/libs/<lib>`), the
|
|
360
|
+
one `env.server.<env>.ts` of its `--env` and its libs' server env defaults (`env.server.testing.ts`) — and it has
|
|
361
|
+
no `public/`: read runtime files from `AKAN_APP_DIR`, never `process.cwd()`.
|
|
362
362
|
- **`assets: { pruneFonts, keepFonts }`** trims from the `dist` copy of `public/` the fonts nothing reads; source
|
|
363
363
|
trees are never touched. A font with `optimize` on is a build input, not a runtime asset. `keepFonts` belongs to
|
|
364
364
|
the `akan.config.ts` that owns the font, written against that scope's own `public/`.
|
|
@@ -187,27 +187,34 @@ const config: AppConfig = { docker: "FROM oven/bun:1-slim\n…" }; // verbatim,
|
|
|
187
187
|
## A Desktop App's Server — `bin` And `trustedDependencies`
|
|
188
188
|
|
|
189
189
|
A mobile target that declares `native: { desktop: { server: true } }` carries the app's server: `akan build-desktop`,
|
|
190
|
-
`start-desktop --release` and `publish-update` put the backend `akan build` made into the app — the
|
|
191
|
-
`akan.build.json
|
|
192
|
-
|
|
190
|
+
`start-desktop --release` and `publish-update` put the backend `akan build` made into the app — everything the
|
|
191
|
+
backend build wrote (the `.js`, `akan.build.json`, `private/`, a bundled package's `.node`, `.wasm` or file asset)
|
|
192
|
+
but the Dockerfile, the RSC worker, the console, `csr/` and `public/` — and install its packages first with
|
|
193
|
+
`bun install --production --prefer-offline`, before `akan build` runs. `start-desktop` without `--release` starts
|
|
194
|
+
`akan start` beside the app when no dev server of this checkout answers. The setting is the app's backend,
|
|
193
195
|
so it does not change under an installed app: an update whose release carries a server when the app has none, or
|
|
194
196
|
none when it has one, is refused, and switching means a reinstall.
|
|
195
197
|
A desktop app builds only for the computer it is built on, so every native addon's prebuild matches the one it runs
|
|
196
198
|
on. It runs as an API-only edge server on SQLite, on a loopback port the launcher picks — the last session's when
|
|
197
199
|
it is free, which is not a guarantee, so a provider that needs an exact redirect URI signs in through a cloud
|
|
198
|
-
server's adapter. It
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
200
|
+
server's adapter. It refuses a `Host` other than its own, but any program on the computer can still call that port:
|
|
201
|
+
guard its endpoints as a network server's. It runs in one process, so a `main.ts` or an env asking for replicas (`replica`,
|
|
202
|
+
`solo: false`, `AKAN_SOLO=false`, `AKAN_REPLICA`, `AKAN_COMMAND_TYPE=start`) does not boot in the app. Its data lives in the app's local data folder (`%LOCALAPPDATA%\<id>\server`
|
|
203
|
+
on Windows, never Roaming; `server-debug` for a `--debug` build). It trusts the OS certificate store, and of the
|
|
204
|
+
user's environment it takes a fixed set and nothing else: the system's own (`PATH`, `HOME`, the temp folder, `LANG`,
|
|
205
|
+
`TZ`, Windows' folders and `ComSpec`), the desktop session a `bin` tool needs for the screen or the audio server
|
|
206
|
+
(`DISPLAY`, `XAUTHORITY`, `WAYLAND_DISPLAY`, the session bus, `PULSE_*`, `XDG_*`), and the proxy and CA variables
|
|
207
|
+
(`HTTP(S)_PROXY`, `NO_PROXY`, `NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE`).
|
|
208
|
+
|
|
209
|
+
**Everything it carries is on the user's computer, readable.** That is `private/` as it is — each lib's too, under
|
|
210
|
+
`private/libs/<lib>` — and the server env of the one environment the build is for (`--env`: `debug` for
|
|
211
|
+
`build-desktop`, `local` for `start-desktop --release`, `main` for `publish-update`, unless named): the build keeps
|
|
212
|
+
`env/env.server.<env>.ts` and swaps every other environment's file for exports that refuse to be read. The server env
|
|
213
|
+
each lib exports as its defaults (the lib's `env.server.testing.ts`, spread into every environment by
|
|
214
|
+
`env.server.type.ts`) ships as well. Keep a key in those files only if every user of the app may hold it; a secret the
|
|
215
|
+
server needs belongs to a cloud server its adapter calls. There is no `public/`: a file the server reads at runtime
|
|
216
|
+
goes in `private/` and is read from `AKAN_APP_DIR` (the folder `server.js` sits in), never from `process.cwd()`, which
|
|
217
|
+
is the app's data folder.
|
|
211
218
|
|
|
212
219
|
**Nothing from `docker` reaches it.** `preRuns`, `postRuns` and a whole Dockerfile install into a Linux image the
|
|
213
220
|
desktop app never runs in, and the build warns when an app has them and carries no `bin`. What the server needs
|
|
@@ -265,9 +272,11 @@ Windows, VAAPI or NVENC on Linux. Codec patents are a separate question to settl
|
|
|
265
272
|
**A server bound to its machine stays a service.** A server that needs a whole environment — ROS, system services,
|
|
266
273
|
root to change the network or the clock — runs as a service on that machine (the image), and the desktop app's
|
|
267
274
|
target leaves `desktop.server` off, pinned to it with `AKAN_PUBLIC_SERVER_URL` at build time. A carried server runs
|
|
268
|
-
as the signed-in user and stops with the app, and so does what it started
|
|
269
|
-
own process group
|
|
270
|
-
|
|
275
|
+
as the signed-in user and stops with the app, and so does what it started. On macOS and Linux the server leads its
|
|
276
|
+
own process group: quitting the app ends the group, and when the app was killed or crashed — even while the server
|
|
277
|
+
was still starting — the server sees its parent gone and ends the group itself, SIGTERM first and SIGKILL a second
|
|
278
|
+
later for whatever ignored it. On Windows the job object ends them all with the app. A process started `detached`
|
|
279
|
+
leaves the group, or the job, and keeps running.
|
|
271
280
|
|
|
272
281
|
**A file the user picks reaches the server as a grant, never as a copy or a path.** With `native.plugins:
|
|
273
282
|
["file-picker"]` on the target, `filePicker.pickFiles({ forServer: true })` (also `pickDirectory` and `saveFile`,
|
|
@@ -80,7 +80,6 @@ var targetHtmlFilename = (target) => {
|
|
|
80
80
|
};
|
|
81
81
|
|
|
82
82
|
// pkgs/@akanjs/devkit/mobile/nativeApp.ts
|
|
83
|
-
import { mkdir as mkdir3 } from "fs/promises";
|
|
84
83
|
import path6 from "path";
|
|
85
84
|
|
|
86
85
|
// pkgs/@akanjs/devkit/mobile/desktopBin.ts
|
|
@@ -573,11 +572,14 @@ ${html}`;
|
|
|
573
572
|
${script}${html.slice(at)}`;
|
|
574
573
|
}
|
|
575
574
|
static #targetTag = "<script>window.__AKAN_MOBILE_TARGET__=";
|
|
575
|
+
async clear() {
|
|
576
|
+
await rm2(this.dir, { recursive: true, force: true });
|
|
577
|
+
await mkdir2(this.dir, { recursive: true });
|
|
578
|
+
}
|
|
576
579
|
async assemble(target, { html, publicDir, fontsDir }) {
|
|
577
580
|
if (!await Bun.file(html).exists())
|
|
578
581
|
throw new Error(`CSR html for mobile target '${target.name}' not found: ${html}`);
|
|
579
|
-
await
|
|
580
|
-
await mkdir2(this.dir, { recursive: true });
|
|
582
|
+
await this.clear();
|
|
581
583
|
if (publicDir && await NativeWebDir.#isDir(publicDir))
|
|
582
584
|
await cp(publicDir, this.dir, { recursive: true });
|
|
583
585
|
if (fontsDir && await NativeWebDir.#isDir(fontsDir))
|
|
@@ -615,6 +617,9 @@ class NativeApp {
|
|
|
615
617
|
outDir(platform) {
|
|
616
618
|
return path6.join(this.targetRoot, "native", platform);
|
|
617
619
|
}
|
|
620
|
+
devOutDir(platform) {
|
|
621
|
+
return path6.join(this.targetRoot, "dev", platform);
|
|
622
|
+
}
|
|
618
623
|
async assembleWeb() {
|
|
619
624
|
const dist = this.app.dist.cwdPath;
|
|
620
625
|
return await this.web.assemble(this.target.config, {
|
|
@@ -658,12 +663,15 @@ class NativeApp {
|
|
|
658
663
|
]);
|
|
659
664
|
for (const warning of warnings)
|
|
660
665
|
this.app.logger.warn(warning);
|
|
666
|
+
this.#assertValid(api, config);
|
|
667
|
+
return { api, config };
|
|
668
|
+
}
|
|
669
|
+
#assertValid(api, config) {
|
|
661
670
|
const problems = api.validateConfig(config, { appDir: this.app.cwdPath });
|
|
662
671
|
if (problems.length)
|
|
663
672
|
throw new Error(`Mobile target '${this.target.name}' makes an invalid native config:
|
|
664
673
|
- ${problems.join(`
|
|
665
674
|
- `)}`);
|
|
666
|
-
return { api, config };
|
|
667
675
|
}
|
|
668
676
|
#appLine = (line) => {
|
|
669
677
|
const read = NativeAppLine.read(line, { verbose: Executor.verbose });
|
|
@@ -672,12 +680,12 @@ class NativeApp {
|
|
|
672
680
|
else
|
|
673
681
|
this.app.logger[read.level](read.message);
|
|
674
682
|
};
|
|
675
|
-
#task(platform, config) {
|
|
683
|
+
#task(platform, config, outDir = this.outDir(platform)) {
|
|
676
684
|
return {
|
|
677
685
|
appDir: this.app.cwdPath,
|
|
678
686
|
config,
|
|
679
687
|
platform,
|
|
680
|
-
outDir
|
|
688
|
+
outDir,
|
|
681
689
|
envFiles: false,
|
|
682
690
|
skipWebBuild: true,
|
|
683
691
|
log: (event) => {
|
|
@@ -723,10 +731,10 @@ class NativeApp {
|
|
|
723
731
|
const boot = { steps: [], lines: [] };
|
|
724
732
|
this.#boot = boot;
|
|
725
733
|
try {
|
|
726
|
-
await
|
|
734
|
+
await this.web.clear();
|
|
727
735
|
const [{ api, config }, { api: routes }] = await Promise.all([this.prepare(platform), this.app.getConfig()]);
|
|
728
736
|
const session = await api.dev({
|
|
729
|
-
...this.#task(platform, config),
|
|
737
|
+
...this.#task(platform, config, this.devOutDir(platform)),
|
|
730
738
|
upstream,
|
|
731
739
|
hmrPath: "/_akan/hmr",
|
|
732
740
|
wsPaths: [`${routes.prefix}${routes.websocketPrefix}`],
|
|
@@ -772,8 +780,7 @@ class NativeApp {
|
|
|
772
780
|
}
|
|
773
781
|
async publishUpdate(platform, { channel, server } = {}) {
|
|
774
782
|
NativeApp.#assertServerPlatform(platform, server);
|
|
775
|
-
|
|
776
|
-
throw new Error(`Mobile target '${this.target.name}' has no updates: { url, publicKey } in akan.config.ts; \`akan update-keygen ${this.app.name}\` prints the key.`);
|
|
783
|
+
this.#assertUpdates();
|
|
777
784
|
await this.assembleWeb();
|
|
778
785
|
const { api, config } = await this.prepare(platform, server);
|
|
779
786
|
return await api.publishUpdate({
|
|
@@ -783,6 +790,32 @@ class NativeApp {
|
|
|
783
790
|
...channel ? { channel } : {}
|
|
784
791
|
});
|
|
785
792
|
}
|
|
793
|
+
async assertPublishable(platform, { channel, server = false } = {}) {
|
|
794
|
+
this.#assertUpdates();
|
|
795
|
+
const [api, { config }] = await Promise.all([
|
|
796
|
+
NativeApi.load(this.app.cwdPath),
|
|
797
|
+
this.config({ platform, stageBin: false })
|
|
798
|
+
]);
|
|
799
|
+
this.#assertValid(api, config);
|
|
800
|
+
try {
|
|
801
|
+
api.checkPublishUpdate({
|
|
802
|
+
appDir: this.app.cwdPath,
|
|
803
|
+
config,
|
|
804
|
+
platform,
|
|
805
|
+
out: this.updatesDir,
|
|
806
|
+
server,
|
|
807
|
+
...channel ? { channel } : {}
|
|
808
|
+
});
|
|
809
|
+
} catch (error) {
|
|
810
|
+
throw new Error(`Mobile target '${this.target.name}': ${error instanceof Error ? error.message : String(error)}`, {
|
|
811
|
+
cause: error
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
#assertUpdates() {
|
|
816
|
+
if (!this.target.config.updates)
|
|
817
|
+
throw new Error(`Mobile target '${this.target.name}' has no updates: { url, publicKey } in akan.config.ts; \`akan update-keygen ${this.app.name}\` prints the key.`);
|
|
818
|
+
}
|
|
786
819
|
async updateKeygen(platform) {
|
|
787
820
|
const [api, { config }] = await Promise.all([
|
|
788
821
|
NativeApi.load(this.app.cwdPath),
|
|
@@ -874,11 +907,20 @@ var isPlaceholderAppId = (appId) => {
|
|
|
874
907
|
return normalized.split(".").some((segment) => placeholderAppIdSegment.test(segment));
|
|
875
908
|
};
|
|
876
909
|
// pkgs/@akanjs/devkit/mobile/desktopServerStage.ts
|
|
877
|
-
import { cp as cp2, mkdir as
|
|
910
|
+
import { cp as cp2, mkdir as mkdir3, readdir as readdir2, rm as rm3, writeFile as writeFile2 } from "fs/promises";
|
|
878
911
|
import path7 from "path";
|
|
879
912
|
class DesktopServerStage {
|
|
880
913
|
app;
|
|
881
|
-
static
|
|
914
|
+
static uncarried = new Set([
|
|
915
|
+
"Dockerfile",
|
|
916
|
+
"package.json",
|
|
917
|
+
"rscWorker.js",
|
|
918
|
+
"console.js",
|
|
919
|
+
"console-runtime.js",
|
|
920
|
+
"csr",
|
|
921
|
+
"public",
|
|
922
|
+
".akan"
|
|
923
|
+
]);
|
|
882
924
|
static rscRenderer = "react-server-dom-webpack";
|
|
883
925
|
dir;
|
|
884
926
|
constructor(app) {
|
|
@@ -920,22 +962,27 @@ class DesktopServerStage {
|
|
|
920
962
|
const dependencies = Object.entries(built.dependencies ?? {}).filter(([name]) => config.externalLibs.includes(name) || name !== DesktopServerStage.rscRenderer && !otherDrivers.has(name));
|
|
921
963
|
return { ...built, dependencies: Object.fromEntries(dependencies) };
|
|
922
964
|
}
|
|
923
|
-
async
|
|
965
|
+
async install() {
|
|
924
966
|
const config = await this.app.getConfig();
|
|
925
967
|
DesktopServerStage.assertCarriable(config);
|
|
926
|
-
const dist = this.app.dist.cwdPath;
|
|
927
968
|
await rm3(this.dir, { recursive: true, force: true });
|
|
928
|
-
await
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
969
|
+
await mkdir3(this.dir, { recursive: true });
|
|
970
|
+
await writeFile2(path7.join(this.dir, "package.json"), JSON.stringify(DesktopServerStage.packageJson(config, config.getProductionPackageJson()), null, 2));
|
|
971
|
+
try {
|
|
972
|
+
await this.app.spawn(process.execPath, ["install", "--production", "--prefer-offline"], { cwd: this.dir });
|
|
973
|
+
} catch (error) {
|
|
974
|
+
throw new Error(`The desktop app's server could not install its packages in ${this.dir}: it needs the npm registry, or a Bun cache that already holds every one of them.
|
|
975
|
+
${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
934
976
|
}
|
|
935
|
-
const built = await Bun.file(path7.join(dist, "package.json")).json();
|
|
936
|
-
await writeFile2(path7.join(this.dir, "package.json"), JSON.stringify(DesktopServerStage.packageJson(config, built), null, 2));
|
|
937
|
-
await this.app.spawn(process.execPath, ["install", "--production"], { cwd: this.dir });
|
|
938
977
|
await rm3(path7.join(this.dir, "node_modules", ".bin"), { recursive: true, force: true });
|
|
978
|
+
}
|
|
979
|
+
async prepare(environment) {
|
|
980
|
+
const config = await this.app.getConfig();
|
|
981
|
+
const dist = this.app.dist.cwdPath;
|
|
982
|
+
await mkdir3(this.dir, { recursive: true });
|
|
983
|
+
for (const name of await readdir2(dist))
|
|
984
|
+
if (!DesktopServerStage.uncarried.has(name))
|
|
985
|
+
await cp2(path7.join(dist, name), path7.join(this.dir, name), { recursive: true });
|
|
939
986
|
const scanInfo = this.app.getScanInfo({ allowEmpty: true }) ?? await this.app.scan({ write: false });
|
|
940
987
|
const carried = [...DesktopBin.select(config, scanInfo.getLibs()).keys()];
|
|
941
988
|
const notice = DesktopServerStage.imageStepsNotice(config, carried);
|
|
@@ -116,7 +116,7 @@ class SubagentPool2 {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
async#run(id, kind, prompt, signal) {
|
|
119
|
-
const { CodeAgent } = await import("./CodeAgent-
|
|
119
|
+
const { CodeAgent } = await import("./CodeAgent-86q8d13j.js");
|
|
120
120
|
const budget = this.#options.parent.tools.subagent;
|
|
121
121
|
const child = SubagentPool2.childOf(this.#options.parent, kind);
|
|
122
122
|
const agent = await CodeAgent.create({
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
akanCodePaths2,
|
|
5
5
|
McpServerConfig,
|
|
6
6
|
McpSignIn
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-8ej6r02m.js";
|
|
8
8
|
import {
|
|
9
9
|
stripAnsi
|
|
10
10
|
} from "./index-7md2g9vw.js";
|
|
@@ -511,7 +511,7 @@ class AkanToolPack2 {
|
|
|
511
511
|
return { name: "akan-tools", factory: async (pi) => await this.#register(pi) };
|
|
512
512
|
}
|
|
513
513
|
async names() {
|
|
514
|
-
const { ContextRunner } = await import("./context.runner-
|
|
514
|
+
const { ContextRunner } = await import("./context.runner-70r2fmty.js");
|
|
515
515
|
return [
|
|
516
516
|
...new ContextRunner().listMcpTools(this.#options.mode).map((tool) => tool.name),
|
|
517
517
|
AkanToolPack2.verifyToolName
|
|
@@ -519,7 +519,7 @@ class AkanToolPack2 {
|
|
|
519
519
|
}
|
|
520
520
|
static verifyToolName = "akan_verify";
|
|
521
521
|
async#register(pi) {
|
|
522
|
-
const { ContextRunner } = await import("./context.runner-
|
|
522
|
+
const { ContextRunner } = await import("./context.runner-70r2fmty.js");
|
|
523
523
|
const runner = new ContextRunner;
|
|
524
524
|
const guidelineNames = await AkanToolPack2.#guidelineNames();
|
|
525
525
|
for (const tool of runner.listMcpTools(this.#options.mode, { guidelineNames })) {
|
|
@@ -44,15 +44,15 @@ import {
|
|
|
44
44
|
LibExecutor,
|
|
45
45
|
PkgExecutor
|
|
46
46
|
} from "./index-r8gp8zk3.js";
|
|
47
|
-
import {
|
|
48
|
-
LibraryScript
|
|
49
|
-
} from "./index-qtz88kh0.js";
|
|
50
47
|
import {
|
|
51
48
|
DesktopServerStage,
|
|
52
49
|
resolveMobileTargets,
|
|
53
50
|
resolveAppId,
|
|
54
51
|
NativeApp
|
|
55
|
-
} from "./index-
|
|
52
|
+
} from "./index-1hs6jrys.js";
|
|
53
|
+
import {
|
|
54
|
+
LibraryScript
|
|
55
|
+
} from "./index-qtz88kh0.js";
|
|
56
56
|
import {
|
|
57
57
|
stripAnsi
|
|
58
58
|
} from "./index-7md2g9vw.js";
|
|
@@ -69,6 +69,7 @@ import { confirm } from "@inquirer/prompts";
|
|
|
69
69
|
import { Logger as Logger6 } from "akanjs/common";
|
|
70
70
|
|
|
71
71
|
// pkgs/@akanjs/cli/application/application.runner.ts
|
|
72
|
+
import { realpathSync } from "fs";
|
|
72
73
|
import path5 from "path";
|
|
73
74
|
|
|
74
75
|
// pkgs/@akanjs/devkit/akanApp/akanApp.host.ts
|
|
@@ -860,6 +861,8 @@ class AkanAppHost {
|
|
|
860
861
|
message: msg.data.message
|
|
861
862
|
});
|
|
862
863
|
this.#sendOrQueueBuildStatus(status);
|
|
864
|
+
if (!status.ok)
|
|
865
|
+
this.#emitDevEvent("failed", status.message);
|
|
863
866
|
return;
|
|
864
867
|
}
|
|
865
868
|
if (backendMsgTypeSet.has(msg.type))
|
|
@@ -1864,7 +1867,7 @@ ${uniqueCandidates.map((candidate) => ` - ${candidate}`).join(`
|
|
|
1864
1867
|
|
|
1865
1868
|
// pkgs/@akanjs/cli/application/application.runner.ts
|
|
1866
1869
|
import { Logger as Logger3 } from "akanjs/common";
|
|
1867
|
-
var loadBuildRunner = async () => (await import("./applicationBuildRunner-
|
|
1870
|
+
var loadBuildRunner = async () => (await import("./applicationBuildRunner-ez37p161.js")).ApplicationBuildRunner;
|
|
1868
1871
|
var loadPrompts = async () => await import("@inquirer/prompts");
|
|
1869
1872
|
|
|
1870
1873
|
class ApplicationRunner extends runner("application") {
|
|
@@ -2087,7 +2090,7 @@ try {
|
|
|
2087
2090
|
return;
|
|
2088
2091
|
}
|
|
2089
2092
|
const upstream = `http://localhost:${await app.getDevPort()}`;
|
|
2090
|
-
if (!await ApplicationRunner.answers(upstream, app.name))
|
|
2093
|
+
if (!await ApplicationRunner.answers(upstream, app.name, app.workspace.workspaceRoot))
|
|
2091
2094
|
throw new Error(`No dev server answers on ${upstream}; run \`akan start ${app.name}\` first.`);
|
|
2092
2095
|
const { i18n } = await app.getConfig();
|
|
2093
2096
|
const session = await nativeApp.dev(platform, { upstream, lang: i18n.defaultLocale, ...selection });
|
|
@@ -2109,20 +2112,33 @@ try {
|
|
|
2109
2112
|
throw new Error(`start-${platform === "ios" || platform === "android" ? platform : "desktop"} runs one mobile target at a time; pass --target <name>.`);
|
|
2110
2113
|
return mobileTarget;
|
|
2111
2114
|
}
|
|
2112
|
-
static async answers(url, appName) {
|
|
2115
|
+
static async answers(url, appName, workspaceRoot) {
|
|
2113
2116
|
const signal = AbortSignal.timeout(3000);
|
|
2114
2117
|
const health = await fetch(new URL("/_akan/app/health", url), { signal }).catch(() => null);
|
|
2115
2118
|
if (!health)
|
|
2116
2119
|
return false;
|
|
2117
2120
|
const info = await fetch(new URL("/_akan/app/info", url), { signal }).then(async (res) => res.ok ? await res.json() : null).catch(() => null);
|
|
2118
|
-
if (info?.appName === appName)
|
|
2119
|
-
return true;
|
|
2120
2121
|
const stopIt = `Stop it (\`akan start ${appName} --kill\` takes the port over) or give ${appName} another port with AKAN_DEV_PORT`;
|
|
2122
|
+
if (info?.appName === appName) {
|
|
2123
|
+
if (typeof info.workspaceRoot !== "string" || ApplicationRunner.#sameCheckout(info.workspaceRoot, workspaceRoot))
|
|
2124
|
+
return true;
|
|
2125
|
+
throw new Error(`${url} is the dev server of ${appName} in ${info.workspaceRoot}, not in ${workspaceRoot}. ${stopIt}.`);
|
|
2126
|
+
}
|
|
2121
2127
|
if (typeof info?.appName === "string")
|
|
2122
2128
|
throw new Error(`${url} is the dev server of ${info.appName}, not ${appName}. ${stopIt}.`);
|
|
2123
2129
|
const { pid } = await health.json().catch(() => null) ?? {};
|
|
2124
2130
|
throw new Error(typeof pid === "number" ? `${url} is an akan dev server (pid ${pid}) too old to say which app it serves. ${stopIt}.` : `${url} answers, but not as an akan dev server. Stop what holds the port or give ${appName} another port with AKAN_DEV_PORT.`);
|
|
2125
2131
|
}
|
|
2132
|
+
static #sameCheckout(reported, own) {
|
|
2133
|
+
const canonical = (root) => {
|
|
2134
|
+
try {
|
|
2135
|
+
return realpathSync.native(root);
|
|
2136
|
+
} catch {
|
|
2137
|
+
return path5.resolve(root);
|
|
2138
|
+
}
|
|
2139
|
+
};
|
|
2140
|
+
return canonical(reported) === canonical(own);
|
|
2141
|
+
}
|
|
2126
2142
|
async releaseIos(app, { target, env = "main", teamId, adHoc = false } = {}) {
|
|
2127
2143
|
const targets = await resolveMobileTargets(app, target);
|
|
2128
2144
|
await this.#buildMobileCsr(app, env);
|
|
@@ -2176,6 +2192,11 @@ try {
|
|
|
2176
2192
|
async publishUpdate(app, platform, { target, env = "main", channel } = {}) {
|
|
2177
2193
|
const targets = await resolveMobileTargets(app, target);
|
|
2178
2194
|
const nativePlatform = platform === "desktop" ? NativeApp.desktopPlatform() : platform;
|
|
2195
|
+
for (const mobileTarget of targets)
|
|
2196
|
+
await new NativeApp(app, mobileTarget, env).assertPublishable(nativePlatform, {
|
|
2197
|
+
server: ApplicationRunner.carriesServer(mobileTarget, nativePlatform),
|
|
2198
|
+
...channel ? { channel } : {}
|
|
2199
|
+
});
|
|
2179
2200
|
const carried = await this.#stageMobile(app, nativePlatform, targets, env);
|
|
2180
2201
|
for (const mobileTarget of targets) {
|
|
2181
2202
|
const nativeApp = new NativeApp(app, mobileTarget, env);
|
|
@@ -2200,11 +2221,10 @@ try {
|
|
|
2200
2221
|
return platform !== "ios" && platform !== "android" && config.native?.desktop?.server === true;
|
|
2201
2222
|
}
|
|
2202
2223
|
async#stageMobile(app, platform, targets, env) {
|
|
2203
|
-
const
|
|
2204
|
-
|
|
2205
|
-
DesktopServerStage.assertCarriable(await app.getConfig());
|
|
2224
|
+
const stage = targets.some((mobileTarget) => ApplicationRunner.carriesServer(mobileTarget, platform)) ? new DesktopServerStage(app) : null;
|
|
2225
|
+
await stage?.install();
|
|
2206
2226
|
await this.#buildMobileCsr(app, env);
|
|
2207
|
-
return
|
|
2227
|
+
return await stage?.prepare(env);
|
|
2208
2228
|
}
|
|
2209
2229
|
async#buildMobileCsr(app, env) {
|
|
2210
2230
|
const prevEnv = {
|
|
@@ -3343,12 +3363,13 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3343
3363
|
const mobileTarget = await ApplicationRunner.startTarget(app, undefined, options.target);
|
|
3344
3364
|
if (!ApplicationRunner.carriesServer(mobileTarget))
|
|
3345
3365
|
return await this.applicationRunner.startDesktop(app, options);
|
|
3366
|
+
DesktopServerStage.assertCarriable(await app.getConfig());
|
|
3346
3367
|
const upstream = `http://localhost:${await app.getDevPort()}`;
|
|
3347
|
-
if (await ApplicationRunner.answers(upstream, app.name))
|
|
3348
|
-
app.log(`The desktop app follows the dev server on ${upstream}.`);
|
|
3349
|
-
else
|
|
3350
|
-
await this.#startDevServerFor(app, upstream);
|
|
3351
3368
|
try {
|
|
3369
|
+
if (await ApplicationRunner.answers(upstream, app.name, app.workspace.workspaceRoot))
|
|
3370
|
+
app.log(`The desktop app follows the dev server on ${upstream}.`);
|
|
3371
|
+
else
|
|
3372
|
+
await this.#startDevServerFor(app, upstream);
|
|
3352
3373
|
await this.applicationRunner.startDesktop(app, { ...options, interrupt: this.#interrupt });
|
|
3353
3374
|
} finally {
|
|
3354
3375
|
await this.#interrupt.runAll();
|
package/index.js
CHANGED
|
@@ -13,18 +13,18 @@ import path from "path";
|
|
|
13
13
|
|
|
14
14
|
// pkgs/@akanjs/cli/commandModules.ts
|
|
15
15
|
var commandModules = {
|
|
16
|
-
workspace: async () => (await import("./workspace.command-
|
|
16
|
+
workspace: async () => (await import("./workspace.command-jxdm0wrb.js")).WorkspaceCommand,
|
|
17
17
|
agent: async () => (await import("./agent.command-q9bmqrag.js")).AgentCommand,
|
|
18
|
-
code: async () => (await import("./code.command-
|
|
19
|
-
application: async () => (await import("./application.command-
|
|
18
|
+
code: async () => (await import("./code.command-n0c2tyzx.js")).CodeCommand,
|
|
19
|
+
application: async () => (await import("./application.command-712jd2z8.js")).ApplicationCommand,
|
|
20
20
|
library: async () => (await import("./library.command-tz7vnwea.js")).LibraryCommand,
|
|
21
|
-
localRegistry: async () => (await import("./localRegistry.command-
|
|
21
|
+
localRegistry: async () => (await import("./localRegistry.command-7dd85czz.js")).LocalRegistryCommand,
|
|
22
22
|
package: async () => (await import("./package.command-z3epnvas.js")).PackageCommand,
|
|
23
23
|
module: async () => (await import("./module.command-qhc9ns0s.js")).ModuleCommand,
|
|
24
24
|
page: async () => (await import("./page.command-exd2vakz.js")).PageCommand,
|
|
25
|
-
context: async () => (await import("./context.command-
|
|
26
|
-
cloud: async () => (await import("./cloud.command-
|
|
27
|
-
subspace: async () => (await import("./subspace.command-
|
|
25
|
+
context: async () => (await import("./context.command-vxf6d7q2.js")).ContextCommand,
|
|
26
|
+
cloud: async () => (await import("./cloud.command-8eegwcsc.js")).CloudCommand,
|
|
27
|
+
subspace: async () => (await import("./subspace.command-683qxcw9.js")).SubspaceCommand,
|
|
28
28
|
guideline: async () => (await import("./guideline.command-ene55fkr.js")).GuidelineCommand,
|
|
29
29
|
scalar: async () => (await import("./scalar.command-60nxfchc.js")).ScalarCommand,
|
|
30
30
|
primitive: async () => (await import("./primitive.command-0w6cha4j.js")).PrimitiveCommand,
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
PkgExecutor
|
|
11
11
|
} from "./index-r8gp8zk3.js";
|
|
12
12
|
import"./index-48k96p55.js";
|
|
13
|
+
import"./index-1hs6jrys.js";
|
|
13
14
|
import"./index-qtz88kh0.js";
|
|
14
15
|
import {
|
|
15
16
|
ApplicationScript
|
|
16
|
-
} from "./index-
|
|
17
|
-
import"./index-tfe3711h.js";
|
|
17
|
+
} from "./index-n9gxx7bp.js";
|
|
18
18
|
import"./index-7md2g9vw.js";
|
|
19
19
|
import"./index-94s080qm.js";
|
|
20
20
|
import {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/cli",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.29",
|
|
4
4
|
"sourceType": "module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@earendil-works/pi-tui": "0.86.1",
|
|
40
40
|
"@inquirer/prompts": "^8.4.3",
|
|
41
41
|
"@tailwindcss/node": "^4.3.0",
|
|
42
|
-
"akanjs": "3.0.0-beta.
|
|
42
|
+
"akanjs": "3.0.0-beta.29",
|
|
43
43
|
"chalk": "^5.6.2",
|
|
44
44
|
"commander": "^14.0.3",
|
|
45
45
|
"dayjs": "^1.11.20",
|
|
@@ -62,4 +62,4 @@
|
|
|
62
62
|
"bun": {
|
|
63
63
|
"platform": "bun"
|
|
64
64
|
}
|
|
65
|
-
}
|
|
65
|
+
}
|
|
@@ -716,7 +716,7 @@ class SubspaceRunner extends runner("subspace") {
|
|
|
716
716
|
if (!asked)
|
|
717
717
|
return { name: subspace.name, workspaceId, host, apps, libs: [], outcome: "cancelled", files: [] };
|
|
718
718
|
const { libs } = await subspace.slice();
|
|
719
|
-
const { CloudScript } = await import("./cloud.script-
|
|
719
|
+
const { CloudScript } = await import("./cloud.script-55s1cmz9.js");
|
|
720
720
|
const { files } = await CommandContainer.get(CloudScript).uploadEnv(workspace, {
|
|
721
721
|
host,
|
|
722
722
|
workspaceId,
|
|
@@ -39,13 +39,13 @@ import {
|
|
|
39
39
|
AgentScript
|
|
40
40
|
} from "./index-rbeahw6j.js";
|
|
41
41
|
import"./index-48k96p55.js";
|
|
42
|
+
import"./index-1hs6jrys.js";
|
|
42
43
|
import {
|
|
43
44
|
LibraryScript
|
|
44
45
|
} from "./index-qtz88kh0.js";
|
|
45
46
|
import {
|
|
46
47
|
ApplicationScript
|
|
47
|
-
} from "./index-
|
|
48
|
-
import"./index-tfe3711h.js";
|
|
48
|
+
} from "./index-n9gxx7bp.js";
|
|
49
49
|
import"./index-7md2g9vw.js";
|
|
50
50
|
import"./index-2ahj896a.js";
|
|
51
51
|
import {
|
|
@@ -57,8 +57,8 @@ import {
|
|
|
57
57
|
} from "./index-rrt9pnb4.js";
|
|
58
58
|
import {
|
|
59
59
|
CloudScript2
|
|
60
|
-
} from "./index-
|
|
61
|
-
import"./index-
|
|
60
|
+
} from "./index-g44da4r2.js";
|
|
61
|
+
import"./index-16k7m3cs.js";
|
|
62
62
|
import"./index-2z30v4k5.js";
|
|
63
63
|
import"./index-ss828r32.js";
|
|
64
64
|
import"./index-genegfnt.js";
|
|
@@ -67,7 +67,7 @@ import"./index-2ctqegdm.js";
|
|
|
67
67
|
import"./index-h9ed99ax.js";
|
|
68
68
|
import {
|
|
69
69
|
ContextScript
|
|
70
|
-
} from "./index-
|
|
70
|
+
} from "./index-2yvy9ztj.js";
|
|
71
71
|
import"./index-nbg9bfnr.js";
|
|
72
72
|
|
|
73
73
|
// pkgs/@akanjs/cli/workspace/workspace.runner.ts
|
package/README.ko.md
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# @akanjs/cli
|
|
2
|
-
|
|
3
|
-
[문서](https://akanjs.com/docs) | [npm](https://www.npmjs.com/package/@akanjs/cli) | [런타임](https://www.npmjs.com/package/akanjs)
|
|
4
|
-
|
|
5
|
-
Akan.js 워크스페이스를 위한 command-line tooling입니다.
|
|
6
|
-
|
|
7
|
-
`@akanjs/cli`는 Akan 애플리케이션, 라이브러리, 프레임워크 패키지를 생성, 빌드, 테스트, 린트,
|
|
8
|
-
릴리즈, 유지보수하는 데 사용하는 `akan` 실행 파일을 제공합니다. Bun-first CLI 패키지이며 Akan
|
|
9
|
-
개발 tooling을 내부에 번들링하므로, 애플리케이션 런타임은 더 작은 `akanjs` 패키지에만 의존할 수
|
|
10
|
-
있습니다.
|
|
11
|
-
|
|
12
|
-
## 설치
|
|
13
|
-
|
|
14
|
-
새 워크스페이스를 바로 만들 수 있습니다.
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
bunx create-akan-workspace@latest
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
또는 CLI를 전역으로 설치할 수 있습니다.
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
bun install -g @akanjs/cli@latest
|
|
24
|
-
akan --help
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## 자주 쓰는 명령
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
akan create-workspace <workspace-name>
|
|
31
|
-
akan start <app-name>
|
|
32
|
-
akan build <app-name>
|
|
33
|
-
akan test <app-or-lib-or-pkg>
|
|
34
|
-
akan lint <app-or-lib-or-pkg>
|
|
35
|
-
akan create-application <app-name>
|
|
36
|
-
akan create-library <lib-name>
|
|
37
|
-
akan create-module <module-name>
|
|
38
|
-
akan create-scalar <scalar-name>
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
패키지 유지보수 명령도 같은 실행 파일에서 제공합니다.
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
akan build-package akanjs
|
|
45
|
-
akan build-package @akanjs/cli
|
|
46
|
-
akan build-package @akanjs/devkit
|
|
47
|
-
akan build-package create-akan-workspace
|
|
48
|
-
akan verify-akan-publish-packages
|
|
49
|
-
akan smoke-registry --test=true --tag=rc
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Akan framework 패키지는 반드시 `dist/pkgs/*` 산출물 기준으로 publish합니다. `verify-akan-publish-packages`는
|
|
53
|
-
빌드된 패키지에 `npm pack --dry-run --json`을 실행하고, `deploy-akan` 또는 local registry smoke 전에 필요한
|
|
54
|
-
metadata를 검증합니다.
|
|
55
|
-
저장소 릴리즈에서는 root `akan` bootstrap script가 CLI dist를 덮어쓰지 않도록
|
|
56
|
-
`bun run release:build-packages && bun run release:verify-packages`를 우선 사용합니다.
|
|
57
|
-
|
|
58
|
-
## 패키지 경계
|
|
59
|
-
|
|
60
|
-
- 애플리케이션과 런타임 코드는 `akanjs`를 사용합니다.
|
|
61
|
-
- 사용자-facing 실행 패키지는 `@akanjs/cli`입니다.
|
|
62
|
-
- `@akanjs/devkit`은 published CLI 사용을 위해 CLI 안에 번들링됩니다. 일반 CLI 사용자가 별도의
|
|
63
|
-
runtime dependency로 설치할 필요는 없습니다.
|
|
64
|
-
|
|
65
|
-
## 요구사항
|
|
66
|
-
|
|
67
|
-
- [Bun](https://bun.sh) `>=1.4.0`
|
|
68
|
-
- TypeScript 기반 Akan 워크스페이스
|
|
69
|
-
|
|
70
|
-
## 라이선스
|
|
71
|
-
|
|
72
|
-
MIT
|
package/README.md
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# @akanjs/cli
|
|
2
|
-
|
|
3
|
-
[Docs](https://akanjs.com/docs) | [npm](https://www.npmjs.com/package/@akanjs/cli) | [Runtime](https://www.npmjs.com/package/akanjs)
|
|
4
|
-
|
|
5
|
-
Command-line tooling for Akan.js workspaces.
|
|
6
|
-
|
|
7
|
-
`@akanjs/cli` provides the `akan` executable used to create, build, test, lint, release, and maintain Akan
|
|
8
|
-
applications, libraries, and framework packages. It is a Bun-first CLI package and bundles Akan development
|
|
9
|
-
tooling internally so application runtimes can depend on the smaller `akanjs` package.
|
|
10
|
-
|
|
11
|
-
## Install
|
|
12
|
-
|
|
13
|
-
Create a new workspace:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
bunx create-akan-workspace@latest
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Or install the CLI globally:
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
bun install -g @akanjs/cli@latest
|
|
23
|
-
akan --help
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Common Commands
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
akan create-workspace <workspace-name>
|
|
30
|
-
akan start <app-name>
|
|
31
|
-
akan build <app-name>
|
|
32
|
-
akan test <app-or-lib-or-pkg>
|
|
33
|
-
akan lint <app-or-lib-or-pkg>
|
|
34
|
-
akan create-application <app-name>
|
|
35
|
-
akan create-library <lib-name>
|
|
36
|
-
akan create-module <module-name>
|
|
37
|
-
akan create-scalar <scalar-name>
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Agent And MCP Commands
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
akan context --format markdown
|
|
44
|
-
akan context --format json --module <module-name>
|
|
45
|
-
akan doctor --format json
|
|
46
|
-
akan guideline list
|
|
47
|
-
akan guideline show framework
|
|
48
|
-
akan agent install cursor
|
|
49
|
-
akan mcp
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
These commands expose Akan workspace structure, module abstracts, diagnostics, and guideline instructions for
|
|
53
|
-
coding agents. The MCP server is read-only and is intended to provide context rather than edit files directly.
|
|
54
|
-
|
|
55
|
-
Package maintenance commands are also exposed through the same executable:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
akan build-package akanjs
|
|
59
|
-
akan build-package @akanjs/cli
|
|
60
|
-
akan build-package @akanjs/devkit
|
|
61
|
-
akan build-package create-akan-workspace
|
|
62
|
-
akan verify-akan-publish-packages
|
|
63
|
-
akan smoke-registry --test=true --tag=rc
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Publish Akan framework packages from `dist/pkgs/*` only. `verify-akan-publish-packages` runs `npm pack --dry-run --json`
|
|
67
|
-
against the built packages and checks metadata that must be correct before `deploy-akan` or local registry smoke.
|
|
68
|
-
For repository releases, prefer `bun run release:build-packages && bun run release:verify-packages` so the CLI package
|
|
69
|
-
artifact is built last and is not overwritten by the root `akan` bootstrap script.
|
|
70
|
-
|
|
71
|
-
## Package Boundary
|
|
72
|
-
|
|
73
|
-
- Use `akanjs` from application and runtime code.
|
|
74
|
-
- Use `@akanjs/cli` as the user-facing executable package.
|
|
75
|
-
- `@akanjs/devkit` is bundled into the CLI for published CLI usage; it is not required as a separate
|
|
76
|
-
runtime dependency for ordinary CLI users.
|
|
77
|
-
- The `akan code` agent follows that same split: its engine, tools and skills are a devkit facet
|
|
78
|
-
(`@akanjs/devkit/codeAgent`), and `@akanjs/cli/code` is the terminal host plus the SDK entry that
|
|
79
|
-
re-exports both.
|
|
80
|
-
|
|
81
|
-
## Requirements
|
|
82
|
-
|
|
83
|
-
- [Bun](https://bun.sh) `>=1.4.0`
|
|
84
|
-
- A TypeScript Akan workspace
|
|
85
|
-
|
|
86
|
-
## License
|
|
87
|
-
|
|
88
|
-
MIT
|