agentgui 1.0.868 → 1.0.870

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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [Unreleased] - GUI observability + workflow-plugin fix
2
+
3
+ - Fix regression from prior commit: workflow-plugin.js declared `dependencies: ['git','database']` but git plugin was deleted; plugin init failed with "Plugin git not found in registry". Removed unused git dep and stale binding.
4
+ - Consolidate client debug registry: `window.__debug` now exposes structured sub-keys (`machines.{conv,toolInstall,voice,convList,prompt,recording,terminal,ws}`, `ws`, `auth`, `perf`, `config`, `renderer`, `conv`) via live getters that snapshot scattered `window.__*` machines into a single queryable tree. Existing `getState`/`getSyncState`/`getMessageState` methods preserved.
5
+ - Null-safe snapshot helpers: uninitialized machines return `'uninitialized'` instead of crashing.
6
+ - test.js: add regression case for workflow-plugin deps (17/17 pass).
7
+
1
8
  ## [Unreleased] - observability + dead-code sweep + root test suite
2
9
 
3
10
  - Expose acp-server-machine snapshots in /api/debug/machines (previously only tool-install + execution machines)
package/CLAUDE.md CHANGED
@@ -368,3 +368,15 @@ The README.md uses shields.io badges with a consistent pattern:
368
368
  - **`JsonlWatcher._read(fp)` override:** Captures `this._currentFp` before calling `super._read(fp)`, making the file path available to `_line()` callbacks for project-directory decoding in `_conv()`. JSONL project dirs are encoded (e.g., `-config-workspace-agentgui`) — decoded via `'/' + dirName.slice(1).replace(/-/g, '/')`.
369
369
  - **`createHttpHandler` uses `getWss: () => wss` (lazy getter):** Passing `wss` directly would crash with TDZ since `wss` is declared after `createHttpHandler` is called. The function form defers access until request time when `wss` is initialized.
370
370
  - **`_promptPushIfWeOwnRemote` fires after every `streaming_complete`:** `client-streaming4.js` calls `git.check` on the server after each agent turn. If `ownsRemote && (hasChanges || hasUnpushed)`, it auto-sends "Push the changes to the remote repository." to the current conversation. `ownsRemote` is true for non-github remotes, and for github.com remotes only when `GITHUB_USER` env var is set and appears in the URL. Without `GITHUB_USER`, github.com remotes return `ownsRemote=false` (safe default).
371
+
372
+ ## Critical Knowledge for Future Sessions
373
+
374
+ **Codebase Insight Stale:** `.codeinsight` snapshot is outdated (v1.0.811 claimed server.js=3407L, db-queries.js=1412L, but actual as of 2026-04-17: server.js=201L, db-queries.js=94L). Heavy refactoring already done. Before acting on insight "issues" (SQL injection claims, hardcoded secrets, large files), always verify with grep/read against current state. Most reported issues are false positives or stale.
375
+
376
+ **Test Harness Pattern:** Use better-sqlite3 in-memory Database, call `initSchema()` → `migrateConversationColumns()` → `migrateACPSchema()` in order (conversations table needs agentType column from second migration). `createQueries` signature: `(db, prep, generateId)` where `prep=(sql)=>db.prepare(sql)`. Silence console during schema init to keep test output clean. Node ships with better-sqlite3 available (optional dep resolved).
377
+
378
+ **CI Auto-Rewrites History:** Every push to main triggers Auto-Declaudeify workflow that filters Claude coauthor commits and force-pushes filtered history. After a push, `git fetch origin` is needed — local SHA drifts from origin SHA.
379
+
380
+ **Debug Endpoints Scattered:** Routes at `/api/debug`, `/api/debug/machines`, `/api/debug/state`, `/api/ws-stats`, `/api/debug/ws-stats` (alias). `routes-debug.js` wires all five + backup/restore. DEBUG API in browser: `window.__debug.getSyncState()`.
381
+
382
+ **Plugin Files NOT Orphans:** lib/plugins/* are dynamically loaded via `lib/plugin-loader.js` (import with file:// URL + cache-busting `?v=` timestamp). Only truly dead plugin was `lib/plugins/git-plugin.js`. Static scan showing orphans is misleading.
@@ -1,18 +1,14 @@
1
- // Workflow plugin - git push detection, workflow execution, status polling
2
-
3
1
  import fs from 'fs';
4
2
  import path from 'path';
5
3
 
6
4
  export default {
7
5
  name: 'workflow',
8
6
  version: '1.0.0',
9
- dependencies: ['git', 'database'],
7
+ dependencies: ['database'],
10
8
 
11
9
  async init(config, plugins) {
12
- const git = plugins.get('git');
13
- const db = plugins.get('database');
10
+ plugins.get('database');
14
11
  const workflowPolls = new Map();
15
- const runCache = new Map();
16
12
 
17
13
  const getWorkflows = () => {
18
14
  const repoRoot = process.cwd();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.868",
3
+ "version": "1.0.870",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",
@@ -112,36 +112,71 @@ Object.assign(AgentGUIClient.prototype, {
112
112
  _setupDebugHooks() {
113
113
  if (typeof window === 'undefined') return;
114
114
  const self = this;
115
- window.__debug = {
115
+ const snap = (actor) => (actor && actor.getSnapshot) ? actor.getSnapshot().value : 'uninitialized';
116
+ const mapSnap = (m) => m ? Object.fromEntries([...m].map(([k, a]) => [k, snap(a)])) : {};
117
+ const registry = {
116
118
  getState: () => ({
117
119
  latencyEma: self.wsManager?._latencyEma || null,
118
120
  serverProcessingEstimate: self._serverProcessingEstimate,
119
121
  latencyTrend: self.wsManager?.latency?.trend || null
120
122
  }),
121
-
122
123
  getSyncState: () => ({
123
124
  currentConversation: self.state.currentConversation,
124
125
  isStreaming: self._convIsStreaming(self.state.currentConversation?.id),
125
126
  streamingConversations: Array.from(self.state.streamingConversations),
126
- convMachineStates: typeof convMachineAPI !== 'undefined' ? Object.fromEntries([...window.__convMachines].map(([k, a]) => [k, a.getSnapshot().value])) : {},
127
- toolInstallMachineStates: typeof window.__toolInstallMachines !== 'undefined' ? Object.fromEntries([...window.__toolInstallMachines].map(([k, a]) => [k, a.getSnapshot().value])) : {},
128
- voiceMachineState: typeof window.__voiceMachine !== 'undefined' ? window.__voiceMachine.getSnapshot().value : 'unknown',
129
- convListMachineState: typeof window.__convListMachine !== 'undefined' ? window.__convListMachine.getSnapshot().value : 'unknown',
130
- promptMachineState: typeof window.__promptMachine !== 'undefined' ? window.__promptMachine.getSnapshot().value : 'unknown',
131
- wsConnectionState: self.wsManager?._wsActor?.getSnapshot().value || 'unknown',
127
+ convMachineStates: mapSnap(window.__convMachines),
128
+ toolInstallMachineStates: mapSnap(window.__toolInstallMachines),
129
+ voiceMachineState: snap(window.__voiceMachine),
130
+ convListMachineState: snap(window.__convListMachine),
131
+ promptMachineState: snap(window.__promptMachine),
132
+ wsConnectionState: snap(self.wsManager?._wsActor),
132
133
  rendererEventQueueLength: self.renderer?.eventQueue?.length || 0,
133
134
  rendererEventHistoryLength: self.renderer?.eventHistory?.length || 0,
134
135
  }),
135
-
136
136
  getMessageState: () => {
137
137
  const output = document.querySelector('.conversation-messages');
138
138
  if (!output) return { error: 'No conversation output found' };
139
- const messageCount = output.querySelectorAll('.message').length;
140
- const queueItems = output.querySelectorAll('.queue-item').length;
141
- const pendingMessages = output.querySelectorAll('.message-sending').length;
142
- return { messageCount, queueItems, pendingMessages };
139
+ return {
140
+ messageCount: output.querySelectorAll('.message').length,
141
+ queueItems: output.querySelectorAll('.queue-item').length,
142
+ pendingMessages: output.querySelectorAll('.message-sending').length,
143
+ };
143
144
  }
144
145
  };
146
+ const subkeys = {
147
+ machines: () => ({
148
+ conv: mapSnap(window.__convMachines),
149
+ toolInstall: mapSnap(window.__toolInstallMachines),
150
+ voice: snap(window.__voiceMachine),
151
+ convList: snap(window.__convListMachine),
152
+ prompt: snap(window.__promptMachine),
153
+ recording: snap(window.__recordingMachine),
154
+ terminal: snap(window.__terminalMachine),
155
+ ws: snap(self.wsManager?._wsActor),
156
+ }),
157
+ ws: () => ({
158
+ state: snap(self.wsManager?._wsActor),
159
+ latencyEma: self.wsManager?._latencyEma || null,
160
+ latencyTrend: self.wsManager?.latency?.trend || null,
161
+ url: window.__WS || null,
162
+ }),
163
+ auth: () => ({
164
+ state: window.__agentAuthState || null,
165
+ oauth: window.__agentAuthOAuth || null,
166
+ }),
167
+ perf: () => window.__convPerfMetrics || null,
168
+ config: () => ({ base: window.__BASE || null, server: window.__SERVER || null }),
169
+ renderer: () => ({
170
+ eventQueueLength: self.renderer?.eventQueue?.length || 0,
171
+ eventHistoryLength: self.renderer?.eventHistory?.length || 0,
172
+ }),
173
+ conv: () => ({
174
+ current: self.state.currentConversation,
175
+ streaming: Array.from(self.state.streamingConversations),
176
+ }),
177
+ };
178
+ for (const [k, fn] of Object.entries(subkeys)) Object.defineProperty(registry, k, { get: fn, enumerable: true });
179
+ window.__debug = registry;
145
180
  },
146
181
 
147
182
 
package/test.js CHANGED
@@ -161,5 +161,11 @@ section('acp-server-machine: getMachineActors returns Map', () => {
161
161
  assert.ok(actors instanceof Map);
162
162
  });
163
163
 
164
+ section('workflow-plugin: deps only list active plugins', async () => {
165
+ const wp = await import('./lib/plugins/workflow-plugin.js');
166
+ assert.deepEqual(wp.default.dependencies, ['database']);
167
+ assert.equal(typeof wp.default.init, 'function');
168
+ });
169
+
164
170
  console.log(`\n${passed} passed, ${failed} failed`);
165
171
  process.exit(failed === 0 ? 0 : 1);