@wardby/cli 0.3.0 → 0.4.1

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 (275) hide show
  1. package/.env.example +22 -3
  2. package/README.md +11 -9
  3. package/dist/cli-help.d.ts +1 -1
  4. package/dist/cli-help.js +1 -0
  5. package/dist/cli.js +68 -10
  6. package/dist/coding/base-commit.d.ts +6 -0
  7. package/dist/coding/base-commit.js +12 -0
  8. package/dist/coding/protocol.d.ts +17 -1
  9. package/dist/coding/protocol.js +17 -6
  10. package/dist/coding/provider.d.ts +6 -1
  11. package/dist/coding/provider.js +16 -9
  12. package/dist/config/providers.d.ts +25 -0
  13. package/dist/config/providers.js +71 -0
  14. package/dist/core/attribution.d.ts +101 -0
  15. package/dist/core/attribution.js +208 -0
  16. package/dist/core/budget-groups.d.ts +17 -10
  17. package/dist/core/budget-groups.js +15 -12
  18. package/dist/core/coding-queue.d.ts +3 -0
  19. package/dist/core/coding-queue.js +6 -2
  20. package/dist/core/coding-service-status.d.ts +11 -0
  21. package/dist/core/coding-service-status.js +17 -0
  22. package/dist/core/cost-report.d.ts +88 -0
  23. package/dist/core/cost-report.js +248 -0
  24. package/dist/core/dispatch.d.ts +42 -2
  25. package/dist/core/dispatch.js +144 -26
  26. package/dist/core/engine-native.js +17 -4
  27. package/dist/core/glob.d.ts +10 -0
  28. package/dist/core/glob.js +33 -0
  29. package/dist/core/host-events.d.ts +24 -1
  30. package/dist/core/host-events.js +341 -1
  31. package/dist/core/host-status.d.ts +19 -2
  32. package/dist/core/host-status.js +47 -30
  33. package/dist/core/issue-bridge.d.ts +60 -0
  34. package/dist/core/issue-bridge.js +189 -0
  35. package/dist/core/issue-dedupe.d.ts +70 -0
  36. package/dist/core/issue-dedupe.js +255 -0
  37. package/dist/core/issue-events.d.ts +42 -0
  38. package/dist/core/issue-events.js +155 -0
  39. package/dist/core/issue-status.d.ts +29 -0
  40. package/dist/core/issue-status.js +241 -0
  41. package/dist/core/issue-tracker-tools.d.ts +64 -0
  42. package/dist/core/issue-tracker-tools.js +850 -0
  43. package/dist/core/model-usage.d.ts +10 -0
  44. package/dist/core/model-usage.js +24 -0
  45. package/dist/core/reconciler.d.ts +8 -4
  46. package/dist/core/reconciler.js +15 -4
  47. package/dist/core/review-host-tools.js +10 -3
  48. package/dist/core/run-pricing.d.ts +61 -0
  49. package/dist/core/run-pricing.js +56 -0
  50. package/dist/core/runner.d.ts +5 -2
  51. package/dist/core/runner.js +178 -27
  52. package/dist/core/scheduler.d.ts +4 -1
  53. package/dist/core/scheduler.js +3 -2
  54. package/dist/core/self-defects.d.ts +80 -0
  55. package/dist/core/self-defects.js +180 -0
  56. package/dist/core/tool-names.js +3 -0
  57. package/dist/core/webhooks.d.ts +9 -1
  58. package/dist/core/webhooks.js +19 -1
  59. package/dist/env.js +6 -1
  60. package/dist/generated/prisma/browser.d.ts +66 -0
  61. package/dist/generated/prisma/client.d.ts +66 -0
  62. package/dist/generated/prisma/commonInputTypes.d.ts +122 -52
  63. package/dist/generated/prisma/enums.d.ts +7 -0
  64. package/dist/generated/prisma/enums.js +6 -0
  65. package/dist/generated/prisma/internal/class.d.ts +99 -0
  66. package/dist/generated/prisma/internal/class.js +4 -4
  67. package/dist/generated/prisma/internal/prismaNamespace.d.ts +826 -1
  68. package/dist/generated/prisma/internal/prismaNamespace.js +135 -2
  69. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +142 -0
  70. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +135 -2
  71. package/dist/generated/prisma/models/Agent.d.ts +389 -1
  72. package/dist/generated/prisma/models/AgentIssueProject.d.ts +1838 -0
  73. package/dist/generated/prisma/models/AgentIssueProject.js +1 -0
  74. package/dist/generated/prisma/models/AgentRepository.d.ts +1 -1
  75. package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
  76. package/dist/generated/prisma/models/CodingProxySession.d.ts +73 -1
  77. package/dist/generated/prisma/models/CodingRun.d.ts +130 -1
  78. package/dist/generated/prisma/models/CodingRunServiceStatus.d.ts +1404 -0
  79. package/dist/generated/prisma/models/CodingRunServiceStatus.js +1 -0
  80. package/dist/generated/prisma/models/IssueFingerprint.d.ts +1183 -0
  81. package/dist/generated/prisma/models/IssueFingerprint.js +1 -0
  82. package/dist/generated/prisma/models/IssuePullRequest.d.ts +1255 -0
  83. package/dist/generated/prisma/models/IssuePullRequest.js +1 -0
  84. package/dist/generated/prisma/models/ModelCatalogEntry.d.ts +1322 -0
  85. package/dist/generated/prisma/models/ModelCatalogEntry.js +1 -0
  86. package/dist/generated/prisma/models/Run.d.ts +933 -1
  87. package/dist/generated/prisma/models/RunAttribution.d.ts +1259 -0
  88. package/dist/generated/prisma/models/RunAttribution.js +1 -0
  89. package/dist/generated/prisma/models/RunIssueStatus.d.ts +1199 -0
  90. package/dist/generated/prisma/models/RunIssueStatus.js +1 -0
  91. package/dist/generated/prisma/models/RunModelUsage.d.ts +1316 -0
  92. package/dist/generated/prisma/models/RunModelUsage.js +1 -0
  93. package/dist/generated/prisma/models/WorkItem.d.ts +1408 -0
  94. package/dist/generated/prisma/models/WorkItem.js +1 -0
  95. package/dist/generated/prisma/models.d.ts +9 -0
  96. package/dist/help-index.json +355 -16
  97. package/dist/import/neutral-schema.d.ts +16 -16
  98. package/dist/knowledge/check.d.ts +13 -0
  99. package/dist/knowledge/check.js +69 -0
  100. package/dist/knowledge/cli.d.ts +14 -0
  101. package/dist/knowledge/cli.js +67 -0
  102. package/dist/knowledge/concept.d.ts +54 -0
  103. package/dist/knowledge/concept.js +78 -0
  104. package/dist/knowledge/note.d.ts +11 -0
  105. package/dist/knowledge/note.js +39 -0
  106. package/dist/knowledge/relevance.d.ts +11 -0
  107. package/dist/knowledge/relevance.js +14 -0
  108. package/dist/knowledge/span-hash.d.ts +3 -0
  109. package/dist/knowledge/span-hash.js +16 -0
  110. package/dist/mcp/auth/access.d.ts +4 -2
  111. package/dist/mcp/auth/ownership.d.ts +9 -9
  112. package/dist/mcp/auth/resource-server.d.ts +3 -1
  113. package/dist/mcp/auth/resource-server.js +18 -3
  114. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  115. package/dist/mcp/auth/self-hosted/session.d.ts +5 -5
  116. package/dist/mcp/context.d.ts +3 -0
  117. package/dist/mcp/host-events/deliveries.d.ts +9 -0
  118. package/dist/mcp/host-events/deliveries.js +17 -0
  119. package/dist/mcp/host-events/github-ingress.d.ts +4 -2
  120. package/dist/mcp/host-events/github-ingress.js +4 -13
  121. package/dist/mcp/host-events/jira-ingress.d.ts +29 -0
  122. package/dist/mcp/host-events/jira-ingress.js +92 -0
  123. package/dist/mcp/index.d.ts +2 -0
  124. package/dist/mcp/index.js +87 -9
  125. package/dist/mcp/server.js +5 -2
  126. package/dist/mcp/tools/agents.js +74 -3
  127. package/dist/mcp/tools/cost-report.d.ts +8 -0
  128. package/dist/mcp/tools/cost-report.js +60 -0
  129. package/dist/mcp/tools/issue-projects.d.ts +2 -0
  130. package/dist/mcp/tools/issue-projects.js +238 -0
  131. package/dist/mcp/tools/model-catalog.d.ts +22 -0
  132. package/dist/mcp/tools/model-catalog.js +423 -0
  133. package/dist/mcp/tools/repositories.js +2 -1
  134. package/dist/mcp/tools/tools.d.ts +2 -2
  135. package/dist/mcp/tools/trigger.js +33 -5
  136. package/dist/mcp/transport/streamable-http.d.ts +5 -0
  137. package/dist/mcp/transport/streamable-http.js +23 -1
  138. package/dist/mcp/webhooks/ingress.d.ts +2 -1
  139. package/dist/mcp/webhooks/ingress.js +9 -2
  140. package/dist/providers/auth/self-hosted.d.ts +8 -1
  141. package/dist/providers/auth/self-hosted.js +39 -2
  142. package/dist/providers/coding-proxy/memory-ledger.d.ts +1 -1
  143. package/dist/providers/coding-proxy/memory-ledger.js +10 -1
  144. package/dist/providers/coding-proxy/metering.d.ts +2 -1
  145. package/dist/providers/coding-proxy/metering.js +13 -2
  146. package/dist/providers/coding-proxy/prisma-ledger.js +59 -6
  147. package/dist/providers/coding-proxy/proxy.d.ts +12 -2
  148. package/dist/providers/coding-proxy/proxy.js +92 -30
  149. package/dist/providers/coding-proxy/types.d.ts +18 -1
  150. package/dist/providers/coding-proxy/types.js +12 -1
  151. package/dist/providers/engine/types.d.ts +19 -0
  152. package/dist/providers/executor/composition.js +9 -1
  153. package/dist/providers/executor/container.d.ts +30 -2
  154. package/dist/providers/executor/container.js +98 -17
  155. package/dist/providers/executor/dbos.d.ts +2 -0
  156. package/dist/providers/executor/dbos.js +7 -5
  157. package/dist/providers/executor/routing.d.ts +6 -0
  158. package/dist/providers/executor/routing.js +5 -0
  159. package/dist/providers/executor/types.d.ts +12 -0
  160. package/dist/providers/issue-tracker/adf.d.ts +31 -0
  161. package/dist/providers/issue-tracker/adf.js +181 -0
  162. package/dist/providers/issue-tracker/index.d.ts +5 -0
  163. package/dist/providers/issue-tracker/index.js +12 -0
  164. package/dist/providers/issue-tracker/jira-client.d.ts +41 -0
  165. package/dist/providers/issue-tracker/jira-client.js +151 -0
  166. package/dist/providers/issue-tracker/jira-events.d.ts +3 -0
  167. package/dist/providers/issue-tracker/jira-events.js +98 -0
  168. package/dist/providers/issue-tracker/jira.d.ts +116 -0
  169. package/dist/providers/issue-tracker/jira.js +502 -0
  170. package/dist/providers/issue-tracker/types.d.ts +269 -0
  171. package/dist/providers/issue-tracker/types.js +16 -0
  172. package/dist/providers/jobs/docker.d.ts +5 -1
  173. package/dist/providers/jobs/docker.js +61 -33
  174. package/dist/providers/jobs/kubernetes.d.ts +3 -0
  175. package/dist/providers/jobs/kubernetes.js +44 -4
  176. package/dist/providers/jobs/service-state.d.ts +22 -0
  177. package/dist/providers/jobs/service-state.js +17 -0
  178. package/dist/providers/llm/anthropic.d.ts +3 -3
  179. package/dist/providers/llm/anthropic.js +3 -9
  180. package/dist/providers/llm/bedrock.d.ts +3 -3
  181. package/dist/providers/llm/bedrock.js +3 -9
  182. package/dist/providers/llm/catalog-lookup.d.ts +10 -0
  183. package/dist/providers/llm/catalog-lookup.js +15 -0
  184. package/dist/providers/llm/catalog-shipped.d.ts +18 -0
  185. package/dist/providers/llm/catalog-shipped.js +197 -0
  186. package/dist/providers/llm/catalog-store.d.ts +58 -0
  187. package/dist/providers/llm/catalog-store.js +138 -0
  188. package/dist/providers/llm/catalog-types.d.ts +66 -0
  189. package/dist/providers/llm/catalog-types.js +64 -0
  190. package/dist/providers/llm/catalog.d.ts +61 -0
  191. package/dist/providers/llm/catalog.js +147 -0
  192. package/dist/providers/llm/claude-provider.d.ts +10 -14
  193. package/dist/providers/llm/claude-provider.js +11 -6
  194. package/dist/providers/llm/index.d.ts +9 -6
  195. package/dist/providers/llm/index.js +8 -5
  196. package/dist/providers/llm/openai.d.ts +14 -5
  197. package/dist/providers/llm/openai.js +24 -14
  198. package/dist/providers/llm/pricing-core.d.ts +5 -3
  199. package/dist/providers/llm/registration.js +8 -12
  200. package/dist/providers/llm/routing.d.ts +18 -17
  201. package/dist/providers/llm/routing.js +40 -24
  202. package/dist/providers/review-host/github-events.js +47 -1
  203. package/dist/providers/review-host/github.js +7 -6
  204. package/dist/providers/review-host/types.d.ts +25 -0
  205. package/dist/providers/vcs/git.js +2 -22
  206. package/dist/providers/vcs/github.d.ts +20 -0
  207. package/dist/providers/vcs/github.js +28 -2
  208. package/dist/providers/vcs/types.d.ts +6 -0
  209. package/dist/quickstart/index.d.ts +8 -0
  210. package/dist/quickstart/index.js +34 -34
  211. package/dist/serve.js +8 -2
  212. package/dist/viewer/api-schema.d.ts +2757 -0
  213. package/dist/viewer/api-schema.js +165 -0
  214. package/dist/viewer/build-schemas.d.ts +2 -0
  215. package/dist/viewer/build-schemas.js +18 -0
  216. package/dist/viewer/event-bus.d.ts +38 -0
  217. package/dist/viewer/event-bus.js +232 -0
  218. package/dist/viewer/graph.d.ts +40 -0
  219. package/dist/viewer/graph.js +243 -0
  220. package/dist/viewer/http.d.ts +30 -0
  221. package/dist/viewer/http.js +133 -0
  222. package/dist/viewer/run-detail.d.ts +4 -0
  223. package/dist/viewer/run-detail.js +61 -0
  224. package/dist/wardby-bin.js +5 -0
  225. package/docs/README.md +10 -0
  226. package/docs/agent-recipes.md +383 -0
  227. package/docs/code-review-agents.md +29 -2
  228. package/docs/coding-agent-setup.md +3 -0
  229. package/docs/coding-worker-isolation.md +39 -5
  230. package/docs/getting-started-gke.md +28 -11
  231. package/docs/getting-started-identity-provider.md +49 -38
  232. package/docs/getting-started.md +14 -0
  233. package/docs/jira-agents.md +649 -0
  234. package/docs/knowledge.md +387 -0
  235. package/docs/models.md +221 -0
  236. package/docs/security-deployment.md +19 -9
  237. package/docs/viewer-api.md +142 -0
  238. package/help/admin-viewer.md +39 -0
  239. package/help/agent-recipes.md +173 -0
  240. package/help/architecture-agent.md +189 -0
  241. package/help/builder-agent.md +80 -0
  242. package/help/code-review-agents.md +6 -0
  243. package/help/cost-attribution.md +67 -0
  244. package/help/creating-agents.md +22 -0
  245. package/help/deploy-gke.md +6 -0
  246. package/help/errors/model-unavailable.md +63 -0
  247. package/help/getting-started.md +1 -0
  248. package/help/github.md +18 -0
  249. package/help/identity-and-access.md +8 -3
  250. package/help/jira.md +135 -0
  251. package/help/knowledge.md +47 -0
  252. package/help/models.md +90 -0
  253. package/help/operating-agents.md +7 -1
  254. package/help/troubleshooting/budgets.md +6 -0
  255. package/package.json +5 -2
  256. package/prisma/migrations/20260930000000_jira_issue_projects/migration.sql +34 -0
  257. package/prisma/migrations/20261001000000_jira_phase2_allowlists/migration.sql +3 -0
  258. package/prisma/migrations/20261001010000_jira_link_types_allowlist/migration.sql +2 -0
  259. package/prisma/migrations/20261002000000_jira_coding_bridge/migration.sql +28 -0
  260. package/prisma/migrations/20261002010000_jira_issue_creation/migration.sql +25 -0
  261. package/prisma/migrations/20261003000000_issue_cost_attribution/migration.sql +56 -0
  262. package/prisma/migrations/20261003010000_coding_run_service_status/migration.sql +23 -0
  263. package/prisma/migrations/20261003020000_viewer_notify/migration.sql +54 -0
  264. package/prisma/migrations/20261003030000_viewer_notify_fixes/migration.sql +47 -0
  265. package/prisma/migrations/20261003040000_viewer_indexes/migration.sql +12 -0
  266. package/prisma/migrations/20261004000000_model_catalog/migration.sql +26 -0
  267. package/prisma/schema.prisma +258 -2
  268. package/dist/mcp/tools/models.d.ts +0 -8
  269. package/dist/mcp/tools/models.js +0 -15
  270. package/dist/providers/llm/pricing-anthropic.d.ts +0 -14
  271. package/dist/providers/llm/pricing-anthropic.js +0 -48
  272. package/dist/providers/llm/pricing-bedrock-claude.d.ts +0 -20
  273. package/dist/providers/llm/pricing-bedrock-claude.js +0 -46
  274. package/dist/providers/llm/pricing.d.ts +0 -30
  275. package/dist/providers/llm/pricing.js +0 -74
@@ -0,0 +1,28 @@
1
+ -- Jira phase 3 (the Jira -> code bridge): per-link PR statuses, the originating
2
+ -- issue on a coding run, and the pull requests opened for tracker issues.
3
+ ALTER TABLE "AgentIssueProject" ADD COLUMN "onPullRequestOpened" TEXT;
4
+ ALTER TABLE "AgentIssueProject" ADD COLUMN "onPullRequestMerged" TEXT;
5
+ ALTER TABLE "CodingRun" ADD COLUMN "issueProvider" TEXT;
6
+ ALTER TABLE "CodingRun" ADD COLUMN "issueKey" TEXT;
7
+
8
+ -- No foreign keys by design: audit-style rows that survive agent/run deletion.
9
+ CREATE TABLE "IssuePullRequest" (
10
+ "id" TEXT NOT NULL,
11
+ "issueProvider" TEXT NOT NULL,
12
+ "issueKey" TEXT NOT NULL,
13
+ "codeProvider" TEXT NOT NULL,
14
+ "repository" TEXT NOT NULL,
15
+ "number" INTEGER NOT NULL,
16
+ "url" TEXT NOT NULL,
17
+ "agentId" TEXT NOT NULL,
18
+ "openedByRunId" TEXT NOT NULL,
19
+ "state" TEXT NOT NULL DEFAULT 'open',
20
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
21
+ "updatedAt" TIMESTAMP(3) NOT NULL,
22
+
23
+ CONSTRAINT "IssuePullRequest_pkey" PRIMARY KEY ("id")
24
+ );
25
+
26
+ CREATE UNIQUE INDEX "IssuePullRequest_codeProvider_repository_number_issueProvid_key" ON "IssuePullRequest"("codeProvider", "repository", "number", "issueProvider", "issueKey");
27
+
28
+ CREATE INDEX "IssuePullRequest_issueProvider_issueKey_idx" ON "IssuePullRequest"("issueProvider", "issueKey");
@@ -0,0 +1,25 @@
1
+ -- Jira phase 4: issue creation allowlist + cap on the link, self-defect config on the agent, and dedupe fingerprints.
2
+ ALTER TABLE "AgentIssueProject" ADD COLUMN "creatableIssueTypes" TEXT[] DEFAULT ARRAY[]::TEXT[];
3
+ ALTER TABLE "AgentIssueProject" ADD COLUMN "maxNewIssuesPerRun" INTEGER;
4
+
5
+ ALTER TABLE "Agent" ADD COLUMN "defectProjectKey" TEXT;
6
+ ALTER TABLE "Agent" ADD COLUMN "defectIssueType" TEXT;
7
+
8
+ CREATE TABLE "IssueFingerprint" (
9
+ "id" TEXT NOT NULL,
10
+ "issueProvider" TEXT NOT NULL,
11
+ "projectKey" TEXT NOT NULL,
12
+ "fingerprintHash" TEXT NOT NULL,
13
+ "issueKey" TEXT NOT NULL,
14
+ "agentId" TEXT NOT NULL,
15
+ "createdByRunId" TEXT,
16
+ "seenCount" INTEGER NOT NULL DEFAULT 1,
17
+ "firstSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
18
+ "lastSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
19
+
20
+ CONSTRAINT "IssueFingerprint_pkey" PRIMARY KEY ("id")
21
+ );
22
+
23
+ CREATE UNIQUE INDEX "IssueFingerprint_issueProvider_issueKey_key" ON "IssueFingerprint"("issueProvider", "issueKey");
24
+ CREATE INDEX "IssueFingerprint_issueProvider_projectKey_fingerprintHash_idx" ON "IssueFingerprint"("issueProvider", "projectKey", "fingerprintHash");
25
+ CREATE INDEX "IssueFingerprint_createdByRunId_idx" ON "IssueFingerprint"("createdByRunId");
@@ -0,0 +1,56 @@
1
+ -- Issue cost attribution (Jira phase 4a): work items, per-run attribution,
2
+ -- and per-run per-model usage by priced token kind.
3
+
4
+ CREATE TABLE "WorkItem" (
5
+ "id" TEXT NOT NULL,
6
+ "provider" TEXT NOT NULL,
7
+ "key" TEXT NOT NULL,
8
+ "title" TEXT,
9
+ "type" TEXT,
10
+ "url" TEXT,
11
+ "scopeKey" TEXT NOT NULL,
12
+ "parentKey" TEXT,
13
+ "parentKind" TEXT,
14
+ "refreshedAt" TIMESTAMP(3),
15
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
16
+ "updatedAt" TIMESTAMP(3) NOT NULL,
17
+
18
+ CONSTRAINT "WorkItem_pkey" PRIMARY KEY ("id")
19
+ );
20
+
21
+ CREATE UNIQUE INDEX "WorkItem_provider_key_key" ON "WorkItem"("provider", "key");
22
+ CREATE INDEX "WorkItem_provider_parentKey_idx" ON "WorkItem"("provider", "parentKey");
23
+ CREATE INDEX "WorkItem_provider_scopeKey_idx" ON "WorkItem"("provider", "scopeKey");
24
+
25
+ CREATE TABLE "RunAttribution" (
26
+ "runId" TEXT NOT NULL,
27
+ "workItemId" TEXT NOT NULL,
28
+ "parentKeyAtRun" TEXT,
29
+ "source" TEXT NOT NULL,
30
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
31
+
32
+ CONSTRAINT "RunAttribution_pkey" PRIMARY KEY ("runId")
33
+ );
34
+
35
+ CREATE INDEX "RunAttribution_workItemId_idx" ON "RunAttribution"("workItemId");
36
+ CREATE INDEX "RunAttribution_parentKeyAtRun_idx" ON "RunAttribution"("parentKeyAtRun");
37
+
38
+ ALTER TABLE "RunAttribution" ADD CONSTRAINT "RunAttribution_runId_fkey"
39
+ FOREIGN KEY ("runId") REFERENCES "Run"("id") ON DELETE CASCADE ON UPDATE CASCADE;
40
+ ALTER TABLE "RunAttribution" ADD CONSTRAINT "RunAttribution_workItemId_fkey"
41
+ FOREIGN KEY ("workItemId") REFERENCES "WorkItem"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
42
+
43
+ CREATE TABLE "RunModelUsage" (
44
+ "runId" TEXT NOT NULL,
45
+ "model" TEXT NOT NULL,
46
+ "freshInputTokens" INTEGER NOT NULL DEFAULT 0,
47
+ "cachedInputTokens" INTEGER NOT NULL DEFAULT 0,
48
+ "cacheWriteTokens" INTEGER NOT NULL DEFAULT 0,
49
+ "outputTokens" INTEGER NOT NULL DEFAULT 0,
50
+ "costUsd" DECIMAL(18,10) NOT NULL DEFAULT 0,
51
+
52
+ CONSTRAINT "RunModelUsage_pkey" PRIMARY KEY ("runId", "model")
53
+ );
54
+
55
+ ALTER TABLE "RunModelUsage" ADD CONSTRAINT "RunModelUsage_runId_fkey"
56
+ FOREIGN KEY ("runId") REFERENCES "Run"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,23 @@
1
+ -- Live start-up state of each coding-run service, one row per run x service,
2
+ -- written by the job launchers for display (wardby viewer, get_run).
3
+ CREATE TYPE "CodingServiceState" AS ENUM ('pending', 'probing', 'ready', 'failed');
4
+
5
+ CREATE TABLE "CodingRunServiceStatus" (
6
+ "id" TEXT NOT NULL,
7
+ "runId" TEXT NOT NULL,
8
+ "name" TEXT NOT NULL,
9
+ "state" "CodingServiceState" NOT NULL DEFAULT 'pending',
10
+ "attempts" INTEGER,
11
+ "reason" TEXT,
12
+ "readyAt" TIMESTAMP(3),
13
+ "failedAt" TIMESTAMP(3),
14
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
15
+ "updatedAt" TIMESTAMP(3) NOT NULL,
16
+
17
+ CONSTRAINT "CodingRunServiceStatus_pkey" PRIMARY KEY ("id")
18
+ );
19
+
20
+ CREATE UNIQUE INDEX "CodingRunServiceStatus_runId_name_key" ON "CodingRunServiceStatus"("runId", "name");
21
+
22
+ ALTER TABLE "CodingRunServiceStatus" ADD CONSTRAINT "CodingRunServiceStatus_runId_fkey"
23
+ FOREIGN KEY ("runId") REFERENCES "Run"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,54 @@
1
+ -- Live events for the admin viewer (docs/viewer-api.md): small pg_notify
2
+ -- payloads on channel wardby_viewer. Runs as the writing role; pg_notify
3
+ -- needs no grant. Payloads stay far below NOTIFY's 8000-byte limit.
4
+ CREATE FUNCTION wardby_viewer_notify() RETURNS trigger LANGUAGE plpgsql AS $$
5
+ DECLARE
6
+ payload jsonb;
7
+ BEGIN
8
+ IF TG_TABLE_NAME = 'Run' THEN
9
+ IF TG_OP = 'UPDATE'
10
+ AND NEW."status" IS NOT DISTINCT FROM OLD."status"
11
+ AND NEW."turns" IS NOT DISTINCT FROM OLD."turns"
12
+ AND NEW."costUsd" IS NOT DISTINCT FROM OLD."costUsd"
13
+ AND NEW."tokensIn" IS NOT DISTINCT FROM OLD."tokensIn"
14
+ AND NEW."tokensOut" IS NOT DISTINCT FROM OLD."tokensOut"
15
+ AND NEW."finishedAt" IS NOT DISTINCT FROM OLD."finishedAt"
16
+ AND NEW."parentRunId" IS NOT DISTINCT FROM OLD."parentRunId" THEN
17
+ RETURN NULL; -- heartbeat-only and other invisible updates
18
+ END IF;
19
+ payload := jsonb_build_object(
20
+ 'kind', 'run', 'runId', NEW."id", 'parentRunId', NEW."parentRunId", 'agentId', NEW."agentId",
21
+ 'status', NEW."status", 'turns', NEW."turns", 'tokensIn', NEW."tokensIn", 'tokensOut', NEW."tokensOut",
22
+ 'costUsd', NEW."costUsd"::float8,
23
+ 'finishedAt', to_char(NEW."finishedAt" AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'));
24
+ ELSIF TG_TABLE_NAME = 'CodingRunServiceStatus' THEN
25
+ payload := jsonb_build_object(
26
+ 'kind', 'service', 'runId', NEW."runId", 'name', NEW."name", 'state', NEW."state", 'attempts', NEW."attempts");
27
+ ELSIF TG_TABLE_NAME = 'IssuePullRequest' THEN
28
+ payload := jsonb_build_object('kind', 'outcome', 'runId', NEW."openedByRunId", 'source', 'pull_request');
29
+ ELSIF TG_TABLE_NAME = 'RunHostStatus' THEN
30
+ payload := jsonb_build_object('kind', 'outcome', 'runId', NEW."runId", 'source', 'host_status');
31
+ ELSIF TG_TABLE_NAME = 'RunIssueStatus' THEN
32
+ payload := jsonb_build_object('kind', 'outcome', 'runId', NEW."runId", 'source', 'issue_status');
33
+ ELSIF TG_TABLE_NAME = 'RunHostCheck' THEN
34
+ payload := jsonb_build_object('kind', 'outcome', 'runId', NEW."runId", 'source', 'host_check');
35
+ ELSE
36
+ RETURN NULL;
37
+ END IF;
38
+ PERFORM pg_notify('wardby_viewer', payload::text);
39
+ RETURN NULL;
40
+ END;
41
+ $$;
42
+
43
+ CREATE TRIGGER "Run_viewer_notify" AFTER INSERT OR UPDATE ON "Run"
44
+ FOR EACH ROW EXECUTE FUNCTION wardby_viewer_notify();
45
+ CREATE TRIGGER "CodingRunServiceStatus_viewer_notify" AFTER INSERT OR UPDATE ON "CodingRunServiceStatus"
46
+ FOR EACH ROW EXECUTE FUNCTION wardby_viewer_notify();
47
+ CREATE TRIGGER "IssuePullRequest_viewer_notify" AFTER INSERT OR UPDATE ON "IssuePullRequest"
48
+ FOR EACH ROW EXECUTE FUNCTION wardby_viewer_notify();
49
+ CREATE TRIGGER "RunHostStatus_viewer_notify" AFTER INSERT OR UPDATE ON "RunHostStatus"
50
+ FOR EACH ROW EXECUTE FUNCTION wardby_viewer_notify();
51
+ CREATE TRIGGER "RunIssueStatus_viewer_notify" AFTER INSERT OR UPDATE ON "RunIssueStatus"
52
+ FOR EACH ROW EXECUTE FUNCTION wardby_viewer_notify();
53
+ CREATE TRIGGER "RunHostCheck_viewer_notify" AFTER INSERT OR UPDATE ON "RunHostCheck"
54
+ FOR EACH ROW EXECUTE FUNCTION wardby_viewer_notify();
@@ -0,0 +1,47 @@
1
+ -- Fixes for wardby_viewer_notify(): finishedAt formatting under a non-UTC
2
+ -- session TimeZone (the column is timestamp without time zone, already UTC),
3
+ -- and notification failures never fail the write. The triggers are unchanged.
4
+ CREATE OR REPLACE FUNCTION wardby_viewer_notify() RETURNS trigger LANGUAGE plpgsql AS $$
5
+ DECLARE
6
+ payload jsonb;
7
+ BEGIN
8
+ IF TG_TABLE_NAME = 'Run' THEN
9
+ IF TG_OP = 'UPDATE'
10
+ AND NEW."status" IS NOT DISTINCT FROM OLD."status"
11
+ AND NEW."turns" IS NOT DISTINCT FROM OLD."turns"
12
+ AND NEW."costUsd" IS NOT DISTINCT FROM OLD."costUsd"
13
+ AND NEW."tokensIn" IS NOT DISTINCT FROM OLD."tokensIn"
14
+ AND NEW."tokensOut" IS NOT DISTINCT FROM OLD."tokensOut"
15
+ AND NEW."finishedAt" IS NOT DISTINCT FROM OLD."finishedAt"
16
+ AND NEW."parentRunId" IS NOT DISTINCT FROM OLD."parentRunId" THEN
17
+ RETURN NULL; -- heartbeat-only and other invisible updates
18
+ END IF;
19
+ payload := jsonb_build_object(
20
+ 'kind', 'run', 'runId', NEW."id", 'parentRunId', NEW."parentRunId", 'agentId', NEW."agentId",
21
+ 'status', NEW."status", 'turns', NEW."turns", 'tokensIn', NEW."tokensIn", 'tokensOut', NEW."tokensOut",
22
+ 'costUsd', NEW."costUsd"::float8,
23
+ 'finishedAt', to_char(NEW."finishedAt", 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'));
24
+ ELSIF TG_TABLE_NAME = 'CodingRunServiceStatus' THEN
25
+ payload := jsonb_build_object(
26
+ 'kind', 'service', 'runId', NEW."runId", 'name', NEW."name", 'state', NEW."state", 'attempts', NEW."attempts");
27
+ ELSIF TG_TABLE_NAME = 'IssuePullRequest' THEN
28
+ payload := jsonb_build_object('kind', 'outcome', 'runId', NEW."openedByRunId", 'source', 'pull_request');
29
+ ELSIF TG_TABLE_NAME = 'RunHostStatus' THEN
30
+ payload := jsonb_build_object('kind', 'outcome', 'runId', NEW."runId", 'source', 'host_status');
31
+ ELSIF TG_TABLE_NAME = 'RunIssueStatus' THEN
32
+ payload := jsonb_build_object('kind', 'outcome', 'runId', NEW."runId", 'source', 'issue_status');
33
+ ELSIF TG_TABLE_NAME = 'RunHostCheck' THEN
34
+ payload := jsonb_build_object('kind', 'outcome', 'runId', NEW."runId", 'source', 'host_check');
35
+ ELSE
36
+ RETURN NULL;
37
+ END IF;
38
+ -- A viewer event must never fail the write that caused it (e.g. a payload
39
+ -- over NOTIFY's 8000-byte limit).
40
+ BEGIN
41
+ PERFORM pg_notify('wardby_viewer', payload::text);
42
+ EXCEPTION WHEN OTHERS THEN
43
+ NULL;
44
+ END;
45
+ RETURN NULL;
46
+ END;
47
+ $$;
@@ -0,0 +1,12 @@
1
+ -- Indexes for the admin viewer's queries (docs/viewer-api.md): the graph
2
+ -- window (runs started since a time, or still pending/running), the
3
+ -- ancestor/children walks, and the outcome lookup by run. Plain CREATE INDEX
4
+ -- briefly blocks writes to each table while it builds; on a large existing
5
+ -- deployment, apply this migration in a quiet period.
6
+ CREATE INDEX "Run_startedAt_idx" ON "Run"("startedAt");
7
+
8
+ CREATE INDEX "Run_status_idx" ON "Run"("status");
9
+
10
+ CREATE INDEX "Run_parentRunId_idx" ON "Run"("parentRunId");
11
+
12
+ CREATE INDEX "IssuePullRequest_openedByRunId_idx" ON "IssuePullRequest"("openedByRunId");
@@ -0,0 +1,26 @@
1
+ -- Model catalog: admin overrides of the shipped catalog, and each run's
2
+ -- catalog entry as recorded when it started. Additive only.
3
+ CREATE TABLE "ModelCatalogEntry" (
4
+ "provider" TEXT NOT NULL,
5
+ "modelId" TEXT NOT NULL,
6
+ "enabled" BOOLEAN NOT NULL,
7
+ "encoding" TEXT NOT NULL,
8
+ "inputPerMTok" DOUBLE PRECISION NOT NULL,
9
+ "outputPerMTok" DOUBLE PRECISION NOT NULL,
10
+ "cachedInputPerMTok" DOUBLE PRECISION NOT NULL,
11
+ "cacheWritePerMTok" DOUBLE PRECISION NOT NULL,
12
+ "efforts" TEXT[],
13
+ "thinkingMode" TEXT NOT NULL,
14
+ "sourceUrl" TEXT NOT NULL,
15
+ "updatedBy" TEXT NOT NULL,
16
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
17
+ "updatedAt" TIMESTAMP(3) NOT NULL,
18
+
19
+ CONSTRAINT "ModelCatalogEntry_pkey" PRIMARY KEY ("provider","modelId")
20
+ );
21
+
22
+ ALTER TABLE "Run" ADD COLUMN "pricingVersion" TEXT;
23
+ ALTER TABLE "Run" ADD COLUMN "pricingSnapshot" JSONB;
24
+
25
+ ALTER TABLE "CodingProxySession" ADD COLUMN "pricingVersion" TEXT;
26
+ ALTER TABLE "CodingProxySession" ADD COLUMN "catalogEntry" JSONB;
@@ -52,6 +52,11 @@ model Agent {
52
52
  datastores AgentDatastore[]
53
53
  webhooks Webhook[]
54
54
  repositories AgentRepository[]
55
+ issueProjects AgentIssueProject[]
56
+
57
+ /// Self-defects opt-in: the Jira project and issue type wardby files the agent's own failures into. Both or neither.
58
+ defectProjectKey String?
59
+ defectIssueType String?
55
60
 
56
61
  // Phase 7: at most one budget group. Null = uncapped beyond its own budgetUsd.
57
62
  budgetGroupId String?
@@ -325,6 +330,12 @@ model Run {
325
330
  /// finalText — MCP's list_runs/get_run need it and it was previously
326
331
  /// dropped after the engine returned.
327
332
  turns Int @default(0)
333
+ /// The run's model catalog entry, recorded when it started (native: the
334
+ /// runner's load step; coding: dispatch). The run is billed at these rates
335
+ /// for its whole life, resumes included. Null on runs from before the
336
+ /// model catalog.
337
+ pricingVersion String?
338
+ pricingSnapshot Json?
328
339
  /// Detached executors are recovered by handle rather than inferred from trigger.
329
340
  executionManaged Boolean @default(false)
330
341
  /// Phase 6: which durable executor backend holds this run, if any
@@ -335,6 +346,10 @@ model Run {
335
346
  codingRun CodingRun?
336
347
  hostCheck RunHostCheck?
337
348
  hostStatus RunHostStatus?
349
+ issueStatus RunIssueStatus?
350
+ attribution RunAttribution?
351
+ modelUsage RunModelUsage[]
352
+ serviceStatuses CodingRunServiceStatus[]
338
353
 
339
354
  /// Un-phased: sub-agent dispatch (see AgentSubAgent). Null for a
340
355
  /// top-level run; set when this run was created by a parent run's
@@ -365,6 +380,11 @@ model Run {
365
380
  triggeredById String?
366
381
 
367
382
  @@index([agentId, triggeredById])
383
+ /// The admin viewer's graph window (runs started since a time, or still
384
+ /// pending/running) and its ancestor/children walks (docs/viewer-api.md).
385
+ @@index([startedAt])
386
+ @@index([status])
387
+ @@index([parentRunId])
368
388
  }
369
389
 
370
390
  /// Phase 5: owner-configured coding behavior. Runtime credentials and opaque
@@ -448,6 +468,9 @@ model CodingRun {
448
468
  /// .wardby/services.yaml: one snapshot per service (the catalog entry minus
449
469
  /// kind), fixed for the run's lifetime. Empty = none.
450
470
  services Json @default("[]")
471
+ /// The originating tracker issue ("jira" + key), set by the control plane from the run tree, never from model output.
472
+ issueProvider String?
473
+ issueKey String?
451
474
  createdAt DateTime @default(now())
452
475
  updatedAt DateTime @updatedAt
453
476
  proxySession CodingProxySession?
@@ -509,6 +532,37 @@ model CodingService {
509
532
  @@unique([name, version])
510
533
  }
511
534
 
535
+ enum CodingServiceState {
536
+ pending
537
+ probing
538
+ ready
539
+ failed
540
+ }
541
+
542
+ /// Live start-up state of one coding-run service (one row per run x
543
+ /// service), written by the job launcher as it observes the service, for
544
+ /// display only (the viewer). The run's CodingRun.services
545
+ /// snapshot says what was started; this says how far each one got.
546
+ /// `attempts` is the readiness probes made so far, known only where wardby
547
+ /// runs the probe itself (Docker); `reason` is a fixed identifier
548
+ /// (image_unavailable, start_failed, exited, probe_failed, timed_out),
549
+ /// never probe output.
550
+ model CodingRunServiceStatus {
551
+ id String @id @default(cuid())
552
+ runId String
553
+ run Run @relation(fields: [runId], references: [id], onDelete: Cascade)
554
+ name String
555
+ state CodingServiceState @default(pending)
556
+ attempts Int?
557
+ reason String?
558
+ readyAt DateTime?
559
+ failedAt DateTime?
560
+ createdAt DateTime @default(now())
561
+ updatedAt DateTime @updatedAt
562
+
563
+ @@unique([runId, name])
564
+ }
565
+
512
566
  enum CodingProxySessionStatus {
513
567
  active
514
568
  cancelled
@@ -547,6 +601,12 @@ model CodingProxySession {
547
601
  /// first provider failure the proxy relayed for this session; lets the
548
602
  /// executor say the model provider refused the run.
549
603
  upstreamFailure String?
604
+ /// The run's catalog entry, copied from Run.pricingSnapshot when the session
605
+ /// is created; the proxy prices and shapes requests from it. Null on
606
+ /// sessions from before the model catalog (the proxy falls back to the
607
+ /// shipped catalog).
608
+ pricingVersion String?
609
+ catalogEntry Json?
550
610
 
551
611
  @@index([deadlineAt])
552
612
  }
@@ -871,7 +931,7 @@ model AuthUser {
871
931
  displayName String?
872
932
  status String @default("enabled")
873
933
  /// wardby roles (src/mcp/auth/resource-server.ts ROLE_PERMISSIONS: admin,
874
- /// package-approver, service-manager), set with `wardby auth user grant`. Empty = member.
934
+ /// package-approver, service-manager, model-manager), set with `wardby auth user grant`. Empty = member.
875
935
  /// A privileged operation needs its scope on the token AND a role here
876
936
  /// that grants it; unknown values grant nothing.
877
937
  roles String[] @default([])
@@ -999,7 +1059,7 @@ model AgentRepository {
999
1059
  repository String
1000
1060
  /// "read" or "write".
1001
1061
  access String
1002
- /// Subset of "pull_request", "mention".
1062
+ /// Subset of "pull_request", "mention", "push".
1003
1063
  triggers String[] @default([])
1004
1064
  /// Only with the "pull_request" trigger (required there); names the agent's
1005
1065
  /// check. Unique per repository across all links (NULLs are distinct).
@@ -1115,3 +1175,199 @@ model HostIdentityLinkRequest {
1115
1175
  @@index([principalId])
1116
1176
  @@index([expiresAt])
1117
1177
  }
1178
+
1179
+ /// Which issue-tracker projects (Jira today) a native agent may act on, and
1180
+ /// which issue events trigger it. Admin-approved in phase 1 (no way to verify
1181
+ /// an owner's Jira access). See
1182
+ /// docs/private/2026-09-30-jira-issue-tracker-design.md §3.
1183
+ model AgentIssueProject {
1184
+ id String @id @default(cuid())
1185
+ agentId String
1186
+ agent Agent @relation(fields: [agentId], references: [id], onDelete: Cascade)
1187
+ /// "jira" today; validated in code.
1188
+ provider String
1189
+ /// Upper-case Jira project key.
1190
+ projectKey String
1191
+ /// "read" or "write".
1192
+ access String
1193
+ /// Subset of "created", "transitioned", "labeled", "assigned", "mention".
1194
+ triggers String[] @default([])
1195
+ /// With "transitioned": the status names (case-insensitive) that trigger.
1196
+ triggerStatuses String[] @default([])
1197
+ /// With "labeled": the labels whose addition triggers.
1198
+ triggerLabels String[] @default([])
1199
+ /// Optional JQL the issue must also match for any trigger.
1200
+ jqlFilter String?
1201
+ /// Jira accountIds whose @-mention or assignment may trigger (required for those triggers).
1202
+ trustedAccountIds String[] @default([])
1203
+ /// Optional project role that the agent's comments are restricted to.
1204
+ commentVisibilityRole String?
1205
+ /// Target status names (case-insensitive) jira_transition may move issues to. Empty = no transitions.
1206
+ allowedTransitions String[] @default([])
1207
+ /// Field ids jira_update_fields may change ("labels", "components", "priority", "customfield_NNNNN"). Empty = none.
1208
+ writableFields String[] @default([])
1209
+ /// Issue link type names (case-insensitive) jira_link_issues may create. Empty = linking off.
1210
+ allowedLinkTypes String[] @default([])
1211
+ /// Status to move the issue to when a pull request for it opens (a control-plane move, not gated by allowedTransitions). Null = none.
1212
+ onPullRequestOpened String?
1213
+ /// Status to move the issue to when a pull request for it merges. Null = none.
1214
+ onPullRequestMerged String?
1215
+ /// Issue type names (case-insensitive) jira_create_issue may create. Empty = creation off.
1216
+ creatableIssueTypes String[] @default([])
1217
+ /// Cap on issues one run may create in this project. Null = no cap.
1218
+ maxNewIssuesPerRun Int?
1219
+ authorizedById String
1220
+ authorizedAt DateTime @default(now())
1221
+ createdAt DateTime @default(now())
1222
+
1223
+ @@unique([agentId, provider, projectKey])
1224
+ @@index([provider, projectKey])
1225
+ }
1226
+
1227
+ /// Dedupe record: an issue wardby created for a fingerprint (several over time — regressions).
1228
+ model IssueFingerprint {
1229
+ id String @id @default(cuid())
1230
+ issueProvider String
1231
+ projectKey String
1232
+ /// sha256 hex of the agent- or control-plane-supplied fingerprint (raw value never stored).
1233
+ fingerprintHash String
1234
+ issueKey String
1235
+ agentId String
1236
+ createdByRunId String?
1237
+ seenCount Int @default(1)
1238
+ firstSeenAt DateTime @default(now())
1239
+ lastSeenAt DateTime @default(now())
1240
+
1241
+ @@unique([issueProvider, issueKey])
1242
+ @@index([issueProvider, projectKey, fingerprintHash])
1243
+ @@index([createdByRunId])
1244
+ }
1245
+
1246
+ /// A pull request wardby opened for a tracker issue (the Jira -> code bridge). Provider-neutral on both sides.
1247
+ /// Deliberately no foreign keys to Agent or Run: audit-style rows that survive agent/run deletion.
1248
+ model IssuePullRequest {
1249
+ id String @id @default(cuid())
1250
+ /// "jira"
1251
+ issueProvider String
1252
+ issueKey String
1253
+ /// "github" today; "bitbucket" next.
1254
+ codeProvider String
1255
+ repository String
1256
+ number Int
1257
+ url String
1258
+ /// The issue-linked agent whose run tree opened it (the parent native agent).
1259
+ agentId String
1260
+ /// The coding run that opened it (continuePriorRun target for follow-ups).
1261
+ openedByRunId String
1262
+ /// "open" | "merged" | "closed"
1263
+ state String @default("open")
1264
+ createdAt DateTime @default(now())
1265
+ updatedAt DateTime @updatedAt
1266
+
1267
+ @@unique([codeProvider, repository, number, issueProvider, issueKey])
1268
+ @@index([issueProvider, issueKey])
1269
+ /// The admin viewer's outcome lookup by run.
1270
+ @@index([openedByRunId])
1271
+ }
1272
+
1273
+ /// The status comment wardby posts on the Jira issue whose event started this
1274
+ /// run ("working on it"), edited with the outcome when the run ends.
1275
+ model RunIssueStatus {
1276
+ runId String @id
1277
+ run Run @relation(fields: [runId], references: [id], onDelete: Cascade)
1278
+ provider String
1279
+ issueKey String
1280
+ /// Null until the "working on it" comment is posted.
1281
+ commentId String?
1282
+ visibilityRole String?
1283
+ createdAt DateTime @default(now())
1284
+ completedAt DateTime?
1285
+
1286
+ @@index([completedAt])
1287
+ }
1288
+
1289
+ /// Latest known state of an issue/epic in an external tracker (Jira, later
1290
+ /// Linear). Shared by every run attributed to it; titles are refreshed by the
1291
+ /// next snapshot, so reports always show current names.
1292
+ model WorkItem {
1293
+ id String @id @default(cuid())
1294
+ /// "jira" | "linear" | ...
1295
+ provider String
1296
+ /// PAY-241, ENG-123
1297
+ key String
1298
+ title String?
1299
+ type String?
1300
+ url String?
1301
+ /// Jira project / Linear team.
1302
+ scopeKey String
1303
+ /// The current parent (epic or parent issue), refreshed on each snapshot.
1304
+ parentKey String?
1305
+ /// "epic" | "parent" | ...
1306
+ parentKind String?
1307
+ /// Last successful snapshot; null = key-only (never snapshotted).
1308
+ refreshedAt DateTime?
1309
+ createdAt DateTime @default(now())
1310
+ updatedAt DateTime @updatedAt
1311
+ attributions RunAttribution[]
1312
+
1313
+ @@unique([provider, key])
1314
+ @@index([provider, parentKey])
1315
+ @@index([provider, scopeKey])
1316
+ }
1317
+
1318
+ /// Which work item a run's cost belongs to, with its parent frozen as of
1319
+ /// dispatch. Written in dispatchRun's persist transaction; child runs copy
1320
+ /// their parent's row (source "inherited"). Control-plane data only.
1321
+ model RunAttribution {
1322
+ runId String @id
1323
+ run Run @relation(fields: [runId], references: [id], onDelete: Cascade)
1324
+ workItemId String
1325
+ workItem WorkItem @relation(fields: [workItemId], references: [id])
1326
+ parentKeyAtRun String?
1327
+ /// issue_event | linked_pr | explicit | inherited
1328
+ source String
1329
+ createdAt DateTime @default(now())
1330
+
1331
+ @@index([workItemId])
1332
+ @@index([parentKeyAtRun])
1333
+ }
1334
+
1335
+ /// Per-run, per-model usage by priced token kind. Sum of costUsd over a
1336
+ /// run's rows equals Run.costUsd (to Run.costUsd's 6 decimal places).
1337
+ model RunModelUsage {
1338
+ runId String
1339
+ run Run @relation(fields: [runId], references: [id], onDelete: Cascade)
1340
+ model String
1341
+ /// Input tokens NOT served from cache (LlmUsage.inputTokens - cachedInputTokens).
1342
+ freshInputTokens Int @default(0)
1343
+ cachedInputTokens Int @default(0)
1344
+ cacheWriteTokens Int @default(0)
1345
+ outputTokens Int @default(0)
1346
+ costUsd Decimal @default(0) @db.Decimal(18, 10)
1347
+
1348
+ @@id([runId, model])
1349
+ }
1350
+
1351
+ /// A deployment's override of the shipped model catalog
1352
+ /// (src/providers/llm/catalog-shipped.ts), written by set_model /
1353
+ /// disable_model (models:admin). A row fully replaces the shipped entry with
1354
+ /// the same key; enabled=false removes the model; a row with no shipped match
1355
+ /// adds one. Rates are the provider's exact published numbers (sourceUrl).
1356
+ model ModelCatalogEntry {
1357
+ provider String
1358
+ modelId String
1359
+ enabled Boolean
1360
+ encoding String
1361
+ inputPerMTok Float
1362
+ outputPerMTok Float
1363
+ cachedInputPerMTok Float
1364
+ cacheWritePerMTok Float
1365
+ efforts String[]
1366
+ thinkingMode String
1367
+ sourceUrl String
1368
+ updatedBy String
1369
+ createdAt DateTime @default(now())
1370
+ updatedAt DateTime @updatedAt
1371
+
1372
+ @@id([provider, modelId])
1373
+ }
@@ -1,8 +0,0 @@
1
- /**
2
- * Read-only lookup for which model IDs the deployment actually has an LLM
3
- * provider registered for — without it, the only way to learn a valid
4
- * model name was to trigger a run and read the "Known models" list off a
5
- * failed run's error message.
6
- */
7
- import type { WardbyMcpServer } from "../server.js";
8
- export declare function registerModelTools(mcp: WardbyMcpServer): void;
@@ -1,15 +0,0 @@
1
- import { textResult } from "./text-result.js";
2
- export function registerModelTools(mcp) {
3
- mcp.registerTool({
4
- name: "list_models",
5
- scope: "agents:read",
6
- inputSchema: { type: "object", properties: {} },
7
- handler: async (_args, ctx) => {
8
- // Production always wires ctx.providers.llm as a RoutingLlmProvider
9
- // (see buildMcpProviders in mcp/index.ts) — listModels() is specific
10
- // to that composite router, not part of the single-provider LlmProvider seam.
11
- const llm = ctx.providers.llm;
12
- return textResult({ models: llm.listModels() });
13
- },
14
- });
15
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Anthropic direct-API pricing table. Every entry is a fully literal,
3
- * hardcoded ModelPricing — every field, including cache read/write, is the
4
- * provider's own published rate for that exact model, never derived from
5
- * another field via a ratio (see CLAUDE.md "LLM pricing tables — STRICT": a
6
- * multiplier that happens to be correct today silently goes stale the
7
- * moment one model's real cache pricing diverges from the pattern).
8
- */
9
- import { type ModelPricing, type UsageTokens } from "./pricing-core.js";
10
- import type { LlmEffort } from "./types.js";
11
- export declare function anthropicSupportedEfforts(model: string): readonly LlmEffort[];
12
- export declare function getAnthropicPricing(model: string): ModelPricing;
13
- export declare function anthropicSupportedModels(): string[];
14
- export declare function anthropicPriceUsd(model: string, usage: UsageTokens): number;