@ipul-labs/forge 1.13.2 → 1.14.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 (64) hide show
  1. package/README.md +137 -91
  2. package/package.json +9 -20
  3. package/server/forge/core/ForgeAgent.js +12 -2
  4. package/server/forge/core/claudeClient.js +3 -1
  5. package/server/forge/core/prompts.js +45 -1
  6. package/server/forge/routes.js +3 -0
  7. package/dist-lib/favicon.svg +0 -8
  8. package/dist-lib/index.d.ts +0 -1
  9. package/dist-lib/style.css +0 -1
  10. package/dist-lib/ui.d.ts +0 -2
  11. package/dist-lib/ui.js +0 -5922
  12. package/dist-lib/views/Forge/ForgeDashboard.d.ts +0 -5
  13. package/dist-lib/views/Forge/activeJobs.d.ts +0 -29
  14. package/dist-lib/views/Forge/analysisCache.d.ts +0 -64
  15. package/dist-lib/views/Forge/api.d.ts +0 -4
  16. package/dist-lib/views/Forge/components/AnalysisProgress.d.ts +0 -13
  17. package/dist-lib/views/Forge/components/CITerminal.d.ts +0 -44
  18. package/dist-lib/views/Forge/components/DiffViewer.d.ts +0 -37
  19. package/dist-lib/views/Forge/components/ForgeConnect.d.ts +0 -6
  20. package/dist-lib/views/Forge/components/IssueList.d.ts +0 -28
  21. package/dist-lib/views/Forge/components/MRStatus.d.ts +0 -9
  22. package/dist-lib/views/Forge/components/NewTaskModal.d.ts +0 -1
  23. package/dist-lib/views/Forge/components/OpenMRList.d.ts +0 -11
  24. package/dist-lib/views/Forge/components/PipelineStatus.d.ts +0 -12
  25. package/dist-lib/views/Forge/components/PipelinesList.d.ts +0 -9
  26. package/dist-lib/views/Forge/components/RolloutStatus.d.ts +0 -5
  27. package/dist-lib/views/Forge/components/UsageWidget.d.ts +0 -8
  28. package/dist-lib/views/Forge/components/ValidationPanel.d.ts +0 -22
  29. package/dist-lib/views/Forge/context/ForgeProvider.d.ts +0 -23
  30. package/dist-lib/views/Forge/hooks/useConfig.d.ts +0 -54
  31. package/dist-lib/views/Forge/hooks/useForgeDashboard.d.ts +0 -107
  32. package/dist-lib/views/Forge/hooks/useForgeQuota.d.ts +0 -22
  33. package/dist-lib/views/Forge/phases/AnalyzingView.d.ts +0 -1
  34. package/dist-lib/views/Forge/phases/IdleView.d.ts +0 -1
  35. package/dist-lib/views/Forge/phases/MonitoringIssueTab.d.ts +0 -1
  36. package/dist-lib/views/Forge/phases/MonitoringPipelineTab.d.ts +0 -1
  37. package/dist-lib/views/Forge/phases/MonitoringView.d.ts +0 -1
  38. package/dist-lib/views/Forge/phases/ReviewingView.d.ts +0 -1
  39. package/dist-lib/views/Forge/phases/SelectedIssueTab.d.ts +0 -11
  40. package/dist-lib/views/Forge/phases/SelectedMRTab.d.ts +0 -1
  41. package/dist-lib/views/Forge/phases/SelectedView.d.ts +0 -1
  42. package/dist-lib/views/Forge/phases/shared/CloseIssueConfirm.d.ts +0 -1
  43. package/dist-lib/views/Forge/phases/shared/DetailTabs.d.ts +0 -14
  44. package/dist-lib/views/Forge/phases/shared/EnvironmentsPanel.d.ts +0 -9
  45. package/dist-lib/views/Forge/phases/shared/ForgeActivity.d.ts +0 -1
  46. package/dist-lib/views/Forge/phases/shared/IssueHeaderBlock.d.ts +0 -13
  47. package/dist-lib/views/Forge/phases/shared/MergedMRList.d.ts +0 -4
  48. package/dist-lib/views/Forge/phases/shared/PreviousAnalyses.d.ts +0 -1
  49. package/dist-lib/views/Forge/phases/shared/ResolutionCheckPanel.d.ts +0 -6
  50. package/dist-lib/views/Forge/settings/ConnectionRow.d.ts +0 -16
  51. package/dist-lib/views/Forge/settings/ConnectionsSection.d.ts +0 -7
  52. package/dist-lib/views/Forge/settings/DefaultsSection.d.ts +0 -7
  53. package/dist-lib/views/Forge/settings/ReposSection.d.ts +0 -7
  54. package/dist-lib/views/Forge/settings/SettingsView.d.ts +0 -1
  55. package/dist-lib/views/Forge/shell/ConfigBar.d.ts +0 -1
  56. package/dist-lib/views/Forge/shell/ForgeRouter.d.ts +0 -9
  57. package/dist-lib/views/Forge/shell/ForgeShell.d.ts +0 -7
  58. package/dist-lib/views/Forge/shell/Sidebar.d.ts +0 -1
  59. package/dist-lib/views/Forge/shell/SidebarFooterMenu.d.ts +0 -1
  60. package/dist-lib/views/Forge/shell/SidebarNav.d.ts +0 -1
  61. package/dist-lib/views/Forge/shell/SidebarNavItem.d.ts +0 -10
  62. package/dist-lib/views/Forge/shell/TopBar.d.ts +0 -5
  63. package/dist-lib/views/Forge/types.d.ts +0 -235
  64. package/dist-lib/views/Forge/utils.d.ts +0 -11
package/README.md CHANGED
@@ -30,32 +30,112 @@ Everything else fills in the gaps that matter for real teams:
30
30
 
31
31
  ---
32
32
 
33
- ## Quick start
33
+ ## Getting started
34
+
35
+ ### Prerequisites
36
+
37
+ - Node.js 20+
38
+ - `claude` CLI installed and authenticated (`claude auth login`)
39
+ - Credentials for your SCM provider (see [Configuration](#configuration))
40
+
41
+ ### Install
42
+
43
+ ```bash
44
+ git clone https://gitlab.com/ipul-labs/forge.git
45
+ cd forge
46
+ npm install
47
+ ```
48
+
49
+ ### Configure
50
+
51
+ ```bash
52
+ # Interactive setup — writes .env and ~/.forge/config.json
53
+ npx forge init
54
+ ```
55
+
56
+ Or copy the example env and fill in the values manually:
34
57
 
35
58
  ```bash
36
59
  cp .env.example .env
37
- # fill in FORGE_TOKEN plus your provider credentials (see Configuration below)
60
+ # fill in FORGE_TOKEN plus your provider credentials
61
+ ```
38
62
 
39
- npm install
63
+ ### Launch the UI
64
+
65
+ ```bash
40
66
  npm run dev
41
- # open http://localhost:5000
67
+ # opens http://localhost:5000 (frontend) with API on :5001
42
68
  ```
43
69
 
44
- ### Prerequisites
70
+ For production:
45
71
 
46
- - Node.js 20+
47
- - `claude` CLI installed and authenticated (`claude auth login`)
48
- - Credentials for your SCM provider (see below)
72
+ ```bash
73
+ npm run build:app # builds Vite SPA to dist/
74
+ npm start # NODE_ENV=production node server.js
75
+ ```
49
76
 
50
- ### Headless / CLI
77
+ ### CLI usage
78
+
79
+ The `forge` CLI drives the same orchestrator from the terminal. Install globally or use `npx`:
80
+
81
+ ```bash
82
+ # Global install (adds `forge` to PATH)
83
+ npm install -g @ipul-labs/forge
84
+
85
+ # Or run via npx from the repo
86
+ npx forge <command>
87
+ ```
88
+
89
+ #### End-to-end: issue to production
90
+
91
+ ```bash
92
+ forge ship 42
93
+ ```
94
+
95
+ Runs: analyze → review → validate → apply → watch CI → merge → watch deploy → close, with a `y/N` gate at every state-changing step.
96
+
97
+ #### Step-by-step commands
98
+
99
+ ```bash
100
+ forge issues # List open issues (--label X, --mine, --limit N)
101
+ forge issue 42 # Show full description
102
+ forge analyze 42 # Run two-pass analysis, cache result
103
+ forge show # Re-render cached analysis
104
+ forge refine --feedback "..." # Iterate with feedback
105
+ forge validate # Run lint/typecheck/test against proposed changes
106
+ forge apply # Push branch + open MR
107
+ forge watch # Poll the MR pipeline
108
+ forge ci-fix # Re-analyze with failed-pipeline logs
109
+ forge merge # Merge the MR
110
+ forge resolution-check # Verify merged MR closes the issue
111
+ forge close # Close the issue
112
+ ```
113
+
114
+ #### Options
115
+
116
+ ```
117
+ -p, --port <n> Port for start
118
+ --repo <group/repo> Primary repo
119
+ --secondary <repo> Additional repo (repeatable)
120
+ --all-repos Include every configured repo
121
+ --model <id> Claude model override
122
+ --agent <name> Agent backend: claude | openclaw
123
+ --prompt <text> Extra user prompt
124
+ --json JSON output
125
+ --quiet Suppress progress
126
+ --yes Skip confirmation gates
127
+ --validate Run validate before apply
128
+ ```
51
129
 
52
- The `forge-agent` bin drives the same orchestrator from the terminal — one command takes an issue all the way to production:
130
+ #### Diagnostics
53
131
 
54
132
  ```bash
55
- forge-agent ship 42
133
+ forge doctor # Check prerequisites (node, claude CLI, env vars)
134
+ forge session list # List cached sessions
135
+ forge session clean # Remove stale session data
56
136
  ```
57
137
 
58
- …analyze → review → validate → apply → watch CI → merge → watch deploy → close, with a `y/N` gate at every state-changing step. See [`bin/README.md`](./bin/README.md) for a quick start, [`docs/cli.md`](./docs/cli.md) for the full command reference, and [`docs/cli-ship-workflow.md`](./docs/cli-ship-workflow.md) for the workflow design.
138
+ See [`docs/cli.md`](./docs/cli.md) for the full command reference and [`docs/cli-ship-workflow.md`](./docs/cli-ship-workflow.md) for the workflow design.
59
139
 
60
140
  ---
61
141
 
@@ -65,7 +145,7 @@ forge-agent ship 42
65
145
 
66
146
  | Variable | Required | Description |
67
147
  |---|---|---|
68
- | `FORGE_TOKEN` | ✅ | Dashboard password — users enter this to access Forge |
148
+ | `FORGE_TOKEN` | Yes | Dashboard password — users enter this to access Forge |
69
149
  | `SCM_PROVIDER` | — | `gitlab` (default) · `github` · `azuredevops` |
70
150
  | `FORGE_REPOS` | — | Comma-separated repo list for multi-repo support |
71
151
  | `ANTHROPIC_API_KEY` | — | Enables live model list from Anthropic; falls back to hardcoded list |
@@ -81,25 +161,25 @@ forge-agent ship 42
81
161
 
82
162
  | Variable | Required | Description |
83
163
  |---|---|---|
84
- | `FORGE_GITLAB_PROJECT` | ✅ | Default project path, e.g. `group/repo` |
85
- | `GITLAB_TOKEN` | ✅ | Personal access token with `api` + `write_repository` scopes |
164
+ | `FORGE_GITLAB_PROJECT` | Yes | Default project path, e.g. `group/repo` |
165
+ | `GITLAB_TOKEN` | Yes | Personal access token with `api` + `write_repository` scopes |
86
166
 
87
167
  ### GitHub (`SCM_PROVIDER=github`)
88
168
 
89
169
  | Variable | Required | Description |
90
170
  |---|---|---|
91
- | `GITHUB_TOKEN` | ✅ | Personal access token with `repo` + `workflow` scopes |
92
- | `GITHUB_OWNER` | ✅ | Organization or user, e.g. `ipul-labs` |
93
- | `GITHUB_REPO` | ✅ | Repository name, e.g. `web-app` |
171
+ | `GITHUB_TOKEN` | Yes | Personal access token with `repo` + `workflow` scopes |
172
+ | `GITHUB_OWNER` | Yes | Organization or user, e.g. `ipul-labs` |
173
+ | `GITHUB_REPO` | Yes | Repository name, e.g. `web-app` |
94
174
  | `GITHUB_BASE_BRANCH` | — | Default target branch (default: `main`) |
95
175
 
96
176
  ### Azure DevOps (`SCM_PROVIDER=azuredevops`)
97
177
 
98
178
  | Variable | Required | Description |
99
179
  |---|---|---|
100
- | `AZURE_DEVOPS_TOKEN` | ✅ | Personal access token (Full access or Code + Work Items) |
101
- | `AZURE_DEVOPS_ORG` | ✅ | Organization name, e.g. `ipul-labs` |
102
- | `AZURE_DEVOPS_PROJECT` | ✅ | Team project name, e.g. `web-app` |
180
+ | `AZURE_DEVOPS_TOKEN` | Yes | Personal access token (Full access or Code + Work Items) |
181
+ | `AZURE_DEVOPS_ORG` | Yes | Organization name, e.g. `ipul-labs` |
182
+ | `AZURE_DEVOPS_PROJECT` | Yes | Team project name, e.g. `web-app` |
103
183
  | `AZURE_DEVOPS_REPO` | — | Git repo name (defaults to project name) |
104
184
  | `AZURE_DEVOPS_BASE_BRANCH` | — | Default target branch (default: `main`) |
105
185
 
@@ -131,75 +211,19 @@ FORGE_REPOS=gitlab:ipul/web-app,github:my-org/mobile
131
211
 
132
212
  | Feature | GitLab | GitHub | Azure DevOps |
133
213
  |---|---|---|---|
134
- | Issues / Work Items | ✅ | ✅ | ✅ (Work Items) |
135
- | Multi-file commits | ✅ | ✅ (Git Data API) | ✅ (Pushes API) |
136
- | Merge / Pull Requests | ✅ | ✅ | ✅ |
137
- | CI pipelines | ✅ GitLab CI | ✅ GitHub Actions | ✅ Azure Pipelines |
138
- | Job log traces | ✅ | ✅ | ✅ |
139
- | Server-side rebase | ✅ | — | — |
140
-
141
- ---
142
-
143
- ## Using as an npm package
144
-
145
- Mount the Forge Express router alongside your own app:
146
-
147
- ```js
148
- import express from "express";
149
- import forgeRouter from "forge-agent";
150
-
151
- const app = express();
152
- app.use("/api/forge", express.json(), forgeRouter);
153
- ```
154
-
155
- The router reads all config from `process.env` — no constructor arguments needed.
156
-
157
- ### Available exports
158
-
159
- ```js
160
- import forgeRouter from "forge-agent"; // Express router
161
- import { ForgeAgent } from "forge-agent/agent"; // Core pipeline class
162
- import { createProvider } from "forge-agent/providers"; // SCM provider factory
163
- ```
164
-
165
- #### `ForgeAgent`
166
-
167
- ```js
168
- const agent = new ForgeAgent({ project: "group/repo" });
169
-
170
- // Analyze an issue and stream progress events
171
- const result = await agent.analyzeIssue(issueIid, (event) => {
172
- console.log(event); // { type: "progress" | "result" | "error" | "usage", ... }
173
- });
174
-
175
- // Apply the analysis: creates branch + commit + MR/PR
176
- const { branchName, mr } = await agent.applyFix(result);
177
-
178
- // Refine with reviewer feedback
179
- await agent.refineIssue(issueIid, result.changes, "use the existing logger utility");
180
-
181
- // Push to an existing branch (for CI fixes)
182
- await agent.commitToBranch(branchName, result);
183
- ```
184
-
185
- #### `createProvider`
186
-
187
- ```js
188
- import { createProvider } from "forge-agent/providers";
189
-
190
- const provider = createProvider("github:my-org/my-repo");
191
-
192
- const issues = await provider.listOpenIssues();
193
- const mr = await provider.getMR(42);
194
- const diffs = await provider.getMRDiffs(42);
195
- ```
214
+ | Issues / Work Items | Yes | Yes | Yes (Work Items) |
215
+ | Multi-file commits | Yes | Yes (Git Data API) | Yes (Pushes API) |
216
+ | Merge / Pull Requests | Yes | Yes | Yes |
217
+ | CI pipelines | Yes (GitLab CI) | Yes (GitHub Actions) | Yes (Azure Pipelines) |
218
+ | Job log traces | Yes | Yes | Yes |
219
+ | Server-side rebase | Yes | — | — |
196
220
 
197
221
  ---
198
222
 
199
223
  ## Production deployment
200
224
 
201
225
  ```bash
202
- npm run build # builds Vite SPA → dist/
226
+ npm run build:app # builds Vite SPA to dist/
203
227
  NODE_ENV=production node server.js
204
228
  ```
205
229
 
@@ -215,15 +239,23 @@ docker run -p 5001:5001 --env-file .env forge
215
239
  ## Architecture
216
240
 
217
241
  ```
242
+ bin/
243
+ forge-agent.js # CLI entry point (forge command)
244
+ cli/
245
+ ship.js # End-to-end orchestrator (Ink UI)
246
+ analyze.js # Two-pass issue analysis
247
+ resolution.js # Post-merge resolution check
248
+ sessionStore.js # ~/.forge/sessions/ persistence
249
+ ...
250
+
218
251
  server/
219
252
  forge/
220
253
  routes.js # Express router — all /api/forge/* endpoints
221
254
  core/
222
- ForgeAgent.js # Orchestrates the full pipeline (analyze → apply → refine)
255
+ ForgeAgent.js # Orchestrates the full pipeline (analyze -> apply -> refine)
223
256
  claudeClient.js # Shells out to the claude CLI for structured output
224
257
  openclawClient.js # OpenClaw Gateway HTTP client
225
258
  agentClient.js # Dispatcher: routes to claudeClient or openclawClient
226
- gitlabClient.js # Legacy shim (kept for backward compatibility)
227
259
  k8s.js # Kubernetes client for rollout monitoring
228
260
  providers/
229
261
  base.js # Abstract ScmProvider — normalized shapes + interface
@@ -238,11 +270,7 @@ src/
238
270
  api.ts # Token management + fetch helper
239
271
  types.ts # Shared TypeScript types
240
272
  utils.ts # SSE helper + state utilities
241
- components/
242
- AnalysisProgress.tsx # Streaming progress display (analyze + ci-fix modes)
243
- PipelineStatus.tsx # CI pipeline + per-job log traces
244
- MRStatus.tsx # MR conflict/rebase banner + inline diff viewer
245
- OpenMRList.tsx # All open Forge MRs with pipeline badges
273
+ components/ # Analysis progress, pipeline status, diff viewer
246
274
  hooks/
247
275
  useForgeDashboard.ts # All state, phase transitions, and API calls
248
276
  ```
@@ -268,6 +296,24 @@ All three SCM providers implement `ScmProvider` from `providers/base.js`. The co
268
296
 
269
297
  ---
270
298
 
299
+ ## Programmatic usage
300
+
301
+ Mount the Forge Express router or use the core classes directly:
302
+
303
+ ```js
304
+ import forgeRouter from "@ipul-labs/forge"; // Express router
305
+ import { ForgeAgent } from "@ipul-labs/forge/agent"; // Core pipeline class
306
+ import { createProvider } from "@ipul-labs/forge/providers"; // SCM factory
307
+ ```
308
+
309
+ ```js
310
+ const agent = new ForgeAgent({ project: "group/repo" });
311
+ const result = await agent.analyzeIssue(42, (event) => console.log(event));
312
+ const { branchName, mr } = await agent.applyFix(result);
313
+ ```
314
+
315
+ ---
316
+
271
317
  ## License
272
318
 
273
319
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ipul-labs/forge",
3
- "version": "1.13.2",
3
+ "version": "1.14.1",
4
4
  "description": "AI-powered code change & deploy control panel — connects Claude, GitLab, and Kubernetes",
5
5
  "type": "module",
6
6
  "main": "server/forge/routes.js",
@@ -10,24 +10,16 @@
10
10
  "exports": {
11
11
  ".": "./server/forge/routes.js",
12
12
  "./agent": "./server/forge/core/ForgeAgent.js",
13
- "./gitlab": "./server/forge/core/gitlabClient.js",
14
- "./ui": {
15
- "import": "./dist-lib/ui.js",
16
- "types": "./dist-lib/ui.d.ts"
17
- },
18
- "./style.css": "./dist-lib/style.css"
13
+ "./providers": "./server/forge/core/providers/index.js"
19
14
  },
20
15
  "files": [
21
16
  "bin",
22
17
  "server/forge",
23
- "dist",
24
- "dist-lib"
18
+ "dist"
25
19
  ],
26
20
  "scripts": {
27
21
  "dev": "trap 'kill 0' EXIT INT TERM; FORGE_NO_VITE=1 node --watch-path=./server --watch-path=./server.js server.js & vite; wait",
28
- "build": "vite build --mode lib",
29
- "build:app": "vite build",
30
- "prepare": "npm run build",
22
+ "build": "vite build",
31
23
  "start": "NODE_ENV=production node server.js",
32
24
  "typecheck": "tsc --noEmit"
33
25
  },
@@ -40,7 +32,10 @@
40
32
  "ink": "^7.0.1",
41
33
  "ink-select-input": "^6.2.0",
42
34
  "ink-spinner": "^5.0.0",
43
- "ink-text-input": "^6.0.0"
35
+ "ink-text-input": "^6.0.0",
36
+ "react": "^19.0.0",
37
+ "react-dom": "^19.0.0",
38
+ "react-router-dom": "^7.14.1"
44
39
  },
45
40
  "devDependencies": {
46
41
  "@semantic-release/changelog": "^6.0.3",
@@ -58,13 +53,7 @@
58
53
  "semantic-release": "^25.0.3",
59
54
  "tailwindcss": "^3.4.14",
60
55
  "typescript": "^5.6.0",
61
- "vite": "^5.4.0",
62
- "vite-plugin-dts": "^4.3.0"
63
- },
64
- "peerDependencies": {
65
- "react": "^18.0.0 || ^19.0.0",
66
- "react-dom": "^18.0.0 || ^19.0.0",
67
- "react-router-dom": "^7.0.0"
56
+ "vite": "^5.4.0"
68
57
  },
69
58
  "engines": {
70
59
  "node": ">=20.0.0"
@@ -350,7 +350,7 @@ export class ForgeAgent {
350
350
  * @param {string} [userPrompt]
351
351
  * @returns {Promise<AnalysisResult>}
352
352
  */
353
- async analyzeIssue(issueIid, onProgress, model, ciContext, userPrompt, kind = "fresh", opts = {}) {
353
+ async analyzeIssue(issueIid, onProgress, model, ciContext, userPrompt, kind = "fresh", opts = {}, previousChanges = null) {
354
354
  const emit = onProgress ?? (() => {});
355
355
  const { signal } = opts;
356
356
 
@@ -416,7 +416,7 @@ export class ForgeAgent {
416
416
  const propose = await proposeFix(
417
417
  issue,
418
418
  fileContents,
419
- { ciContext, userPrompt, repos: this.allRepos },
419
+ { ciContext, userPrompt, previousChanges, repos: this.allRepos },
420
420
  model,
421
421
  this.agent,
422
422
  { signal },
@@ -859,6 +859,16 @@ export class ForgeAgent {
859
859
  }
860
860
 
861
861
  const provider = this._provider(repo);
862
+
863
+ // Rebase onto latest main before pushing so CI runs against current code.
864
+ try {
865
+ const mrs = await provider.listAllForgeMRs();
866
+ const mr = mrs.find((m) => m.source_branch === branchName);
867
+ if (mr && provider.supportsRebase) {
868
+ await provider.rebaseMR(mr.iid);
869
+ }
870
+ } catch { /* rebase failure is non-fatal — push will still work */ }
871
+
862
872
  const actions = changes.map((c) => ({ action: c.action, file_path: c.file, content: c.proposed }));
863
873
  const subject = buildCommitSubject(analysis);
864
874
  const commitMessage = buildCommitMessage(subject, changes, analysis, "ci-fix");
@@ -14,6 +14,7 @@ import { spawn } from "child_process";
14
14
  import {
15
15
  SELECT_FILES_SCHEMA,
16
16
  PROPOSE_FIX_SCHEMA,
17
+ CI_FIX_SCHEMA,
17
18
  REFINE_OR_ASK_SCHEMA,
18
19
  RESOLUTION_CHECK_SCHEMA,
19
20
  buildIdentifyFilesPrompt,
@@ -332,9 +333,10 @@ Your final message MUST be a single raw JSON object matching the schema — no p
332
333
  }
333
334
 
334
335
  export async function proposeFix(issue, fileContents, options = {}, model, opts = {}) {
336
+ const schema = options.ciContext ? CI_FIX_SCHEMA : PROPOSE_FIX_SCHEMA;
335
337
  const { data, cost, serviceTier, inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens } = await runClaude(
336
338
  buildProposeFixPrompt(issue, fileContents, options),
337
- PROPOSE_FIX_SCHEMA,
339
+ schema,
338
340
  `You are Forge, an AI code assistant in a production React/TypeScript/Express codebase.
339
341
  Rules:
340
342
  - Changes must be minimal and surgical.
@@ -61,6 +61,43 @@ export const PROPOSE_FIX_SCHEMA = JSON.stringify({
61
61
  required: ["title", "explanation", "changes"],
62
62
  });
63
63
 
64
+ export const CI_FIX_SCHEMA = JSON.stringify({
65
+ type: "object",
66
+ properties: {
67
+ unfixable: {
68
+ type: "boolean",
69
+ description: "True ONLY when the failure cannot be resolved by any source-code or package.json change (e.g. Docker registry outage, runner OOM, flaky network). Default false.",
70
+ },
71
+ unfixableReason: {
72
+ type: "string",
73
+ description: "Required when unfixable=true. One sentence explaining why no code change can fix this.",
74
+ },
75
+ title: {
76
+ type: "string",
77
+ description: "Conventional-commit MR title describing the actual fix, e.g. 'fix: resolve token refresh race condition in AuthService'. Max 72 chars. No issue number.",
78
+ },
79
+ explanation: {
80
+ type: "string",
81
+ description: "2-4 sentences on root cause and approach. If changes span multiple repos, describe how the pieces fit together.",
82
+ },
83
+ changes: {
84
+ type: "array",
85
+ items: {
86
+ type: "object",
87
+ properties: {
88
+ repo: { type: "string", description: "Repository id this change belongs to, exactly as given in the 'Available repositories' list." },
89
+ file: { type: "string", description: "Path from that repo's root." },
90
+ action: { type: "string", enum: ["create", "modify", "delete"] },
91
+ proposed: { type: "string", description: "For create/modify: the COMPLETE new file content. For delete: empty string." },
92
+ summary: { type: "string", description: "One sentence describing this file's change." },
93
+ },
94
+ required: ["repo", "file", "action", "proposed", "summary"],
95
+ },
96
+ },
97
+ },
98
+ required: ["title", "explanation", "changes"],
99
+ });
100
+
64
101
  export const REFINE_OR_ASK_SCHEMA = JSON.stringify({
65
102
  type: "object",
66
103
  properties: {
@@ -198,7 +235,14 @@ export function buildProposeFixPrompt(issue, fileContents, options = {}) {
198
235
  : "";
199
236
 
200
237
  const ciBlock = ciContext?.trim()
201
- ? `\n\n## CI pipeline failure logs\nThe pipeline failed. Propose changes that fix the pipeline.\n\n${ciContext.trim()}`
238
+ ? `\n\n## CI pipeline failure logs
239
+ The pipeline failed. Read the logs carefully and classify the failure:
240
+
241
+ 1. **Code/test failure** — broken imports, type errors, failing assertions → propose the source-code fix.
242
+ 2. **Dependency audit failure** (npm audit, yarn audit) — a package has a known vulnerability → update the version constraint in package.json. Do NOT touch package-lock.json; the lock file will be regenerated automatically.
243
+ 3. **Unfixable infrastructure failure** — Docker registry outage, runner OOM, network timeout, flaky CI runner → set "unfixable": true and explain why in "unfixableReason". Return an empty "changes" array.
244
+
245
+ ${ciContext.trim()}`
202
246
  : "";
203
247
 
204
248
  const userBlock = userPrompt?.trim()
@@ -575,6 +575,8 @@ router.post("/issues/:iid/analyze", (req, res) => {
575
575
  ? req.body.kind
576
576
  : "fresh";
577
577
 
578
+ const previousChanges = Array.isArray(req.body.previousChanges) ? req.body.previousChanges : null;
579
+
578
580
  const jobId = jobStore.createJob("analyze", (send, signal) =>
579
581
  agent.analyzeIssue(
580
582
  Number(iid),
@@ -584,6 +586,7 @@ router.post("/issues/:iid/analyze", (req, res) => {
584
586
  req.body.prompt || undefined,
585
587
  kind,
586
588
  { signal },
589
+ previousChanges,
587
590
  ),
588
591
  );
589
592
  res.json({ jobId });
@@ -1,8 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
2
- <path fill="#111" d="M6.814 33.279c-1.166 1.166-3.021 1.221-4.121.121-1.1-1.1-1.045-2.955.121-4.121L26.079 6.014c1.167-1.167 3.021-1.221 4.121-.121 1.101 1.1 1.046 2.955-.121 4.121L6.814 33.279z"/>
3
- <path fill="#111" d="M32.585 7.657c.781-.781.781-2.048 0-2.829l-1.414-1.414c-.78-.78-2.047-.78-2.828 0-.781.781-.781 2.048 0 2.829l1.414 1.414c.781.781 2.048.781 2.828 0z"/>
4
- <path fill="#66757F" d="M35.789 13.424c-.252-1.765-.375-4.354-3.204-7.182l-.707-.708-4.949-4.95c-.781-.781-2.048-.781-2.828 0L20.565 4.12c-.781.781-.781 2.047 0 2.829l6.364 6.364 2.121 2.121 1.414 1.414c1.027 1.027 3.314 3.315 4.718 1.911.773-.772.961-2.86.607-5.335z"/>
5
- <path fill="#111" d="M29.185 33.279c1.166 1.166 3.022 1.221 4.121.121 1.1-1.1 1.045-2.955-.121-4.121L9.921 6.014C8.754 4.847 6.899 4.792 5.8 5.893c-1.101 1.1-1.046 2.955.121 4.121l23.264 23.265z"/>
6
- <path fill="#111" d="M3.415 7.657c-.781-.781-.781-2.048 0-2.829l1.414-1.414c.78-.78 2.047-.78 2.828 0 .781.781.781 2.048 0 2.829L6.243 7.657c-.781.781-2.048.781-2.828 0z"/>
7
- <path fill="#66757F" d="M4.122 15.436c.78.78 2.047.78 2.828 0l8.485-8.485c.781-.781.781-2.048 0-2.829L11.899.587c-.78-.781-2.047-.781-2.828 0L.586 9.071c-.781.781-.781 2.047 0 2.828l3.536 3.537z"/>
8
- </svg>
@@ -1 +0,0 @@
1
- export { ForgeDashboard } from './views/Forge/ForgeDashboard';
@@ -1 +0,0 @@
1
- .visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.bottom-full{bottom:100%}.left-0{left:0}.right-0{right:0}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-10{margin-left:2.5rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-5{margin-left:1.25rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.line-clamp-1{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.hidden{display:none}.h-1\.5{height:.375rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-20{height:5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-32{height:8rem}.h-4{height:1rem}.h-screen{height:100vh}.max-h-12{max-height:3rem}.max-h-32{max-height:8rem}.max-h-40{max-height:10rem}.max-h-48{max-height:12rem}.max-h-56{max-height:14rem}.max-h-64{max-height:16rem}.max-h-80{max-height:20rem}.max-h-\[50vh\]{max-height:50vh}.max-h-\[60vh\]{max-height:60vh}.max-h-\[65vh\]{max-height:65vh}.min-h-0{min-height:0px}.min-h-10{min-height:2.5rem}.min-h-\[12rem\]{min-height:12rem}.min-h-\[40vh\]{min-height:40vh}.min-h-\[60vh\]{min-height:60vh}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-36{width:9rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.select-all{-webkit-user-select:all;-moz-user-select:all;user-select:all}.resize-none{resize:none}.resize-y{resize:vertical}.list-none{list-style-type:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-10{gap:2.5rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.self-start{align-self:flex-start}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-t-0{border-top-width:0px}.border-dashed{border-style:dashed}.border-amber-300{--tw-border-opacity: 1;border-color:rgb(252 211 77 / var(--tw-border-opacity, 1))}.border-amber-700{--tw-border-opacity: 1;border-color:rgb(180 83 9 / var(--tw-border-opacity, 1))}.border-amber-700\/50{border-color:#b4530980}.border-amber-800{--tw-border-opacity: 1;border-color:rgb(146 64 14 / var(--tw-border-opacity, 1))}.border-amber-800\/40{border-color:#92400e66}.border-amber-800\/60{border-color:#92400e99}.border-amber-900{--tw-border-opacity: 1;border-color:rgb(120 53 15 / var(--tw-border-opacity, 1))}.border-amber-900\/40{border-color:#78350f66}.border-current{border-color:currentColor}.border-emerald-800\/40{border-color:#065f4666}.border-emerald-800\/60{border-color:#065f4699}.border-green-800{--tw-border-opacity: 1;border-color:rgb(22 101 52 / var(--tw-border-opacity, 1))}.border-red-800{--tw-border-opacity: 1;border-color:rgb(153 27 27 / var(--tw-border-opacity, 1))}.border-red-800\/50{border-color:#991b1b80}.border-red-800\/60{border-color:#991b1b99}.border-red-800\/70{border-color:#991b1bb3}.border-red-900{--tw-border-opacity: 1;border-color:rgb(127 29 29 / var(--tw-border-opacity, 1))}.border-red-900\/60{border-color:#7f1d1d99}.border-sky-800\/60{border-color:#07598599}.border-transparent{border-color:transparent}.border-violet-300{--tw-border-opacity: 1;border-color:rgb(196 181 253 / var(--tw-border-opacity, 1))}.border-violet-400{--tw-border-opacity: 1;border-color:rgb(167 139 250 / var(--tw-border-opacity, 1))}.border-violet-500\/70{border-color:#8b5cf6b3}.border-violet-600{--tw-border-opacity: 1;border-color:rgb(124 58 237 / var(--tw-border-opacity, 1))}.border-violet-600\/40{border-color:#7c3aed66}.border-violet-700\/50{border-color:#6d28d980}.border-violet-800\/60{border-color:#5b21b699}.border-violet-900\/50{border-color:#4c1d9580}.border-yellow-400{--tw-border-opacity: 1;border-color:rgb(250 204 21 / var(--tw-border-opacity, 1))}.border-zinc-400{--tw-border-opacity: 1;border-color:rgb(161 161 170 / var(--tw-border-opacity, 1))}.border-zinc-500{--tw-border-opacity: 1;border-color:rgb(113 113 122 / var(--tw-border-opacity, 1))}.border-zinc-600{--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1))}.border-zinc-700{--tw-border-opacity: 1;border-color:rgb(63 63 70 / var(--tw-border-opacity, 1))}.border-zinc-700\/50{border-color:#3f3f4680}.border-zinc-800{--tw-border-opacity: 1;border-color:rgb(39 39 42 / var(--tw-border-opacity, 1))}.border-zinc-800\/60{border-color:#27272a99}.\!border-b-violet-500{--tw-border-opacity: 1 !important;border-bottom-color:rgb(139 92 246 / var(--tw-border-opacity, 1))!important}.\!border-t-violet-500{--tw-border-opacity: 1 !important;border-top-color:rgb(139 92 246 / var(--tw-border-opacity, 1))!important}.border-t-transparent{border-top-color:transparent}.bg-amber-500\/60{background-color:#f59e0b99}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-amber-600\/40{background-color:#d9770666}.bg-amber-900\/50{background-color:#78350f80}.bg-amber-950\/20{background-color:#451a0333}.bg-amber-950\/30{background-color:#451a034d}.bg-amber-950\/40{background-color:#451a0366}.bg-amber-950\/60{background-color:#451a0399}.bg-black\/60{background-color:#0009}.bg-cyan-900\/50{background-color:#164e6380}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity, 1))}.bg-emerald-500\/60{background-color:#10b98199}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity, 1))}.bg-emerald-900\/40{background-color:#064e3b66}.bg-emerald-950\/50{background-color:#022c2280}.bg-green-400{--tw-bg-opacity: 1;background-color:rgb(74 222 128 / var(--tw-bg-opacity, 1))}.bg-green-950\/40{background-color:#052e1666}.bg-orange-400{--tw-bg-opacity: 1;background-color:rgb(251 146 60 / var(--tw-bg-opacity, 1))}.bg-red-400{--tw-bg-opacity: 1;background-color:rgb(248 113 113 / var(--tw-bg-opacity, 1))}.bg-red-500\/60{background-color:#ef444499}.bg-red-700\/70{background-color:#b91c1cb3}.bg-red-800{--tw-bg-opacity: 1;background-color:rgb(153 27 27 / var(--tw-bg-opacity, 1))}.bg-red-900\/30{background-color:#7f1d1d4d}.bg-red-950\/30{background-color:#450a0a4d}.bg-red-950\/40{background-color:#450a0a66}.bg-sky-950\/30{background-color:#082f494d}.bg-sky-950\/50{background-color:#082f4980}.bg-violet-400{--tw-bg-opacity: 1;background-color:rgb(167 139 250 / var(--tw-bg-opacity, 1))}.bg-violet-600{--tw-bg-opacity: 1;background-color:rgb(124 58 237 / var(--tw-bg-opacity, 1))}.bg-violet-600\/15{background-color:#7c3aed26}.bg-violet-600\/25{background-color:#7c3aed40}.bg-violet-600\/40{background-color:#7c3aed66}.bg-violet-900\/40{background-color:#4c1d9566}.bg-violet-900\/50{background-color:#4c1d9580}.bg-violet-950\/30{background-color:#2e10654d}.bg-violet-950\/50{background-color:#2e106580}.bg-yellow-400{--tw-bg-opacity: 1;background-color:rgb(250 204 21 / var(--tw-bg-opacity, 1))}.bg-yellow-600{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.bg-zinc-400{--tw-bg-opacity: 1;background-color:rgb(161 161 170 / var(--tw-bg-opacity, 1))}.bg-zinc-500{--tw-bg-opacity: 1;background-color:rgb(113 113 122 / var(--tw-bg-opacity, 1))}.bg-zinc-600{--tw-bg-opacity: 1;background-color:rgb(82 82 91 / var(--tw-bg-opacity, 1))}.bg-zinc-700{--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity, 1))}.bg-zinc-800{--tw-bg-opacity: 1;background-color:rgb(39 39 42 / var(--tw-bg-opacity, 1))}.bg-zinc-800\/30{background-color:#27272a4d}.bg-zinc-800\/40{background-color:#27272a66}.bg-zinc-800\/50{background-color:#27272a80}.bg-zinc-800\/60{background-color:#27272a99}.bg-zinc-900{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity, 1))}.bg-zinc-900\/40{background-color:#18181b66}.bg-zinc-900\/60{background-color:#18181b99}.bg-zinc-900\/80{background-color:#18181bcc}.bg-zinc-950{--tw-bg-opacity: 1;background-color:rgb(9 9 11 / var(--tw-bg-opacity, 1))}.bg-zinc-950\/40{background-color:#09090b66}.bg-zinc-950\/60{background-color:#09090b99}.bg-zinc-950\/80{background-color:#09090bcc}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-\[2px\]{padding-top:2px;padding-bottom:2px}.py-px{padding-top:1px;padding-bottom:1px}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pt-0\.5{padding-top:.125rem}.pt-1{padding-top:.25rem}.pt-24{padding-top:6rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.italic{font-style:italic}.ordinal{--tw-ordinal: ordinal;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.tabular-nums{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-5{line-height:1.25rem}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-normal{letter-spacing:0em}.tracking-wide{letter-spacing:.025em}.text-amber-200{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity, 1))}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.text-amber-300\/80{color:#fcd34dcc}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-amber-400\/70{color:#fbbf24b3}.text-amber-400\/80{color:#fbbf24cc}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-cyan-300{--tw-text-opacity: 1;color:rgb(103 232 249 / var(--tw-text-opacity, 1))}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-emerald-500\/80{color:#10b981cc}.text-green-300{--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-400\/80{color:#4ade80cc}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-orange-400{--tw-text-opacity: 1;color:rgb(251 146 60 / var(--tw-text-opacity, 1))}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.text-red-300\/80{color:#fca5a5cc}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-400\/70{color:#f87171b3}.text-red-400\/80{color:#f87171cc}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-sky-300{--tw-text-opacity: 1;color:rgb(125 211 252 / var(--tw-text-opacity, 1))}.text-sky-400{--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.text-teal-400\/70{color:#2dd4bfb3}.text-violet-200{--tw-text-opacity: 1;color:rgb(221 214 254 / var(--tw-text-opacity, 1))}.text-violet-300{--tw-text-opacity: 1;color:rgb(196 181 253 / var(--tw-text-opacity, 1))}.text-violet-400{--tw-text-opacity: 1;color:rgb(167 139 250 / var(--tw-text-opacity, 1))}.text-violet-400\/70{color:#a78bfab3}.text-violet-400\/80{color:#a78bfacc}.text-violet-600{--tw-text-opacity: 1;color:rgb(124 58 237 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-300{--tw-text-opacity: 1;color:rgb(253 224 71 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.text-zinc-100{--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity, 1))}.text-zinc-200{--tw-text-opacity: 1;color:rgb(228 228 231 / var(--tw-text-opacity, 1))}.text-zinc-300{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.text-zinc-400{--tw-text-opacity: 1;color:rgb(161 161 170 / var(--tw-text-opacity, 1))}.text-zinc-500{--tw-text-opacity: 1;color:rgb(113 113 122 / var(--tw-text-opacity, 1))}.text-zinc-500\/80{color:#71717acc}.text-zinc-600{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.text-zinc-700{--tw-text-opacity: 1;color:rgb(63 63 70 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.decoration-dotted{text-decoration-style:dotted}.placeholder-zinc-600::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(82 82 91 / var(--tw-placeholder-opacity, 1))}.placeholder-zinc-600::placeholder{--tw-placeholder-opacity: 1;color:rgb(82 82 91 / var(--tw-placeholder-opacity, 1))}.accent-violet-500{accent-color:#8b5cf6}.opacity-0{opacity:0}.opacity-40{opacity:.4}.opacity-70{opacity:.7}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.\[overflow-anchor\:none\]{overflow-anchor:none}.\[overflow-wrap\:anywhere\]{overflow-wrap:anywhere}.placeholder\:text-zinc-500::-moz-placeholder{--tw-text-opacity: 1;color:rgb(113 113 122 / var(--tw-text-opacity, 1))}.placeholder\:text-zinc-500::placeholder{--tw-text-opacity: 1;color:rgb(113 113 122 / var(--tw-text-opacity, 1))}.hover\:border-amber-600:hover{--tw-border-opacity: 1;border-color:rgb(217 119 6 / var(--tw-border-opacity, 1))}.hover\:border-red-800:hover{--tw-border-opacity: 1;border-color:rgb(153 27 27 / var(--tw-border-opacity, 1))}.hover\:border-red-800\/60:hover{border-color:#991b1b99}.hover\:border-red-900\/70:hover{border-color:#7f1d1db3}.hover\:border-violet-500:hover{--tw-border-opacity: 1;border-color:rgb(139 92 246 / var(--tw-border-opacity, 1))}.hover\:border-zinc-500:hover{--tw-border-opacity: 1;border-color:rgb(113 113 122 / var(--tw-border-opacity, 1))}.hover\:border-zinc-600:hover{--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1))}.hover\:bg-amber-500:hover{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.hover\:bg-amber-900\/50:hover{background-color:#78350f80}.hover\:bg-emerald-500:hover{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.hover\:bg-emerald-900\/60:hover{background-color:#064e3b99}.hover\:bg-red-600:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-red-900\/40:hover{background-color:#7f1d1d66}.hover\:bg-red-900\/50:hover{background-color:#7f1d1d80}.hover\:bg-red-950\/50:hover{background-color:#450a0a80}.hover\:bg-sky-900\/60:hover{background-color:#0c4a6e99}.hover\:bg-violet-500:hover{--tw-bg-opacity: 1;background-color:rgb(139 92 246 / var(--tw-bg-opacity, 1))}.hover\:bg-violet-600\/40:hover{background-color:#7c3aed66}.hover\:bg-violet-900\/20:hover{background-color:#4c1d9533}.hover\:bg-white\/\[0\.02\]:hover{background-color:#ffffff05}.hover\:bg-zinc-600:hover{--tw-bg-opacity: 1;background-color:rgb(82 82 91 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-700:hover{--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-800\/50:hover{background-color:#27272a80}.hover\:bg-zinc-800\/60:hover{background-color:#27272a99}.hover\:text-amber-200:hover{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity, 1))}.hover\:text-emerald-300:hover{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.hover\:text-red-200:hover{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.hover\:text-red-300:hover{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.hover\:text-violet-100:hover{--tw-text-opacity: 1;color:rgb(237 233 254 / var(--tw-text-opacity, 1))}.hover\:text-violet-200:hover{--tw-text-opacity: 1;color:rgb(221 214 254 / var(--tw-text-opacity, 1))}.hover\:text-violet-400:hover{--tw-text-opacity: 1;color:rgb(167 139 250 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:text-zinc-200:hover{--tw-text-opacity: 1;color:rgb(228 228 231 / var(--tw-text-opacity, 1))}.hover\:text-zinc-300:hover{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.hover\:text-zinc-400:hover{--tw-text-opacity: 1;color:rgb(161 161 170 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.focus\:border-red-600:focus{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity, 1))}.focus\:border-violet-500:focus{--tw-border-opacity: 1;border-color:rgb(139 92 246 / var(--tw-border-opacity, 1))}.focus\:border-zinc-500:focus{--tw-border-opacity: 1;border-color:rgb(113 113 122 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-violet-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(139 92 246 / var(--tw-ring-opacity, 1)) }.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.group[open] .group-open\:rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:opacity-100{opacity:1}
package/dist-lib/ui.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './index'
2
- export {}