@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 CHANGED
@@ -1,107 +1,12 @@
1
- # Forge v0.8.0
1
+ # Forge v0.8.1
2
2
 
3
3
  Released: 2026-05-19
4
4
 
5
- ## Changes since v0.6.3
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(chat): local memory fallback + simplified /chat web page
20
- - feat(security): encrypt plugin secrets at rest + mask on API
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.6.3...v0.8.0
12
+ **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.8.0...v0.8.1
@@ -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>
@@ -12,7 +12,7 @@
12
12
  */
13
13
 
14
14
  import { streamLlm, type LlmTool } from './llm';
15
- import { loadSettings } from '@/lib/settings';
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 '@/lib/plugins/registry';
34
+ } from '../plugins/registry';
35
35
  import type {
36
36
  ContentBlock,
37
37
  Message,
@@ -17,8 +17,8 @@
17
17
  */
18
18
 
19
19
  import { join } from 'node:path';
20
- import { getDb } from '@/src/core/db/database';
21
- import { getDataDir } from '@/lib/dirs';
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,
@@ -15,7 +15,7 @@
15
15
  * so the chat loop registers the memory_* tools either way.
16
16
  */
17
17
 
18
- import { loadSettings } from '@/lib/settings';
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 '@/lib/plugins/types';
19
- import { expandAllTokens } from '@/lib/plugins/templates';
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 '@/lib/plugins/types';
19
- import { expandAllTokens } from '@/lib/plugins/templates';
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 '@/src/core/db/database';
11
- import { getDataDir } from '@/lib/dirs';
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 '@/lib/plugins/registry';
20
- import { expandSettingsTokens } from '@/lib/plugins/templates';
21
- import type { Connector, ConnectorTool } from '@/lib/plugins/types';
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {