jeo-code 0.7.30 → 0.7.32

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.ja.md +5 -3
  3. package/README.ko.md +5 -3
  4. package/README.md +5 -3
  5. package/README.zh.md +5 -3
  6. package/package.json +3 -3
  7. package/scripts/install.sh +19 -0
  8. package/scripts/uninstall.sh +2 -2
  9. package/src/agent/AGENTS.md +12 -0
  10. package/src/agent/ast-edit-tool.ts +123 -0
  11. package/src/agent/ast-file-scan.ts +62 -0
  12. package/src/agent/ast-grep-tool.ts +107 -0
  13. package/src/agent/ast-match.ts +241 -0
  14. package/src/agent/compaction.ts +6 -19
  15. package/src/agent/debug-session.ts +435 -0
  16. package/src/agent/debug-tool.ts +89 -0
  17. package/src/agent/engine.ts +103 -18
  18. package/src/agent/goal-tool.ts +57 -0
  19. package/src/agent/irc-tool.ts +71 -0
  20. package/src/agent/job-registry.ts +163 -0
  21. package/src/agent/job-tool.ts +106 -0
  22. package/src/agent/lsp-rename-tool.ts +108 -0
  23. package/src/agent/lsp-tool.ts +177 -0
  24. package/src/agent/memory-graph.ts +6 -1
  25. package/src/agent/memory.ts +73 -52
  26. package/src/agent/session.ts +27 -0
  27. package/src/agent/subagent-registry.ts +40 -4
  28. package/src/agent/subagent-tool.ts +27 -7
  29. package/src/agent/subagents.ts +1 -1
  30. package/src/agent/task-tool.ts +27 -5
  31. package/src/agent/tools.ts +100 -5
  32. package/src/agent/ts-language-service.ts +173 -0
  33. package/src/ai/model-manager.ts +58 -26
  34. package/src/ai/sse.ts +22 -7
  35. package/src/ai/think-tags.ts +10 -1
  36. package/src/commands/deep-interview.ts +49 -1
  37. package/src/commands/launch/agents-slash.ts +489 -0
  38. package/src/commands/launch/flags.ts +27 -9
  39. package/src/commands/launch/model-slash.ts +290 -0
  40. package/src/commands/launch/session-slash.ts +305 -0
  41. package/src/commands/launch/slash-handlers.ts +6 -0
  42. package/src/commands/launch/system-slash.ts +81 -0
  43. package/src/commands/launch/tmux.ts +32 -0
  44. package/src/commands/launch.ts +227 -750
  45. package/src/tui/app.ts +32 -12
  46. package/src/tui/components/evolution.ts +23 -3
  47. package/src/tui/components/width.ts +11 -6
@@ -0,0 +1,81 @@
1
+ /**
2
+ * System/meta slash handlers (`/theme`, `/config` + `/settings`, `/evolve`)
3
+ * extracted from launch.ts.
4
+ *
5
+ * These commands used to have two byte-identical implementations in
6
+ * launch.ts — one in the one-shot control-command block, one in the
7
+ * interactive REPL loop — which is exactly the kind of drift that lets a fix
8
+ * to one copy silently miss the other. Following the `decideWikiSlash`
9
+ * pattern (see wiki-slash.ts), the decision/formatting logic lives here as
10
+ * pure (or narrowly side-effecting) functions; each launch.ts call site just
11
+ * applies the persistence/live-repaint side effects appropriate to its mode.
12
+ */
13
+
14
+ import { readGlobalConfig } from "../../agent/state";
15
+ import { describeModel } from "../../ai";
16
+ import { formatConfigPanel } from "../../tui/components/config-panel";
17
+ import { EVOLUTION_STAGES } from "../../tui/components/ascii-art";
18
+
19
+ /** Outcome of parsing a `/theme [name]` command line. `lines` are printed verbatim. */
20
+ export interface ThemeDecision {
21
+ kind: "list" | "unknown" | "set";
22
+ lines: string[];
23
+ themeName?: string; // present when kind === "set"
24
+ }
25
+
26
+ /**
27
+ * Decide what `/theme [name]` should print/do, given the known themes and
28
+ * active name. Pure — callers apply the persistence + optional live-repaint
29
+ * side effects based on `kind`.
30
+ */
31
+ export function decideThemeSlash(
32
+ cmd: string,
33
+ themes: readonly { name: string; description: string }[],
34
+ activeName: string,
35
+ ): ThemeDecision {
36
+ const want = cmd.substring(6).trim().toLowerCase();
37
+ if (!want) {
38
+ const lines = ["TUI themes (set with /theme <name>, persists via ~/.jeo/config.json):"];
39
+ for (const t of themes) lines.push(` ${t.name === activeName ? "*" : " "} ${t.name.padEnd(10)} ${t.description}`);
40
+ return { kind: "list", lines };
41
+ }
42
+ if (!themes.some(t => t.name === want)) {
43
+ return { kind: "unknown", lines: [`Unknown theme '${want}'. Known: ${themes.map(t => t.name).join(", ")}.`] };
44
+ }
45
+ return { kind: "set", lines: [`Theme set to ${want} — saved to ~/.jeo/config.json`], themeName: want };
46
+ }
47
+
48
+ /** Build the `/config` (+ `/settings`) panel lines. Read-only, no side effects. */
49
+ export async function buildConfigPanelLines(opts: {
50
+ sessionModel?: string;
51
+ sessionThinking?: string;
52
+ sessionId?: string;
53
+ }): Promise<string[]> {
54
+ const cfgNow = await readGlobalConfig();
55
+ const label = opts.sessionModel || cfgNow.defaultModel;
56
+ const { resolved, provider } = await describeModel(label);
57
+ const lines = ["Effective runtime config:"];
58
+ for (const line of formatConfigPanel({
59
+ model: label,
60
+ resolved,
61
+ provider,
62
+ thinkingLevel: opts.sessionThinking ?? cfgNow.thinkingLevel ?? "medium",
63
+ ollamaBaseUrl: cfgNow.ollamaBaseUrl,
64
+ openaiBaseUrl: cfgNow.openaiBaseUrl,
65
+ requestMaxRetries: cfgNow.retry?.requestMaxRetries,
66
+ sessionId: opts.sessionId,
67
+ })) lines.push(line);
68
+ return lines;
69
+ }
70
+
71
+ /** Run the `/evolve` ascii-art animation sequence. */
72
+ export async function runEvolveSimulation(
73
+ animateAsciiArt: (stage: (typeof EVOLUTION_STAGES)[number], opts: { delayMs: number }) => Promise<void>,
74
+ ): Promise<void> {
75
+ console.log("=== Initiating Evolutionary Simulation ===");
76
+ for (const stage of EVOLUTION_STAGES) {
77
+ console.log(`\nStage: ${stage.name}`);
78
+ await animateAsciiArt(stage, { delayMs: 40 });
79
+ }
80
+ console.log("\n=== Evolved to Singularity! ===");
81
+ }
@@ -94,6 +94,38 @@ export function shellQuote(arg: string): string {
94
94
  return `'${arg.replace(/'/g, `'\\''`)}'`;
95
95
  }
96
96
 
97
+ /** Caller-terminal dimensions for a detached `tmux new-session` (gjc launch-tmux parity #1376). */
98
+ export interface TmuxTerminalSize {
99
+ columns: number;
100
+ rows: number;
101
+ }
102
+
103
+ function normalizeTmuxDimension(value: number | undefined): number | undefined {
104
+ return value !== undefined && Number.isSafeInteger(value) && value > 0 ? value : undefined;
105
+ }
106
+
107
+ /**
108
+ * Resolve the caller terminal's size so a detached `tmux new-session` is created at
109
+ * the REAL terminal dimensions instead of tmux's 80x24 detached default. Without this
110
+ * the inner jeo renders its first frames (banner, status footer) at 80 columns, and
111
+ * that mis-wrapped output stays wrong in the pane scrollback even after the attach
112
+ * resizes the window. Returns undefined when stdout is not a TTY or either dimension
113
+ * is unknown/invalid — callers then omit sizing and let tmux use its default.
114
+ */
115
+ export function callerTmuxTerminalSize(
116
+ out: { isTTY?: boolean; columns?: number; rows?: number } = process.stdout,
117
+ ): TmuxTerminalSize | undefined {
118
+ if (!out.isTTY) return undefined;
119
+ const columns = normalizeTmuxDimension(out.columns);
120
+ const rows = normalizeTmuxDimension(out.rows);
121
+ return columns !== undefined && rows !== undefined ? { columns, rows } : undefined;
122
+ }
123
+
124
+ /** `-x/-y` args for `new-session`; empty when the size is unknown. */
125
+ export function tmuxNewSessionSizeArgs(size: TmuxTerminalSize | undefined): string[] {
126
+ return size ? ["-x", String(size.columns), "-y", String(size.rows)] : [];
127
+ }
128
+
97
129
 
98
130
 
99
131