@cat-factory/contracts 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.
Files changed (166) hide show
  1. package/LICENSE +21 -0
  2. package/dist/accounts.d.ts +103 -0
  3. package/dist/accounts.d.ts.map +1 -0
  4. package/dist/accounts.js +102 -0
  5. package/dist/accounts.js.map +1 -0
  6. package/dist/agent-config.d.ts +77 -0
  7. package/dist/agent-config.d.ts.map +1 -0
  8. package/dist/agent-config.js +78 -0
  9. package/dist/agent-config.js.map +1 -0
  10. package/dist/api-keys.d.ts +44 -0
  11. package/dist/api-keys.d.ts.map +1 -0
  12. package/dist/api-keys.js +49 -0
  13. package/dist/api-keys.js.map +1 -0
  14. package/dist/auth.d.ts +24 -0
  15. package/dist/auth.d.ts.map +1 -0
  16. package/dist/auth.js +15 -0
  17. package/dist/auth.js.map +1 -0
  18. package/dist/board-scan.d.ts +89 -0
  19. package/dist/board-scan.d.ts.map +1 -0
  20. package/dist/board-scan.js +122 -0
  21. package/dist/board-scan.js.map +1 -0
  22. package/dist/bootstrap.d.ts +168 -0
  23. package/dist/bootstrap.d.ts.map +1 -0
  24. package/dist/bootstrap.js +148 -0
  25. package/dist/bootstrap.js.map +1 -0
  26. package/dist/clarity.d.ts +75 -0
  27. package/dist/clarity.d.ts.map +1 -0
  28. package/dist/clarity.js +66 -0
  29. package/dist/clarity.js.map +1 -0
  30. package/dist/companion.d.ts +32 -0
  31. package/dist/companion.d.ts.map +1 -0
  32. package/dist/companion.js +43 -0
  33. package/dist/companion.js.map +1 -0
  34. package/dist/consensus.d.ts +195 -0
  35. package/dist/consensus.d.ts.map +1 -0
  36. package/dist/consensus.js +164 -0
  37. package/dist/consensus.js.map +1 -0
  38. package/dist/documents.d.ts +197 -0
  39. package/dist/documents.d.ts.map +1 -0
  40. package/dist/documents.js +161 -0
  41. package/dist/documents.js.map +1 -0
  42. package/dist/entities.d.ts +1691 -0
  43. package/dist/entities.d.ts.map +1 -0
  44. package/dist/entities.js +853 -0
  45. package/dist/entities.js.map +1 -0
  46. package/dist/environments.d.ts +426 -0
  47. package/dist/environments.d.ts.map +1 -0
  48. package/dist/environments.js +190 -0
  49. package/dist/environments.js.map +1 -0
  50. package/dist/events.d.ts +98 -0
  51. package/dist/events.d.ts.map +1 -0
  52. package/dist/events.js +2 -0
  53. package/dist/events.js.map +1 -0
  54. package/dist/fragment-library.d.ts +123 -0
  55. package/dist/fragment-library.d.ts.map +1 -0
  56. package/dist/fragment-library.js +88 -0
  57. package/dist/fragment-library.js.map +1 -0
  58. package/dist/github.d.ts +215 -0
  59. package/dist/github.d.ts.map +1 -0
  60. package/dist/github.js +204 -0
  61. package/dist/github.js.map +1 -0
  62. package/dist/index.d.ts +41 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +41 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/iteration-cap.d.ts +17 -0
  67. package/dist/iteration-cap.d.ts.map +1 -0
  68. package/dist/iteration-cap.js +25 -0
  69. package/dist/iteration-cap.js.map +1 -0
  70. package/dist/localModels.d.ts +54 -0
  71. package/dist/localModels.d.ts.map +1 -0
  72. package/dist/localModels.js +79 -0
  73. package/dist/localModels.js.map +1 -0
  74. package/dist/merge.d.ts +106 -0
  75. package/dist/merge.d.ts.map +1 -0
  76. package/dist/merge.js +129 -0
  77. package/dist/merge.js.map +1 -0
  78. package/dist/model-defaults.d.ts +23 -0
  79. package/dist/model-defaults.d.ts.map +1 -0
  80. package/dist/model-defaults.js +34 -0
  81. package/dist/model-defaults.js.map +1 -0
  82. package/dist/notifications.d.ts +136 -0
  83. package/dist/notifications.d.ts.map +1 -0
  84. package/dist/notifications.js +125 -0
  85. package/dist/notifications.js.map +1 -0
  86. package/dist/observability.d.ts +271 -0
  87. package/dist/observability.d.ts.map +1 -0
  88. package/dist/observability.js +152 -0
  89. package/dist/observability.js.map +1 -0
  90. package/dist/personal-subscriptions.d.ts +66 -0
  91. package/dist/personal-subscriptions.d.ts.map +1 -0
  92. package/dist/personal-subscriptions.js +70 -0
  93. package/dist/personal-subscriptions.js.map +1 -0
  94. package/dist/primitives.d.ts +57 -0
  95. package/dist/primitives.d.ts.map +1 -0
  96. package/dist/primitives.js +66 -0
  97. package/dist/primitives.js.map +1 -0
  98. package/dist/provisioning.d.ts +46 -0
  99. package/dist/provisioning.d.ts.map +1 -0
  100. package/dist/provisioning.js +107 -0
  101. package/dist/provisioning.js.map +1 -0
  102. package/dist/recurring.d.ts +117 -0
  103. package/dist/recurring.d.ts.map +1 -0
  104. package/dist/recurring.js +99 -0
  105. package/dist/recurring.js.map +1 -0
  106. package/dist/release.d.ts +60 -0
  107. package/dist/release.d.ts.map +1 -0
  108. package/dist/release.js +75 -0
  109. package/dist/release.js.map +1 -0
  110. package/dist/requests.d.ts +451 -0
  111. package/dist/requests.d.ts.map +1 -0
  112. package/dist/requests.js +231 -0
  113. package/dist/requests.js.map +1 -0
  114. package/dist/requirements.d.ts +127 -0
  115. package/dist/requirements.d.ts.map +1 -0
  116. package/dist/requirements.js +137 -0
  117. package/dist/requirements.js.map +1 -0
  118. package/dist/runners.d.ts +387 -0
  119. package/dist/runners.d.ts.map +1 -0
  120. package/dist/runners.js +117 -0
  121. package/dist/runners.js.map +1 -0
  122. package/dist/sandbox.d.ts +300 -0
  123. package/dist/sandbox.d.ts.map +1 -0
  124. package/dist/sandbox.js +243 -0
  125. package/dist/sandbox.js.map +1 -0
  126. package/dist/service-fragment-defaults.d.ts +16 -0
  127. package/dist/service-fragment-defaults.d.ts.map +1 -0
  128. package/dist/service-fragment-defaults.js +23 -0
  129. package/dist/service-fragment-defaults.js.map +1 -0
  130. package/dist/services.d.ts +81 -0
  131. package/dist/services.d.ts.map +1 -0
  132. package/dist/services.js +77 -0
  133. package/dist/services.js.map +1 -0
  134. package/dist/slack.d.ts +104 -0
  135. package/dist/slack.d.ts.map +1 -0
  136. package/dist/slack.js +98 -0
  137. package/dist/slack.js.map +1 -0
  138. package/dist/snapshot.d.ts +522 -0
  139. package/dist/snapshot.d.ts.map +1 -0
  140. package/dist/snapshot.js +104 -0
  141. package/dist/snapshot.js.map +1 -0
  142. package/dist/spec.d.ts +174 -0
  143. package/dist/spec.d.ts.map +1 -0
  144. package/dist/spec.js +173 -0
  145. package/dist/spec.js.map +1 -0
  146. package/dist/tasks.d.ts +150 -0
  147. package/dist/tasks.d.ts.map +1 -0
  148. package/dist/tasks.js +146 -0
  149. package/dist/tasks.js.map +1 -0
  150. package/dist/testing.d.ts +67 -0
  151. package/dist/testing.d.ts.map +1 -0
  152. package/dist/testing.js +64 -0
  153. package/dist/testing.js.map +1 -0
  154. package/dist/tracker.d.ts +18 -0
  155. package/dist/tracker.d.ts.map +1 -0
  156. package/dist/tracker.js +24 -0
  157. package/dist/tracker.js.map +1 -0
  158. package/dist/vendor-credentials.d.ts +37 -0
  159. package/dist/vendor-credentials.d.ts.map +1 -0
  160. package/dist/vendor-credentials.js +40 -0
  161. package/dist/vendor-credentials.js.map +1 -0
  162. package/dist/workspace-settings.d.ts +36 -0
  163. package/dist/workspace-settings.d.ts.map +1 -0
  164. package/dist/workspace-settings.js +41 -0
  165. package/dist/workspace-settings.js.map +1 -0
  166. package/package.json +31 -0
@@ -0,0 +1,125 @@
1
+ import * as v from 'valibot';
2
+ import { mergeAssessmentSchema } from './merge.js';
3
+ import { onCallAssessmentSchema, releaseSignalSchema } from './release.js';
4
+ // ---------------------------------------------------------------------------
5
+ // Notification wire contracts. A notification is a first-class, human-actionable
6
+ // item surfaced on the board that is NOT a mid-pipeline gate (those are
7
+ // Decisions / approval gates parked inside a running pipeline). Notifications
8
+ // outlive the run that raised them and are resolved out-of-band:
9
+ // - `merge_review` — a `merger` agent scored a PR outside the task's
10
+ // auto-merge thresholds; a human decides whether to merge.
11
+ // - `pipeline_complete`— a pipeline with no `merger` step finished; a human
12
+ // confirms the work as complete (and merges the PR).
13
+ // - `ci_failed` — the `ci-fixer` agent exhausted its attempt budget and
14
+ // CI is still red; a human takes over.
15
+ // - `test_failed` — the `fixer` agent exhausted its attempt budget (or there
16
+ // was no PR branch to fix) and the `tester` still withholds
17
+ // its greenlight; a human takes over.
18
+ // - `requirement_review`— a requirements-review agent raised findings on a task
19
+ // (gaps / clarifications / risks); product people + the
20
+ // task's creator are told to go react to them. Purely
21
+ // informational (no typed side-effect — `act` just marks
22
+ // it read), unlike the engineering notifications above.
23
+ // - `clarity_review` — a clarity-review (bug-report triage) agent raised findings
24
+ // on a bug task; same informational shape as `requirement_review`.
25
+ // - `release_regression`— the post-release-health gate detected a Datadog monitor/SLO
26
+ // regression after deploy and the `on-call` agent investigated;
27
+ // a human decides whether to revert the PR or acknowledge. Carries
28
+ // the on-call assessment + the regressed signals in its payload.
29
+ // - `decision_required`— an iterative gate parked on a human decision after spending
30
+ // its automatic budget (a quality companion at its rework cap,
31
+ // or the requirements reviewer at its iteration cap). Without
32
+ // this the three-choice decision is reachable only by drilling
33
+ // into the parked step, so the run looks silently stuck; acting
34
+ // on it opens that step's decision surface.
35
+ //
36
+ // In-app delivery is the only channel today, but the core models delivery behind
37
+ // a `NotificationChannel` port so email / Slack channels can be added later
38
+ // without touching the call sites that raise notifications.
39
+ // ---------------------------------------------------------------------------
40
+ /**
41
+ * The kind of human-actionable event a notification represents. A closed set so
42
+ * the frontend can switch on it to render the right action; extending it is a
43
+ * one-line change here plus a handler in the worker's `act` route.
44
+ */
45
+ export const notificationTypeSchema = v.picklist([
46
+ 'merge_review',
47
+ 'pipeline_complete',
48
+ 'ci_failed',
49
+ 'test_failed',
50
+ 'requirement_review',
51
+ 'clarity_review',
52
+ 'release_regression',
53
+ 'decision_required',
54
+ ]);
55
+ /**
56
+ * Lifecycle of a notification: `open` until a human engages, terminal `acted`
57
+ * once its action ran (merged, confirmed, retried…), or `dismissed` when waved
58
+ * off. Only `open` notifications surface on the board.
59
+ */
60
+ export const notificationStatusSchema = v.picklist(['open', 'acted', 'dismissed']);
61
+ /**
62
+ * How urgently a notification is rendered. A notification starts `normal` (the
63
+ * inbox's usual per-type color) and is escalated to `urgent` (red) by the periodic
64
+ * sweep once it has been waiting for a human longer than the workspace's
65
+ * `waitingEscalationMinutes` threshold. This is the run-timing signal that replaced
66
+ * the old hard "decision timeout" auto-fail: runs now wait indefinitely, and the
67
+ * notification colour — not a killed run — conveys that a human is overdue.
68
+ */
69
+ export const notificationSeveritySchema = v.picklist(['normal', 'urgent']);
70
+ /**
71
+ * Optional structured detail a notification carries for rendering its card —
72
+ * e.g. a `merge_review` carries the agent's assessment + the PR it concerns. Kept
73
+ * deliberately small and additive so new notification types can attach their own
74
+ * context without a schema migration.
75
+ */
76
+ export const notificationPayloadSchema = v.object({
77
+ /** The `merger` agent's assessment, on a `merge_review`. */
78
+ assessment: v.optional(mergeAssessmentSchema),
79
+ /** Web URL of the PR the notification concerns, when one is known. */
80
+ prUrl: v.optional(v.string()),
81
+ /** The pipeline run that raised it, for display ("from the Full build run"). */
82
+ pipelineName: v.optional(v.string()),
83
+ /** Number of open findings, on a `requirement_review`. */
84
+ findingCount: v.optional(v.number()),
85
+ /** The `on-call` agent's assessment, on a `release_regression`. */
86
+ onCallAssessment: v.optional(onCallAssessmentSchema),
87
+ /** The monitors/SLOs that regressed, on a `release_regression`. */
88
+ releaseSignals: v.optional(v.array(releaseSignalSchema)),
89
+ /** Web URL of a proposed revert PR the human can open/merge, when known. */
90
+ revertUrl: v.optional(v.string()),
91
+ /**
92
+ * Internal user id (`usr_*`) of the member this notification is directed at — the
93
+ * task's responsible product person on a `requirement_review`. The inbox highlights
94
+ * it as "for you"; the notification stays workspace-visible to everyone.
95
+ */
96
+ targetUserId: v.optional(v.nullable(v.string())),
97
+ });
98
+ /** A human-actionable item surfaced on the board. */
99
+ export const notificationSchema = v.object({
100
+ id: v.string(),
101
+ type: notificationTypeSchema,
102
+ status: notificationStatusSchema,
103
+ /**
104
+ * Render urgency (see {@link notificationSeveritySchema}). Absent ⇒ `normal`. Flipped
105
+ * to `urgent` by the escalation sweep once it has waited past the workspace threshold.
106
+ */
107
+ severity: v.optional(notificationSeveritySchema),
108
+ /** The block (task/frame) the notification is about; null for workspace-wide. */
109
+ blockId: v.nullable(v.string()),
110
+ /** The execution run that raised it, when applicable. */
111
+ executionId: v.nullable(v.string()),
112
+ /** Short headline shown on the card. */
113
+ title: v.string(),
114
+ /** Longer prose body / context. */
115
+ body: v.string(),
116
+ /** Optional structured detail for rendering (see {@link notificationPayloadSchema}). */
117
+ payload: v.optional(v.nullable(notificationPayloadSchema)),
118
+ createdAt: v.number(),
119
+ /** When it left `open` (acted/dismissed); null while open. */
120
+ resolvedAt: v.nullable(v.number()),
121
+ });
122
+ // ---- Request bodies -------------------------------------------------------
123
+ /** How a human resolved a notification from its card. */
124
+ export const resolveNotificationActionSchema = v.picklist(['act', 'dismiss']);
125
+ //# sourceMappingURL=notifications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,271 @@
1
+ import * as v from 'valibot';
2
+ /** One proxied LLM call, with its full prompt/response and timing breakdown. */
3
+ export declare const llmCallMetricSchema: v.ObjectSchema<{
4
+ readonly id: v.StringSchema<undefined>;
5
+ readonly workspaceId: v.StringSchema<undefined>;
6
+ readonly executionId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
7
+ readonly agentKind: v.StringSchema<undefined>;
8
+ readonly provider: v.StringSchema<undefined>;
9
+ readonly model: v.StringSchema<undefined>;
10
+ /** When the call completed (epoch ms). */
11
+ readonly createdAt: v.NumberSchema<undefined>;
12
+ readonly streaming: v.BooleanSchema<undefined>;
13
+ readonly messageCount: v.NumberSchema<undefined>;
14
+ /** Tools offered to the model (0 = the agent could not edit anything). */
15
+ readonly toolCount: v.NumberSchema<undefined>;
16
+ /** The `max_tokens` the request asked for (the output ceiling), or null. */
17
+ readonly requestMaxTokens: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
18
+ readonly promptTokens: v.NumberSchema<undefined>;
19
+ /** Prompt tokens served from the provider's prompt cache (subset of promptTokens). */
20
+ readonly cachedPromptTokens: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
21
+ readonly completionTokens: v.NumberSchema<undefined>;
22
+ readonly totalTokens: v.NumberSchema<undefined>;
23
+ /** Upstream finish reason (`stop` | `length` | `tool_calls` | `content_filter` | …). */
24
+ readonly finishReason: v.NullableSchema<v.StringSchema<undefined>, undefined>;
25
+ /** Time waiting on the model (ms) — the actual execution. */
26
+ readonly upstreamMs: v.NumberSchema<undefined>;
27
+ /** Transport/proxy overhead (ms). */
28
+ readonly overheadMs: v.NumberSchema<undefined>;
29
+ /** End-to-end time the proxy spent on the call (ms). */
30
+ readonly totalMs: v.NumberSchema<undefined>;
31
+ readonly ok: v.BooleanSchema<undefined>;
32
+ readonly httpStatus: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
33
+ readonly errorMessage: v.NullableSchema<v.StringSchema<undefined>, undefined>;
34
+ /**
35
+ * The request messages serialised as JSON, stored as a DELTA — only the messages
36
+ * this call appended beyond `promptPrefixCount` (the full array when that is 0).
37
+ * The export rebuilds the full prompt from a chain's deltas.
38
+ */
39
+ readonly promptText: v.StringSchema<undefined>;
40
+ /**
41
+ * Leading messages elided from `promptText` (stored by an earlier call in the same
42
+ * conversation). 0 ⇒ `promptText` is the full array. Optional/defaulted so exports
43
+ * predating delta storage still parse.
44
+ */
45
+ readonly promptPrefixCount: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
46
+ /** Hash of the call's full messages array (chain key for the next call's delta). */
47
+ readonly promptHash: v.OptionalSchema<v.StringSchema<undefined>, "">;
48
+ /** The full assistant response text. */
49
+ readonly responseText: v.StringSchema<undefined>;
50
+ /**
51
+ * The model's reasoning / "thinking" trace on a separate channel, when emitted
52
+ * (empty for non-reasoning models). Optional/defaulted so exports predating reasoning
53
+ * capture still parse.
54
+ */
55
+ readonly reasoningText: v.OptionalSchema<v.StringSchema<undefined>, "">;
56
+ }, undefined>;
57
+ export type LlmCallMetric = v.InferOutput<typeof llmCallMetricSchema>;
58
+ /**
59
+ * The compact per-call summary pushed live over the workspace event stream (the
60
+ * `llmCall` {@link WorkspaceEvent}). It is {@link llmCallMetricSchema} WITHOUT the
61
+ * heavy text bodies (`promptText`/`responseText`) and the delta bookkeeping
62
+ * (`promptPrefixCount`/`promptHash`), so a stalled-driver "is the agent still
63
+ * calling the model?" view updates in real time without shipping prompt bytes over
64
+ * the socket. The drill-down panel lazy-loads the full bodies for an expanded row
65
+ * from `GET /executions/:id/llm-metrics` (the persisted store), keyed by the shared
66
+ * call `id`.
67
+ */
68
+ export declare const llmCallActivitySchema: v.ObjectSchema<{
69
+ readonly id: v.StringSchema<undefined>;
70
+ readonly workspaceId: v.StringSchema<undefined>;
71
+ readonly executionId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
72
+ readonly agentKind: v.StringSchema<undefined>;
73
+ readonly provider: v.StringSchema<undefined>;
74
+ readonly model: v.StringSchema<undefined>;
75
+ readonly createdAt: v.NumberSchema<undefined>;
76
+ readonly streaming: v.BooleanSchema<undefined>;
77
+ readonly messageCount: v.NumberSchema<undefined>;
78
+ readonly toolCount: v.NumberSchema<undefined>;
79
+ readonly requestMaxTokens: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
80
+ readonly promptTokens: v.NumberSchema<undefined>;
81
+ readonly cachedPromptTokens: v.NumberSchema<undefined>;
82
+ readonly completionTokens: v.NumberSchema<undefined>;
83
+ readonly totalTokens: v.NumberSchema<undefined>;
84
+ readonly finishReason: v.NullableSchema<v.StringSchema<undefined>, undefined>;
85
+ readonly upstreamMs: v.NumberSchema<undefined>;
86
+ readonly overheadMs: v.NumberSchema<undefined>;
87
+ readonly totalMs: v.NumberSchema<undefined>;
88
+ readonly ok: v.BooleanSchema<undefined>;
89
+ readonly httpStatus: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
90
+ readonly errorMessage: v.NullableSchema<v.StringSchema<undefined>, undefined>;
91
+ }, undefined>;
92
+ export type LlmCallActivity = v.InferOutput<typeof llmCallActivitySchema>;
93
+ /** Response of `GET /workspaces/:ws/executions/:id/llm-metrics` (drill-down panel). */
94
+ export declare const llmMetricsResponseSchema: v.ObjectSchema<{
95
+ readonly executionId: v.StringSchema<undefined>;
96
+ readonly calls: v.ArraySchema<v.ObjectSchema<{
97
+ readonly id: v.StringSchema<undefined>;
98
+ readonly workspaceId: v.StringSchema<undefined>;
99
+ readonly executionId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
100
+ readonly agentKind: v.StringSchema<undefined>;
101
+ readonly provider: v.StringSchema<undefined>;
102
+ readonly model: v.StringSchema<undefined>;
103
+ /** When the call completed (epoch ms). */
104
+ readonly createdAt: v.NumberSchema<undefined>;
105
+ readonly streaming: v.BooleanSchema<undefined>;
106
+ readonly messageCount: v.NumberSchema<undefined>;
107
+ /** Tools offered to the model (0 = the agent could not edit anything). */
108
+ readonly toolCount: v.NumberSchema<undefined>;
109
+ /** The `max_tokens` the request asked for (the output ceiling), or null. */
110
+ readonly requestMaxTokens: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
111
+ readonly promptTokens: v.NumberSchema<undefined>;
112
+ /** Prompt tokens served from the provider's prompt cache (subset of promptTokens). */
113
+ readonly cachedPromptTokens: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
114
+ readonly completionTokens: v.NumberSchema<undefined>;
115
+ readonly totalTokens: v.NumberSchema<undefined>;
116
+ /** Upstream finish reason (`stop` | `length` | `tool_calls` | `content_filter` | …). */
117
+ readonly finishReason: v.NullableSchema<v.StringSchema<undefined>, undefined>;
118
+ /** Time waiting on the model (ms) — the actual execution. */
119
+ readonly upstreamMs: v.NumberSchema<undefined>;
120
+ /** Transport/proxy overhead (ms). */
121
+ readonly overheadMs: v.NumberSchema<undefined>;
122
+ /** End-to-end time the proxy spent on the call (ms). */
123
+ readonly totalMs: v.NumberSchema<undefined>;
124
+ readonly ok: v.BooleanSchema<undefined>;
125
+ readonly httpStatus: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
126
+ readonly errorMessage: v.NullableSchema<v.StringSchema<undefined>, undefined>;
127
+ /**
128
+ * The request messages serialised as JSON, stored as a DELTA — only the messages
129
+ * this call appended beyond `promptPrefixCount` (the full array when that is 0).
130
+ * The export rebuilds the full prompt from a chain's deltas.
131
+ */
132
+ readonly promptText: v.StringSchema<undefined>;
133
+ /**
134
+ * Leading messages elided from `promptText` (stored by an earlier call in the same
135
+ * conversation). 0 ⇒ `promptText` is the full array. Optional/defaulted so exports
136
+ * predating delta storage still parse.
137
+ */
138
+ readonly promptPrefixCount: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
139
+ /** Hash of the call's full messages array (chain key for the next call's delta). */
140
+ readonly promptHash: v.OptionalSchema<v.StringSchema<undefined>, "">;
141
+ /** The full assistant response text. */
142
+ readonly responseText: v.StringSchema<undefined>;
143
+ /**
144
+ * The model's reasoning / "thinking" trace on a separate channel, when emitted
145
+ * (empty for non-reasoning models). Optional/defaulted so exports predating reasoning
146
+ * capture still parse.
147
+ */
148
+ readonly reasoningText: v.OptionalSchema<v.StringSchema<undefined>, "">;
149
+ }, undefined>, undefined>;
150
+ }, undefined>;
151
+ export type LlmMetricsResponse = v.InferOutput<typeof llmMetricsResponseSchema>;
152
+ /**
153
+ * A single per-agent-kind insight in the LLM-friendly export: the same rollup the
154
+ * board step shows, plus derived ratios so an analysing model needs no arithmetic.
155
+ */
156
+ export declare const llmExportInsightSchema: v.ObjectSchema<{
157
+ readonly agentKind: v.StringSchema<undefined>;
158
+ readonly calls: v.NumberSchema<undefined>;
159
+ readonly promptTokens: v.NumberSchema<undefined>;
160
+ readonly completionTokens: v.NumberSchema<undefined>;
161
+ readonly peakCompletionTokens: v.NumberSchema<undefined>;
162
+ readonly maxOutputTokens: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
163
+ /** peakCompletionTokens / maxOutputTokens, 0..1; null when the ceiling is unknown. */
164
+ readonly outputHeadroomRatio: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
165
+ readonly truncatedCalls: v.NumberSchema<undefined>;
166
+ readonly upstreamMs: v.NumberSchema<undefined>;
167
+ readonly overheadMs: v.NumberSchema<undefined>;
168
+ /** overheadMs / (upstreamMs + overheadMs), 0..1; the share spent in transport. */
169
+ readonly transportOverheadRatio: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
170
+ readonly errors: v.NumberSchema<undefined>;
171
+ readonly warnings: v.NumberSchema<undefined>;
172
+ }, undefined>;
173
+ export type LlmExportInsight = v.InferOutput<typeof llmExportInsightSchema>;
174
+ /**
175
+ * LLM-friendly export of a run's model activity: a self-describing, structured JSON
176
+ * bundle (totals + per-agent insights + every call) intended to be handed straight
177
+ * to a model for analysis ("why did this run truncate / spend / stall?"). Field
178
+ * names and derived ratios are explicit so no external context is needed.
179
+ */
180
+ export declare const llmMetricsExportSchema: v.ObjectSchema<{
181
+ /** Schema marker so a consuming model knows the shape. */
182
+ readonly kind: v.LiteralSchema<"cat-factory.llm-metrics-export", undefined>;
183
+ readonly version: v.LiteralSchema<1, undefined>;
184
+ readonly executionId: v.StringSchema<undefined>;
185
+ readonly generatedAt: v.NumberSchema<undefined>;
186
+ readonly totals: v.ObjectSchema<{
187
+ readonly calls: v.NumberSchema<undefined>;
188
+ readonly promptTokens: v.NumberSchema<undefined>;
189
+ readonly completionTokens: v.NumberSchema<undefined>;
190
+ readonly upstreamMs: v.NumberSchema<undefined>;
191
+ readonly overheadMs: v.NumberSchema<undefined>;
192
+ /** Share of total latency spent in transport/proxy (0..1), or null with no timing. */
193
+ readonly transportOverheadRatio: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
194
+ readonly errors: v.NumberSchema<undefined>;
195
+ readonly warnings: v.NumberSchema<undefined>;
196
+ readonly truncatedCalls: v.NumberSchema<undefined>;
197
+ }, undefined>;
198
+ readonly insights: v.ArraySchema<v.ObjectSchema<{
199
+ readonly agentKind: v.StringSchema<undefined>;
200
+ readonly calls: v.NumberSchema<undefined>;
201
+ readonly promptTokens: v.NumberSchema<undefined>;
202
+ readonly completionTokens: v.NumberSchema<undefined>;
203
+ readonly peakCompletionTokens: v.NumberSchema<undefined>;
204
+ readonly maxOutputTokens: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
205
+ /** peakCompletionTokens / maxOutputTokens, 0..1; null when the ceiling is unknown. */
206
+ readonly outputHeadroomRatio: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
207
+ readonly truncatedCalls: v.NumberSchema<undefined>;
208
+ readonly upstreamMs: v.NumberSchema<undefined>;
209
+ readonly overheadMs: v.NumberSchema<undefined>;
210
+ /** overheadMs / (upstreamMs + overheadMs), 0..1; the share spent in transport. */
211
+ readonly transportOverheadRatio: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
212
+ readonly errors: v.NumberSchema<undefined>;
213
+ readonly warnings: v.NumberSchema<undefined>;
214
+ }, undefined>, undefined>;
215
+ readonly calls: v.ArraySchema<v.ObjectSchema<{
216
+ readonly id: v.StringSchema<undefined>;
217
+ readonly workspaceId: v.StringSchema<undefined>;
218
+ readonly executionId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
219
+ readonly agentKind: v.StringSchema<undefined>;
220
+ readonly provider: v.StringSchema<undefined>;
221
+ readonly model: v.StringSchema<undefined>;
222
+ /** When the call completed (epoch ms). */
223
+ readonly createdAt: v.NumberSchema<undefined>;
224
+ readonly streaming: v.BooleanSchema<undefined>;
225
+ readonly messageCount: v.NumberSchema<undefined>;
226
+ /** Tools offered to the model (0 = the agent could not edit anything). */
227
+ readonly toolCount: v.NumberSchema<undefined>;
228
+ /** The `max_tokens` the request asked for (the output ceiling), or null. */
229
+ readonly requestMaxTokens: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
230
+ readonly promptTokens: v.NumberSchema<undefined>;
231
+ /** Prompt tokens served from the provider's prompt cache (subset of promptTokens). */
232
+ readonly cachedPromptTokens: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
233
+ readonly completionTokens: v.NumberSchema<undefined>;
234
+ readonly totalTokens: v.NumberSchema<undefined>;
235
+ /** Upstream finish reason (`stop` | `length` | `tool_calls` | `content_filter` | …). */
236
+ readonly finishReason: v.NullableSchema<v.StringSchema<undefined>, undefined>;
237
+ /** Time waiting on the model (ms) — the actual execution. */
238
+ readonly upstreamMs: v.NumberSchema<undefined>;
239
+ /** Transport/proxy overhead (ms). */
240
+ readonly overheadMs: v.NumberSchema<undefined>;
241
+ /** End-to-end time the proxy spent on the call (ms). */
242
+ readonly totalMs: v.NumberSchema<undefined>;
243
+ readonly ok: v.BooleanSchema<undefined>;
244
+ readonly httpStatus: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
245
+ readonly errorMessage: v.NullableSchema<v.StringSchema<undefined>, undefined>;
246
+ /**
247
+ * The request messages serialised as JSON, stored as a DELTA — only the messages
248
+ * this call appended beyond `promptPrefixCount` (the full array when that is 0).
249
+ * The export rebuilds the full prompt from a chain's deltas.
250
+ */
251
+ readonly promptText: v.StringSchema<undefined>;
252
+ /**
253
+ * Leading messages elided from `promptText` (stored by an earlier call in the same
254
+ * conversation). 0 ⇒ `promptText` is the full array. Optional/defaulted so exports
255
+ * predating delta storage still parse.
256
+ */
257
+ readonly promptPrefixCount: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
258
+ /** Hash of the call's full messages array (chain key for the next call's delta). */
259
+ readonly promptHash: v.OptionalSchema<v.StringSchema<undefined>, "">;
260
+ /** The full assistant response text. */
261
+ readonly responseText: v.StringSchema<undefined>;
262
+ /**
263
+ * The model's reasoning / "thinking" trace on a separate channel, when emitted
264
+ * (empty for non-reasoning models). Optional/defaulted so exports predating reasoning
265
+ * capture still parse.
266
+ */
267
+ readonly reasoningText: v.OptionalSchema<v.StringSchema<undefined>, "">;
268
+ }, undefined>, undefined>;
269
+ }, undefined>;
270
+ export type LlmMetricsExport = v.InferOutput<typeof llmMetricsExportSchema>;
271
+ //# sourceMappingURL=observability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../src/observability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAQ5B,gFAAgF;AAChF,eAAO,MAAM,mBAAmB;;;;;;;IAO9B,0CAA0C;;;;IAI1C,0EAA0E;;IAE1E,4EAA4E;;;IAG5E,sFAAsF;;;;IAItF,wFAAwF;;IAExF,6DAA6D;;IAE7D,qCAAqC;;IAErC,wDAAwD;;;;;IAKxD;;;;OAIG;;IAEH;;;;OAIG;;IAEH,oFAAoF;;IAEpF,wCAAwC;;IAExC;;;;OAIG;;aAEH,CAAA;AACF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAErE;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;aA0BhC,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEzE,uFAAuF;AACvF,eAAO,MAAM,wBAAwB;;;;;;;;;QAzFnC,0CAA0C;;;;QAI1C,0EAA0E;;QAE1E,4EAA4E;;;QAG5E,sFAAsF;;;;QAItF,wFAAwF;;QAExF,6DAA6D;;QAE7D,qCAAqC;;QAErC,wDAAwD;;;;;QAKxD;;;;WAIG;;QAEH;;;;WAIG;;QAEH,oFAAoF;;QAEpF,wCAAwC;;QAExC;;;;WAIG;;;aAgDH,CAAA;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAE/E;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;IAOjC,sFAAsF;;;;;IAKtF,kFAAkF;;;;aAIlF,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAE3E;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;IACjC,0DAA0D;;;;;;;;;;;QAWxD,sFAAsF;;;;;;;;;;;;;QA9BxF,sFAAsF;;;;;QAKtF,kFAAkF;;;;;;;;;;;;QA/GlF,0CAA0C;;;;QAI1C,0EAA0E;;QAE1E,4EAA4E;;;QAG5E,sFAAsF;;;;QAItF,wFAAwF;;QAExF,6DAA6D;;QAE7D,qCAAqC;;QAErC,wDAAwD;;;;;QAKxD;;;;WAIG;;QAEH;;;;WAIG;;QAEH,oFAAoF;;QAEpF,wCAAwC;;QAExC;;;;WAIG;;;aAoGH,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,sBAAsB,CAAC,CAAA"}
@@ -0,0 +1,152 @@
1
+ import * as v from 'valibot';
2
+ // Wire contracts for LLM observability — the per-call detail behind the board's
3
+ // step rollups (see `stepMetricsSchema` in entities). The proxy records one of
4
+ // these per model call (full prompt + response, output-limit headroom, the
5
+ // transport-vs-execution latency split); the drill-down panel lists them and the
6
+ // export endpoint returns an LLM-analysable bundle.
7
+ /** One proxied LLM call, with its full prompt/response and timing breakdown. */
8
+ export const llmCallMetricSchema = v.object({
9
+ id: v.string(),
10
+ workspaceId: v.string(),
11
+ executionId: v.nullable(v.string()),
12
+ agentKind: v.string(),
13
+ provider: v.string(),
14
+ model: v.string(),
15
+ /** When the call completed (epoch ms). */
16
+ createdAt: v.number(),
17
+ streaming: v.boolean(),
18
+ messageCount: v.number(),
19
+ /** Tools offered to the model (0 = the agent could not edit anything). */
20
+ toolCount: v.number(),
21
+ /** The `max_tokens` the request asked for (the output ceiling), or null. */
22
+ requestMaxTokens: v.nullable(v.number()),
23
+ promptTokens: v.number(),
24
+ /** Prompt tokens served from the provider's prompt cache (subset of promptTokens). */
25
+ cachedPromptTokens: v.optional(v.number(), 0),
26
+ completionTokens: v.number(),
27
+ totalTokens: v.number(),
28
+ /** Upstream finish reason (`stop` | `length` | `tool_calls` | `content_filter` | …). */
29
+ finishReason: v.nullable(v.string()),
30
+ /** Time waiting on the model (ms) — the actual execution. */
31
+ upstreamMs: v.number(),
32
+ /** Transport/proxy overhead (ms). */
33
+ overheadMs: v.number(),
34
+ /** End-to-end time the proxy spent on the call (ms). */
35
+ totalMs: v.number(),
36
+ ok: v.boolean(),
37
+ httpStatus: v.nullable(v.number()),
38
+ errorMessage: v.nullable(v.string()),
39
+ /**
40
+ * The request messages serialised as JSON, stored as a DELTA — only the messages
41
+ * this call appended beyond `promptPrefixCount` (the full array when that is 0).
42
+ * The export rebuilds the full prompt from a chain's deltas.
43
+ */
44
+ promptText: v.string(),
45
+ /**
46
+ * Leading messages elided from `promptText` (stored by an earlier call in the same
47
+ * conversation). 0 ⇒ `promptText` is the full array. Optional/defaulted so exports
48
+ * predating delta storage still parse.
49
+ */
50
+ promptPrefixCount: v.optional(v.number(), 0),
51
+ /** Hash of the call's full messages array (chain key for the next call's delta). */
52
+ promptHash: v.optional(v.string(), ''),
53
+ /** The full assistant response text. */
54
+ responseText: v.string(),
55
+ /**
56
+ * The model's reasoning / "thinking" trace on a separate channel, when emitted
57
+ * (empty for non-reasoning models). Optional/defaulted so exports predating reasoning
58
+ * capture still parse.
59
+ */
60
+ reasoningText: v.optional(v.string(), ''),
61
+ });
62
+ /**
63
+ * The compact per-call summary pushed live over the workspace event stream (the
64
+ * `llmCall` {@link WorkspaceEvent}). It is {@link llmCallMetricSchema} WITHOUT the
65
+ * heavy text bodies (`promptText`/`responseText`) and the delta bookkeeping
66
+ * (`promptPrefixCount`/`promptHash`), so a stalled-driver "is the agent still
67
+ * calling the model?" view updates in real time without shipping prompt bytes over
68
+ * the socket. The drill-down panel lazy-loads the full bodies for an expanded row
69
+ * from `GET /executions/:id/llm-metrics` (the persisted store), keyed by the shared
70
+ * call `id`.
71
+ */
72
+ export const llmCallActivitySchema = v.object({
73
+ id: v.string(),
74
+ workspaceId: v.string(),
75
+ executionId: v.nullable(v.string()),
76
+ agentKind: v.string(),
77
+ provider: v.string(),
78
+ model: v.string(),
79
+ createdAt: v.number(),
80
+ streaming: v.boolean(),
81
+ messageCount: v.number(),
82
+ toolCount: v.number(),
83
+ requestMaxTokens: v.nullable(v.number()),
84
+ promptTokens: v.number(),
85
+ // Always supplied by the proxy emit (unlike the persisted metric, which defaults it
86
+ // for rows that predate delta storage), so it is required here — matching the SPA's
87
+ // `LlmCallActivity` type, which derives it as a required field from `LlmCallMetric`.
88
+ cachedPromptTokens: v.number(),
89
+ completionTokens: v.number(),
90
+ totalTokens: v.number(),
91
+ finishReason: v.nullable(v.string()),
92
+ upstreamMs: v.number(),
93
+ overheadMs: v.number(),
94
+ totalMs: v.number(),
95
+ ok: v.boolean(),
96
+ httpStatus: v.nullable(v.number()),
97
+ errorMessage: v.nullable(v.string()),
98
+ });
99
+ /** Response of `GET /workspaces/:ws/executions/:id/llm-metrics` (drill-down panel). */
100
+ export const llmMetricsResponseSchema = v.object({
101
+ executionId: v.string(),
102
+ calls: v.array(llmCallMetricSchema),
103
+ });
104
+ /**
105
+ * A single per-agent-kind insight in the LLM-friendly export: the same rollup the
106
+ * board step shows, plus derived ratios so an analysing model needs no arithmetic.
107
+ */
108
+ export const llmExportInsightSchema = v.object({
109
+ agentKind: v.string(),
110
+ calls: v.number(),
111
+ promptTokens: v.number(),
112
+ completionTokens: v.number(),
113
+ peakCompletionTokens: v.number(),
114
+ maxOutputTokens: v.nullable(v.number()),
115
+ /** peakCompletionTokens / maxOutputTokens, 0..1; null when the ceiling is unknown. */
116
+ outputHeadroomRatio: v.nullable(v.number()),
117
+ truncatedCalls: v.number(),
118
+ upstreamMs: v.number(),
119
+ overheadMs: v.number(),
120
+ /** overheadMs / (upstreamMs + overheadMs), 0..1; the share spent in transport. */
121
+ transportOverheadRatio: v.nullable(v.number()),
122
+ errors: v.number(),
123
+ warnings: v.number(),
124
+ });
125
+ /**
126
+ * LLM-friendly export of a run's model activity: a self-describing, structured JSON
127
+ * bundle (totals + per-agent insights + every call) intended to be handed straight
128
+ * to a model for analysis ("why did this run truncate / spend / stall?"). Field
129
+ * names and derived ratios are explicit so no external context is needed.
130
+ */
131
+ export const llmMetricsExportSchema = v.object({
132
+ /** Schema marker so a consuming model knows the shape. */
133
+ kind: v.literal('cat-factory.llm-metrics-export'),
134
+ version: v.literal(1),
135
+ executionId: v.string(),
136
+ generatedAt: v.number(),
137
+ totals: v.object({
138
+ calls: v.number(),
139
+ promptTokens: v.number(),
140
+ completionTokens: v.number(),
141
+ upstreamMs: v.number(),
142
+ overheadMs: v.number(),
143
+ /** Share of total latency spent in transport/proxy (0..1), or null with no timing. */
144
+ transportOverheadRatio: v.nullable(v.number()),
145
+ errors: v.number(),
146
+ warnings: v.number(),
147
+ truncatedCalls: v.number(),
148
+ }),
149
+ insights: v.array(llmExportInsightSchema),
150
+ calls: v.array(llmCallMetricSchema),
151
+ });
152
+ //# sourceMappingURL=observability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.js","sourceRoot":"","sources":["../src/observability.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import * as v from 'valibot';
2
+ /**
3
+ * The personal password that gates the second encryption layer (8–256 chars). Restricted
4
+ * to printable ASCII so the same value can ride **raw** in the `X-Personal-Password`
5
+ * request header (see below) when unlocking a run — HTTP header values must be Latin-1, so
6
+ * a non-ASCII password could not be sent without encoding. Never stored server-side.
7
+ */
8
+ export declare const personalPasswordSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>, v.MaxLengthAction<string, 256, undefined>, v.RegexAction<string, "Password must use printable ASCII characters (no tabs/newlines).">]>;
9
+ /**
10
+ * HTTP header carrying the personal password to unlock a run's individual-usage
11
+ * credential(s). It is an AMBIENT credential — like the bearer token, the client attaches
12
+ * it on the gated calls (start / retry / resolve / approve / request-changes) rather than
13
+ * baking it into each request body — so it never appears in a wire-contract payload. The
14
+ * server reads it, unlocks, and mints/re-mints the per-run activation; absent + required ⇒
15
+ * `428 credential_required`.
16
+ */
17
+ export declare const PERSONAL_PASSWORD_HEADER = "X-Personal-Password";
18
+ /** Store (or replace) the signed-in user's personal subscription for a vendor. */
19
+ export declare const storePersonalSubscriptionSchema: v.ObjectSchema<{
20
+ readonly vendor: v.PicklistSchema<["claude", "codex", "glm", "kimi", "deepseek"], undefined>;
21
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
22
+ /** The raw secret (write-only): the `claude setup-token` OAuth token for `claude`. */
23
+ readonly token: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
24
+ /** Personal password that gates the second encryption layer. Never stored. */
25
+ readonly password: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>, v.MaxLengthAction<string, 256, undefined>, v.RegexAction<string, "Password must use printable ASCII characters (no tabs/newlines).">]>;
26
+ /**
27
+ * Epoch ms the subscription itself expires (so we can warn well in advance and
28
+ * block runs once lapsed). Optional — omit if the plan has no fixed end date.
29
+ */
30
+ readonly expiresAt: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
31
+ }, undefined>;
32
+ export type StorePersonalSubscriptionInput = v.InferOutput<typeof storePersonalSubscriptionSchema>;
33
+ /** Read-only status of one personal subscription — metadata only, never the secret. */
34
+ export declare const personalSubscriptionStatusSchema: v.ObjectSchema<{
35
+ readonly vendor: v.PicklistSchema<["claude", "codex", "glm", "kimi", "deepseek"], undefined>;
36
+ readonly label: v.StringSchema<undefined>;
37
+ readonly createdAt: v.NumberSchema<undefined>;
38
+ readonly updatedAt: v.NumberSchema<undefined>;
39
+ readonly lastUsedAt: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
40
+ /** Subscription's own expiry (null = no fixed end date). */
41
+ readonly expiresAt: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
42
+ /** Whole days until `expiresAt` (negative once lapsed; null when no expiry). */
43
+ readonly expiresInDays: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
44
+ /** Whether the subscription's expiry has already passed. */
45
+ readonly expired: v.BooleanSchema<undefined>;
46
+ /** Whether renewal should be surfaced now (expiry within the warning window). */
47
+ readonly renewSoon: v.BooleanSchema<undefined>;
48
+ }, undefined>;
49
+ export type PersonalSubscriptionStatus = v.InferOutput<typeof personalSubscriptionStatusSchema>;
50
+ export declare const personalSubscriptionListSchema: v.ArraySchema<v.ObjectSchema<{
51
+ readonly vendor: v.PicklistSchema<["claude", "codex", "glm", "kimi", "deepseek"], undefined>;
52
+ readonly label: v.StringSchema<undefined>;
53
+ readonly createdAt: v.NumberSchema<undefined>;
54
+ readonly updatedAt: v.NumberSchema<undefined>;
55
+ readonly lastUsedAt: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
56
+ /** Subscription's own expiry (null = no fixed end date). */
57
+ readonly expiresAt: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
58
+ /** Whole days until `expiresAt` (negative once lapsed; null when no expiry). */
59
+ readonly expiresInDays: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
60
+ /** Whether the subscription's expiry has already passed. */
61
+ readonly expired: v.BooleanSchema<undefined>;
62
+ /** Whether renewal should be surfaced now (expiry within the warning window). */
63
+ readonly renewSoon: v.BooleanSchema<undefined>;
64
+ }, undefined>, undefined>;
65
+ export type PersonalSubscriptionList = v.InferOutput<typeof personalSubscriptionListSchema>;
66
+ //# sourceMappingURL=personal-subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personal-subscriptions.d.ts","sourceRoot":"","sources":["../src/personal-subscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAwB5B;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,uOAKlC,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,wBAAwB,CAAA;AAE7D,kFAAkF;AAClF,eAAO,MAAM,+BAA+B;;;IAG1C,sFAAsF;;IAEtF,8EAA8E;;IAE9E;;;OAGG;;aAEH,CAAA;AACF,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAElG,uFAAuF;AACvF,eAAO,MAAM,gCAAgC;;;;;;IAM3C,4DAA4D;;IAE5D,gFAAgF;;IAEhF,4DAA4D;;IAE5D,iFAAiF;;aAEjF,CAAA;AACF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAE/F,eAAO,MAAM,8BAA8B;;;;;;IAXzC,4DAA4D;;IAE5D,gFAAgF;;IAEhF,4DAA4D;;IAE5D,iFAAiF;;yBAKI,CAAA;AACvF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,8BAA8B,CAAC,CAAA"}