jeo-code 0.4.5 → 0.4.7
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/README.ja.md +2 -2
- package/README.ko.md +2 -2
- package/README.md +2 -2
- package/README.zh.md +2 -2
- package/package.json +1 -1
- package/src/agent/dev/evolution-bridge.ts +36 -3
- package/src/agent/dev/self-analysis.ts +6 -1
- package/src/agent/engine.ts +76 -71
- package/src/agent/loop.ts +2 -0
- package/src/agent/step-budget.ts +10 -0
- package/src/agent/subagent-registry.ts +131 -0
- package/src/agent/subagent-tool.ts +89 -0
- package/src/agent/subagents.ts +22 -3
- package/src/agent/task-tool.ts +123 -19
- package/src/agent/tool-output.ts +115 -0
- package/src/agent/tools.ts +42 -8
- package/src/ai/model-manager.ts +9 -14
- package/src/ai/model-registry.ts +8 -3
- package/src/ai/providers/antigravity.ts +11 -2
- package/src/ai/providers/gemini.ts +12 -2
- package/src/ai/register-providers.ts +21 -0
- package/src/ai/types.ts +4 -0
- package/src/cli/runner.ts +0 -9
- package/src/commands/launch.ts +157 -52
- package/src/commands/team.ts +13 -6
- package/src/skills/catalog.ts +0 -2
- package/src/tui/app.ts +131 -20
- package/src/tui/components/forge.ts +25 -7
- package/src/tui/components/input-box.ts +8 -3
- package/src/tui/components/markdown-text.ts +10 -1
- package/src/tui/components/themes.ts +57 -1
- package/src/tui/components/todo-card.ts +44 -13
- package/src/tui/monitoring/hud-view.ts +53 -30
- package/src/util/update-check.ts +53 -0
- package/src/commands/gjc.ts +0 -52
- package/src/prompts/skills/gjc/AGENTS.md +0 -31
- package/src/prompts/skills/gjc/SKILL.md +0 -15
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { renderHud, type JeoPhase } from "../components/hud";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { padLineTo } from "../components/layout";
|
|
4
|
+
import { visibleWidth, truncateToWidth } from "../components/width";
|
|
5
|
+
import {
|
|
6
|
+
evolutionTrack,
|
|
7
|
+
stageIndexForStep,
|
|
6
8
|
getEvolutionStatusMessage,
|
|
7
|
-
stageProgressRatio,
|
|
8
9
|
meterGlyphsFor,
|
|
9
|
-
EVOLUTION_STAGE_COLORS
|
|
10
10
|
} from "../components/evolution";
|
|
11
11
|
|
|
12
12
|
export interface MonitorState {
|
|
@@ -17,39 +17,62 @@ export interface MonitorState {
|
|
|
17
17
|
analysisReport?: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* The `ooo ralph` sovereign monitoring HUD. Every row is padded by DISPLAY width
|
|
22
|
+
* (ANSI escapes count 0, wide glyphs count 2) and the box auto-sizes to its widest
|
|
23
|
+
* row, so the heavy border stays flush regardless of color/unicode content. The
|
|
24
|
+
* old version padded ANSI-colored strings with `String.padEnd`, which counted the
|
|
25
|
+
* SGR escape bytes and tore the right edge whenever color was on.
|
|
26
|
+
*/
|
|
20
27
|
export function renderMonitorView(state: MonitorState): string {
|
|
21
28
|
const unicode = true;
|
|
22
29
|
const stage = stageIndexForStep(state.step, state.maxSteps);
|
|
30
|
+
const ratio = Math.max(0, Math.min(1, state.maxSteps > 0 ? state.step / state.maxSteps : 0));
|
|
31
|
+
|
|
23
32
|
const hud = renderHud(state.phase, { unicode, color: true });
|
|
24
|
-
const evo = evolutionTrack(stage, { color: true, unicode, ratio
|
|
33
|
+
const evo = evolutionTrack(stage, { color: true, unicode, ratio });
|
|
25
34
|
const statusMsg = getEvolutionStatusMessage(state.step, state.maxSteps, state.tickCount);
|
|
26
|
-
|
|
27
|
-
// Progress
|
|
28
|
-
const ratio = Math.max(0, Math.min(1, state.step / state.maxSteps));
|
|
35
|
+
|
|
36
|
+
// Progress meter.
|
|
29
37
|
const barWidth = 30;
|
|
30
38
|
const filledWidth = Math.round(ratio * barWidth);
|
|
31
39
|
const glyphs = meterGlyphsFor(stage, unicode);
|
|
32
40
|
const bar = glyphs.color(glyphs.fill.repeat(filledWidth)) + chalk.dim(glyphs.empty.repeat(barWidth - filledWidth));
|
|
33
|
-
const percentage = (ratio * 100).toFixed(1) + "%";
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
const percentage = chalk.bold((ratio * 100).toFixed(1) + "%");
|
|
42
|
+
|
|
43
|
+
const label = (s: string) => chalk.bold(s);
|
|
44
|
+
const title = `${chalk.bold.yellow("ooo ralph")}${chalk.bold(" Sovereign Monitoring HUD")}`;
|
|
45
|
+
const phaseRow = `${label("PHASE:")} ${hud}`;
|
|
46
|
+
const evoRow = `${label("EVO :")} ${evo}`;
|
|
47
|
+
const progLeft = `${label("PROG :")} ${bar}`;
|
|
48
|
+
const statusRow = chalk.italic.dim(`> ${statusMsg}`);
|
|
49
|
+
const analysisRows = state.analysisReport
|
|
50
|
+
? state.analysisReport.split("\n").slice(0, 5).map(l => chalk.yellow(l))
|
|
51
|
+
: [];
|
|
52
|
+
|
|
53
|
+
// Size the inner content area to the widest row (clamped), then right-align the
|
|
54
|
+
// progress percentage within that width.
|
|
55
|
+
const MIN_INNER = 40;
|
|
56
|
+
const MAX_INNER = 88;
|
|
57
|
+
const measured = [title, phaseRow, evoRow, progLeft, statusRow, ...analysisRows].map(visibleWidth);
|
|
58
|
+
const progMin = visibleWidth(progLeft) + 1 + visibleWidth(percentage);
|
|
59
|
+
const inner = Math.min(MAX_INNER, Math.max(MIN_INNER, progMin, ...measured));
|
|
60
|
+
|
|
61
|
+
const progGap = Math.max(1, inner - visibleWidth(progLeft) - visibleWidth(percentage));
|
|
62
|
+
const progRow = `${progLeft}${" ".repeat(progGap)}${percentage}`;
|
|
63
|
+
|
|
64
|
+
const paint = chalk.bold.cyan;
|
|
65
|
+
const top = paint("┏" + "━".repeat(inner + 2) + "┓");
|
|
66
|
+
const sep = paint("┠" + "─".repeat(inner + 2) + "┨");
|
|
67
|
+
const bottom = paint("┗" + "━".repeat(inner + 2) + "┛");
|
|
68
|
+
const v = paint("┃");
|
|
69
|
+
const row = (content: string) => `${v} ${padLineTo(truncateToWidth(content, inner), inner, "left")} ${v}`;
|
|
70
|
+
|
|
71
|
+
const out: string[] = [top, row(title), sep, row(phaseRow), row(evoRow), row(progRow), sep, row(statusRow)];
|
|
72
|
+
if (analysisRows.length > 0) {
|
|
73
|
+
out.push(sep);
|
|
74
|
+
for (const line of analysisRows) out.push(row(line));
|
|
51
75
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return output;
|
|
76
|
+
out.push(bottom);
|
|
77
|
+
return out.join("\n") + "\n";
|
|
55
78
|
}
|
package/src/util/update-check.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import pkg from "../../package.json";
|
|
2
2
|
import { compareVersions } from "../commands/update";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
6
|
+
import { jeoEnv } from "./env";
|
|
3
7
|
|
|
4
8
|
export interface UpdateCheckResult {
|
|
5
9
|
current: string;
|
|
@@ -62,3 +66,52 @@ export async function checkForUpdate(deps?: UpdateCheckDeps): Promise<UpdateChec
|
|
|
62
66
|
return null;
|
|
63
67
|
}
|
|
64
68
|
}
|
|
69
|
+
|
|
70
|
+
// ---- Update-check disk cache ------------------------------------------------
|
|
71
|
+
// The live npm check often loses the startup race, so the "New version" banner
|
|
72
|
+
// rarely shows even when an update exists. Persisting the last-known-latest lets
|
|
73
|
+
// the NEXT launch render the banner INSTANTLY from disk (and offline), while a
|
|
74
|
+
// background refresh keeps the cache fresh. Mirrors gjc / npm update notices.
|
|
75
|
+
|
|
76
|
+
interface CachedUpdateCheck {
|
|
77
|
+
latest: string;
|
|
78
|
+
checkedAt: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function updateCacheDir(): string {
|
|
82
|
+
return jeoEnv("CONFIG_DIR") || path.join(os.homedir(), ".jeo");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function updateCachePath(): string {
|
|
86
|
+
return path.join(updateCacheDir(), "update-check.json");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Last-known-latest from disk, re-evaluated against the CURRENT local version
|
|
90
|
+
* (so an interim upgrade clears the banner). Null when no/invalid cache. */
|
|
91
|
+
export async function readUpdateCache(localVersion: string = pkg.version): Promise<UpdateCheckResult | null> {
|
|
92
|
+
if (typeof localVersion !== "string" || !localVersion) return null;
|
|
93
|
+
try {
|
|
94
|
+
const raw = await readFile(updateCachePath(), "utf-8");
|
|
95
|
+
const data = JSON.parse(raw) as Partial<CachedUpdateCheck>;
|
|
96
|
+
if (!data || typeof data.latest !== "string" || !data.latest) return null;
|
|
97
|
+
return {
|
|
98
|
+
current: localVersion,
|
|
99
|
+
latest: data.latest,
|
|
100
|
+
updateAvailable: compareVersions(localVersion, data.latest) < 0,
|
|
101
|
+
};
|
|
102
|
+
} catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Persist the latest version for the next launch (best-effort; never throws). */
|
|
108
|
+
export async function writeUpdateCache(latest: string): Promise<void> {
|
|
109
|
+
if (typeof latest !== "string" || !latest) return;
|
|
110
|
+
try {
|
|
111
|
+
await mkdir(updateCacheDir(), { recursive: true, mode: 0o700 });
|
|
112
|
+
const payload: CachedUpdateCheck = { latest, checkedAt: Date.now() };
|
|
113
|
+
await writeFile(updateCachePath(), JSON.stringify(payload, null, 2), { encoding: "utf-8", mode: 0o600 });
|
|
114
|
+
} catch {
|
|
115
|
+
// Cache is an optimization; a write failure must never break launch.
|
|
116
|
+
}
|
|
117
|
+
}
|
package/src/commands/gjc.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { runAgentLoop, executorSystemPrompt, DEFAULT_TOOLS } from "../agent/engine";
|
|
2
|
-
import { loadSkills, buildSkillTask, getSkillFrom } from "../skills/catalog";
|
|
3
|
-
import { readGlobalConfig, isDevMode } from "../agent/state";
|
|
4
|
-
import { runPostImplementationHooks } from "../agent/hooks";
|
|
5
|
-
|
|
6
|
-
export async function runGjcCommand(args: string[]): Promise<void> {
|
|
7
|
-
const intent = args.join(" ").trim();
|
|
8
|
-
const config = await readGlobalConfig();
|
|
9
|
-
|
|
10
|
-
if (intent.toLowerCase().includes("self-improve") && !isDevMode()) {
|
|
11
|
-
console.error("Error: Self-improvement tasks are only allowed in JEO_DEV_MODE=1.");
|
|
12
|
-
process.exit(1);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const model = config.defaultModel || "fast";
|
|
16
|
-
const skills = await loadSkills();
|
|
17
|
-
const gjcSkill = getSkillFrom(skills, "gjc");
|
|
18
|
-
|
|
19
|
-
if (!gjcSkill) {
|
|
20
|
-
console.error("Error: gjc skill not found.");
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Correct signature: executorSystemPrompt(role?, protocol?, verificationDirective?)
|
|
25
|
-
const systemPrompt = executorSystemPrompt();
|
|
26
|
-
const task = buildSkillTask(gjcSkill, intent);
|
|
27
|
-
|
|
28
|
-
await runAgentLoop([{ role: "user", content: task }], {
|
|
29
|
-
cwd: process.cwd(),
|
|
30
|
-
systemPrompt,
|
|
31
|
-
model,
|
|
32
|
-
tools: DEFAULT_TOOLS,
|
|
33
|
-
maxSteps: 50,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
console.log("\n[jeo] Verifying implementation...");
|
|
37
|
-
const verify = await runPostImplementationHooks(process.cwd(), intent);
|
|
38
|
-
|
|
39
|
-
if (!verify.success) {
|
|
40
|
-
console.error("\n[jeo] Verification FAILED. Auto-repairing...");
|
|
41
|
-
const repairTask = `Previous implementation failed verification.\nErrors:\n${verify.output}\n\nPlease fix.`;
|
|
42
|
-
await runAgentLoop([{ role: "user", content: repairTask }], {
|
|
43
|
-
cwd: process.cwd(),
|
|
44
|
-
systemPrompt,
|
|
45
|
-
model,
|
|
46
|
-
tools: DEFAULT_TOOLS,
|
|
47
|
-
maxSteps: 30,
|
|
48
|
-
});
|
|
49
|
-
} else {
|
|
50
|
-
console.log("\n[jeo] Verification SUCCESSFUL.");
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
<!-- Parent: ../AGENTS.md -->
|
|
2
|
-
<!-- Generated: 2026-06-11 | Updated: 2026-06-11 -->
|
|
3
|
-
|
|
4
|
-
# gjc
|
|
5
|
-
|
|
6
|
-
## Purpose
|
|
7
|
-
Bundled SKILL.md for the `gjc` workflow.
|
|
8
|
-
|
|
9
|
-
## Key Files
|
|
10
|
-
| File | Description |
|
|
11
|
-
|------|-------------|
|
|
12
|
-
| `SKILL.md` | The primary skill definition |
|
|
13
|
-
|
|
14
|
-
## Subdirectories
|
|
15
|
-
*(None)*
|
|
16
|
-
|
|
17
|
-
## For AI Agents
|
|
18
|
-
|
|
19
|
-
### Working In This Directory
|
|
20
|
-
- Do not modify this without understanding the broader workflow implications.
|
|
21
|
-
|
|
22
|
-
### Testing Requirements
|
|
23
|
-
- N/A
|
|
24
|
-
|
|
25
|
-
### Common Patterns
|
|
26
|
-
*(None)*
|
|
27
|
-
|
|
28
|
-
## Dependencies
|
|
29
|
-
*(None)*
|
|
30
|
-
|
|
31
|
-
<!-- MANUAL: -->
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Main implementation process using gjc spec-first workflow.
|
|
3
|
-
command: jeo gjc "<request>"
|
|
4
|
-
when: When you need to perform significant code changes, refactoring, or feature development using the core gjc process.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# gjc (Gajae-Code Process)
|
|
8
|
-
|
|
9
|
-
Executes the primary code implementation workflow by leveraging the underlying `gjc` engine (jeo-claw).
|
|
10
|
-
This process manages the heavy lifting of code transformation, while the surrounding `jeo-code` ecosystem handles loop-level orchestration.
|
|
11
|
-
|
|
12
|
-
1. **Mutation Guard**: Ensures safe code writes by blocking operations until ambiguity is low (≤ 20%).
|
|
13
|
-
2. **Role Delegation**: Utilizes specialized subagents (architect, planner, executor, critic) for focused tasks.
|
|
14
|
-
3. **Loop Control**: Maintains a tight feedback loop between planning and execution.
|
|
15
|
-
4. **Verification**: Automatically runs verification steps after implementation to ensure correctness.
|