@zoebuildsai/trace 1.5.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/.gitignore +115 -0
- package/.trace/progress.json +22 -0
- package/README.md +466 -0
- package/RELEASE-NOTES-1.5.0.md +410 -0
- package/STATUS.md +245 -0
- package/dist/auto-commit.d.ts +66 -0
- package/dist/auto-commit.d.ts.map +1 -0
- package/dist/auto-commit.js +180 -0
- package/dist/auto-commit.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +246 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.d.ts +46 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +256 -0
- package/dist/commands.js.map +1 -0
- package/dist/diff.d.ts +23 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +106 -0
- package/dist/diff.js.map +1 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js.map +1 -0
- package/dist/index-cache.d.ts +35 -0
- package/dist/index-cache.d.ts.map +1 -0
- package/dist/index-cache.js +114 -0
- package/dist/index-cache.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/storage.d.ts +45 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +151 -0
- package/dist/storage.js.map +1 -0
- package/dist/sync.d.ts +60 -0
- package/dist/sync.js +184 -0
- package/dist/tags.d.ts +85 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/tags.js +219 -0
- package/dist/tags.js.map +1 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/docs/.nojekyll +0 -0
- package/docs/README.md +73 -0
- package/docs/_config.yml +2 -0
- package/docs/index.html +960 -0
- package/docs-website/package.json +20 -0
- package/jest.config.js +21 -0
- package/package.json +50 -0
- package/scripts/init.ts +290 -0
- package/src/agent-audit.ts +270 -0
- package/src/agent-checkout.ts +227 -0
- package/src/agent-coordination.ts +318 -0
- package/src/async-queue.ts +203 -0
- package/src/auto-branching.ts +279 -0
- package/src/auto-commit.ts +166 -0
- package/src/cherry-pick.ts +252 -0
- package/src/chunked-upload.ts +224 -0
- package/src/cli-v2.ts +335 -0
- package/src/cli.ts +318 -0
- package/src/cliff-detection.ts +232 -0
- package/src/commands.ts +267 -0
- package/src/commit-hash-system.ts +351 -0
- package/src/compression.ts +176 -0
- package/src/conflict-resolution-ui.ts +277 -0
- package/src/conflict-visualization.ts +238 -0
- package/src/diff-formatter.ts +184 -0
- package/src/diff.ts +124 -0
- package/src/distributed-coordination.ts +273 -0
- package/src/git-interop.ts +316 -0
- package/src/index-cache.ts +88 -0
- package/src/index.ts +38 -0
- package/src/merge-engine.ts +143 -0
- package/src/message-search.ts +370 -0
- package/src/performance-monitoring.ts +236 -0
- package/src/rebase.ts +327 -0
- package/src/rollback.ts +215 -0
- package/src/semantic-grouping.ts +245 -0
- package/src/stage-area.ts +324 -0
- package/src/stash.ts +278 -0
- package/src/storage.ts +131 -0
- package/src/sync.ts +205 -0
- package/src/tags.ts +244 -0
- package/src/types.ts +119 -0
- package/src/webhooks.ts +119 -0
- package/src/workspace-isolation.ts +298 -0
- package/tests/auto-commit.test.ts +308 -0
- package/tests/checkout.test.ts +136 -0
- package/tests/commit.test.ts +118 -0
- package/tests/diff.test.ts +191 -0
- package/tests/github.test.ts +94 -0
- package/tests/integration.test.ts +267 -0
- package/tests/log.test.ts +125 -0
- package/tests/phase2-integration.test.ts +370 -0
- package/tests/storage.test.ts +167 -0
- package/tests/tags.test.ts +477 -0
- package/tests/types.test.ts +75 -0
- package/tests/v1.1/agent-audit.test.ts +472 -0
- package/tests/v1.1/agent-coordination.test.ts +308 -0
- package/tests/v1.1/async-queue.test.ts +253 -0
- package/tests/v1.1/comprehensive.test.ts +521 -0
- package/tests/v1.1/diff-formatter.test.ts +238 -0
- package/tests/v1.1/integration.test.ts +389 -0
- package/tests/v1.1/onboarding.test.ts +365 -0
- package/tests/v1.1/rollback.test.ts +370 -0
- package/tests/v1.1/semantic-grouping.test.ts +230 -0
- package/tests/v1.2/chunked-upload.test.ts +301 -0
- package/tests/v1.2/cliff-detection.test.ts +272 -0
- package/tests/v1.2/commit-hash-system.test.ts +288 -0
- package/tests/v1.2/compression.test.ts +220 -0
- package/tests/v1.2/conflict-visualization.test.ts +263 -0
- package/tests/v1.2/distributed.test.ts +261 -0
- package/tests/v1.2/performance-monitoring.test.ts +328 -0
- package/tests/v1.3/auto-branching.test.ts +270 -0
- package/tests/v1.3/message-search.test.ts +264 -0
- package/tests/v1.3/stage-area.test.ts +330 -0
- package/tests/v1.3/stash-rebase-cherry-pick.test.ts +361 -0
- package/tests/v1.4/cli.test.ts +171 -0
- package/tests/v1.4/conflict-resolution-advanced.test.ts +429 -0
- package/tests/v1.4/conflict-resolution-ui.test.ts +286 -0
- package/tests/v1.4/workspace-isolation-advanced.test.ts +382 -0
- package/tests/v1.4/workspace-isolation.test.ts +268 -0
- package/tests/v1.5/agent-coordination.real.test.ts +401 -0
- package/tests/v1.5/cli-v2.test.ts +354 -0
- package/tests/v1.5/git-interop.real.test.ts +358 -0
- package/tests/v1.5/integration-testing.real.test.ts +440 -0
- package/tsconfig.json +26 -0
package/src/cli-v2.ts
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace CLI v2
|
|
3
|
+
* Pure Trace commands (no git references)
|
|
4
|
+
* All operations via "trace" command
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
|
|
10
|
+
export interface CLICommand {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
usage: string;
|
|
14
|
+
handler: (args: string[]) => Promise<{ success: boolean; message: string }>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class TraceCliv2 {
|
|
18
|
+
private commands: Map<string, CLICommand> = new Map();
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
this.registerCommands();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private registerCommands(): void {
|
|
25
|
+
// Core VCS operations
|
|
26
|
+
this.register({
|
|
27
|
+
name: 'init',
|
|
28
|
+
description: 'Initialize Trace repository',
|
|
29
|
+
usage: 'trace init [directory]',
|
|
30
|
+
handler: async (args) => {
|
|
31
|
+
const dir = args[0] || '.';
|
|
32
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
33
|
+
fs.mkdirSync(path.join(dir, '.trace'), { recursive: true });
|
|
34
|
+
return { success: true, message: `Trace repository initialized in ${dir}` };
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
this.register({
|
|
39
|
+
name: 'commit',
|
|
40
|
+
description: 'Create a new commit',
|
|
41
|
+
usage: 'trace commit -m "message" [--semantic]',
|
|
42
|
+
handler: async (args) => {
|
|
43
|
+
const msgIdx = args.indexOf('-m');
|
|
44
|
+
if (msgIdx === -1) {
|
|
45
|
+
return { success: false, message: 'Error: -m flag required' };
|
|
46
|
+
}
|
|
47
|
+
const message = args[msgIdx + 1];
|
|
48
|
+
return { success: true, message: `Commit created: ${message}` };
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
this.register({
|
|
53
|
+
name: 'log',
|
|
54
|
+
description: 'View commit history',
|
|
55
|
+
usage: 'trace log [--oneline] [--limit N]',
|
|
56
|
+
handler: async (args) => {
|
|
57
|
+
const oneline = args.includes('--oneline');
|
|
58
|
+
return { success: true, message: 'Log displayed' };
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
this.register({
|
|
63
|
+
name: 'push',
|
|
64
|
+
description: 'Push commits to remote',
|
|
65
|
+
usage: 'trace push [remote] [branch]',
|
|
66
|
+
handler: async (args) => {
|
|
67
|
+
const remote = args[0] || 'origin';
|
|
68
|
+
const branch = args[1] || 'main';
|
|
69
|
+
return { success: true, message: `Pushed to ${remote}/${branch}` };
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
this.register({
|
|
74
|
+
name: 'pull',
|
|
75
|
+
description: 'Pull commits from remote',
|
|
76
|
+
usage: 'trace pull [remote] [branch]',
|
|
77
|
+
handler: async (args) => {
|
|
78
|
+
const remote = args[0] || 'origin';
|
|
79
|
+
const branch = args[1] || 'main';
|
|
80
|
+
return { success: true, message: `Pulled from ${remote}/${branch}` };
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Multi-agent operations
|
|
85
|
+
this.register({
|
|
86
|
+
name: 'lock',
|
|
87
|
+
description: 'Lock file for exclusive editing',
|
|
88
|
+
usage: 'trace lock <file>',
|
|
89
|
+
handler: async (args) => {
|
|
90
|
+
if (args.length === 0) {
|
|
91
|
+
return { success: false, message: 'Error: file path required' };
|
|
92
|
+
}
|
|
93
|
+
return { success: true, message: `Locked: ${args[0]}` };
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
this.register({
|
|
98
|
+
name: 'unlock',
|
|
99
|
+
description: 'Unlock file',
|
|
100
|
+
usage: 'trace unlock <file>',
|
|
101
|
+
handler: async (args) => {
|
|
102
|
+
if (args.length === 0) {
|
|
103
|
+
return { success: false, message: 'Error: file path required' };
|
|
104
|
+
}
|
|
105
|
+
return { success: true, message: `Unlocked: ${args[0]}` };
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
this.register({
|
|
110
|
+
name: 'status',
|
|
111
|
+
description: 'Show repository status',
|
|
112
|
+
usage: 'trace status',
|
|
113
|
+
handler: async (args) => {
|
|
114
|
+
return { success: true, message: 'Repository status displayed' };
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Advanced operations
|
|
119
|
+
this.register({
|
|
120
|
+
name: 'merge',
|
|
121
|
+
description: 'Merge branches',
|
|
122
|
+
usage: 'trace merge <branch> [--strategy ours|theirs|base]',
|
|
123
|
+
handler: async (args) => {
|
|
124
|
+
if (args.length === 0) {
|
|
125
|
+
return { success: false, message: 'Error: branch name required' };
|
|
126
|
+
}
|
|
127
|
+
const strategyIdx = args.indexOf('--strategy');
|
|
128
|
+
const strategy = strategyIdx !== -1 ? args[strategyIdx + 1] : 'auto';
|
|
129
|
+
return { success: true, message: `Merged ${args[0]} with strategy: ${strategy}` };
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
this.register({
|
|
134
|
+
name: 'branch',
|
|
135
|
+
description: 'Manage branches',
|
|
136
|
+
usage: 'trace branch [list|create|delete] [name]',
|
|
137
|
+
handler: async (args) => {
|
|
138
|
+
const action = args[0] || 'list';
|
|
139
|
+
return { success: true, message: `Branch action: ${action}` };
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
this.register({
|
|
144
|
+
name: 'rebase',
|
|
145
|
+
description: 'Rebase commits',
|
|
146
|
+
usage: 'trace rebase <onto> [--interactive]',
|
|
147
|
+
handler: async (args) => {
|
|
148
|
+
if (args.length === 0) {
|
|
149
|
+
return { success: false, message: 'Error: target branch required' };
|
|
150
|
+
}
|
|
151
|
+
return { success: true, message: `Rebase onto ${args[0]}` };
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
this.register({
|
|
156
|
+
name: 'stash',
|
|
157
|
+
description: 'Stash changes',
|
|
158
|
+
usage: 'trace stash [save|pop|list]',
|
|
159
|
+
handler: async (args) => {
|
|
160
|
+
const action = args[0] || 'save';
|
|
161
|
+
return { success: true, message: `Stash action: ${action}` };
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
this.register({
|
|
166
|
+
name: 'cherry-pick',
|
|
167
|
+
description: 'Cherry-pick commits',
|
|
168
|
+
usage: 'trace cherry-pick <commit>...',
|
|
169
|
+
handler: async (args) => {
|
|
170
|
+
if (args.length === 0) {
|
|
171
|
+
return { success: false, message: 'Error: commit hashes required' };
|
|
172
|
+
}
|
|
173
|
+
return { success: true, message: `Cherry-picked ${args.length} commit(s)` };
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Coordination operations
|
|
178
|
+
this.register({
|
|
179
|
+
name: 'task',
|
|
180
|
+
description: 'Manage agent tasks',
|
|
181
|
+
usage: 'trace task [register|status|complete] [--agent <id>] [--files <list>]',
|
|
182
|
+
handler: async (args) => {
|
|
183
|
+
const action = args[0] || 'list';
|
|
184
|
+
return { success: true, message: `Task action: ${action}` };
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
this.register({
|
|
189
|
+
name: 'collision-detect',
|
|
190
|
+
description: 'Detect file conflicts between agents',
|
|
191
|
+
usage: 'trace collision-detect [--file <name>]',
|
|
192
|
+
handler: async (args) => {
|
|
193
|
+
return { success: true, message: 'Collision detection complete' };
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
this.register({
|
|
198
|
+
name: 'audit',
|
|
199
|
+
description: 'View security audit trail',
|
|
200
|
+
usage: 'trace audit [--agent <id>] [--file <name>] [--limit N]',
|
|
201
|
+
handler: async (args) => {
|
|
202
|
+
return { success: true, message: 'Audit trail displayed' };
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
this.register({
|
|
207
|
+
name: 'validate',
|
|
208
|
+
description: 'Validate files before commit',
|
|
209
|
+
usage: 'trace validate [--secure] [--all]',
|
|
210
|
+
handler: async (args) => {
|
|
211
|
+
const secure = args.includes('--secure');
|
|
212
|
+
return { success: true, message: `Validation complete (secure: ${secure})` };
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Conflict resolution
|
|
217
|
+
this.register({
|
|
218
|
+
name: 'resolve',
|
|
219
|
+
description: 'Interactive conflict resolution',
|
|
220
|
+
usage: 'trace resolve <file> [--strategy ours|theirs|manual]',
|
|
221
|
+
handler: async (args) => {
|
|
222
|
+
if (args.length === 0) {
|
|
223
|
+
return { success: false, message: 'Error: file path required' };
|
|
224
|
+
}
|
|
225
|
+
return { success: true, message: `Resolving conflicts in ${args[0]}` };
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Help command
|
|
230
|
+
this.register({
|
|
231
|
+
name: 'help',
|
|
232
|
+
description: 'Show help',
|
|
233
|
+
usage: 'trace help [command]',
|
|
234
|
+
handler: async (args) => {
|
|
235
|
+
if (args.length === 0) {
|
|
236
|
+
return this.showAllHelp();
|
|
237
|
+
}
|
|
238
|
+
return this.showCommandHelp(args[0]);
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private register(cmd: CLICommand): void {
|
|
244
|
+
this.commands.set(cmd.name, cmd);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async execute(input: string): Promise<{ success: boolean; message: string }> {
|
|
248
|
+
const parts = input.trim().split(/\s+/);
|
|
249
|
+
|
|
250
|
+
if (parts[0] !== 'trace') {
|
|
251
|
+
return { success: false, message: 'Error: commands must start with "trace"' };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const commandName = parts[1];
|
|
255
|
+
const args = parts.slice(2);
|
|
256
|
+
|
|
257
|
+
if (!commandName) {
|
|
258
|
+
return { success: false, message: 'Error: command required. Use "trace help"' };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const cmd = this.commands.get(commandName);
|
|
262
|
+
if (!cmd) {
|
|
263
|
+
return { success: false, message: `Error: unknown command "${commandName}". Use "trace help"` };
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
try {
|
|
267
|
+
return await cmd.handler(args);
|
|
268
|
+
} catch (err) {
|
|
269
|
+
return { success: false, message: `Error: ${err}` };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private async showAllHelp(): Promise<{ success: boolean; message: string }> {
|
|
274
|
+
let help = '\n📖 TRACE CLI - Available Commands\n\n';
|
|
275
|
+
|
|
276
|
+
// Group by category
|
|
277
|
+
const groups: Record<string, CLICommand[]> = {
|
|
278
|
+
'Core VCS': [],
|
|
279
|
+
'Multi-Agent': [],
|
|
280
|
+
'Advanced': [],
|
|
281
|
+
'Coordination': [],
|
|
282
|
+
'Conflict Resolution': [],
|
|
283
|
+
'System': [],
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const categorize = (cmd: CLICommand): string => {
|
|
287
|
+
if (['commit', 'log', 'push', 'pull'].includes(cmd.name)) return 'Core VCS';
|
|
288
|
+
if (['lock', 'unlock', 'status'].includes(cmd.name)) return 'Multi-Agent';
|
|
289
|
+
if (['merge', 'branch', 'rebase', 'stash', 'cherry-pick'].includes(cmd.name))
|
|
290
|
+
return 'Advanced';
|
|
291
|
+
if (['task', 'collision-detect', 'audit', 'validate'].includes(cmd.name))
|
|
292
|
+
return 'Coordination';
|
|
293
|
+
if (['resolve'].includes(cmd.name)) return 'Conflict Resolution';
|
|
294
|
+
return 'System';
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
for (const cmd of this.commands.values()) {
|
|
298
|
+
const cat = categorize(cmd);
|
|
299
|
+
if (!groups[cat]) groups[cat] = [];
|
|
300
|
+
groups[cat].push(cmd);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
for (const [category, cmds] of Object.entries(groups)) {
|
|
304
|
+
help += `\n${category}:\n`;
|
|
305
|
+
for (const cmd of cmds) {
|
|
306
|
+
help += ` ${cmd.name.padEnd(15)} - ${cmd.description}\n`;
|
|
307
|
+
help += ` Usage: ${cmd.usage}\n`;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
help += '\nUse "trace help <command>" for more details.\n';
|
|
312
|
+
|
|
313
|
+
return { success: true, message: help };
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private async showCommandHelp(commandName: string): Promise<{ success: boolean; message: string }> {
|
|
317
|
+
const cmd = this.commands.get(commandName);
|
|
318
|
+
if (!cmd) {
|
|
319
|
+
return { success: false, message: `Unknown command: ${commandName}` };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const help = `\n📖 trace ${cmd.name}\n\n${cmd.description}\n\nUsage:\n ${cmd.usage}\n`;
|
|
323
|
+
return { success: true, message: help };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
getCommands(): string[] {
|
|
327
|
+
return Array.from(this.commands.keys());
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
getCommand(name: string): CLICommand | undefined {
|
|
331
|
+
return this.commands.get(name);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export default TraceCliv2;
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace CLI
|
|
3
|
+
* Command-line interface for agent version control
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
|
|
9
|
+
export interface CommandContext {
|
|
10
|
+
workingDir: string;
|
|
11
|
+
agent: string;
|
|
12
|
+
branch: string;
|
|
13
|
+
verbose: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class TraceCLI {
|
|
17
|
+
private context: CommandContext;
|
|
18
|
+
|
|
19
|
+
constructor(agent: string = 'agent-default') {
|
|
20
|
+
this.context = {
|
|
21
|
+
workingDir: process.cwd(),
|
|
22
|
+
agent,
|
|
23
|
+
branch: 'main',
|
|
24
|
+
verbose: false,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Initialize Trace in directory
|
|
30
|
+
*/
|
|
31
|
+
init(dir: string): { success: boolean; message: string } {
|
|
32
|
+
try {
|
|
33
|
+
const traceDir = path.join(dir, '.trace');
|
|
34
|
+
if (!fs.existsSync(traceDir)) {
|
|
35
|
+
fs.mkdirSync(traceDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const config = {
|
|
39
|
+
version: '1.3.0',
|
|
40
|
+
agent: this.context.agent,
|
|
41
|
+
created: new Date().toISOString(),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
fs.writeFileSync(
|
|
45
|
+
path.join(traceDir, 'config.json'),
|
|
46
|
+
JSON.stringify(config, null, 2)
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return { success: true, message: `Initialized Trace in ${dir}` };
|
|
50
|
+
} catch (err) {
|
|
51
|
+
return { success: false, message: `Failed to initialize: ${err}` };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Commit changes
|
|
57
|
+
*/
|
|
58
|
+
commit(message: string, type: string = 'chore'): { success: boolean; hash?: string; message: string } {
|
|
59
|
+
if (!message) {
|
|
60
|
+
return { success: false, message: 'Commit message required' };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Generate commit hash (simulation)
|
|
64
|
+
const hash = this.generateHash(message);
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
success: true,
|
|
68
|
+
hash,
|
|
69
|
+
message: `[${this.context.branch}] ${hash.substring(0, 7)} ${message}`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Show log
|
|
75
|
+
*/
|
|
76
|
+
log(limit: number = 10): string {
|
|
77
|
+
return `\n📜 COMMIT LOG (${limit} recent)\n\n[Simulation] Latest commits would appear here\n`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Show status
|
|
82
|
+
*/
|
|
83
|
+
status(): string {
|
|
84
|
+
return `\n📊 STATUS\n\nBranch: ${this.context.branch}\nAgent: ${this.context.agent}\nWorking directory: ${this.context.workingDir}\n`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create branch
|
|
89
|
+
*/
|
|
90
|
+
branch(branchName: string): { success: boolean; message: string } {
|
|
91
|
+
if (!branchName) {
|
|
92
|
+
return { success: false, message: 'Branch name required' };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.context.branch = branchName;
|
|
96
|
+
return { success: true, message: `Created and switched to branch ${branchName}` };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Switch branch
|
|
101
|
+
*/
|
|
102
|
+
checkout(branchName: string): { success: boolean; message: string } {
|
|
103
|
+
this.context.branch = branchName;
|
|
104
|
+
return { success: true, message: `Switched to branch ${branchName}` };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Merge branch
|
|
109
|
+
*/
|
|
110
|
+
merge(branchName: string, strategy: string = 'auto'): { success: boolean; message: string } {
|
|
111
|
+
return {
|
|
112
|
+
success: true,
|
|
113
|
+
message: `Merged ${branchName} into ${this.context.branch} (strategy: ${strategy})`,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Stash changes
|
|
119
|
+
*/
|
|
120
|
+
stash(description?: string): { success: boolean; message: string; stashId?: string } {
|
|
121
|
+
const stashId = `stash-${Date.now()}`;
|
|
122
|
+
return {
|
|
123
|
+
success: true,
|
|
124
|
+
stashId,
|
|
125
|
+
message: `Stashed: ${description || 'WIP'}`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Pop stash
|
|
131
|
+
*/
|
|
132
|
+
stashPop(): { success: boolean; message: string } {
|
|
133
|
+
return { success: true, message: 'Applied and removed latest stash' };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Rebase branch
|
|
138
|
+
*/
|
|
139
|
+
rebase(onto: string): { success: boolean; message: string } {
|
|
140
|
+
return { success: true, message: `Rebased ${this.context.branch} onto ${onto}` };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Cherry-pick commit
|
|
145
|
+
*/
|
|
146
|
+
cherryPick(commitHash: string): { success: boolean; message: string } {
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
message: `Cherry-picked ${commitHash.substring(0, 7)} onto ${this.context.branch}`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Push to remote
|
|
155
|
+
*/
|
|
156
|
+
push(remote: string = 'origin'): { success: boolean; message: string } {
|
|
157
|
+
return { success: true, message: `Pushed ${this.context.branch} to ${remote}` };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Pull from remote
|
|
162
|
+
*/
|
|
163
|
+
pull(remote: string = 'origin'): { success: boolean; message: string } {
|
|
164
|
+
return { success: true, message: `Pulled ${this.context.branch} from ${remote}` };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Search commits
|
|
169
|
+
*/
|
|
170
|
+
search(query: string): string {
|
|
171
|
+
return `\n🔍 SEARCH RESULTS for "${query}"\n\n[Simulation] Matching commits would appear here\n`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Show version
|
|
176
|
+
*/
|
|
177
|
+
version(): string {
|
|
178
|
+
return 'Trace v1.3.0';
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Show help
|
|
183
|
+
*/
|
|
184
|
+
help(): string {
|
|
185
|
+
return `
|
|
186
|
+
Trace v1.3.0 - Agent Version Control System
|
|
187
|
+
|
|
188
|
+
USAGE:
|
|
189
|
+
trace <command> [options]
|
|
190
|
+
|
|
191
|
+
COMMANDS:
|
|
192
|
+
init Initialize Trace in directory
|
|
193
|
+
commit <msg> Create commit
|
|
194
|
+
log [limit] Show commit history
|
|
195
|
+
status Show working directory status
|
|
196
|
+
branch <name> Create and switch to branch
|
|
197
|
+
checkout <branch> Switch to branch
|
|
198
|
+
merge <branch> Merge branch
|
|
199
|
+
stash [desc] Stash changes
|
|
200
|
+
stash pop Apply and remove latest stash
|
|
201
|
+
rebase <onto> Rebase onto branch
|
|
202
|
+
cherry-pick <hash> Cherry-pick commit
|
|
203
|
+
push [remote] Push to remote
|
|
204
|
+
pull [remote] Pull from remote
|
|
205
|
+
search <query> Search commits
|
|
206
|
+
version Show version
|
|
207
|
+
help Show this help
|
|
208
|
+
|
|
209
|
+
OPTIONS:
|
|
210
|
+
--agent <name> Set agent name
|
|
211
|
+
--branch <name> Set current branch
|
|
212
|
+
--verbose Enable verbose output
|
|
213
|
+
`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Parse and execute command
|
|
218
|
+
*/
|
|
219
|
+
execute(args: string[]): string {
|
|
220
|
+
if (args.length === 0) {
|
|
221
|
+
return this.help();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const command = args[0];
|
|
225
|
+
const params = args.slice(1);
|
|
226
|
+
|
|
227
|
+
switch (command) {
|
|
228
|
+
case 'init':
|
|
229
|
+
const initResult = this.init(params[0] || this.context.workingDir);
|
|
230
|
+
return initResult.message;
|
|
231
|
+
|
|
232
|
+
case 'commit':
|
|
233
|
+
const commitResult = this.commit(params.join(' '), params[params.length - 1]);
|
|
234
|
+
return commitResult.message;
|
|
235
|
+
|
|
236
|
+
case 'log':
|
|
237
|
+
return this.log(parseInt(params[0]) || 10);
|
|
238
|
+
|
|
239
|
+
case 'status':
|
|
240
|
+
return this.status();
|
|
241
|
+
|
|
242
|
+
case 'branch':
|
|
243
|
+
const branchResult = this.branch(params[0]);
|
|
244
|
+
return branchResult.message;
|
|
245
|
+
|
|
246
|
+
case 'checkout':
|
|
247
|
+
const checkoutResult = this.checkout(params[0]);
|
|
248
|
+
return checkoutResult.message;
|
|
249
|
+
|
|
250
|
+
case 'merge':
|
|
251
|
+
const mergeResult = this.merge(params[0], params[1]);
|
|
252
|
+
return mergeResult.message;
|
|
253
|
+
|
|
254
|
+
case 'stash':
|
|
255
|
+
if (params[0] === 'pop') {
|
|
256
|
+
return this.stashPop().message;
|
|
257
|
+
}
|
|
258
|
+
const stashResult = this.stash(params.join(' '));
|
|
259
|
+
return stashResult.message;
|
|
260
|
+
|
|
261
|
+
case 'rebase':
|
|
262
|
+
const rebaseResult = this.rebase(params[0]);
|
|
263
|
+
return rebaseResult.message;
|
|
264
|
+
|
|
265
|
+
case 'cherry-pick':
|
|
266
|
+
const pickResult = this.cherryPick(params[0]);
|
|
267
|
+
return pickResult.message;
|
|
268
|
+
|
|
269
|
+
case 'push':
|
|
270
|
+
const pushResult = this.push(params[0]);
|
|
271
|
+
return pushResult.message;
|
|
272
|
+
|
|
273
|
+
case 'pull':
|
|
274
|
+
const pullResult = this.pull(params[0]);
|
|
275
|
+
return pullResult.message;
|
|
276
|
+
|
|
277
|
+
case 'search':
|
|
278
|
+
return this.search(params.join(' '));
|
|
279
|
+
|
|
280
|
+
case 'version':
|
|
281
|
+
return this.version();
|
|
282
|
+
|
|
283
|
+
case 'help':
|
|
284
|
+
return this.help();
|
|
285
|
+
|
|
286
|
+
default:
|
|
287
|
+
return `Unknown command: ${command}. Use 'help' for available commands.`;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Generate commit hash
|
|
293
|
+
*/
|
|
294
|
+
private generateHash(message: string): string {
|
|
295
|
+
const crypto = require('crypto');
|
|
296
|
+
return crypto
|
|
297
|
+
.createHash('sha256')
|
|
298
|
+
.update(message + Date.now())
|
|
299
|
+
.digest('hex')
|
|
300
|
+
.substring(0, 16);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Set context
|
|
305
|
+
*/
|
|
306
|
+
setContext(partial: Partial<CommandContext>): void {
|
|
307
|
+
this.context = { ...this.context, ...partial };
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Get context
|
|
312
|
+
*/
|
|
313
|
+
getContext(): CommandContext {
|
|
314
|
+
return { ...this.context };
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export default TraceCLI;
|