codiedev 0.10.0-beta.4 → 0.10.0-beta.6

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 (157) hide show
  1. package/README.md +11 -5
  2. package/assets/tui-brand-plugin.tsx +14 -2
  3. package/dist/backup/cache.js +1 -5
  4. package/dist/backup/match.js +0 -6
  5. package/dist/backup/run.js +3 -35
  6. package/dist/captureExclusions.js +0 -12
  7. package/dist/captureLog.js +0 -28
  8. package/dist/captureReadiness.js +0 -58
  9. package/dist/captureSignals.js +68 -3
  10. package/dist/cli.js +75 -64
  11. package/dist/codexHookTrust.js +125 -6
  12. package/dist/codexLimitScan.js +2 -109
  13. package/dist/codie.js +50 -114
  14. package/dist/codieBrandInstall.js +0 -18
  15. package/dist/codieLauncher.js +20 -92
  16. package/dist/codieRuntime.js +19 -23
  17. package/dist/codieRuntimeInstall.js +108 -23
  18. package/dist/codieUsage.js +38 -41
  19. package/dist/commands/agentTemplates.generated.js +136 -0
  20. package/dist/commands/agents.js +1066 -0
  21. package/dist/commands/agentsSdk.generated.js +7 -0
  22. package/dist/commands/ask.js +0 -3
  23. package/dist/commands/capture.js +0 -2
  24. package/dist/commands/createTicket.js +0 -10
  25. package/dist/commands/doctor.js +53 -120
  26. package/dist/commands/evals.js +187 -0
  27. package/dist/commands/inbox.js +0 -2
  28. package/dist/commands/library.js +0 -3
  29. package/dist/commands/pack.js +573 -0
  30. package/dist/commands/ping.js +0 -2
  31. package/dist/commands/pull.js +6 -10
  32. package/dist/commands/push.js +2 -12
  33. package/dist/commands/search.js +0 -4
  34. package/dist/commands/send.js +0 -5
  35. package/dist/commands/share.js +0 -4
  36. package/dist/commands/shared.js +0 -35
  37. package/dist/commands/traces.js +344 -0
  38. package/dist/commands/tracesLabel.js +348 -0
  39. package/dist/configDir.js +0 -10
  40. package/dist/connect.js +19 -116
  41. package/dist/connectFlow.js +0 -9
  42. package/dist/copilotHooks.js +391 -0
  43. package/dist/copilotInstallation.js +64 -0
  44. package/dist/cursorHooks.js +38 -30
  45. package/dist/cursorLifecycle.js +109 -0
  46. package/dist/detection.js +0 -30
  47. package/dist/harnessDirs.js +77 -0
  48. package/dist/hook.js +182 -469
  49. package/dist/inboxFormat.js +0 -24
  50. package/dist/launchContext.js +150 -0
  51. package/dist/launcher.js +140 -0
  52. package/dist/limitEvent.js +41 -35
  53. package/dist/limitEventReporter.js +1 -1
  54. package/dist/managedPi.js +240 -0
  55. package/dist/mcp.js +3 -384
  56. package/dist/nativeSteering.js +24 -0
  57. package/dist/packs/codie.js +182 -0
  58. package/dist/packs/harnesses.js +411 -0
  59. package/dist/packs/hookGate.js +256 -0
  60. package/dist/packs/install.js +286 -0
  61. package/dist/packs/manifest.js +126 -0
  62. package/dist/packs/paths.js +81 -0
  63. package/dist/packs/shim.js +214 -0
  64. package/dist/packs/store.js +155 -0
  65. package/dist/packs/sync.js +170 -0
  66. package/dist/piHooks.js +216 -0
  67. package/dist/piRuntime.js +120 -0
  68. package/dist/repoResolver.js +0 -19
  69. package/dist/secret.js +0 -3
  70. package/dist/selfUpdate.js +376 -0
  71. package/dist/skillMarker.js +23 -0
  72. package/dist/subagents.js +135 -0
  73. package/dist/teamSkillContext.js +10 -0
  74. package/dist/transcriptModels.js +6 -8
  75. package/dist/upgradeNudge.js +0 -30
  76. package/dist/utils.js +494 -824
  77. package/dist/version.js +0 -10
  78. package/dist/versionCheck.js +0 -33
  79. package/package.json +8 -9
  80. package/dist/backup/cache.d.ts +0 -14
  81. package/dist/backup/match.d.ts +0 -2
  82. package/dist/backup/run.d.ts +0 -25
  83. package/dist/captureExclusions.d.ts +0 -30
  84. package/dist/captureLog.d.ts +0 -20
  85. package/dist/captureReadiness.d.ts +0 -65
  86. package/dist/captureSignals.d.ts +0 -19
  87. package/dist/cli.d.ts +0 -16
  88. package/dist/codexHookTrust.d.ts +0 -34
  89. package/dist/codexLimitScan.d.ts +0 -64
  90. package/dist/codie.d.ts +0 -2
  91. package/dist/codieBrandInstall.d.ts +0 -11
  92. package/dist/codieLauncher.d.ts +0 -86
  93. package/dist/codieRuntime.d.ts +0 -29
  94. package/dist/codieRuntimeInstall.d.ts +0 -28
  95. package/dist/codieStartup.d.ts +0 -26
  96. package/dist/codieStartup.js +0 -30
  97. package/dist/codieUsage.d.ts +0 -57
  98. package/dist/commands/ask.d.ts +0 -1
  99. package/dist/commands/capture.d.ts +0 -14
  100. package/dist/commands/createTicket.d.ts +0 -27
  101. package/dist/commands/delete.d.ts +0 -1
  102. package/dist/commands/doctor.d.ts +0 -1
  103. package/dist/commands/inbox.d.ts +0 -3
  104. package/dist/commands/library.d.ts +0 -2
  105. package/dist/commands/note.d.ts +0 -1
  106. package/dist/commands/ping.d.ts +0 -1
  107. package/dist/commands/promote.d.ts +0 -1
  108. package/dist/commands/promote.js +0 -53
  109. package/dist/commands/pull.d.ts +0 -2
  110. package/dist/commands/push.d.ts +0 -33
  111. package/dist/commands/react.d.ts +0 -2
  112. package/dist/commands/react.js +0 -40
  113. package/dist/commands/reverseTicket.d.ts +0 -2
  114. package/dist/commands/reverseTicket.js +0 -477
  115. package/dist/commands/search.d.ts +0 -2
  116. package/dist/commands/security.d.ts +0 -1
  117. package/dist/commands/security.js +0 -156
  118. package/dist/commands/send.d.ts +0 -2
  119. package/dist/commands/share.d.ts +0 -2
  120. package/dist/commands/shared.d.ts +0 -64
  121. package/dist/configDir.d.ts +0 -1
  122. package/dist/connect.d.ts +0 -1
  123. package/dist/connectFlow.d.ts +0 -13
  124. package/dist/cursorHooks.d.ts +0 -23
  125. package/dist/detection.d.ts +0 -30
  126. package/dist/hook.d.ts +0 -6
  127. package/dist/inboxFormat.d.ts +0 -38
  128. package/dist/limitEvent.d.ts +0 -16
  129. package/dist/limitEventReporter.d.ts +0 -21
  130. package/dist/mcp.d.ts +0 -12
  131. package/dist/prUrl.d.ts +0 -9
  132. package/dist/prUrl.js +0 -33
  133. package/dist/repoResolver.d.ts +0 -17
  134. package/dist/secret.d.ts +0 -1
  135. package/dist/security.d.ts +0 -102
  136. package/dist/security.js +0 -437
  137. package/dist/securityDeepScan.d.ts +0 -41
  138. package/dist/securityDeepScan.js +0 -248
  139. package/dist/securityDoctor.d.ts +0 -32
  140. package/dist/securityDoctor.js +0 -63
  141. package/dist/securityFeature.d.ts +0 -5
  142. package/dist/securityFeature.js +0 -7
  143. package/dist/securityInstall.d.ts +0 -63
  144. package/dist/securityInstall.js +0 -239
  145. package/dist/securityInventory.d.ts +0 -54
  146. package/dist/securityInventory.js +0 -556
  147. package/dist/securityPilot.d.ts +0 -19
  148. package/dist/securityPilot.js +0 -61
  149. package/dist/securityPolicy.d.ts +0 -33
  150. package/dist/securityPolicy.js +0 -188
  151. package/dist/securitySession.d.ts +0 -6
  152. package/dist/securitySession.js +0 -72
  153. package/dist/transcriptModels.d.ts +0 -18
  154. package/dist/upgradeNudge.d.ts +0 -25
  155. package/dist/utils.d.ts +0 -346
  156. package/dist/version.d.ts +0 -1
  157. package/dist/versionCheck.d.ts +0 -68
@@ -0,0 +1,391 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.COPILOT_VSCODE_CLIENT = void 0;
37
+ exports.copilotHome = copilotHome;
38
+ exports.copilotSessionDir = copilotSessionDir;
39
+ exports.copilotTranscriptPath = copilotTranscriptPath;
40
+ exports.parseCopilotWorkspace = parseCopilotWorkspace;
41
+ exports.readCopilotWorkspace = readCopilotWorkspace;
42
+ exports.copilotLaunch = copilotLaunch;
43
+ exports.normalizeCopilotHookInput = normalizeCopilotHookInput;
44
+ exports.isCopilotTranscriptEmpty = isCopilotTranscriptEmpty;
45
+ exports.hasCopilotShutdown = hasCopilotShutdown;
46
+ exports.normalizeCopilotTranscript = normalizeCopilotTranscript;
47
+ const fs = __importStar(require("node:fs"));
48
+ const os = __importStar(require("node:os"));
49
+ const path = __importStar(require("node:path"));
50
+ function copilotHome(env = process.env, home = os.homedir()) {
51
+ const override = env.COPILOT_HOME?.trim();
52
+ return override ? path.resolve(override) : path.join(home, ".copilot");
53
+ }
54
+ const SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
55
+ function copilotSessionDir(sessionId, home = copilotHome()) {
56
+ return SESSION_ID.test(sessionId) ? path.join(home, "session-state", sessionId) : undefined;
57
+ }
58
+ function copilotTranscriptPath(sessionId, home = copilotHome()) {
59
+ const dir = sessionId ? copilotSessionDir(sessionId, home) : undefined;
60
+ return dir ? path.join(dir, "events.jsonl") : undefined;
61
+ }
62
+ function parseCopilotWorkspace(yaml) {
63
+ const fields = new Map();
64
+ for (const line of yaml.split(/\r?\n/)) {
65
+ const match = line.match(/^([a-z_]+):\s*(.*)$/);
66
+ if (!match)
67
+ continue;
68
+ let value = match[2].trim();
69
+ if (/^(["']).*\1$/.test(value))
70
+ value = value.slice(1, -1);
71
+ if (value)
72
+ fields.set(match[1], value);
73
+ }
74
+ const pick = (key) => fields.get(key);
75
+ return {
76
+ ...(pick("id") ? { id: pick("id") } : {}),
77
+ ...(pick("cwd") ? { cwd: pick("cwd") } : {}),
78
+ ...(pick("git_root") ? { gitRoot: pick("git_root") } : {}),
79
+ ...(pick("branch") ? { branch: pick("branch") } : {}),
80
+ ...(pick("client_name") ? { clientName: pick("client_name") } : {}),
81
+ };
82
+ }
83
+ function readCopilotWorkspace(transcriptPathOrDir) {
84
+ if (!transcriptPathOrDir)
85
+ return {};
86
+ const dir = transcriptPathOrDir.endsWith(".jsonl") ? path.dirname(transcriptPathOrDir) : transcriptPathOrDir;
87
+ try {
88
+ return parseCopilotWorkspace(fs.readFileSync(path.join(dir, "workspace.yaml"), "utf8"));
89
+ }
90
+ catch {
91
+ return {};
92
+ }
93
+ }
94
+ exports.COPILOT_VSCODE_CLIENT = "vscode-agent-host";
95
+ const isVSCodeClient = (name) => name === exports.COPILOT_VSCODE_CLIENT || name === "vscode";
96
+ function copilotLaunch(clientName, detected) {
97
+ if (isVSCodeClient(clientName))
98
+ return "copilot:vscode";
99
+ return detected;
100
+ }
101
+ const firstString = (...values) => values.find((value) => typeof value === "string" && value.trim().length > 0);
102
+ function normalizeCopilotHookInput(input, home = copilotHome()) {
103
+ const sessionId = firstString(input.session_id, input.sessionId);
104
+ const transcriptPath = firstString(input.transcript_path, input.transcriptPath)
105
+ ?? copilotTranscriptPath(sessionId, home);
106
+ const calls = copilotToolCalls(input);
107
+ const first = calls[0];
108
+ const toolResult = input.toolResult ?? input.tool_response;
109
+ return {
110
+ ...input,
111
+ ...(sessionId ? { session_id: sessionId } : {}),
112
+ ...(transcriptPath ? { transcript_path: transcriptPath } : {}),
113
+ ...(first ? { tool_name: first.name, tool_input: first.input } : {}),
114
+ ...(first?.id ? { tool_use_id: first.id } : {}),
115
+ ...(toolResult !== undefined ? { tool_response: toolResult } : {}),
116
+ ...(calls.length > 1 ? { copilotToolCalls: calls } : {}),
117
+ };
118
+ }
119
+ function copilotToolCalls(input) {
120
+ const parse = (args) => {
121
+ if (typeof args !== "string")
122
+ return args;
123
+ try {
124
+ return JSON.parse(args);
125
+ }
126
+ catch {
127
+ return args;
128
+ }
129
+ };
130
+ if (Array.isArray(input.toolCalls)) {
131
+ return input.toolCalls.flatMap((raw) => {
132
+ const call = raw;
133
+ const name = firstString(call?.name, call?.toolName);
134
+ return name
135
+ ? [{ ...(typeof call.id === "string" ? { id: call.id } : {}), name, input: parse(call.args ?? call.toolArgs) }]
136
+ : [];
137
+ });
138
+ }
139
+ const name = firstString(input.toolName, input.tool_name);
140
+ return name ? [{ name, input: parse(input.toolArgs ?? input.tool_input) }] : [];
141
+ }
142
+ function isCopilotTranscriptEmpty(content) {
143
+ return content.trim().length === 0;
144
+ }
145
+ function hasCopilotShutdown(content) {
146
+ return content.includes('"session.shutdown"');
147
+ }
148
+ function claudeTool(name, args) {
149
+ const a = (args && typeof args === "object" ? args : {});
150
+ const lower = name.toLowerCase();
151
+ const file = firstString(a.path, a.file_path, a.filePath);
152
+ if (lower === "bash" || lower === "shell" || lower === "powershell") {
153
+ return { name: "Bash", input: { ...a, command: firstString(a.command, a.cmd) ?? "" } };
154
+ }
155
+ if ((lower === "edit" || lower === "str_replace" || lower === "str_replace_editor" || lower === "apply_patch") && file) {
156
+ return { name: "Edit", input: { ...a, file_path: file } };
157
+ }
158
+ if ((lower === "create" || lower === "write") && file)
159
+ return { name: "Write", input: { ...a, file_path: file } };
160
+ if (lower === "view" && file)
161
+ return { name: "Read", input: { ...a, file_path: file } };
162
+ if (lower === "skill")
163
+ return { name: "skill", input: {} };
164
+ return { name, input: args ?? {} };
165
+ }
166
+ const num = (value) => (typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0);
167
+ function copilotUserContent(data) {
168
+ const content = [];
169
+ if (typeof data.content === "string" && data.content)
170
+ content.push({ type: "text", text: data.content });
171
+ if (Array.isArray(data.attachments)) {
172
+ for (const attachment of data.attachments) {
173
+ if (!attachment || typeof attachment !== "object")
174
+ continue;
175
+ const { displayName, mimeType, type } = attachment;
176
+ const name = typeof displayName === "string" ? displayName : "unnamed attachment";
177
+ const kind = typeof mimeType === "string" ? mimeType : typeof type === "string" ? type : "attachment";
178
+ content.push({ type: "text", text: `[Attachment: ${name} (${kind}); attachment contents unavailable in captured transcript]` });
179
+ }
180
+ }
181
+ return content.length ? content : [{ type: "text", text: "" }];
182
+ }
183
+ function resultText(data) {
184
+ const result = data.result;
185
+ if (typeof result === "string")
186
+ return result;
187
+ if (result && typeof result === "object") {
188
+ const { content, detailedContent } = result;
189
+ return [content, detailedContent].filter((v) => typeof v === "string").join("\n");
190
+ }
191
+ return typeof data.error?.message === "string" ? data.error.message : "";
192
+ }
193
+ const count = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
194
+ function premiumOf(data, at) {
195
+ return {
196
+ premiumRequests: count(data.totalPremiumRequests),
197
+ nanoAiu: count(data.totalNanoAiu),
198
+ ...(at ? { at } : {}),
199
+ };
200
+ }
201
+ function sumAgentMetrics(agents) {
202
+ const totals = {};
203
+ for (const metrics of agents) {
204
+ for (const [model, metric] of Object.entries(metrics ?? {})) {
205
+ const into = (totals[model] ??= {});
206
+ for (const [key, value] of Object.entries(metric?.usage ?? {}))
207
+ into[key] = (into[key] ?? 0) + num(value);
208
+ }
209
+ }
210
+ return Object.fromEntries(Object.entries(totals).map(([model, usage]) => [model, { usage }]));
211
+ }
212
+ function normalizeCopilotTranscript(raw, opts = {}) {
213
+ const out = [];
214
+ const subagentCalls = new Set();
215
+ let shutdownAgents = 0;
216
+ let assistantModel = false;
217
+ let premium;
218
+ let checkpointModels = [];
219
+ let final = false;
220
+ for (const line of raw.split("\n")) {
221
+ if (!line.trim())
222
+ continue;
223
+ let event;
224
+ try {
225
+ event = JSON.parse(line);
226
+ }
227
+ catch {
228
+ continue;
229
+ }
230
+ const data = event?.data ?? {};
231
+ const timestamp = typeof event.timestamp === "string" ? event.timestamp : undefined;
232
+ const uuid = typeof event.id === "string" ? event.id : undefined;
233
+ const base = { ...(timestamp ? { timestamp } : {}), ...(uuid ? { uuid } : {}) };
234
+ switch (event.type) {
235
+ case "session.start": {
236
+ const context = data.context ?? {};
237
+ out.push(JSON.stringify({
238
+ type: "system",
239
+ subtype: "copilot_session_start",
240
+ ...base,
241
+ ...(typeof data.sessionId === "string" ? { sessionId: data.sessionId } : {}),
242
+ ...(typeof context.cwd === "string" ? { cwd: context.cwd } : {}),
243
+ ...(typeof context.branch === "string" ? { gitBranch: context.branch } : {}),
244
+ ...(typeof data.copilotVersion === "string" ? { version: data.copilotVersion } : {}),
245
+ ...(isVSCodeClient(opts.clientName) ? { entrypoint: "copilot:vscode" } : {}),
246
+ }));
247
+ break;
248
+ }
249
+ case "session.error":
250
+ out.push(JSON.stringify({ type: "agent.error", ...base, error: data.error ?? { message: data.message, code: data.errorType } }));
251
+ break;
252
+ case "hook.start":
253
+ if (data.hookType === "sessionEnd" && data.input?.reason === "abort") {
254
+ out.push(JSON.stringify({ type: "agent.interruption", ...base, id: uuid }));
255
+ }
256
+ break;
257
+ case "user.message":
258
+ out.push(JSON.stringify({
259
+ type: "user",
260
+ ...base,
261
+ message: { role: "user", content: copilotUserContent(data) },
262
+ }));
263
+ break;
264
+ case "subagent.started":
265
+ if (typeof data.toolCallId === "string")
266
+ subagentCalls.add(data.toolCallId);
267
+ break;
268
+ case "session.usage_checkpoint":
269
+ if (!final)
270
+ premium = premiumOf(data, timestamp);
271
+ if (Array.isArray(data.modelCacheState)) {
272
+ checkpointModels = data.modelCacheState
273
+ .map((m) => (m && typeof m === "object" ? m.modelId : undefined))
274
+ .filter((m) => typeof m === "string" && m.length > 0);
275
+ }
276
+ break;
277
+ case "assistant.message": {
278
+ if (typeof data.model === "string" && data.model)
279
+ assistantModel = true;
280
+ const tools = Array.isArray(data.toolRequests) ? data.toolRequests : [];
281
+ const content = [];
282
+ if (typeof data.content === "string" && data.content)
283
+ content.push({ type: "text", text: data.content });
284
+ for (const request of tools) {
285
+ if (typeof request?.name !== "string")
286
+ continue;
287
+ const mapped = claudeTool(request.name, request.arguments);
288
+ content.push({ type: "tool_use", id: request.toolCallId, name: mapped.name, input: mapped.input });
289
+ }
290
+ out.push(JSON.stringify({
291
+ type: "assistant",
292
+ ...base,
293
+ tokensAvailable: false,
294
+ message: {
295
+ id: firstString(data.apiCallId, data.messageId, uuid),
296
+ role: "assistant",
297
+ content,
298
+ ...(typeof data.model === "string" && data.model
299
+ ? {
300
+ model: data.model,
301
+ usage: { input_tokens: 0, output_tokens: 0, cache_read_input_tokens: 0, cache_creation_input_tokens: 0 },
302
+ }
303
+ : {}),
304
+ },
305
+ }));
306
+ break;
307
+ }
308
+ case "tool.execution_complete":
309
+ if (data.error?.code === "user_denied") {
310
+ out.push(JSON.stringify({ type: "agent.rejection", ...base, id: data.toolCallId ?? uuid }));
311
+ }
312
+ out.push(JSON.stringify({
313
+ type: "user",
314
+ ...base,
315
+ message: {
316
+ role: "user",
317
+ content: [{
318
+ type: "tool_result",
319
+ tool_use_id: data.toolCallId,
320
+ content: resultText(data),
321
+ ...(data.success === false ? { is_error: true } : {}),
322
+ }],
323
+ },
324
+ }).replace('"content":[{', '"content":[ {'));
325
+ break;
326
+ case "skill.invoked":
327
+ if (typeof data.name === "string" && data.name) {
328
+ out.push(JSON.stringify({ type: "copilot.skill_invoked", ...base, skill: data.name }));
329
+ }
330
+ break;
331
+ case "session.shutdown": {
332
+ final = true;
333
+ premium = premiumOf(data, timestamp);
334
+ const agents = Object.entries(data.agentMetrics ?? {});
335
+ shutdownAgents = agents.filter(([agent]) => agent !== "main").length;
336
+ const metrics = data.modelMetrics ?? sumAgentMetrics(agents.map(([, agent]) => agent?.modelMetrics));
337
+ for (const [model, metric] of Object.entries(metrics)) {
338
+ const usage = metric?.usage ?? {};
339
+ if (![usage.inputTokens, usage.outputTokens, usage.cacheReadTokens, usage.cacheWriteTokens].some(value => typeof value === "number" && Number.isFinite(value)))
340
+ continue;
341
+ const cacheRead = num(usage.cacheReadTokens);
342
+ out.push(JSON.stringify({
343
+ type: "copilot.usage",
344
+ ...base,
345
+ requests: 0,
346
+ message: {
347
+ id: `copilot-usage:${model}`,
348
+ model,
349
+ usage: {
350
+ input_tokens: Math.max(0, num(usage.inputTokens) - cacheRead),
351
+ output_tokens: num(usage.outputTokens),
352
+ cache_read_input_tokens: cacheRead,
353
+ cache_creation_input_tokens: num(usage.cacheWriteTokens),
354
+ },
355
+ },
356
+ }));
357
+ }
358
+ break;
359
+ }
360
+ default:
361
+ break;
362
+ }
363
+ }
364
+ if (!assistantModel) {
365
+ for (const model of checkpointModels) {
366
+ out.push(JSON.stringify({
367
+ type: "copilot.model",
368
+ tokensAvailable: false,
369
+ requests: 0,
370
+ message: {
371
+ id: `copilot-model:${model}`,
372
+ model,
373
+ usage: { input_tokens: 0, output_tokens: 0, cache_read_input_tokens: 0, cache_creation_input_tokens: 0 },
374
+ },
375
+ }));
376
+ }
377
+ }
378
+ if (premium && (premium.premiumRequests !== undefined || premium.nanoAiu !== undefined)) {
379
+ out.push(JSON.stringify({
380
+ type: "copilot.usage_summary",
381
+ ...(premium.at ? { timestamp: premium.at } : {}),
382
+ ...(premium.premiumRequests !== undefined ? { premiumRequests: premium.premiumRequests } : {}),
383
+ ...(premium.nanoAiu !== undefined ? { nanoAiu: premium.nanoAiu } : {}),
384
+ }));
385
+ }
386
+ return {
387
+ content: out.join("\n") + (out.length ? "\n" : ""),
388
+ subagents: { count: Math.max(subagentCalls.size, shutdownAgents), truncated: false },
389
+ final,
390
+ };
391
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.inspectCopilotHooks = inspectCopilotHooks;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const copilotHooks_1 = require("./copilotHooks");
40
+ const detection_1 = require("./detection");
41
+ function inspectCopilotHooks(file = path.join((0, copilotHooks_1.copilotHome)(), "hooks", "codiedev.json"), security = false) {
42
+ if (!fs.existsSync(file))
43
+ return { status: "not-installed", detail: `${file} not found` };
44
+ try {
45
+ const parsed = JSON.parse(fs.readFileSync(file, "utf8"));
46
+ const expected = security
47
+ ? [["userPromptSubmitted", "discover-copilot"], ["preToolUse", "security-pre-copilot"], ["postToolUse", "security-post-copilot"]]
48
+ : [["sessionStart", "session-start-copilot"], ["agentStop", "backup-copilot"], ["sessionEnd", "capture-copilot"], ["errorOccurred", "limit-copilot"]];
49
+ const missing = expected.filter(([event, subcommand]) => {
50
+ const entries = parsed.hooks?.[event];
51
+ return !Array.isArray(entries) || !entries.some((entry) => {
52
+ const commands = [entry.bash ?? entry.command, entry.powershell ?? entry.command];
53
+ return commands.every((command) => typeof command === "string"
54
+ && (0, detection_1.isCodiedevHookCommand)(command) && command.trim().endsWith(subcommand));
55
+ });
56
+ }).map(([event]) => event);
57
+ if (parsed.version !== 1 || missing.length)
58
+ return { status: "fail", detail: `invalid or missing hooks: ${missing.join(", ") || "version"}` };
59
+ return { status: "pass", detail: security ? "prompt guard and tool telemetry hooks installed" : "session start, backup, capture and limit hooks installed" };
60
+ }
61
+ catch {
62
+ return { status: "fail", detail: "invalid Copilot hook configuration" };
63
+ }
64
+ }
@@ -3,12 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeCursorHookInput = normalizeCursorHookInput;
4
4
  exports.normalizeCursorTranscript = normalizeCursorTranscript;
5
5
  exports.isCursorTranscriptEmpty = isCursorTranscriptEmpty;
6
- exports.cursorPreToolBlockResponse = cursorPreToolBlockResponse;
7
- exports.cursorPromptBlockResponse = cursorPromptBlockResponse;
8
- /** Cursor's native hook payload is close to Claude Code's, but its stable
9
- * conversation identifier and several tool fields use different names. Keep
10
- * the translation at the process boundary so the shared capture/security
11
- * pipeline never has to guess which surface produced an event. */
6
+ exports.cursorTranscriptHasUsage = cursorTranscriptHasUsage;
7
+ exports.cursorObservedModel = cursorObservedModel;
12
8
  function normalizeCursorHookInput(input) {
13
9
  const sessionId = firstString(input.session_id, input.sessionId, input.conversation_id);
14
10
  const roots = Array.isArray(input.workspace_roots)
@@ -29,9 +25,6 @@ function normalizeCursorHookInput(input) {
29
25
  ...(duration !== undefined ? { duration_ms: duration } : {}),
30
26
  };
31
27
  }
32
- /** Cursor stores JSONL message roles in `role`; the shared capture pipeline
33
- * uses Claude's top-level `type` discriminator. Preserve all original fields
34
- * and add only that discriminator so the existing parsers see real messages. */
35
28
  function normalizeCursorTranscript(content) {
36
29
  return content
37
30
  .split("\n")
@@ -40,23 +33,27 @@ function normalizeCursorTranscript(content) {
40
33
  return line;
41
34
  try {
42
35
  const entry = JSON.parse(line);
43
- if ((entry.role === "user" || entry.role === "assistant") &&
44
- entry.type === undefined) {
45
- return JSON.stringify({ ...entry, type: entry.role });
46
- }
36
+ const type = entry.type ?? entry.role;
37
+ if (type !== "user" && type !== "assistant")
38
+ return line;
39
+ const message = entry.message;
40
+ const content = Array.isArray(message?.content) ? message.content.map((block) => {
41
+ if (!block || block.type !== "tool_use")
42
+ return block;
43
+ const input = block.input ?? {};
44
+ const name = block.name === "Shell" ? "Bash" : block.name === "StrReplace" ? "Edit" : block.name;
45
+ return { ...block, name, input: { ...input,
46
+ ...(typeof input.path === "string" && input.file_path === undefined ? { file_path: input.path } : {}),
47
+ } };
48
+ }) : message?.content;
49
+ return JSON.stringify({ ...entry, type, ...(message ? { message: { ...message, content } } : {}) });
47
50
  }
48
51
  catch {
49
- // Preserve malformed/non-JSON lines; tolerant downstream parsers skip
50
- // anything they cannot consume.
51
52
  }
52
53
  return line;
53
54
  })
54
55
  .join("\n");
55
56
  }
56
- /** Cursor may change its private JSONL record shape independently of the hook
57
- * contract. Only a byte-empty snapshot is safe to discard; a non-empty file
58
- * that the current normalizer cannot parse must still be uploaded for backend
59
- * recovery and diagnosis. */
60
57
  function isCursorTranscriptEmpty(content) {
61
58
  return content.trim().length === 0;
62
59
  }
@@ -66,16 +63,27 @@ function firstString(...values) {
66
63
  function firstNumber(...values) {
67
64
  return values.find((value) => typeof value === "number" && Number.isFinite(value));
68
65
  }
69
- function cursorPreToolBlockResponse(reason) {
70
- return {
71
- permission: "deny",
72
- user_message: reason,
73
- agent_message: reason,
74
- };
66
+ function cursorTranscriptHasUsage(content) {
67
+ return content.split("\n").some((line) => {
68
+ try {
69
+ const usage = JSON.parse(line).message?.usage;
70
+ return usage && ["input_tokens", "output_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"]
71
+ .some((key) => typeof usage[key] === "number" && Number.isFinite(usage[key]));
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ });
75
77
  }
76
- function cursorPromptBlockResponse(reason) {
77
- return {
78
- continue: false,
79
- user_message: reason,
80
- };
78
+ function cursorObservedModel(content) {
79
+ let model;
80
+ for (const line of content.split("\n")) {
81
+ try {
82
+ const event = JSON.parse(line);
83
+ if (event.subtype === "cursor_model" && typeof event.model === "string")
84
+ model = event.model;
85
+ }
86
+ catch { }
87
+ }
88
+ return model;
81
89
  }
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.recordCursorLifecycle = recordCursorLifecycle;
37
+ exports.cursorLifecycleRecords = cursorLifecycleRecords;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const crypto = __importStar(require("crypto"));
41
+ const configDir_1 = require("./configDir");
42
+ const limitEvent_1 = require("./limitEvent");
43
+ function fileFor(sessionId) {
44
+ const key = crypto.createHash("sha256").update(sessionId).digest("hex");
45
+ return path.join((0, configDir_1.codiedevStateDir)(), "cursor-lifecycle", `${key}.json`);
46
+ }
47
+ function recordCursorLifecycle(input, final) {
48
+ if (typeof input.session_id !== "string")
49
+ return;
50
+ const status = input.status ?? input.reason;
51
+ const file = fileFor(input.session_id);
52
+ let state = { ids: [] };
53
+ try {
54
+ state = JSON.parse(fs.readFileSync(file, "utf8"));
55
+ }
56
+ catch { }
57
+ const model = typeof input.model_id === "string" && input.model_id.trim() ? input.model_id
58
+ : typeof input.model === "string" && input.model.trim() ? input.model : undefined;
59
+ if (model)
60
+ state.model = model;
61
+ const event = typeof input.hook_event_name === "string" ? input.hook_event_name : final ? "sessionEnd" : "stop";
62
+ if (event !== "sessionEnd" || !state.observations?.length) {
63
+ const timestamp = new Date().toISOString();
64
+ state.observations = [...(state.observations ?? []), { event, timestamp, ...(model ? { model } : {}) }].slice(-1000);
65
+ }
66
+ const limit = event === "postToolUse" || event === "postToolUseFailure" ? null : (0, limitEvent_1.parseNativeLimitError)(input);
67
+ if (limit) {
68
+ const generationId = typeof input.generation_id === "string" ? input.generation_id : undefined;
69
+ const last = state.limits?.at(-1);
70
+ const retry = last && (generationId ? last.generationId === generationId
71
+ : final && state.lastStatus === "error" && last.reason === limit.reason && last.resetText === limit.resetText);
72
+ if (!retry)
73
+ state.limits = [...(state.limits ?? []), { ...limit, ...(generationId ? { generationId } : {}) }].slice(-1000);
74
+ }
75
+ if (event === "subagentStart" && typeof input.subagent_id === "string") {
76
+ state.subagents = [...new Set([...(state.subagents ?? []), input.subagent_id])].slice(-1000);
77
+ }
78
+ if (event === "postToolUseFailure" && input.failure_type === "permission_denied") {
79
+ const rejectionId = typeof input.tool_use_id === "string" ? input.tool_use_id : `${Date.now()}-${state.rejections?.length ?? 0}`;
80
+ state.rejections = [...new Set([...(state.rejections ?? []), rejectionId])].slice(-1000);
81
+ }
82
+ const aborted = status === "aborted" || input.is_interrupt === true;
83
+ const id = typeof input.generation_id === "string" ? input.generation_id
84
+ : `${Date.now()}-${state.ids.length}`;
85
+ if (aborted && !(final && state.lastStatus === "aborted") && !state.ids.includes(id))
86
+ state.ids.push(id);
87
+ if (typeof status === "string")
88
+ state.lastStatus = status;
89
+ state.ids = state.ids.slice(-1000);
90
+ fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
91
+ fs.writeFileSync(file, JSON.stringify(state), { mode: 0o600 });
92
+ }
93
+ function cursorLifecycleRecords(sessionId) {
94
+ if (!sessionId)
95
+ return "";
96
+ try {
97
+ const state = JSON.parse(fs.readFileSync(fileFor(sessionId), "utf8"));
98
+ return [...(state.observations ?? []).map((observation) => JSON.stringify({ type: "system", subtype: "cursor_hook_observation", ...observation })),
99
+ ...(state.model ? [JSON.stringify({ type: "system", subtype: "cursor_model", model: state.model })] : []),
100
+ ...(state.rejections ?? []).map(id => JSON.stringify({ type: "agent.rejection", id })),
101
+ ...(state.subagents?.length ? [JSON.stringify({ type: "cursor.subagent_summary", count: state.subagents.length, truncated: state.subagents.length >= 1000 })] : []),
102
+ ...state.ids.map((id) => JSON.stringify({ type: "agent.interruption", id })),
103
+ ...(state.limits ?? []).map(({ generationId: _generationId, ...event }) => JSON.stringify({ type: "agent.limit", ...event })),
104
+ ].join("\n");
105
+ }
106
+ catch {
107
+ return "";
108
+ }
109
+ }