@akanjs/cli 3.0.0-beta.13 → 3.0.0-beta.14
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/{TunnelShare-2kwqb1j6.js → TunnelShare-r5tc2qk5.js} +2 -2
- package/{agent.command-7357vxd8.js → agent.command-bhwsc2aj.js} +1 -1
- package/{application.command-8s8ns95d.js → application.command-436y543n.js} +1 -11
- package/{cloud.command-p5dnhft9.js → cloud.command-3xn0xpz8.js} +4 -17
- package/{cloud.script-gxpbhras.js → cloud.script-0a76c2g8.js} +4 -5
- package/commandManifest.json +1 -1
- package/{context.command-wsjt98c1.js → context.command-hxh96cc3.js} +4 -6
- package/{devTui-myg3pqeg.js → devTui-4ted58a6.js} +1 -1
- package/{devTuiView-gz2fbf4v.js → devTuiView-1dj2yq7t.js} +1 -1
- package/guideline.command-cyw8c0m0.js +48 -0
- package/guidelines/agentRule/agentRule.instruction.md +24 -13
- package/guidelines/conventions/conventions.instruction.md +6 -3
- package/guidelines/moduleCodegen/moduleCodegen.instruction.md +1 -1
- package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +1 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +62 -0
- package/index-1mrmve4s.js +61 -0
- package/{index-s3fvrydw.js → index-31hmq4ys.js} +1 -1
- package/{index-t3c045et.js → index-8tcj5wk8.js} +6 -19
- package/index-9fbk3dbh.js +234 -0
- package/{index-j7rwsd23.js → index-fad0hhty.js} +3 -3
- package/{index-wmb05v4q.js → index-gm76f0qb.js} +1 -1
- package/{index-649svkyt.js → index-myj01w9r.js} +8 -15
- package/{index-h3g1152j.js → index-r73ha1rf.js} +1 -1
- package/{index-cnzm1wn5.js → index-sg1bgdhe.js} +65 -68
- package/{index-bz10w9t2.js → index-tt6kzwj5.js} +5 -15
- package/index.js +14 -14
- package/{localRegistry.command-w6w35j4r.js → localRegistry.command-4cbgz63s.js} +3 -4
- package/{module.command-8zkq0q9q.js → module.command-ew0484va.js} +4 -7
- package/package.json +2 -5
- package/{primitive.command-qm7tybpn.js → primitive.command-50ecfzg4.js} +2 -5
- package/{quality.command-5evdd263.js → quality.command-a2jytczs.js} +63 -3
- package/{scalar.command-a1ewkmab.js → scalar.command-bptz6aj6.js} +3 -6
- package/{subspace.command-3w5x13a1.js → subspace.command-kmemx1vm.js} +2 -2
- package/{tunnel.command-09n8h4s1.js → tunnel.command-67q8vsg5.js} +2 -2
- package/{workflow.command-y3fct1rq.js → workflow.command-2ze5y2xp.js} +4 -7
- package/{workspace.command-p6td4qad.js → workspace.command-2n385jkt.js} +9 -10
- package/abstractCompactor-g04vqcff.js +0 -102
- package/guideline.command-snqzfyt0.js +0 -360
- package/index-5tw8t1ts.js +0 -338
- package/index-j1tajctp.js +0 -229
- package/index-kpnp2e10.js +0 -841
- package/index-meh558jy.js +0 -65
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
runner,
|
|
4
|
+
script
|
|
5
|
+
} from "./index-b3ae16mg.js";
|
|
6
|
+
import {
|
|
7
|
+
ModuleExecutor
|
|
8
|
+
} from "./index-5nyznra1.js";
|
|
9
|
+
import {
|
|
10
|
+
sourceFile,
|
|
11
|
+
moduleSourcePaths,
|
|
12
|
+
generatedFilesForSync,
|
|
13
|
+
createPassedPrimitiveReport,
|
|
14
|
+
bilingualLabelForField,
|
|
15
|
+
bilingualDescriptionForField
|
|
16
|
+
} from "./index-jwjaf9fy.js";
|
|
17
|
+
import {
|
|
18
|
+
PageScript
|
|
19
|
+
} from "./index-sh88vtye.js";
|
|
20
|
+
import {
|
|
21
|
+
pluralizeName
|
|
22
|
+
} from "./index-nz8prx9g.js";
|
|
23
|
+
|
|
24
|
+
// pkgs/@akanjs/cli/module/module.script.ts
|
|
25
|
+
import { capitalize as capitalize2 } from "akanjs/common";
|
|
26
|
+
|
|
27
|
+
// pkgs/@akanjs/cli/module/module.runner.ts
|
|
28
|
+
import { capitalize } from "akanjs/common";
|
|
29
|
+
var purposeByModule = {
|
|
30
|
+
budget: "Budget represents planned or actual money allocated inside the app.",
|
|
31
|
+
project: "Project represents a project workspace or business initiative managed by the app.",
|
|
32
|
+
task: "Task represents work items that move through the app workflow."
|
|
33
|
+
};
|
|
34
|
+
var moduleAbstractContent = (moduleName) => {
|
|
35
|
+
const title = capitalize(moduleName);
|
|
36
|
+
const label = bilingualLabelForField(moduleName);
|
|
37
|
+
const purpose = purposeByModule[moduleName] ?? `${title} represents ${label.en.toLowerCase()} records managed by the app.`;
|
|
38
|
+
return `# ${title} Module Abstract
|
|
39
|
+
|
|
40
|
+
## Purpose
|
|
41
|
+
|
|
42
|
+
${purpose}
|
|
43
|
+
|
|
44
|
+
## Domain Rules
|
|
45
|
+
|
|
46
|
+
- Keep ${label.en.toLowerCase()} data consistent with user-facing dictionary labels.
|
|
47
|
+
|
|
48
|
+
## Data Meaning
|
|
49
|
+
|
|
50
|
+
${label.en} (${label.ko}) is the primary business concept for this module.
|
|
51
|
+
|
|
52
|
+
## Workflows
|
|
53
|
+
|
|
54
|
+
No lifecycle workflow yet.
|
|
55
|
+
|
|
56
|
+
## Agent Notes
|
|
57
|
+
|
|
58
|
+
- Read this abstract before changing the module.
|
|
59
|
+
- Update this file when business invariants, workflows, or public behavior change.
|
|
60
|
+
- Do not update this file for formatting-only, import-only, or style-only changes.
|
|
61
|
+
|
|
62
|
+
## Related Modules
|
|
63
|
+
|
|
64
|
+
- None yet.
|
|
65
|
+
`;
|
|
66
|
+
};
|
|
67
|
+
var localModuleFilename = (moduleName, pathKey) => moduleSourcePaths(moduleName)[pathKey].replace(`lib/${moduleName}/`, "");
|
|
68
|
+
|
|
69
|
+
class ModuleRunner extends runner("module") {
|
|
70
|
+
async createService(module) {
|
|
71
|
+
const serviceName = module.name.replace(/^_+/, "");
|
|
72
|
+
await module.applyTemplate({
|
|
73
|
+
basePath: `.`,
|
|
74
|
+
template: "service",
|
|
75
|
+
dict: { model: serviceName, sysName: module.sys.name }
|
|
76
|
+
});
|
|
77
|
+
const [abstractContent, dictionaryContent, serviceContent, signalContent, storeContent] = await Promise.all([
|
|
78
|
+
module.readFile(`${serviceName}.abstract.md`),
|
|
79
|
+
module.readFile(`${serviceName}.dictionary.ts`),
|
|
80
|
+
module.readFile(`${serviceName}.service.ts`),
|
|
81
|
+
module.readFile(`${serviceName}.signal.ts`),
|
|
82
|
+
module.readFile(`${serviceName}.store.ts`)
|
|
83
|
+
]);
|
|
84
|
+
return {
|
|
85
|
+
abstract: { filename: `${serviceName}.abstract.md`, content: abstractContent },
|
|
86
|
+
dictionary: { filename: `${serviceName}.dictionary.ts`, content: dictionaryContent },
|
|
87
|
+
service: { filename: `${serviceName}.service.ts`, content: serviceContent },
|
|
88
|
+
signal: { filename: `${serviceName}.signal.ts`, content: signalContent },
|
|
89
|
+
store: { filename: `${serviceName}.store.ts`, content: storeContent }
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async removeModule(module) {
|
|
93
|
+
await module.sys.removeDir(`lib/${module.name}`);
|
|
94
|
+
}
|
|
95
|
+
async createComponentTemplate(module, type) {
|
|
96
|
+
await module.sys.applyTemplate({
|
|
97
|
+
basePath: `./lib/${module.name}`,
|
|
98
|
+
template: `module/__Model__.${capitalize(type)}.tsx`,
|
|
99
|
+
dict: { model: module.name, sysName: module.sys.name, sysType: module.sys.type }
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
component: {
|
|
103
|
+
filename: `${capitalize(module.name)}.${capitalize(type)}.tsx`,
|
|
104
|
+
content: await module.sys.readFile(`lib/${module.name}/${capitalize(module.name)}.${capitalize(type)}.tsx`)
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
async createModuleTemplate(module) {
|
|
109
|
+
const names = pluralizeName(module.name);
|
|
110
|
+
const modelLabel = bilingualLabelForField(module.name);
|
|
111
|
+
const modelDescription = bilingualDescriptionForField(module.name);
|
|
112
|
+
const filenames = {
|
|
113
|
+
abstract: localModuleFilename(module.name, "abstract"),
|
|
114
|
+
constant: localModuleFilename(module.name, "constant"),
|
|
115
|
+
dictionary: localModuleFilename(module.name, "dictionary"),
|
|
116
|
+
service: localModuleFilename(module.name, "service"),
|
|
117
|
+
store: localModuleFilename(module.name, "store"),
|
|
118
|
+
signal: localModuleFilename(module.name, "signal"),
|
|
119
|
+
unit: localModuleFilename(module.name, "unit"),
|
|
120
|
+
view: localModuleFilename(module.name, "view"),
|
|
121
|
+
template: localModuleFilename(module.name, "template"),
|
|
122
|
+
zone: localModuleFilename(module.name, "zone"),
|
|
123
|
+
util: localModuleFilename(module.name, "util")
|
|
124
|
+
};
|
|
125
|
+
await module.applyTemplate({
|
|
126
|
+
basePath: `.`,
|
|
127
|
+
template: "module",
|
|
128
|
+
dict: {
|
|
129
|
+
model: module.name,
|
|
130
|
+
models: names,
|
|
131
|
+
sysName: module.sys.name,
|
|
132
|
+
sysType: module.sys.type,
|
|
133
|
+
modelLabelEn: modelLabel.en,
|
|
134
|
+
modelLabelKo: modelLabel.ko,
|
|
135
|
+
modelDescEn: modelDescription.en,
|
|
136
|
+
modelDescKo: modelDescription.ko
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
await module.writeFile(filenames.abstract, moduleAbstractContent(module.name));
|
|
140
|
+
const [
|
|
141
|
+
abstractContent,
|
|
142
|
+
constantContent,
|
|
143
|
+
dictionaryContent,
|
|
144
|
+
serviceContent,
|
|
145
|
+
storeContent,
|
|
146
|
+
signalContent,
|
|
147
|
+
unitContent,
|
|
148
|
+
viewContent,
|
|
149
|
+
templateContent,
|
|
150
|
+
zoneContent,
|
|
151
|
+
utilContent
|
|
152
|
+
] = await Promise.all([
|
|
153
|
+
module.readFile(filenames.abstract),
|
|
154
|
+
module.readFile(filenames.constant),
|
|
155
|
+
module.readFile(filenames.dictionary),
|
|
156
|
+
module.readFile(filenames.service),
|
|
157
|
+
module.readFile(filenames.store),
|
|
158
|
+
module.readFile(filenames.signal),
|
|
159
|
+
module.readFile(filenames.unit),
|
|
160
|
+
module.readFile(filenames.view),
|
|
161
|
+
module.readFile(filenames.template),
|
|
162
|
+
module.readFile(filenames.zone),
|
|
163
|
+
module.readFile(filenames.util)
|
|
164
|
+
]);
|
|
165
|
+
return {
|
|
166
|
+
abstract: { filename: filenames.abstract, content: abstractContent },
|
|
167
|
+
constant: { filename: filenames.constant, content: constantContent },
|
|
168
|
+
dictionary: { filename: filenames.dictionary, content: dictionaryContent },
|
|
169
|
+
service: { filename: filenames.service, content: serviceContent },
|
|
170
|
+
store: { filename: filenames.store, content: storeContent },
|
|
171
|
+
signal: { filename: filenames.signal, content: signalContent },
|
|
172
|
+
unit: { filename: filenames.unit, content: unitContent },
|
|
173
|
+
view: { filename: filenames.view, content: viewContent },
|
|
174
|
+
template: { filename: filenames.template, content: templateContent },
|
|
175
|
+
zone: { filename: filenames.zone, content: zoneContent },
|
|
176
|
+
util: { filename: filenames.util, content: utilContent }
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// pkgs/@akanjs/cli/module/module.script.ts
|
|
182
|
+
var moduleChangedFiles = (sys, moduleName, files) => Object.values(files).map((file) => sourceFile(sys, `lib/${moduleName}/${file.filename}`, "create", "Module source file was created."));
|
|
183
|
+
|
|
184
|
+
class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
|
|
185
|
+
async createModuleTemplate(sys, name, { page = false } = {}) {
|
|
186
|
+
const mod = ModuleExecutor.from(sys, name);
|
|
187
|
+
const files = await this.moduleRunner.createModuleTemplate(mod);
|
|
188
|
+
if (page && sys.type === "app")
|
|
189
|
+
await this.pageScript.createCrudPage(mod, { app: sys, basePath: null, single: false });
|
|
190
|
+
await sys.scan();
|
|
191
|
+
return createPassedPrimitiveReport({
|
|
192
|
+
command: "create-module",
|
|
193
|
+
changedFiles: moduleChangedFiles(sys, name, files),
|
|
194
|
+
generatedFiles: generatedFilesForSync(sys, "Generated files were refreshed after module creation."),
|
|
195
|
+
target: sys.name
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
async removeModule(mod) {
|
|
199
|
+
await this.moduleRunner.removeModule(mod);
|
|
200
|
+
}
|
|
201
|
+
async createService(sys, name) {
|
|
202
|
+
const service = ModuleExecutor.from(sys, `_${name}`);
|
|
203
|
+
const files = await this.moduleRunner.createService(service);
|
|
204
|
+
await sys.scan();
|
|
205
|
+
return createPassedPrimitiveReport({
|
|
206
|
+
command: "create-service",
|
|
207
|
+
changedFiles: moduleChangedFiles(sys, `_${name}`, files),
|
|
208
|
+
generatedFiles: generatedFilesForSync(sys, "Generated files were refreshed after service creation."),
|
|
209
|
+
target: sys.name
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
async createTest(workspace, name) {}
|
|
213
|
+
async createTemplate(mod) {
|
|
214
|
+
return await this.#createComponent(mod, "template");
|
|
215
|
+
}
|
|
216
|
+
async createUnit(mod) {
|
|
217
|
+
return await this.#createComponent(mod, "unit");
|
|
218
|
+
}
|
|
219
|
+
async createView(mod) {
|
|
220
|
+
return await this.#createComponent(mod, "view");
|
|
221
|
+
}
|
|
222
|
+
async#createComponent(mod, type) {
|
|
223
|
+
const { component } = await this.moduleRunner.createComponentTemplate(mod, type);
|
|
224
|
+
return createPassedPrimitiveReport({
|
|
225
|
+
command: `create-${type}`,
|
|
226
|
+
changedFiles: [
|
|
227
|
+
sourceFile(mod.sys, `lib/${mod.name}/${component.filename}`, "create", `${capitalize2(type)} UI source was created.`)
|
|
228
|
+
],
|
|
229
|
+
target: mod.sys.name
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export { ModuleScript };
|
|
@@ -39,13 +39,13 @@ import {
|
|
|
39
39
|
} from "./index-8pkvrcv1.js";
|
|
40
40
|
import {
|
|
41
41
|
ModuleScript
|
|
42
|
-
} from "./index-
|
|
42
|
+
} from "./index-9fbk3dbh.js";
|
|
43
43
|
import {
|
|
44
44
|
PrimitiveScript
|
|
45
|
-
} from "./index-
|
|
45
|
+
} from "./index-r73ha1rf.js";
|
|
46
46
|
import {
|
|
47
47
|
ScalarScript
|
|
48
|
-
} from "./index-
|
|
48
|
+
} from "./index-1mrmve4s.js";
|
|
49
49
|
import {
|
|
50
50
|
getMobileTargets
|
|
51
51
|
} from "./index-47pj3aee.js";
|
|
@@ -13,8 +13,7 @@ var configPath = `${basePath}/config.json`;
|
|
|
13
13
|
var getDefaultHostConfig = (host = GlobalConfig.akanCloudHost) => ({ host });
|
|
14
14
|
var defaultAkanGlobalConfig = {
|
|
15
15
|
cloudHost: {},
|
|
16
|
-
remoteEnvServers: {}
|
|
17
|
-
llm: null
|
|
16
|
+
remoteEnvServers: {}
|
|
18
17
|
};
|
|
19
18
|
|
|
20
19
|
// pkgs/@akanjs/devkit/cloud/globalConfig.ts
|
|
@@ -44,14 +43,6 @@ class GlobalConfig {
|
|
|
44
43
|
akanConfig.cloudHost[config.host] = GlobalConfig.toHostConfigDto(config);
|
|
45
44
|
await GlobalConfig.#setAkanGlobalConfig(akanConfig);
|
|
46
45
|
}
|
|
47
|
-
static async getLlmConfig() {
|
|
48
|
-
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
49
|
-
return akanConfig.llm ?? null;
|
|
50
|
-
}
|
|
51
|
-
static async setLlmConfig(llmConfig) {
|
|
52
|
-
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
53
|
-
await GlobalConfig.#setAkanGlobalConfig({ ...akanConfig, llm: llmConfig });
|
|
54
|
-
}
|
|
55
46
|
static async getRemoteEnvServers() {
|
|
56
47
|
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
57
48
|
return akanConfig.remoteEnvServers;
|
|
@@ -119,13 +110,14 @@ class HttpClient {
|
|
|
119
110
|
this.baseUrl = baseUrl;
|
|
120
111
|
this.headers = headers;
|
|
121
112
|
}
|
|
122
|
-
async get(url, { headers } = {}) {
|
|
113
|
+
async get(url, { headers, signal } = {}) {
|
|
123
114
|
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
124
115
|
headers: {
|
|
125
116
|
"Content-Type": "application/json",
|
|
126
117
|
...this.headers,
|
|
127
118
|
...headers
|
|
128
|
-
}
|
|
119
|
+
},
|
|
120
|
+
...signal ? { signal } : {}
|
|
129
121
|
});
|
|
130
122
|
return await HttpClient.#body(response, url);
|
|
131
123
|
}
|
|
@@ -137,12 +129,13 @@ class HttpClient {
|
|
|
137
129
|
throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
|
|
138
130
|
await Bun.write(localPath, response);
|
|
139
131
|
}
|
|
140
|
-
async post(url, data, { headers } = {}) {
|
|
132
|
+
async post(url, data, { headers, signal } = {}) {
|
|
141
133
|
const isFormData = data instanceof FormData;
|
|
142
134
|
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
143
135
|
method: "POST",
|
|
144
136
|
body: isFormData ? data : JSON.stringify(data),
|
|
145
|
-
headers: isFormData ? { ...this.headers, ...headers } : { "Content-Type": "application/json", ...this.headers, ...headers }
|
|
137
|
+
headers: isFormData ? { ...this.headers, ...headers } : { "Content-Type": "application/json", ...this.headers, ...headers },
|
|
138
|
+
...signal ? { signal } : {}
|
|
146
139
|
});
|
|
147
140
|
return await HttpClient.#body(response, url);
|
|
148
141
|
}
|
|
@@ -229,7 +222,7 @@ class CloudApi {
|
|
|
229
222
|
return await this.#api.get(`/tunnel/tunnelListInSelf`);
|
|
230
223
|
}
|
|
231
224
|
async revokeTunnel(code) {
|
|
232
|
-
return await this.#api.post(`/tunnel/revokeTunnel`, { code });
|
|
225
|
+
return await this.#api.post(`/tunnel/revokeTunnel`, { code }, { signal: AbortSignal.timeout(5000) });
|
|
233
226
|
}
|
|
234
227
|
async getRemoteSelf() {
|
|
235
228
|
try {
|
|
@@ -166,7 +166,7 @@ Caused by: ${ApplicationBuildReporter.formatError(error.cause)}` : "";
|
|
|
166
166
|
|
|
167
167
|
// pkgs/@akanjs/cli/application/application.script.ts
|
|
168
168
|
import { confirm } from "@inquirer/prompts";
|
|
169
|
-
import { Logger as
|
|
169
|
+
import { Logger as Logger7 } from "akanjs/common";
|
|
170
170
|
|
|
171
171
|
// pkgs/@akanjs/cli/application/application.runner.ts
|
|
172
172
|
import path5 from "path";
|
|
@@ -2048,11 +2048,9 @@ ${uniqueCandidates.map((candidate) => ` - ${candidate}`).join(`
|
|
|
2048
2048
|
|
|
2049
2049
|
// pkgs/@akanjs/cli/application/application.runner.ts
|
|
2050
2050
|
import { Logger as Logger4 } from "akanjs/common";
|
|
2051
|
-
import ora from "ora";
|
|
2052
2051
|
var loadBuildRunner = async () => (await import("./applicationBuildRunner-4f1wrba0.js")).ApplicationBuildRunner;
|
|
2053
2052
|
var loadReleasePackager = async () => (await import("./applicationReleasePackager-jkjmy5ee.js")).ApplicationReleasePackager;
|
|
2054
2053
|
var loadCapacitorApp = async () => (await import("./capacitorApp-hqvsrec4.js")).CapacitorApp;
|
|
2055
|
-
var loadAbstractCompactor = async () => (await import("./abstractCompactor-g04vqcff.js")).AbstractCompactor;
|
|
2056
2054
|
var loadPrompts = async () => await import("@inquirer/prompts");
|
|
2057
2055
|
|
|
2058
2056
|
class ApplicationRunner extends runner("application") {
|
|
@@ -2193,10 +2191,6 @@ try {
|
|
|
2193
2191
|
async typecheck(app, options = {}) {
|
|
2194
2192
|
await new (await loadBuildRunner())(app).typecheck(options);
|
|
2195
2193
|
}
|
|
2196
|
-
async compact(sys, { module, minLines, interactive } = {}) {
|
|
2197
|
-
const compactor = new (await loadAbstractCompactor())(sys, { minLines, interactive });
|
|
2198
|
-
return await compactor.compactAll({ module });
|
|
2199
|
-
}
|
|
2200
2194
|
async test(exec) {
|
|
2201
2195
|
const isSignalTarget = exec instanceof AppExecutor || exec instanceof LibExecutor;
|
|
2202
2196
|
const preloadPath = isSignalTarget ? await resolveSignalTestPreloadPath(exec) : null;
|
|
@@ -2434,28 +2428,6 @@ ${detail}`
|
|
|
2434
2428
|
});
|
|
2435
2429
|
return;
|
|
2436
2430
|
}
|
|
2437
|
-
async generateApplicationTemplate(app) {
|
|
2438
|
-
const openAIApiKey = process.env.OPENAI_API_KEY;
|
|
2439
|
-
if (!openAIApiKey)
|
|
2440
|
-
throw new Error("OPENAI_API_KEY is not set");
|
|
2441
|
-
const [{ StringOutputParser }, { PromptTemplate }, { RunnableSequence }, { ChatOpenAI }, prompts] = await Promise.all([
|
|
2442
|
-
import("@langchain/core/output_parsers"),
|
|
2443
|
-
import("@langchain/core/prompts"),
|
|
2444
|
-
import("@langchain/core/runnables"),
|
|
2445
|
-
import("@langchain/openai"),
|
|
2446
|
-
loadPrompts()
|
|
2447
|
-
]);
|
|
2448
|
-
const chatModel = new ChatOpenAI({ modelName: "gpt-4o", openAIApiKey });
|
|
2449
|
-
const projectName = await prompts.input({ message: "please enter project name." });
|
|
2450
|
-
const projectDesc = await prompts.input({
|
|
2451
|
-
message: "please enter project description. (40 ~ 60 characters)"
|
|
2452
|
-
});
|
|
2453
|
-
const spinner = ora("Gerating project files...");
|
|
2454
|
-
const mainPrompt = PromptTemplate.fromTemplate(`prompt.requestApplication()`);
|
|
2455
|
-
const chain = RunnableSequence.from([mainPrompt, chatModel, new StringOutputParser]);
|
|
2456
|
-
await chain.invoke({ projectName, projectDesc });
|
|
2457
|
-
spinner.succeed("Loading complete!");
|
|
2458
|
-
}
|
|
2459
2431
|
}
|
|
2460
2432
|
|
|
2461
2433
|
// pkgs/@akanjs/cli/application/devPortReclaimer.ts
|
|
@@ -3054,9 +3026,54 @@ var resolveDevUi = (plain, { isTty = !!process.stdout.isTTY, columns = process.s
|
|
|
3054
3026
|
return { mode: "tui", downgraded: false };
|
|
3055
3027
|
};
|
|
3056
3028
|
|
|
3029
|
+
// pkgs/@akanjs/cli/application/interruptTeardown.ts
|
|
3030
|
+
import { Logger as Logger6 } from "akanjs/common";
|
|
3031
|
+
|
|
3032
|
+
class InterruptTeardown {
|
|
3033
|
+
#teardowns = [];
|
|
3034
|
+
#exit;
|
|
3035
|
+
#listen;
|
|
3036
|
+
#report;
|
|
3037
|
+
#interrupted = false;
|
|
3038
|
+
ownsExit = true;
|
|
3039
|
+
constructor({ exit, listen, report } = {}) {
|
|
3040
|
+
this.#exit = exit ?? ((code) => process.exit(code));
|
|
3041
|
+
this.#listen = listen ?? ((onSignal) => {
|
|
3042
|
+
process.on("SIGINT", onSignal);
|
|
3043
|
+
});
|
|
3044
|
+
this.#report = report ?? ((message) => Logger6.rawLog(message, undefined, "error"));
|
|
3045
|
+
}
|
|
3046
|
+
add(run, abandoned) {
|
|
3047
|
+
this.#teardowns.push({ run, abandoned, running: false });
|
|
3048
|
+
if (this.#teardowns.length === 1)
|
|
3049
|
+
this.#listen(() => this.#onSignal());
|
|
3050
|
+
}
|
|
3051
|
+
#onSignal() {
|
|
3052
|
+
if (this.#interrupted) {
|
|
3053
|
+
for (const one of this.#teardowns)
|
|
3054
|
+
if (one.running)
|
|
3055
|
+
this.#report(one.abandoned);
|
|
3056
|
+
this.#exit(130);
|
|
3057
|
+
return;
|
|
3058
|
+
}
|
|
3059
|
+
this.#interrupted = true;
|
|
3060
|
+
Promise.all(this.#teardowns.map(async (one) => {
|
|
3061
|
+
one.running = true;
|
|
3062
|
+
await one.run().catch(() => {
|
|
3063
|
+
return;
|
|
3064
|
+
});
|
|
3065
|
+
one.running = false;
|
|
3066
|
+
})).finally(() => {
|
|
3067
|
+
if (this.ownsExit)
|
|
3068
|
+
this.#exit(0);
|
|
3069
|
+
});
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
|
|
3057
3073
|
// pkgs/@akanjs/cli/application/application.script.ts
|
|
3058
3074
|
class ApplicationScript extends script("application", [ApplicationRunner, LibraryScript]) {
|
|
3059
3075
|
static dbShutdownTimeoutMs = 20000;
|
|
3076
|
+
#interrupt = new InterruptTeardown;
|
|
3060
3077
|
async confirmDatabaseModeDependencyInstall(databaseMode, installSpecs) {
|
|
3061
3078
|
return await confirm({
|
|
3062
3079
|
message: [
|
|
@@ -3148,7 +3165,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3148
3165
|
const spinner = app.spinning("Planning distributable slice...");
|
|
3149
3166
|
const plan = await this.applicationRunner.planSlice(app);
|
|
3150
3167
|
spinner.succeed(`Slice planned (${plan.libs.length} libs, ${plan.warnings.length} warnings)`);
|
|
3151
|
-
|
|
3168
|
+
Logger7.rawLog(format === "json" ? JSON.stringify(plan, null, 2) : formatSlicePlan(plan));
|
|
3152
3169
|
}
|
|
3153
3170
|
async sync(sys) {
|
|
3154
3171
|
if (sys.type === "app")
|
|
@@ -3156,17 +3173,6 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3156
3173
|
else
|
|
3157
3174
|
await this.libraryScript.syncLibrary(sys);
|
|
3158
3175
|
}
|
|
3159
|
-
async compact(sys, { module = null, minLines, interactive = false } = {}) {
|
|
3160
|
-
const { scanned, reports } = await this.applicationRunner.compact(sys, { module, minLines, interactive });
|
|
3161
|
-
if (!reports.length) {
|
|
3162
|
-
Logger6.rawLog(`No abstract file long enough to compact in ${sys.name} (${scanned} scanned)`);
|
|
3163
|
-
return;
|
|
3164
|
-
}
|
|
3165
|
-
for (const report of reports)
|
|
3166
|
-
Logger6.rawLog(`${report.status}: ${report.path} (${report.beforeLines} -> ${report.afterLines} lines)`);
|
|
3167
|
-
const compactedNum = reports.filter((report) => report.status === "compacted").length;
|
|
3168
|
-
Logger6.rawLog(`Compacted ${compactedNum}/${reports.length} abstract files in ${sys.name}`);
|
|
3169
|
-
}
|
|
3170
3176
|
async script(app, filename) {
|
|
3171
3177
|
const scriptFilename = filename ?? await this.applicationRunner.getScriptFilename(app);
|
|
3172
3178
|
await app.scanSync();
|
|
@@ -3182,18 +3188,18 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3182
3188
|
async build(app, { write = true, fast = false, quiet = false } = {}) {
|
|
3183
3189
|
await app.scanSync({ write });
|
|
3184
3190
|
if (!quiet)
|
|
3185
|
-
|
|
3191
|
+
Logger7.rawLog(`Creating an optimized production build for ${app.name}...`);
|
|
3186
3192
|
try {
|
|
3187
3193
|
const result = await this.applicationRunner.build(app, {
|
|
3188
3194
|
fast,
|
|
3189
3195
|
spinner: !quiet
|
|
3190
3196
|
});
|
|
3191
|
-
|
|
3197
|
+
Logger7.rawLog(`${app.name} built in dist/apps/${app.name}`);
|
|
3192
3198
|
if (!quiet)
|
|
3193
3199
|
ApplicationBuildReporter.printSummary(result);
|
|
3194
3200
|
} catch (error) {
|
|
3195
|
-
|
|
3196
|
-
|
|
3201
|
+
Logger7.rawLog(`${app.name} build failed in dist/apps/${app.name}`, undefined, "error");
|
|
3202
|
+
Logger7.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
|
|
3197
3203
|
throw error;
|
|
3198
3204
|
}
|
|
3199
3205
|
}
|
|
@@ -3205,7 +3211,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3205
3211
|
spinner.succeed(`${app.name} typechecked`);
|
|
3206
3212
|
} catch (error) {
|
|
3207
3213
|
spinner.fail(`${app.name} typecheck failed`);
|
|
3208
|
-
|
|
3214
|
+
Logger7.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
|
|
3209
3215
|
throw error;
|
|
3210
3216
|
}
|
|
3211
3217
|
}
|
|
@@ -3251,6 +3257,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3251
3257
|
await this.#shareOnInterrupt(apps);
|
|
3252
3258
|
if (mode === "stream" && apps.length === 1)
|
|
3253
3259
|
return await this.startOne(first, { open, dbup, write, ...DevSupervisor.childHooks() });
|
|
3260
|
+
this.#interrupt.ownsExit = false;
|
|
3254
3261
|
await this.#startMany(apps, { open, dbup, write, mode, concurrency });
|
|
3255
3262
|
}
|
|
3256
3263
|
async startOne(app, { open = false, dbup = true, stdio = "inherit", write = true, onDevEvent } = {}) {
|
|
@@ -3283,7 +3290,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3283
3290
|
for (const holder of killed)
|
|
3284
3291
|
workspace.log(`freed port ${holder.port} \u2014 killed pid ${holder.pid} (${holder.command})`);
|
|
3285
3292
|
for (const holder of foreign)
|
|
3286
|
-
|
|
3293
|
+
Logger7.rawLog(`port ${holder.port} is held by pid ${holder.pid} and was left alone: ${holder.command}`, undefined, "error");
|
|
3287
3294
|
if (killed.length === 0 && foreign.length === 0)
|
|
3288
3295
|
workspace.log("dev ports are free; nothing to kill");
|
|
3289
3296
|
}
|
|
@@ -3299,7 +3306,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3299
3306
|
throw new Error("No app selected to start");
|
|
3300
3307
|
const startedDatabase = dbup ? await this.#prepareSharedDatabase(apps) : false;
|
|
3301
3308
|
const supervisor = new DevSupervisor({ apps, mode, concurrency, open, write });
|
|
3302
|
-
const view = mode === "tui" ? await (await import("./devTuiView-
|
|
3309
|
+
const view = mode === "tui" ? await (await import("./devTuiView-1dj2yq7t.js")).createDevTuiView(supervisor) : new DevStreamView(apps.map((app) => app.name));
|
|
3303
3310
|
await supervisor.run(view);
|
|
3304
3311
|
if (startedDatabase)
|
|
3305
3312
|
await this.#stopDatabase(workspace);
|
|
@@ -3420,32 +3427,22 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3420
3427
|
#shareOnInterrupt(apps) {
|
|
3421
3428
|
const shares = [];
|
|
3422
3429
|
const open = Promise.all(apps.map(async (app) => {
|
|
3423
|
-
const { TunnelShare } = await import("./TunnelShare-
|
|
3430
|
+
const { TunnelShare } = await import("./TunnelShare-r5tc2qk5.js");
|
|
3424
3431
|
const share = await TunnelShare.open(app, { workspace: app.workspace });
|
|
3425
3432
|
shares.push(share);
|
|
3426
|
-
|
|
3433
|
+
Logger7.rawLog(`${app.name} is shared at ${share.url}`);
|
|
3427
3434
|
})).catch((error) => {
|
|
3428
|
-
|
|
3429
|
-
});
|
|
3430
|
-
let closing = false;
|
|
3431
|
-
process.on("SIGINT", () => {
|
|
3432
|
-
if (closing)
|
|
3433
|
-
return;
|
|
3434
|
-
closing = true;
|
|
3435
|
-
Promise.all(shares.map(async (share) => await share.close()));
|
|
3435
|
+
Logger7.rawLog(`Could not open the tunnel: ${error instanceof Error ? error.message : String(error)}`, undefined, "error");
|
|
3436
3436
|
});
|
|
3437
|
+
this.#interrupt.add(async () => {
|
|
3438
|
+
await Promise.all(shares.map(async (share) => await share.close()));
|
|
3439
|
+
}, "Abandoning the tunnel release; the shares expire on their own.");
|
|
3437
3440
|
return open;
|
|
3438
3441
|
}
|
|
3439
3442
|
#stopDatabaseOnInterrupt(workspace) {
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
Logger6.rawLog("Abandoning the local database teardown; containers are left running.", undefined, "error");
|
|
3444
|
-
process.exit(130);
|
|
3445
|
-
}
|
|
3446
|
-
stopping = true;
|
|
3447
|
-
this.#stopDatabase(workspace).finally(() => process.exit(0));
|
|
3448
|
-
});
|
|
3443
|
+
this.#interrupt.add(async () => {
|
|
3444
|
+
await this.#stopDatabase(workspace);
|
|
3445
|
+
}, "Abandoning the local database teardown; containers are left running.");
|
|
3449
3446
|
}
|
|
3450
3447
|
async#stopDatabase(workspace) {
|
|
3451
3448
|
let timer = null;
|
|
@@ -3458,7 +3455,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3458
3455
|
}), timeout]);
|
|
3459
3456
|
if (result !== "timeout")
|
|
3460
3457
|
return;
|
|
3461
|
-
|
|
3458
|
+
Logger7.rawLog(`Local database did not stop within ${ApplicationScript.dbShutdownTimeoutMs}ms; run \`akan dbdown\` once Docker responds.`, undefined, "error");
|
|
3462
3459
|
} finally {
|
|
3463
3460
|
if (timer)
|
|
3464
3461
|
clearTimeout(timer);
|
|
@@ -3,20 +3,17 @@ import {
|
|
|
3
3
|
getDefaultHostConfig,
|
|
4
4
|
GlobalConfig,
|
|
5
5
|
CloudApi
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-myj01w9r.js";
|
|
7
|
+
import {
|
|
8
|
+
runner
|
|
9
|
+
} from "./index-b3ae16mg.js";
|
|
7
10
|
import {
|
|
8
11
|
WorkspaceExecutor,
|
|
9
12
|
AppExecutor
|
|
10
13
|
} from "./index-5nyznra1.js";
|
|
11
|
-
import {
|
|
12
|
-
AiSession
|
|
13
|
-
} from "./index-5tw8t1ts.js";
|
|
14
|
-
import {
|
|
15
|
-
runner
|
|
16
|
-
} from "./index-b3ae16mg.js";
|
|
17
14
|
import {
|
|
18
15
|
openBrowser
|
|
19
|
-
} from "./index-
|
|
16
|
+
} from "./index-sg1bgdhe.js";
|
|
20
17
|
|
|
21
18
|
// pkgs/@akanjs/cli/cloud/cloud.runner.ts
|
|
22
19
|
import path from "path";
|
|
@@ -239,13 +236,6 @@ ${chalk.green("\u27A4")} Authentication Required`));
|
|
|
239
236
|
`));
|
|
240
237
|
}
|
|
241
238
|
}
|
|
242
|
-
async setLlm() {
|
|
243
|
-
await AiSession.init({ useExisting: false });
|
|
244
|
-
}
|
|
245
|
-
resetLlm() {
|
|
246
|
-
AiSession.setLlmConfig(null);
|
|
247
|
-
Logger.rawLog(chalk.green("\u2611\uFE0F LLM model config is cleared. Please run `akan set-llm` to set a new LLM model."));
|
|
248
|
-
}
|
|
249
239
|
async getAkanPkgs(workspace) {
|
|
250
240
|
const pkgs = await workspace.getPkgs();
|
|
251
241
|
return pkgs.filter((pkg) => pkg === "akanjs" || pkg === "create-akan-workspace" || pkg.startsWith("@akanjs/"));
|
package/index.js
CHANGED
|
@@ -14,24 +14,24 @@ import path from "path";
|
|
|
14
14
|
|
|
15
15
|
// pkgs/@akanjs/cli/commandModules.ts
|
|
16
16
|
var commandModules = {
|
|
17
|
-
workspace: async () => (await import("./workspace.command-
|
|
18
|
-
agent: async () => (await import("./agent.command-
|
|
19
|
-
application: async () => (await import("./application.command-
|
|
17
|
+
workspace: async () => (await import("./workspace.command-2n385jkt.js")).WorkspaceCommand,
|
|
18
|
+
agent: async () => (await import("./agent.command-bhwsc2aj.js")).AgentCommand,
|
|
19
|
+
application: async () => (await import("./application.command-436y543n.js")).ApplicationCommand,
|
|
20
20
|
library: async () => (await import("./library.command-1f9h2ex6.js")).LibraryCommand,
|
|
21
|
-
localRegistry: async () => (await import("./localRegistry.command-
|
|
21
|
+
localRegistry: async () => (await import("./localRegistry.command-4cbgz63s.js")).LocalRegistryCommand,
|
|
22
22
|
package: async () => (await import("./package.command-y2rh4np7.js")).PackageCommand,
|
|
23
|
-
module: async () => (await import("./module.command-
|
|
23
|
+
module: async () => (await import("./module.command-ew0484va.js")).ModuleCommand,
|
|
24
24
|
page: async () => (await import("./page.command-e5h29fyt.js")).PageCommand,
|
|
25
|
-
context: async () => (await import("./context.command-
|
|
26
|
-
cloud: async () => (await import("./cloud.command-
|
|
27
|
-
subspace: async () => (await import("./subspace.command-
|
|
28
|
-
guideline: async () => (await import("./guideline.command-
|
|
29
|
-
scalar: async () => (await import("./scalar.command-
|
|
30
|
-
primitive: async () => (await import("./primitive.command-
|
|
31
|
-
quality: async () => (await import("./quality.command-
|
|
25
|
+
context: async () => (await import("./context.command-hxh96cc3.js")).ContextCommand,
|
|
26
|
+
cloud: async () => (await import("./cloud.command-3xn0xpz8.js")).CloudCommand,
|
|
27
|
+
subspace: async () => (await import("./subspace.command-kmemx1vm.js")).SubspaceCommand,
|
|
28
|
+
guideline: async () => (await import("./guideline.command-cyw8c0m0.js")).GuidelineCommand,
|
|
29
|
+
scalar: async () => (await import("./scalar.command-bptz6aj6.js")).ScalarCommand,
|
|
30
|
+
primitive: async () => (await import("./primitive.command-50ecfzg4.js")).PrimitiveCommand,
|
|
31
|
+
quality: async () => (await import("./quality.command-a2jytczs.js")).QualityCommand,
|
|
32
32
|
repair: async () => (await import("./repair.command-c2amvt74.js")).RepairCommand,
|
|
33
|
-
workflow: async () => (await import("./workflow.command-
|
|
34
|
-
tunnel: async () => (await import("./tunnel.command-
|
|
33
|
+
workflow: async () => (await import("./workflow.command-2ze5y2xp.js")).WorkflowCommand,
|
|
34
|
+
tunnel: async () => (await import("./tunnel.command-67q8vsg5.js")).TunnelCommand
|
|
35
35
|
};
|
|
36
36
|
var commandModuleIds = Object.keys(commandModules);
|
|
37
37
|
|