@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,7 +1,7 @@
1
1
  export declare class ApiClient {
2
2
  private baseUrl;
3
- private apiKey;
4
- constructor(baseUrl: string, apiKey: string);
3
+ private apiKey?;
4
+ constructor(baseUrl: string, apiKey?: string | undefined);
5
5
  get(path: string): Promise<unknown>;
6
6
  post(path: string, body: unknown): Promise<unknown>;
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAS;IAElB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAGlB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWnC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAe1D"}
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAS;IAElB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,MAAM,CAAC;gBADP,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,YAAA;IAGnB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWnC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAe1D"}
@@ -7,7 +7,7 @@ export class ApiClient {
7
7
  }
8
8
  async get(path) {
9
9
  const res = await fetch(`${this.baseUrl}${path}`, {
10
- headers: { "X-Api-Key": this.apiKey },
10
+ headers: this.apiKey ? { "X-Api-Key": this.apiKey } : {},
11
11
  });
12
12
  if (!res.ok) {
13
13
  const text = await res.text();
@@ -20,7 +20,7 @@ export class ApiClient {
20
20
  method: "POST",
21
21
  headers: {
22
22
  "Content-Type": "application/json",
23
- "X-Api-Key": this.apiKey,
23
+ ...(this.apiKey ? { "X-Api-Key": this.apiKey } : {}),
24
24
  },
25
25
  body: JSON.stringify(body),
26
26
  });
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,SAAS;IAEV;IACA;IAFV,YACU,OAAe,EACf,MAAc;QADd,YAAO,GAAP,OAAO,CAAQ;QACf,WAAM,GAAN,MAAM,CAAQ;IACrB,CAAC;IAEJ,KAAK,CAAC,GAAG,CAAC,IAAY;QACpB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YAChD,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE;SACtC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAAa;QACpC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;CACF"}
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,SAAS;IAEV;IACA;IAFV,YACU,OAAe,EACf,MAAe;QADf,YAAO,GAAP,OAAO,CAAQ;QACf,WAAM,GAAN,MAAM,CAAS;IACtB,CAAC;IAEJ,KAAK,CAAC,GAAG,CAAC,IAAY;QACpB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YAChD,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;SACzD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAAa;QACpC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACrD;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;CACF"}
package/dist/cli.js CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import { readFileSync } from "fs";
3
+ import { dirname, join } from "path";
4
+ import { fileURLToPath } from "url";
2
5
  import { program } from "commander";
3
6
  import { loginCommand } from "./commands/login.js";
4
7
  import { registerCommand } from "./commands/register.js";
@@ -9,31 +12,41 @@ import { historyCommand } from "./commands/history.js";
9
12
  import { autoSubmitCommand } from "./commands/auto-submit.js";
10
13
  import { setupHookCommand } from "./commands/setup-hook.js";
11
14
  import { daemonCommand } from "./commands/daemon.js";
15
+ import { removeHookCommand } from "./commands/remove-hook.js";
16
+ import { CLI_NAME, DEFAULT_PROFILE, PROD_SERVER_URL } from "./constants.js";
17
+ const profileOptionDescription = `Config profile (default: ${DEFAULT_PROFILE})`;
18
+ const packageVersion = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "../package.json"), "utf-8")).version;
12
19
  program
13
- .name("trace")
20
+ .name(CLI_NAME)
14
21
  .description("Trace Marketplace CLI — submit AI coding sessions, get paid")
15
- .version("0.0.1");
22
+ .version(packageVersion);
16
23
  program
17
24
  .command("login")
18
- .description("Sign in via browser opens tracemarketplace.dev, no key needed")
19
- .action(() => loginCommand().catch(handleError));
25
+ .description("Sign in via browser and save your API key")
26
+ .option("--profile <name>", profileOptionDescription)
27
+ .option("--server-url <url>", `Server URL (default prod: ${PROD_SERVER_URL})`)
28
+ .action((opts) => loginCommand({ profile: opts.profile, serverUrl: opts.serverUrl }).catch(handleError));
20
29
  program
21
30
  .command("register")
22
- .description("Register your email and get an API key")
23
- .option("--server-url <url>", "Server URL (default: https://trace-marketplace-api.fly.dev)")
24
- .action((opts) => registerCommand({ serverUrl: opts.serverUrl }).catch(handleError));
31
+ .description("Alias for login — signs in via browser and saves your API key")
32
+ .option("--profile <name>", profileOptionDescription)
33
+ .option("--server-url <url>", `Server URL (default prod: ${PROD_SERVER_URL})`)
34
+ .action((opts) => registerCommand({ profile: opts.profile, serverUrl: opts.serverUrl }).catch(handleError));
25
35
  program
26
36
  .command("whoami")
27
37
  .description("Show your account info and balance")
28
- .action(() => whoamiCommand().catch(handleError));
38
+ .option("--profile <name>", profileOptionDescription)
39
+ .action((opts) => whoamiCommand({ profile: opts.profile }).catch(handleError));
29
40
  program
30
41
  .command("submit")
31
42
  .description("Auto-detect and submit traces from Claude Code, Codex CLI, and Cursor")
43
+ .option("--profile <name>", profileOptionDescription)
32
44
  .option("--tool <tool>", "Only submit from specific tool (claude-code|codex|cursor)")
33
45
  .option("--session <id>", "Only submit a specific session ID")
34
46
  .option("--dry-run", "Preview without submitting")
35
47
  .option("--created-since <duration>", "Only include sessions created within duration (e.g. 30d, 12h, 30m)", "30d")
36
48
  .action((opts) => submitCommand({
49
+ profile: opts.profile,
37
50
  tool: opts.tool,
38
51
  session: opts.session,
39
52
  dryRun: opts.dryRun,
@@ -42,27 +55,45 @@ program
42
55
  program
43
56
  .command("status")
44
57
  .description("Show pending submissions and balance")
45
- .action(() => statusCommand().catch(handleError));
58
+ .option("--profile <name>", profileOptionDescription)
59
+ .action((opts) => statusCommand({ profile: opts.profile }).catch(handleError));
46
60
  program
47
61
  .command("history")
48
62
  .description("Show submission history")
49
- .action(() => historyCommand().catch(handleError));
63
+ .option("--profile <name>", profileOptionDescription)
64
+ .action((opts) => historyCommand({ profile: opts.profile }).catch(handleError));
50
65
  program
51
66
  .command("auto-submit")
52
67
  .description("Submit the current session (called by tool hooks — do not run manually)")
68
+ .option("--profile <name>", profileOptionDescription)
53
69
  .option("--tool <tool>", "Tool that triggered the hook (claude-code|cursor|codex)")
54
70
  .option("--session <id>", "Session ID (for cursor/codex hooks)")
55
71
  .option("--file <path>", "Direct path to session file (for claude-code)")
56
- .action((opts) => autoSubmitCommand({ tool: opts.tool, session: opts.session, file: opts.file }));
72
+ .action((opts) => autoSubmitCommand({ profile: opts.profile, tool: opts.tool, session: opts.session, file: opts.file }));
57
73
  program
58
74
  .command("daemon")
59
- .description("Watch session directories and auto-submit new sessions as they appear")
60
- .action(() => daemonCommand().catch(handleError));
75
+ .description("Poll for new sessions and auto-submit them; use --once for cron or --watch for live mode")
76
+ .option("--profile <name>", profileOptionDescription)
77
+ .option("--interval <seconds>", "Polling interval in seconds", "60")
78
+ .option("--once", "Run one polling pass and exit")
79
+ .option("--watch", "Use live filesystem watch mode instead of polling")
80
+ .action((opts) => daemonCommand({
81
+ profile: opts.profile,
82
+ interval: opts.interval,
83
+ once: opts.once,
84
+ watch: opts.watch,
85
+ }).catch(handleError));
61
86
  program
62
87
  .command("setup-hook")
63
88
  .description("Install session-end hooks for Claude Code, Cursor, and Codex CLI")
89
+ .option("--profile <name>", profileOptionDescription)
64
90
  .option("--tool <tool>", "Only set up hook for specific tool (claude-code|cursor|codex)")
65
- .action((opts) => setupHookCommand({ tool: opts.tool }).catch(handleError));
91
+ .action((opts) => setupHookCommand({ profile: opts.profile, tool: opts.tool }).catch(handleError));
92
+ program
93
+ .command("remove-hook")
94
+ .description("Remove tracemp hooks from Claude Code, Cursor, and Codex CLI")
95
+ .option("--tool <tool>", "Only remove hook for specific tool (claude-code|cursor|codex)")
96
+ .action((opts) => removeHookCommand({ tool: opts.tool }).catch(handleError));
66
97
  function handleError(e) {
67
98
  console.error(e.message ?? String(e));
68
99
  process.exit(1);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,6DAA6D,CAAC;KAC1E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,iEAAiE,CAAC;KAC9E,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;AAEnD,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,oBAAoB,EAAE,6DAA6D,CAAC;KAC3F,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;AAEvF,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;AAEpD,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,uEAAuE,CAAC;KACpF,MAAM,CAAC,eAAe,EAAE,2DAA2D,CAAC;KACpF,MAAM,CAAC,gBAAgB,EAAE,mCAAmC,CAAC;KAC7D,MAAM,CAAC,WAAW,EAAE,4BAA4B,CAAC;KACjD,MAAM,CAAC,4BAA4B,EAAE,oEAAoE,EAAE,KAAK,CAAC;KACjH,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACf,aAAa,CAAC;IACZ,IAAI,EAAE,IAAI,CAAC,IAAI;IACf,OAAO,EAAE,IAAI,CAAC,OAAO;IACrB,MAAM,EAAE,IAAI,CAAC,MAAM;IACnB,KAAK,EAAE,IAAI,CAAC,YAAY;CACzB,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CACtB,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;AAEpD,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;AAErD,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,yEAAyE,CAAC;KACtF,MAAM,CAAC,eAAe,EAAE,yDAAyD,CAAC;KAClF,MAAM,CAAC,gBAAgB,EAAE,qCAAqC,CAAC;KAC/D,MAAM,CAAC,eAAe,EAAE,+CAA+C,CAAC;KACxE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAEpG,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,uEAAuE,CAAC;KACpF,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;AAEpD,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,kEAAkE,CAAC;KAC/E,MAAM,CAAC,eAAe,EAAE,+DAA+D,CAAC;KACxF,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;AAE9E,SAAS,WAAW,CAAC,CAAU;IAC7B,OAAO,CAAC,KAAK,CAAE,CAAW,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  interface AutoSubmitOptions {
2
+ profile?: string;
2
3
  tool?: string;
3
4
  session?: string;
4
5
  file?: string;
5
6
  }
6
- export declare function log(msg: string): void;
7
+ export declare function log(msg: string, profile?: string): void;
7
8
  export declare function autoSubmitCommand(opts: AutoSubmitOptions): Promise<void>;
8
9
  export {};
9
10
  //# sourceMappingURL=auto-submit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auto-submit.d.ts","sourceRoot":"","sources":["../../src/commands/auto-submit.ts"],"names":[],"mappings":"AAYA,UAAU,iBAAiB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,QAM9B;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E"}
1
+ {"version":3,"file":"auto-submit.d.ts","sourceRoot":"","sources":["../../src/commands/auto-submit.ts"],"names":[],"mappings":"AAgBA,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,SAAkB,QAKzD;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9E"}
@@ -1,19 +1,17 @@
1
1
  /**
2
2
  * auto-submit — called by tool hooks (Claude Code Stop, Cursor sessionEnd).
3
3
  * Non-interactive: never prompts, always exits 0 so it never blocks the user's tool.
4
- * Logs results to ~/.config/tracemarketplace/auto-submit.log
4
+ * Logs results to ~/.config/tracemarketplace/auto-submit(.<profile>).log
5
5
  */
6
6
  import { readFileSync, appendFileSync, mkdirSync } from "fs";
7
- import { homedir } from "os";
8
- import { join } from "path";
9
- import { loadConfig } from "../config.js";
7
+ import { getAutoSubmitLogPath, getConfigDir, loadConfig, resolveProfile } from "../config.js";
10
8
  import { findLatestFile, findCodexFileById } from "../sessions.js";
11
- import { submitFile, submitCursorSession } from "../submitter.js";
12
- export function log(msg) {
13
- const dir = join(homedir(), ".config", "tracemarketplace");
14
- mkdirSync(dir, { recursive: true });
9
+ import { loginCommandForProfile, DEFAULT_PROFILE } from "../constants.js";
10
+ import { buildCursorSessionSource, buildFileSessionSource, flushTrackedSessions, } from "../flush.js";
11
+ export function log(msg, profile = DEFAULT_PROFILE) {
12
+ mkdirSync(getConfigDir(), { recursive: true });
15
13
  try {
16
- appendFileSync(join(dir, "auto-submit.log"), `[${new Date().toISOString()}] ${msg}\n`);
14
+ appendFileSync(getAutoSubmitLogPath(profile), `[${new Date().toISOString()}] ${msg}\n`);
17
15
  }
18
16
  catch { }
19
17
  }
@@ -22,13 +20,14 @@ export async function autoSubmitCommand(opts) {
22
20
  await run(opts);
23
21
  }
24
22
  catch (err) {
25
- log(`ERROR: ${String(err)}`);
23
+ log(`ERROR: ${String(err)}`, resolveProfile(opts.profile));
26
24
  }
27
25
  }
28
26
  async function run(opts) {
29
- const config = loadConfig();
27
+ const profile = resolveProfile(opts.profile);
28
+ const config = loadConfig(profile);
30
29
  if (!config) {
31
- log("Not registered — run: trace register");
30
+ log(`Not authenticated — run: ${loginCommandForProfile(profile)}`, profile);
32
31
  return;
33
32
  }
34
33
  // Read hook payload from stdin
@@ -40,64 +39,52 @@ async function run(opts) {
40
39
  }
41
40
  catch { }
42
41
  const tool = opts.tool ?? inferTool(hookPayload);
43
- if (!tool) {
44
- log("Could not determine tool");
42
+ const triggerSource = resolveTriggerSource(tool, opts, hookPayload);
43
+ if (!triggerSource && !tool) {
44
+ log("Could not determine tool", profile);
45
45
  return;
46
46
  }
47
- log(`auto-submit triggered for tool=${tool}`);
47
+ log(`auto-submit triggered for profile=${profile} tool=${tool ?? "unknown"}`, profile);
48
+ const result = await flushTrackedSessions(config, triggerSource ? [triggerSource] : [], { includeIdleTracked: true });
49
+ logFlushResult(result, profile);
50
+ }
51
+ function logFlushResult(result, profile) {
52
+ for (const session of result.results) {
53
+ if (session.error && session.error !== "Empty session") {
54
+ log(`${session.source.label}: ${session.error}`, profile);
55
+ continue;
56
+ }
57
+ if (session.uploadedChunks > 0 || session.duplicateChunks > 0) {
58
+ const status = session.uploadedChunks > 0 ? "uploaded" : "duplicate";
59
+ log(`${session.source.label}: ${status} chunks=${session.uploadedChunks + session.duplicateChunks} pending=${session.pending} payout=$${(session.payoutCents / 100).toFixed(2)}`, profile);
60
+ }
61
+ }
62
+ if (result.uploadedChunks === 0 && result.duplicateChunks === 0) {
63
+ log(`no finalized chunks ready; pending_sessions=${result.pendingSessions}`, profile);
64
+ }
65
+ }
66
+ function resolveTriggerSource(tool, opts, hookPayload) {
67
+ if (!tool) {
68
+ return null;
69
+ }
48
70
  if (tool === "claude-code" || tool === "claude_code") {
49
- // Claude Code Stop hook sends { session_id, transcript_path }
50
71
  const filePath = opts.file
51
72
  ?? hookPayload["transcript_path"]
52
73
  ?? findLatestFile("claude_code");
53
- if (!filePath) {
54
- log("Claude Code: no session file found");
55
- return;
56
- }
57
- const result = await submitFile("claude_code", filePath, config);
58
- logResult(result, filePath);
74
+ return filePath ? buildFileSessionSource("claude_code", filePath) : null;
59
75
  }
60
- else if (tool === "cursor") {
76
+ if (tool === "cursor") {
61
77
  const sessionId = opts.session ?? hookPayload["sessionId"];
62
- if (!sessionId) {
63
- log("Cursor: no sessionId");
64
- return;
65
- }
66
- const result = await submitCursorSession(sessionId, config);
67
- logResult(result, sessionId);
78
+ return sessionId ? buildCursorSessionSource(sessionId) : null;
68
79
  }
69
- else if (tool === "codex" || tool === "codex_cli") {
70
- // after_agent payload: { "thread-id": "...", "turn-id": "...", "cwd": "...", "last-assistant-message": "..." }
71
- // Legacy / manual: session_path or session_id
80
+ if (tool === "codex" || tool === "codex_cli") {
72
81
  const threadId = hookPayload["thread-id"] ?? "";
73
82
  const filePath = opts.file
74
83
  ?? hookPayload["session_path"]
75
84
  ?? findCodexFileById(opts.session ?? hookPayload["session_id"] ?? threadId ?? "");
76
- if (!filePath) {
77
- log("Codex: no session file found");
78
- return;
79
- }
80
- const result = await submitFile("codex_cli", filePath, config);
81
- logResult(result, filePath);
82
- }
83
- else {
84
- log(`Unknown tool: ${tool}`);
85
- }
86
- }
87
- function logResult(result, label) {
88
- if (result.error) {
89
- log(`${label}: ${result.error}`);
90
- return;
85
+ return filePath ? buildFileSessionSource("codex_cli", filePath) : null;
91
86
  }
92
- if (result.duplicate) {
93
- log(`${label}: already captured — skipped`);
94
- return;
95
- }
96
- if (result.superseded) {
97
- log(`${label}: updated (${result.turnCount} turns) — $${(result.payoutCents / 100).toFixed(2)}`);
98
- return;
99
- }
100
- log(`${label}: accepted (${result.turnCount} turns) — $${(result.payoutCents / 100).toFixed(2)}`);
87
+ return null;
101
88
  }
102
89
  function inferTool(payload) {
103
90
  if (payload["transcript_path"])
@@ -1 +1 @@
1
- {"version":3,"file":"auto-submit.js","sourceRoot":"","sources":["../../src/commands/auto-submit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAQlE,MAAM,UAAU,GAAG,CAAC,GAAW;IAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;IAC3D,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAuB;IAC7D,IAAI,CAAC;QAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,GAAG,CAAC,UAAU,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAAC,CAAC;AACxE,CAAC;AAED,KAAK,UAAU,GAAG,CAAC,IAAuB;IACxC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAErE,+BAA+B;IAC/B,IAAI,WAAW,GAA4B,EAAE,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,IAAI,GAAG;YAAE,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,CAAC,IAAI,EAAE,CAAC;QAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAEvD,GAAG,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC;IAE9C,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QACrD,8DAA8D;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI;eACrB,WAAW,CAAC,iBAAiB,CAAW;eACxC,cAAc,CAAC,aAAa,CAAC,CAAC;QAEnC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAErE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,aAAa,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjE,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE9B,CAAC;SAAM,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC,WAAW,CAAW,CAAC;QACrE,IAAI,CAAC,SAAS,EAAE,CAAC;YAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAExD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC5D,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE/B,CAAC;SAAM,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACpD,+GAA+G;QAC/G,8CAA8C;QAC9C,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAW,IAAI,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI;eACrB,WAAW,CAAC,cAAc,CAAW;eACrC,iBAAiB,CAAC,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC,YAAY,CAAW,IAAI,QAAQ,IAAI,EAAE,CAAC,CAAC;QAE9F,IAAI,CAAC,QAAQ,EAAE,CAAC;YAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAE/D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/D,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE9B,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,MAA8C,EAAE,KAAa;IAC9E,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAAC,GAAG,CAAC,GAAG,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC/D,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QAAC,GAAG,CAAC,GAAG,KAAK,8BAA8B,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC9E,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAAC,GAAG,CAAC,GAAG,KAAK,cAAc,MAAM,CAAC,SAAS,cAAc,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IACpI,GAAG,CAAC,GAAG,KAAK,eAAe,MAAM,CAAC,SAAS,cAAc,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpG,CAAC;AAED,SAAS,SAAS,CAAC,OAAgC;IACjD,IAAI,OAAO,CAAC,iBAAiB,CAAC;QAAE,OAAO,aAAa,CAAC;IACrD,IAAI,OAAO,CAAC,mBAAmB,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1E,IAAI,OAAO,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,OAAO,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"auto-submit.js","sourceRoot":"","sources":["../../src/commands/auto-submit.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,9 @@
1
- export declare function daemonCommand(): Promise<void>;
1
+ interface DaemonOptions {
2
+ profile?: string;
3
+ interval?: string | number;
4
+ once?: boolean;
5
+ watch?: boolean;
6
+ }
7
+ export declare function daemonCommand(opts?: DaemonOptions): Promise<void>;
8
+ export {};
2
9
  //# sourceMappingURL=daemon.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/commands/daemon.ts"],"names":[],"mappings":"AA2EA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAoDnD"}
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/commands/daemon.ts"],"names":[],"mappings":"AAwBA,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA+CD,wBAAsB,aAAa,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoD3E"}
@@ -1,34 +1,35 @@
1
1
  /**
2
- * trace daemon — watches ~/.claude and ~/.codex session dirs and auto-submits on change.
3
- * Keeps a state file so already-submitted unchanged files are skipped on restart.
2
+ * tracemp daemon — scans local session dirs and auto-submits new work.
4
3
  *
5
- * State: ~/.config/tracemarketplace/daemon-state.json
6
- * { [filePath]: { mtime: number, size: number } }
4
+ * Default mode polls on an interval, which makes it cron-friendly and simpler
5
+ * to reason about than a long-lived filesystem watcher. `--once` runs a single
6
+ * pass and exits. `--watch` preserves the old live-watch behavior.
7
7
  *
8
- * On startup: backfills any files newer than last run.
9
- * While running: submits files 5s after they stop changing (debounce in watchDirs).
10
- * Server handles dedup/supersession — daemon just fires on change.
8
+ * State: ~/.config/tracemarketplace/daemon-state(.<profile>).json
9
+ * { [filePath]: { mtime: number, size: number } }
11
10
  */
12
11
  import { readFileSync, writeFileSync, mkdirSync, statSync, existsSync } from "fs";
13
12
  import { homedir } from "os";
14
13
  import { join } from "path";
15
14
  import chalk from "chalk";
16
- import { loadConfig } from "../config.js";
15
+ import { getConfigDir, getDaemonStatePath, loadConfig, resolveProfile } from "../config.js";
17
16
  import { findFiles, watchDirs } from "../sessions.js";
18
- import { submitFile } from "../submitter.js";
19
17
  import { log } from "./auto-submit.js";
20
- const STATE_PATH = join(homedir(), ".config", "tracemarketplace", "daemon-state.json");
21
- function loadState() {
18
+ import { loginCommandForProfile } from "../constants.js";
19
+ import { buildFileSessionSource, flushTrackedSessions } from "../flush.js";
20
+ const DEFAULT_INTERVAL_SECONDS = 60;
21
+ const BACKFILL_LOOKBACK_DAYS = 7;
22
+ function loadState(profile) {
22
23
  try {
23
- return JSON.parse(readFileSync(STATE_PATH, "utf-8"));
24
+ return JSON.parse(readFileSync(getDaemonStatePath(profile), "utf-8"));
24
25
  }
25
26
  catch {
26
27
  return {};
27
28
  }
28
29
  }
29
- function saveState(state) {
30
- mkdirSync(join(homedir(), ".config", "tracemarketplace"), { recursive: true });
31
- writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
30
+ function saveState(state, profile) {
31
+ mkdirSync(getConfigDir(), { recursive: true });
32
+ writeFileSync(getDaemonStatePath(profile), JSON.stringify(state, null, 2) + "\n");
32
33
  }
33
34
  function hasChanged(filePath, state) {
34
35
  try {
@@ -51,32 +52,19 @@ function recordFile(filePath, state) {
51
52
  return state;
52
53
  }
53
54
  }
54
- async function processFile(tool, filePath, state) {
55
- const config = loadConfig();
56
- if (!config)
57
- return state;
58
- const result = await submitFile(tool, filePath, config);
55
+ async function processFile(tool, filePath, state, config) {
56
+ const result = await flushTrackedSessions(config, [buildFileSessionSource(tool, filePath)], { includeIdleTracked: true });
59
57
  const updated = recordFile(filePath, state);
60
- if (result.error && result.error !== "Empty session") {
61
- log(`daemon: ${filePath}: ${result.error}`);
62
- }
63
- else if (result.duplicate) {
64
- // Already current — no log noise
65
- }
66
- else if (result.superseded) {
67
- log(`daemon: updated ${filePath} (${result.turnCount} turns) +$${(result.payoutCents / 100).toFixed(2)}`);
68
- console.log(chalk.cyan(` ↑ updated`), chalk.gray(filePath.split("/").slice(-2).join("/")), chalk.green(`+$${(result.payoutCents / 100).toFixed(2)}`));
69
- }
70
- else if (result.accepted) {
71
- log(`daemon: accepted ${filePath} (${result.turnCount} turns) +$${(result.payoutCents / 100).toFixed(2)}`);
72
- console.log(chalk.green(` ✓ new`), chalk.gray(filePath.split("/").slice(-2).join("/")), chalk.green(`+$${(result.payoutCents / 100).toFixed(2)}`));
58
+ for (const session of result.results) {
59
+ logDaemonResult(session, config.profile);
73
60
  }
74
61
  return updated;
75
62
  }
76
- export async function daemonCommand() {
77
- const config = loadConfig();
63
+ export async function daemonCommand(opts = {}) {
64
+ const profile = resolveProfile(opts.profile);
65
+ const config = loadConfig(profile);
78
66
  if (!config) {
79
- console.error(chalk.red("Not registered. Run: trace register"));
67
+ console.error(chalk.red(`Not authenticated for profile '${profile}'. Run: ${loginCommandForProfile(profile)}`));
80
68
  process.exit(1);
81
69
  }
82
70
  const tools = [];
@@ -88,38 +76,106 @@ export async function daemonCommand() {
88
76
  console.log(chalk.yellow("No supported tools detected (Claude Code, Codex)."));
89
77
  return;
90
78
  }
91
- console.log(chalk.bold("Trace daemon starting"));
92
- console.log(chalk.gray(`Watching: ${tools.join(", ")}`));
93
- console.log(chalk.gray("Press Ctrl+C to stop\n"));
94
- let state = loadState();
95
- // Backfill: submit any files from the last 7 days that have changed since last run
96
- console.log(chalk.gray("Backfilling new/changed sessions..."));
97
- let backfilled = 0;
79
+ const intervalSeconds = parseIntervalSeconds(opts.interval);
80
+ let state = loadState(config.profile);
81
+ console.log(chalk.bold("tracemp daemon starting"));
82
+ console.log(chalk.gray(`Profile: ${config.profile}`));
83
+ console.log(chalk.gray(`Server: ${config.serverUrl}`));
84
+ console.log(chalk.gray(`Sources: ${tools.join(", ")}`));
85
+ if (opts.watch) {
86
+ console.log(chalk.gray("Mode: live watch"));
87
+ console.log(chalk.gray("Press Ctrl+C to stop\n"));
88
+ await runWatchLoop(config, tools, state);
89
+ return;
90
+ }
91
+ console.log(chalk.gray(`Mode: poll every ${intervalSeconds}s${opts.once ? " (one shot)" : ""}\n`));
92
+ state = await runScanPass(config, tools, state, { logWhenEmpty: true });
93
+ if (opts.once)
94
+ return;
95
+ let shuttingDown = false;
96
+ const stop = () => {
97
+ if (shuttingDown)
98
+ return;
99
+ shuttingDown = true;
100
+ console.log(chalk.gray("\nDaemon stopped."));
101
+ process.exit(0);
102
+ };
103
+ process.on("SIGINT", stop);
104
+ process.on("SIGTERM", stop);
105
+ while (!shuttingDown) {
106
+ await sleep(intervalSeconds * 1000);
107
+ state = await runScanPass(config, tools, state);
108
+ }
109
+ }
110
+ async function runScanPass(config, tools, state, opts = {}) {
111
+ let nextState = state;
112
+ let processed = 0;
98
113
  for (const tool of tools) {
99
- for (const filePath of findFiles(tool, 7)) {
100
- if (hasChanged(filePath, state)) {
101
- state = await processFile(tool, filePath, state);
102
- backfilled++;
103
- }
114
+ for (const filePath of findFiles(tool, BACKFILL_LOOKBACK_DAYS)) {
115
+ if (!hasChanged(filePath, nextState))
116
+ continue;
117
+ nextState = await processFile(tool, filePath, nextState, config);
118
+ processed++;
119
+ }
120
+ }
121
+ const idleResults = await flushTrackedSessions(config, [], { includeIdleTracked: true });
122
+ for (const session of idleResults.results) {
123
+ if (session.uploadedChunks > 0 || session.duplicateChunks > 0) {
124
+ logDaemonResult(session, config.profile);
104
125
  }
105
126
  }
106
- saveState(state);
107
- if (backfilled === 0)
108
- console.log(chalk.gray(" Nothing new.\n"));
109
- else
110
- console.log();
111
- // Watch for ongoing changes
127
+ saveState(nextState, config.profile);
128
+ if (opts.logWhenEmpty &&
129
+ processed === 0 &&
130
+ idleResults.uploadedChunks === 0 &&
131
+ idleResults.duplicateChunks === 0) {
132
+ console.log(chalk.gray("Nothing new.\n"));
133
+ }
134
+ return nextState;
135
+ }
136
+ async function runWatchLoop(config, tools, state) {
137
+ let nextState = await runScanPass(config, tools, state, { logWhenEmpty: true });
112
138
  const stop = watchDirs(tools, async (tool, filePath) => {
113
- if (!hasChanged(filePath, state))
139
+ if (!hasChanged(filePath, nextState))
114
140
  return;
115
- state = await processFile(tool, filePath, state);
116
- saveState(state);
141
+ nextState = await processFile(tool, filePath, nextState, config);
142
+ saveState(nextState, config.profile);
143
+ });
144
+ process.on("SIGINT", () => {
145
+ stop();
146
+ console.log(chalk.gray("\nDaemon stopped."));
147
+ process.exit(0);
148
+ });
149
+ process.on("SIGTERM", () => {
150
+ stop();
151
+ process.exit(0);
117
152
  });
118
- console.log(chalk.gray("Watching for new sessions...\n"));
119
- // Graceful shutdown
120
- process.on("SIGINT", () => { stop(); console.log(chalk.gray("\nDaemon stopped.")); process.exit(0); });
121
- process.on("SIGTERM", () => { stop(); process.exit(0); });
122
- // Keep alive
123
153
  await new Promise(() => { });
124
154
  }
155
+ function logDaemonResult(session, profile) {
156
+ if (session.error && session.error !== "Empty session") {
157
+ log(`daemon: ${session.source.label}: ${session.error}`, profile);
158
+ return;
159
+ }
160
+ if (session.uploadedChunks > 0) {
161
+ log(`daemon: accepted ${session.source.label} chunks=${session.uploadedChunks} +$${(session.payoutCents / 100).toFixed(2)}`, profile);
162
+ console.log(chalk.green(" ✓ new"), chalk.gray(session.source.label.split("/").slice(-2).join("/") || session.source.label), chalk.green(`+$${(session.payoutCents / 100).toFixed(2)}`));
163
+ return;
164
+ }
165
+ if (session.duplicateChunks > 0) {
166
+ console.log(chalk.cyan(" ↑ current"), chalk.gray(session.source.label.split("/").slice(-2).join("/") || session.source.label));
167
+ }
168
+ }
169
+ function parseIntervalSeconds(raw) {
170
+ if (raw === undefined)
171
+ return DEFAULT_INTERVAL_SECONDS;
172
+ const value = typeof raw === "number" ? raw : Number.parseInt(String(raw), 10);
173
+ if (!Number.isFinite(value) || value <= 0) {
174
+ throw new Error("Daemon interval must be a positive integer number of seconds.");
175
+ }
176
+ return value;
177
+ }
178
+ function sleep(ms) {
179
+ return new Promise((resolve) => setTimeout(resolve, ms));
180
+ }
125
181
  //# sourceMappingURL=daemon.js.map