clawck 0.1.3 → 0.4.1

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 (106) hide show
  1. package/README.md +251 -174
  2. package/dist/cli/index.js +947 -87
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/core/atp.d.ts +31 -0
  5. package/dist/core/atp.d.ts.map +1 -0
  6. package/dist/core/atp.js +96 -0
  7. package/dist/core/atp.js.map +1 -0
  8. package/dist/core/benchmarks.d.ts +20 -0
  9. package/dist/core/benchmarks.d.ts.map +1 -0
  10. package/dist/core/benchmarks.js +86 -0
  11. package/dist/core/benchmarks.js.map +1 -0
  12. package/dist/core/clawck.d.ts +39 -3
  13. package/dist/core/clawck.d.ts.map +1 -1
  14. package/dist/core/clawck.js +140 -18
  15. package/dist/core/clawck.js.map +1 -1
  16. package/dist/core/database.d.ts +16 -1
  17. package/dist/core/database.d.ts.map +1 -1
  18. package/dist/core/database.js +177 -8
  19. package/dist/core/database.js.map +1 -1
  20. package/dist/core/patterns.d.ts +7 -0
  21. package/dist/core/patterns.d.ts.map +1 -0
  22. package/dist/core/patterns.js +36 -0
  23. package/dist/core/patterns.js.map +1 -0
  24. package/dist/core/personal.d.ts +26 -0
  25. package/dist/core/personal.d.ts.map +1 -0
  26. package/dist/core/personal.js +60 -0
  27. package/dist/core/personal.js.map +1 -0
  28. package/dist/core/runtime.d.ts +17 -0
  29. package/dist/core/runtime.d.ts.map +1 -0
  30. package/dist/core/runtime.js +43 -0
  31. package/dist/core/runtime.js.map +1 -0
  32. package/dist/core/types.d.ts +93 -2
  33. package/dist/core/types.d.ts.map +1 -1
  34. package/dist/core/types.js +9 -2
  35. package/dist/core/types.js.map +1 -1
  36. package/dist/core/webhooks.d.ts +22 -0
  37. package/dist/core/webhooks.d.ts.map +1 -0
  38. package/dist/core/webhooks.js +70 -0
  39. package/dist/core/webhooks.js.map +1 -0
  40. package/dist/hooks/adapters.d.ts +8 -0
  41. package/dist/hooks/adapters.d.ts.map +1 -0
  42. package/dist/hooks/adapters.js +152 -0
  43. package/dist/hooks/adapters.js.map +1 -0
  44. package/dist/hooks/handler.d.ts +9 -0
  45. package/dist/hooks/handler.d.ts.map +1 -0
  46. package/dist/hooks/handler.js +93 -0
  47. package/dist/hooks/handler.js.map +1 -0
  48. package/dist/hooks/index.d.ts +10 -0
  49. package/dist/hooks/index.d.ts.map +1 -0
  50. package/dist/hooks/index.js +23 -0
  51. package/dist/hooks/index.js.map +1 -0
  52. package/dist/hooks/install.d.ts +16 -0
  53. package/dist/hooks/install.d.ts.map +1 -0
  54. package/dist/hooks/install.js +247 -0
  55. package/dist/hooks/install.js.map +1 -0
  56. package/dist/hooks/session.d.ts +10 -0
  57. package/dist/hooks/session.d.ts.map +1 -0
  58. package/dist/hooks/session.js +72 -0
  59. package/dist/hooks/session.js.map +1 -0
  60. package/dist/hooks/stdin.d.ts +6 -0
  61. package/dist/hooks/stdin.d.ts.map +1 -0
  62. package/dist/hooks/stdin.js +38 -0
  63. package/dist/hooks/stdin.js.map +1 -0
  64. package/dist/hooks/types.d.ts +26 -0
  65. package/dist/hooks/types.d.ts.map +1 -0
  66. package/dist/hooks/types.js +7 -0
  67. package/dist/hooks/types.js.map +1 -0
  68. package/dist/index.d.ts +10 -0
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +19 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/reports/html.d.ts +14 -0
  73. package/dist/reports/html.d.ts.map +1 -0
  74. package/dist/reports/html.js +353 -0
  75. package/dist/reports/html.js.map +1 -0
  76. package/dist/reports/pdf.d.ts +14 -0
  77. package/dist/reports/pdf.d.ts.map +1 -0
  78. package/dist/reports/pdf.js +177 -0
  79. package/dist/reports/pdf.js.map +1 -0
  80. package/dist/reports/periods.d.ts +18 -0
  81. package/dist/reports/periods.d.ts.map +1 -0
  82. package/dist/reports/periods.js +55 -0
  83. package/dist/reports/periods.js.map +1 -0
  84. package/dist/server/api.d.ts.map +1 -1
  85. package/dist/server/api.js +156 -2
  86. package/dist/server/api.js.map +1 -1
  87. package/dist/server/mcp.d.ts.map +1 -1
  88. package/dist/server/mcp.js +31 -10
  89. package/dist/server/mcp.js.map +1 -1
  90. package/docs/atp-schema.json +298 -0
  91. package/docs/atp-spec-v0.2.md +216 -0
  92. package/docs/benchmarks-sources.md +202 -0
  93. package/docs/platform-testing-guide.md +423 -0
  94. package/docs/skills/clawck-setup.md +131 -0
  95. package/docs/skills/clawck-usage.md +148 -0
  96. package/docs/snippets/claude-md.txt +33 -0
  97. package/docs/snippets/hooks-claude.json +24 -0
  98. package/docs/snippets/hooks-cline.txt +10 -0
  99. package/docs/snippets/hooks-codex.json +16 -0
  100. package/docs/snippets/hooks-cursor.json +16 -0
  101. package/docs/snippets/hooks-gemini.json +16 -0
  102. package/docs/snippets/hooks-windsurf.json +16 -0
  103. package/docs/snippets/mcp-config.json +7 -0
  104. package/docs/snippets/openclaw-agent-md.txt +18 -0
  105. package/docs/snippets/openclaw-heartbeat-md.txt +17 -0
  106. package/package.json +4 -2
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ /**
3
+ * ⏱️🦀 Clawck — Session File Management
4
+ * Persists hook session state as JSON files (not SQLite) to avoid DB lock issues.
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.saveSession = saveSession;
11
+ exports.loadSession = loadSession;
12
+ exports.clearSession = clearSession;
13
+ exports.cleanStaleSessions = cleanStaleSessions;
14
+ const fs_1 = __importDefault(require("fs"));
15
+ const path_1 = __importDefault(require("path"));
16
+ function sessionsDir(dataDir) {
17
+ return path_1.default.join(dataDir, 'hooks', 'sessions');
18
+ }
19
+ function sessionPath(dataDir, sessionId) {
20
+ // Sanitize session ID to prevent path traversal
21
+ const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, '_');
22
+ return path_1.default.join(sessionsDir(dataDir), `${safe}.json`);
23
+ }
24
+ function saveSession(dataDir, sessionId, state) {
25
+ const dir = sessionsDir(dataDir);
26
+ fs_1.default.mkdirSync(dir, { recursive: true });
27
+ fs_1.default.writeFileSync(sessionPath(dataDir, sessionId), JSON.stringify(state));
28
+ }
29
+ function loadSession(dataDir, sessionId) {
30
+ const filePath = sessionPath(dataDir, sessionId);
31
+ if (!fs_1.default.existsSync(filePath))
32
+ return null;
33
+ try {
34
+ return JSON.parse(fs_1.default.readFileSync(filePath, 'utf-8'));
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ function clearSession(dataDir, sessionId) {
41
+ const filePath = sessionPath(dataDir, sessionId);
42
+ try {
43
+ fs_1.default.unlinkSync(filePath);
44
+ }
45
+ catch {
46
+ // Already gone — fine
47
+ }
48
+ }
49
+ function cleanStaleSessions(dataDir, maxAgeMs = 86400000) {
50
+ const dir = sessionsDir(dataDir);
51
+ if (!fs_1.default.existsSync(dir))
52
+ return 0;
53
+ let cleaned = 0;
54
+ const now = Date.now();
55
+ for (const file of fs_1.default.readdirSync(dir)) {
56
+ if (!file.endsWith('.json'))
57
+ continue;
58
+ const filePath = path_1.default.join(dir, file);
59
+ try {
60
+ const stat = fs_1.default.statSync(filePath);
61
+ if (now - stat.mtimeMs > maxAgeMs) {
62
+ fs_1.default.unlinkSync(filePath);
63
+ cleaned++;
64
+ }
65
+ }
66
+ catch {
67
+ // Skip files we can't stat
68
+ }
69
+ }
70
+ return cleaned;
71
+ }
72
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/hooks/session.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAgBH,kCAIC;AAED,kCAQC;AAED,oCAOC;AAED,gDAsBC;AA7DD,4CAAoB;AACpB,gDAAwB;AAGxB,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,WAAW,CAAC,OAAe,EAAE,SAAiB;IACrD,gDAAgD;IAChD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IACvD,OAAO,cAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;AACzD,CAAC;AAED,SAAgB,WAAW,CAAC,OAAe,EAAE,SAAiB,EAAE,KAAmB;IACjF,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,YAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,YAAE,CAAC,aAAa,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,SAAgB,WAAW,CAAC,OAAe,EAAE,SAAiB;IAC5D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACjD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,YAAY,CAAC,OAAe,EAAE,SAAiB;IAC7D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAAe,EAAE,QAAQ,GAAG,QAAQ;IACrE,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAElC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,KAAK,MAAM,IAAI,IAAI,YAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACtC,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,CAAC;gBAClC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACxB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ⏱️🦀 Clawck — Stdin Reader
3
+ * Reads JSON from stdin with timeout protection.
4
+ */
5
+ export declare function readStdin(timeoutMs?: number): Promise<string>;
6
+ //# sourceMappingURL=stdin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdin.d.ts","sourceRoot":"","sources":["../../src/hooks/stdin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,SAAS,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAmC3D"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ /**
3
+ * ⏱️🦀 Clawck — Stdin Reader
4
+ * Reads JSON from stdin with timeout protection.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.readStdin = readStdin;
8
+ function readStdin(timeoutMs = 1000) {
9
+ // No piped data if running in a TTY
10
+ if (process.stdin.isTTY) {
11
+ return Promise.resolve('');
12
+ }
13
+ return new Promise((resolve) => {
14
+ const chunks = [];
15
+ let resolved = false;
16
+ const finish = () => {
17
+ if (resolved)
18
+ return;
19
+ resolved = true;
20
+ process.stdin.removeAllListeners();
21
+ resolve(Buffer.concat(chunks).toString('utf-8'));
22
+ };
23
+ const timer = setTimeout(finish, timeoutMs);
24
+ process.stdin.on('data', (chunk) => {
25
+ chunks.push(chunk);
26
+ });
27
+ process.stdin.on('end', () => {
28
+ clearTimeout(timer);
29
+ finish();
30
+ });
31
+ process.stdin.on('error', () => {
32
+ clearTimeout(timer);
33
+ finish();
34
+ });
35
+ process.stdin.resume();
36
+ });
37
+ }
38
+ //# sourceMappingURL=stdin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdin.js","sourceRoot":"","sources":["../../src/hooks/stdin.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,8BAmCC;AAnCD,SAAgB,SAAS,CAAC,SAAS,GAAG,IAAI;IACxC,oCAAoC;IACpC,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC;YACnC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAE5C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACzC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YAC3B,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAC7B,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * ⏱️🦀 Clawck — Hook Types
3
+ * Type definitions for platform hook integration.
4
+ */
5
+ export type HookEvent = 'start' | 'stop';
6
+ export type Platform = 'claude' | 'gemini' | 'cursor' | 'cline' | 'windsurf' | 'codex' | 'unknown';
7
+ export interface HookContext {
8
+ platform: Platform;
9
+ session_id: string;
10
+ task: string;
11
+ project?: string;
12
+ agent?: string;
13
+ model?: string;
14
+ cwd?: string;
15
+ tokens_in?: number;
16
+ tokens_out?: number;
17
+ tool_calls?: number;
18
+ raw: unknown;
19
+ }
20
+ export interface SessionState {
21
+ entry_id: string;
22
+ platform: Platform;
23
+ started_at: string;
24
+ session_id: string;
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/hooks/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEzC,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAEnG,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * ⏱️🦀 Clawck — Hook Types
4
+ * Type definitions for platform hook integration.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/hooks/types.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
package/dist/index.d.ts CHANGED
@@ -27,4 +27,14 @@ export { SyncManager } from './core/sync';
27
27
  export { createServer, startServer } from './server/api';
28
28
  export { startMCPServer } from './server/mcp';
29
29
  export * from './core/types';
30
+ export { estimateAgentRuntime, calculateWallClock, DEFAULT_RUNTIME_CONFIG } from './core/runtime';
31
+ export type { RuntimeEstimatorConfig } from './core/runtime';
32
+ export { INDUSTRY_BENCHMARKS, lookupBenchmark, getCategoryMedian, computeIndustryMultiplier } from './core/benchmarks';
33
+ export type { IndustryBenchmark } from './core/benchmarks';
34
+ export { compareEntry } from './core/personal';
35
+ export type { PersonalBaseline, PersonalComparisonResult } from './core/personal';
36
+ export { validateEntry, migrateV1toV2, exportATP, importATP } from './core/atp';
37
+ export type { ATPExportEnvelope, EntryComparison } from './core/atp';
38
+ export { resolvePeriod } from './reports/periods';
39
+ export type { StoredReport, ReportMetadata, ReportPeriod, ReportStyle, ReportFormat } from './core/types';
30
40
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAClG,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AACvH,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAChF,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
37
37
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
38
38
  };
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.startMCPServer = exports.startServer = exports.createServer = exports.SyncManager = exports.ClawckDB = exports.Clawck = void 0;
40
+ exports.resolvePeriod = exports.importATP = exports.exportATP = exports.migrateV1toV2 = exports.validateEntry = exports.compareEntry = exports.computeIndustryMultiplier = exports.getCategoryMedian = exports.lookupBenchmark = exports.INDUSTRY_BENCHMARKS = exports.DEFAULT_RUNTIME_CONFIG = exports.calculateWallClock = exports.estimateAgentRuntime = exports.startMCPServer = exports.startServer = exports.createServer = exports.SyncManager = exports.ClawckDB = exports.Clawck = void 0;
41
41
  var clawck_1 = require("./core/clawck");
42
42
  Object.defineProperty(exports, "Clawck", { enumerable: true, get: function () { return clawck_1.Clawck; } });
43
43
  var database_1 = require("./core/database");
@@ -50,4 +50,22 @@ Object.defineProperty(exports, "startServer", { enumerable: true, get: function
50
50
  var mcp_1 = require("./server/mcp");
51
51
  Object.defineProperty(exports, "startMCPServer", { enumerable: true, get: function () { return mcp_1.startMCPServer; } });
52
52
  __exportStar(require("./core/types"), exports);
53
+ var runtime_1 = require("./core/runtime");
54
+ Object.defineProperty(exports, "estimateAgentRuntime", { enumerable: true, get: function () { return runtime_1.estimateAgentRuntime; } });
55
+ Object.defineProperty(exports, "calculateWallClock", { enumerable: true, get: function () { return runtime_1.calculateWallClock; } });
56
+ Object.defineProperty(exports, "DEFAULT_RUNTIME_CONFIG", { enumerable: true, get: function () { return runtime_1.DEFAULT_RUNTIME_CONFIG; } });
57
+ var benchmarks_1 = require("./core/benchmarks");
58
+ Object.defineProperty(exports, "INDUSTRY_BENCHMARKS", { enumerable: true, get: function () { return benchmarks_1.INDUSTRY_BENCHMARKS; } });
59
+ Object.defineProperty(exports, "lookupBenchmark", { enumerable: true, get: function () { return benchmarks_1.lookupBenchmark; } });
60
+ Object.defineProperty(exports, "getCategoryMedian", { enumerable: true, get: function () { return benchmarks_1.getCategoryMedian; } });
61
+ Object.defineProperty(exports, "computeIndustryMultiplier", { enumerable: true, get: function () { return benchmarks_1.computeIndustryMultiplier; } });
62
+ var personal_1 = require("./core/personal");
63
+ Object.defineProperty(exports, "compareEntry", { enumerable: true, get: function () { return personal_1.compareEntry; } });
64
+ var atp_1 = require("./core/atp");
65
+ Object.defineProperty(exports, "validateEntry", { enumerable: true, get: function () { return atp_1.validateEntry; } });
66
+ Object.defineProperty(exports, "migrateV1toV2", { enumerable: true, get: function () { return atp_1.migrateV1toV2; } });
67
+ Object.defineProperty(exports, "exportATP", { enumerable: true, get: function () { return atp_1.exportATP; } });
68
+ Object.defineProperty(exports, "importATP", { enumerable: true, get: function () { return atp_1.importATP; } });
69
+ var periods_1 = require("./reports/periods");
70
+ Object.defineProperty(exports, "resolvePeriod", { enumerable: true, get: function () { return periods_1.resolvePeriod; } });
53
71
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;;;;;;;;;;;;;;;AAEH,wCAAuC;AAA9B,gGAAA,MAAM,OAAA;AACf,4CAA2C;AAAlC,oGAAA,QAAQ,OAAA;AACjB,oCAA0C;AAAjC,mGAAA,WAAW,OAAA;AACpB,oCAAyD;AAAhD,mGAAA,YAAY,OAAA;AAAE,kGAAA,WAAW,OAAA;AAClC,oCAA8C;AAArC,qGAAA,cAAc,OAAA;AACvB,+CAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;;;;;;;;;;;;;;;AAEH,wCAAuC;AAA9B,gGAAA,MAAM,OAAA;AACf,4CAA2C;AAAlC,oGAAA,QAAQ,OAAA;AACjB,oCAA0C;AAAjC,mGAAA,WAAW,OAAA;AACpB,oCAAyD;AAAhD,mGAAA,YAAY,OAAA;AAAE,kGAAA,WAAW,OAAA;AAClC,oCAA8C;AAArC,qGAAA,cAAc,OAAA;AACvB,+CAA6B;AAC7B,0CAAkG;AAAzF,+GAAA,oBAAoB,OAAA;AAAE,6GAAA,kBAAkB,OAAA;AAAE,iHAAA,sBAAsB,OAAA;AAEzE,gDAAuH;AAA9G,iHAAA,mBAAmB,OAAA;AAAE,6GAAA,eAAe,OAAA;AAAE,+GAAA,iBAAiB,OAAA;AAAE,uHAAA,yBAAyB,OAAA;AAE3F,4CAA+C;AAAtC,wGAAA,YAAY,OAAA;AAErB,kCAAgF;AAAvE,oGAAA,aAAa,OAAA;AAAE,oGAAA,aAAa,OAAA;AAAE,gGAAA,SAAS,OAAA;AAAE,gGAAA,SAAS,OAAA;AAE3D,6CAAkD;AAAzC,wGAAA,aAAa,OAAA"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * ⏱️🦀 Clawck — HTML Report Generation
3
+ * Generates interactive timesheet HTML reports.
4
+ */
5
+ import { TimesheetSummary, ClawckEntry, ReportStyle } from '../core/types';
6
+ export interface HTMLReportOptions {
7
+ title?: string;
8
+ clientName?: string;
9
+ dateRange: string;
10
+ rawEntries?: ClawckEntry[];
11
+ style?: ReportStyle;
12
+ }
13
+ export declare function generateTimesheetHTML(summary: TimesheetSummary, options: HTMLReportOptions): string;
14
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/reports/html.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3E,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,iBAAiB,GACzB,MAAM,CAoQR"}
@@ -0,0 +1,353 @@
1
+ "use strict";
2
+ /**
3
+ * ⏱️🦀 Clawck — HTML Report Generation
4
+ * Generates interactive timesheet HTML reports.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.generateTimesheetHTML = generateTimesheetHTML;
8
+ function generateTimesheetHTML(summary, options) {
9
+ const title = options.title || 'Clawck Timesheet Report';
10
+ const entries = summary.entries;
11
+ const rawEntries = options.rawEntries || [];
12
+ const style = options.style || 'full';
13
+ // Determine which sections to show based on style
14
+ const showCards = style !== 'table' && style !== 'calendar' && style !== 'visual';
15
+ const showCalendar = style === 'full' || style === 'visual' || style === 'calendar';
16
+ const showTable = style === 'full' || style === 'table';
17
+ const showGantt = style === 'full' || style === 'visual';
18
+ const showCSV = style === 'full';
19
+ const showTabs = [showCalendar, showTable, showGantt, showCSV].filter(Boolean).length > 1;
20
+ const isShort = style === 'short';
21
+ const isText = style === 'text';
22
+ // Group entries by date for calendar
23
+ const byDate = new Map();
24
+ for (const e of entries) {
25
+ const d = byDate.get(e.date) || { count: 0, hours: 0 };
26
+ d.count++;
27
+ d.hours += e.duration_minutes / 60;
28
+ byDate.set(e.date, d);
29
+ }
30
+ // Build CSV string
31
+ const csvHeader = 'Date,Agent,Client,Project,Task,Category,Duration (min),Tokens,Cost,Human Equiv Hrs,Status,Approved';
32
+ const csvRows = entries.map(e => {
33
+ const esc = (s) => `"${s.replace(/"/g, '""')}"`;
34
+ return [e.date, esc(e.agent), esc(e.client), esc(e.project), esc(e.task), e.category,
35
+ e.duration_minutes.toFixed(2), e.tokens_total, e.cost_usd.toFixed(4),
36
+ e.human_equiv_hours.toFixed(2), e.status, e.approved ? 'yes' : 'no'].join(',');
37
+ });
38
+ const csvContent = [csvHeader, ...csvRows].join('\\n');
39
+ // Calendar range
40
+ const startDate = summary.period_start.split('T')[0];
41
+ const endDate = summary.period_end.split('T')[0];
42
+ // Max hours for color scaling
43
+ const maxHours = Math.max(...[...byDate.values()].map(d => d.hours), 1);
44
+ // Build calendar HTML
45
+ const calendarDays = buildCalendarDays(startDate, endDate, byDate, maxHours);
46
+ // Build Gantt data from raw entries
47
+ const ganttHTML = buildGanttChart(rawEntries);
48
+ return `<!DOCTYPE html>
49
+ <html lang="en">
50
+ <head>
51
+ <meta charset="UTF-8">
52
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
53
+ <title>${escapeHtml(title)}</title>
54
+ <link rel="preconnect" href="https://fonts.googleapis.com">
55
+ <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
56
+ <style>
57
+ :root {
58
+ --bg: #0f1117;
59
+ --surface: #1a1d27;
60
+ --surface2: #242836;
61
+ --border: #2d3348;
62
+ --text: #e4e6ed;
63
+ --text-dim: #8b8fa3;
64
+ --accent: #6c63ff;
65
+ --green: #4ade80;
66
+ --red: #f87171;
67
+ --orange: #fb923c;
68
+ --blue: #60a5fa;
69
+ --cyan: #22d3ee;
70
+ --purple: #a78bfa;
71
+ --pink: #f472b6;
72
+ }
73
+ * { margin: 0; padding: 0; box-sizing: border-box; }
74
+ body { background: var(--bg); color: var(--text); font-family: 'DM Sans', sans-serif; padding: 2rem; }
75
+ .mono { font-family: 'JetBrains Mono', monospace; }
76
+ h1 { font-size: 1.8rem; font-weight: 700; margin-bottom: 0.25rem; }
77
+ .subtitle { color: var(--text-dim); font-size: 0.95rem; margin-bottom: 0.5rem; }
78
+ .meta { color: var(--text-dim); font-size: 0.8rem; margin-bottom: 1.5rem; }
79
+
80
+ /* Summary Cards */
81
+ .cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
82
+ .card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 1.2rem; }
83
+ .card-label { font-size: 0.75rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.3rem; }
84
+ .card-value { font-family: 'JetBrains Mono', monospace; font-size: 1.4rem; font-weight: 600; }
85
+ .card-value.green { color: var(--green); }
86
+ .card-value.blue { color: var(--blue); }
87
+ .card-value.accent { color: var(--accent); }
88
+ .card-value.orange { color: var(--orange); }
89
+
90
+ /* Tabs */
91
+ .tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin-bottom: 1.5rem; }
92
+ .tab { padding: 0.7rem 1.5rem; cursor: pointer; color: var(--text-dim); font-size: 0.9rem; font-weight: 500; border-bottom: 2px solid transparent; transition: all 0.2s; }
93
+ .tab:hover { color: var(--text); }
94
+ .tab.active { color: var(--accent); border-bottom-color: var(--accent); }
95
+ .tab-content { display: none; }
96
+ .tab-content.active { display: block; }
97
+
98
+ /* Calendar */
99
+ .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
100
+ .cal-header { font-size: 0.7rem; color: var(--text-dim); text-align: center; padding: 4px; font-weight: 600; }
101
+ .cal-day { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 6px; min-height: 60px; font-size: 0.75rem; }
102
+ .cal-day.empty { background: transparent; border-color: transparent; }
103
+ .cal-day .day-num { font-weight: 600; margin-bottom: 2px; }
104
+ .cal-day .day-info { font-family: 'JetBrains Mono', monospace; font-size: 0.65rem; color: var(--text-dim); }
105
+ .cal-day.has-entries { border-color: var(--accent); }
106
+
107
+ /* Table */
108
+ .data-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
109
+ .data-table th { background: var(--surface2); padding: 8px 10px; text-align: left; font-weight: 600; font-size: 0.75rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.03em; cursor: pointer; user-select: none; border-bottom: 1px solid var(--border); white-space: nowrap; }
110
+ .data-table th:hover { color: var(--text); }
111
+ .data-table td { padding: 7px 10px; border-bottom: 1px solid var(--border); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; }
112
+ .data-table tr:hover td { background: var(--surface); }
113
+ .data-table .mono { font-family: 'JetBrains Mono', monospace; font-size: 0.78rem; }
114
+ .status-completed { color: var(--green); }
115
+ .status-running { color: var(--orange); }
116
+ .status-failed { color: var(--red); }
117
+
118
+ /* Gantt */
119
+ .gantt-container { overflow-x: auto; }
120
+ .gantt-row { display: flex; align-items: center; margin-bottom: 4px; min-height: 28px; }
121
+ .gantt-label { width: 120px; flex-shrink: 0; font-size: 0.75rem; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
122
+ .gantt-bars { flex: 1; position: relative; height: 22px; background: var(--surface); border-radius: 4px; }
123
+ .gantt-bar { position: absolute; height: 18px; top: 2px; border-radius: 3px; opacity: 0.85; min-width: 3px; }
124
+ .gantt-bar[title]:hover { opacity: 1; }
125
+ .gantt-axis { display: flex; margin-left: 120px; margin-bottom: 8px; }
126
+ .gantt-tick { flex: 1; font-size: 0.65rem; color: var(--text-dim); font-family: 'JetBrains Mono', monospace; }
127
+
128
+ /* CSV */
129
+ .csv-container { position: relative; }
130
+ .csv-pre { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 1rem; overflow-x: auto; font-family: 'JetBrains Mono', monospace; font-size: 0.75rem; line-height: 1.6; white-space: pre; max-height: 500px; }
131
+ .copy-btn { position: absolute; top: 8px; right: 8px; background: var(--accent); color: #fff; border: none; border-radius: 6px; padding: 6px 14px; cursor: pointer; font-size: 0.78rem; font-weight: 500; }
132
+ .copy-btn:hover { opacity: 0.9; }
133
+
134
+ /* Category colors */
135
+ .cat-research { background: var(--blue); }
136
+ .cat-content { background: var(--purple); }
137
+ .cat-code { background: var(--green); }
138
+ .cat-data_entry { background: var(--cyan); }
139
+ .cat-design { background: var(--pink); }
140
+ .cat-communication { background: var(--orange); }
141
+ .cat-analysis { background: #818cf8; }
142
+ .cat-testing { background: #fbbf24; }
143
+ .cat-planning { background: #34d399; }
144
+ .cat-other { background: var(--text-dim); }
145
+ </style>
146
+ </head>
147
+ <body>
148
+ <h1>${escapeHtml(title)}</h1>
149
+ ${options.clientName ? `<div class="subtitle">Client: ${escapeHtml(options.clientName)}</div>` : ''}
150
+ <div class="subtitle">Period: ${escapeHtml(options.dateRange)}</div>
151
+ <div class="meta">Generated ${new Date().toISOString()}</div>
152
+
153
+ ${isText ? `<pre class="csv-pre" style="margin-top:1.5rem">${escapeHtml(buildTextReport(summary))}</pre>` : `
154
+ ${showCards ? `<div class="cards">
155
+ <div class="card"><div class="card-label">Wall-Clock Hours</div><div class="card-value mono blue">${summary.total_agent_hours.toFixed(2)}</div></div>
156
+ <div class="card"><div class="card-label">Agent Runtime (est.)</div><div class="card-value mono" style="color:#22d3ee">${formatMins(entries.reduce((s, e) => s + (e.agent_runtime_minutes || 0), 0))}</div></div>
157
+ <div class="card"><div class="card-label">Human Equiv</div><div class="card-value mono accent">${summary.total_human_equiv_hours.toFixed(2)} hrs</div></div>
158
+ <div class="card"><div class="card-label">Cost</div><div class="card-value mono orange">$${summary.total_cost_usd.toFixed(2)}</div></div>
159
+ <div class="card"><div class="card-label">Savings</div><div class="card-value mono green">$${summary.total_savings_usd.toFixed(0)}</div></div>
160
+ <div class="card"><div class="card-label">Entries</div><div class="card-value mono">${summary.total_entries}</div></div>
161
+ <div class="card"><div class="card-label">Tokens</div><div class="card-value mono">${summary.total_tokens.toLocaleString()}</div></div>
162
+ </div>` : ''}
163
+
164
+ ${isShort ? '' : `
165
+ ${showTabs ? `<div class="tabs">
166
+ ${showCalendar ? `<div class="tab${showCalendar && !showTable ? ' active' : (showCalendar ? ' active' : '')}" data-tab="calendar">Calendar</div>` : ''}
167
+ ${showTable ? `<div class="tab${!showCalendar ? ' active' : ''}" data-tab="table">Table</div>` : ''}
168
+ ${showGantt ? `<div class="tab" data-tab="gantt">Gantt</div>` : ''}
169
+ ${showCSV ? `<div class="tab" data-tab="csv">CSV</div>` : ''}
170
+ </div>` : ''}
171
+
172
+ ${showCalendar ? `<div id="tab-calendar" class="tab-content${showCalendar ? ' active' : ''}">
173
+ <div class="calendar-grid">
174
+ <div class="cal-header">Sun</div><div class="cal-header">Mon</div><div class="cal-header">Tue</div>
175
+ <div class="cal-header">Wed</div><div class="cal-header">Thu</div><div class="cal-header">Fri</div><div class="cal-header">Sat</div>
176
+ ${calendarDays}
177
+ </div>
178
+ </div>` : ''}
179
+
180
+ ${showTable ? `<div id="tab-table" class="tab-content${!showCalendar ? ' active' : ''}">
181
+ <table class="data-table" id="entries-table">
182
+ <thead>
183
+ <tr>
184
+ <th data-col="0">Date</th><th data-col="1">Agent</th><th data-col="2">Client</th>
185
+ <th data-col="3">Project</th><th data-col="4">Task</th><th data-col="5">Category</th>
186
+ <th data-col="6">Wall Clock</th><th data-col="7">Agent Runtime</th><th data-col="8">Tokens</th><th data-col="9">Cost</th>
187
+ <th data-col="10">Human Equiv</th><th data-col="11">Status</th><th data-col="12">Approved</th>
188
+ </tr>
189
+ </thead>
190
+ <tbody>
191
+ ${entries.map(e => `<tr>
192
+ <td class="mono">${e.date}</td><td>${escapeHtml(e.agent)}</td><td>${escapeHtml(e.client)}</td>
193
+ <td>${escapeHtml(e.project)}</td><td title="${escapeHtml(e.task)}">${escapeHtml(e.task)}</td><td>${e.category}</td>
194
+ <td class="mono">${formatMins(e.duration_minutes)}</td><td class="mono">${e.agent_runtime_minutes != null ? formatMins(e.agent_runtime_minutes) : '-'}</td><td class="mono">${e.tokens_total.toLocaleString()}</td>
195
+ <td class="mono">$${e.cost_usd.toFixed(4)}</td><td class="mono">${e.human_equiv_hours.toFixed(2)}h</td>
196
+ <td class="status-${e.status}">${e.status}</td><td>${e.approved ? 'Yes' : '-'}</td>
197
+ </tr>`).join('\n')}
198
+ </tbody>
199
+ </table>
200
+ </div>` : ''}
201
+
202
+ ${showGantt ? `<div id="tab-gantt" class="tab-content">
203
+ ${ganttHTML}
204
+ </div>` : ''}
205
+
206
+ ${showCSV ? `<div id="tab-csv" class="tab-content">
207
+ <div class="csv-container">
208
+ <button class="copy-btn" onclick="copyCSV()">Copy</button>
209
+ <pre class="csv-pre" id="csv-data">${escapeHtml([csvHeader, ...csvRows].join('\n'))}</pre>
210
+ </div>
211
+ </div>` : ''}
212
+ `}
213
+ `}
214
+
215
+ <script>
216
+ // Tab switching
217
+ document.querySelectorAll('.tab').forEach(tab => {
218
+ tab.addEventListener('click', () => {
219
+ document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
220
+ document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
221
+ tab.classList.add('active');
222
+ document.getElementById('tab-' + tab.dataset.tab).classList.add('active');
223
+ });
224
+ });
225
+
226
+ // Table sorting
227
+ document.querySelectorAll('#entries-table th').forEach(th => {
228
+ let asc = true;
229
+ th.addEventListener('click', () => {
230
+ const col = parseInt(th.dataset.col);
231
+ const tbody = document.querySelector('#entries-table tbody');
232
+ const rows = Array.from(tbody.querySelectorAll('tr'));
233
+ rows.sort((a, b) => {
234
+ const av = a.children[col].textContent.trim();
235
+ const bv = b.children[col].textContent.trim();
236
+ const an = parseFloat(av.replace(/[^0-9.-]/g, ''));
237
+ const bn = parseFloat(bv.replace(/[^0-9.-]/g, ''));
238
+ if (!isNaN(an) && !isNaN(bn)) return asc ? an - bn : bn - an;
239
+ return asc ? av.localeCompare(bv) : bv.localeCompare(av);
240
+ });
241
+ rows.forEach(r => tbody.appendChild(r));
242
+ asc = !asc;
243
+ });
244
+ });
245
+
246
+ // Copy CSV
247
+ function copyCSV() {
248
+ const el = document.getElementById('csv-data');
249
+ if (!el) return;
250
+ const text = el.textContent;
251
+ navigator.clipboard.writeText(text).then(() => {
252
+ const btn = document.querySelector('.copy-btn');
253
+ btn.textContent = 'Copied!';
254
+ setTimeout(() => btn.textContent = 'Copy', 2000);
255
+ });
256
+ }
257
+ </script>
258
+ </body>
259
+ </html>`;
260
+ }
261
+ function buildTextReport(summary) {
262
+ const totalAgentRuntimeMin = summary.entries.reduce((s, e) => s + (e.agent_runtime_minutes || 0), 0);
263
+ const lines = [
264
+ `Clawck Timesheet Report`,
265
+ `${'─'.repeat(50)}`,
266
+ `Wall-clock hours: ${summary.total_agent_hours.toFixed(2)} hrs`,
267
+ totalAgentRuntimeMin > 0 ? `Agent runtime: ${formatMins(totalAgentRuntimeMin)} (estimated)` : null,
268
+ `Human equiv: ${summary.total_human_equiv_hours.toFixed(2)} hrs`,
269
+ `Agent cost: $${summary.total_cost_usd.toFixed(2)}`,
270
+ `Est. savings: $${summary.total_savings_usd.toFixed(0)}`,
271
+ `Total entries: ${summary.total_entries}`,
272
+ `Total tokens: ${summary.total_tokens.toLocaleString()}`,
273
+ ].filter(Boolean);
274
+ return lines.join('\n');
275
+ }
276
+ function escapeHtml(str) {
277
+ return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
278
+ }
279
+ function formatMins(mins) {
280
+ if (mins < 1)
281
+ return `${Math.round(mins * 60)}s`;
282
+ if (mins < 60)
283
+ return `${Math.round(mins)}m`;
284
+ const h = Math.floor(mins / 60);
285
+ const m = Math.round(mins % 60);
286
+ return m > 0 ? `${h}h ${m}m` : `${h}h`;
287
+ }
288
+ function buildCalendarDays(startStr, endStr, byDate, maxHours) {
289
+ const start = new Date(startStr + 'T00:00:00');
290
+ const end = new Date(endStr + 'T00:00:00');
291
+ const days = [];
292
+ // Pad to start of week (Sunday)
293
+ const firstDay = new Date(start);
294
+ firstDay.setDate(firstDay.getDate() - firstDay.getDay());
295
+ const current = new Date(firstDay);
296
+ while (current <= end || current.getDay() !== 0) {
297
+ const dateStr = current.toISOString().split('T')[0];
298
+ const inRange = current >= start && current <= end;
299
+ const data = byDate.get(dateStr);
300
+ if (!inRange && !data) {
301
+ days.push(`<div class="cal-day empty"></div>`);
302
+ }
303
+ else {
304
+ const hasEntries = data && data.count > 0;
305
+ const intensity = hasEntries ? Math.min(data.hours / maxHours, 1) : 0;
306
+ const bgStyle = hasEntries ? `background: rgba(108,99,255,${0.1 + intensity * 0.5})` : '';
307
+ days.push(`<div class="cal-day${hasEntries ? ' has-entries' : ''}" style="${bgStyle}">
308
+ <div class="day-num">${current.getDate()}</div>
309
+ ${hasEntries ? `<div class="day-info">${data.count} entries<br>${data.hours.toFixed(1)}h</div>` : ''}
310
+ </div>`);
311
+ }
312
+ current.setDate(current.getDate() + 1);
313
+ if (current > end && current.getDay() === 0)
314
+ break;
315
+ }
316
+ return days.join('\n');
317
+ }
318
+ function buildGanttChart(rawEntries) {
319
+ if (rawEntries.length === 0)
320
+ return '<p style="color:var(--text-dim)">No entries to display.</p>';
321
+ // Group by date
322
+ const byDate = new Map();
323
+ for (const e of rawEntries) {
324
+ const date = e.start.split('T')[0];
325
+ const arr = byDate.get(date) || [];
326
+ arr.push(e);
327
+ byDate.set(date, arr);
328
+ }
329
+ const categoryColors = {
330
+ research: 'cat-research', content: 'cat-content', code: 'cat-code',
331
+ data_entry: 'cat-data_entry', design: 'cat-design', communication: 'cat-communication',
332
+ analysis: 'cat-analysis', testing: 'cat-testing', planning: 'cat-planning', other: 'cat-other',
333
+ };
334
+ const sortedDates = [...byDate.keys()].sort();
335
+ const rows = [];
336
+ // Axis
337
+ rows.push(`<div class="gantt-axis">${Array.from({ length: 24 }, (_, i) => `<div class="gantt-tick">${String(i).padStart(2, '0')}</div>`).join('')}</div>`);
338
+ for (const date of sortedDates.slice(-14)) { // Limit to last 14 days
339
+ const dateEntries = byDate.get(date);
340
+ const bars = dateEntries.map(e => {
341
+ const startHour = new Date(e.start).getHours() + new Date(e.start).getMinutes() / 60;
342
+ const endTime = e.end ? new Date(e.end) : new Date();
343
+ const durHours = (endTime.getTime() - new Date(e.start).getTime()) / 3600000;
344
+ const left = (startHour / 24) * 100;
345
+ const width = Math.max((durHours / 24) * 100, 0.5);
346
+ const cls = categoryColors[e.category] || 'cat-other';
347
+ return `<div class="gantt-bar ${cls}" style="left:${left}%;width:${width}%" title="${escapeHtml(e.task)} (${e.category}, ${formatMins(durHours * 60)})"></div>`;
348
+ }).join('');
349
+ rows.push(`<div class="gantt-row"><div class="gantt-label">${date}</div><div class="gantt-bars">${bars}</div></div>`);
350
+ }
351
+ return `<div class="gantt-container">${rows.join('\n')}</div>`;
352
+ }
353
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/reports/html.ts"],"names":[],"mappings":"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"}