@tracemarketplace/cli 0.0.13 → 0.0.15

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 (84) hide show
  1. package/dist/api-client.d.ts +2 -2
  2. package/dist/api-client.d.ts.map +1 -1
  3. package/dist/api-client.js +2 -2
  4. package/dist/api-client.js.map +1 -1
  5. package/dist/cli.js +45 -14
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/auto-submit.d.ts +2 -1
  8. package/dist/commands/auto-submit.d.ts.map +1 -1
  9. package/dist/commands/auto-submit.js +43 -56
  10. package/dist/commands/auto-submit.js.map +1 -1
  11. package/dist/commands/daemon.d.ts +8 -1
  12. package/dist/commands/daemon.d.ts.map +1 -1
  13. package/dist/commands/daemon.js +118 -62
  14. package/dist/commands/daemon.js.map +1 -1
  15. package/dist/commands/history.d.ts +3 -1
  16. package/dist/commands/history.d.ts.map +1 -1
  17. package/dist/commands/history.js +8 -4
  18. package/dist/commands/history.js.map +1 -1
  19. package/dist/commands/login.d.ts +5 -1
  20. package/dist/commands/login.d.ts.map +1 -1
  21. package/dist/commands/login.js +25 -9
  22. package/dist/commands/login.js.map +1 -1
  23. package/dist/commands/register.d.ts +1 -0
  24. package/dist/commands/register.d.ts.map +1 -1
  25. package/dist/commands/register.js +4 -39
  26. package/dist/commands/register.js.map +1 -1
  27. package/dist/commands/remove-hook.d.ts +6 -0
  28. package/dist/commands/remove-hook.d.ts.map +1 -0
  29. package/dist/commands/remove-hook.js +174 -0
  30. package/dist/commands/remove-hook.js.map +1 -0
  31. package/dist/commands/setup-hook.d.ts +2 -0
  32. package/dist/commands/setup-hook.d.ts.map +1 -1
  33. package/dist/commands/setup-hook.js +85 -41
  34. package/dist/commands/setup-hook.js.map +1 -1
  35. package/dist/commands/status.d.ts +3 -1
  36. package/dist/commands/status.d.ts.map +1 -1
  37. package/dist/commands/status.js +8 -4
  38. package/dist/commands/status.js.map +1 -1
  39. package/dist/commands/submit.d.ts +1 -0
  40. package/dist/commands/submit.d.ts.map +1 -1
  41. package/dist/commands/submit.js +136 -83
  42. package/dist/commands/submit.js.map +1 -1
  43. package/dist/commands/whoami.d.ts +3 -1
  44. package/dist/commands/whoami.d.ts.map +1 -1
  45. package/dist/commands/whoami.js +8 -4
  46. package/dist/commands/whoami.js.map +1 -1
  47. package/dist/config.d.ts +33 -6
  48. package/dist/config.d.ts.map +1 -1
  49. package/dist/config.js +163 -17
  50. package/dist/config.js.map +1 -1
  51. package/dist/constants.d.ts +8 -0
  52. package/dist/constants.d.ts.map +1 -0
  53. package/dist/constants.js +16 -0
  54. package/dist/constants.js.map +1 -0
  55. package/dist/flush.d.ts +46 -0
  56. package/dist/flush.d.ts.map +1 -0
  57. package/dist/flush.js +338 -0
  58. package/dist/flush.js.map +1 -0
  59. package/dist/flush.test.d.ts +2 -0
  60. package/dist/flush.test.d.ts.map +1 -0
  61. package/dist/flush.test.js +175 -0
  62. package/dist/flush.test.js.map +1 -0
  63. package/dist/submitter.d.ts.map +1 -1
  64. package/dist/submitter.js +5 -2
  65. package/dist/submitter.js.map +1 -1
  66. package/package.json +8 -7
  67. package/src/api-client.ts +3 -3
  68. package/src/cli.ts +51 -14
  69. package/src/commands/auto-submit.ts +80 -40
  70. package/src/commands/daemon.ts +166 -59
  71. package/src/commands/history.ts +9 -4
  72. package/src/commands/login.ts +37 -9
  73. package/src/commands/register.ts +5 -49
  74. package/src/commands/remove-hook.ts +194 -0
  75. package/src/commands/setup-hook.ts +93 -43
  76. package/src/commands/status.ts +8 -4
  77. package/src/commands/submit.ts +189 -83
  78. package/src/commands/whoami.ts +8 -4
  79. package/src/config.ts +223 -21
  80. package/src/constants.ts +18 -0
  81. package/src/flush.test.ts +214 -0
  82. package/src/flush.ts +505 -0
  83. package/vitest.config.ts +8 -0
  84. package/src/submitter.ts +0 -110
@@ -1,5 +1,5 @@
1
1
  /**
2
- * setup-hook — installs trace auto-submit as a per-turn hook for AI coding tools.
2
+ * setup-hook — installs tracemp auto-submit as a per-turn hook for AI coding tools.
3
3
  * Run once; sessions are then captured automatically with no user action.
4
4
  *
5
5
  * Supported tools:
@@ -12,43 +12,45 @@ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
12
12
  import { homedir } from "os";
13
13
  import { join } from "path";
14
14
  import chalk from "chalk";
15
- // The command that hooks invoke — must be on PATH after `npm install -g`
16
- const HOOK_COMMAND = "tracemp auto-submit";
15
+ import { getAutoSubmitLogPath, resolveProfile } from "../config.js";
17
16
  export async function setupHookCommand(opts) {
17
+ const profile = resolveProfile(opts.profile);
18
18
  const tools = opts.tool ? [opts.tool] : detectInstalledTools();
19
+ const hookCommand = buildHookCommand(profile);
19
20
  if (tools.length === 0) {
20
21
  console.log(chalk.yellow("No supported AI coding tools detected."));
21
22
  console.log(chalk.gray("Install Claude Code, Cursor, or Codex CLI, then run setup-hook again."));
22
- console.log(chalk.gray("Or specify: trace setup-hook --tool claude-code"));
23
+ console.log(chalk.gray("Or specify: tracemp setup-hook --tool claude-code"));
23
24
  return;
24
25
  }
25
26
  for (const tool of tools) {
26
27
  try {
27
28
  switch (tool) {
28
29
  case "claude-code":
29
- setupClaudeCode();
30
+ setupClaudeCode(hookCommand);
30
31
  break;
31
32
  case "cursor":
32
- setupCursor();
33
+ setupCursor(hookCommand);
33
34
  break;
34
35
  case "codex":
35
- setupCodex();
36
+ setupCodex(hookCommand);
36
37
  break;
37
38
  default:
38
- console.log(chalk.yellow(`Unknown tool: ${tool}. Supported: claude-code, cursor`));
39
+ console.log(chalk.yellow(`Unknown tool: ${tool}. Supported: claude-code, cursor, codex`));
39
40
  }
40
41
  }
41
42
  catch (err) {
42
43
  console.error(chalk.red(`Failed to set up hook for ${tool}: ${err}`));
43
44
  }
44
45
  }
45
- console.log(chalk.gray(`\nHook logs: ~/.config/tracemarketplace/auto-submit.log`));
46
- console.log(chalk.gray(`Remove hooks: trace remove-hook`));
46
+ console.log(chalk.gray(`\nProfile: ${profile}`));
47
+ console.log(chalk.gray(`Hook logs: ${getAutoSubmitLogPath(profile)}`));
48
+ console.log(chalk.gray("Remove hooks: tracemp remove-hook"));
47
49
  }
48
50
  // ─── Claude Code ────────────────────────────────────────────────────────────
49
51
  // Hook config: ~/.claude/settings.json
50
52
  // Stop hook fires at session end with stdin: { session_id, transcript_path }
51
- function setupClaudeCode() {
53
+ function setupClaudeCode(hookCommand) {
52
54
  const settingsPath = join(homedir(), ".claude", "settings.json");
53
55
  mkdirSync(join(homedir(), ".claude"), { recursive: true });
54
56
  let settings = {};
@@ -60,27 +62,27 @@ function setupClaudeCode() {
60
62
  }
61
63
  const hooks = settings.hooks ?? {};
62
64
  const stopHooks = hooks["Stop"] ?? [];
63
- // Don't add if already present
64
- const alreadyInstalled = stopHooks.some((h) => {
65
- const entry = h;
66
- const innerHooks = entry.hooks;
67
- return innerHooks?.some((ih) => String(ih.command ?? "").includes("auto-submit"));
65
+ const nextStopHooks = stopHooks
66
+ .map((h) => {
67
+ const entry = { ...h };
68
+ const innerHooks = Array.isArray(entry.hooks) ? entry.hooks : [];
69
+ entry.hooks = innerHooks.filter((ih) => !String(ih.command ?? "").includes("auto-submit"));
70
+ return entry;
71
+ })
72
+ .filter((entry) => Array.isArray(entry.hooks) && entry.hooks.length > 0);
73
+ nextStopHooks.push({
74
+ matcher: "",
75
+ hooks: [{ type: "command", command: hookCommand, async: true }],
68
76
  });
69
- if (!alreadyInstalled) {
70
- stopHooks.push({
71
- matcher: "",
72
- hooks: [{ type: "command", command: HOOK_COMMAND, async: true }],
73
- });
74
- hooks["Stop"] = stopHooks;
75
- settings.hooks = hooks;
76
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
77
- }
77
+ hooks["Stop"] = nextStopHooks;
78
+ settings.hooks = hooks;
79
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
78
80
  console.log(chalk.green("✓ Claude Code") + chalk.gray(` — Stop hook installed in ${settingsPath}`));
79
81
  }
80
82
  // ─── Cursor ─────────────────────────────────────────────────────────────────
81
83
  // Hook config: ~/.cursor/hooks.json
82
84
  // stop fires after each assistant turn with stdin: { sessionId, terminationReason, duration }
83
- function setupCursor() {
85
+ function setupCursor(hookCommand) {
84
86
  const hooksPath = join(homedir(), ".cursor", "hooks.json");
85
87
  mkdirSync(join(homedir(), ".cursor"), { recursive: true });
86
88
  let hooks = [];
@@ -91,19 +93,17 @@ function setupCursor() {
91
93
  }
92
94
  catch { }
93
95
  }
94
- // Remove any old sessionEnd entry for trace auto-submit (migration)
96
+ // Remove any old sessionEnd entry for tracemp auto-submit (migration)
95
97
  hooks = hooks.filter((h) => {
96
98
  const entry = h;
97
99
  return !(entry.event === "sessionEnd" && String(entry.command ?? "").includes("auto-submit"));
98
100
  });
99
- const alreadyInstalled = hooks.some((h) => {
101
+ hooks = hooks.filter((h) => {
100
102
  const entry = h;
101
- return entry.event === "stop" && String(entry.command ?? "").includes("auto-submit");
103
+ return !(entry.event === "stop" && String(entry.command ?? "").includes("auto-submit"));
102
104
  });
103
- if (!alreadyInstalled) {
104
- hooks.push({ event: "stop", command: HOOK_COMMAND, timeout: 30 });
105
- writeFileSync(hooksPath, JSON.stringify(hooks, null, 2), "utf-8");
106
- }
105
+ hooks.push({ event: "stop", command: hookCommand, timeout: 30 });
106
+ writeFileSync(hooksPath, JSON.stringify(hooks, null, 2) + "\n", "utf-8");
107
107
  console.log(chalk.green("✓ Cursor") + chalk.gray(` — stop hook installed in ${hooksPath}`));
108
108
  }
109
109
  // ─── Codex CLI ───────────────────────────────────────────────────────────────
@@ -111,8 +111,8 @@ function setupCursor() {
111
111
  // after_agent fires after each agent turn with stdin:
112
112
  // { "thread-id": "...", "turn-id": "...", "cwd": "...", "last-assistant-message": "..." }
113
113
  // Uses TOML [[hooks]] array-of-tables format.
114
- const CODEX_HOOK_MARKER = "# trace-marketplace-hook";
115
- function setupCodex() {
114
+ export const CODEX_HOOK_MARKER = "# tracemp-hook";
115
+ function setupCodex(hookCommand) {
116
116
  const configPath = join(homedir(), ".codex", "config.toml");
117
117
  mkdirSync(join(homedir(), ".codex"), { recursive: true });
118
118
  let existing = "";
@@ -122,12 +122,8 @@ function setupCodex() {
122
122
  }
123
123
  catch { }
124
124
  }
125
- if (existing.includes("auto-submit")) {
126
- console.log(chalk.green("✓ Codex") + chalk.gray(` — after_agent hook already installed in ${configPath}`));
127
- return;
128
- }
129
- const hookEntry = `\n${CODEX_HOOK_MARKER}\n[[hooks]]\nevent = "after_agent"\ncommand = "${HOOK_COMMAND} --tool codex"\n`;
130
- writeFileSync(configPath, existing + hookEntry, "utf-8");
125
+ const next = appendCodexHook(existing, `${hookCommand} --tool codex`);
126
+ writeFileSync(configPath, next, "utf-8");
131
127
  console.log(chalk.green("✓ Codex") + chalk.gray(` — after_agent hook installed in ${configPath}`));
132
128
  }
133
129
  // ─── Tool detection ──────────────────────────────────────────────────────────
@@ -145,4 +141,52 @@ function detectInstalledTools() {
145
141
  }
146
142
  return found;
147
143
  }
144
+ function buildHookCommand(profile) {
145
+ return `tracemp auto-submit --profile ${profile}`;
146
+ }
147
+ function appendCodexHook(content, hookCommand) {
148
+ const base = removeCodexHookBlocks(content).trimEnd();
149
+ const hookBlock = `${CODEX_HOOK_MARKER}\n[[hooks]]\nevent = "after_agent"\ncommand = "${hookCommand}"`;
150
+ return base ? `${base}\n\n${hookBlock}\n` : `${hookBlock}\n`;
151
+ }
152
+ function removeCodexHookBlocks(content) {
153
+ const lines = content.split("\n");
154
+ const out = [];
155
+ let i = 0;
156
+ while (i < lines.length) {
157
+ const line = lines[i];
158
+ const trimmed = line.trim();
159
+ if (trimmed === CODEX_HOOK_MARKER) {
160
+ i++;
161
+ while (i < lines.length && lines[i].trim() === "")
162
+ i++;
163
+ if (i < lines.length && lines[i].trim() === "[[hooks]]") {
164
+ i = skipHookBlock(lines, i);
165
+ while (i < lines.length && lines[i].trim() === "")
166
+ i++;
167
+ }
168
+ continue;
169
+ }
170
+ if (trimmed === "[[hooks]]") {
171
+ const blockEnd = skipHookBlock(lines, i);
172
+ const blockText = lines.slice(i, blockEnd).join("\n");
173
+ if (blockText.includes("auto-submit")) {
174
+ i = blockEnd;
175
+ while (i < lines.length && lines[i].trim() === "")
176
+ i++;
177
+ continue;
178
+ }
179
+ }
180
+ out.push(line);
181
+ i++;
182
+ }
183
+ return out.join("\n").replace(/\n{3,}/g, "\n\n");
184
+ }
185
+ function skipHookBlock(lines, start) {
186
+ let i = start + 1;
187
+ while (i < lines.length && !lines[i].trim().startsWith("[")) {
188
+ i++;
189
+ }
190
+ return i;
191
+ }
148
192
  //# sourceMappingURL=setup-hook.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup-hook.js","sourceRoot":"","sources":["../../src/commands/setup-hook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup-hook.js","sourceRoot":"","sources":["../../src/commands/setup-hook.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,4 @@
1
- export declare function statusCommand(): Promise<void>;
1
+ export declare function statusCommand(opts?: {
2
+ profile?: string;
3
+ }): Promise<void>;
2
4
  //# sourceMappingURL=status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAIA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAqBnD"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAKA,wBAAsB,aAAa,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBlF"}
@@ -1,10 +1,12 @@
1
1
  import chalk from "chalk";
2
- import { loadConfig } from "../config.js";
2
+ import { loadConfig, resolveProfile } from "../config.js";
3
3
  import { ApiClient } from "../api-client.js";
4
- export async function statusCommand() {
5
- const config = loadConfig();
4
+ import { loginCommandForProfile } from "../constants.js";
5
+ export async function statusCommand(opts = {}) {
6
+ const profile = resolveProfile(opts.profile);
7
+ const config = loadConfig(profile);
6
8
  if (!config) {
7
- console.error(chalk.red("Not registered. Run: trace register"));
9
+ console.error(chalk.red(`Not authenticated for profile '${profile}'. Run: ${loginCommandForProfile(profile)}`));
8
10
  process.exit(1);
9
11
  }
10
12
  const client = new ApiClient(config.serverUrl, config.apiKey);
@@ -13,6 +15,8 @@ export async function statusCommand() {
13
15
  client.get("/api/v1/submissions"),
14
16
  ]);
15
17
  const balance = (me.balanceCents ?? me.balance_cents ?? 0) / 100;
18
+ console.log(chalk.gray("Profile:"), config.profile);
19
+ console.log(chalk.gray("Server:"), config.serverUrl);
16
20
  console.log(chalk.bold("Balance:"), chalk.green(`$${balance.toFixed(2)}`));
17
21
  console.log(chalk.bold("Submissions:"), subs.length);
18
22
  const pending = subs.filter((s) => s.acceptedCount === null);
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,YAAY,CAA8E;QACrG,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAmB;KACpD,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,CAAE,EAAU,CAAC,YAAY,IAAK,EAAU,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;IACnF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAG,IAAc,CAAC,MAAM,CAAC,CAAC;IAEhE,MAAM,OAAO,GAAI,IAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC;IACxE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,wBAAwB,CAAC,CAAC,CAAC;IACzE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B,EAAE;IACjE,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,kCAAkC,OAAO,WAAW,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;QAChH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,YAAY,CAA8E;QACrG,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAmB;KACpD,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,CAAE,EAAU,CAAC,YAAY,IAAK,EAAU,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;IACnF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAG,IAAc,CAAC,MAAM,CAAC,CAAC;IAEhE,MAAM,OAAO,GAAI,IAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC;IACxE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,wBAAwB,CAAC,CAAC,CAAC;IACzE,CAAC;AACH,CAAC"}
@@ -1,4 +1,5 @@
1
1
  interface SubmitOptions {
2
+ profile?: string;
2
3
  tool?: string;
3
4
  session?: string;
4
5
  dryRun?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../src/commands/submit.ts"],"names":[],"mappings":"AAYA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAWD,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgLtE"}
1
+ {"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../src/commands/submit.ts"],"names":[],"mappings":"AAmBA,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmCD,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmPtE"}
@@ -1,12 +1,21 @@
1
1
  import { existsSync } from "fs";
2
- import { homedir } from "os";
2
+ import { readFile } from "fs/promises";
3
3
  import chalk from "chalk";
4
4
  import ora from "ora";
5
5
  import inquirer from "inquirer";
6
- import { extractClaudeCode, extractCodex, extractCursor, redactTrace } from "@tracemarketplace/shared";
7
- import { loadConfig } from "../config.js";
8
- import { ApiClient } from "../api-client.js";
9
- import { findFiles, CURSOR_DB_PATH } from "../sessions.js";
6
+ import { extractClaudeCode, extractCodex, extractCursor } from "@tracemarketplace/shared";
7
+ import { loadConfig, loadState, resolveProfile, stateKey } from "../config.js";
8
+ import { loginCommandForProfile } from "../constants.js";
9
+ import { buildCursorSessionSource, buildFileSessionSource, createFreshSessionState, flushTrackedSessions, migrateLegacySessionState, planSessionUploads, } from "../flush.js";
10
+ import { CURSOR_DB_PATH, findFiles } from "../sessions.js";
11
+ function pushSessionIfNonEmpty(sessions, source, trace, emptyLabel, skippedEmpty) {
12
+ if (trace.turn_count > 0) {
13
+ sessions.push({ source, trace });
14
+ }
15
+ else {
16
+ skippedEmpty.push(emptyLabel);
17
+ }
18
+ }
10
19
  function parseSinceMs(since) {
11
20
  const m = since.match(/^(\d+)(m|h|d)$/);
12
21
  if (!m)
@@ -19,16 +28,18 @@ function parseSinceMs(since) {
19
28
  return n * 24 * 60 * 60 * 1000;
20
29
  }
21
30
  export async function submitCommand(opts) {
22
- const config = loadConfig();
31
+ const profile = resolveProfile(opts.profile);
32
+ const config = loadConfig(profile);
23
33
  if (!config) {
24
- console.error(chalk.red("Not registered. Run: trace register"));
34
+ console.error(chalk.red(`Not authenticated for profile '${profile}'. Run: ${loginCommandForProfile(profile)}`));
25
35
  process.exit(1);
26
36
  }
27
37
  const sinceMs = parseSinceMs(opts.since ?? "30d");
28
38
  const sinceDays = sinceMs / (24 * 60 * 60 * 1000);
29
39
  const spinner = ora("Discovering sessions...").start();
30
- const traces = [];
40
+ const discovered = [];
31
41
  const errors = [];
42
+ const skippedEmpty = [];
32
43
  const toolAlias = {
33
44
  "claude-code": "claude_code",
34
45
  "codex": "codex_cli",
@@ -38,112 +49,142 @@ export async function submitCommand(opts) {
38
49
  if (tools.includes("claude_code")) {
39
50
  const files = findFiles("claude_code", sinceDays);
40
51
  spinner.text = `Found ${files.length} Claude Code sessions`;
41
- for (const f of files) {
52
+ for (const filePath of files) {
42
53
  try {
43
- traces.push(await extractClaudeCode(f, config.email));
54
+ pushSessionIfNonEmpty(discovered, buildFileSessionSource("claude_code", filePath), await extractClaudeCode(filePath, config.email), `Claude Code ${filePath}`, skippedEmpty);
44
55
  }
45
56
  catch (e) {
46
- errors.push(`Claude Code ${f}: ${e}`);
57
+ errors.push(`Claude Code ${filePath}: ${e}`);
47
58
  }
48
59
  }
49
60
  }
50
61
  if (tools.includes("codex_cli")) {
51
62
  const files = findFiles("codex_cli", sinceDays);
52
63
  spinner.text = `Found ${files.length} Codex sessions`;
53
- for (const f of files) {
64
+ for (const filePath of files) {
54
65
  try {
55
- const { readFile } = await import("fs/promises");
56
- const trace = await extractCodex(await readFile(f), config.email);
57
- if (trace.turn_count > 0)
58
- traces.push(trace);
66
+ pushSessionIfNonEmpty(discovered, buildFileSessionSource("codex_cli", filePath), await extractCodex(await readFile(filePath), config.email), `Codex ${filePath}`, skippedEmpty);
59
67
  }
60
68
  catch (e) {
61
- errors.push(`Codex ${f}: ${e}`);
69
+ errors.push(`Codex ${filePath}: ${e}`);
62
70
  }
63
71
  }
64
72
  }
65
- if (tools.includes("cursor")) {
66
- if (existsSync(CURSOR_DB_PATH)) {
67
- try {
68
- const { default: Database } = await import("better-sqlite3");
69
- const db = new Database(CURSOR_DB_PATH, { readonly: true });
70
- const cutoff = Date.now() - sinceMs;
71
- const allRows = db.prepare("SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'").all();
72
- const rows = allRows.filter(r => {
73
- try {
74
- const d = JSON.parse(r.value);
75
- return (d.createdAt ?? 0) >= cutoff;
76
- }
77
- catch {
78
- return false;
79
- }
80
- });
81
- db.close();
82
- spinner.text = `Found ${rows.length} Cursor sessions`;
83
- for (const { key } of rows) {
84
- const sessionId = key.replace("composerData:", "");
85
- try {
86
- traces.push(await extractCursor(CURSOR_DB_PATH, sessionId, config.email));
87
- }
88
- catch (e) {
89
- errors.push(`Cursor ${sessionId}: ${e}`);
90
- }
73
+ if (tools.includes("cursor") && existsSync(CURSOR_DB_PATH)) {
74
+ try {
75
+ const { default: Database } = await import("better-sqlite3");
76
+ const db = new Database(CURSOR_DB_PATH, { readonly: true });
77
+ const cutoff = Date.now() - sinceMs;
78
+ const allRows = db.prepare("SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'").all();
79
+ const rows = allRows.filter((row) => {
80
+ try {
81
+ const data = JSON.parse(row.value);
82
+ return (data.createdAt ?? 0) >= cutoff;
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ });
88
+ db.close();
89
+ spinner.text = `Found ${rows.length} Cursor sessions`;
90
+ for (const { key } of rows) {
91
+ const sessionId = key.replace("composerData:", "");
92
+ try {
93
+ pushSessionIfNonEmpty(discovered, buildCursorSessionSource(sessionId), await extractCursor(CURSOR_DB_PATH, sessionId, config.email), `Cursor ${sessionId}`, skippedEmpty);
94
+ }
95
+ catch (e) {
96
+ errors.push(`Cursor ${sessionId}: ${e}`);
91
97
  }
92
- }
93
- catch (e) {
94
- errors.push(`Cursor DB: ${e}`);
95
98
  }
96
99
  }
100
+ catch (e) {
101
+ errors.push(`Cursor DB: ${e}`);
102
+ }
97
103
  }
98
104
  spinner.stop();
99
- // Filter to specific session if requested
100
- const filteredTraces = opts.session
101
- ? traces.filter((t) => t.source_session_id.startsWith(opts.session))
102
- : traces;
103
- if (opts.session && filteredTraces.length === 0) {
105
+ const filtered = opts.session
106
+ ? discovered.filter((session) => session.trace.source_session_id.startsWith(opts.session))
107
+ : discovered;
108
+ if (opts.session && filtered.length === 0) {
104
109
  console.log(chalk.yellow(`No session found matching ID: ${opts.session}`));
105
110
  return;
106
111
  }
107
112
  if (errors.length > 0) {
108
113
  console.log(chalk.yellow(`\n${errors.length} extraction error(s):`));
109
- errors.slice(0, 3).forEach((e) => console.log(chalk.gray(` ${e}`)));
114
+ errors.slice(0, 3).forEach((error) => console.log(chalk.gray(` ${error}`)));
110
115
  if (errors.length > 3)
111
116
  console.log(chalk.gray(` ...and ${errors.length - 3} more`));
112
117
  }
113
- if (filteredTraces.length === 0) {
114
- console.log(chalk.yellow("No sessions found in the last " + sinceDays + " days."));
118
+ if (skippedEmpty.length > 0) {
119
+ console.log(chalk.gray(`\nSkipped ${skippedEmpty.length} empty/in-progress session(s).`));
120
+ skippedEmpty.slice(0, 3).forEach((label) => console.log(chalk.gray(` ${label}`)));
121
+ if (skippedEmpty.length > 3) {
122
+ console.log(chalk.gray(` ...and ${skippedEmpty.length - 3} more`));
123
+ }
124
+ }
125
+ if (filtered.length === 0) {
126
+ console.log(chalk.yellow(`No sessions found in the last ${sinceDays} days.`));
115
127
  return;
116
128
  }
117
- // Preview table
118
- console.log(`\n${chalk.bold("Sessions to submit:")} (${filteredTraces.length} total)\n`);
129
+ const state = loadState(config.profile);
130
+ const now = new Date();
131
+ const plannedSessions = filtered.map((session) => {
132
+ const key = stateKey(session.trace.source_tool, session.trace.source_session_id);
133
+ const existing = state.sessions[key];
134
+ const legacyChunkIndex = state.chunks[key];
135
+ const cursor = existing
136
+ ? {
137
+ ...existing,
138
+ locator: session.source.locator,
139
+ sourceTool: session.trace.source_tool,
140
+ sourceSessionId: session.trace.source_session_id,
141
+ }
142
+ : typeof legacyChunkIndex === "number"
143
+ ? migrateLegacySessionState(session.source, session.trace, legacyChunkIndex)
144
+ : createFreshSessionState(session.source, session.trace);
145
+ const plan = planSessionUploads(session.trace, cursor, now);
146
+ return {
147
+ ...session,
148
+ readyChunks: plan.uploads.length,
149
+ pending: plan.pending,
150
+ };
151
+ });
152
+ const readyChunkCount = plannedSessions.reduce((sum, session) => sum + session.readyChunks, 0);
153
+ const readySessionCount = plannedSessions.filter((session) => session.readyChunks > 0).length;
154
+ const pendingSessionCount = plannedSessions.filter((session) => session.pending).length;
155
+ console.log(chalk.gray(`Target: ${config.profile} (${config.serverUrl})`));
156
+ console.log(`\n${chalk.bold("Sessions scanned:")} (${plannedSessions.length} total)\n`);
119
157
  console.log(chalk.gray(" Tool".padEnd(16) +
120
158
  "Session ID".padEnd(20) +
121
159
  "Turns".padEnd(8) +
122
- "Tokens".padEnd(12) +
123
- "Est. payout"));
124
- console.log(chalk.gray(" " + "─".repeat(60)));
125
- for (const t of filteredTraces.slice(0, 20)) {
126
- const tokens = (t.total_input_tokens ?? 0) + (t.total_output_tokens ?? 0);
127
- const estPayout = t.content_fidelity === "full" ? "$0.04" : "$0.02";
160
+ "Ready".padEnd(8) +
161
+ "Status"));
162
+ console.log(chalk.gray(" " + "─".repeat(62)));
163
+ for (const session of plannedSessions.slice(0, 20)) {
128
164
  console.log(" " +
129
- t.source_tool.padEnd(16) +
130
- t.source_session_id.slice(0, 18).padEnd(20) +
131
- String(t.turn_count).padEnd(8) +
132
- String(tokens || "—").padEnd(12) +
133
- estPayout);
165
+ session.trace.source_tool.padEnd(16) +
166
+ session.trace.source_session_id.slice(0, 18).padEnd(20) +
167
+ String(session.trace.turn_count).padEnd(8) +
168
+ String(session.readyChunks).padEnd(8) +
169
+ describeSessionStatus(session));
134
170
  }
135
- if (filteredTraces.length > 20) {
136
- console.log(chalk.gray(` ... and ${filteredTraces.length - 20} more`));
171
+ if (plannedSessions.length > 20) {
172
+ console.log(chalk.gray(` ... and ${plannedSessions.length - 20} more`));
137
173
  }
174
+ console.log(chalk.gray(`\nReady chunks: ${readyChunkCount} across ${readySessionCount} session(s); pending sessions: ${pendingSessionCount}`));
138
175
  if (opts.dryRun) {
139
176
  console.log(chalk.cyan("\nDry run — nothing submitted."));
140
177
  return;
141
178
  }
179
+ if (readyChunkCount === 0) {
180
+ console.log(chalk.yellow("\nNo finalized chunks are ready to submit yet."));
181
+ return;
182
+ }
142
183
  const { confirm } = await inquirer.prompt([
143
184
  {
144
185
  type: "confirm",
145
186
  name: "confirm",
146
- message: `Submit ${filteredTraces.length} traces to ${config.serverUrl}?`,
187
+ message: `Submit ${readyChunkCount} finalized chunk(s) from ${readySessionCount} session(s) to ${config.profile} (${config.serverUrl})?`,
147
188
  default: true,
148
189
  },
149
190
  ]);
@@ -151,22 +192,25 @@ export async function submitCommand(opts) {
151
192
  console.log(chalk.gray("Cancelled."));
152
193
  return;
153
194
  }
154
- const uploadSpinner = ora(`Submitting ${traces.length} traces...`).start();
155
- const client = new ApiClient(config.serverUrl, config.apiKey);
195
+ const uploadSpinner = ora(`Submitting ${readyChunkCount} finalized chunk(s) to ${config.profile}...`).start();
156
196
  try {
157
- const home = homedir();
158
- const result = (await client.post("/api/v1/traces/batch", {
159
- traces: filteredTraces.map((t) => redactTrace(t, { homeDir: home })),
160
- source_tool: tools[0] ?? "mixed",
161
- }));
197
+ const result = await flushTrackedSessions(config, plannedSessions.map((session) => session.source), { includeIdleTracked: false });
162
198
  uploadSpinner.stop();
163
- const totalPayout = result.traces?.reduce((s, t) => s + (t.payout_cents ?? 0), 0) ?? 0;
199
+ const failedSessions = result.results.filter((session) => session.error && session.error !== "Empty session");
164
200
  console.log(chalk.green("\nSubmission complete!"));
165
- console.log(` Accepted: ${chalk.bold(result.accepted)}`);
166
- console.log(` Duplicates: ${chalk.gray(result.duplicate)}`);
167
- console.log(` Total: ${result.total}`);
168
- console.log(` Payout: ${chalk.green("$" + (totalPayout / 100).toFixed(2))}`);
169
- console.log(chalk.gray(`\nSubmission ID: ${result.submission_id}`));
201
+ console.log(` Uploaded chunks: ${chalk.bold(result.uploadedChunks)}`);
202
+ console.log(` Duplicate chunks: ${chalk.gray(result.duplicateChunks)}`);
203
+ console.log(` Pending sessions: ${result.pendingSessions}`);
204
+ console.log(` Payout: ${chalk.green("$" + (result.payoutCents / 100).toFixed(2))}`);
205
+ if (failedSessions.length > 0) {
206
+ console.log(chalk.yellow(`\n${failedSessions.length} session(s) failed during submit:`));
207
+ failedSessions.slice(0, 3).forEach((session) => {
208
+ console.log(chalk.gray(` ${session.source.label}: ${session.error}`));
209
+ });
210
+ if (failedSessions.length > 3) {
211
+ console.log(chalk.gray(` ...and ${failedSessions.length - 3} more`));
212
+ }
213
+ }
170
214
  }
171
215
  catch (e) {
172
216
  uploadSpinner.fail("Submission failed");
@@ -174,4 +218,13 @@ export async function submitCommand(opts) {
174
218
  process.exit(1);
175
219
  }
176
220
  }
221
+ function describeSessionStatus(session) {
222
+ if (session.readyChunks > 0 && session.pending)
223
+ return "ready + pending";
224
+ if (session.readyChunks > 0)
225
+ return "ready";
226
+ if (session.pending)
227
+ return "pending";
228
+ return "up-to-date";
229
+ }
177
230
  //# sourceMappingURL=submit.js.map