@gkorepanov/ccodex 0.5.0-rc.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +159 -157
  2. package/config/compatibility.json +1 -1
  3. package/dist/claude/delegation.d.ts +10 -0
  4. package/dist/claude/delegation.js +41 -0
  5. package/dist/claude/delegation.js.map +1 -0
  6. package/dist/claude/native/catalog.d.ts +5 -0
  7. package/dist/claude/native/catalog.js +26 -17
  8. package/dist/claude/native/catalog.js.map +1 -1
  9. package/dist/claude/native/history.js +4 -3
  10. package/dist/claude/native/history.js.map +1 -1
  11. package/dist/claude/native/pages.d.ts +2 -0
  12. package/dist/claude/native/pages.js +6 -1
  13. package/dist/claude/native/pages.js.map +1 -1
  14. package/dist/claude/native/projector.js +33 -12
  15. package/dist/claude/native/projector.js.map +1 -1
  16. package/dist/claude/native/records.js +19 -0
  17. package/dist/claude/native/records.js.map +1 -1
  18. package/dist/claude/native/search.d.ts +7 -0
  19. package/dist/claude/native/search.js +79 -0
  20. package/dist/claude/native/search.js.map +1 -0
  21. package/dist/claude/native/summary.d.ts +6 -1
  22. package/dist/claude/native/summary.js +24 -6
  23. package/dist/claude/native/summary.js.map +1 -1
  24. package/dist/claude/peers.d.ts +2 -0
  25. package/dist/claude/peers.js +13 -4
  26. package/dist/claude/peers.js.map +1 -1
  27. package/dist/claude/processes.d.ts +2 -0
  28. package/dist/claude/processes.js +15 -0
  29. package/dist/claude/processes.js.map +1 -1
  30. package/dist/claude/sdk.d.ts +6 -5
  31. package/dist/claude/sdk.js +15 -8
  32. package/dist/claude/sdk.js.map +1 -1
  33. package/dist/claude/session.d.ts +25 -5
  34. package/dist/claude/session.js +134 -29
  35. package/dist/claude/session.js.map +1 -1
  36. package/dist/claude/threads.d.ts +43 -3
  37. package/dist/claude/threads.js +255 -60
  38. package/dist/claude/threads.js.map +1 -1
  39. package/dist/claude/toolMapper.d.ts +7 -0
  40. package/dist/claude/toolMapper.js +14 -1
  41. package/dist/claude/toolMapper.js.map +1 -1
  42. package/dist/config.d.ts +2 -0
  43. package/dist/config.js +2 -1
  44. package/dist/config.js.map +1 -1
  45. package/dist/daemon/daemon.d.ts +3 -0
  46. package/dist/daemon/daemon.js +6 -3
  47. package/dist/daemon/daemon.js.map +1 -1
  48. package/dist/daemon/supervisor.d.ts +3 -0
  49. package/dist/daemon/supervisor.js +2 -0
  50. package/dist/daemon/supervisor.js.map +1 -1
  51. package/dist/desktop/stdioFrontend.js +1 -1
  52. package/dist/desktop/stdioFrontend.js.map +1 -1
  53. package/dist/gateway/catalog.js +35 -20
  54. package/dist/gateway/catalog.js.map +1 -1
  55. package/dist/gateway/connection.d.ts +2 -0
  56. package/dist/gateway/connection.js +14 -2
  57. package/dist/gateway/connection.js.map +1 -1
  58. package/dist/gateway/lineage.d.ts +9 -1
  59. package/dist/gateway/lineage.js +134 -37
  60. package/dist/gateway/lineage.js.map +1 -1
  61. package/dist/gateway/server.d.ts +2 -1
  62. package/dist/gateway/server.js +24 -12
  63. package/dist/gateway/server.js.map +1 -1
  64. package/dist/gateway/status.d.ts +15 -5
  65. package/dist/gateway/status.js +142 -47
  66. package/dist/gateway/status.js.map +1 -1
  67. package/dist/gateway/stock.js +17 -2
  68. package/dist/gateway/stock.js.map +1 -1
  69. package/dist/instructions.d.ts +4 -0
  70. package/dist/instructions.js +13 -0
  71. package/dist/instructions.js.map +1 -0
  72. package/dist/management/commands.js +19 -2
  73. package/dist/management/commands.js.map +1 -1
  74. package/dist/meta.d.ts +39 -11
  75. package/dist/meta.js +59 -28
  76. package/dist/meta.js.map +1 -1
  77. package/dist/protocol/codex.d.ts +1 -3
  78. package/dist/protocol/codex.js +1 -4
  79. package/dist/protocol/codex.js.map +1 -1
  80. package/dist/protocol/turnPagination.d.ts +27 -2
  81. package/dist/protocol/turnPagination.js +46 -18
  82. package/dist/protocol/turnPagination.js.map +1 -1
  83. package/examples/config.toml +6 -2
  84. package/instructions/ccodex_extra_claude_instructions.md +20 -0
  85. package/instructions/ccodex_extra_common_instructions.md +23 -0
  86. package/legal/THIRD_PARTY_NOTICES.md +9 -9
  87. package/package.json +6 -5
  88. package/scripts/migrate-0.4-to-0.5.mjs +29 -18
@@ -0,0 +1,23 @@
1
+ ### Formulas
2
+ Write formulas in LaTeX: \(...\) inline, \[...\] for display equations; not $...$, which the chat shows as raw text. Use them for any maths instead of plain-text formulas.
3
+
4
+ ### Plots
5
+ When you make a plot for the user, check it before the final response: look at the resulting image and make sure it makes sense, lines are clearly visible, x/y ranges are reasonable etc.
6
+
7
+ Give each plot a short, unique, memorable name (e.g. `latency_by_region`) so the user can reference it later; for edits add suffixes like `_fix`, `_v2`.
8
+
9
+ When sending plots in chat, always use this format (link title + inline image):
10
+
11
+ ```
12
+ [plot_name](/abs/full/path/to/img.png)
13
+
14
+ ![plot_name](/abs/full/path/to/img.png)
15
+
16
+ ---
17
+
18
+ Here goes a description of the plot, the logic/maths behind it, what are the panels/lines and key takeaways to look at.
19
+
20
+ ---
21
+ ```
22
+
23
+ Do not forget the newlines around the image and the dividers around the description.
@@ -1131,15 +1131,15 @@ Generated from package-lock.json and locked Cargo metadata. Review entries and u
1131
1131
  | cargo:zvariant | 4.2.0 | MIT |
1132
1132
  | cargo:zvariant_derive | 4.2.0 | MIT |
1133
1133
  | cargo:zvariant_utils | 2.1.0 | MIT |
1134
- | npm:@anthropic-ai/claude-agent-sdk | 0.3.280 | SEE LICENSE IN README.md |
1135
- | npm:@anthropic-ai/claude-agent-sdk-darwin-arm64 | 0.3.280 | SEE LICENSE IN LICENSE.md |
1136
- | npm:@anthropic-ai/claude-agent-sdk-darwin-x64 | 0.3.280 | SEE LICENSE IN LICENSE.md |
1137
- | npm:@anthropic-ai/claude-agent-sdk-linux-arm64 | 0.3.280 | SEE LICENSE IN LICENSE.md |
1138
- | npm:@anthropic-ai/claude-agent-sdk-linux-arm64-musl | 0.3.280 | SEE LICENSE IN LICENSE.md |
1139
- | npm:@anthropic-ai/claude-agent-sdk-linux-x64 | 0.3.280 | SEE LICENSE IN LICENSE.md |
1140
- | npm:@anthropic-ai/claude-agent-sdk-linux-x64-musl | 0.3.280 | SEE LICENSE IN LICENSE.md |
1141
- | npm:@anthropic-ai/claude-agent-sdk-win32-arm64 | 0.3.280 | SEE LICENSE IN LICENSE.md |
1142
- | npm:@anthropic-ai/claude-agent-sdk-win32-x64 | 0.3.280 | SEE LICENSE IN LICENSE.md |
1134
+ | npm:@anthropic-ai/claude-agent-sdk | 0.3.284 | SEE LICENSE IN README.md |
1135
+ | npm:@anthropic-ai/claude-agent-sdk-darwin-arm64 | 0.3.284 | SEE LICENSE IN LICENSE.md |
1136
+ | npm:@anthropic-ai/claude-agent-sdk-darwin-x64 | 0.3.284 | SEE LICENSE IN LICENSE.md |
1137
+ | npm:@anthropic-ai/claude-agent-sdk-linux-arm64 | 0.3.284 | SEE LICENSE IN LICENSE.md |
1138
+ | npm:@anthropic-ai/claude-agent-sdk-linux-arm64-musl | 0.3.284 | SEE LICENSE IN LICENSE.md |
1139
+ | npm:@anthropic-ai/claude-agent-sdk-linux-x64 | 0.3.284 | SEE LICENSE IN LICENSE.md |
1140
+ | npm:@anthropic-ai/claude-agent-sdk-linux-x64-musl | 0.3.284 | SEE LICENSE IN LICENSE.md |
1141
+ | npm:@anthropic-ai/claude-agent-sdk-win32-arm64 | 0.3.284 | SEE LICENSE IN LICENSE.md |
1142
+ | npm:@anthropic-ai/claude-agent-sdk-win32-x64 | 0.3.284 | SEE LICENSE IN LICENSE.md |
1143
1143
  | npm:@anthropic-ai/sdk | 0.111.0 | MIT |
1144
1144
  | npm:@babel/runtime | 7.29.7 | MIT |
1145
1145
  | npm:@esbuild/aix-ppc64 | 0.25.12 | MIT |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gkorepanov/ccodex",
3
- "version": "0.5.0-rc.8",
3
+ "version": "0.5.0",
4
4
  "description": "Unofficial Codex App compatibility bridge for Codex CLI and Claude Code runtimes.",
5
5
  "homepage": "https://github.com/gkorepanov/ccodex#readme",
6
6
  "repository": {
@@ -33,6 +33,7 @@
33
33
  "scripts/install-claude-stack.sh",
34
34
  "agents/*.md",
35
35
  "skills/**/*.md",
36
+ "instructions/*.md",
36
37
  "examples/config.toml",
37
38
  "legal/LICENSES.md",
38
39
  "legal/THIRD_PARTY_NOTICES.md",
@@ -59,15 +60,15 @@
59
60
  "check:relay-transport": "node scripts/relay-transport.mjs --check"
60
61
  },
61
62
  "dependencies": {
62
- "@anthropic-ai/claude-agent-sdk": "0.3.280",
63
+ "@anthropic-ai/claude-agent-sdk": "0.3.284",
63
64
  "smol-toml": "1.9.0",
64
65
  "uuid": "13.0.2",
65
66
  "ws": "8.21.0"
66
67
  },
67
68
  "optionalDependencies": {
68
- "@gkorepanov/ccodex-relay-darwin-arm64": "0.5.0-rc.8",
69
- "@gkorepanov/ccodex-relay-linux-arm64-gnu": "0.5.0-rc.8",
70
- "@gkorepanov/ccodex-relay-linux-x64-gnu": "0.5.0-rc.8"
69
+ "@gkorepanov/ccodex-relay-darwin-arm64": "0.5.0",
70
+ "@gkorepanov/ccodex-relay-linux-arm64-gnu": "0.5.0",
71
+ "@gkorepanov/ccodex-relay-linux-x64-gnu": "0.5.0"
71
72
  },
72
73
  "devDependencies": {
73
74
  "@openai/codex": "0.156.0",
@@ -2,17 +2,18 @@
2
2
  // One-off migration of CCodex 0.4 state (state.sqlite + handoffs.sqlite) to 0.5's meta.json. `ccodex setup` runs it
3
3
  // once, before it activates 0.5 (0.4's state.sqlite is there, meta.json is not). `--dry-run` only prints what it would do.
4
4
  //
5
- // - Every 0.4 Claude thread keeps its id: meta.lineages[<0.4 id>] = [{ claude, <session id> }].
6
- // - Provider-switch lineages become segment lists; forks whose 0.4 id was no backend move to their current backend.
5
+ // - 0.4 thread ids go: a Claude thread is listed under its Claude session id, a provider-switch lineage (a segment
6
+ // list) under its first segment, a fork whose 0.4 id was no backend under its current backend.
7
+ // - 0.4 side chats (/btw, full Claude forks) are no chats: their sessions are archived, without a 0.4 id.
7
8
  // - Archive flags, sections and section order of Claude threads carry over; names go into the transcripts.
8
9
  // - Claude threads whose transcript Claude's cleanup deleted (cleanupPeriodDays, 30 by default) get one back from the
9
10
  // 0.4 turns: prompts and answers as text, without tool calls, reasoning or compactions. Claude resumes it as such.
10
11
  // - A lineage is archived when its current backend was (0.4 archived sealed stock backends to hide them); 0.5 reads
11
12
  // the flag from the row's backend, so that one is set to match, stock ones through `codex app-server`.
12
- // SQLite files are only read. meta.json is backed up before it is replaced.
13
+ // SQLite files are only read, then moved to ~/.ccodex.0.4-backup. meta.json is backed up before it is replaced.
13
14
  import { spawn } from "node:child_process";
14
15
  import { randomUUID } from "node:crypto";
15
- import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, utimesSync, writeFileSync } from "node:fs";
16
+ import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, utimesSync, writeFileSync } from "node:fs";
16
17
  import { homedir } from "node:os";
17
18
  import { dirname, join } from "node:path";
18
19
  import { createInterface } from "node:readline";
@@ -51,13 +52,14 @@ const claudeThreads = new Map(state.prepare(`select id, claude_session_id, archi
51
52
  json_extract(thread_json, '$.parentThreadId') parent, json_extract(thread_json, '$.name') name,
52
53
  json_extract(thread_json, '$.section') section, json_extract(thread_json, '$.sectionEnteredAt') section_entered_at
53
54
  from threads`).all().map((row) => [row.id, row]));
55
+ const sides = new Set(handoffs?.prepare("select public_thread_id from side_threads").all().map((row) => row.public_thread_id));
54
56
 
55
57
  // A turn's last record takes the uuid 0.4 kept for it, so provider-switch segments still end at that turn.
56
58
  for (const thread of state.prepare(`select id, claude_session_id, cwd, claude_code_version, coalesce(resolved_model, claude_model_value) model
57
59
  from threads where claude_session_id is not null and deletion_pending = 0
58
60
  and json_extract(thread_json, '$.parentThreadId') is null`).all()) {
59
61
  const sessionId = thread.claude_session_id;
60
- if (transcripts.has(sessionId)) continue;
62
+ if (transcripts.has(sessionId) || sides.has(thread.id)) continue;
61
63
  const lines = [];
62
64
  let parentUuid = null;
63
65
  let at = 0;
@@ -102,6 +104,8 @@ function claudeTurnId(threadId, turnId) {
102
104
  }
103
105
 
104
106
  const lineages = {};
107
+ /** 0.4 public id → the id 0.5 lists its lineage under. */
108
+ const publicIds = new Map();
105
109
  const lineageBackends = new Set();
106
110
  let skipped = 0;
107
111
  if (handoffs) {
@@ -127,12 +131,13 @@ if (handoffs) {
127
131
  lastTurnId: last || !end ? null : claudeTurnId(epoch.backend_thread_id, end),
128
132
  };
129
133
  });
130
- // 0.5 names a fork by its current backend; a lineage started from a thread keeps that thread's id.
134
+ // 0.5 names a fork by its current backend; a lineage started from a thread goes by that thread's backend.
131
135
  // Stock never lists threads without a user message of their own (0.4 made such forks); those take the current id.
132
136
  const unlisted = segments[0].provider === "codex"
133
137
  && stock.prepare("select first_user_message from threads where id = ?").get(segments[0].threadId)?.first_user_message === "";
134
- const publicId = parts[0].epoch.backend_thread_id === task.public_thread_id && !unlisted ? task.public_thread_id : segments.at(-1).threadId;
135
- if (publicId !== task.public_thread_id) log(`${unlisted ? "unlisted" : "fork"} ${task.public_thread_id} is now ${publicId}`);
138
+ const publicId = parts[0].epoch.backend_thread_id === task.public_thread_id && !unlisted ? segments[0].threadId : segments.at(-1).threadId;
139
+ if (publicId !== segments[0].threadId) log(`${unlisted ? "unlisted" : "fork"} ${task.public_thread_id} is now ${publicId}`);
140
+ publicIds.set(task.public_thread_id, publicId);
136
141
  if (segments.length === 1 && segments[0].threadId === publicId) continue;
137
142
  lineages[publicId] = segments;
138
143
  }
@@ -144,8 +149,9 @@ const named = [];
144
149
  for (const thread of claudeThreads.values()) {
145
150
  const sessionId = thread.claude_session_id;
146
151
  if (thread.deletion_pending || thread.parent || !transcripts.has(sessionId)) continue;
147
- if (!lineages[thread.id] && !lineageBackends.has(thread.id) && thread.id !== sessionId) {
148
- lineages[thread.id] = [{ provider: "claude", threadId: sessionId, lastTurnId: null }];
152
+ if (sides.has(thread.id)) {
153
+ archived.add(sessionId);
154
+ continue;
149
155
  }
150
156
  if (thread.archived) archived.add(sessionId);
151
157
  if (thread.section) sections[sessionId] = { sectionId: JSON.parse(thread.section).id, enteredAt: thread.section_entered_at ?? thread.updated_at };
@@ -165,7 +171,7 @@ for (const { backend_thread_id: id } of handoffs?.prepare("select backend_thread
165
171
 
166
172
  const archived04 = new Set([...claudeThreads.values()].filter((thread) => thread.archived).map((thread) => thread.claude_session_id));
167
173
  for (const [publicId, segments] of Object.entries(lineages)) {
168
- const row = segments.find((segment) => segment.threadId === publicId) ?? segments[0];
174
+ const row = segments.find((segment) => segment.threadId === publicId);
169
175
  const isArchived = (segment) => segment.provider === "codex"
170
176
  ? stock.prepare("select archived from threads where id = ?").get(segment.threadId)?.archived === 1
171
177
  : archived04.has(segment.threadId);
@@ -200,11 +206,9 @@ async function stockRequests(requests) {
200
206
  child.kill();
201
207
  }
202
208
 
203
- /** A 0.4 id as 0.5 lists it (the row's backend). */
209
+ /** A 0.4 id as 0.5 lists it. */
204
210
  function rowId(id) {
205
- const segments = lineages[id];
206
- if (segments) return (segments.find((segment) => segment.threadId === id) ?? segments[0]).threadId;
207
- return claudeThreads.get(id)?.claude_session_id ?? id;
211
+ return publicIds.get(id) ?? claudeThreads.get(id)?.claude_session_id ?? id;
208
212
  }
209
213
  // Older 0.4 states predate section orders.
210
214
  const sectionOrders = state.prepare("select 1 from sqlite_master where type = 'table' and name = 'section_orders'").get()
@@ -217,11 +221,9 @@ const meta = {
217
221
  archived: [...new Set([...archived, ...(existing.archived ?? [])])],
218
222
  sections: { ...sections, ...existing.sections },
219
223
  sectionOrder: { ...sectionOrder, ...existing.sectionOrder },
220
- leaves: existing.leaves ?? {},
221
224
  };
222
225
 
223
- const aliases = Object.values(lineages).filter((segments) => segments.length === 1).length;
224
- log(`lineages: ${Object.keys(lineages).length} (${aliases} kept 0.4 Claude ids, ${Object.keys(lineages).length - aliases} provider switches), skipped ${skipped}`);
226
+ log(`lineages: ${Object.keys(lineages).length}, skipped ${skipped}`);
225
227
  log(`restored transcripts: ${restored.size}`);
226
228
  log(`archived: ${archived.size}, stock archive changes: ${stockArchives.length}, in sections: ${Object.keys(sections).length}, section orders: ${Object.keys(sectionOrder).length}, names to write: ${named.length}`);
227
229
  if (dryRun) {
@@ -240,4 +242,13 @@ for (const { sessionId, name } of named) {
240
242
  }
241
243
  // Claude lists sessions by their file's time: a restored one keeps its place.
242
244
  for (const [sessionId, { at }] of restored) utimesSync(transcripts.get(sessionId), at, at);
245
+ // 0.4's databases go out of the way: nothing reads them, and setup migrates only while state.sqlite is there.
246
+ state.close();
247
+ handoffs?.close();
248
+ const backup = `${home}.0.4-backup`;
249
+ mkdirSync(backup, { recursive: true, mode: 0o700 });
250
+ for (const name of readdirSync(stateDir).filter((name) => /^(state|handoffs)\.sqlite|^backups$|^cursor\.key$/.test(name))) {
251
+ renameSync(join(stateDir, name), join(backup, name));
252
+ }
253
+ log(`moved 0.4's databases to ${backup}`);
243
254
  log(`wrote ${metaPath}. Restart the gateway: codex app-server daemon restart`);