@aion0/forge 0.8.0 → 0.8.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.
- package/RELEASE_NOTES.md +5 -100
- package/app/api/monitor/route.ts +26 -0
- package/components/MonitorPanel.tsx +43 -0
- package/lib/chat/agent-loop.ts +2 -2
- package/lib/chat/local-memory.ts +2 -2
- package/lib/chat/memory-store.ts +1 -1
- package/lib/chat/protocols/http.ts +2 -2
- package/lib/chat/protocols/shell.ts +2 -2
- package/lib/chat/session-store.ts +2 -2
- package/lib/chat/tool-dispatcher.ts +3 -3
- package/package.json +1 -1
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,107 +1,12 @@
|
|
|
1
|
-
# Forge v0.8.
|
|
1
|
+
# Forge v0.8.1
|
|
2
2
|
|
|
3
3
|
Released: 2026-05-19
|
|
4
4
|
|
|
5
|
-
## Changes since v0.
|
|
6
|
-
|
|
7
|
-
### Features
|
|
8
|
-
- feat: job preview auto-fill + forge worktree CLI + faster startup
|
|
9
|
-
|
|
10
|
-
### Documentation
|
|
11
|
-
- docs: example pipeline for a Forge Job driving Mantis → branch triage
|
|
12
|
-
- docs: Jobs — scheduled connector polls that fan out to pipelines or chat
|
|
13
|
-
- docs: connector declarative-extract spec + handoff + updated help doc
|
|
14
|
-
- docs: connector packaging section + plugin category ADR
|
|
15
|
-
- docs: ADR for browser-agent data architecture (Temper write strategy)
|
|
16
|
-
- docs: RFC + implementation plan for browser-agent / connector system
|
|
5
|
+
## Changes since v0.8.0
|
|
17
6
|
|
|
18
7
|
### Other
|
|
19
|
-
- feat(
|
|
20
|
-
-
|
|
21
|
-
- feat(pipeline): print fetch-bug-details + download-attachments to task log
|
|
22
|
-
- feat(mantis+pipeline): attachment download into worktree for vision analysis
|
|
23
|
-
- fix(pipeline): push-and-mr detects revoked glab token + prints fix cmd
|
|
24
|
-
- fix(pipeline): push-and-mr surfaces glab output + MR-list fallback
|
|
25
|
-
- feat(pipeline/mantis): fetch-bug-details exposes ALL fields downstream
|
|
26
|
-
- fix(pipeline-ui): fetch full pipeline on click — summary breaks detail view
|
|
27
|
-
- feat(jobs): expose {{total_matching}} placeholder in chat summary mode
|
|
28
|
-
- fix(mantis): regex escape — YAML | block passes backslashes verbatim
|
|
29
|
-
- fix(time): normalize all SQLite datetimes to ISO Z + add settings.timezone
|
|
30
|
-
- feat(jobs/mantis): target='main' chat dispatch + total_matching count
|
|
31
|
-
- fix(mantis): reset all filter fields before applying — no session leak
|
|
32
|
-
- feat(chat): persistent main session + clear-messages + fork
|
|
33
|
-
- feat(jobs): chat 'summary' dispatch mode — bundle N items into 1 LLM analysis
|
|
34
|
-
- perf(pipeline-ui): lazy-load runs per workflow, drop 5s full poll
|
|
35
|
-
- perf(watcher): defer initial sync + skip entry_count on first pass
|
|
36
|
-
- feat(pipeline-ui): 'Load older runs' button per workflow
|
|
37
|
-
- perf(pipeline): default limit 100 + ?workflow / ?before cursor
|
|
38
|
-
- perf(pipeline): mtime cache + summary mode for list — 1.6MB → <50KB
|
|
39
|
-
- perf(init): instrument 5s gap + demote skills sync failure to warn
|
|
40
|
-
- feat(teams): _probe diagnostic tool — DOM state in one call
|
|
41
|
-
- fix(chat): unwrap Node fetch 'fetch failed' with concrete remediation
|
|
42
|
-
- fix(teams): char-by-char typing for search input (keyboard events)
|
|
43
|
-
- feat(teams): v0.8.0 — send_message 3-tier resolver (left-rail → expand groups → search)
|
|
44
|
-
- feat(mantis): v0.4.3 — accurate filters via show_status + handler_id
|
|
45
|
-
- fix(pipeline): real workdir support + worktree-setup emits path only
|
|
46
|
-
- fix(pipeline): node tasks always start fresh Claude session
|
|
47
|
-
- fix(jobs): warn loudly when input_template keys render to empty
|
|
48
|
-
- feat(jobs): 'Force run' — reset dedup + run, one click
|
|
49
|
-
- fix(jobs): drop dedup_key from triggerPipeline — UNIQUE blocked replay
|
|
50
|
-
- feat(gitlab): full HTTP-API connector (32 tools) — replaces DOM scraping
|
|
51
|
-
- fix(mantis): bug notes always carry an id — fallback strategies + hash
|
|
52
|
-
- feat(chat): connector narrowing — /teams forces tool use; bare mention narrows tool list
|
|
53
|
-
- fix(chat): connector tools always surfaced + stronger 'use the tool' prompt
|
|
54
|
-
- fix(notify-test): explain 'fetch failed' (corp SSL / proxy / DNS)
|
|
55
|
-
- fix(notify-test): drop Markdown parse_mode + split chat_id + surface real reason
|
|
56
|
-
- fix(mantis): search_bugs — fix_schedule (version) filter + auto-pagination
|
|
57
|
-
- fix(mantis): search_bugs honours status + project_id, drops broken query syntax
|
|
58
|
-
- feat(health): startup probe + Pipelines banner for missing CLIs (glab/gh/git/jq)
|
|
59
|
-
- feat(pipeline): mantis-bug-fix-and-mr builtin + connector-tool API
|
|
60
|
-
- feat(mantis): notes carry stable note_id so Jobs can dedup on them
|
|
61
|
-
- feat(jobs): per-run verbose execution log persisted to job_runs.log
|
|
62
|
-
- feat(web): Jobs first in Automation, deep-link to logs filtered by job id
|
|
63
|
-
- fix(web): Automation sub-tabs squished header; new sub-toolbar row fix(terminal): Split Right/Down → SVG icons; mouse hint to tooltip feat(jobs): notes column — backfill + items_path mismatch surfaced
|
|
64
|
-
- feat(web): Automation hub — merge Tasks/Pipelines nav + add Jobs view
|
|
65
|
-
- feat(jobs): trace flow — Dashboard deep-link + CLI dispatches view
|
|
66
|
-
- feat(jobs): Jobs backend — scheduled connector polls + dispatch
|
|
67
|
-
- fix(settings): don't overwrite agent apiKey with masked placeholder
|
|
68
|
-
- feat(chat): port Temper memory to Forge — pinned blocks + memory_* tools
|
|
69
|
-
- feat(chat): reuse API agent profiles + add baseUrl (LiteLLM support)
|
|
70
|
-
- feat(bridge): drop pairing — bridge auths with the user's Forge token
|
|
71
|
-
- feat(connectors): Phase 3 — multi-protocol runtime (http, shell)
|
|
72
|
-
- feat(chat): Phase 5 part 3 — Telegram /chat command
|
|
73
|
-
- feat(chat): Phase 5 part 2 — forge chat CLI subcommand
|
|
74
|
-
- feat(chat): Phase 5 part 1 — chat-standalone (8408) + Next proxy
|
|
75
|
-
- fix(bridge): spawn browser-bridge from lib/init.ts too
|
|
76
|
-
- feat(chat): Phase 2 part 3 — HTTP API + WS push streaming
|
|
77
|
-
- feat(chat): Phase 2 part 2 — tool dispatcher + agent loop
|
|
78
|
-
- feat(chat): Phase 2 part 1 — chat backend foundation
|
|
79
|
-
- feat(bridge): Phase 1 — Forge↔Extension WebSocket bridge
|
|
80
|
-
- feat(connectors): teams v0.7.1 — send_message no longer requires confirmation
|
|
81
|
-
- feat(connectors): teams v0.7.0 — robust wait + send_message by name
|
|
82
|
-
- feat(connectors): teams v0.6.0 — read_chat + read_channel by name
|
|
83
|
-
- feat(connectors): teams v0.5.0 — channels support (list + read posts)
|
|
84
|
-
- feat(connectors): pmdb v0.2.0 — read-only Fortinet PMDB connector
|
|
85
|
-
- feat(connectors): teams v0.4.0 — send_message (destructive)
|
|
86
|
-
- feat(connectors): teams v0.3.0 — rewritten from real DOM probe
|
|
87
|
-
- feat(connectors): multi-runner — manifest declares execution context
|
|
88
|
-
- feat(connectors): teams (Microsoft Teams) — first-cut declarative manifest
|
|
89
|
-
- chore(connectors): bump gitlab to 0.2.0
|
|
90
|
-
- feat(connectors): gitlab — declarative manifest with 6 tools
|
|
91
|
-
- feat(connectors): declarative extract — manifest carries page + script
|
|
92
|
-
- chore(connectors): bump mantis to 0.2.0 — full tool set landed
|
|
93
|
-
- feat(mcp): user-managed external MCP servers in .mcp.json
|
|
94
|
-
- feat(connectors): mantis probe — auto-copy JSON result to clipboard
|
|
95
|
-
- fix(connectors): mantis probe — support 1.x classic URL + checkbox row marker
|
|
96
|
-
- feat(connectors): mantis selector probe sibling script
|
|
97
|
-
- chore(connectors): bump mantis + gitlab-browser to 0.1.1
|
|
98
|
-
- docs(connectors): DOM extraction is the default path, not REST APIs
|
|
99
|
-
- feat(ui): dedicated Connectors panel separate from Plugins
|
|
100
|
-
- fix(connectors-api): rely on middleware auth, drop explicit token check
|
|
101
|
-
- feat(api): connectors discovery + per-user settings endpoints
|
|
102
|
-
- feat(plugins): connector category + browser-side mode, mantis + gitlab manifests
|
|
103
|
-
- feat(gitlab): \`gitlab-issue-fix-and-review\` pipeline + scanner
|
|
104
|
-
- fix(mcp): mirror .forge/mcp.json to project root so claude picks it up
|
|
8
|
+
- feat(monitor): show Chat Server + Browser Bridge in Monitor panel
|
|
9
|
+
- fix(chat): use relative imports in chat-standalone graph
|
|
105
10
|
|
|
106
11
|
|
|
107
|
-
**Full Changelog**: https://github.com/aiwatching/forge/compare/v0.
|
|
12
|
+
**Full Changelog**: https://github.com/aiwatching/forge/compare/v0.8.0...v0.8.1
|
package/app/api/monitor/route.ts
CHANGED
|
@@ -22,8 +22,25 @@ export async function GET() {
|
|
|
22
22
|
const terminal = countProcess('terminal-standalone');
|
|
23
23
|
const telegram = countProcess('telegram-standalone');
|
|
24
24
|
const workspace = countProcess('workspace-standalone');
|
|
25
|
+
const chat = countProcess('chat-standalone');
|
|
26
|
+
const browserBridge = countProcess('browser-bridge-standalone');
|
|
25
27
|
const tunnel = countProcess('cloudflared tunnel');
|
|
26
28
|
|
|
29
|
+
// Chat backend health (port 8408 — process can be alive but crashed)
|
|
30
|
+
let chatStatus: { running: boolean; sessions: number; port: number } = {
|
|
31
|
+
running: false,
|
|
32
|
+
sessions: 0,
|
|
33
|
+
port: Number(process.env.CHAT_PORT) || 8408,
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
const chatRes = run(`curl -s http://127.0.0.1:${chatStatus.port}/api/status 2>/dev/null`);
|
|
37
|
+
if (chatRes) {
|
|
38
|
+
const data = JSON.parse(chatRes);
|
|
39
|
+
chatStatus.running = true;
|
|
40
|
+
chatStatus.sessions = data.active_sse_sessions ?? 0;
|
|
41
|
+
}
|
|
42
|
+
} catch {}
|
|
43
|
+
|
|
27
44
|
// MCP Server (runs inside workspace process, check /health endpoint)
|
|
28
45
|
let mcpStatus = { running: false, sessions: 0 };
|
|
29
46
|
try {
|
|
@@ -65,6 +82,15 @@ export async function GET() {
|
|
|
65
82
|
terminal: { running: terminal.count > 0, pid: terminal.pid, startedAt: terminal.startedAt },
|
|
66
83
|
telegram: { running: telegram.count > 0, pid: telegram.pid, startedAt: telegram.startedAt },
|
|
67
84
|
workspace: { running: workspace.count > 0, pid: workspace.pid, startedAt: workspace.startedAt },
|
|
85
|
+
browserBridge: { running: browserBridge.count > 0, pid: browserBridge.pid, startedAt: browserBridge.startedAt },
|
|
86
|
+
chat: {
|
|
87
|
+
running: chatStatus.running,
|
|
88
|
+
pid: chat.pid,
|
|
89
|
+
startedAt: chat.startedAt,
|
|
90
|
+
port: chatStatus.port,
|
|
91
|
+
sessions: chatStatus.sessions,
|
|
92
|
+
processAlive: chat.count > 0,
|
|
93
|
+
},
|
|
68
94
|
tunnel: { running: tunnel.count > 0, pid: tunnel.pid, url: tunnelUrl, startedAt: tunnel.startedAt },
|
|
69
95
|
mcp: { running: mcpStatus.running, port: 8406, sessions: mcpStatus.sessions },
|
|
70
96
|
},
|
|
@@ -8,6 +8,15 @@ interface MonitorData {
|
|
|
8
8
|
terminal: { running: boolean; pid: string; startedAt?: string };
|
|
9
9
|
telegram: { running: boolean; pid: string; startedAt?: string };
|
|
10
10
|
workspace: { running: boolean; pid: string; startedAt?: string };
|
|
11
|
+
browserBridge?: { running: boolean; pid: string; startedAt?: string };
|
|
12
|
+
chat?: {
|
|
13
|
+
running: boolean;
|
|
14
|
+
pid: string;
|
|
15
|
+
startedAt?: string;
|
|
16
|
+
port: number;
|
|
17
|
+
sessions: number;
|
|
18
|
+
processAlive: boolean;
|
|
19
|
+
};
|
|
11
20
|
tunnel: { running: boolean; pid: string; url: string };
|
|
12
21
|
mcp: { running: boolean; port: number; sessions: number };
|
|
13
22
|
};
|
|
@@ -50,6 +59,7 @@ export default function MonitorPanel({ onClose }: { onClose: () => void }) {
|
|
|
50
59
|
{ label: 'Terminal Server', ...data.processes.terminal },
|
|
51
60
|
{ label: 'Telegram Bot', ...data.processes.telegram },
|
|
52
61
|
{ label: 'Workspace Daemon', ...data.processes.workspace },
|
|
62
|
+
...(data.processes.browserBridge ? [{ label: 'Browser Bridge', ...data.processes.browserBridge }] : []),
|
|
53
63
|
{ label: 'Tunnel', ...data.processes.tunnel },
|
|
54
64
|
].map(p => (
|
|
55
65
|
<div key={p.label} className="flex items-center gap-2 text-xs">
|
|
@@ -65,6 +75,39 @@ export default function MonitorPanel({ onClose }: { onClose: () => void }) {
|
|
|
65
75
|
)}
|
|
66
76
|
</div>
|
|
67
77
|
))}
|
|
78
|
+
{/* Chat Server (port 8408) — running = HTTP responds. If the
|
|
79
|
+
process is alive but port isn't, the daemon likely crashed
|
|
80
|
+
at boot (e.g. import error). */}
|
|
81
|
+
{data.processes.chat && (
|
|
82
|
+
<div className="flex items-center gap-2 text-xs">
|
|
83
|
+
<span
|
|
84
|
+
className={
|
|
85
|
+
data.processes.chat.running
|
|
86
|
+
? 'text-green-400'
|
|
87
|
+
: data.processes.chat.processAlive
|
|
88
|
+
? 'text-yellow-500'
|
|
89
|
+
: 'text-gray-500'
|
|
90
|
+
}
|
|
91
|
+
>
|
|
92
|
+
●
|
|
93
|
+
</span>
|
|
94
|
+
<span className="text-[var(--text-primary)] w-28">Chat Server</span>
|
|
95
|
+
{data.processes.chat.running ? (
|
|
96
|
+
<>
|
|
97
|
+
<span className="text-[var(--text-secondary)] font-mono text-[10px]">port: {data.processes.chat.port}</span>
|
|
98
|
+
<span className="text-gray-500 font-mono text-[9px]">{data.processes.chat.sessions} SSE</span>
|
|
99
|
+
{data.processes.chat.pid && (
|
|
100
|
+
<span className="text-[var(--text-secondary)] font-mono text-[10px]">pid: {data.processes.chat.pid}</span>
|
|
101
|
+
)}
|
|
102
|
+
</>
|
|
103
|
+
) : data.processes.chat.processAlive ? (
|
|
104
|
+
<span className="text-yellow-500 text-[10px]">port {data.processes.chat.port} unreachable (check forge.log)</span>
|
|
105
|
+
) : (
|
|
106
|
+
<span className="text-gray-500 text-[10px]">stopped</span>
|
|
107
|
+
)}
|
|
108
|
+
</div>
|
|
109
|
+
)}
|
|
110
|
+
|
|
68
111
|
{/* MCP Server — separate row (no pid, uses port + sessions) */}
|
|
69
112
|
<div className="flex items-center gap-2 text-xs">
|
|
70
113
|
<span className={data.processes.mcp?.running ? 'text-green-400' : 'text-gray-500'}>●</span>
|
package/lib/chat/agent-loop.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { streamLlm, type LlmTool } from './llm';
|
|
15
|
-
import { loadSettings } from '
|
|
15
|
+
import { loadSettings } from '../settings';
|
|
16
16
|
import {
|
|
17
17
|
appendMessage,
|
|
18
18
|
getSession,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
getPlugin,
|
|
32
32
|
getInstalledPlugin,
|
|
33
33
|
getConnectorsForPlugin,
|
|
34
|
-
} from '
|
|
34
|
+
} from '../plugins/registry';
|
|
35
35
|
import type {
|
|
36
36
|
ContentBlock,
|
|
37
37
|
Message,
|
package/lib/chat/local-memory.ts
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { join } from 'node:path';
|
|
20
|
-
import { getDb } from '
|
|
21
|
-
import { getDataDir } from '
|
|
20
|
+
import { getDb } from '../../src/core/db/database';
|
|
21
|
+
import { getDataDir } from '../dirs';
|
|
22
22
|
import type Database from 'better-sqlite3';
|
|
23
23
|
import type {
|
|
24
24
|
EpisodeInput,
|
package/lib/chat/memory-store.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* so the chat loop registers the memory_* tools either way.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { loadSettings } from '
|
|
18
|
+
import { loadSettings } from '../settings';
|
|
19
19
|
import { TemperClient } from './temper';
|
|
20
20
|
import { LocalMemoryStore } from './local-memory';
|
|
21
21
|
import type { EpisodeInput, MemoryBlock, SearchHit } from './temper';
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* is_error so the LLM can react.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import type { HttpRequestSpec, ConnectorTool } from '
|
|
19
|
-
import { expandAllTokens } from '
|
|
18
|
+
import type { HttpRequestSpec, ConnectorTool } from '../../plugins/types';
|
|
19
|
+
import { expandAllTokens } from '../../plugins/templates';
|
|
20
20
|
|
|
21
21
|
export interface HttpProtocolArgs {
|
|
22
22
|
tool: ConnectorTool;
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* automatic command allow-list in v1.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import type { ConnectorTool } from '
|
|
19
|
-
import { expandAllTokens } from '
|
|
18
|
+
import type { ConnectorTool } from '../../plugins/types';
|
|
19
|
+
import { expandAllTokens } from '../../plugins/templates';
|
|
20
20
|
import { spawn } from 'node:child_process';
|
|
21
21
|
|
|
22
22
|
export interface ShellProtocolArgs {
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
|
-
import { getDb } from '
|
|
11
|
-
import { getDataDir } from '
|
|
10
|
+
import { getDb } from '../../src/core/db/database';
|
|
11
|
+
import { getDataDir } from '../dirs';
|
|
12
12
|
import type { ContentBlock, Message, Role, Session } from './types';
|
|
13
13
|
|
|
14
14
|
function db() {
|
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
getPlugin,
|
|
17
17
|
getInstalledPlugin,
|
|
18
18
|
getConnectorsForPlugin,
|
|
19
|
-
} from '
|
|
20
|
-
import { expandSettingsTokens } from '
|
|
21
|
-
import type { Connector, ConnectorTool } from '
|
|
19
|
+
} from '../plugins/registry';
|
|
20
|
+
import { expandSettingsTokens } from '../plugins/templates';
|
|
21
|
+
import type { Connector, ConnectorTool } from '../plugins/types';
|
|
22
22
|
|
|
23
23
|
export interface ToolCall {
|
|
24
24
|
id: string;
|