@company-semantics/contracts 80.0.0 → 81.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@company-semantics/contracts",
3
- "version": "80.0.0",
3
+ "version": "81.0.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
2
- export const SPEC_HASH = 'c2954b6d06a9' as const;
3
- export const SPEC_HASH_FULL = 'c2954b6d06a981632d4d61991aa61f16ee28485116ec66949fe08d64cbde4ceb' as const;
2
+ export const SPEC_HASH = '7e0656a03459' as const;
3
+ export const SPEC_HASH_FULL = '7e0656a03459e90e26051fe9aea403e95f0de11fea465f6a0f00ae5caf8b0aa7' as const;
@@ -7438,50 +7438,55 @@ export interface components {
7438
7438
  };
7439
7439
  OrgUsageResponse: {
7440
7440
  period: {
7441
+ /** Format: date-time */
7441
7442
  start: string;
7443
+ /** Format: date-time */
7442
7444
  end: string;
7445
+ timezone: string;
7443
7446
  };
7444
7447
  summary: {
7445
- executions: number;
7446
- totalCostUsd: string;
7447
- totalTokens: number;
7448
- avgDurationMs: number;
7449
- failureRate: number;
7448
+ requests: number;
7449
+ tokens: number;
7450
+ customerChargeMicros: string;
7450
7451
  };
7451
7452
  daily: {
7452
7453
  date: string;
7453
- executions: number;
7454
- totalCostUsd: string;
7455
- }[];
7456
- byProfile: {
7457
- profile: string;
7458
- executions: number;
7459
- percentOfTotal: number;
7460
- totalCostUsd: string;
7461
- avgDurationMs: number;
7462
- failureRate: number;
7454
+ requests: number;
7455
+ customerChargeMicros: string;
7463
7456
  }[];
7464
- byUser: {
7465
- userId: string;
7466
- email: string;
7467
- executions: number;
7468
- totalCostUsd: string;
7469
- totalTokens: number;
7470
- favoriteProfile: string;
7457
+ byFeature: {
7458
+ requests: number;
7459
+ tokens: number;
7460
+ customerChargeMicros: string;
7461
+ /** @enum {string} */
7462
+ feature: "chat" | "chat_title" | "ingest_summarize" | "ingest_embedding" | "company_md_extraction" | "org_chart_import" | "org_structure_inference" | "source_sync_discovery" | "source_sync_digest" | "source_sync_synthesis" | "comment_agent_reply" | "slack_mention_reply" | "structure_review_interpret" | "retrieval_embedding" | "company_md_embedding" | "meeting_embedding" | "unattributed";
7471
7463
  }[];
7472
7464
  byModel: {
7473
- model: string;
7465
+ requests: number;
7466
+ tokens: number;
7467
+ customerChargeMicros: string;
7474
7468
  provider: string;
7475
- totalTokens: number;
7476
- estimatedCostUsd: string;
7477
- requestCount: number;
7469
+ modelId: string;
7478
7470
  }[];
7479
- byFeature: {
7480
- feature: string;
7481
- totalTokens: number;
7482
- estimatedCostUsd: string;
7483
- requestCount: number;
7471
+ byUser: {
7472
+ requests: number;
7473
+ tokens: number;
7474
+ customerChargeMicros: string;
7475
+ userId: string;
7476
+ email: string | null;
7484
7477
  }[];
7478
+ chatRuns: {
7479
+ executions: number;
7480
+ avgDurationMs: number;
7481
+ failureRate: number;
7482
+ byProfile: {
7483
+ profile: string;
7484
+ executions: number;
7485
+ percentOfTotal: number;
7486
+ avgDurationMs: number;
7487
+ failureRate: number;
7488
+ }[];
7489
+ };
7485
7490
  };
7486
7491
  AccountDeletionEligibilityResponse: {
7487
7492
  eligible: boolean;
@@ -14812,7 +14817,6 @@ export interface operations {
14812
14817
  parameters: {
14813
14818
  query?: {
14814
14819
  period?: "current_month" | "last_30_days" | "last_7_days";
14815
- tz?: string;
14816
14820
  };
14817
14821
  header?: never;
14818
14822
  path: {
package/src/index.ts CHANGED
@@ -1298,15 +1298,10 @@ export type {
1298
1298
  ImpersonationSseEvent,
1299
1299
  } from "./impersonation-events";
1300
1300
 
1301
- // Usage tracking types (internal admin)
1302
- // @see PRD-00166 for design rationale
1301
+ // AI features (INV-AI-ATTRIBUTION) and the internal-admin telemetry usage types
1302
+ export { AI_FEATURES, AI_FEATURE_LABELS } from "./usage/features";
1303
1303
  export type {
1304
1304
  AiFeature,
1305
- UsageSummary,
1306
- DailyUsage,
1307
- UsageByModel,
1308
- UsageByFeature,
1309
- UsageByUser,
1310
1305
  // Unified usage types (PRD-00276/277)
1311
1306
  UnifiedUsageSummary,
1312
1307
  UnifiedDailyUsage,
package/src/org/README.md CHANGED
@@ -513,6 +513,7 @@ Shared type vocabulary for organization ownership, type classification, and tran
513
513
  - `decisions`
514
514
  - `identity`
515
515
  - `permissions`
516
+ - `usage`
516
517
 
517
518
  **External packages:**
518
519
 
@@ -12,7 +12,8 @@
12
12
  */
13
13
  import { z } from "zod";
14
14
  import { CursorPageSchema, IsoDateTime } from "../api/primitives";
15
- import { AI_PAUSE_REASONS } from "../billing/vocabulary";
15
+ import { AI_PAUSE_REASONS, MoneyMicrosSchema } from "../billing/vocabulary";
16
+ import { AI_FEATURES } from "../usage/features";
16
17
  import { OrgChartRoleSchema } from "../permissions/orgchart-roles";
17
18
  import { PositionRefSchema } from "../identity/position-ref";
18
19
  import {
@@ -1385,64 +1386,68 @@ export type AcknowledgeSystemEventResponse = z.infer<
1385
1386
 
1386
1387
  // ---------------------------------------------------------------------------
1387
1388
  // GET /api/orgs/:orgId/ai-usage
1388
- // Matches UnifiedUsageResponse from usage/types.ts
1389
+ //
1390
+ // INV-USAGE-LEDGER: every request, token and dollar here is read from the
1391
+ // settled billing ledger (`billing_usage_events`) — one row per billed provider
1392
+ // call, whatever feature made it. A `request` is one settled billable provider
1393
+ // invocation (retries and fallbacks are separate requests), every amount is
1394
+ // the customer charge in integer micro-USD, and `tokens` is input + output +
1395
+ // cache read + cache write (reasoning is a subset of output, never added).
1396
+ // `chatRuns` alone comes from runtime telemetry: duration and failure
1397
+ // diagnostics for chat turns, carrying no money.
1389
1398
  // ---------------------------------------------------------------------------
1390
1399
 
1391
- const UnifiedUsageSummarySchema = z.object({
1392
- executions: z.number(),
1393
- totalCostUsd: z.string(),
1394
- totalTokens: z.number(),
1395
- avgDurationMs: z.number(),
1396
- failureRate: z.number(),
1397
- });
1398
-
1399
- const UnifiedDailyUsageSchema = z.object({
1400
- date: z.string(),
1401
- executions: z.number(),
1402
- totalCostUsd: z.string(),
1400
+ const OrgAiUsageTotalsSchema = z.object({
1401
+ requests: z.number().int().min(0),
1402
+ tokens: z.number().int().min(0),
1403
+ customerChargeMicros: MoneyMicrosSchema,
1403
1404
  });
1404
1405
 
1405
- const UnifiedProfileUsageSchema = z.object({
1406
+ const OrgChatRunProfileSchema = z.object({
1406
1407
  profile: z.string(),
1407
- executions: z.number(),
1408
+ executions: z.number().int().min(0),
1408
1409
  percentOfTotal: z.number(),
1409
- totalCostUsd: z.string(),
1410
1410
  avgDurationMs: z.number(),
1411
1411
  failureRate: z.number(),
1412
1412
  });
1413
1413
 
1414
- const UnifiedUserUsageSchema = z.object({
1415
- userId: z.string(),
1416
- email: z.string(),
1417
- executions: z.number(),
1418
- totalCostUsd: z.string(),
1419
- totalTokens: z.number(),
1420
- favoriteProfile: z.string(),
1421
- });
1422
-
1423
- const UnifiedModelUsageSchema = z.object({
1424
- model: z.string(),
1425
- provider: z.string(),
1426
- totalTokens: z.number(),
1427
- estimatedCostUsd: z.string(),
1428
- requestCount: z.number(),
1429
- });
1430
-
1431
- const UnifiedFeatureUsageSchema = z.object({
1432
- feature: z.string(),
1433
- totalTokens: z.number(),
1434
- estimatedCostUsd: z.string(),
1435
- requestCount: z.number(),
1436
- });
1437
-
1438
1414
  export const OrgUsageResponseSchema = z.object({
1439
- period: z.object({ start: z.string(), end: z.string() }),
1440
- summary: UnifiedUsageSummarySchema,
1441
- daily: z.array(UnifiedDailyUsageSchema),
1442
- byProfile: z.array(UnifiedProfileUsageSchema),
1443
- byUser: z.array(UnifiedUserUsageSchema),
1444
- byModel: z.array(UnifiedModelUsageSchema),
1445
- byFeature: z.array(UnifiedFeatureUsageSchema),
1415
+ /** The org's billing window: `start`/`end` in UTC, days bucketed in `timezone`. */
1416
+ period: z.object({
1417
+ start: IsoDateTime,
1418
+ end: IsoDateTime,
1419
+ timezone: z.string(),
1420
+ }),
1421
+ summary: OrgAiUsageTotalsSchema,
1422
+ daily: z.array(
1423
+ z.object({
1424
+ date: z.string(),
1425
+ requests: z.number().int().min(0),
1426
+ customerChargeMicros: MoneyMicrosSchema,
1427
+ }),
1428
+ ),
1429
+ byFeature: z.array(
1430
+ OrgAiUsageTotalsSchema.extend({ feature: z.enum(AI_FEATURES) }),
1431
+ ),
1432
+ byModel: z.array(
1433
+ OrgAiUsageTotalsSchema.extend({
1434
+ provider: z.string(),
1435
+ modelId: z.string(),
1436
+ }),
1437
+ ),
1438
+ /** Attributed usage only: system work (no user) counts in the totals, not here. */
1439
+ byUser: z.array(
1440
+ OrgAiUsageTotalsSchema.extend({
1441
+ userId: z.string(),
1442
+ email: z.string().nullable(),
1443
+ }),
1444
+ ),
1445
+ chatRuns: z.object({
1446
+ executions: z.number().int().min(0),
1447
+ avgDurationMs: z.number(),
1448
+ failureRate: z.number(),
1449
+ byProfile: z.array(OrgChatRunProfileSchema),
1450
+ }),
1446
1451
  });
1447
1452
 
1448
1453
  export type OrgUsageResponse = z.infer<typeof OrgUsageResponseSchema>;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * AI features — what work caused a billed model call (INV-AI-ATTRIBUTION).
3
+ *
4
+ * The CANONICAL list is the backend's Postgres `ai_feature` enum; this mirror
5
+ * is checked against it by a backend type test in both directions, so a value
6
+ * added on one side without the other cannot typecheck. Order follows the
7
+ * enum's (append-only) order.
8
+ *
9
+ * `unattributed` is a failure-containment state, not an accepted feature: a
10
+ * production model call that reached the billing gate with no attribution.
11
+ */
12
+ export const AI_FEATURES = [
13
+ "chat",
14
+ "chat_title",
15
+ "ingest_summarize",
16
+ "ingest_embedding",
17
+ "company_md_extraction",
18
+ "org_chart_import",
19
+ "org_structure_inference",
20
+ "source_sync_discovery",
21
+ "source_sync_digest",
22
+ "source_sync_synthesis",
23
+ "comment_agent_reply",
24
+ "slack_mention_reply",
25
+ "structure_review_interpret",
26
+ "retrieval_embedding",
27
+ "company_md_embedding",
28
+ "meeting_embedding",
29
+ "unattributed",
30
+ ] as const;
31
+
32
+ export type AiFeature = (typeof AI_FEATURES)[number];
33
+
34
+ /**
35
+ * The one display name per feature, Sentence case. `satisfies` so a new
36
+ * feature cannot render as a raw enum value or go unlabeled.
37
+ */
38
+ export const AI_FEATURE_LABELS = {
39
+ chat: "Chat",
40
+ chat_title: "Chat titles",
41
+ ingest_summarize: "Slack summaries",
42
+ ingest_embedding: "Slack indexing",
43
+ company_md_extraction: "Document extraction",
44
+ org_chart_import: "Org chart import",
45
+ org_structure_inference: "Org structure analysis",
46
+ source_sync_discovery: "Google Drive search",
47
+ source_sync_digest: "Google Drive file reading",
48
+ source_sync_synthesis: "Google Drive drafting",
49
+ comment_agent_reply: "Comment replies",
50
+ slack_mention_reply: "Slack replies",
51
+ structure_review_interpret: "Org review answers",
52
+ retrieval_embedding: "Search queries",
53
+ company_md_embedding: "Document indexing",
54
+ meeting_embedding: "Meeting indexing",
55
+ unattributed: "Unattributed",
56
+ } as const satisfies Record<AiFeature, string>;
@@ -1,55 +1,12 @@
1
1
  /**
2
- * AI Usage Tracking Types (v1)
3
- * Internal admin usage visibility. Not org-facing in v1.
4
- * See PRD-00166 for design rationale and invariants.
2
+ * AI usage telemetry types — the internal-admin usage views (runtime
3
+ * executions). The org-facing AI usage page reads the billing ledger instead;
4
+ * its shape is `OrgUsageResponseSchema` in `org/schemas.ts` (INV-USAGE-LEDGER).
5
5
  */
6
6
 
7
- export type AiFeature =
8
- | "chat"
9
- | "chat_title"
10
- | "ingest_summarize"
11
- | "ingest_embedding"
12
- | "company_md_extraction";
7
+ import type { AiFeature } from "./features";
13
8
 
14
- export interface UsageSummary {
15
- totalTokens: number;
16
- totalInputTokens: number;
17
- totalOutputTokens: number;
18
- estimatedCostUsd: string;
19
- requestCount: number;
20
- periodStart: string; // UTC ISO8601
21
- periodEnd: string; // UTC ISO8601
22
- }
23
-
24
- export interface DailyUsage {
25
- date: string; // YYYY-MM-DD
26
- totalTokens: number;
27
- estimatedCostUsd: string;
28
- requestCount: number;
29
- }
30
-
31
- export interface UsageByModel {
32
- model: string;
33
- provider: string;
34
- totalTokens: number;
35
- estimatedCostUsd: string;
36
- requestCount: number;
37
- }
38
-
39
- export interface UsageByFeature {
40
- feature: AiFeature;
41
- totalTokens: number;
42
- estimatedCostUsd: string;
43
- requestCount: number;
44
- }
45
-
46
- export interface UsageByUser {
47
- userId: string;
48
- email: string;
49
- totalTokens: number;
50
- estimatedCostUsd: string;
51
- requestCount: number;
52
- }
9
+ export type { AiFeature };
53
10
 
54
11
  // ---------------------------------------------------------------------------
55
12
  // Unified Usage Response (PRD-00276/277)