kadai 0.6.0 → 0.8.0
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/dist/cli.js +354 -246
- package/dist/exports/ink.js +3 -0
- package/dist/exports/jsx-dev-runtime.js +3 -0
- package/dist/exports/jsx-runtime.js +3 -0
- package/dist/exports/react.js +7 -0
- package/dist/exports/ui.js +3 -0
- package/dist/types.js +1 -0
- package/package.json +10 -1
package/dist/cli.js
CHANGED
|
@@ -29,14 +29,67 @@ var __export = (target, all) => {
|
|
|
29
29
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
30
30
|
var __require = import.meta.require;
|
|
31
31
|
|
|
32
|
+
// src/core/shared-deps.ts
|
|
33
|
+
import { existsSync, mkdirSync, symlinkSync, unlinkSync } from "fs";
|
|
34
|
+
import { dirname, join } from "path";
|
|
35
|
+
function registerSharedDeps() {
|
|
36
|
+
const escaped = SHARED_DEPS.map((d) => d.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
37
|
+
const filter = new RegExp(`^(${escaped.join("|")})(/.*)?$`);
|
|
38
|
+
Bun.plugin({
|
|
39
|
+
name: "kadai-shared-deps",
|
|
40
|
+
setup(build) {
|
|
41
|
+
build.onResolve({ filter }, (args) => {
|
|
42
|
+
try {
|
|
43
|
+
return { path: __require.resolve(args.path) };
|
|
44
|
+
} catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function ensureKadaiResolvable(projectNodeModules) {
|
|
52
|
+
const link = join(projectNodeModules, "kadai");
|
|
53
|
+
if (existsSync(link))
|
|
54
|
+
return null;
|
|
55
|
+
const kadaiRoot = dirname(import.meta.dir);
|
|
56
|
+
if (!existsSync(join(kadaiRoot, "package.json")))
|
|
57
|
+
return null;
|
|
58
|
+
try {
|
|
59
|
+
if (!existsSync(projectNodeModules)) {
|
|
60
|
+
mkdirSync(projectNodeModules, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
symlinkSync(kadaiRoot, link);
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
let cleaned = false;
|
|
67
|
+
const cleanup = () => {
|
|
68
|
+
if (cleaned)
|
|
69
|
+
return;
|
|
70
|
+
cleaned = true;
|
|
71
|
+
try {
|
|
72
|
+
unlinkSync(link);
|
|
73
|
+
} catch {}
|
|
74
|
+
};
|
|
75
|
+
process.on("exit", cleanup);
|
|
76
|
+
process.on("SIGTERM", cleanup);
|
|
77
|
+
process.on("SIGINT", cleanup);
|
|
78
|
+
return cleanup;
|
|
79
|
+
}
|
|
80
|
+
var SHARED_DEPS;
|
|
81
|
+
var init_shared_deps = __esm(() => {
|
|
82
|
+
SHARED_DEPS = ["ink", "react", "@inkjs/ui"];
|
|
83
|
+
});
|
|
84
|
+
|
|
32
85
|
// src/core/config.ts
|
|
33
86
|
var exports_config = {};
|
|
34
87
|
__export(exports_config, {
|
|
35
88
|
loadConfig: () => loadConfig
|
|
36
89
|
});
|
|
37
|
-
import { join } from "path";
|
|
90
|
+
import { join as join2 } from "path";
|
|
38
91
|
async function loadConfig(kadaiDir) {
|
|
39
|
-
const configPath =
|
|
92
|
+
const configPath = join2(kadaiDir, "config.ts");
|
|
40
93
|
const configFile = Bun.file(configPath);
|
|
41
94
|
if (!await configFile.exists()) {
|
|
42
95
|
return { ...DEFAULT_CONFIG };
|
|
@@ -150,7 +203,7 @@ var init_metadata = __esm(() => {
|
|
|
150
203
|
|
|
151
204
|
// src/core/loader.ts
|
|
152
205
|
import { readdir } from "fs/promises";
|
|
153
|
-
import { join as
|
|
206
|
+
import { join as join3 } from "path";
|
|
154
207
|
async function readShebang(filePath) {
|
|
155
208
|
try {
|
|
156
209
|
const head = await Bun.file(filePath).slice(0, 256).text();
|
|
@@ -192,7 +245,7 @@ async function getGitAddedDates(dir) {
|
|
|
192
245
|
if (/^\d+$/.test(trimmed)) {
|
|
193
246
|
currentTimestamp = Number.parseInt(trimmed, 10) * 1000;
|
|
194
247
|
} else {
|
|
195
|
-
const absPath =
|
|
248
|
+
const absPath = join3(repoRoot, trimmed);
|
|
196
249
|
dates.set(absPath, currentTimestamp);
|
|
197
250
|
}
|
|
198
251
|
}
|
|
@@ -218,7 +271,7 @@ async function scanDirectory(baseDir, currentDir, category, actions, depth, gitD
|
|
|
218
271
|
for (const entry of entries) {
|
|
219
272
|
if (entry.name.startsWith("_") || entry.name.startsWith("."))
|
|
220
273
|
continue;
|
|
221
|
-
const fullPath =
|
|
274
|
+
const fullPath = join3(currentDir, entry.name);
|
|
222
275
|
if (entry.isDirectory()) {
|
|
223
276
|
await scanDirectory(baseDir, fullPath, [...category, entry.name], actions, depth + 1, gitDates, origin);
|
|
224
277
|
} else if (entry.isFile()) {
|
|
@@ -247,15 +300,15 @@ async function scanDirectory(baseDir, currentDir, category, actions, depth, gitD
|
|
|
247
300
|
function findZcliDir(cwd) {
|
|
248
301
|
let dir = cwd;
|
|
249
302
|
while (true) {
|
|
250
|
-
const candidate =
|
|
251
|
-
if (Bun.file(
|
|
303
|
+
const candidate = join3(dir, ".kadai");
|
|
304
|
+
if (Bun.file(join3(candidate, "actions")).name) {
|
|
252
305
|
try {
|
|
253
306
|
const stat = __require("fs").statSync(candidate);
|
|
254
307
|
if (stat.isDirectory())
|
|
255
308
|
return candidate;
|
|
256
309
|
} catch {}
|
|
257
310
|
}
|
|
258
|
-
const parent =
|
|
311
|
+
const parent = join3(dir, "..");
|
|
259
312
|
if (parent === dir)
|
|
260
313
|
break;
|
|
261
314
|
dir = parent;
|
|
@@ -276,9 +329,24 @@ var init_loader = __esm(() => {
|
|
|
276
329
|
]);
|
|
277
330
|
});
|
|
278
331
|
|
|
332
|
+
// src/core/last-action.ts
|
|
333
|
+
import { join as join4 } from "path";
|
|
334
|
+
async function saveLastAction(kadaiDir, actionId) {
|
|
335
|
+
await Bun.write(join4(kadaiDir, LAST_ACTION_FILE), actionId);
|
|
336
|
+
}
|
|
337
|
+
async function loadLastAction(kadaiDir) {
|
|
338
|
+
const file = Bun.file(join4(kadaiDir, LAST_ACTION_FILE));
|
|
339
|
+
if (!await file.exists())
|
|
340
|
+
return null;
|
|
341
|
+
const content = (await file.text()).trim();
|
|
342
|
+
return content || null;
|
|
343
|
+
}
|
|
344
|
+
var LAST_ACTION_FILE = ".last-action";
|
|
345
|
+
var init_last_action = () => {};
|
|
346
|
+
|
|
279
347
|
// src/core/fetchers/github.ts
|
|
280
348
|
import { mkdir, rm } from "fs/promises";
|
|
281
|
-
import { join as
|
|
349
|
+
import { join as join5 } from "path";
|
|
282
350
|
async function fetchGithubPlugin(source, destDir) {
|
|
283
351
|
const ref = source.ref ?? "main";
|
|
284
352
|
const repoUrl = `https://github.com/${source.github}.git`;
|
|
@@ -296,7 +364,7 @@ async function fetchGithubPlugin(source, destDir) {
|
|
|
296
364
|
});
|
|
297
365
|
const sha = (await new Response(shaProc.stdout).text()).trim();
|
|
298
366
|
await shaProc.exited;
|
|
299
|
-
await rm(
|
|
367
|
+
await rm(join5(destDir, ".git"), { recursive: true, force: true });
|
|
300
368
|
return { resolvedVersion: sha };
|
|
301
369
|
}
|
|
302
370
|
async function checkGithubUpdate(source, currentSha) {
|
|
@@ -321,29 +389,25 @@ async function checkGithubUpdate(source, currentSha) {
|
|
|
321
389
|
}
|
|
322
390
|
var init_github = () => {};
|
|
323
391
|
|
|
324
|
-
// src/core/
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const withoutPrerelease = v.replace(/^v/, "").split("-")[0] ?? "";
|
|
329
|
-
const clean = withoutPrerelease.split("+")[0] ?? "";
|
|
330
|
-
const parts = clean.split(".");
|
|
331
|
-
if (parts.length !== 3)
|
|
332
|
-
return null;
|
|
333
|
-
const nums = parts.map(Number);
|
|
334
|
-
if (nums.some((n) => Number.isNaN(n)))
|
|
392
|
+
// src/core/semver.ts
|
|
393
|
+
function parseSemver(version) {
|
|
394
|
+
const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
395
|
+
if (!match)
|
|
335
396
|
return null;
|
|
336
|
-
return
|
|
397
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
337
398
|
}
|
|
338
399
|
function compareSemver(a, b) {
|
|
339
400
|
for (let i = 0;i < 3; i++) {
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
return av - bv;
|
|
401
|
+
const diff = a[i] - b[i];
|
|
402
|
+
if (diff !== 0)
|
|
403
|
+
return diff;
|
|
344
404
|
}
|
|
345
405
|
return 0;
|
|
346
406
|
}
|
|
407
|
+
|
|
408
|
+
// src/core/fetchers/npm.ts
|
|
409
|
+
import { mkdir as mkdir2, unlink } from "fs/promises";
|
|
410
|
+
import { join as join6 } from "path";
|
|
347
411
|
function satisfies(version, range) {
|
|
348
412
|
if (range === "*" || range === "x")
|
|
349
413
|
return true;
|
|
@@ -417,7 +481,7 @@ async function fetchNpmPlugin(source, destDir) {
|
|
|
417
481
|
}
|
|
418
482
|
await mkdir2(destDir, { recursive: true });
|
|
419
483
|
const tarball = await tarballRes.arrayBuffer();
|
|
420
|
-
const tarballPath =
|
|
484
|
+
const tarballPath = join6(destDir, ".plugin.tgz");
|
|
421
485
|
await Bun.write(tarballPath, tarball);
|
|
422
486
|
const proc = Bun.spawn(["tar", "xzf", tarballPath, "--strip-components=1"], {
|
|
423
487
|
cwd: destDir,
|
|
@@ -457,9 +521,9 @@ var init_which = __esm(() => {
|
|
|
457
521
|
});
|
|
458
522
|
|
|
459
523
|
// src/core/pm.ts
|
|
460
|
-
import { join as
|
|
524
|
+
import { join as join7 } from "path";
|
|
461
525
|
async function resolvePM(dir) {
|
|
462
|
-
const pkgJsonPath =
|
|
526
|
+
const pkgJsonPath = join7(dir, "package.json");
|
|
463
527
|
try {
|
|
464
528
|
const file = Bun.file(pkgJsonPath);
|
|
465
529
|
if (await file.exists()) {
|
|
@@ -489,13 +553,13 @@ var init_pm = __esm(() => {
|
|
|
489
553
|
});
|
|
490
554
|
|
|
491
555
|
// src/core/plugins.ts
|
|
492
|
-
import { existsSync } from "fs";
|
|
556
|
+
import { existsSync as existsSync2 } from "fs";
|
|
493
557
|
import { mkdir as mkdir3, rm as rm2 } from "fs/promises";
|
|
494
|
-
import { isAbsolute, join as
|
|
558
|
+
import { isAbsolute, join as join8, resolve } from "path";
|
|
495
559
|
async function ensurePluginCacheDir(kadaiDir) {
|
|
496
|
-
const cacheDir =
|
|
560
|
+
const cacheDir = join8(kadaiDir, ".cache", "plugins");
|
|
497
561
|
await mkdir3(cacheDir, { recursive: true });
|
|
498
|
-
const gitignorePath =
|
|
562
|
+
const gitignorePath = join8(kadaiDir, ".cache", ".gitignore");
|
|
499
563
|
const gitignoreFile = Bun.file(gitignorePath);
|
|
500
564
|
if (!await gitignoreFile.exists()) {
|
|
501
565
|
await Bun.write(gitignorePath, `*
|
|
@@ -522,7 +586,7 @@ function pluginDisplayName(source) {
|
|
|
522
586
|
}
|
|
523
587
|
async function readPluginMeta(cacheDir) {
|
|
524
588
|
try {
|
|
525
|
-
const file = Bun.file(
|
|
589
|
+
const file = Bun.file(join8(cacheDir, ".plugin-meta.json"));
|
|
526
590
|
if (!await file.exists())
|
|
527
591
|
return null;
|
|
528
592
|
return await file.json();
|
|
@@ -531,18 +595,18 @@ async function readPluginMeta(cacheDir) {
|
|
|
531
595
|
}
|
|
532
596
|
}
|
|
533
597
|
async function writePluginMeta(cacheDir, meta) {
|
|
534
|
-
await Bun.write(
|
|
598
|
+
await Bun.write(join8(cacheDir, ".plugin-meta.json"), JSON.stringify(meta, null, 2));
|
|
535
599
|
}
|
|
536
600
|
async function loadCachedPlugins(kadaiDir, plugins) {
|
|
537
601
|
const allActions = [];
|
|
538
|
-
const cacheBase =
|
|
602
|
+
const cacheBase = join8(kadaiDir, ".cache", "plugins");
|
|
539
603
|
for (const source of plugins) {
|
|
540
604
|
if ("path" in source)
|
|
541
605
|
continue;
|
|
542
606
|
const key = cacheKeyFor(source);
|
|
543
|
-
const pluginCacheDir =
|
|
544
|
-
const actionsDir =
|
|
545
|
-
if (!
|
|
607
|
+
const pluginCacheDir = join8(cacheBase, key);
|
|
608
|
+
const actionsDir = join8(pluginCacheDir, "actions");
|
|
609
|
+
if (!existsSync2(actionsDir))
|
|
546
610
|
continue;
|
|
547
611
|
const name = pluginDisplayName(source);
|
|
548
612
|
const origin = { type: "plugin", pluginName: name };
|
|
@@ -556,8 +620,8 @@ async function loadCachedPlugins(kadaiDir, plugins) {
|
|
|
556
620
|
return allActions;
|
|
557
621
|
}
|
|
558
622
|
async function installPluginDeps(pluginDir) {
|
|
559
|
-
const pkgJsonPath =
|
|
560
|
-
if (!
|
|
623
|
+
const pkgJsonPath = join8(pluginDir, "package.json");
|
|
624
|
+
if (!existsSync2(pkgJsonPath))
|
|
561
625
|
return;
|
|
562
626
|
const pm = await resolvePM(pluginDir);
|
|
563
627
|
const proc = Bun.spawn(pm.install, {
|
|
@@ -574,7 +638,7 @@ async function installPluginDeps(pluginDir) {
|
|
|
574
638
|
async function syncPlugin(kadaiDir, source) {
|
|
575
639
|
const cacheBase = await ensurePluginCacheDir(kadaiDir);
|
|
576
640
|
const key = cacheKeyFor(source);
|
|
577
|
-
const pluginCacheDir =
|
|
641
|
+
const pluginCacheDir = join8(cacheBase, key);
|
|
578
642
|
const meta = await readPluginMeta(pluginCacheDir);
|
|
579
643
|
if (meta) {
|
|
580
644
|
let needsUpdate = false;
|
|
@@ -624,8 +688,8 @@ async function syncPlugins(kadaiDir, plugins, callbacks) {
|
|
|
624
688
|
}
|
|
625
689
|
async function loadPathPlugin(kadaiDir, source) {
|
|
626
690
|
const pluginRoot = isAbsolute(source.path) ? source.path : resolve(kadaiDir, source.path);
|
|
627
|
-
const actionsDir =
|
|
628
|
-
if (!
|
|
691
|
+
const actionsDir = join8(pluginRoot, "actions");
|
|
692
|
+
if (!existsSync2(actionsDir))
|
|
629
693
|
return [];
|
|
630
694
|
const name = source.path;
|
|
631
695
|
const origin = { type: "plugin", pluginName: name };
|
|
@@ -640,8 +704,8 @@ async function loadUserGlobalActions() {
|
|
|
640
704
|
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
641
705
|
if (!homeDir)
|
|
642
706
|
return [];
|
|
643
|
-
const actionsDir =
|
|
644
|
-
if (!
|
|
707
|
+
const actionsDir = join8(homeDir, ".kadai", "actions");
|
|
708
|
+
if (!existsSync2(actionsDir))
|
|
645
709
|
return [];
|
|
646
710
|
const origin = { type: "plugin", pluginName: "~" };
|
|
647
711
|
const actions = await loadActions(actionsDir, origin);
|
|
@@ -729,13 +793,14 @@ var exports_commands = {};
|
|
|
729
793
|
__export(exports_commands, {
|
|
730
794
|
handleSync: () => handleSync,
|
|
731
795
|
handleRun: () => handleRun,
|
|
796
|
+
handleRerun: () => handleRerun,
|
|
732
797
|
handleList: () => handleList
|
|
733
798
|
});
|
|
734
|
-
import { join as
|
|
799
|
+
import { join as join9 } from "path";
|
|
735
800
|
async function handleList(options) {
|
|
736
801
|
const { kadaiDir, all } = options;
|
|
737
802
|
const config = await loadConfig(kadaiDir);
|
|
738
|
-
const actionsDir =
|
|
803
|
+
const actionsDir = join9(kadaiDir, config.actionsDir ?? "actions");
|
|
739
804
|
let actions = await loadActions(actionsDir);
|
|
740
805
|
const globalActions = await loadUserGlobalActions();
|
|
741
806
|
actions = [...actions, ...globalActions];
|
|
@@ -768,7 +833,7 @@ async function handleList(options) {
|
|
|
768
833
|
async function handleRun(options) {
|
|
769
834
|
const { kadaiDir, actionId, cwd } = options;
|
|
770
835
|
const config = await loadConfig(kadaiDir);
|
|
771
|
-
const actionsDir =
|
|
836
|
+
const actionsDir = join9(kadaiDir, config.actionsDir ?? "actions");
|
|
772
837
|
let actions = await loadActions(actionsDir);
|
|
773
838
|
const globalActions = await loadUserGlobalActions();
|
|
774
839
|
actions = [...actions, ...globalActions];
|
|
@@ -788,7 +853,9 @@ async function handleRun(options) {
|
|
|
788
853
|
`);
|
|
789
854
|
process.exit(1);
|
|
790
855
|
}
|
|
856
|
+
await saveLastAction(kadaiDir, actionId);
|
|
791
857
|
if (action.runtime === "ink") {
|
|
858
|
+
const cleanupKadai = ensureKadaiResolvable(join9(cwd, "node_modules"));
|
|
792
859
|
const mod = await import(action.filePath);
|
|
793
860
|
if (typeof mod.default !== "function") {
|
|
794
861
|
process.stderr.write(`Error: "${action.filePath}" does not export a default function component
|
|
@@ -806,6 +873,7 @@ async function handleRun(options) {
|
|
|
806
873
|
}));
|
|
807
874
|
await instance.waitUntilExit();
|
|
808
875
|
cleanupFullscreen?.();
|
|
876
|
+
cleanupKadai?.();
|
|
809
877
|
process.exit(0);
|
|
810
878
|
}
|
|
811
879
|
const cmd = resolveCommand(action);
|
|
@@ -829,6 +897,16 @@ async function handleRun(options) {
|
|
|
829
897
|
const exitCode = await proc.exited;
|
|
830
898
|
process.exit(exitCode);
|
|
831
899
|
}
|
|
900
|
+
async function handleRerun(options) {
|
|
901
|
+
const { kadaiDir, cwd } = options;
|
|
902
|
+
const actionId = await loadLastAction(kadaiDir);
|
|
903
|
+
if (!actionId) {
|
|
904
|
+
process.stderr.write(`No last action found. Run an action first before using --rerun.
|
|
905
|
+
`);
|
|
906
|
+
process.exit(1);
|
|
907
|
+
}
|
|
908
|
+
return handleRun({ kadaiDir, actionId, cwd });
|
|
909
|
+
}
|
|
832
910
|
async function handleSync(options) {
|
|
833
911
|
const { kadaiDir } = options;
|
|
834
912
|
const config = await loadConfig(kadaiDir);
|
|
@@ -875,6 +953,8 @@ All plugins synced.
|
|
|
875
953
|
var init_commands = __esm(() => {
|
|
876
954
|
init_config();
|
|
877
955
|
init_loader();
|
|
956
|
+
init_last_action();
|
|
957
|
+
init_shared_deps();
|
|
878
958
|
init_plugins();
|
|
879
959
|
init_runner();
|
|
880
960
|
});
|
|
@@ -883,11 +963,20 @@ var init_commands = __esm(() => {
|
|
|
883
963
|
var require_package = __commonJS((exports, module) => {
|
|
884
964
|
module.exports = {
|
|
885
965
|
name: "kadai",
|
|
886
|
-
version: "0.
|
|
966
|
+
version: "0.8.0",
|
|
887
967
|
type: "module",
|
|
888
968
|
bin: {
|
|
889
969
|
kadai: "./dist/cli.js"
|
|
890
970
|
},
|
|
971
|
+
exports: {
|
|
972
|
+
".": "./dist/cli.js",
|
|
973
|
+
"./types": "./dist/types.js",
|
|
974
|
+
"./ink": "./dist/exports/ink.js",
|
|
975
|
+
"./ui": "./dist/exports/ui.js",
|
|
976
|
+
"./react": "./dist/exports/react.js",
|
|
977
|
+
"./react/jsx-runtime": "./dist/exports/jsx-runtime.js",
|
|
978
|
+
"./react/jsx-dev-runtime": "./dist/exports/jsx-dev-runtime.js"
|
|
979
|
+
},
|
|
891
980
|
scripts: {
|
|
892
981
|
build: "bun build.ts",
|
|
893
982
|
check: "tsc --noEmit && biome check ./src ./test",
|
|
@@ -924,7 +1013,7 @@ __export(exports_mcp, {
|
|
|
924
1013
|
ensureMcpConfig: () => ensureMcpConfig,
|
|
925
1014
|
actionIdToToolName: () => actionIdToToolName
|
|
926
1015
|
});
|
|
927
|
-
import { join as
|
|
1016
|
+
import { join as join10, resolve as resolve2 } from "path";
|
|
928
1017
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
929
1018
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
930
1019
|
function resolveInvocationCommand() {
|
|
@@ -951,40 +1040,35 @@ function buildToolDescription(action) {
|
|
|
951
1040
|
return parts.join(" ");
|
|
952
1041
|
}
|
|
953
1042
|
async function ensureMcpConfig(projectRoot) {
|
|
954
|
-
const mcpJsonPath =
|
|
1043
|
+
const mcpJsonPath = join10(projectRoot, ".mcp.json");
|
|
955
1044
|
const mcpFile = Bun.file(mcpJsonPath);
|
|
956
1045
|
const kadaiEntry = resolveInvocationCommand();
|
|
957
1046
|
if (await mcpFile.exists()) {
|
|
958
1047
|
const existing = await mcpFile.json();
|
|
959
1048
|
if (existing.mcpServers?.kadai) {
|
|
960
|
-
|
|
961
|
-
`);
|
|
962
|
-
return;
|
|
1049
|
+
return false;
|
|
963
1050
|
}
|
|
964
1051
|
existing.mcpServers = existing.mcpServers ?? {};
|
|
965
1052
|
existing.mcpServers.kadai = kadaiEntry;
|
|
966
1053
|
await Bun.write(mcpJsonPath, `${JSON.stringify(existing, null, 2)}
|
|
967
1054
|
`);
|
|
968
|
-
|
|
969
|
-
`);
|
|
970
|
-
} else {
|
|
971
|
-
const config = {
|
|
972
|
-
mcpServers: {
|
|
973
|
-
kadai: kadaiEntry
|
|
974
|
-
}
|
|
975
|
-
};
|
|
976
|
-
await Bun.write(mcpJsonPath, `${JSON.stringify(config, null, 2)}
|
|
977
|
-
`);
|
|
978
|
-
process.stderr.write(`Created .mcp.json with kadai MCP server config
|
|
979
|
-
`);
|
|
1055
|
+
return true;
|
|
980
1056
|
}
|
|
1057
|
+
const config = {
|
|
1058
|
+
mcpServers: {
|
|
1059
|
+
kadai: kadaiEntry
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
await Bun.write(mcpJsonPath, `${JSON.stringify(config, null, 2)}
|
|
1063
|
+
`);
|
|
1064
|
+
return true;
|
|
981
1065
|
}
|
|
982
1066
|
async function startMcpServer(kadaiDir, cwd) {
|
|
983
1067
|
let visibleActions = [];
|
|
984
1068
|
let config = {};
|
|
985
1069
|
if (kadaiDir) {
|
|
986
1070
|
config = await loadConfig(kadaiDir);
|
|
987
|
-
const actionsDir =
|
|
1071
|
+
const actionsDir = join10(kadaiDir, config.actionsDir ?? "actions");
|
|
988
1072
|
let allActions = await loadActions(actionsDir);
|
|
989
1073
|
const globalActions = await loadUserGlobalActions();
|
|
990
1074
|
allActions = [...allActions, ...globalActions];
|
|
@@ -1051,6 +1135,173 @@ var init_mcp = __esm(() => {
|
|
|
1051
1135
|
init_runner();
|
|
1052
1136
|
});
|
|
1053
1137
|
|
|
1138
|
+
// src/core/init-wizard.ts
|
|
1139
|
+
var exports_init_wizard = {};
|
|
1140
|
+
__export(exports_init_wizard, {
|
|
1141
|
+
writeInitFiles: () => writeInitFiles,
|
|
1142
|
+
generateConfigFile: () => generateConfigFile,
|
|
1143
|
+
ensureClaudeIntegration: () => ensureClaudeIntegration
|
|
1144
|
+
});
|
|
1145
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
1146
|
+
import { join as join11 } from "path";
|
|
1147
|
+
function generateConfigFile() {
|
|
1148
|
+
const lines = [' // actionsDir: "actions",', " // env: {},"];
|
|
1149
|
+
return `export default {
|
|
1150
|
+
${lines.join(`
|
|
1151
|
+
`)}
|
|
1152
|
+
};
|
|
1153
|
+
`;
|
|
1154
|
+
}
|
|
1155
|
+
async function writeInitFiles(cwd) {
|
|
1156
|
+
const kadaiDir = join11(cwd, ".kadai");
|
|
1157
|
+
const actionsDir = join11(kadaiDir, "actions");
|
|
1158
|
+
mkdirSync2(actionsDir, { recursive: true });
|
|
1159
|
+
const sampleAction = join11(actionsDir, "hello.sh");
|
|
1160
|
+
const sampleFile = Bun.file(sampleAction);
|
|
1161
|
+
let sampleCreated = false;
|
|
1162
|
+
if (!await sampleFile.exists()) {
|
|
1163
|
+
await Bun.write(sampleAction, `#!/bin/bash
|
|
1164
|
+
# kadai:name Hello World
|
|
1165
|
+
# kadai:emoji \uD83D\uDC4B
|
|
1166
|
+
# kadai:description A sample action \u2014 edit or delete this file
|
|
1167
|
+
|
|
1168
|
+
echo "Hello from kadai!"
|
|
1169
|
+
echo "Add your own scripts to .kadai/actions/ to get started."
|
|
1170
|
+
`);
|
|
1171
|
+
sampleCreated = true;
|
|
1172
|
+
}
|
|
1173
|
+
const gitignorePath = join11(kadaiDir, ".gitignore");
|
|
1174
|
+
if (!await Bun.file(gitignorePath).exists()) {
|
|
1175
|
+
await Bun.write(gitignorePath, `.last-action
|
|
1176
|
+
`);
|
|
1177
|
+
}
|
|
1178
|
+
const configContent = generateConfigFile();
|
|
1179
|
+
const configPath = join11(kadaiDir, "config.ts");
|
|
1180
|
+
await Bun.write(configPath, configContent);
|
|
1181
|
+
const integration = await ensureClaudeIntegration(cwd);
|
|
1182
|
+
return { sampleCreated, skillCreated: integration.skillCreated };
|
|
1183
|
+
}
|
|
1184
|
+
async function ensureClaudeIntegration(projectRoot) {
|
|
1185
|
+
const hasClaudeDir = existsSync3(join11(projectRoot, ".claude"));
|
|
1186
|
+
const hasClaudeMd = existsSync3(join11(projectRoot, "CLAUDE.md"));
|
|
1187
|
+
if (!hasClaudeDir && !hasClaudeMd) {
|
|
1188
|
+
return { skillCreated: false, mcpConfigured: false };
|
|
1189
|
+
}
|
|
1190
|
+
const skillCreated = await ensureSkillFile(projectRoot);
|
|
1191
|
+
const mcpConfigured = await ensureMcpJsonEntry(projectRoot);
|
|
1192
|
+
return { skillCreated, mcpConfigured };
|
|
1193
|
+
}
|
|
1194
|
+
async function ensureSkillFile(projectRoot) {
|
|
1195
|
+
const skillDir = join11(projectRoot, ".claude", "skills", "kadai");
|
|
1196
|
+
const skillPath = join11(skillDir, "SKILL.md");
|
|
1197
|
+
if (await Bun.file(skillPath).exists()) {
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
mkdirSync2(skillDir, { recursive: true });
|
|
1201
|
+
await Bun.write(skillPath, generateSkillFile());
|
|
1202
|
+
return true;
|
|
1203
|
+
}
|
|
1204
|
+
async function ensureMcpJsonEntry(projectRoot) {
|
|
1205
|
+
const { ensureMcpConfig: ensureMcpConfig2 } = await Promise.resolve().then(() => (init_mcp(), exports_mcp));
|
|
1206
|
+
return await ensureMcpConfig2(projectRoot);
|
|
1207
|
+
}
|
|
1208
|
+
function generateSkillFile() {
|
|
1209
|
+
return `---
|
|
1210
|
+
name: kadai
|
|
1211
|
+
description: >-
|
|
1212
|
+
kadai is a script runner for this project. Discover available actions with
|
|
1213
|
+
kadai list --json, and run them with kadai run <action-id>.
|
|
1214
|
+
user-invocable: false
|
|
1215
|
+
---
|
|
1216
|
+
|
|
1217
|
+
# kadai \u2014 Project Script Runner
|
|
1218
|
+
|
|
1219
|
+
kadai manages and runs project-specific shell scripts stored in \`.kadai/actions/\`.
|
|
1220
|
+
|
|
1221
|
+
## Discovering Actions
|
|
1222
|
+
|
|
1223
|
+
\`\`\`bash
|
|
1224
|
+
kadai list --json
|
|
1225
|
+
\`\`\`
|
|
1226
|
+
|
|
1227
|
+
Returns a JSON array of available actions:
|
|
1228
|
+
|
|
1229
|
+
\`\`\`json
|
|
1230
|
+
[
|
|
1231
|
+
{
|
|
1232
|
+
"id": "database/reset",
|
|
1233
|
+
"name": "Reset Database",
|
|
1234
|
+
"emoji": "\uD83D\uDDD1\uFE0F",
|
|
1235
|
+
"description": "Drop and recreate the dev database",
|
|
1236
|
+
"category": ["database"],
|
|
1237
|
+
"runtime": "bash",
|
|
1238
|
+
"confirm": true
|
|
1239
|
+
}
|
|
1240
|
+
]
|
|
1241
|
+
\`\`\`
|
|
1242
|
+
|
|
1243
|
+
Use \`--all\` to include hidden actions: \`kadai list --json --all\`
|
|
1244
|
+
|
|
1245
|
+
Always use \`kadai list --json\` for the current set of actions \u2014 do not hardcode action lists.
|
|
1246
|
+
|
|
1247
|
+
## Running Actions
|
|
1248
|
+
|
|
1249
|
+
\`\`\`bash
|
|
1250
|
+
kadai run <action-id>
|
|
1251
|
+
\`\`\`
|
|
1252
|
+
|
|
1253
|
+
Runs the action and streams stdout/stderr directly. The process exits with the action's exit code.
|
|
1254
|
+
Confirmation prompts are automatically skipped in non-TTY environments.
|
|
1255
|
+
|
|
1256
|
+
### Examples
|
|
1257
|
+
|
|
1258
|
+
\`\`\`bash
|
|
1259
|
+
kadai run hello
|
|
1260
|
+
kadai run database/reset
|
|
1261
|
+
\`\`\`
|
|
1262
|
+
|
|
1263
|
+
## Creating Actions
|
|
1264
|
+
|
|
1265
|
+
Create a script file in \`.kadai/actions/\`. Supported extensions: \`.sh\`, \`.bash\`, \`.ts\`, \`.js\`, \`.mjs\`, \`.py\`, \`.tsx\`.
|
|
1266
|
+
|
|
1267
|
+
Add metadata as comments in the first 20 lines using \`# kadai:<key> <value>\` (for shell/python) or \`// kadai:<key> <value>\` (for JS/TS):
|
|
1268
|
+
|
|
1269
|
+
\`\`\`bash
|
|
1270
|
+
#!/bin/bash
|
|
1271
|
+
# kadai:name Deploy Staging
|
|
1272
|
+
# kadai:emoji \uD83D\uDE80
|
|
1273
|
+
# kadai:description Deploy the app to the staging environment
|
|
1274
|
+
# kadai:confirm true
|
|
1275
|
+
|
|
1276
|
+
echo "Deploying..."
|
|
1277
|
+
\`\`\`
|
|
1278
|
+
|
|
1279
|
+
Available metadata keys:
|
|
1280
|
+
|
|
1281
|
+
| Key | Description |
|
|
1282
|
+
|---------------|---------------------------------------------|
|
|
1283
|
+
| \`name\` | Display name in menus |
|
|
1284
|
+
| \`emoji\` | Emoji prefix |
|
|
1285
|
+
| \`description\` | Short description |
|
|
1286
|
+
| \`confirm\` | Require confirmation before running (true/false) |
|
|
1287
|
+
| \`hidden\` | Hide from default listing (true/false) |
|
|
1288
|
+
| \`fullscreen\` | Use alternate screen buffer for ink actions (true/false) |
|
|
1289
|
+
|
|
1290
|
+
If \`name\` is omitted, it is inferred from the filename (e.g. \`deploy-staging.sh\` \u2192 "Deploy Staging").
|
|
1291
|
+
|
|
1292
|
+
Organize actions into categories using subdirectories:
|
|
1293
|
+
|
|
1294
|
+
\`\`\`
|
|
1295
|
+
.kadai/actions/
|
|
1296
|
+
hello.sh \u2192 id: "hello"
|
|
1297
|
+
database/
|
|
1298
|
+
migrate.sh \u2192 id: "database/migrate"
|
|
1299
|
+
reset.ts \u2192 id: "database/reset"
|
|
1300
|
+
\`\`\`
|
|
1301
|
+
`;
|
|
1302
|
+
}
|
|
1303
|
+
var init_init_wizard = () => {};
|
|
1304
|
+
|
|
1054
1305
|
// src/components/Breadcrumbs.tsx
|
|
1055
1306
|
import { Box, Text } from "ink";
|
|
1056
1307
|
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
@@ -1087,6 +1338,7 @@ var init_FullscreenProvider = () => {};
|
|
|
1087
1338
|
|
|
1088
1339
|
// src/components/InkActionRenderer.tsx
|
|
1089
1340
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
1341
|
+
import { join as join12 } from "path";
|
|
1090
1342
|
import React, { useEffect, useState } from "react";
|
|
1091
1343
|
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
1092
1344
|
function InkActionRenderer({
|
|
@@ -1100,6 +1352,7 @@ function InkActionRenderer({
|
|
|
1100
1352
|
let cancelled = false;
|
|
1101
1353
|
(async () => {
|
|
1102
1354
|
try {
|
|
1355
|
+
ensureKadaiResolvable(join12(cwd, "node_modules"));
|
|
1103
1356
|
const mod = await import(action.filePath);
|
|
1104
1357
|
if (cancelled)
|
|
1105
1358
|
return;
|
|
@@ -1162,6 +1415,7 @@ function InkActionRenderer({
|
|
|
1162
1415
|
}
|
|
1163
1416
|
var InkActionErrorBoundary;
|
|
1164
1417
|
var init_InkActionRenderer = __esm(() => {
|
|
1418
|
+
init_shared_deps();
|
|
1165
1419
|
InkActionErrorBoundary = class InkActionErrorBoundary extends React.Component {
|
|
1166
1420
|
constructor(props) {
|
|
1167
1421
|
super(props);
|
|
@@ -1212,7 +1466,7 @@ function StatusBar() {
|
|
|
1212
1466
|
var init_StatusBar = () => {};
|
|
1213
1467
|
|
|
1214
1468
|
// src/hooks/useActions.ts
|
|
1215
|
-
import { join as
|
|
1469
|
+
import { join as join13 } from "path";
|
|
1216
1470
|
import { useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
1217
1471
|
function useActions({ kadaiDir }) {
|
|
1218
1472
|
const [actions, setActions] = useState2([]);
|
|
@@ -1225,7 +1479,7 @@ function useActions({ kadaiDir }) {
|
|
|
1225
1479
|
(async () => {
|
|
1226
1480
|
const cfg = await loadConfig(kadaiDir);
|
|
1227
1481
|
setConfig(cfg);
|
|
1228
|
-
const actionsDir =
|
|
1482
|
+
const actionsDir = join13(kadaiDir, cfg.actionsDir ?? "actions");
|
|
1229
1483
|
const localActions = await loadActions(actionsDir);
|
|
1230
1484
|
let allActions = [...localActions];
|
|
1231
1485
|
const globalActions = await loadUserGlobalActions();
|
|
@@ -2267,6 +2521,7 @@ function MenuList({
|
|
|
2267
2521
|
}
|
|
2268
2522
|
const selected = i === selectedIndex;
|
|
2269
2523
|
return /* @__PURE__ */ jsxDEV5(Box4, {
|
|
2524
|
+
width: "100%",
|
|
2270
2525
|
children: [
|
|
2271
2526
|
/* @__PURE__ */ jsxDEV5(Text4, {
|
|
2272
2527
|
color: selected ? "cyan" : undefined,
|
|
@@ -2288,14 +2543,13 @@ function MenuList({
|
|
|
2288
2543
|
dimColor: true,
|
|
2289
2544
|
children: " \u27F3"
|
|
2290
2545
|
}, undefined, false, undefined, this),
|
|
2546
|
+
/* @__PURE__ */ jsxDEV5(Box4, {
|
|
2547
|
+
flexGrow: 1
|
|
2548
|
+
}, undefined, false, undefined, this),
|
|
2291
2549
|
item.description && /* @__PURE__ */ jsxDEV5(Text4, {
|
|
2292
2550
|
dimColor: true,
|
|
2293
|
-
children:
|
|
2294
|
-
|
|
2295
|
-
item.description,
|
|
2296
|
-
")"
|
|
2297
|
-
]
|
|
2298
|
-
}, undefined, true, undefined, this)
|
|
2551
|
+
children: item.description
|
|
2552
|
+
}, undefined, false, undefined, this)
|
|
2299
2553
|
]
|
|
2300
2554
|
}, `${i}-${item.value}`, true, undefined, this);
|
|
2301
2555
|
})
|
|
@@ -2548,172 +2802,8 @@ var init_app = __esm(() => {
|
|
|
2548
2802
|
SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
|
|
2549
2803
|
});
|
|
2550
2804
|
|
|
2551
|
-
// src/
|
|
2552
|
-
|
|
2553
|
-
__export(exports_init_wizard, {
|
|
2554
|
-
writeInitFiles: () => writeInitFiles,
|
|
2555
|
-
generateConfigFile: () => generateConfigFile
|
|
2556
|
-
});
|
|
2557
|
-
import { existsSync as existsSync2, mkdirSync } from "fs";
|
|
2558
|
-
import { join as join10 } from "path";
|
|
2559
|
-
function generateConfigFile() {
|
|
2560
|
-
const lines = [' // actionsDir: "actions",', " // env: {},"];
|
|
2561
|
-
return `export default {
|
|
2562
|
-
${lines.join(`
|
|
2563
|
-
`)}
|
|
2564
|
-
};
|
|
2565
|
-
`;
|
|
2566
|
-
}
|
|
2567
|
-
async function writeInitFiles(cwd) {
|
|
2568
|
-
const kadaiDir = join10(cwd, ".kadai");
|
|
2569
|
-
const actionsDir = join10(kadaiDir, "actions");
|
|
2570
|
-
mkdirSync(actionsDir, { recursive: true });
|
|
2571
|
-
const sampleAction = join10(actionsDir, "hello.sh");
|
|
2572
|
-
const sampleFile = Bun.file(sampleAction);
|
|
2573
|
-
let sampleCreated = false;
|
|
2574
|
-
if (!await sampleFile.exists()) {
|
|
2575
|
-
await Bun.write(sampleAction, `#!/bin/bash
|
|
2576
|
-
# kadai:name Hello World
|
|
2577
|
-
# kadai:emoji \uD83D\uDC4B
|
|
2578
|
-
# kadai:description A sample action \u2014 edit or delete this file
|
|
2579
|
-
|
|
2580
|
-
echo "Hello from kadai!"
|
|
2581
|
-
echo "Add your own scripts to .kadai/actions/ to get started."
|
|
2582
|
-
`);
|
|
2583
|
-
sampleCreated = true;
|
|
2584
|
-
}
|
|
2585
|
-
const configContent = generateConfigFile();
|
|
2586
|
-
const configPath = join10(kadaiDir, "config.ts");
|
|
2587
|
-
await Bun.write(configPath, configContent);
|
|
2588
|
-
let skillCreated = false;
|
|
2589
|
-
const hasClaudeDir = existsSync2(join10(cwd, ".claude"));
|
|
2590
|
-
const hasClaudeMd = existsSync2(join10(cwd, "CLAUDE.md"));
|
|
2591
|
-
if (hasClaudeDir || hasClaudeMd) {
|
|
2592
|
-
const skillDir = join10(cwd, ".claude", "skills", "kadai");
|
|
2593
|
-
const skillPath = join10(skillDir, "SKILL.md");
|
|
2594
|
-
if (!await Bun.file(skillPath).exists()) {
|
|
2595
|
-
mkdirSync(skillDir, { recursive: true });
|
|
2596
|
-
await Bun.write(skillPath, generateSkillFile());
|
|
2597
|
-
skillCreated = true;
|
|
2598
|
-
}
|
|
2599
|
-
}
|
|
2600
|
-
return { sampleCreated, skillCreated };
|
|
2601
|
-
}
|
|
2602
|
-
function generateSkillFile() {
|
|
2603
|
-
return `---
|
|
2604
|
-
name: kadai
|
|
2605
|
-
description: >-
|
|
2606
|
-
kadai is a script runner for this project. Discover available actions with
|
|
2607
|
-
kadai list --json, and run them with kadai run <action-id>.
|
|
2608
|
-
user-invocable: false
|
|
2609
|
-
---
|
|
2610
|
-
|
|
2611
|
-
# kadai \u2014 Project Script Runner
|
|
2612
|
-
|
|
2613
|
-
kadai manages and runs project-specific shell scripts stored in \`.kadai/actions/\`.
|
|
2614
|
-
|
|
2615
|
-
## Discovering Actions
|
|
2616
|
-
|
|
2617
|
-
\`\`\`bash
|
|
2618
|
-
kadai list --json
|
|
2619
|
-
\`\`\`
|
|
2620
|
-
|
|
2621
|
-
Returns a JSON array of available actions:
|
|
2622
|
-
|
|
2623
|
-
\`\`\`json
|
|
2624
|
-
[
|
|
2625
|
-
{
|
|
2626
|
-
"id": "database/reset",
|
|
2627
|
-
"name": "Reset Database",
|
|
2628
|
-
"emoji": "\uD83D\uDDD1\uFE0F",
|
|
2629
|
-
"description": "Drop and recreate the dev database",
|
|
2630
|
-
"category": ["database"],
|
|
2631
|
-
"runtime": "bash",
|
|
2632
|
-
"confirm": true
|
|
2633
|
-
}
|
|
2634
|
-
]
|
|
2635
|
-
\`\`\`
|
|
2636
|
-
|
|
2637
|
-
Use \`--all\` to include hidden actions: \`kadai list --json --all\`
|
|
2638
|
-
|
|
2639
|
-
Always use \`kadai list --json\` for the current set of actions \u2014 do not hardcode action lists.
|
|
2640
|
-
|
|
2641
|
-
## Running Actions
|
|
2642
|
-
|
|
2643
|
-
\`\`\`bash
|
|
2644
|
-
kadai run <action-id>
|
|
2645
|
-
\`\`\`
|
|
2646
|
-
|
|
2647
|
-
Runs the action and streams stdout/stderr directly. The process exits with the action's exit code.
|
|
2648
|
-
Confirmation prompts are automatically skipped in non-TTY environments.
|
|
2649
|
-
|
|
2650
|
-
### Examples
|
|
2651
|
-
|
|
2652
|
-
\`\`\`bash
|
|
2653
|
-
kadai run hello
|
|
2654
|
-
kadai run database/reset
|
|
2655
|
-
\`\`\`
|
|
2656
|
-
|
|
2657
|
-
## Creating Actions
|
|
2658
|
-
|
|
2659
|
-
Create a script file in \`.kadai/actions/\`. Supported extensions: \`.sh\`, \`.bash\`, \`.ts\`, \`.js\`, \`.mjs\`, \`.py\`, \`.tsx\`.
|
|
2660
|
-
|
|
2661
|
-
Add metadata as comments in the first 20 lines using \`# kadai:<key> <value>\` (for shell/python) or \`// kadai:<key> <value>\` (for JS/TS):
|
|
2662
|
-
|
|
2663
|
-
\`\`\`bash
|
|
2664
|
-
#!/bin/bash
|
|
2665
|
-
# kadai:name Deploy Staging
|
|
2666
|
-
# kadai:emoji \uD83D\uDE80
|
|
2667
|
-
# kadai:description Deploy the app to the staging environment
|
|
2668
|
-
# kadai:confirm true
|
|
2669
|
-
|
|
2670
|
-
echo "Deploying..."
|
|
2671
|
-
\`\`\`
|
|
2672
|
-
|
|
2673
|
-
Available metadata keys:
|
|
2674
|
-
|
|
2675
|
-
| Key | Description |
|
|
2676
|
-
|---------------|---------------------------------------------|
|
|
2677
|
-
| \`name\` | Display name in menus |
|
|
2678
|
-
| \`emoji\` | Emoji prefix |
|
|
2679
|
-
| \`description\` | Short description |
|
|
2680
|
-
| \`confirm\` | Require confirmation before running (true/false) |
|
|
2681
|
-
| \`hidden\` | Hide from default listing (true/false) |
|
|
2682
|
-
| \`fullscreen\` | Use alternate screen buffer for ink actions (true/false) |
|
|
2683
|
-
|
|
2684
|
-
If \`name\` is omitted, it is inferred from the filename (e.g. \`deploy-staging.sh\` \u2192 "Deploy Staging").
|
|
2685
|
-
|
|
2686
|
-
Organize actions into categories using subdirectories:
|
|
2687
|
-
|
|
2688
|
-
\`\`\`
|
|
2689
|
-
.kadai/actions/
|
|
2690
|
-
hello.sh \u2192 id: "hello"
|
|
2691
|
-
database/
|
|
2692
|
-
migrate.sh \u2192 id: "database/migrate"
|
|
2693
|
-
reset.ts \u2192 id: "database/reset"
|
|
2694
|
-
\`\`\`
|
|
2695
|
-
`;
|
|
2696
|
-
}
|
|
2697
|
-
var init_init_wizard = () => {};
|
|
2698
|
-
|
|
2699
|
-
// src/core/shared-deps.ts
|
|
2700
|
-
var SHARED_DEPS = ["ink", "react", "@inkjs/ui"];
|
|
2701
|
-
function registerSharedDeps() {
|
|
2702
|
-
const escaped = SHARED_DEPS.map((d) => d.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
2703
|
-
const filter = new RegExp(`^(${escaped.join("|")})(/.*)?$`);
|
|
2704
|
-
Bun.plugin({
|
|
2705
|
-
name: "kadai-shared-deps",
|
|
2706
|
-
setup(build) {
|
|
2707
|
-
build.onResolve({ filter }, (args) => {
|
|
2708
|
-
try {
|
|
2709
|
-
return { path: __require.resolve(args.path) };
|
|
2710
|
-
} catch {
|
|
2711
|
-
return;
|
|
2712
|
-
}
|
|
2713
|
-
});
|
|
2714
|
-
}
|
|
2715
|
-
});
|
|
2716
|
-
}
|
|
2805
|
+
// src/cli.tsx
|
|
2806
|
+
init_shared_deps();
|
|
2717
2807
|
|
|
2718
2808
|
// src/core/args.ts
|
|
2719
2809
|
function parseArgs(argv) {
|
|
@@ -2724,6 +2814,9 @@ function parseArgs(argv) {
|
|
|
2724
2814
|
if (command === "--version" || command === "-v") {
|
|
2725
2815
|
return { type: "version" };
|
|
2726
2816
|
}
|
|
2817
|
+
if (command === "--rerun" || command === "-r") {
|
|
2818
|
+
return { type: "rerun" };
|
|
2819
|
+
}
|
|
2727
2820
|
switch (command) {
|
|
2728
2821
|
case "list": {
|
|
2729
2822
|
if (!argv.includes("--json")) {
|
|
@@ -2749,7 +2842,7 @@ function parseArgs(argv) {
|
|
|
2749
2842
|
default:
|
|
2750
2843
|
return {
|
|
2751
2844
|
type: "error",
|
|
2752
|
-
message: `Unknown command: ${command}. Available commands: list, run, sync, mcp, --version`
|
|
2845
|
+
message: `Unknown command: ${command}. Available commands: list, run, sync, mcp, --version, --rerun`
|
|
2753
2846
|
};
|
|
2754
2847
|
}
|
|
2755
2848
|
}
|
|
@@ -2757,6 +2850,7 @@ function parseArgs(argv) {
|
|
|
2757
2850
|
// src/cli.tsx
|
|
2758
2851
|
init_commands();
|
|
2759
2852
|
init_loader();
|
|
2853
|
+
init_last_action();
|
|
2760
2854
|
registerSharedDeps();
|
|
2761
2855
|
var cwd = process.cwd();
|
|
2762
2856
|
var parsed = parseArgs(process.argv.slice(2));
|
|
@@ -2778,17 +2872,22 @@ if (parsed.type === "mcp") {
|
|
|
2778
2872
|
await startMcpServer2(kadaiDir, cwd);
|
|
2779
2873
|
await new Promise(() => {});
|
|
2780
2874
|
}
|
|
2781
|
-
if (parsed.type === "list" || parsed.type === "run" || parsed.type === "sync") {
|
|
2875
|
+
if (parsed.type === "list" || parsed.type === "run" || parsed.type === "sync" || parsed.type === "rerun") {
|
|
2782
2876
|
const kadaiDir = findZcliDir(cwd);
|
|
2783
2877
|
if (!kadaiDir) {
|
|
2784
2878
|
process.stderr.write(`Error: No .kadai directory found. Run kadai to initialize.
|
|
2785
2879
|
`);
|
|
2786
2880
|
process.exit(1);
|
|
2787
2881
|
}
|
|
2882
|
+
const { dirname: dirname2 } = await import("path");
|
|
2883
|
+
const { ensureClaudeIntegration: ensureClaudeIntegration2 } = await Promise.resolve().then(() => (init_init_wizard(), exports_init_wizard));
|
|
2884
|
+
await ensureClaudeIntegration2(dirname2(kadaiDir));
|
|
2788
2885
|
if (parsed.type === "list") {
|
|
2789
2886
|
await handleList({ kadaiDir, all: parsed.all });
|
|
2790
2887
|
} else if (parsed.type === "run") {
|
|
2791
2888
|
await handleRun({ kadaiDir, actionId: parsed.actionId, cwd });
|
|
2889
|
+
} else if (parsed.type === "rerun") {
|
|
2890
|
+
await handleRerun({ kadaiDir, cwd });
|
|
2792
2891
|
} else {
|
|
2793
2892
|
const { handleSync: handleSync2 } = await Promise.resolve().then(() => (init_commands(), exports_commands));
|
|
2794
2893
|
await handleSync2({ kadaiDir });
|
|
@@ -2814,12 +2913,20 @@ if (!kadaiDir) {
|
|
|
2814
2913
|
console.log(" Created .kadai/config.ts");
|
|
2815
2914
|
if (result.sampleCreated)
|
|
2816
2915
|
console.log(" Created .kadai/actions/hello.sh");
|
|
2817
|
-
if (result.skillCreated)
|
|
2818
|
-
console.log(" Created .claude/skills/kadai/SKILL.md");
|
|
2819
2916
|
console.log(`
|
|
2820
2917
|
Done! Run kadai again to get started.`);
|
|
2821
2918
|
process.exit(0);
|
|
2822
2919
|
}
|
|
2920
|
+
{
|
|
2921
|
+
const { dirname: dirname2 } = await import("path");
|
|
2922
|
+
const { ensureClaudeIntegration: ensureClaudeIntegration2 } = await Promise.resolve().then(() => (init_init_wizard(), exports_init_wizard));
|
|
2923
|
+
const projectRoot = dirname2(kadaiDir);
|
|
2924
|
+
const ensured = await ensureClaudeIntegration2(projectRoot);
|
|
2925
|
+
if (ensured.skillCreated)
|
|
2926
|
+
console.log("Created .claude/skills/kadai/SKILL.md");
|
|
2927
|
+
if (ensured.mcpConfigured)
|
|
2928
|
+
console.log("Configured kadai in .mcp.json");
|
|
2929
|
+
}
|
|
2823
2930
|
function createStdinStream() {
|
|
2824
2931
|
if (process.stdin.isTTY) {
|
|
2825
2932
|
return process.stdin;
|
|
@@ -2901,6 +3008,7 @@ await instance.waitUntilExit();
|
|
|
2901
3008
|
if (!selectedAction)
|
|
2902
3009
|
process.exit(0);
|
|
2903
3010
|
var action = selectedAction;
|
|
3011
|
+
await saveLastAction(kadaiDir, action.id);
|
|
2904
3012
|
var config = await loadConfig2(kadaiDir);
|
|
2905
3013
|
var cmd = resolveCommand2(action);
|
|
2906
3014
|
var env = {
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// @bun
|
package/package.json
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kadai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"kadai": "./dist/cli.js"
|
|
7
7
|
},
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/cli.js",
|
|
10
|
+
"./types": "./dist/types.js",
|
|
11
|
+
"./ink": "./dist/exports/ink.js",
|
|
12
|
+
"./ui": "./dist/exports/ui.js",
|
|
13
|
+
"./react": "./dist/exports/react.js",
|
|
14
|
+
"./react/jsx-runtime": "./dist/exports/jsx-runtime.js",
|
|
15
|
+
"./react/jsx-dev-runtime": "./dist/exports/jsx-dev-runtime.js"
|
|
16
|
+
},
|
|
8
17
|
"scripts": {
|
|
9
18
|
"build": "bun build.ts",
|
|
10
19
|
"check": "tsc --noEmit && biome check ./src ./test",
|