@cat-factory/app 0.35.0 → 0.37.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 (87) hide show
  1. package/app/components/auth/UserMenu.vue +11 -1
  2. package/app/components/brainstorm/BrainstormWindow.vue +2 -1
  3. package/app/components/clarity/ClarityReviewWindow.vue +2 -1
  4. package/app/components/gates/GateResultView.vue +107 -12
  5. package/app/components/layout/IntegrationBackTitle.vue +12 -7
  6. package/app/components/layout/IntegrationsHub.vue +191 -43
  7. package/app/components/layout/NotificationsInbox.vue +16 -0
  8. package/app/components/layout/PersonalSetupModal.vue +141 -0
  9. package/app/components/pipeline/PipelineBuilder.vue +1 -1
  10. package/app/components/providers/VendorCredentialsModal.vue +7 -2
  11. package/app/components/slack/SlackPanel.vue +1 -0
  12. package/app/composables/api/accounts.ts +36 -51
  13. package/app/composables/api/auth.ts +20 -19
  14. package/app/composables/api/board.ts +60 -40
  15. package/app/composables/api/bootstrap.ts +25 -22
  16. package/app/composables/api/client.ts +102 -0
  17. package/app/composables/api/context.ts +25 -6
  18. package/app/composables/api/documents.ts +36 -34
  19. package/app/composables/api/execution.ts +65 -48
  20. package/app/composables/api/followUps.ts +26 -26
  21. package/app/composables/api/fragments.ts +47 -34
  22. package/app/composables/api/github.ts +65 -45
  23. package/app/composables/api/humanReview.ts +19 -0
  24. package/app/composables/api/humanTest.ts +15 -11
  25. package/app/composables/api/kaizen.ts +8 -6
  26. package/app/composables/api/localSettings.ts +5 -4
  27. package/app/composables/api/models.ts +58 -51
  28. package/app/composables/api/notifications.ts +13 -7
  29. package/app/composables/api/presets.ts +34 -28
  30. package/app/composables/api/providerConnections.ts +68 -26
  31. package/app/composables/api/recurring.ts +40 -30
  32. package/app/composables/api/releaseHealth.ts +28 -26
  33. package/app/composables/api/reviews.ts +136 -114
  34. package/app/composables/api/sandbox.ts +52 -34
  35. package/app/composables/api/slack.ts +22 -25
  36. package/app/composables/api/spec.ts +3 -3
  37. package/app/composables/api/tasks.ts +42 -41
  38. package/app/composables/api/userSecrets.ts +12 -17
  39. package/app/composables/api/workspaces.ts +21 -15
  40. package/app/composables/useApi.ts +11 -1
  41. package/app/composables/useIntegrationBack.ts +9 -3
  42. package/app/pages/index.vue +2 -0
  43. package/app/stores/auth.ts +2 -1
  44. package/app/stores/board.ts +2 -1
  45. package/app/stores/brainstorm.ts +2 -2
  46. package/app/stores/clarity.ts +6 -2
  47. package/app/stores/execution.ts +3 -2
  48. package/app/stores/github.ts +1 -2
  49. package/app/stores/humanReview.ts +41 -0
  50. package/app/stores/mergePresets.ts +2 -6
  51. package/app/stores/pipelines.ts +1 -1
  52. package/app/stores/recurringPipelines.ts +2 -7
  53. package/app/stores/sandbox.ts +1 -2
  54. package/app/stores/ui.ts +62 -19
  55. package/app/types/accountSettings.ts +11 -36
  56. package/app/types/accounts.ts +16 -71
  57. package/app/types/bootstrap.ts +13 -75
  58. package/app/types/brainstorm.ts +13 -38
  59. package/app/types/clarity.ts +12 -43
  60. package/app/types/consensus.ts +16 -89
  61. package/app/types/documents.ts +19 -94
  62. package/app/types/domain.ts +54 -582
  63. package/app/types/execution.ts +48 -499
  64. package/app/types/fragments.ts +15 -83
  65. package/app/types/github.ts +25 -161
  66. package/app/types/incidentEnrichment.ts +10 -25
  67. package/app/types/localModels.ts +11 -61
  68. package/app/types/localSettings.ts +9 -26
  69. package/app/types/merge.ts +10 -68
  70. package/app/types/model-presets.ts +7 -28
  71. package/app/types/models.ts +16 -164
  72. package/app/types/notifications.ts +18 -76
  73. package/app/types/openrouter.ts +8 -34
  74. package/app/types/providerConnections.ts +21 -41
  75. package/app/types/provisioningLogs.ts +9 -29
  76. package/app/types/recurring.ts +10 -63
  77. package/app/types/releaseHealth.ts +15 -39
  78. package/app/types/requirements.ts +14 -84
  79. package/app/types/sandbox.ts +45 -161
  80. package/app/types/services.ts +3 -22
  81. package/app/types/slack.ts +10 -47
  82. package/app/types/spec.ts +15 -68
  83. package/app/types/tasks.ts +15 -111
  84. package/app/types/tracker.ts +9 -24
  85. package/app/types/userSecrets.ts +12 -47
  86. package/app/utils/catalog.ts +12 -0
  87. package/package.json +9 -2
@@ -1,149 +1,33 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // GitHub integration. The backend's `GitHubModule` projects GitHub data
3
3
  // (repos/branches, pull requests/issues) into D1 and serves it fast and
4
- // rate-limit-free, alongside connect/resync/write endpoints. These mirror the
5
- // `@cat-factory/contracts` GitHub schemas so responses drop straight into the
6
- // Pinia store, just as the document-source types do for Confluence/Notion.
4
+ // rate-limit-free, alongside connect/resync/write endpoints.
5
+ //
6
+ // All wire shapes are sourced from @cat-factory/contracts (single source of
7
+ // truth). `CreatedRepo` has no exported contract type (the create-repo route
8
+ // models the response inline), so it stays frontend-only below.
7
9
  // ---------------------------------------------------------------------------
8
10
 
9
- /** A workspace's GitHub App installation, as exposed to clients (no token). */
10
- export interface GitHubConnection {
11
- installationId: number
12
- accountLogin: string
13
- targetType: 'Organization' | 'User'
14
- connectedAt: number
15
- /**
16
- * Whether cat-factory can create repos under this account itself (privileged
17
- * App tier). When true, the bootstrap UI drops the manual "create on GitHub"
18
- * step. Defaults to false for older backends that don't send it.
19
- */
20
- canCreateRepos?: boolean
21
- /**
22
- * Whether the installation granted the App `workflows: write`. When false, agent
23
- * pushes that add/update `.github/workflows/*` are rejected by GitHub, so the UI
24
- * warns the user to grant the permission. Defaults to false for older backends.
25
- */
26
- canManageWorkflows?: boolean
27
- }
28
-
29
- /**
30
- * A discoverable App installation for the connect picker. `connected` says
31
- * whether it's already bound: to THIS workspace, to ANOTHER (so connecting would
32
- * be rejected), or to NONE (free to connect).
33
- */
34
- export interface GitHubInstallationOption {
35
- installationId: number
36
- accountLogin: string
37
- targetType: 'Organization' | 'User'
38
- accountAvatarUrl: string | null
39
- connected: 'this' | 'other' | 'none'
40
- }
41
-
42
- /** A repository the integration tracks for a workspace. */
43
- export interface GitHubRepo {
44
- githubId: number
45
- installationId: number
46
- owner: string
47
- name: string
48
- defaultBranch: string | null
49
- private: boolean
50
- /** Optional link to a board block this repo backs. */
51
- blockId: string | null
52
- /** Whether this repo is a monorepo hosting several services (each pinned to a subdirectory). */
53
- isMonorepo?: boolean
54
- syncedAt: number
55
- }
56
-
57
- /** One directory entry of a repo's tree, used by the monorepo service picker. */
58
- export interface RepoTreeEntry {
59
- /** Path relative to the repo root, e.g. `packages/api`. */
60
- path: string
61
- /** Base name, e.g. `api`. */
62
- name: string
63
- /** `file` | `dir` | `symlink` | `submodule`. */
64
- type: string
65
- }
66
-
67
- export interface GitHubBranch {
68
- repoGithubId: number
69
- name: string
70
- headSha: string
71
- protected: boolean
72
- syncedAt: number
73
- }
74
-
75
- /**
76
- * A repo the connected installation can access, annotated with whether the
77
- * current workspace links it. Drives the per-workspace repo picker — repos are
78
- * linked explicitly per board, since the installation is shared across an
79
- * account's workspaces.
80
- */
81
- export interface GitHubAvailableRepo {
82
- githubId: number
83
- owner: string
84
- name: string
85
- defaultBranch: string | null
86
- private: boolean
87
- linked: boolean
88
- /** Whether the (linked) repo is flagged as a monorepo. */
89
- isMonorepo?: boolean
90
- }
91
-
92
- export type GitHubPullRequestState = 'open' | 'closed'
93
-
94
- export interface GitHubPullRequest {
95
- repoGithubId: number
96
- number: number
97
- githubId: number
98
- title: string
99
- state: GitHubPullRequestState
100
- headRef: string | null
101
- baseRef: string | null
102
- headSha: string | null
103
- merged: boolean
104
- author: string | null
105
- updatedAt: number | null
106
- syncedAt: number
107
- }
108
-
109
- export type GitHubIssueState = 'open' | 'closed'
110
-
111
- export interface GitHubIssue {
112
- repoGithubId: number
113
- number: number
114
- githubId: number
115
- title: string
116
- state: GitHubIssueState
117
- author: string | null
118
- labels: string[]
119
- updatedAt: number | null
120
- syncedAt: number
121
- }
122
-
123
- // ---- request inputs -------------------------------------------------------
124
-
125
- /** Trigger a resync. Defaults to an incremental resync of all tracked repos. */
126
- export interface ResyncRequest {
127
- /** Limit the resync to a single repo (by its GitHub numeric id). */
128
- repoGithubId?: number
129
- /** Run a full backfill (durable Workflow) instead of an incremental pass. */
130
- full?: boolean
131
- }
132
-
133
- export interface CreateBranchInput {
134
- name: string
135
- fromSha: string
136
- }
137
-
138
- /** Body for programmatic repo creation (privileged App tier). */
139
- export interface CreateRepoRequest {
140
- /** A single GitHub name segment — no "owner/" prefix. */
141
- name: string
142
- private?: boolean
143
- description?: string
144
- }
145
-
146
- /** The freshly-created repository returned by the create-repo endpoint. */
11
+ export type {
12
+ GitHubConnection,
13
+ GitHubInstallationOption,
14
+ GitHubRepo,
15
+ RepoTreeEntry,
16
+ GitHubBranch,
17
+ GitHubAvailableRepo,
18
+ GitHubPullRequestState,
19
+ GitHubPullRequest,
20
+ GitHubIssueState,
21
+ GitHubIssue,
22
+ ResyncRequest,
23
+ CreateBranchInput,
24
+ CreateRepoRequest,
25
+ CommitFilesInput,
26
+ OpenPullRequestInput,
27
+ MergePullRequestInput,
28
+ } from '@cat-factory/contracts'
29
+
30
+ /** The freshly-created repository returned by the create-repo endpoint. Frontend-only. */
147
31
  export interface CreatedRepo {
148
32
  githubId: number
149
33
  owner: string
@@ -151,23 +35,3 @@ export interface CreatedRepo {
151
35
  defaultBranch: string | null
152
36
  private: boolean
153
37
  }
154
-
155
- export interface CommitFilesInput {
156
- branch: string
157
- message: string
158
- files: { path: string; content: string }[]
159
- /** Parent commit to build on; defaults to the branch tip. */
160
- baseSha?: string
161
- }
162
-
163
- export interface OpenPullRequestInput {
164
- title: string
165
- head: string
166
- base: string
167
- body?: string
168
- draft?: boolean
169
- }
170
-
171
- export interface MergePullRequestInput {
172
- method?: 'merge' | 'squash' | 'rebase'
173
- }
@@ -1,28 +1,13 @@
1
1
  // Per-workspace incident-enrichment connection (PagerDuty + incident.io). Mirrors
2
2
  // `@cat-factory/contracts` incident-enrichment. Credentials are write-only — the view
3
3
  // returns only a presence `summary`.
4
-
5
- export interface PagerDutyCredentials {
6
- apiToken: string
7
- fromEmail: string
8
- }
9
-
10
- export interface IncidentIoCredentials {
11
- apiKey: string
12
- }
13
-
14
- /** Write input — set one or both providers; an omitted group is left unchanged. */
15
- export interface UpsertIncidentEnrichmentInput {
16
- pagerDuty?: PagerDutyCredentials
17
- incidentIo?: IncidentIoCredentials
18
- }
19
-
20
- export interface IncidentEnrichmentSummary {
21
- pagerDuty: boolean
22
- incidentIo: boolean
23
- }
24
-
25
- export interface IncidentEnrichmentView {
26
- connected: boolean
27
- summary: IncidentEnrichmentSummary | null
28
- }
4
+ //
5
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
6
+
7
+ export type {
8
+ PagerDutyCredentials,
9
+ IncidentIoCredentials,
10
+ UpsertIncidentEnrichmentInput,
11
+ IncidentEnrichmentSummary,
12
+ IncidentEnrichmentView,
13
+ } from '@cat-factory/contracts'
@@ -8,66 +8,16 @@
8
8
  // Mirrors the `@cat-factory/contracts` `localModels` schemas exactly, so a payload
9
9
  // returned by the backend drops straight into the Pinia store without translation.
10
10
  // ---------------------------------------------------------------------------
11
+ //
12
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
11
13
 
12
- /** The supported local runner types. The runner type IS the `ModelRef.provider`. */
13
- export type LocalRunner = 'ollama' | 'lmstudio' | 'llamacpp' | 'vllm' | 'custom'
14
-
15
- /** Default base URL per runner, for UI prefill. `custom` has none (user supplies it). */
16
- export const LOCAL_RUNNER_DEFAULTS: Record<LocalRunner, string | null> = {
17
- ollama: 'http://localhost:11434/v1',
18
- lmstudio: 'http://localhost:1234/v1',
19
- llamacpp: 'http://localhost:8080/v1',
20
- vllm: 'http://localhost:8000/v1',
21
- custom: null,
22
- }
23
-
24
- /** Short display label per runner, shown in the picker as the provider label. */
25
- export const LOCAL_RUNNER_LABELS: Record<LocalRunner, string> = {
26
- ollama: 'Ollama',
27
- lmstudio: 'LM Studio',
28
- llamacpp: 'llama.cpp',
29
- vllm: 'vLLM',
30
- custom: 'Custom',
31
- }
32
-
33
- /**
34
- * A user's configured local runner endpoint, as returned to the SPA. The API key is
35
- * write-only (never returned); `hasApiKey` reports whether one is stored.
36
- */
37
- export interface LocalModelEndpoint {
38
- provider: LocalRunner
39
- label: string
40
- baseUrl: string
41
- /** Whether a (write-only) API key is stored for this endpoint. */
42
- hasApiKey: boolean
43
- /** The model ids the user has enabled from this runner (surfaced in the picker). */
44
- models: string[]
45
- createdAt: number
46
- updatedAt: number
47
- }
48
-
49
- /** Create or replace the signed-in user's endpoint for a runner (one per runner). */
50
- export interface UpsertLocalModelEndpointInput {
51
- provider: LocalRunner
52
- label?: string
53
- baseUrl: string
54
- /** Optional bearer key (most local runners ignore it); stored encrypted at rest. */
55
- apiKey?: string
56
- models: string[]
57
- }
58
-
59
- /** Probe a runner endpoint for reachability + the models it currently serves. */
60
- export interface TestLocalModelEndpointInput {
61
- provider: LocalRunner
62
- baseUrl: string
63
- apiKey?: string
64
- }
14
+ export type {
15
+ LocalRunner,
16
+ LocalModelEndpoint,
17
+ UpsertLocalModelEndpointInput,
18
+ TestLocalModelEndpointInput,
19
+ LocalModelEndpointTestResult,
20
+ } from '@cat-factory/contracts'
65
21
 
66
- /** The result of probing a runner endpoint's `/models`. */
67
- export interface LocalModelEndpointTestResult {
68
- reachable: boolean
69
- /** Model ids the runner reports (empty when unreachable). */
70
- models: string[]
71
- /** Human-readable failure reason when `reachable` is false. */
72
- error?: string
73
- }
22
+ // Value re-exports (the per-runner default base URL + display labels).
23
+ export { LOCAL_RUNNER_DEFAULTS, LOCAL_RUNNER_LABELS } from '@cat-factory/contracts'
@@ -3,29 +3,12 @@
3
3
  // dedicated local-mode settings panel — these replaced the old LOCAL_POOL_* / HARNESS_* env
4
4
  // vars. There are no secrets, so the read view is the plain config. Local-mode-only (the
5
5
  // warm pool is the local Docker-family runner's differentiator).
6
-
7
- export interface LocalPoolSettings {
8
- /** Max idle warm containers kept for re-lease. 0 disables pooling (cold-start per run). */
9
- size: number
10
- /** Containers pre-warmed when the service starts. */
11
- minWarm: number
12
- /** Hard cap on total containers (leased + idle). `null` ⇒ defaults to `size`. */
13
- max: number | null
14
- /** How long an idle pooled container is kept before eviction (ms). */
15
- idleTtlMs: number
16
- }
17
-
18
- export interface LocalCheckoutSettings {
19
- /** Absolute in-container dir the reused per-repo checkout lives under. */
20
- workspaceRoot: string
21
- /** Dep-cache directories the per-run clean sweep keeps (so deps aren't reinstalled). */
22
- cleanKeep: string[]
23
- }
24
-
25
- export interface LocalSettings {
26
- pool: LocalPoolSettings
27
- checkout: LocalCheckoutSettings
28
- }
29
-
30
- /** Admin write: the full settings blob fully replaces the stored config. */
31
- export type UpdateLocalSettingsInput = LocalSettings
6
+ //
7
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
8
+
9
+ export type {
10
+ LocalPoolSettings,
11
+ LocalCheckoutSettings,
12
+ LocalSettings,
13
+ UpdateLocalSettingsInput,
14
+ } from '@cat-factory/contracts'
@@ -1,71 +1,13 @@
1
1
  // Merge-policy shapes, mirroring `@cat-factory/contracts` (merge.ts). A `merger`
2
2
  // agent scores a PR on three 0..1 axes and the engine compares them against the
3
3
  // task's resolved threshold preset to auto-merge or raise a review notification.
4
-
5
- /** A `merger` agent's assessment of a pull request (each axis 0..1). */
6
- export interface MergeAssessment {
7
- complexity: number
8
- risk: number
9
- impact: number
10
- rationale: string
11
- }
12
-
13
- /**
14
- * The highest reviewer-finding severity a task tolerates before the requirements review
15
- * stops for a human. `none` tolerates nothing; `high` tolerates everything. Ordered
16
- * none < low < medium < high.
17
- */
18
- export type RequirementConcernLevel = 'none' | 'low' | 'medium' | 'high'
19
-
20
- /** A named, per-workspace merge policy a task can select. */
21
- export interface MergeThresholdPreset {
22
- id: string
23
- name: string
24
- /** Auto-merge only when the assessment's complexity is ≤ this. */
25
- maxComplexity: number
26
- /** Auto-merge only when the assessment's risk is ≤ this. */
27
- maxRisk: number
28
- /** Auto-merge only when the assessment's impact is ≤ this. */
29
- maxImpact: number
30
- /** How many times the CI-fixer may try before the CI gate gives up. */
31
- ciMaxAttempts: number
32
- /** How many reviewer passes the requirements-review loop runs before asking the human. */
33
- maxRequirementIterations: number
34
- /** Findings at or below this severity auto-pass without stopping for a human. */
35
- maxRequirementConcernAllowed: RequirementConcernLevel
36
- /** Minutes the post-release-health gate watches the release's monitors/SLOs after deploy. */
37
- releaseWatchWindowMinutes: number
38
- /** How many on-call investigations the post-release-health gate may dispatch. */
39
- releaseMaxAttempts: number
40
- /** The workspace's fallback preset, used by tasks that pick none. */
41
- isDefault: boolean
42
- createdAt: number
43
- }
44
-
45
- /** Create a merge threshold preset. */
46
- export interface CreateMergePresetInput {
47
- name: string
48
- maxComplexity: number
49
- maxRisk: number
50
- maxImpact: number
51
- ciMaxAttempts: number
52
- maxRequirementIterations: number
53
- maxRequirementConcernAllowed: RequirementConcernLevel
54
- releaseWatchWindowMinutes?: number
55
- releaseMaxAttempts?: number
56
- isDefault?: boolean
57
- }
58
-
59
- /** Patch a merge threshold preset (all fields optional). */
60
- export interface UpdateMergePresetInput {
61
- name?: string
62
- maxComplexity?: number
63
- maxRisk?: number
64
- maxImpact?: number
65
- ciMaxAttempts?: number
66
- maxRequirementIterations?: number
67
- maxRequirementConcernAllowed?: RequirementConcernLevel
68
- releaseWatchWindowMinutes?: number
69
- releaseMaxAttempts?: number
70
- isDefault?: boolean
71
- }
4
+ //
5
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
6
+
7
+ export type {
8
+ MergeAssessment,
9
+ RequirementConcernLevel,
10
+ MergeThresholdPreset,
11
+ CreateMergePresetInput,
12
+ UpdateMergePresetInput,
13
+ } from '@cat-factory/contracts'
@@ -2,32 +2,11 @@
2
2
  // is a named, per-workspace model->agent mapping: one base model applied to every
3
3
  // agent kind plus per-kind overrides. A task selects one (Block.modelPresetId); none
4
4
  // resolves to the workspace default preset.
5
+ //
6
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
5
7
 
6
- /** A named, per-workspace model preset a task can select. */
7
- export interface ModelPreset {
8
- id: string
9
- name: string
10
- /** The model every agent kind defaults to under this preset (a catalog id). */
11
- baseModelId: string
12
- /** Per-agent-kind model overrides on top of the base (agent kind → model id). */
13
- overrides: Record<string, string>
14
- /** The workspace's fallback preset, used by tasks that pick none. */
15
- isDefault: boolean
16
- createdAt: number
17
- }
18
-
19
- /** Create a model preset. */
20
- export interface CreateModelPresetInput {
21
- name: string
22
- baseModelId: string
23
- overrides?: Record<string, string>
24
- isDefault?: boolean
25
- }
26
-
27
- /** Patch a model preset (all fields optional; `overrides` replaces the map). */
28
- export interface UpdateModelPresetInput {
29
- name?: string
30
- baseModelId?: string
31
- overrides?: Record<string, string>
32
- isDefault?: boolean
33
- }
8
+ export type {
9
+ ModelPreset,
10
+ CreateModelPresetInput,
11
+ UpdateModelPresetInput,
12
+ } from '@cat-factory/contracts'
@@ -2,167 +2,19 @@
2
2
  // Model selection & best-practice prompt fragments. Mirrors the
3
3
  // `@cat-factory/contracts` schemas served read-only by the backend.
4
4
  // ---------------------------------------------------------------------------
5
-
6
- import type { AgentKind, BlockType } from './domain'
7
- import type { DocumentSourceKind } from './documents'
8
-
9
- /** Subscription vendors whose pooled tokens drive the Claude Code / Codex harnesses. */
10
- export type SubscriptionVendor = 'claude' | 'codex' | 'glm' | 'kimi' | 'deepseek'
11
-
12
- /** Informational list price (per 1M tokens) for a model flavour. */
13
- export interface ModelCost {
14
- inputPerMillion: number
15
- outputPerMillion: number
16
- currency: string
17
- }
18
-
19
- /**
20
- * A selectable LLM model, resolved to the flavour in use for this deployment
21
- * (served by `GET /models`). Mirrors `ModelOption` in `@cat-factory/contracts`.
22
- * The base `flavor`/`provider`/`model` is the always-available fallback
23
- * (cloudflare/direct/openrouter), or the subscription itself for subscription-only
24
- * models. `subscription` (when present) is the alternative the picker prefers once
25
- * the workspace has a token for its vendor.
26
- */
27
- export interface ModelOption {
28
- id: string
29
- label: string
30
- description: string
31
- flavor: 'cloudflare' | 'direct' | 'openrouter' | 'subscription'
32
- /**
33
- * Whether this model is actually selectable for the workspace: a direct API key for
34
- * its provider, a connected subscription vendor, or Cloudflare AI enabled. Absent on
35
- * the deployment-level catalog; present on the per-workspace `/workspaces/:id/models`.
36
- */
37
- available?: boolean
38
- providerLabel: string
39
- provider: string
40
- model: string
41
- vendor?: SubscriptionVendor
42
- cost?: ModelCost
43
- contextTokens?: number
44
- /** True when the effective flavour is flat-rate quota (not budget-metered). */
45
- quotaBased?: boolean
46
- /** The alternative subscription flavour for a dual-mode model (GLM/Kimi). */
47
- subscription?: {
48
- vendor: SubscriptionVendor
49
- providerLabel: string
50
- provider: string
51
- model: string
52
- cost?: ModelCost
53
- contextTokens?: number
54
- }
55
- }
56
-
57
- /**
58
- * Status of a user's personal (individual-usage) subscription — Claude consumer
59
- * subscriptions are licensed per individual, so they're stored per-user (not pooled)
60
- * and unlocked with a personal password. Metadata only; never the token.
61
- */
62
- export interface PersonalSubscriptionStatus {
63
- vendor: SubscriptionVendor
64
- label: string
65
- createdAt: number
66
- updatedAt: number
67
- lastUsedAt: number | null
68
- /** Subscription's own expiry (null = no fixed end date). */
69
- expiresAt: number | null
70
- /** Whole days until `expiresAt` (negative once lapsed; null when no expiry). */
71
- expiresInDays: number | null
72
- expired: boolean
73
- /** Whether renewal should be surfaced now (expiry within the warning window). */
74
- renewSoon: boolean
75
- }
76
-
77
- /** Connect (or replace) the signed-in user's personal subscription for a vendor. */
78
- export interface StorePersonalSubscriptionInput {
79
- vendor: SubscriptionVendor
80
- label: string
81
- token: string
82
- /** Personal password gating the second encryption layer; never stored. */
83
- password: string
84
- /** Epoch ms the subscription expires (for renewal warnings); optional. */
85
- expiresAt?: number | null
86
- }
87
-
88
- /** The scope a stored direct-provider API key belongs to. */
89
- export type ApiKeyScope = 'account' | 'workspace' | 'user'
90
-
91
- /** The direct providers that own a poolable API key. */
92
- export type ApiKeyProvider =
93
- | 'openai'
94
- | 'anthropic'
95
- | 'qwen'
96
- | 'deepseek'
97
- | 'moonshot'
98
- | 'openrouter'
99
- | 'litellm'
100
-
101
- /** A connected direct-provider API key (metadata + usage), never the secret. */
102
- export interface ApiKey {
103
- id: string
104
- scope: ApiKeyScope
105
- scopeId: string
106
- provider: ApiKeyProvider
107
- label: string
108
- createdAt: number
109
- lastUsedAt: number | null
110
- inputTokens: number
111
- outputTokens: number
112
- requestCount: number
113
- }
114
-
115
- /** Add a direct-provider API key to a pool. `key` is write-only (the raw secret). */
116
- export interface AddApiKeyInput {
117
- provider: ApiKeyProvider
118
- label: string
119
- key: string
120
- }
121
-
122
- /** A connected subscription credential (metadata + usage), never the secret. */
123
- export interface VendorCredential {
124
- id: string
125
- vendor: SubscriptionVendor
126
- label: string
127
- createdAt: number
128
- lastUsedAt: number | null
129
- inputTokens: number
130
- outputTokens: number
131
- requestCount: number
132
- }
133
-
134
- /**
135
- * A curated best-practice "prompt fragment" served read-only by the backend
136
- * (`GET /prompt-fragments`). Users pick which apply to a block; the backend folds
137
- * the selected fragments' bodies into the agent system prompt at run time.
138
- */
139
- export interface PromptFragment {
140
- id: string
141
- version: string
142
- title: string
143
- category: string
144
- summary: string
145
- body: string
146
- appliesTo?: {
147
- blockTypes?: BlockType[]
148
- agentKinds?: AgentKind[]
149
- }
150
- /** Free-form tags the relevance selector uses (managed/sourced fragments only). */
151
- tags?: string[]
152
- /** Provenance when sourced from a repo; absent for built-in/hand-authored. */
153
- source?: {
154
- sourceId: string
155
- path: string
156
- sha: string
157
- }
158
- /**
159
- * Provenance when the body is a LIVING external document (Confluence/Notion/
160
- * GitHub). The body is re-resolved from the source at run time, not frozen.
161
- */
162
- documentRef?: {
163
- source: DocumentSourceKind
164
- externalId: string
165
- }
166
- /** When the document-backed body was last resolved from the source (epoch ms). */
167
- resolvedAt?: number
168
- }
5
+ //
6
+ // All wire shapes are sourced from @cat-factory/contracts (single source of truth).
7
+
8
+ export type {
9
+ SubscriptionVendor,
10
+ ModelCost,
11
+ ModelOption,
12
+ PersonalSubscriptionStatus,
13
+ StorePersonalSubscriptionInput,
14
+ ApiKeyScope,
15
+ ApiKeyProvider,
16
+ ApiKey,
17
+ AddApiKeyInput,
18
+ VendorCredential,
19
+ PromptFragment,
20
+ } from '@cat-factory/contracts'