@aion0/forge 0.8.6 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/RELEASE_NOTES.md CHANGED
@@ -1,8 +1,11 @@
1
- # Forge v0.8.6
1
+ # Forge v0.8.8
2
2
 
3
3
  Released: 2026-05-21
4
4
 
5
- ## Changes since v0.8.5
5
+ ## Changes since v0.8.7
6
6
 
7
+ ### Other
8
+ - fix(install): move tsx from devDependencies to dependencies
7
9
 
8
- **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.8.5...v0.8.6
10
+
11
+ **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.8.7...v0.8.8
@@ -40,7 +40,7 @@ import { getDataDir } from '../dirs';
40
40
  import { createJob } from './store';
41
41
  import type { Job, PipelineDispatchParams, ChatDispatchParams } from './types';
42
42
 
43
- export type ParamType = 'string' | 'number' | 'boolean' | 'select' | 'project_picker';
43
+ export type ParamType = 'string' | 'number' | 'boolean' | 'select' | 'project_picker' | 'gitlab_mr_url';
44
44
 
45
45
  export interface RecipeParam {
46
46
  name: string;
@@ -205,6 +205,19 @@ export function instantiateRecipe(name: string, rawParams: Record<string, any>):
205
205
  val = n;
206
206
  } else if (p.type === 'boolean') {
207
207
  val = !!val && val !== 'false';
208
+ } else if (p.type === 'gitlab_mr_url' && val !== '') {
209
+ // Parse a full GitLab MR URL into two derived params:
210
+ // <name>__path → "namespace/repo" (URL-encoded path-style id)
211
+ // <name>__iid → numeric MR iid
212
+ // Lets a recipe ask the user for just ONE field (the MR URL) and
213
+ // still produce both `project_id` and `mr_iid` for the underlying
214
+ // tool calls.
215
+ const m = String(val).match(/^https?:\/\/[^/]+\/(.+?)\/-\/merge_requests\/(\d+)/);
216
+ if (!m) {
217
+ return { ok: false, error: `param "${p.name}" must be a GitLab MR URL like https://host/namespace/repo/-/merge_requests/N — got: ${String(val).slice(0, 80)}` };
218
+ }
219
+ params[`${p.name}__path`] = m[1];
220
+ params[`${p.name}__iid`] = parseInt(m[2], 10);
208
221
  }
209
222
  params[p.name] = val;
210
223
  }
@@ -130,27 +130,20 @@ export function listMarketplace(): { recipes: MarketplaceEntry[]; pipelines: Mar
130
130
  installed: false,
131
131
  });
132
132
  }
133
+ // Marketplace = registry catalog ONLY. Recipes / pipelines that
134
+ // exist only locally (uploaded copy, hand-edited file, custom
135
+ // workflow) belong to the user and don't show here — Marketplace
136
+ // is for browsing the remote forge-workflow repo. We still mark
137
+ // registry items as `installed` when a local copy exists, so the
138
+ // UI can show "your local copy is on v0.2.0, registry is v0.3.0".
133
139
  for (const ir of installedRecipes) {
134
140
  const cached = recipeMap.get(ir.name);
135
141
  if (cached) {
136
142
  cached.installed = true;
137
143
  cached.installed_version = ir.version;
138
144
  cached.has_update = compareVersions(cached.version, ir.version) > 0;
139
- } else {
140
- // Local-only recipe (uploaded, not in marketplace)
141
- recipeMap.set(ir.name, {
142
- kind: 'recipe',
143
- name: ir.name,
144
- display_name: ir.display_name,
145
- description: ir.description,
146
- version: ir.version,
147
- author: ir.author,
148
- tags: ir.tags,
149
- source: 'local',
150
- installed: true,
151
- installed_version: ir.version,
152
- });
153
145
  }
146
+ // else: local-only recipe — intentionally skipped
154
147
  }
155
148
 
156
149
  const pipelineMap = new Map<string, MarketplaceEntry>();
@@ -170,24 +163,19 @@ export function listMarketplace(): { recipes: MarketplaceEntry[]; pipelines: Mar
170
163
  installed: false,
171
164
  });
172
165
  }
166
+ // Same model for pipelines: Marketplace lists only registry items.
167
+ // Local-only workflows (yours, edited, custom) live in the
168
+ // Pipelines tab list — they're shown there, not here. This split
169
+ // keeps "browse upstream catalog" and "manage your local files"
170
+ // as two distinct mental modes.
173
171
  for (const iw of installedWorkflows) {
174
- if (iw.builtin) continue; // built-ins aren't user workflows
172
+ if (iw.builtin) continue;
175
173
  const cached = pipelineMap.get(iw.name);
176
174
  if (cached) {
177
175
  cached.installed = true;
178
- // pipeline yaml doesn't carry an explicit version; treat unknown.
179
176
  cached.installed_version = (iw as any).version || cached.version;
180
- } else {
181
- pipelineMap.set(iw.name, {
182
- kind: 'pipeline',
183
- name: iw.name,
184
- display_name: iw.name,
185
- description: iw.description,
186
- version: '0.0.0',
187
- source: 'local',
188
- installed: true,
189
- });
190
177
  }
178
+ // else: local-only pipeline — intentionally skipped
191
179
  }
192
180
 
193
181
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.8.6",
3
+ "version": "0.8.8",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -53,6 +53,7 @@
53
53
  "react-dom": "^19.2.4",
54
54
  "react-markdown": "^10.1.0",
55
55
  "remark-gfm": "^4.0.1",
56
+ "tsx": "^4.21.0",
56
57
  "ws": "^8.19.0",
57
58
  "yaml": "^2.8.2",
58
59
  "zod": "^4.3.6"
@@ -73,7 +74,6 @@
73
74
  "@types/ws": "^8.18.1",
74
75
  "postcss": "^8.5.8",
75
76
  "tailwindcss": "^4.2.1",
76
- "tsx": "^4.21.0",
77
77
  "typescript": "^5.9.3"
78
78
  }
79
79
  }