@jskit-ai/jskit-cli 0.2.92 → 0.2.97
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/package.json +4 -4
- package/src/server/appBlueprint.js +37 -14
- package/src/server/core/argParser.js +0 -12
- package/src/server/core/commandCatalog.js +2 -92
- package/src/server/core/createCommandHandlers.js +0 -3
- package/src/server/helperMap.js +214 -56
- package/src/server/index.js +0 -1
- package/src/server/{sessionRuntime/prompts → prompts}/app_blueprint.md +1 -1
- package/src/server/commandHandlers/session.js +0 -471
- package/src/server/sessionRuntime/appReadiness.js +0 -55
- package/src/server/sessionRuntime/constants.js +0 -377
- package/src/server/sessionRuntime/io.js +0 -97
- package/src/server/sessionRuntime/paths.js +0 -163
- package/src/server/sessionRuntime/preconditions.js +0 -663
- package/src/server/sessionRuntime/promptRenderer.js +0 -41
- package/src/server/sessionRuntime/prompts/automated_checks_run.md +0 -28
- package/src/server/sessionRuntime/prompts/blueprint_updated.md +0 -29
- package/src/server/sessionRuntime/prompts/deep_ui_check_run.md +0 -40
- package/src/server/sessionRuntime/prompts/final_comment.md +0 -10
- package/src/server/sessionRuntime/prompts/final_report_created.md +0 -44
- package/src/server/sessionRuntime/prompts/issue_created.md +0 -26
- package/src/server/sessionRuntime/prompts/issue_prompt_rendered.md +0 -1
- package/src/server/sessionRuntime/prompts/make_plan.md +0 -57
- package/src/server/sessionRuntime/prompts/plan_executed.md +0 -39
- package/src/server/sessionRuntime/prompts/pr_failure.md +0 -28
- package/src/server/sessionRuntime/prompts/pr_merge_prepared.md +0 -22
- package/src/server/sessionRuntime/prompts/review_changes_accepted_resolve.md +0 -12
- package/src/server/sessionRuntime/prompts/review_prompt_rendered.md +0 -61
- package/src/server/sessionRuntime/prompts/user_check_completed.md +0 -17
- package/src/server/sessionRuntime/responses.js +0 -1481
- package/src/server/sessionRuntime/worktrees.js +0 -31
- package/src/server/sessionRuntime.js +0 -3659
|
@@ -1,471 +0,0 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import {
|
|
3
|
-
abandonSession,
|
|
4
|
-
advanceSessionStep,
|
|
5
|
-
adoptCodexThreadId,
|
|
6
|
-
buildSessionErrorResponse,
|
|
7
|
-
createSession,
|
|
8
|
-
inspectSessionDiff,
|
|
9
|
-
inspectSessionDetails,
|
|
10
|
-
listSessions,
|
|
11
|
-
rewindSession,
|
|
12
|
-
runSessionStep,
|
|
13
|
-
runSessionStepAction
|
|
14
|
-
} from "../sessionRuntime.js";
|
|
15
|
-
|
|
16
|
-
function writeJson(stdout, payload) {
|
|
17
|
-
stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function writeSessionText(stdout, payload) {
|
|
21
|
-
if (payload.sessions) {
|
|
22
|
-
stdout.write("JSKIT sessions\n");
|
|
23
|
-
if (payload.sessions.length < 1) {
|
|
24
|
-
stdout.write("No sessions found.\n");
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
for (const session of payload.sessions) {
|
|
28
|
-
stdout.write(`- ${session.sessionId} ${session.status} ${session.currentStep || "done"}\n`);
|
|
29
|
-
}
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
stdout.write(`Session: ${payload.sessionId || "unknown"}\n`);
|
|
34
|
-
stdout.write(`Status: ${payload.status || "unknown"}\n`);
|
|
35
|
-
stdout.write(`Current step: ${payload.currentStep || "done"}\n`);
|
|
36
|
-
if (payload.issueUrl) {
|
|
37
|
-
stdout.write(`Issue: ${payload.issueUrl}\n`);
|
|
38
|
-
}
|
|
39
|
-
if (payload.prUrl) {
|
|
40
|
-
stdout.write(`PR: ${payload.prUrl}\n`);
|
|
41
|
-
}
|
|
42
|
-
if (payload.branch) {
|
|
43
|
-
stdout.write(`Branch: ${payload.branch}\n`);
|
|
44
|
-
}
|
|
45
|
-
if (payload.worktree) {
|
|
46
|
-
stdout.write(`Worktree: ${payload.worktree}\n`);
|
|
47
|
-
}
|
|
48
|
-
if (payload.completedSteps?.length) {
|
|
49
|
-
stdout.write("Done steps:\n");
|
|
50
|
-
for (const step of payload.completedSteps) {
|
|
51
|
-
stdout.write(`- ${step}\n`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (payload.prompt) {
|
|
55
|
-
stdout.write("\n");
|
|
56
|
-
stdout.write(payload.prompt);
|
|
57
|
-
stdout.write("\n");
|
|
58
|
-
}
|
|
59
|
-
if (payload.gitStatus !== undefined && payload.unstagedDiff !== undefined) {
|
|
60
|
-
stdout.write("\nGit status:\n");
|
|
61
|
-
stdout.write(payload.gitStatus || "No changes.");
|
|
62
|
-
stdout.write("\n");
|
|
63
|
-
const diff = [payload.stagedDiff, payload.unstagedDiff, payload.untrackedDiff].filter(Boolean).join("\n");
|
|
64
|
-
if (diff) {
|
|
65
|
-
stdout.write("\nDiff:\n");
|
|
66
|
-
stdout.write(diff);
|
|
67
|
-
stdout.write("\n");
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (payload.errors?.length) {
|
|
71
|
-
stdout.write("Errors:\n");
|
|
72
|
-
for (const error of payload.errors) {
|
|
73
|
-
stdout.write(`- [${error.code}] ${error.message}\n`);
|
|
74
|
-
if (error.repairCommand) {
|
|
75
|
-
stdout.write(` Repair: ${error.repairCommand}\n`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (payload.nextCommand) {
|
|
80
|
-
stdout.write(`Next: ${payload.nextCommand}\n`);
|
|
81
|
-
}
|
|
82
|
-
if (payload.actionCommands?.length) {
|
|
83
|
-
stdout.write("Available commands:\n");
|
|
84
|
-
for (const command of payload.actionCommands) {
|
|
85
|
-
stdout.write(`- ${command.command}\n`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function readStream(stream) {
|
|
91
|
-
const chunks = [];
|
|
92
|
-
for await (const chunk of stream) {
|
|
93
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
94
|
-
}
|
|
95
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function resolveInputFilePath(cwd, filePath) {
|
|
99
|
-
return filePath.startsWith("/") ? filePath : `${cwd}/${filePath}`;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async function resolveTextInput({
|
|
103
|
-
codePrefix,
|
|
104
|
-
fileOption,
|
|
105
|
-
inlineOptions = {},
|
|
106
|
-
io = {},
|
|
107
|
-
repairCommand,
|
|
108
|
-
cwd,
|
|
109
|
-
stdinOption,
|
|
110
|
-
textOption,
|
|
111
|
-
sessionId
|
|
112
|
-
}) {
|
|
113
|
-
if (Object.hasOwn(inlineOptions, fileOption)) {
|
|
114
|
-
const inputFile = String(inlineOptions[fileOption] || "").trim();
|
|
115
|
-
if (!inputFile) {
|
|
116
|
-
return { ok: true, value: "" };
|
|
117
|
-
}
|
|
118
|
-
const resolvedInputFile = resolveInputFilePath(cwd, inputFile);
|
|
119
|
-
try {
|
|
120
|
-
return {
|
|
121
|
-
ok: true,
|
|
122
|
-
value: await readFile(resolvedInputFile, "utf8")
|
|
123
|
-
};
|
|
124
|
-
} catch (error) {
|
|
125
|
-
return {
|
|
126
|
-
ok: false,
|
|
127
|
-
payload: buildSessionErrorResponse({
|
|
128
|
-
targetRoot: cwd,
|
|
129
|
-
sessionId,
|
|
130
|
-
code: `${codePrefix}_file_read_failed`,
|
|
131
|
-
message: `Could not read ${codePrefix.replaceAll("_", " ")} file ${resolvedInputFile}: ${error.message}`,
|
|
132
|
-
repairCommand
|
|
133
|
-
})
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
if (Object.hasOwn(inlineOptions, textOption)) {
|
|
138
|
-
const textValue = String(inlineOptions[textOption] ?? "");
|
|
139
|
-
if (textValue === stdinOption) {
|
|
140
|
-
return {
|
|
141
|
-
ok: true,
|
|
142
|
-
value: await readStream(io.stdin)
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
ok: true,
|
|
147
|
-
value: textValue
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
return { ok: true, value: "" };
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
async function resolveStepInputs({
|
|
154
|
-
inlineOptions = {},
|
|
155
|
-
io = {},
|
|
156
|
-
cwd,
|
|
157
|
-
sessionId
|
|
158
|
-
}) {
|
|
159
|
-
if (Object.hasOwn(inlineOptions, "blueprint") || Object.hasOwn(inlineOptions, "blueprint-file")) {
|
|
160
|
-
return {
|
|
161
|
-
ok: false,
|
|
162
|
-
payload: buildSessionErrorResponse({
|
|
163
|
-
targetRoot: cwd,
|
|
164
|
-
sessionId,
|
|
165
|
-
code: "session_blueprint_input_removed",
|
|
166
|
-
message: "The session blueprint step no longer accepts --blueprint input. Run the step to get the Codex prompt, let Codex edit .jskit/APP_BLUEPRINT.md, then run the step again.",
|
|
167
|
-
repairCommand: `jskit session ${sessionId} step`
|
|
168
|
-
})
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const reworkNotes = await resolveTextInput({
|
|
173
|
-
codePrefix: "rework_notes",
|
|
174
|
-
fileOption: "rework-notes-file",
|
|
175
|
-
inlineOptions,
|
|
176
|
-
io,
|
|
177
|
-
repairCommand: `jskit session ${sessionId} step --user-check failed --rework-notes -`,
|
|
178
|
-
cwd,
|
|
179
|
-
sessionId,
|
|
180
|
-
stdinOption: "-",
|
|
181
|
-
textOption: "rework-notes"
|
|
182
|
-
});
|
|
183
|
-
if (reworkNotes.ok === false) {
|
|
184
|
-
return reworkNotes;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const skipReason = await resolveTextInput({
|
|
188
|
-
codePrefix: "skip_reason",
|
|
189
|
-
fileOption: "skip-reason-file",
|
|
190
|
-
inlineOptions,
|
|
191
|
-
io,
|
|
192
|
-
repairCommand: `jskit session ${sessionId} skip --skip-reason "<reason>"`,
|
|
193
|
-
cwd,
|
|
194
|
-
sessionId,
|
|
195
|
-
stdinOption: "-",
|
|
196
|
-
textOption: "skip-reason"
|
|
197
|
-
});
|
|
198
|
-
if (skipReason.ok === false) {
|
|
199
|
-
return skipReason;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return {
|
|
203
|
-
ok: true,
|
|
204
|
-
reworkNotes: reworkNotes.value,
|
|
205
|
-
skipReason: skipReason.value
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function normalizeStepOptions(inlineOptions = {}) {
|
|
210
|
-
const options = {
|
|
211
|
-
...inlineOptions,
|
|
212
|
-
mergePr: inlineOptions["merge-pr"] === "true" || inlineOptions.mergePr === true,
|
|
213
|
-
prompt: inlineOptions.prompt,
|
|
214
|
-
reviewFindings: inlineOptions["review-findings"] || inlineOptions.reviewFindings,
|
|
215
|
-
resolveDeslop: inlineOptions["resolve-deslop"] === "true" || inlineOptions.resolveDeslop === true,
|
|
216
|
-
skipStep: inlineOptions["skip-step"] === "true" ||
|
|
217
|
-
inlineOptions.skipStep === true ||
|
|
218
|
-
inlineOptions.skip === true ||
|
|
219
|
-
inlineOptions.skip === "true",
|
|
220
|
-
userCheck: inlineOptions["user-check"] || inlineOptions.userCheck
|
|
221
|
-
};
|
|
222
|
-
if (Object.hasOwn(inlineOptions, "review-findings-remaining") || Object.hasOwn(inlineOptions, "reviewFindingsRemaining")) {
|
|
223
|
-
options.reviewFindingsRemaining = inlineOptions["review-findings-remaining"] === "true" ||
|
|
224
|
-
inlineOptions.reviewFindingsRemaining === true;
|
|
225
|
-
}
|
|
226
|
-
return options;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function resolveListArchiveOption(options = {}) {
|
|
230
|
-
const archives = [];
|
|
231
|
-
if (options.abandoned) {
|
|
232
|
-
archives.push("abandoned");
|
|
233
|
-
}
|
|
234
|
-
if (options.completed) {
|
|
235
|
-
archives.push("completed");
|
|
236
|
-
}
|
|
237
|
-
if (options.all) {
|
|
238
|
-
archives.push("all");
|
|
239
|
-
}
|
|
240
|
-
return archives.length > 0 ? archives : "active";
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
async function runSessionStepCommand({
|
|
244
|
-
cwd,
|
|
245
|
-
inlineOptions = {},
|
|
246
|
-
io = {},
|
|
247
|
-
sessionId
|
|
248
|
-
}) {
|
|
249
|
-
const stepInputs = await resolveStepInputs({
|
|
250
|
-
inlineOptions,
|
|
251
|
-
io,
|
|
252
|
-
cwd,
|
|
253
|
-
sessionId
|
|
254
|
-
});
|
|
255
|
-
return stepInputs.ok === false
|
|
256
|
-
? stepInputs.payload
|
|
257
|
-
: runSessionStep({
|
|
258
|
-
targetRoot: cwd,
|
|
259
|
-
sessionId,
|
|
260
|
-
options: {
|
|
261
|
-
...normalizeStepOptions(inlineOptions),
|
|
262
|
-
reworkNotes: stepInputs.reworkNotes,
|
|
263
|
-
skipReason: stepInputs.skipReason
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
async function runNextSessionStep({
|
|
269
|
-
cwd,
|
|
270
|
-
sessionId
|
|
271
|
-
}) {
|
|
272
|
-
return advanceSessionStep({
|
|
273
|
-
targetRoot: cwd,
|
|
274
|
-
sessionId
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
async function runSkipSessionStep({
|
|
279
|
-
cwd,
|
|
280
|
-
inlineOptions = {},
|
|
281
|
-
io = {},
|
|
282
|
-
sessionId
|
|
283
|
-
}) {
|
|
284
|
-
return runSessionStepCommand({
|
|
285
|
-
cwd,
|
|
286
|
-
inlineOptions: {
|
|
287
|
-
...inlineOptions,
|
|
288
|
-
skipStep: true
|
|
289
|
-
},
|
|
290
|
-
io,
|
|
291
|
-
sessionId
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
async function runDeslopSessionStep({
|
|
296
|
-
cwd,
|
|
297
|
-
sessionId
|
|
298
|
-
}) {
|
|
299
|
-
const details = await inspectSessionDetails({
|
|
300
|
-
targetRoot: cwd,
|
|
301
|
-
sessionId
|
|
302
|
-
});
|
|
303
|
-
if (details.ok === false) {
|
|
304
|
-
return details;
|
|
305
|
-
}
|
|
306
|
-
if (details.currentStep === "review_changes_accepted") {
|
|
307
|
-
const accepted = await runSessionStep({
|
|
308
|
-
targetRoot: cwd,
|
|
309
|
-
sessionId,
|
|
310
|
-
options: {
|
|
311
|
-
reviewFindingsRemaining: true
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
if (accepted.ok === false) {
|
|
315
|
-
return accepted;
|
|
316
|
-
}
|
|
317
|
-
} else if (details.currentStep !== "review_prompt_rendered") {
|
|
318
|
-
return buildSessionErrorResponse({
|
|
319
|
-
targetRoot: cwd,
|
|
320
|
-
sessionId,
|
|
321
|
-
code: "deslop_not_current_step",
|
|
322
|
-
message: `Cannot run deslop while current step is ${details.currentStep || "done"}.`,
|
|
323
|
-
repairCommand: `jskit session ${sessionId}`
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
return runSessionStep({
|
|
327
|
-
targetRoot: cwd,
|
|
328
|
-
sessionId,
|
|
329
|
-
options: {}
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function createSessionCommands() {
|
|
334
|
-
return {
|
|
335
|
-
async commandSession({
|
|
336
|
-
positional = [],
|
|
337
|
-
options = {},
|
|
338
|
-
cwd,
|
|
339
|
-
stdout,
|
|
340
|
-
io = {}
|
|
341
|
-
} = {}) {
|
|
342
|
-
const [first, second, third] = positional;
|
|
343
|
-
const inlineOptions = options.inlineOptions || {};
|
|
344
|
-
let payload;
|
|
345
|
-
|
|
346
|
-
if (!first) {
|
|
347
|
-
payload = await listSessions({
|
|
348
|
-
targetRoot: cwd,
|
|
349
|
-
archive: resolveListArchiveOption(options)
|
|
350
|
-
});
|
|
351
|
-
} else if (first === "create" || first === "new") {
|
|
352
|
-
payload = await createSession({ targetRoot: cwd });
|
|
353
|
-
} else if (second === "step") {
|
|
354
|
-
payload = await inspectSessionDetails({
|
|
355
|
-
targetRoot: cwd,
|
|
356
|
-
sessionId: first
|
|
357
|
-
});
|
|
358
|
-
} else if (second === "run") {
|
|
359
|
-
const details = await inspectSessionDetails({
|
|
360
|
-
targetRoot: cwd,
|
|
361
|
-
sessionId: first
|
|
362
|
-
});
|
|
363
|
-
payload = {
|
|
364
|
-
...details,
|
|
365
|
-
ok: false,
|
|
366
|
-
errors: [
|
|
367
|
-
{
|
|
368
|
-
code: "explicit_session_action_required",
|
|
369
|
-
message: "Generic run is not a session action. Use one of the available step commands, then run next."
|
|
370
|
-
}
|
|
371
|
-
]
|
|
372
|
-
};
|
|
373
|
-
} else if ([
|
|
374
|
-
"create_worktree",
|
|
375
|
-
"run_npm_install",
|
|
376
|
-
"define_issue",
|
|
377
|
-
"create_issue_file",
|
|
378
|
-
"create_issue_on_gh",
|
|
379
|
-
"make_plan",
|
|
380
|
-
"execute_plan",
|
|
381
|
-
"run_deep_ui_check",
|
|
382
|
-
"run_automated_checks",
|
|
383
|
-
"update_blueprint",
|
|
384
|
-
"commit_changes",
|
|
385
|
-
"create_pull_request_file",
|
|
386
|
-
"create_pr_on_gh",
|
|
387
|
-
"prepare_for_merge",
|
|
388
|
-
"merge_pr",
|
|
389
|
-
"sync_main_checkout",
|
|
390
|
-
"finish_session"
|
|
391
|
-
].includes(second)) {
|
|
392
|
-
payload = await runSessionStepAction({
|
|
393
|
-
action: second,
|
|
394
|
-
targetRoot: cwd,
|
|
395
|
-
sessionId: first,
|
|
396
|
-
options: normalizeStepOptions(inlineOptions)
|
|
397
|
-
});
|
|
398
|
-
} else if (second === "next") {
|
|
399
|
-
payload = await runNextSessionStep({
|
|
400
|
-
cwd,
|
|
401
|
-
sessionId: first
|
|
402
|
-
});
|
|
403
|
-
} else if (second === "skip") {
|
|
404
|
-
payload = await runSkipSessionStep({
|
|
405
|
-
cwd,
|
|
406
|
-
inlineOptions,
|
|
407
|
-
io,
|
|
408
|
-
sessionId: first
|
|
409
|
-
});
|
|
410
|
-
} else if (second === "deslop") {
|
|
411
|
-
payload = await runDeslopSessionStep({
|
|
412
|
-
cwd,
|
|
413
|
-
sessionId: first
|
|
414
|
-
});
|
|
415
|
-
} else if (second === "resolve-deslop") {
|
|
416
|
-
payload = await runSessionStepAction({
|
|
417
|
-
action: "resolve_deslop",
|
|
418
|
-
targetRoot: cwd,
|
|
419
|
-
sessionId: first,
|
|
420
|
-
options: {
|
|
421
|
-
resolveDeslop: true
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
} else if (second === "abandon") {
|
|
425
|
-
payload = await abandonSession({
|
|
426
|
-
targetRoot: cwd,
|
|
427
|
-
sessionId: first
|
|
428
|
-
});
|
|
429
|
-
} else if (second === "diff") {
|
|
430
|
-
payload = await inspectSessionDiff({
|
|
431
|
-
targetRoot: cwd,
|
|
432
|
-
sessionId: first
|
|
433
|
-
});
|
|
434
|
-
} else if (second === "rewind") {
|
|
435
|
-
payload = await rewindSession({
|
|
436
|
-
targetRoot: cwd,
|
|
437
|
-
sessionId: first,
|
|
438
|
-
stepId: inlineOptions.step || third
|
|
439
|
-
});
|
|
440
|
-
} else if (second === "adopt-codex-thread") {
|
|
441
|
-
payload = await adoptCodexThreadId({
|
|
442
|
-
targetRoot: cwd,
|
|
443
|
-
sessionId: first,
|
|
444
|
-
codexThreadId: inlineOptions["codex-thread-id"] || inlineOptions.codexThreadId
|
|
445
|
-
});
|
|
446
|
-
} else if (!second) {
|
|
447
|
-
payload = await inspectSessionDetails({
|
|
448
|
-
targetRoot: cwd,
|
|
449
|
-
sessionId: first
|
|
450
|
-
});
|
|
451
|
-
} else {
|
|
452
|
-
payload = buildSessionErrorResponse({
|
|
453
|
-
targetRoot: cwd,
|
|
454
|
-
sessionId: first,
|
|
455
|
-
code: "unknown_session_subcommand",
|
|
456
|
-
message: `Unknown session subcommand: ${second}`,
|
|
457
|
-
repairCommand: `jskit session ${first}`
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
if (options.json) {
|
|
462
|
-
writeJson(stdout, payload);
|
|
463
|
-
} else {
|
|
464
|
-
writeSessionText(stdout, payload);
|
|
465
|
-
}
|
|
466
|
-
return payload.ok === false ? 1 : 0;
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
export { createSessionCommands };
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { access, stat } from "node:fs/promises";
|
|
2
|
-
import { constants as fsConstants } from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
|
|
5
|
-
const REQUIRED_READY_FILES = Object.freeze([
|
|
6
|
-
"package.json",
|
|
7
|
-
".jskit/lock.json",
|
|
8
|
-
"config/public.js"
|
|
9
|
-
]);
|
|
10
|
-
const REQUIRED_READY_DIRECTORIES = Object.freeze([
|
|
11
|
-
"src",
|
|
12
|
-
"packages"
|
|
13
|
-
]);
|
|
14
|
-
|
|
15
|
-
async function pathExists(filePath) {
|
|
16
|
-
try {
|
|
17
|
-
await access(filePath, fsConstants.F_OK);
|
|
18
|
-
return true;
|
|
19
|
-
} catch {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async function directoryExists(filePath) {
|
|
25
|
-
try {
|
|
26
|
-
return (await stat(filePath)).isDirectory();
|
|
27
|
-
} catch {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async function inspectReadyJskitAppRoot(rootPath) {
|
|
33
|
-
const missing = [];
|
|
34
|
-
for (const relativePath of REQUIRED_READY_FILES) {
|
|
35
|
-
if (!await pathExists(path.join(rootPath, relativePath))) {
|
|
36
|
-
missing.push(relativePath);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
for (const relativePath of REQUIRED_READY_DIRECTORIES) {
|
|
40
|
-
if (!await directoryExists(path.join(rootPath, relativePath))) {
|
|
41
|
-
missing.push(`${relativePath}/`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
missing,
|
|
46
|
-
ok: missing.length < 1,
|
|
47
|
-
requiredDirectories: [...REQUIRED_READY_DIRECTORIES],
|
|
48
|
-
requiredFiles: [...REQUIRED_READY_FILES],
|
|
49
|
-
rootPath
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export {
|
|
54
|
-
inspectReadyJskitAppRoot
|
|
55
|
-
};
|