agenthud 0.1.1 → 0.2.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/index.js +120 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import React2 from "react";
|
|
5
5
|
import { render } from "ink";
|
|
6
|
+
import { existsSync } from "fs";
|
|
6
7
|
|
|
7
8
|
// src/ui/App.tsx
|
|
8
9
|
import { useState, useEffect, useCallback } from "react";
|
|
9
|
-
import { Box as
|
|
10
|
+
import { Box as Box5, Text as Text5, useApp, useInput } from "ink";
|
|
10
11
|
|
|
11
12
|
// src/ui/GitPanel.tsx
|
|
12
13
|
import { Box, Text } from "ink";
|
|
@@ -249,6 +250,24 @@ function TestPanel({
|
|
|
249
250
|
] });
|
|
250
251
|
}
|
|
251
252
|
|
|
253
|
+
// src/ui/WelcomePanel.tsx
|
|
254
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
255
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
256
|
+
function WelcomePanel() {
|
|
257
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "single", paddingX: 1, width: PANEL_WIDTH, children: [
|
|
258
|
+
/* @__PURE__ */ jsx4(Box4, { marginTop: -1, children: /* @__PURE__ */ jsx4(Text4, { children: " Welcome to agenthud " }) }),
|
|
259
|
+
/* @__PURE__ */ jsx4(Text4, { children: " " }),
|
|
260
|
+
/* @__PURE__ */ jsx4(Text4, { children: " No .agent/ directory found." }),
|
|
261
|
+
/* @__PURE__ */ jsx4(Text4, { children: " " }),
|
|
262
|
+
/* @__PURE__ */ jsx4(Text4, { children: " Quick setup:" }),
|
|
263
|
+
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: " npx agenthud init" }),
|
|
264
|
+
/* @__PURE__ */ jsx4(Text4, { children: " " }),
|
|
265
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: " Or visit: github.com/neochoon/agenthud" }),
|
|
266
|
+
/* @__PURE__ */ jsx4(Text4, { children: " " }),
|
|
267
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: " Press q to quit" })
|
|
268
|
+
] });
|
|
269
|
+
}
|
|
270
|
+
|
|
252
271
|
// src/data/git.ts
|
|
253
272
|
import { execSync as nodeExecSync } from "child_process";
|
|
254
273
|
var execFn = (command, options2) => nodeExecSync(command, options2);
|
|
@@ -398,7 +417,7 @@ function getTestData(dir = process.cwd()) {
|
|
|
398
417
|
}
|
|
399
418
|
|
|
400
419
|
// src/ui/App.tsx
|
|
401
|
-
import { jsx as
|
|
420
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
402
421
|
var REFRESH_INTERVAL = 5e3;
|
|
403
422
|
var REFRESH_SECONDS = REFRESH_INTERVAL / 1e3;
|
|
404
423
|
function useGitData() {
|
|
@@ -432,7 +451,10 @@ function useTestData() {
|
|
|
432
451
|
}, []);
|
|
433
452
|
return [data, refresh];
|
|
434
453
|
}
|
|
435
|
-
function
|
|
454
|
+
function WelcomeApp() {
|
|
455
|
+
return /* @__PURE__ */ jsx5(WelcomePanel, {});
|
|
456
|
+
}
|
|
457
|
+
function DashboardApp({ mode }) {
|
|
436
458
|
const { exit } = useApp();
|
|
437
459
|
const [gitData, refreshGit] = useGitData();
|
|
438
460
|
const [planData, refreshPlan] = usePlanData();
|
|
@@ -458,7 +480,6 @@ function App({ mode }) {
|
|
|
458
480
|
}, [mode]);
|
|
459
481
|
useInput(
|
|
460
482
|
(input) => {
|
|
461
|
-
if (mode !== "watch") return;
|
|
462
483
|
if (input === "q") {
|
|
463
484
|
exit();
|
|
464
485
|
}
|
|
@@ -468,8 +489,8 @@ function App({ mode }) {
|
|
|
468
489
|
},
|
|
469
490
|
{ isActive: mode === "watch" }
|
|
470
491
|
);
|
|
471
|
-
return /* @__PURE__ */
|
|
472
|
-
/* @__PURE__ */
|
|
492
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
493
|
+
/* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(
|
|
473
494
|
GitPanel,
|
|
474
495
|
{
|
|
475
496
|
branch: gitData.branch,
|
|
@@ -478,7 +499,7 @@ function App({ mode }) {
|
|
|
478
499
|
uncommitted: gitData.uncommitted
|
|
479
500
|
}
|
|
480
501
|
) }),
|
|
481
|
-
/* @__PURE__ */
|
|
502
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(
|
|
482
503
|
PlanPanel,
|
|
483
504
|
{
|
|
484
505
|
plan: planData.plan,
|
|
@@ -486,7 +507,7 @@ function App({ mode }) {
|
|
|
486
507
|
error: planData.error
|
|
487
508
|
}
|
|
488
509
|
) }),
|
|
489
|
-
/* @__PURE__ */
|
|
510
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(
|
|
490
511
|
TestPanel,
|
|
491
512
|
{
|
|
492
513
|
results: testData.results,
|
|
@@ -495,17 +516,23 @@ function App({ mode }) {
|
|
|
495
516
|
error: testData.error
|
|
496
517
|
}
|
|
497
518
|
) }),
|
|
498
|
-
mode === "watch" && /* @__PURE__ */
|
|
519
|
+
mode === "watch" && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, width: PANEL_WIDTH, children: /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
499
520
|
"\u21BB ",
|
|
500
521
|
countdown,
|
|
501
522
|
"s \xB7 ",
|
|
502
|
-
/* @__PURE__ */
|
|
523
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "q:" }),
|
|
503
524
|
" quit \xB7 ",
|
|
504
|
-
/* @__PURE__ */
|
|
525
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "r:" }),
|
|
505
526
|
" refresh"
|
|
506
527
|
] }) })
|
|
507
528
|
] });
|
|
508
529
|
}
|
|
530
|
+
function App({ mode, agentDirExists: agentDirExists2 = true }) {
|
|
531
|
+
if (!agentDirExists2) {
|
|
532
|
+
return /* @__PURE__ */ jsx5(WelcomeApp, {});
|
|
533
|
+
}
|
|
534
|
+
return /* @__PURE__ */ jsx5(DashboardApp, { mode });
|
|
535
|
+
}
|
|
509
536
|
|
|
510
537
|
// src/cli.ts
|
|
511
538
|
var clearFn = () => console.clear();
|
|
@@ -515,18 +542,97 @@ function clearScreen() {
|
|
|
515
542
|
function parseArgs(args) {
|
|
516
543
|
const hasOnce = args.includes("--once");
|
|
517
544
|
const hasWatch = args.includes("--watch") || args.includes("-w");
|
|
545
|
+
const command = args[0] === "init" ? "init" : void 0;
|
|
518
546
|
if (hasOnce) {
|
|
519
|
-
return { mode: "once" };
|
|
547
|
+
return { mode: "once", command };
|
|
520
548
|
}
|
|
521
|
-
return { mode: "watch" };
|
|
549
|
+
return { mode: "watch", command };
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// src/commands/init.ts
|
|
553
|
+
import {
|
|
554
|
+
existsSync as nodeExistsSync,
|
|
555
|
+
mkdirSync as nodeMkdirSync,
|
|
556
|
+
writeFileSync as nodeWriteFileSync,
|
|
557
|
+
readFileSync as nodeReadFileSync3,
|
|
558
|
+
appendFileSync as nodeAppendFileSync
|
|
559
|
+
} from "fs";
|
|
560
|
+
var fs = {
|
|
561
|
+
existsSync: nodeExistsSync,
|
|
562
|
+
mkdirSync: nodeMkdirSync,
|
|
563
|
+
writeFileSync: nodeWriteFileSync,
|
|
564
|
+
readFileSync: (path) => nodeReadFileSync3(path, "utf-8"),
|
|
565
|
+
appendFileSync: nodeAppendFileSync
|
|
566
|
+
};
|
|
567
|
+
var AGENT_STATE_SECTION = `## Agent State
|
|
568
|
+
|
|
569
|
+
Maintain \`.agent/\` directory:
|
|
570
|
+
- Update \`plan.json\` when plan changes
|
|
571
|
+
- Append to \`decisions.json\` for key decisions
|
|
572
|
+
`;
|
|
573
|
+
function runInit() {
|
|
574
|
+
const result = {
|
|
575
|
+
created: [],
|
|
576
|
+
skipped: []
|
|
577
|
+
};
|
|
578
|
+
if (!fs.existsSync(".agent")) {
|
|
579
|
+
fs.mkdirSync(".agent", { recursive: true });
|
|
580
|
+
result.created.push(".agent/");
|
|
581
|
+
} else {
|
|
582
|
+
result.skipped.push(".agent/");
|
|
583
|
+
}
|
|
584
|
+
if (!fs.existsSync(".agent/plan.json")) {
|
|
585
|
+
fs.writeFileSync(".agent/plan.json", "{}\n");
|
|
586
|
+
result.created.push(".agent/plan.json");
|
|
587
|
+
} else {
|
|
588
|
+
result.skipped.push(".agent/plan.json");
|
|
589
|
+
}
|
|
590
|
+
if (!fs.existsSync(".agent/decisions.json")) {
|
|
591
|
+
fs.writeFileSync(".agent/decisions.json", "[]\n");
|
|
592
|
+
result.created.push(".agent/decisions.json");
|
|
593
|
+
} else {
|
|
594
|
+
result.skipped.push(".agent/decisions.json");
|
|
595
|
+
}
|
|
596
|
+
if (!fs.existsSync("CLAUDE.md")) {
|
|
597
|
+
fs.writeFileSync("CLAUDE.md", AGENT_STATE_SECTION);
|
|
598
|
+
result.created.push("CLAUDE.md");
|
|
599
|
+
} else {
|
|
600
|
+
const content = fs.readFileSync("CLAUDE.md");
|
|
601
|
+
if (!content.includes("## Agent State")) {
|
|
602
|
+
fs.appendFileSync("CLAUDE.md", "\n" + AGENT_STATE_SECTION);
|
|
603
|
+
result.created.push("CLAUDE.md");
|
|
604
|
+
} else {
|
|
605
|
+
result.skipped.push("CLAUDE.md");
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return result;
|
|
522
609
|
}
|
|
523
610
|
|
|
524
611
|
// src/index.ts
|
|
525
612
|
var options = parseArgs(process.argv.slice(2));
|
|
613
|
+
if (options.command === "init") {
|
|
614
|
+
const result = runInit();
|
|
615
|
+
console.log("\n\u2713 agenthud initialized\n");
|
|
616
|
+
if (result.created.length > 0) {
|
|
617
|
+
console.log("Created:");
|
|
618
|
+
result.created.forEach((file) => console.log(` ${file}`));
|
|
619
|
+
}
|
|
620
|
+
if (result.skipped.length > 0) {
|
|
621
|
+
console.log("\nSkipped (already exists):");
|
|
622
|
+
result.skipped.forEach((file) => console.log(` ${file}`));
|
|
623
|
+
}
|
|
624
|
+
console.log("\nNext steps:");
|
|
625
|
+
console.log(" 1. Edit .agent/plan.json to add your project plan");
|
|
626
|
+
console.log(" 2. Run: npx agenthud\n");
|
|
627
|
+
process.exit(0);
|
|
628
|
+
}
|
|
629
|
+
var agentDirExists = existsSync(".agent");
|
|
526
630
|
if (options.mode === "watch") {
|
|
527
631
|
clearScreen();
|
|
528
632
|
}
|
|
529
|
-
var { waitUntilExit } = render(
|
|
633
|
+
var { waitUntilExit } = render(
|
|
634
|
+
React2.createElement(App, { mode: options.mode, agentDirExists })
|
|
635
|
+
);
|
|
530
636
|
if (options.mode === "once") {
|
|
531
637
|
setTimeout(() => process.exit(0), 100);
|
|
532
638
|
} else {
|
package/package.json
CHANGED