@yuaone/cli 0.1.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.
Files changed (58) hide show
  1. package/LICENSE +663 -0
  2. package/dist/auth.d.ts +71 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +240 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/cli.d.ts +16 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +212 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/cloud-client.d.ts +179 -0
  11. package/dist/cloud-client.d.ts.map +1 -0
  12. package/dist/cloud-client.js +369 -0
  13. package/dist/cloud-client.js.map +1 -0
  14. package/dist/config.d.ts +59 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +214 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/design-renderer.d.ts +16 -0
  19. package/dist/design-renderer.d.ts.map +1 -0
  20. package/dist/design-renderer.js +78 -0
  21. package/dist/design-renderer.js.map +1 -0
  22. package/dist/design.d.ts +18 -0
  23. package/dist/design.d.ts.map +1 -0
  24. package/dist/design.js +190 -0
  25. package/dist/design.js.map +1 -0
  26. package/dist/diff-renderer.d.ts +56 -0
  27. package/dist/diff-renderer.d.ts.map +1 -0
  28. package/dist/diff-renderer.js +133 -0
  29. package/dist/diff-renderer.js.map +1 -0
  30. package/dist/index.d.ts +16 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +16 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/interactive.d.ts +73 -0
  35. package/dist/interactive.d.ts.map +1 -0
  36. package/dist/interactive.js +638 -0
  37. package/dist/interactive.js.map +1 -0
  38. package/dist/oneshot.d.ts +17 -0
  39. package/dist/oneshot.d.ts.map +1 -0
  40. package/dist/oneshot.js +281 -0
  41. package/dist/oneshot.js.map +1 -0
  42. package/dist/progress-renderer.d.ts +116 -0
  43. package/dist/progress-renderer.d.ts.map +1 -0
  44. package/dist/progress-renderer.js +249 -0
  45. package/dist/progress-renderer.js.map +1 -0
  46. package/dist/renderer.d.ts +67 -0
  47. package/dist/renderer.d.ts.map +1 -0
  48. package/dist/renderer.js +182 -0
  49. package/dist/renderer.js.map +1 -0
  50. package/dist/session.d.ts +71 -0
  51. package/dist/session.d.ts.map +1 -0
  52. package/dist/session.js +246 -0
  53. package/dist/session.js.map +1 -0
  54. package/dist/y-spinner.d.ts +34 -0
  55. package/dist/y-spinner.d.ts.map +1 -0
  56. package/dist/y-spinner.js +93 -0
  57. package/dist/y-spinner.js.map +1 -0
  58. package/package.json +45 -0
@@ -0,0 +1,246 @@
1
+ /**
2
+ * YUAN CLI — Session Manager
3
+ *
4
+ * Handles saving/loading agent sessions for `yuan resume`.
5
+ * Connects to @yuaone/core SessionPersistence for disk-level persistence
6
+ * with checkpointing and crash recovery support.
7
+ */
8
+ import * as fs from "node:fs";
9
+ import * as path from "node:path";
10
+ import * as os from "node:os";
11
+ import * as crypto from "node:crypto";
12
+ import { SessionPersistence, } from "@yuaone/core";
13
+ const YUAN_DIR = path.join(os.homedir(), ".yuan");
14
+ const SESSIONS_DIR = path.join(YUAN_DIR, "sessions");
15
+ const LAST_SESSION_FILE = path.join(YUAN_DIR, "last-session");
16
+ /**
17
+ * SessionManager — save/load/resume agent sessions.
18
+ *
19
+ * Wraps @yuaone/core SessionPersistence with CLI-friendly interface.
20
+ * Sessions are stored in ~/.yuan/sessions/<sessionId>/ with:
21
+ * - state.json: metadata
22
+ * - messages.json: conversation history
23
+ * - checkpoint.json: iteration/token state
24
+ */
25
+ export class SessionManager {
26
+ persistence;
27
+ constructor(baseDir) {
28
+ this.persistence = new SessionPersistence(baseDir);
29
+ }
30
+ /** Create a new session */
31
+ create(workDir, provider, model) {
32
+ const session = {
33
+ id: crypto.randomUUID(),
34
+ createdAt: Date.now(),
35
+ updatedAt: Date.now(),
36
+ workDir,
37
+ messages: [],
38
+ provider,
39
+ model,
40
+ status: "running",
41
+ iteration: 0,
42
+ tokenUsage: { input: 0, output: 0 },
43
+ };
44
+ // Ensure session directory exists SYNCHRONOUSLY before any async writes.
45
+ // This prevents ENOENT race conditions when fire-and-forget persistence.save()
46
+ // hasn't created the directory yet and a subsequent save() call runs concurrently.
47
+ const sessionDir = path.join(SESSIONS_DIR, session.id);
48
+ fs.mkdirSync(sessionDir, { recursive: true });
49
+ // Save to disk immediately
50
+ this.save(session);
51
+ return session;
52
+ }
53
+ /** Save a session to disk (via core SessionPersistence) */
54
+ save(session) {
55
+ session.updatedAt = Date.now();
56
+ const persistentData = {
57
+ snapshot: this.toSnapshot(session),
58
+ messages: session.messages.map((m) => ({
59
+ role: m.role,
60
+ content: m.content,
61
+ })),
62
+ plan: null,
63
+ changedFiles: [],
64
+ };
65
+ // Ensure session directory exists SYNCHRONOUSLY before any async writes.
66
+ // This prevents ENOENT when multiple fire-and-forget saves race.
67
+ const sessionDir = path.join(SESSIONS_DIR, session.id);
68
+ try {
69
+ fs.mkdirSync(sessionDir, { recursive: true });
70
+ }
71
+ catch {
72
+ // Best-effort — persistence.save() will also try ensureDir
73
+ }
74
+ // Write last-session pointer
75
+ try {
76
+ fs.writeFileSync(LAST_SESSION_FILE, session.id, "utf-8");
77
+ }
78
+ catch {
79
+ // Best-effort
80
+ }
81
+ // Fire-and-forget async save with error logging
82
+ this.persistence.save(session.id, persistentData).catch((err) => {
83
+ process.stderr.write(`Session save failed: ${err}\n`);
84
+ });
85
+ }
86
+ /** Load a session by ID */
87
+ load(sessionId) {
88
+ return this.loadSync(sessionId);
89
+ }
90
+ /** Load the last session */
91
+ loadLast() {
92
+ const lastId = this.getLastSessionId();
93
+ if (!lastId)
94
+ return null;
95
+ return this.loadSync(lastId);
96
+ }
97
+ /** Get the last session ID */
98
+ getLastSessionId() {
99
+ try {
100
+ if (fs.existsSync(LAST_SESSION_FILE)) {
101
+ return fs.readFileSync(LAST_SESSION_FILE, "utf-8").trim() || null;
102
+ }
103
+ }
104
+ catch {
105
+ // Ignore
106
+ }
107
+ return null;
108
+ }
109
+ /** Add a message to a session */
110
+ addMessage(session, role, content) {
111
+ session.messages.push({
112
+ role,
113
+ content,
114
+ timestamp: Date.now(),
115
+ });
116
+ this.save(session);
117
+ }
118
+ /** Save a checkpoint (called after each iteration) */
119
+ async saveCheckpoint(session, changedFiles = [], lastToolCall) {
120
+ const checkpoint = {
121
+ iteration: session.iteration,
122
+ tokenUsage: session.tokenUsage,
123
+ timestamp: new Date().toISOString(),
124
+ changedFiles,
125
+ lastToolCall,
126
+ };
127
+ await this.persistence.checkpoint(session.id, checkpoint);
128
+ }
129
+ /** Update session status */
130
+ async updateStatus(session, status) {
131
+ session.status = status;
132
+ await this.persistence.updateStatus(session.id, status);
133
+ }
134
+ /** List recent sessions (async) */
135
+ async listSessions(limit = 20) {
136
+ return this.persistence.listSessions(limit);
137
+ }
138
+ /** List recent sessions (sync for CLI display) */
139
+ listRecent(limit = 10) {
140
+ const sessions = [];
141
+ try {
142
+ const entries = fs.readdirSync(SESSIONS_DIR, { withFileTypes: true });
143
+ for (const entry of entries) {
144
+ if (!entry.isDirectory())
145
+ continue;
146
+ try {
147
+ const stateFile = path.join(SESSIONS_DIR, entry.name, "state.json");
148
+ const messagesFile = path.join(SESSIONS_DIR, entry.name, "messages.json");
149
+ if (!fs.existsSync(stateFile))
150
+ continue;
151
+ const snapshot = JSON.parse(fs.readFileSync(stateFile, "utf-8"));
152
+ let messages = [];
153
+ if (fs.existsSync(messagesFile)) {
154
+ const rawMessages = JSON.parse(fs.readFileSync(messagesFile, "utf-8"));
155
+ messages = rawMessages.map((m, i) => ({
156
+ role: m.role,
157
+ content: m.content,
158
+ timestamp: new Date(snapshot.createdAt).getTime() + i * 1000,
159
+ }));
160
+ }
161
+ sessions.push({
162
+ id: snapshot.id,
163
+ createdAt: new Date(snapshot.createdAt).getTime(),
164
+ updatedAt: new Date(snapshot.updatedAt).getTime(),
165
+ workDir: snapshot.workDir,
166
+ messages,
167
+ provider: snapshot.provider,
168
+ model: snapshot.model,
169
+ status: snapshot.status,
170
+ iteration: snapshot.iteration,
171
+ tokenUsage: snapshot.tokenUsage,
172
+ });
173
+ }
174
+ catch {
175
+ // Skip corrupted sessions
176
+ }
177
+ }
178
+ }
179
+ catch {
180
+ // Sessions dir doesn't exist yet
181
+ }
182
+ sessions.sort((a, b) => b.updatedAt - a.updatedAt);
183
+ return sessions.slice(0, limit);
184
+ }
185
+ /** Detect crashed sessions */
186
+ async detectCrashed() {
187
+ return this.persistence.detectCrashedSessions();
188
+ }
189
+ /** Clean up old sessions */
190
+ async cleanup(maxAgeDays = 30) {
191
+ return this.persistence.cleanup(maxAgeDays);
192
+ }
193
+ // ─── Private ───
194
+ toSnapshot(session) {
195
+ return {
196
+ id: session.id,
197
+ createdAt: new Date(session.createdAt).toISOString(),
198
+ updatedAt: new Date(session.updatedAt).toISOString(),
199
+ workDir: session.workDir,
200
+ provider: session.provider,
201
+ model: session.model,
202
+ status: session.status,
203
+ iteration: session.iteration,
204
+ tokenUsage: session.tokenUsage,
205
+ messageCount: session.messages.length,
206
+ };
207
+ }
208
+ /** Sync load from disk (for CLI compatibility) */
209
+ loadSync(sessionId) {
210
+ const sessionDir = path.join(SESSIONS_DIR, sessionId);
211
+ if (!fs.existsSync(sessionDir))
212
+ return null;
213
+ try {
214
+ const stateFile = path.join(sessionDir, "state.json");
215
+ const messagesFile = path.join(sessionDir, "messages.json");
216
+ if (!fs.existsSync(stateFile))
217
+ return null;
218
+ const snapshot = JSON.parse(fs.readFileSync(stateFile, "utf-8"));
219
+ let messages = [];
220
+ if (fs.existsSync(messagesFile)) {
221
+ const rawMessages = JSON.parse(fs.readFileSync(messagesFile, "utf-8"));
222
+ messages = rawMessages.map((m, i) => ({
223
+ role: m.role,
224
+ content: m.content,
225
+ timestamp: new Date(snapshot.createdAt).getTime() + i * 1000,
226
+ }));
227
+ }
228
+ return {
229
+ id: snapshot.id,
230
+ createdAt: new Date(snapshot.createdAt).getTime(),
231
+ updatedAt: new Date(snapshot.updatedAt).getTime(),
232
+ workDir: snapshot.workDir,
233
+ messages,
234
+ provider: snapshot.provider,
235
+ model: snapshot.model,
236
+ status: snapshot.status,
237
+ iteration: snapshot.iteration,
238
+ tokenUsage: snapshot.tokenUsage,
239
+ };
240
+ }
241
+ catch {
242
+ return null;
243
+ }
244
+ }
245
+ }
246
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @module y-spinner
3
+ * @description Y spinner animation for CLI.
4
+ * Uses ANSI 256 colors for a glowing Y logo effect.
5
+ */
6
+ /**
7
+ * YSpinner — Terminal spinner with a glowing Y logo animation.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const spinner = new YSpinner();
12
+ * spinner.start("Authenticating...");
13
+ * // ... async work ...
14
+ * spinner.success("Logged in!");
15
+ * ```
16
+ */
17
+ export declare class YSpinner {
18
+ private timer;
19
+ private frameIndex;
20
+ private message;
21
+ /** Start the spinner with an initial message. */
22
+ start(message: string): void;
23
+ /** Update the spinner message without stopping it. */
24
+ update(message: string): void;
25
+ /** Stop the spinner and show a success message. */
26
+ success(message: string): void;
27
+ /** Stop the spinner and show a failure message. */
28
+ fail(message: string): void;
29
+ /** Stop the spinner and restore the cursor. */
30
+ stop(): void;
31
+ /** Render the current frame to stderr. */
32
+ private render;
33
+ }
34
+ //# sourceMappingURL=y-spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"y-spinner.d.ts","sourceRoot":"","sources":["../src/y-spinner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoCH;;;;;;;;;;GAUG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAM;IAErB,iDAAiD;IACjD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAa5B,sDAAsD;IACtD,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI7B,mDAAmD;IACnD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM9B,mDAAmD;IACnD,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM3B,+CAA+C;IAC/C,IAAI,IAAI,IAAI;IASZ,0CAA0C;IAC1C,OAAO,CAAC,MAAM;CAIf"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @module y-spinner
3
+ * @description Y spinner animation for CLI.
4
+ * Uses ANSI 256 colors for a glowing Y logo effect.
5
+ */
6
+ /** ANSI 256-color palette for the Y spinner */
7
+ const COLORS = {
8
+ dim: "\x1b[38;5;240m",
9
+ normal: "\x1b[38;5;33m",
10
+ bright: "\x1b[38;5;39m",
11
+ glow: "\x1b[38;5;51m",
12
+ accent: "\x1b[38;5;220m",
13
+ green: "\x1b[38;5;82m",
14
+ red: "\x1b[38;5;196m",
15
+ reset: "\x1b[0m",
16
+ };
17
+ /** Hide/show cursor ANSI sequences */
18
+ const CURSOR_HIDE = "\x1b[?25l";
19
+ const CURSOR_SHOW = "\x1b[?25h";
20
+ const CLEAR_LINE = "\x1b[2K\r";
21
+ /**
22
+ * Animation frames — 8 frames cycling through dim → normal → bright → glow.
23
+ * Each frame applies a different color to the Y character.
24
+ */
25
+ const FRAMES = [
26
+ `${COLORS.dim}Y${COLORS.reset}`,
27
+ `${COLORS.dim}Y${COLORS.reset}`,
28
+ `${COLORS.normal}Y${COLORS.reset}`,
29
+ `${COLORS.normal}Y${COLORS.reset}`,
30
+ `${COLORS.bright}Y${COLORS.reset}`,
31
+ `${COLORS.bright}Y${COLORS.reset}`,
32
+ `${COLORS.glow}Y${COLORS.reset}`,
33
+ `${COLORS.accent}Y${COLORS.reset}`,
34
+ ];
35
+ const FRAME_INTERVAL = 100;
36
+ /**
37
+ * YSpinner — Terminal spinner with a glowing Y logo animation.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * const spinner = new YSpinner();
42
+ * spinner.start("Authenticating...");
43
+ * // ... async work ...
44
+ * spinner.success("Logged in!");
45
+ * ```
46
+ */
47
+ export class YSpinner {
48
+ timer = null;
49
+ frameIndex = 0;
50
+ message = "";
51
+ /** Start the spinner with an initial message. */
52
+ start(message) {
53
+ this.message = message;
54
+ this.frameIndex = 0;
55
+ process.stderr.write(CURSOR_HIDE);
56
+ this.render();
57
+ this.timer = setInterval(() => {
58
+ this.frameIndex = (this.frameIndex + 1) % FRAMES.length;
59
+ this.render();
60
+ }, FRAME_INTERVAL);
61
+ }
62
+ /** Update the spinner message without stopping it. */
63
+ update(message) {
64
+ this.message = message;
65
+ }
66
+ /** Stop the spinner and show a success message. */
67
+ success(message) {
68
+ this.stop();
69
+ const icon = `${COLORS.green}Y\u2713${COLORS.reset}`;
70
+ process.stderr.write(`${CLEAR_LINE}${icon} ${message}\n`);
71
+ }
72
+ /** Stop the spinner and show a failure message. */
73
+ fail(message) {
74
+ this.stop();
75
+ const icon = `${COLORS.red}Y\u2717${COLORS.reset}`;
76
+ process.stderr.write(`${CLEAR_LINE}${icon} ${message}\n`);
77
+ }
78
+ /** Stop the spinner and restore the cursor. */
79
+ stop() {
80
+ if (this.timer !== null) {
81
+ clearInterval(this.timer);
82
+ this.timer = null;
83
+ }
84
+ process.stderr.write(CLEAR_LINE);
85
+ process.stderr.write(CURSOR_SHOW);
86
+ }
87
+ /** Render the current frame to stderr. */
88
+ render() {
89
+ const frame = FRAMES[this.frameIndex];
90
+ process.stderr.write(`${CLEAR_LINE}${frame} ${this.message}`);
91
+ }
92
+ }
93
+ //# sourceMappingURL=y-spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"y-spinner.js","sourceRoot":"","sources":["../src/y-spinner.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@yuaone/cli",
3
+ "version": "0.1.0",
4
+ "description": "YUAN — Autonomous Coding Agent CLI",
5
+ "license": "AGPL-3.0",
6
+ "type": "module",
7
+ "bin": {
8
+ "yuan": "dist/cli.js"
9
+ },
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "files": ["dist/", "README.md", "LICENSE"],
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/yuaone/yuan.git",
19
+ "directory": "packages/yuan-cli"
20
+ },
21
+ "homepage": "https://github.com/yuaone/yuan#readme",
22
+ "bugs": {
23
+ "url": "https://github.com/yuaone/yuan/issues"
24
+ },
25
+ "keywords": ["coding-agent", "ai", "autonomous", "cli", "llm", "developer-tools"],
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc && chmod +x dist/cli.js",
31
+ "dev": "tsc --watch",
32
+ "clean": "rm -rf dist",
33
+ "lint": "tsc --noEmit",
34
+ "start": "node dist/cli.js"
35
+ },
36
+ "dependencies": {
37
+ "@yuaone/core": "workspace:*",
38
+ "@yuaone/tools": "workspace:*",
39
+ "commander": "^13.1.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.19.15",
43
+ "typescript": "^5.7.0"
44
+ }
45
+ }