@agent-finops/core 0.5.8 → 0.6.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.
- package/README.md +6 -0
- package/dist/agentInventory.d.ts +11 -14
- package/dist/agentInventory.js +180 -46
- package/dist/analyze.js +165 -113
- package/dist/contextHealth.d.ts +10 -1
- package/dist/contextHealth.js +216 -44
- package/dist/cutList.d.ts +9 -3
- package/dist/cutList.js +99 -41
- package/dist/deadContext.d.ts +8 -4
- package/dist/deadContext.js +83 -26
- package/dist/discovery.d.ts +6 -2
- package/dist/discovery.js +36 -14
- package/dist/glance.d.ts +9 -2
- package/dist/glance.js +107 -24
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/insights.js +53 -30
- package/dist/localAgentLogs.d.ts +80 -2
- package/dist/localAgentLogs.js +480 -88
- package/dist/modelPricing.js +0 -1
- package/dist/providerConnectors.d.ts +3 -2
- package/dist/providerConnectors.js +673 -89
- package/dist/sampleData.js +32 -4
- package/dist/schema.d.ts +105 -27
- package/dist/schema.js +110 -2
- package/dist/sourceRegistry.d.ts +30 -5
- package/dist/sourceRegistry.js +250 -21
- package/dist/sourceStatus.d.ts +65 -0
- package/dist/sourceStatus.js +147 -0
- package/dist/stateTrust.d.ts +37 -0
- package/dist/stateTrust.js +277 -0
- package/dist/toolInvocations.d.ts +47 -18
- package/dist/toolInvocations.js +200 -48
- package/package.json +1 -1
- package/samples/anthropic-usage.csv +4 -4
- package/samples/openai-usage.csv +7 -7
package/dist/toolInvocations.js
CHANGED
|
@@ -36,10 +36,12 @@ export function parseClaudeCodeInvocations(content, sinceMs) {
|
|
|
36
36
|
if (timestamp && (!lastActivityAt || timestamp > lastActivityAt)) {
|
|
37
37
|
lastActivityAt = timestamp;
|
|
38
38
|
}
|
|
39
|
-
//
|
|
39
|
+
// A selected window requires dated evidence. Undated lines cannot prove an
|
|
40
|
+
// invocation occurred inside that window and must not create removal-safe
|
|
41
|
+
// coverage by accident.
|
|
40
42
|
if (typeof sinceMs === "number") {
|
|
41
43
|
const ts = Date.parse(stringOf(entry.timestamp) ?? "");
|
|
42
|
-
if (Number.isFinite(ts)
|
|
44
|
+
if (!Number.isFinite(ts) || ts < sinceMs)
|
|
43
45
|
continue;
|
|
44
46
|
}
|
|
45
47
|
if (isClaudeCompactionEntry(entry))
|
|
@@ -114,6 +116,27 @@ export function parseClaudeCodeInvocations(content, sinceMs) {
|
|
|
114
116
|
}
|
|
115
117
|
/** Parse ONE Codex rollout's tool/skill/subagent invocations. */
|
|
116
118
|
export function parseCodexInvocations(content, sinceMs) {
|
|
119
|
+
const collector = createCodexInvocationCollector(sinceMs);
|
|
120
|
+
for (const line of content.split("\n")) {
|
|
121
|
+
if (!line.trim())
|
|
122
|
+
continue;
|
|
123
|
+
let entry;
|
|
124
|
+
try {
|
|
125
|
+
entry = JSON.parse(line);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (isRecord(entry))
|
|
131
|
+
collector.consume(entry);
|
|
132
|
+
}
|
|
133
|
+
return collector.finish();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Stateful Codex invocation parser used to share localAgentLogs' JSONL pass.
|
|
137
|
+
* One collector is created per rollout file and discarded after `finish()`.
|
|
138
|
+
*/
|
|
139
|
+
export function createCodexInvocationCollector(sinceMs) {
|
|
117
140
|
const counts = new Map();
|
|
118
141
|
const mcpTools = new Set();
|
|
119
142
|
const skills = new Set();
|
|
@@ -122,35 +145,70 @@ export function parseCodexInvocations(content, sinceMs) {
|
|
|
122
145
|
const fileReads = new Map();
|
|
123
146
|
let assistantTurns = 0;
|
|
124
147
|
let sessionId;
|
|
148
|
+
let rootSessionMetaSeen = false;
|
|
149
|
+
let rootStartedAtMs;
|
|
150
|
+
let rootTaskStarted = false;
|
|
125
151
|
let lastActivityAt;
|
|
126
152
|
let compactionEvents = 0;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
153
|
+
let isSubagent = false;
|
|
154
|
+
let parentSessionId;
|
|
155
|
+
const nestedSessions = new Map();
|
|
156
|
+
const resetObservedEvidence = () => {
|
|
157
|
+
counts.clear();
|
|
158
|
+
mcpTools.clear();
|
|
159
|
+
skills.clear();
|
|
160
|
+
subagents.clear();
|
|
161
|
+
commands.clear();
|
|
162
|
+
fileReads.clear();
|
|
163
|
+
assistantTurns = 0;
|
|
164
|
+
compactionEvents = 0;
|
|
165
|
+
};
|
|
166
|
+
const consume = (entry) => {
|
|
167
|
+
const payload = isRecord(entry.payload) ? entry.payload : undefined;
|
|
168
|
+
if (entry.type === "session_meta" && payload) {
|
|
169
|
+
const metadata = codexSessionMetadata(payload);
|
|
170
|
+
if (!rootSessionMetaSeen) {
|
|
171
|
+
// Forked rollouts can contain a complete parent history after the
|
|
172
|
+
// first line. Bind this file to its first/root metadata exactly once.
|
|
173
|
+
rootSessionMetaSeen = true;
|
|
174
|
+
sessionId = metadata.sessionId;
|
|
175
|
+
isSubagent = metadata.isSubagent;
|
|
176
|
+
parentSessionId = metadata.parentSessionId;
|
|
177
|
+
rootStartedAtMs = timestampMilliseconds(payload.timestamp ?? entry.timestamp);
|
|
178
|
+
}
|
|
179
|
+
else if (metadata.sessionId !== sessionId ||
|
|
180
|
+
metadata.parentSessionId !== parentSessionId ||
|
|
181
|
+
metadata.isSubagent !== isSubagent) {
|
|
182
|
+
const key = [
|
|
183
|
+
metadata.sessionId ?? "",
|
|
184
|
+
metadata.parentSessionId ?? "",
|
|
185
|
+
metadata.isSubagent ? "subagent" : "session"
|
|
186
|
+
].join("\u0000");
|
|
187
|
+
nestedSessions.set(key, metadata);
|
|
188
|
+
}
|
|
133
189
|
}
|
|
134
|
-
|
|
135
|
-
|
|
190
|
+
if (isSubagent &&
|
|
191
|
+
!rootTaskStarted &&
|
|
192
|
+
payload?.type === "task_started" &&
|
|
193
|
+
isRootSpecificTaskStart(payload.started_at, rootStartedAtMs)) {
|
|
194
|
+
// Everything before this boundary is inherited parent history copied
|
|
195
|
+
// into the fork. It is useful nested provenance, but it is not evidence
|
|
196
|
+
// that the child invoked those tools or incurred those compactions.
|
|
197
|
+
rootTaskStarted = true;
|
|
198
|
+
resetObservedEvidence();
|
|
199
|
+
lastActivityAt = stringOf(entry.timestamp) ?? lastActivityAt;
|
|
136
200
|
}
|
|
137
|
-
if (!isRecord(entry))
|
|
138
|
-
continue;
|
|
139
201
|
const timestampValue = stringOf(entry.timestamp);
|
|
140
202
|
if (timestampValue && (!lastActivityAt || timestampValue > lastActivityAt)) {
|
|
141
203
|
lastActivityAt = timestampValue;
|
|
142
204
|
}
|
|
143
205
|
if (typeof sinceMs === "number") {
|
|
144
206
|
const timestamp = Date.parse(stringOf(entry.timestamp) ?? "");
|
|
145
|
-
if (Number.isFinite(timestamp)
|
|
146
|
-
|
|
207
|
+
if (!Number.isFinite(timestamp) || timestamp < sinceMs)
|
|
208
|
+
return;
|
|
147
209
|
}
|
|
148
|
-
const payload = isRecord(entry.payload) ? entry.payload : undefined;
|
|
149
210
|
if (!payload)
|
|
150
|
-
|
|
151
|
-
if (entry.type === "session_meta") {
|
|
152
|
-
sessionId = stringOf(payload.id) ?? sessionId;
|
|
153
|
-
}
|
|
211
|
+
return;
|
|
154
212
|
// Codex writes both a top-level `compacted` entry and a separate
|
|
155
213
|
// `context_compacted` event for one compaction. Count only the former.
|
|
156
214
|
if (entry.type === "compacted")
|
|
@@ -158,7 +216,7 @@ export function parseCodexInvocations(content, sinceMs) {
|
|
|
158
216
|
// Codex emits one turn_context per model turn.
|
|
159
217
|
if (entry.type === "turn_context") {
|
|
160
218
|
assistantTurns += 1;
|
|
161
|
-
|
|
219
|
+
return;
|
|
162
220
|
}
|
|
163
221
|
if (payload.type === "message" && payload.role === "user") {
|
|
164
222
|
for (const text of codexTextValues(payload.content)) {
|
|
@@ -166,14 +224,14 @@ export function parseCodexInvocations(content, sinceMs) {
|
|
|
166
224
|
if (command)
|
|
167
225
|
commands.add(command);
|
|
168
226
|
}
|
|
169
|
-
|
|
227
|
+
return;
|
|
170
228
|
}
|
|
171
229
|
if (payload.type !== "function_call" && payload.type !== "custom_tool_call") {
|
|
172
|
-
|
|
230
|
+
return;
|
|
173
231
|
}
|
|
174
232
|
const name = stringOf(payload.name);
|
|
175
233
|
if (!name)
|
|
176
|
-
|
|
234
|
+
return;
|
|
177
235
|
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
178
236
|
const input = codexToolInput(payload);
|
|
179
237
|
if (name.startsWith("mcp__")) {
|
|
@@ -194,25 +252,35 @@ export function parseCodexInvocations(content, sinceMs) {
|
|
|
194
252
|
const file = input && explicitReadFile(name, input);
|
|
195
253
|
if (file)
|
|
196
254
|
fileReads.set(file, (fileReads.get(file) ?? 0) + 1);
|
|
197
|
-
}
|
|
198
|
-
return {
|
|
199
|
-
invocations: [...counts.entries()]
|
|
200
|
-
.map(([name, count]) => ({ name, count }))
|
|
201
|
-
.sort((left, right) => right.count - left.count || left.name.localeCompare(right.name)),
|
|
202
|
-
invokedMcpTools: [...mcpTools].sort(),
|
|
203
|
-
invokedSkills: [...skills].sort(),
|
|
204
|
-
invokedSubagents: [...subagents].sort(),
|
|
205
|
-
invokedCommands: [...commands].sort(),
|
|
206
|
-
assistantTurns,
|
|
207
|
-
contextSignal: buildSessionContextSignal({
|
|
208
|
-
agent: "codex",
|
|
209
|
-
sessionId,
|
|
210
|
-
lastActivityAt,
|
|
211
|
-
compactionEvents,
|
|
212
|
-
fileReads,
|
|
213
|
-
isSubagent: false
|
|
214
|
-
})
|
|
215
255
|
};
|
|
256
|
+
const finish = () => {
|
|
257
|
+
// Without a recognized root task boundary, an older-format child file is
|
|
258
|
+
// indistinguishable from copied parent history. Preserve nested metadata,
|
|
259
|
+
// but do not manufacture child invocation/turn coverage from it.
|
|
260
|
+
if (isSubagent && !rootTaskStarted)
|
|
261
|
+
resetObservedEvidence();
|
|
262
|
+
return {
|
|
263
|
+
invocations: [...counts.entries()]
|
|
264
|
+
.map(([name, count]) => ({ name, count }))
|
|
265
|
+
.sort((left, right) => right.count - left.count || left.name.localeCompare(right.name)),
|
|
266
|
+
invokedMcpTools: [...mcpTools].sort(),
|
|
267
|
+
invokedSkills: [...skills].sort(),
|
|
268
|
+
invokedSubagents: [...subagents].sort(),
|
|
269
|
+
invokedCommands: [...commands].sort(),
|
|
270
|
+
assistantTurns,
|
|
271
|
+
contextSignal: buildSessionContextSignal({
|
|
272
|
+
agent: "codex",
|
|
273
|
+
sessionId,
|
|
274
|
+
lastActivityAt,
|
|
275
|
+
compactionEvents,
|
|
276
|
+
fileReads,
|
|
277
|
+
isSubagent,
|
|
278
|
+
parentSessionId,
|
|
279
|
+
nestedSessions: [...nestedSessions.values()]
|
|
280
|
+
})
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
return { consume, finish };
|
|
216
284
|
}
|
|
217
285
|
/** Scan this machine's Claude Code + Codex transcripts and aggregate invocations. */
|
|
218
286
|
export async function loadToolInvocations(options = {}) {
|
|
@@ -227,6 +295,10 @@ export async function loadToolInvocations(options = {}) {
|
|
|
227
295
|
const commands = new Set();
|
|
228
296
|
const sessionTurnCounts = [];
|
|
229
297
|
const sessionSignals = [];
|
|
298
|
+
const hostEvidence = {
|
|
299
|
+
"claude-code": createHostInvocationAccumulator(),
|
|
300
|
+
codex: createHostInvocationAccumulator()
|
|
301
|
+
};
|
|
230
302
|
let sessions = 0;
|
|
231
303
|
let claudeCodeSessions = 0;
|
|
232
304
|
let codexSessions = 0;
|
|
@@ -234,11 +306,18 @@ export async function loadToolInvocations(options = {}) {
|
|
|
234
306
|
const content = await readFile(file, "utf8").catch(() => "");
|
|
235
307
|
if (!content)
|
|
236
308
|
continue;
|
|
309
|
+
const parsed = parseClaudeCodeInvocations(content, sinceMs);
|
|
310
|
+
// A transcript file is not coverage for the selected window merely
|
|
311
|
+
// because it exists on disk. Without an in-window assistant turn there
|
|
312
|
+
// was no opportunity to observe an invocation, so counting the file would
|
|
313
|
+
// manufacture configured-without-invocation findings from stale history.
|
|
314
|
+
if (parsed.assistantTurns === 0)
|
|
315
|
+
continue;
|
|
237
316
|
sessions += 1;
|
|
238
317
|
claudeCodeSessions += 1;
|
|
239
|
-
const parsed = parseClaudeCodeInvocations(content, sinceMs);
|
|
240
318
|
sessionTurnCounts.push(parsed.assistantTurns);
|
|
241
319
|
sessionSignals.push(parsed.contextSignal);
|
|
320
|
+
addHostInvocationEvidence(hostEvidence["claude-code"], parsed);
|
|
242
321
|
for (const { name, count } of parsed.invocations) {
|
|
243
322
|
counts.set(name, (counts.get(name) ?? 0) + count);
|
|
244
323
|
}
|
|
@@ -251,17 +330,26 @@ export async function loadToolInvocations(options = {}) {
|
|
|
251
330
|
for (const c of parsed.invokedCommands)
|
|
252
331
|
commands.add(c);
|
|
253
332
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
333
|
+
const codexInvocationFiles = options.codexInvocationFiles ?? await (async () => {
|
|
334
|
+
const parsedFiles = [];
|
|
335
|
+
for (const file of await listJsonlFiles(codexDir)) {
|
|
336
|
+
if (!file.split(/[\\/]/).pop()?.startsWith("rollout-"))
|
|
337
|
+
continue;
|
|
338
|
+
const content = await readFile(file, "utf8").catch(() => "");
|
|
339
|
+
if (!content)
|
|
340
|
+
continue;
|
|
341
|
+
parsedFiles.push(parseCodexInvocations(content, sinceMs));
|
|
342
|
+
}
|
|
343
|
+
return parsedFiles;
|
|
344
|
+
})();
|
|
345
|
+
for (const parsed of codexInvocationFiles) {
|
|
346
|
+
if (parsed.assistantTurns === 0)
|
|
259
347
|
continue;
|
|
260
348
|
sessions += 1;
|
|
261
349
|
codexSessions += 1;
|
|
262
|
-
const parsed = parseCodexInvocations(content, sinceMs);
|
|
263
350
|
sessionTurnCounts.push(parsed.assistantTurns);
|
|
264
351
|
sessionSignals.push(parsed.contextSignal);
|
|
352
|
+
addHostInvocationEvidence(hostEvidence.codex, parsed);
|
|
265
353
|
for (const { name, count } of parsed.invocations) {
|
|
266
354
|
counts.set(name, (counts.get(name) ?? 0) + count);
|
|
267
355
|
}
|
|
@@ -290,9 +378,40 @@ export async function loadToolInvocations(options = {}) {
|
|
|
290
378
|
claudeCode: claudeCodeSessions,
|
|
291
379
|
codex: codexSessions
|
|
292
380
|
},
|
|
381
|
+
byHost: {
|
|
382
|
+
"claude-code": finishHostInvocationEvidence(hostEvidence["claude-code"]),
|
|
383
|
+
codex: finishHostInvocationEvidence(hostEvidence.codex)
|
|
384
|
+
},
|
|
293
385
|
sessionSignals
|
|
294
386
|
};
|
|
295
387
|
}
|
|
388
|
+
function createHostInvocationAccumulator() {
|
|
389
|
+
return {
|
|
390
|
+
sessionTurnCounts: [],
|
|
391
|
+
mcpTools: new Set(),
|
|
392
|
+
skills: new Set(),
|
|
393
|
+
subagents: new Set(),
|
|
394
|
+
commands: new Set()
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function addHostInvocationEvidence(accumulator, parsed) {
|
|
398
|
+
accumulator.sessionTurnCounts.push(parsed.assistantTurns);
|
|
399
|
+
parsed.invokedMcpTools.forEach((value) => accumulator.mcpTools.add(value));
|
|
400
|
+
parsed.invokedSkills.forEach((value) => accumulator.skills.add(value));
|
|
401
|
+
parsed.invokedSubagents.forEach((value) => accumulator.subagents.add(value));
|
|
402
|
+
parsed.invokedCommands.forEach((value) => accumulator.commands.add(value));
|
|
403
|
+
}
|
|
404
|
+
function finishHostInvocationEvidence(accumulator) {
|
|
405
|
+
return {
|
|
406
|
+
sessions: accumulator.sessionTurnCounts.length,
|
|
407
|
+
totalAssistantTurns: accumulator.sessionTurnCounts.reduce((sum, count) => sum + count, 0),
|
|
408
|
+
sessionTurnCounts: accumulator.sessionTurnCounts,
|
|
409
|
+
invokedMcpTools: [...accumulator.mcpTools].sort(),
|
|
410
|
+
invokedSkills: [...accumulator.skills].sort(),
|
|
411
|
+
invokedSubagents: [...accumulator.subagents].sort(),
|
|
412
|
+
invokedCommands: [...accumulator.commands].sort()
|
|
413
|
+
};
|
|
414
|
+
}
|
|
296
415
|
/** Extract "/foo" slash-command names from a user entry's content. */
|
|
297
416
|
function slashCommandsFrom(entry) {
|
|
298
417
|
const message = isRecord(entry.message) ? entry.message : undefined;
|
|
@@ -417,9 +536,42 @@ function buildSessionContextSignal(input) {
|
|
|
417
536
|
repeatedFileReads: fileReads.filter((file) => file.count > 1),
|
|
418
537
|
isSubagent: input.isSubagent,
|
|
419
538
|
...(input.parentSessionId ? { parentSessionId: input.parentSessionId } : {}),
|
|
539
|
+
...(input.nestedSessions && input.nestedSessions.length > 0
|
|
540
|
+
? { nestedSessions: input.nestedSessions }
|
|
541
|
+
: {}),
|
|
420
542
|
readCoverage: "explicit_read_tools_only"
|
|
421
543
|
};
|
|
422
544
|
}
|
|
545
|
+
function codexSessionMetadata(payload) {
|
|
546
|
+
return {
|
|
547
|
+
...(stringOf(payload.id) ? { sessionId: stringOf(payload.id) } : {}),
|
|
548
|
+
isSubagent: stringOf(payload.thread_source) === "subagent" ||
|
|
549
|
+
isRecord(payload.source) && "subagent" in payload.source,
|
|
550
|
+
...(stringOf(payload.parent_thread_id)
|
|
551
|
+
? { parentSessionId: stringOf(payload.parent_thread_id) }
|
|
552
|
+
: {})
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
const ROOT_TASK_CLOCK_TOLERANCE_MS = 5_000;
|
|
556
|
+
function isRootSpecificTaskStart(value, rootStartedAtMs) {
|
|
557
|
+
const taskStartedAtMs = timestampMilliseconds(value);
|
|
558
|
+
return typeof rootStartedAtMs === "number" &&
|
|
559
|
+
typeof taskStartedAtMs === "number" &&
|
|
560
|
+
taskStartedAtMs >= rootStartedAtMs - ROOT_TASK_CLOCK_TOLERANCE_MS;
|
|
561
|
+
}
|
|
562
|
+
function timestampMilliseconds(value) {
|
|
563
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
564
|
+
return value < 1_000_000_000_000 ? value * 1_000 : value;
|
|
565
|
+
}
|
|
566
|
+
if (typeof value !== "string" || value.length === 0)
|
|
567
|
+
return undefined;
|
|
568
|
+
const numeric = Number(value);
|
|
569
|
+
if (Number.isFinite(numeric)) {
|
|
570
|
+
return numeric < 1_000_000_000_000 ? numeric * 1_000 : numeric;
|
|
571
|
+
}
|
|
572
|
+
const parsed = Date.parse(value);
|
|
573
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
574
|
+
}
|
|
423
575
|
function isRecord(value) {
|
|
424
576
|
return typeof value === "object" && value !== null;
|
|
425
577
|
}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
id,timestamp,source_id,source_name,provider,source_confidence,observed_from,model,input_tokens,output_tokens,amount_usd,cost_confidence,client_id,project_id,agent_id,user_id,workspace_id,api_key_id,operation
|
|
2
|
-
ant-001,2026-05-17T16:00:00.000Z,anthropic-sample,Anthropic sample export,anthropic,detected_unverified,sample_csv,claude-fable-5,90000,9000,8.00,detected_unverified,client-acme,project-support,agent-drafter,user-ops-lead,workspace-acme,anthropic-key-support,reply_draft
|
|
3
|
-
ant-002,2026-05-18T12:20:00.000Z,anthropic-sample,Anthropic sample export,anthropic,detected_unverified,sample_csv,claude-haiku-4-5,42000,5000,5.50,detected_unverified,client-acme,project-support,agent-drafter,user-support-rep,workspace-acme,anthropic-key-support,reply_draft
|
|
4
|
-
ant-003,2026-05-19T17:05:00.000Z,anthropic-sample,Anthropic sample export,anthropic,detected_unverified,sample_csv,claude-fable-5,140000,16000,16.90,detected_unverified,client-beta,project-research,agent-analyst,user-research-lead,workspace-beta,anthropic-key-research,research_summary
|
|
1
|
+
id,timestamp,source_id,source_name,provider,source_confidence,observed_from,model,input_tokens,output_tokens,amount_usd,cost_confidence,client_id,project_id,agent_id,user_id,workspace_id,api_key_id,provider_cost_type,operation,usage_granularity,stable_input_fingerprint,batch_eligible,downgrade_safe
|
|
2
|
+
ant-001,2026-05-17T16:00:00.000Z,anthropic-sample,Anthropic sample export,anthropic,detected_unverified,sample_csv,claude-fable-5,90000,9000,8.00,detected_unverified,client-acme,project-support,agent-drafter,user-ops-lead,workspace-acme,anthropic-key-support,sample_call,reply_draft,call,,false,true
|
|
3
|
+
ant-002,2026-05-18T12:20:00.000Z,anthropic-sample,Anthropic sample export,anthropic,detected_unverified,sample_csv,claude-haiku-4-5,42000,5000,5.50,detected_unverified,client-acme,project-support,agent-drafter,user-support-rep,workspace-acme,anthropic-key-support,sample_call,reply_draft,call,,false,true
|
|
4
|
+
ant-003,2026-05-19T17:05:00.000Z,anthropic-sample,Anthropic sample export,anthropic,detected_unverified,sample_csv,claude-fable-5,140000,16000,16.90,detected_unverified,client-beta,project-research,agent-analyst,user-research-lead,workspace-beta,anthropic-key-research,sample_call,research_summary,call,research-summary-anthropic-v1,true,true
|
package/samples/openai-usage.csv
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
id,timestamp,source_id,source_name,provider,source_confidence,observed_from,model,input_tokens,output_tokens,amount_usd,cost_confidence,client_id,project_id,agent_id,user_id,workspace_id,api_key_id,operation
|
|
2
|
-
oai-001,2026-05-17T10:00:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5,60000,7000,4.80,estimated,client-acme,project-support,agent-triage,user-ops-lead,workspace-acme,key-support,ticket_triage
|
|
3
|
-
oai-002,2026-05-17T13:30:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5-mini,32000,5000,2.70,estimated,client-acme,project-support,agent-triage,user-support-rep,workspace-acme,key-support,ticket_triage
|
|
4
|
-
oai-003,2026-05-18T09:10:00.000Z,openai-sample,OpenAI sample export,openai,
|
|
5
|
-
oai-004,2026-05-18T15:45:00.000Z,openai-sample,OpenAI sample export,openai,
|
|
6
|
-
oai-005,2026-05-19T11:15:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5,180000,14000,22.40,estimated,client-beta,project-research,agent-analyst,user-research-lead,workspace-beta,key-research,research_summary
|
|
7
|
-
oai-006,2026-05-19T14:40:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5,160000,12000,18.60,estimated,client-beta,project-research,agent-analyst,user-research-lead,workspace-beta,key-research,research_summary
|
|
1
|
+
id,timestamp,source_id,source_name,provider,source_confidence,observed_from,model,input_tokens,output_tokens,amount_usd,cost_confidence,client_id,project_id,agent_id,user_id,workspace_id,api_key_id,provider_cost_type,operation,usage_granularity,stable_input_fingerprint,batch_eligible,downgrade_safe
|
|
2
|
+
oai-001,2026-05-17T10:00:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5,60000,7000,4.80,estimated,client-acme,project-support,agent-triage,user-ops-lead,workspace-acme,key-support,sample_call,ticket_triage,call,,false,true
|
|
3
|
+
oai-002,2026-05-17T13:30:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5-mini,32000,5000,2.70,estimated,client-acme,project-support,agent-triage,user-support-rep,workspace-acme,key-support,sample_call,ticket_triage,call,,false,true
|
|
4
|
+
oai-003,2026-05-18T09:10:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5,70000,8500,6.10,estimated,client-beta,project-research,agent-analyst,user-research-lead,workspace-beta,key-research,sample_call,research_summary,call,research-summary-v1,true,true
|
|
5
|
+
oai-004,2026-05-18T15:45:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5-mini,24000,4200,2.00,estimated,client-acme,project-support,agent-triage,user-support-rep,workspace-acme,key-support,sample_call,ticket_triage,call,,false,true
|
|
6
|
+
oai-005,2026-05-19T11:15:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5,180000,14000,22.40,estimated,client-beta,project-research,agent-analyst,user-research-lead,workspace-beta,key-research,sample_call,research_summary,call,research-summary-v1,true,true
|
|
7
|
+
oai-006,2026-05-19T14:40:00.000Z,openai-sample,OpenAI sample export,openai,estimated,sample_csv,gpt-5.5,160000,12000,18.60,estimated,client-beta,project-research,agent-analyst,user-research-lead,workspace-beta,key-research,sample_call,research_summary,call,research-summary-v1,true,true
|