@aion0/forge 0.9.10 → 0.9.12
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,12 +1,13 @@
|
|
|
1
|
-
# Forge v0.9.
|
|
1
|
+
# Forge v0.9.12
|
|
2
2
|
|
|
3
|
-
Released: 2026-05-
|
|
3
|
+
Released: 2026-05-27
|
|
4
4
|
|
|
5
|
-
## Changes since v0.9.
|
|
5
|
+
## Changes since v0.9.11
|
|
6
6
|
|
|
7
7
|
### Other
|
|
8
|
-
-
|
|
9
|
-
- fix(
|
|
8
|
+
- fix(settings): id-collision guards on agent + profile add
|
|
9
|
+
- fix(settings): functional setSettings in profile add — preserves new agent
|
|
10
|
+
- fix(settings): adding an Agent no longer creates a CLI Profile
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
**Full Changelog**: https://github.com/aiwatching/forge/compare/v0.9.
|
|
13
|
+
**Full Changelog**: https://github.com/aiwatching/forge/compare/v0.9.11...v0.9.12
|
|
@@ -88,7 +88,7 @@ interface Workflow {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
interface PipelineNodeState {
|
|
91
|
-
status: 'pending' | 'running' | 'done' | 'failed' | 'skipped';
|
|
91
|
+
status: 'pending' | 'running' | 'done' | 'failed' | 'skipped' | 'cancelled';
|
|
92
92
|
taskId?: string;
|
|
93
93
|
outputs: Record<string, string>;
|
|
94
94
|
iterations: number;
|
|
@@ -1379,8 +1379,16 @@ function AgentsSection({ settings, setSettings }: { settings: any; setSettings:
|
|
|
1379
1379
|
const agentsCfg: Record<string, any> = { ...(prev.agents || {}) };
|
|
1380
1380
|
for (const a of updated) {
|
|
1381
1381
|
const existing = agentsCfg[a.id] || {};
|
|
1382
|
+
// NOTE: do NOT write `cliType` from the entry here. cliType is the
|
|
1383
|
+
// load-time discriminator between agents and CLI profiles (see the
|
|
1384
|
+
// filter ~line 1349 — `if (cfg.cliType || cfg.base) continue`).
|
|
1385
|
+
// The Agents-add form seeds newAgent.cliType for cliDefaults lookup
|
|
1386
|
+
// (taskFlags / resumeFlag presets), but persisting it would make
|
|
1387
|
+
// the new agent show up as a profile on reload. `...existing`
|
|
1388
|
+
// carries forward cliType for detected agents whose inline selector
|
|
1389
|
+
// wrote it via setSettings directly (line ~1540).
|
|
1382
1390
|
agentsCfg[a.id] = {
|
|
1383
|
-
...existing, // preserve profile-specific fields
|
|
1391
|
+
...existing, // preserve profile-specific fields + any prior cliType
|
|
1384
1392
|
name: a.name,
|
|
1385
1393
|
path: a.path,
|
|
1386
1394
|
enabled: a.enabled,
|
|
@@ -1391,7 +1399,6 @@ function AgentsSection({ settings, setSettings }: { settings: any; setSettings:
|
|
|
1391
1399
|
models: a.models,
|
|
1392
1400
|
skipPermissionsFlag: a.skipPermissionsFlag,
|
|
1393
1401
|
requiresTTY: a.requiresTTY,
|
|
1394
|
-
cliType: (a as any).cliType || existing.cliType,
|
|
1395
1402
|
};
|
|
1396
1403
|
}
|
|
1397
1404
|
const claude = updated.find(a => a.id === 'claude');
|
|
@@ -1437,6 +1444,15 @@ function AgentsSection({ settings, setSettings }: { settings: any; setSettings:
|
|
|
1437
1444
|
|
|
1438
1445
|
const addAgent = () => {
|
|
1439
1446
|
if (!newAgent.id || !newAgent.path) return;
|
|
1447
|
+
// settings.agents is one map keyed by id — agents + CLI profiles + API
|
|
1448
|
+
// profiles all coexist. A duplicate id silently overwrites whichever
|
|
1449
|
+
// entry was there first. Block the add and tell the user why.
|
|
1450
|
+
if (agents.some(a => a.id === newAgent.id) || settings.agents?.[newAgent.id]) {
|
|
1451
|
+
const existing = settings.agents?.[newAgent.id] as any;
|
|
1452
|
+
const kind = existing?.type === 'api' ? 'API profile' : existing?.cliType || existing?.base ? 'CLI profile' : 'agent';
|
|
1453
|
+
alert(`id "${newAgent.id}" is already in use by a ${kind}. Pick a different id.`);
|
|
1454
|
+
return;
|
|
1455
|
+
}
|
|
1440
1456
|
const entry: AgentEntry = {
|
|
1441
1457
|
...newAgent,
|
|
1442
1458
|
enabled: true,
|
|
@@ -1743,11 +1759,34 @@ function AgentsSection({ settings, setSettings }: { settings: any; setSettings:
|
|
|
1743
1759
|
))}
|
|
1744
1760
|
|
|
1745
1761
|
<div className="flex gap-2 mt-1">
|
|
1762
|
+
{/* Functional setSettings — non-functional form captures a stale
|
|
1763
|
+
`settings` snapshot, which clobbers any agent that was saved
|
|
1764
|
+
between this component's last render and the Add click
|
|
1765
|
+
(debouncedSave for the Agents section fires 1s later, so the
|
|
1766
|
+
window is real). Also: settings.agents is a single map keyed
|
|
1767
|
+
by id — agents + CLI profiles + API profiles share it — so
|
|
1768
|
+
reusing an id silently overwrites. Block dups with an alert. */}
|
|
1746
1769
|
<AddProfileForm type="cli" baseAgents={agents.filter(a => !a.isProfile && a.detected)} onAdd={(id, cfg) => {
|
|
1747
|
-
setSettings(
|
|
1770
|
+
setSettings((prev: any) => {
|
|
1771
|
+
if (prev.agents?.[id]) {
|
|
1772
|
+
const existing = prev.agents[id] as any;
|
|
1773
|
+
const kind = existing.type === 'api' ? 'API profile' : existing.cliType || existing.base ? 'CLI profile' : 'agent';
|
|
1774
|
+
alert(`id "${id}" is already in use by a ${kind}. Pick a different id.`);
|
|
1775
|
+
return prev;
|
|
1776
|
+
}
|
|
1777
|
+
return { ...prev, agents: { ...(prev.agents || {}), [id]: cfg } };
|
|
1778
|
+
});
|
|
1748
1779
|
}} />
|
|
1749
1780
|
<AddProfileForm type="api" baseAgents={[]} onAdd={(id, cfg) => {
|
|
1750
|
-
setSettings(
|
|
1781
|
+
setSettings((prev: any) => {
|
|
1782
|
+
if (prev.agents?.[id]) {
|
|
1783
|
+
const existing = prev.agents[id] as any;
|
|
1784
|
+
const kind = existing.type === 'api' ? 'API profile' : existing.cliType || existing.base ? 'CLI profile' : 'agent';
|
|
1785
|
+
alert(`id "${id}" is already in use by a ${kind}. Pick a different id.`);
|
|
1786
|
+
return prev;
|
|
1787
|
+
}
|
|
1788
|
+
return { ...prev, agents: { ...(prev.agents || {}), [id]: cfg } };
|
|
1789
|
+
});
|
|
1751
1790
|
}} />
|
|
1752
1791
|
</div>
|
|
1753
1792
|
</div>
|
package/package.json
CHANGED