@jamesaphoenix/tx-api-server 0.1.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 (109) hide show
  1. package/dist/__tests__/api.test.d.ts +7 -0
  2. package/dist/__tests__/api.test.d.ts.map +1 -0
  3. package/dist/__tests__/api.test.js +184 -0
  4. package/dist/__tests__/api.test.js.map +1 -0
  5. package/dist/__tests__/auth.test.d.ts +7 -0
  6. package/dist/__tests__/auth.test.d.ts.map +1 -0
  7. package/dist/__tests__/auth.test.js +174 -0
  8. package/dist/__tests__/auth.test.js.map +1 -0
  9. package/dist/__tests__/body-limit.test.d.ts +7 -0
  10. package/dist/__tests__/body-limit.test.d.ts.map +1 -0
  11. package/dist/__tests__/body-limit.test.js +60 -0
  12. package/dist/__tests__/body-limit.test.js.map +1 -0
  13. package/dist/__tests__/health.test.d.ts.map +1 -0
  14. package/dist/__tests__/health.test.js.map +1 -0
  15. package/dist/__tests__/log-reader.test.d.ts +8 -0
  16. package/dist/__tests__/log-reader.test.d.ts.map +1 -0
  17. package/dist/__tests__/log-reader.test.js +55 -0
  18. package/dist/__tests__/log-reader.test.js.map +1 -0
  19. package/dist/__tests__/rate-limit.test.d.ts.map +1 -0
  20. package/dist/__tests__/rate-limit.test.js.map +1 -0
  21. package/dist/__tests__/server-lib.test.d.ts +10 -0
  22. package/dist/__tests__/server-lib.test.d.ts.map +1 -0
  23. package/dist/__tests__/server-lib.test.js +145 -0
  24. package/dist/__tests__/server-lib.test.js.map +1 -0
  25. package/dist/api.d.ts +1616 -0
  26. package/dist/api.d.ts.map +1 -0
  27. package/dist/api.js +566 -0
  28. package/dist/api.js.map +1 -0
  29. package/dist/index.d.ts +16 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +19 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/middleware/auth.d.ts +31 -0
  34. package/dist/middleware/auth.d.ts.map +1 -0
  35. package/dist/middleware/auth.js +65 -0
  36. package/dist/middleware/auth.js.map +1 -0
  37. package/dist/middleware/body-limit.d.ts +33 -0
  38. package/dist/middleware/body-limit.d.ts.map +1 -0
  39. package/dist/middleware/body-limit.js +50 -0
  40. package/dist/middleware/body-limit.js.map +1 -0
  41. package/dist/middleware/cors.d.ts +15 -0
  42. package/dist/middleware/cors.d.ts.map +1 -0
  43. package/dist/middleware/cors.js +31 -0
  44. package/dist/middleware/cors.js.map +1 -0
  45. package/dist/middleware/error.d.ts +26 -0
  46. package/dist/middleware/error.d.ts.map +1 -0
  47. package/dist/middleware/error.js +84 -0
  48. package/dist/middleware/error.js.map +1 -0
  49. package/dist/middleware/rate-limit.d.ts +59 -0
  50. package/dist/middleware/rate-limit.d.ts.map +1 -0
  51. package/dist/middleware/rate-limit.js +296 -0
  52. package/dist/middleware/rate-limit.js.map +1 -0
  53. package/dist/routes/attempts.d.ts +9 -0
  54. package/dist/routes/attempts.d.ts.map +1 -0
  55. package/dist/routes/attempts.js +26 -0
  56. package/dist/routes/attempts.js.map +1 -0
  57. package/dist/routes/claims.d.ts +9 -0
  58. package/dist/routes/claims.d.ts.map +1 -0
  59. package/dist/routes/claims.js +42 -0
  60. package/dist/routes/claims.js.map +1 -0
  61. package/dist/routes/docs.d.ts +9 -0
  62. package/dist/routes/docs.d.ts.map +1 -0
  63. package/dist/routes/docs.js +80 -0
  64. package/dist/routes/docs.js.map +1 -0
  65. package/dist/routes/health.d.ts +8 -0
  66. package/dist/routes/health.d.ts.map +1 -0
  67. package/dist/routes/health.js +101 -0
  68. package/dist/routes/health.js.map +1 -0
  69. package/dist/routes/invariants.d.ts +9 -0
  70. package/dist/routes/invariants.d.ts.map +1 -0
  71. package/dist/routes/invariants.js +64 -0
  72. package/dist/routes/invariants.js.map +1 -0
  73. package/dist/routes/learnings.d.ts +8 -0
  74. package/dist/routes/learnings.d.ts.map +1 -0
  75. package/dist/routes/learnings.js +93 -0
  76. package/dist/routes/learnings.js.map +1 -0
  77. package/dist/routes/runs.d.ts +8 -0
  78. package/dist/routes/runs.d.ts.map +1 -0
  79. package/dist/routes/runs.js +195 -0
  80. package/dist/routes/runs.js.map +1 -0
  81. package/dist/routes/sync.d.ts +8 -0
  82. package/dist/routes/sync.d.ts.map +1 -0
  83. package/dist/routes/sync.js +67 -0
  84. package/dist/routes/sync.js.map +1 -0
  85. package/dist/routes/tasks.d.ts +9 -0
  86. package/dist/routes/tasks.d.ts.map +1 -0
  87. package/dist/routes/tasks.js +167 -0
  88. package/dist/routes/tasks.js.map +1 -0
  89. package/dist/runtime.d.ts +10 -0
  90. package/dist/runtime.d.ts.map +1 -0
  91. package/dist/runtime.js +10 -0
  92. package/dist/runtime.js.map +1 -0
  93. package/dist/server-lib.d.ts +26 -0
  94. package/dist/server-lib.d.ts.map +1 -0
  95. package/dist/server-lib.js +123 -0
  96. package/dist/server-lib.js.map +1 -0
  97. package/dist/server.d.ts +14 -0
  98. package/dist/server.d.ts.map +1 -0
  99. package/dist/server.js +15 -0
  100. package/dist/server.js.map +1 -0
  101. package/dist/utils/log-reader.d.ts +26 -0
  102. package/dist/utils/log-reader.d.ts.map +1 -0
  103. package/dist/utils/log-reader.js +52 -0
  104. package/dist/utils/log-reader.js.map +1 -0
  105. package/dist/utils/transcript-parser.d.ts +40 -0
  106. package/dist/utils/transcript-parser.d.ts.map +1 -0
  107. package/dist/utils/transcript-parser.js +216 -0
  108. package/dist/utils/transcript-parser.js.map +1 -0
  109. package/package.json +75 -0
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Transcript Parser for Claude JSONL files
3
+ *
4
+ * Parses Claude's conversation transcript files (~/.claude/projects/.../session.jsonl)
5
+ * and converts them to a format suitable for display in the dashboard.
6
+ */
7
+ import { Effect } from "effect";
8
+ import { readFile, readdir, stat } from "node:fs/promises";
9
+ import { existsSync } from "node:fs";
10
+ import { join, resolve, sep } from "node:path";
11
+ /**
12
+ * Validate that a transcript path is under an allowed directory.
13
+ * Prevents arbitrary file reads via path traversal.
14
+ *
15
+ * Allowed directories: ~/.claude/ and any .tx/ directory.
16
+ */
17
+ export const isAllowedTranscriptPath = (filePath) => {
18
+ const homeDir = process.env.HOME || "";
19
+ // Always check .tx/ paths first (works even when HOME is unset, e.g., containers)
20
+ const resolved = homeDir
21
+ ? resolve(filePath.replace(/^~/, homeDir))
22
+ : resolve(filePath);
23
+ const txDir = resolve(".tx");
24
+ if (resolved.startsWith(txDir + sep))
25
+ return true;
26
+ // Check ~/.claude/ paths (requires HOME to be set)
27
+ if (!homeDir)
28
+ return false;
29
+ const claudeDir = resolve(join(homeDir, ".claude"));
30
+ if (resolved.startsWith(claudeDir + sep))
31
+ return true;
32
+ return false;
33
+ };
34
+ /**
35
+ * Parse a Claude transcript JSONL file and extract conversation messages
36
+ */
37
+ export const parseTranscript = (path) => Effect.gen(function* () {
38
+ // Security: validate path is under allowed directories before any file I/O
39
+ if (!isAllowedTranscriptPath(path)) {
40
+ return yield* Effect.fail(new Error("Path traversal attempt: transcript path must be under ~/.claude/ or .tx/"));
41
+ }
42
+ return yield* Effect.tryPromise({
43
+ try: async () => {
44
+ // Expand ~ to home directory
45
+ const expandedPath = path.replace(/^~/, process.env.HOME || "");
46
+ if (!existsSync(expandedPath)) {
47
+ return [];
48
+ }
49
+ const content = await readFile(expandedPath, "utf-8");
50
+ const lines = content.split("\n").filter((line) => line.trim());
51
+ const messages = [];
52
+ const seenUuids = new Set();
53
+ // Map tool_use_id -> tool_name so we can label tool results
54
+ const toolNameById = new Map();
55
+ for (const line of lines) {
56
+ try {
57
+ const entry = JSON.parse(line);
58
+ // Handle assistant messages first to build tool name map
59
+ if (entry.type === "assistant") {
60
+ const assistantEntry = entry;
61
+ // Avoid duplicates from the same uuid
62
+ if (seenUuids.has(assistantEntry.uuid))
63
+ continue;
64
+ seenUuids.add(assistantEntry.uuid);
65
+ const contentItems = assistantEntry.message.content;
66
+ if (Array.isArray(contentItems)) {
67
+ for (const item of contentItems) {
68
+ if (item.type === "thinking") {
69
+ // Skip thinking blocks for cleaner display
70
+ }
71
+ else if (item.type === "text") {
72
+ // Skip empty text blocks (e.g., assistant messages with only thinking content)
73
+ if (!item.text || item.text.trim() === "")
74
+ continue;
75
+ messages.push({
76
+ role: "assistant",
77
+ content: item.text,
78
+ type: "text",
79
+ timestamp: assistantEntry.timestamp,
80
+ });
81
+ }
82
+ else if (item.type === "tool_use") {
83
+ // Track tool name by ID for correlating with results
84
+ toolNameById.set(item.id, item.name);
85
+ messages.push({
86
+ role: "assistant",
87
+ content: item.input,
88
+ type: "tool_use",
89
+ tool_name: item.name,
90
+ timestamp: assistantEntry.timestamp,
91
+ });
92
+ }
93
+ }
94
+ }
95
+ }
96
+ // Handle user messages (tool results come as user messages)
97
+ if (entry.type === "user") {
98
+ const userEntry = entry;
99
+ // Avoid duplicates from the same uuid
100
+ if (seenUuids.has(userEntry.uuid))
101
+ continue;
102
+ seenUuids.add(userEntry.uuid);
103
+ const content = userEntry.message.content;
104
+ if (typeof content === "string") {
105
+ messages.push({
106
+ role: "user",
107
+ content: content,
108
+ timestamp: userEntry.timestamp,
109
+ });
110
+ }
111
+ else if (Array.isArray(content)) {
112
+ // Handle tool results in user messages
113
+ for (const item of content) {
114
+ if (item.type === "tool_result") {
115
+ // Look up the tool name from the corresponding tool_use
116
+ const toolName = item.tool_use_id
117
+ ? toolNameById.get(item.tool_use_id)
118
+ : undefined;
119
+ // tool_result content can be a string, an array of content blocks, or undefined
120
+ // Claude API sends arrays like [{type: "text", text: "..."}] for multi-block results
121
+ let resultContent = "";
122
+ const rawContent = item.content;
123
+ if (typeof rawContent === "string") {
124
+ resultContent = rawContent;
125
+ }
126
+ else if (Array.isArray(rawContent)) {
127
+ // Extract text from content blocks: [{type: "text", text: "..."}]
128
+ resultContent = rawContent
129
+ .filter((block) => block.type === "text")
130
+ .map((block) => block.text ?? "")
131
+ .join("\n");
132
+ }
133
+ messages.push({
134
+ role: "user",
135
+ content: resultContent,
136
+ type: "tool_result",
137
+ tool_name: toolName,
138
+ timestamp: userEntry.timestamp,
139
+ });
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ catch {
146
+ // Skip malformed lines
147
+ }
148
+ }
149
+ return messages;
150
+ },
151
+ catch: (error) => new Error(`Failed to parse transcript: ${String(error)}`),
152
+ });
153
+ });
154
+ /**
155
+ * Check if a transcript file exists
156
+ */
157
+ export const transcriptExists = (path) => {
158
+ const expandedPath = path.replace(/^~/, process.env.HOME || "");
159
+ return existsSync(expandedPath);
160
+ };
161
+ /**
162
+ * Find a transcript file that matches a run's time window.
163
+ * Looks in ~/.claude/projects/<escaped-cwd>/ for JSONL files modified during the run.
164
+ *
165
+ * @param cwd - The working directory (used to find Claude's project directory)
166
+ * @param startedAt - When the run started
167
+ * @param endedAt - When the run ended (optional, uses now if not set)
168
+ * @returns Path to the matching transcript, or null if none found
169
+ */
170
+ export const findMatchingTranscript = async (cwd, startedAt, endedAt) => {
171
+ const homeDir = process.env.HOME || "";
172
+ if (!homeDir)
173
+ return null;
174
+ // Convert cwd to Claude's escaped directory format
175
+ // Claude CLI replaces ALL non-alphanumeric chars with dashes:
176
+ // /Users/foo/my_project -> -Users-foo-my-project
177
+ const escapedCwd = cwd.replace(/[^a-zA-Z0-9]/g, "-");
178
+ const claudeProjectDir = join(homeDir, ".claude", "projects", escapedCwd);
179
+ if (!existsSync(claudeProjectDir)) {
180
+ return null;
181
+ }
182
+ try {
183
+ const files = await readdir(claudeProjectDir);
184
+ const jsonlFiles = files.filter((f) => f.endsWith(".jsonl"));
185
+ if (jsonlFiles.length === 0)
186
+ return null;
187
+ const startTime = startedAt.getTime();
188
+ // Allow a 5-minute buffer for the run to end
189
+ const endTime = endedAt ? endedAt.getTime() + 5 * 60 * 1000 : Date.now() + 5 * 60 * 1000;
190
+ // Find files modified within the run's time window
191
+ const candidates = [];
192
+ for (const file of jsonlFiles) {
193
+ const filePath = join(claudeProjectDir, file);
194
+ try {
195
+ const stats = await stat(filePath);
196
+ const mtime = stats.mtime.getTime();
197
+ // File was modified during the run window (with 1 minute buffer before start)
198
+ if (mtime >= startTime - 60 * 1000 && mtime <= endTime) {
199
+ candidates.push({ path: filePath, mtime });
200
+ }
201
+ }
202
+ catch {
203
+ // Skip files we can't stat
204
+ }
205
+ }
206
+ if (candidates.length === 0)
207
+ return null;
208
+ // Return the most recently modified file (most likely to be the run's transcript)
209
+ candidates.sort((a, b) => b.mtime - a.mtime);
210
+ return candidates[0].path;
211
+ }
212
+ catch {
213
+ return null;
214
+ }
215
+ };
216
+ //# sourceMappingURL=transcript-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-parser.js","sourceRoot":"","sources":["../../src/utils/transcript-parser.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@jamesaphoenix/tx-api-server",
3
+ "version": "0.1.1",
4
+ "description": "TX REST/HTTP API server - OpenAPI-compliant HTTP interface",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "tx-api": "./dist/server.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ },
16
+ "./runtime": {
17
+ "types": "./dist/runtime.d.ts",
18
+ "import": "./dist/runtime.js"
19
+ },
20
+ "./routes/tasks": {
21
+ "types": "./dist/routes/tasks.d.ts",
22
+ "import": "./dist/routes/tasks.js"
23
+ },
24
+ "./routes/runs": {
25
+ "types": "./dist/routes/runs.d.ts",
26
+ "import": "./dist/routes/runs.js"
27
+ },
28
+ "./routes/learnings": {
29
+ "types": "./dist/routes/learnings.d.ts",
30
+ "import": "./dist/routes/learnings.js"
31
+ },
32
+ "./routes/sync": {
33
+ "types": "./dist/routes/sync.d.ts",
34
+ "import": "./dist/routes/sync.js"
35
+ },
36
+ "./routes/health": {
37
+ "types": "./dist/routes/health.d.ts",
38
+ "import": "./dist/routes/health.js"
39
+ }
40
+ },
41
+ "files": [
42
+ "dist"
43
+ ],
44
+ "scripts": {
45
+ "build": "tsc -b",
46
+ "typecheck": "tsc --noEmit",
47
+ "lint": "eslint src/",
48
+ "test": "bun test src/",
49
+ "dev": "tsx --watch src/server.ts",
50
+ "start": "node dist/server.js"
51
+ },
52
+ "dependencies": {
53
+ "@jamesaphoenix/tx-core": "*",
54
+ "@jamesaphoenix/tx-types": "*",
55
+ "@effect/platform": "^0.94.2",
56
+ "@effect/platform-node": "^0.104.1",
57
+ "effect": "^3.19.15"
58
+ },
59
+ "devDependencies": {
60
+ "@types/bun": "^1.2.0",
61
+ "@types/node": "^25.2.0",
62
+ "@vitest/coverage-v8": "^4.0.18",
63
+ "tsx": "^4.19.0",
64
+ "typescript": "^5.7.0",
65
+ "vitest": "^4.0.18"
66
+ },
67
+ "keywords": [
68
+ "tx",
69
+ "api",
70
+ "rest",
71
+ "http",
72
+ "openapi",
73
+ "effect-ts"
74
+ ]
75
+ }