@bli-cockpit/cli 0.1.8 → 0.1.11

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/dist/upload.js CHANGED
@@ -1,4 +1,4 @@
1
- import { TelemetryIngestEnvelopeSchema, TelemetryIngestEventDtoSchema, } from "@bli-cockpit/telemetry-core";
1
+ import { AgentImageArtifactReportRequestSchema, TelemetryIngestEnvelopeSchema, TelemetryIngestEventDtoSchema, } from "@bli-cockpit/telemetry-core";
2
2
  import path from "node:path";
3
3
  import { getCollectorRuntimePaths, LOCAL_COLLECTOR_VERSION, readLocalCollectorConfig, readLocalCollectorSessionFile, readLocalSessionReference, readLocalWorkContextForRepo, } from "./local-state.js";
4
4
  import { runLocalSourceCollectors } from "./adapters/local-sources.js";
@@ -138,8 +138,8 @@ export async function syncLocalAmbientEnvelope(options = {}) {
138
138
  throw new Error("global fetch is unavailable; use Node.js 20 or newer.");
139
139
  }
140
140
  const provenance = built.envelope.work_context.provenance;
141
- if (built.raw_evidence_upload_files.length > 0 && !provenance) {
142
- throw new Error("Raw evidence upload requires collector provenance.");
141
+ if (!provenance) {
142
+ throw new Error("Ambient upload requires collector provenance.");
143
143
  }
144
144
  let uploadOutcomes = [];
145
145
  let uploadedChunkCount = 0;
@@ -185,6 +185,23 @@ export async function syncLocalAmbientEnvelope(options = {}) {
185
185
  }
186
186
  cursor.updated_at = attemptedAt;
187
187
  await writeRawEvidenceCursor(paths, cursor);
188
+ await reportAgentImageArtifacts({
189
+ fetchImpl,
190
+ dashboardUrl: built.dashboard_url,
191
+ deviceToken: built.device_token,
192
+ provenance,
193
+ generatedAt: built.envelope.generated_at,
194
+ ticketId: built.ticket_id,
195
+ repoFingerprint: built.envelope.work_context.repo_fingerprint,
196
+ worktreeFingerprint: built.envelope.work_context.worktree_fingerprint,
197
+ outcomes: uploadOutcomes,
198
+ reused: built.raw_evidence_facts?.reused ?? [],
199
+ cursorObjects: cursor.objects,
200
+ }).catch(() => ({
201
+ posted: false,
202
+ reason: "agent_artifact_report_local_error",
203
+ recorded_count: 0,
204
+ }));
188
205
  await recordUploadSuccess(paths, { attemptedAt });
189
206
  return {
190
207
  status: "uploaded",
@@ -330,6 +347,132 @@ export async function reportCodexSessionAttributions(options) {
330
347
  return { posted: false, reason: "report_network_error" };
331
348
  }
332
349
  }
350
+ export async function reportAgentImageArtifacts(options) {
351
+ const artifacts = agentArtifactsFromEvidence(options);
352
+ if (artifacts.length === 0) {
353
+ return {
354
+ posted: false,
355
+ reason: "no_agent_image_artifacts",
356
+ recorded_count: 0,
357
+ };
358
+ }
359
+ const payload = AgentImageArtifactReportRequestSchema.parse({
360
+ schema_version: "ambient-agent-image-artifacts.v1",
361
+ generated_at: options.generatedAt,
362
+ provenance: options.provenance,
363
+ artifacts,
364
+ });
365
+ try {
366
+ const response = await options.fetchImpl(`${options.dashboardUrl}/api/ambient/agent-artifacts`, {
367
+ method: "POST",
368
+ headers: {
369
+ "Authorization": `Bearer ${options.deviceToken}`,
370
+ "Content-Type": "application/json",
371
+ },
372
+ body: JSON.stringify(payload),
373
+ });
374
+ if (response.status === 404) {
375
+ return {
376
+ posted: false,
377
+ reason: "agent_artifact_api_unavailable",
378
+ recorded_count: 0,
379
+ };
380
+ }
381
+ if (!response.ok) {
382
+ return {
383
+ posted: false,
384
+ reason: `report_failed_http_${response.status}`,
385
+ recorded_count: 0,
386
+ };
387
+ }
388
+ const body = await readResponseJson(response);
389
+ const recordedCount = body && typeof body === "object"
390
+ ? Number(body.recorded_count ?? 0)
391
+ : 0;
392
+ return {
393
+ posted: true,
394
+ reason: "recorded",
395
+ recorded_count: Number.isFinite(recordedCount) ? recordedCount : 0,
396
+ };
397
+ }
398
+ catch {
399
+ return { posted: false, reason: "report_network_error", recorded_count: 0 };
400
+ }
401
+ }
402
+ function agentArtifactsFromEvidence(options) {
403
+ const byPointerId = new Map();
404
+ for (const outcome of options.outcomes) {
405
+ if (outcome.upload_state === "upload_failed" || !outcome.artifact_metadata) {
406
+ continue;
407
+ }
408
+ const artifact = agentArtifactFromMetadata({
409
+ metadata: outcome.artifact_metadata,
410
+ rawEvidencePointerId: outcome.pointer.raw_evidence_pointer_id,
411
+ objectKey: outcome.object_key,
412
+ ticketId: options.ticketId,
413
+ repoFingerprint: options.repoFingerprint,
414
+ worktreeFingerprint: options.worktreeFingerprint,
415
+ uploadState: outcome.upload_state,
416
+ });
417
+ byPointerId.set(artifact.raw_evidence_pointer_id, artifact);
418
+ }
419
+ for (const entry of options.reused) {
420
+ if (!entry.artifact_metadata)
421
+ continue;
422
+ const objectKey = options.cursorObjects[entry.content_hash_sha256]?.object_key;
423
+ if (!objectKey)
424
+ continue;
425
+ const artifact = agentArtifactFromMetadata({
426
+ metadata: entry.artifact_metadata,
427
+ rawEvidencePointerId: objectKey,
428
+ objectKey,
429
+ ticketId: options.ticketId,
430
+ repoFingerprint: options.repoFingerprint,
431
+ worktreeFingerprint: options.worktreeFingerprint,
432
+ uploadState: "reused_existing",
433
+ });
434
+ byPointerId.set(artifact.raw_evidence_pointer_id, artifact);
435
+ }
436
+ return [...byPointerId.values()];
437
+ }
438
+ function agentArtifactFromMetadata(options) {
439
+ return {
440
+ raw_evidence_pointer_id: options.rawEvidencePointerId,
441
+ agent_source: options.metadata.agent_source,
442
+ source_session_id: options.metadata.source_session_id,
443
+ ...(options.metadata.source_message_id
444
+ ? { source_message_id: options.metadata.source_message_id }
445
+ : {}),
446
+ ...(options.metadata.turn_index !== undefined
447
+ ? { turn_index: options.metadata.turn_index }
448
+ : {}),
449
+ occurred_at: options.metadata.occurred_at,
450
+ artifact_kind: options.metadata.artifact_kind,
451
+ capture_origin: "agent_session_attachment",
452
+ ...(options.ticketId ? { ticket_id: options.ticketId } : {}),
453
+ ...(options.repoFingerprint
454
+ ? { repo_fingerprint: options.repoFingerprint }
455
+ : {}),
456
+ ...(options.worktreeFingerprint
457
+ ? { worktree_fingerprint: options.worktreeFingerprint }
458
+ : {}),
459
+ storage_bucket: "ambient-raw-evidence",
460
+ object_key: options.objectKey,
461
+ content_hash_sha256: options.metadata.content_hash_sha256,
462
+ byte_size: options.metadata.byte_size,
463
+ media_type: options.metadata.media_type,
464
+ width: options.metadata.width,
465
+ height: options.metadata.height,
466
+ redaction_status: "not_started",
467
+ ocr_status: "not_started",
468
+ labels: {
469
+ collector_upload_state: options.uploadState,
470
+ ...(options.metadata.source_sidecar_id
471
+ ? { source_sidecar_id: options.metadata.source_sidecar_id }
472
+ : {}),
473
+ },
474
+ };
475
+ }
333
476
  function rawEvidenceSummary(built, outcomes, uploadedChunkCount, cursor) {
334
477
  const cursorReused = built.raw_evidence_facts?.reused ?? [];
335
478
  const serverReusedCount = outcomes.filter((outcome) => outcome.upload_state === "reused_existing").length;
@@ -339,6 +482,9 @@ function rawEvidenceSummary(built, outcomes, uploadedChunkCount, cursor) {
339
482
  raw_evidence_pointer_id: cursor.objects[entry.content_hash_sha256]?.object_key ?? "",
340
483
  kind: entry.kind,
341
484
  codex_session_id: entry.codex_session_id,
485
+ ...(entry.artifact_metadata
486
+ ? { artifact_metadata: entry.artifact_metadata }
487
+ : {}),
342
488
  upload_state: "reused_existing",
343
489
  reason: "cursor_content_match",
344
490
  }));
@@ -357,6 +503,9 @@ function rawEvidenceSummary(built, outcomes, uploadedChunkCount, cursor) {
357
503
  raw_evidence_pointer_id: outcome.pointer.raw_evidence_pointer_id,
358
504
  kind: outcome.kind,
359
505
  codex_session_id: outcome.codex_session_id,
506
+ ...(outcome.artifact_metadata
507
+ ? { artifact_metadata: outcome.artifact_metadata }
508
+ : {}),
360
509
  upload_state: outcome.upload_state,
361
510
  reason: outcome.reason,
362
511
  })),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bli-cockpit/cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.11",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -26,6 +26,6 @@
26
26
  "test": "node dist/cli.js --help && node ../../scripts/assert-public-package-pack.mjs --workspace=@bli-cockpit/cli"
27
27
  },
28
28
  "dependencies": {
29
- "@bli-cockpit/telemetry-core": "0.1.4"
29
+ "@bli-cockpit/telemetry-core": "0.1.5"
30
30
  }
31
31
  }