conductor-oss 0.3.1 → 0.3.3

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.
Files changed (136) hide show
  1. package/node_modules/@conductor-oss/plugin-agent-amp/package.json +1 -1
  2. package/node_modules/@conductor-oss/plugin-agent-ccr/package.json +1 -1
  3. package/node_modules/@conductor-oss/plugin-agent-claude-code/package.json +1 -1
  4. package/node_modules/@conductor-oss/plugin-agent-codex/package.json +1 -1
  5. package/node_modules/@conductor-oss/plugin-agent-cursor-cli/package.json +1 -1
  6. package/node_modules/@conductor-oss/plugin-agent-droid/package.json +1 -1
  7. package/node_modules/@conductor-oss/plugin-agent-gemini/dist/index.d.ts +44 -2
  8. package/node_modules/@conductor-oss/plugin-agent-gemini/dist/index.js +203 -17
  9. package/node_modules/@conductor-oss/plugin-agent-gemini/package.json +1 -1
  10. package/node_modules/@conductor-oss/plugin-agent-github-copilot/package.json +1 -1
  11. package/node_modules/@conductor-oss/plugin-agent-opencode/package.json +1 -1
  12. package/node_modules/@conductor-oss/plugin-agent-qwen-code/package.json +1 -1
  13. package/node_modules/@conductor-oss/plugin-mcp-server/package.json +1 -1
  14. package/node_modules/@conductor-oss/plugin-notifier-desktop/package.json +1 -1
  15. package/node_modules/@conductor-oss/plugin-notifier-discord/package.json +1 -1
  16. package/node_modules/@conductor-oss/plugin-runtime-tmux/package.json +1 -1
  17. package/node_modules/@conductor-oss/plugin-scm-github/package.json +1 -1
  18. package/node_modules/@conductor-oss/plugin-terminal-web/package.json +1 -1
  19. package/node_modules/@conductor-oss/plugin-tracker-github/package.json +1 -1
  20. package/node_modules/@conductor-oss/plugin-workspace-worktree/package.json +1 -1
  21. package/package.json +24 -23
  22. package/web/.next/standalone/packages/web/.next/BUILD_ID +1 -1
  23. package/web/.next/standalone/packages/web/.next/build-manifest.json +2 -2
  24. package/web/.next/standalone/packages/web/.next/prerender-manifest.json +3 -3
  25. package/web/.next/standalone/packages/web/.next/server/app/_global-error.html +2 -2
  26. package/web/.next/standalone/packages/web/.next/server/app/_global-error.rsc +1 -1
  27. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  28. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  29. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  30. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  31. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  32. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/server-reference-manifest.json +7 -7
  33. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  34. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  35. package/web/.next/standalone/packages/web/.next/server/app/_not-found.html +1 -1
  36. package/web/.next/standalone/packages/web/.next/server/app/_not-found.rsc +3 -3
  37. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  38. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  39. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  40. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  41. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  42. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  43. package/web/.next/standalone/packages/web/.next/server/app/index.html +1 -1
  44. package/web/.next/standalone/packages/web/.next/server/app/index.rsc +4 -4
  45. package/web/.next/standalone/packages/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  46. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
  47. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  48. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_index.segment.rsc +3 -3
  49. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  50. package/web/.next/standalone/packages/web/.next/server/app/page/react-loadable-manifest.json +1 -1
  51. package/web/.next/standalone/packages/web/.next/server/app/page/server-reference-manifest.json +7 -7
  52. package/web/.next/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
  53. package/web/.next/standalone/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
  54. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/server-reference-manifest.json +7 -7
  55. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  56. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  57. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/server-reference-manifest.json +7 -7
  58. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js.nft.json +1 -1
  59. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page_client-reference-manifest.js +1 -1
  60. package/web/.next/standalone/packages/web/.next/server/app/unlock/page/server-reference-manifest.json +7 -7
  61. package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js.nft.json +1 -1
  62. package/web/.next/standalone/packages/web/.next/server/app/unlock/page_client-reference-manifest.js +1 -1
  63. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__6622b514._.js +1 -1
  64. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__869d9ac0._.js +1 -1
  65. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__9dc23e5a._.js +1 -1
  66. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__c3eb4913._.js → [root-of-the-server]__a324b6db._.js} +2 -2
  67. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__b388693f._.js +1 -1
  68. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_0e1412de._.js +1 -1
  69. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_3acfb388._.js +1 -1
  70. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_668c9201._.js +1 -1
  71. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_69e05fca._.js +1 -1
  72. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_80efe193._.js +1 -1
  73. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_b6d31783._.js +1 -1
  74. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_c0f0e227._.js +1 -1
  75. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_f36ddaa9._.js +1 -1
  76. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{node_modules_@clerk_nextjs_dist_esm_app-router_129dde21._.js → node_modules_@clerk_nextjs_dist_esm_app-router_6ed7a74d._.js} +2 -2
  77. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_9e576054._.js +3 -0
  78. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_f2ebd7a9._.js +1 -1
  79. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_79316445._.js +1 -1
  80. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_a078c137._.js +1 -1
  81. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_app_page_tsx_cd282e82._.js +1 -1
  82. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{packages_web_src_components_aad7de7c._.js → packages_web_src_components_80ce6eea._.js} +1 -1
  83. package/web/.next/standalone/packages/web/.next/server/pages/404.html +1 -1
  84. package/web/.next/standalone/packages/web/.next/server/pages/500.html +2 -2
  85. package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
  86. package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.json +8 -8
  87. package/web/.next/standalone/packages/web/.next/static/chunks/25438e9094804f85.js +1 -0
  88. package/web/.next/standalone/packages/web/.next/static/chunks/{5c5637796e242130.js → 34d660195aaf8635.js} +2 -2
  89. package/web/.next/standalone/packages/web/.next/static/chunks/{07a5ac7389686572.js → 3814813ead38f9ae.js} +1 -1
  90. package/web/.next/standalone/packages/web/.next/static/chunks/524a7c2a8e85ea2f.js +1 -0
  91. package/web/.next/{static/chunks/e8d146cc2723147b.js → standalone/packages/web/.next/static/chunks/5672ef74a562c5dd.js} +1 -1
  92. package/web/.next/standalone/packages/web/.next/static/chunks/77d150e9b7dda43c.js +1 -0
  93. package/web/.next/standalone/packages/web/.next/static/chunks/8ec81b945f12169b.js +1 -0
  94. package/web/.next/standalone/packages/web/.next/static/chunks/aa158726d4a10331.js +1 -0
  95. package/web/.next/standalone/packages/web/.next/static/chunks/d3cd3cf58c908ec9.js +1 -0
  96. package/web/.next/standalone/packages/web/.next/static/chunks/df9658182f4f7d54.css +3 -0
  97. package/web/.next/standalone/packages/web/package.json +1 -0
  98. package/web/.next/standalone/packages/web/src/components/layout/Sidebar.tsx +20 -2
  99. package/web/.next/standalone/packages/web/src/components/layout/WorkspaceSidebarPanel.tsx +64 -74
  100. package/web/.next/standalone/packages/web/src/components/sessions/SessionOverview.tsx +114 -50
  101. package/web/.next/standalone/packages/web/src/features/dashboard/DashboardClient.tsx +459 -115
  102. package/web/.next/standalone/packages/web/src/features/dashboard/components/WorkspaceOverview.tsx +13 -31
  103. package/web/.next/standalone/packages/web/src/features/sessions/SessionPageClient.tsx +4 -1
  104. package/web/.next/standalone/packages/web/src/hooks/useSessions.ts +13 -0
  105. package/web/.next/standalone/packages/web/src/lib/types.ts +3 -0
  106. package/web/.next/static/chunks/25438e9094804f85.js +1 -0
  107. package/web/.next/static/chunks/{5c5637796e242130.js → 34d660195aaf8635.js} +2 -2
  108. package/web/.next/static/chunks/{07a5ac7389686572.js → 3814813ead38f9ae.js} +1 -1
  109. package/web/.next/static/chunks/524a7c2a8e85ea2f.js +1 -0
  110. package/web/.next/{standalone/packages/web/.next/static/chunks/e8d146cc2723147b.js → static/chunks/5672ef74a562c5dd.js} +1 -1
  111. package/web/.next/static/chunks/77d150e9b7dda43c.js +1 -0
  112. package/web/.next/static/chunks/8ec81b945f12169b.js +1 -0
  113. package/web/.next/static/chunks/aa158726d4a10331.js +1 -0
  114. package/web/.next/static/chunks/d3cd3cf58c908ec9.js +1 -0
  115. package/web/.next/static/chunks/df9658182f4f7d54.css +3 -0
  116. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_1776df7f._.js +0 -3
  117. package/web/.next/standalone/packages/web/.next/static/chunks/3603312f8407bd12.js +0 -1
  118. package/web/.next/standalone/packages/web/.next/static/chunks/382be8f0b30c5f08.js +0 -1
  119. package/web/.next/standalone/packages/web/.next/static/chunks/479b8cb58c95a8a0.js +0 -1
  120. package/web/.next/standalone/packages/web/.next/static/chunks/53e4f3b495e423c9.js +0 -1
  121. package/web/.next/standalone/packages/web/.next/static/chunks/5e05e67a26b7ecbc.js +0 -1
  122. package/web/.next/standalone/packages/web/.next/static/chunks/6d083840413686dd.css +0 -3
  123. package/web/.next/standalone/packages/web/.next/static/chunks/c7c1bd729f17c8bf.js +0 -1
  124. package/web/.next/static/chunks/3603312f8407bd12.js +0 -1
  125. package/web/.next/static/chunks/382be8f0b30c5f08.js +0 -1
  126. package/web/.next/static/chunks/479b8cb58c95a8a0.js +0 -1
  127. package/web/.next/static/chunks/53e4f3b495e423c9.js +0 -1
  128. package/web/.next/static/chunks/5e05e67a26b7ecbc.js +0 -1
  129. package/web/.next/static/chunks/6d083840413686dd.css +0 -3
  130. package/web/.next/static/chunks/c7c1bd729f17c8bf.js +0 -1
  131. /package/web/.next/standalone/packages/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_buildManifest.js +0 -0
  132. /package/web/.next/standalone/packages/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_clientMiddlewareManifest.json +0 -0
  133. /package/web/.next/standalone/packages/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_ssgManifest.js +0 -0
  134. /package/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_buildManifest.js +0 -0
  135. /package/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_clientMiddlewareManifest.json +0 -0
  136. /package/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_ssgManifest.js +0 -0
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -2,8 +2,8 @@
2
2
  * agent-gemini plugin — Google Gemini CLI as the AI coding agent.
3
3
  *
4
4
  * - processName: "gemini"
5
- * - promptDelivery: "inline" (prompt passed as positional arg)
6
- * - getLaunchCommand: `gemini --yolo "<prompt>"`
5
+ * - promptDelivery: "inline" (prompt passed via --prompt-interactive)
6
+ * - getLaunchCommand: `gemini --prompt-interactive "<prompt>"`
7
7
  * - Activity detection from terminal output patterns
8
8
  * - isProcessRunning: check tmux pane for gemini process
9
9
  *
@@ -16,7 +16,49 @@ export declare const manifest: {
16
16
  description: string;
17
17
  version: string;
18
18
  };
19
+ interface GeminiThought {
20
+ subject?: string;
21
+ description?: string;
22
+ timestamp?: string;
23
+ }
24
+ interface GeminiTokens {
25
+ input?: number;
26
+ output?: number;
27
+ }
28
+ interface GeminiMessagePart {
29
+ text?: string;
30
+ }
31
+ interface GeminiChatMessage {
32
+ id?: string;
33
+ timestamp?: string;
34
+ type?: string;
35
+ content?: string | GeminiMessagePart[];
36
+ thoughts?: GeminiThought[];
37
+ tokens?: GeminiTokens;
38
+ model?: string;
39
+ }
40
+ interface GeminiChatSession {
41
+ sessionId?: string;
42
+ startTime?: string;
43
+ lastUpdated?: string;
44
+ messages?: GeminiChatMessage[];
45
+ }
46
+ declare function readGeminiProjectsIndex(baseDir?: string): Promise<Record<string, string>>;
47
+ declare function resolveGeminiProjectAlias(workspacePath: string, baseDir?: string): Promise<string | null>;
48
+ declare function findGeminiSessionFile(workspacePath: string, baseDir?: string): Promise<string | null>;
49
+ declare function extractGeminiMessageText(message: GeminiChatMessage | null | undefined): string | null;
50
+ declare function extractGeminiSummary(data: GeminiChatSession): {
51
+ summary: string | null;
52
+ summaryIsFallback: boolean;
53
+ };
19
54
  export declare function create(): Agent;
55
+ export declare const __test__: {
56
+ extractGeminiMessageText: typeof extractGeminiMessageText;
57
+ extractGeminiSummary: typeof extractGeminiSummary;
58
+ findGeminiSessionFile: typeof findGeminiSessionFile;
59
+ readGeminiProjectsIndex: typeof readGeminiProjectsIndex;
60
+ resolveGeminiProjectAlias: typeof resolveGeminiProjectAlias;
61
+ };
20
62
  declare const _default: {
21
63
  manifest: {
22
64
  name: string;
@@ -2,8 +2,8 @@
2
2
  * agent-gemini plugin — Google Gemini CLI as the AI coding agent.
3
3
  *
4
4
  * - processName: "gemini"
5
- * - promptDelivery: "inline" (prompt passed as positional arg)
6
- * - getLaunchCommand: `gemini --yolo "<prompt>"`
5
+ * - promptDelivery: "inline" (prompt passed via --prompt-interactive)
6
+ * - getLaunchCommand: `gemini --prompt-interactive "<prompt>"`
7
7
  * - Activity detection from terminal output patterns
8
8
  * - isProcessRunning: check tmux pane for gemini process
9
9
  *
@@ -12,7 +12,7 @@
12
12
  import { shellEscape } from "@conductor-oss/core";
13
13
  import { execFile } from "node:child_process";
14
14
  import { existsSync } from "node:fs";
15
- import { writeFile, mkdir, readFile, rename } from "node:fs/promises";
15
+ import { writeFile, mkdir, readFile, rename, readdir, stat } from "node:fs/promises";
16
16
  import { homedir } from "node:os";
17
17
  import { join } from "node:path";
18
18
  import { promisify } from "node:util";
@@ -52,6 +52,8 @@ function findTmuxBin() {
52
52
  const TMUX_BIN = findTmuxBin();
53
53
  const DEFAULT_READY_THRESHOLD_MS = 60_000;
54
54
  const CLAW_BIN_DIR = join(homedir(), ".conductor", "bin");
55
+ const GEMINI_HOME_DIR = join(homedir(), ".gemini");
56
+ const geminiSessionFileCache = new Map();
55
57
  // =============================================================================
56
58
  // Plugin Manifest
57
59
  // =============================================================================
@@ -157,6 +159,137 @@ async function setupGeminiWorkspace(workspacePath) {
157
159
  await writeFile(agentsMdPath, existing ? existing.trimEnd() + "\n" + section : section.trimStart(), "utf-8");
158
160
  }
159
161
  }
162
+ async function readGeminiProjectsIndex(baseDir = GEMINI_HOME_DIR) {
163
+ try {
164
+ const content = await readFile(join(baseDir, "projects.json"), "utf-8");
165
+ const parsed = JSON.parse(content);
166
+ return Object.fromEntries(Object.entries(parsed.projects ?? {}).filter((entry) => {
167
+ return typeof entry[0] === "string" && typeof entry[1] === "string" && entry[1].trim().length > 0;
168
+ }));
169
+ }
170
+ catch {
171
+ return {};
172
+ }
173
+ }
174
+ async function resolveGeminiProjectAlias(workspacePath, baseDir = GEMINI_HOME_DIR) {
175
+ const projects = await readGeminiProjectsIndex(baseDir);
176
+ const alias = projects[workspacePath];
177
+ return typeof alias === "string" && alias.trim().length > 0 ? alias : null;
178
+ }
179
+ async function findGeminiSessionFile(workspacePath, baseDir = GEMINI_HOME_DIR) {
180
+ const alias = await resolveGeminiProjectAlias(workspacePath, baseDir);
181
+ if (!alias)
182
+ return null;
183
+ const chatsDir = join(baseDir, "tmp", alias, "chats");
184
+ let entries;
185
+ try {
186
+ entries = await readdir(chatsDir);
187
+ }
188
+ catch {
189
+ return null;
190
+ }
191
+ const candidates = entries.filter((entry) => entry.startsWith("session-") && entry.endsWith(".json"));
192
+ if (candidates.length === 0)
193
+ return null;
194
+ let bestMatch = null;
195
+ for (const entry of candidates) {
196
+ const filePath = join(chatsDir, entry);
197
+ try {
198
+ const info = await stat(filePath);
199
+ if (!bestMatch || info.mtimeMs > bestMatch.mtimeMs) {
200
+ bestMatch = { path: filePath, mtimeMs: info.mtimeMs };
201
+ }
202
+ }
203
+ catch {
204
+ // Skip unreadable files.
205
+ }
206
+ }
207
+ return bestMatch?.path ?? null;
208
+ }
209
+ async function findGeminiSessionFileCached(workspacePath) {
210
+ const cached = geminiSessionFileCache.get(workspacePath);
211
+ if (cached) {
212
+ try {
213
+ await stat(cached);
214
+ return cached;
215
+ }
216
+ catch {
217
+ geminiSessionFileCache.delete(workspacePath);
218
+ }
219
+ }
220
+ const resolved = await findGeminiSessionFile(workspacePath);
221
+ geminiSessionFileCache.set(workspacePath, resolved);
222
+ return resolved;
223
+ }
224
+ async function readGeminiSessionFile(filePath) {
225
+ try {
226
+ const content = await readFile(filePath, "utf-8");
227
+ return JSON.parse(content);
228
+ }
229
+ catch {
230
+ return null;
231
+ }
232
+ }
233
+ function extractGeminiMessageText(message) {
234
+ if (!message)
235
+ return null;
236
+ if (typeof message.content === "string") {
237
+ const normalized = message.content.trim();
238
+ return normalized.length > 0 ? normalized : null;
239
+ }
240
+ if (Array.isArray(message.content)) {
241
+ const normalized = message.content
242
+ .map((part) => part?.text?.trim())
243
+ .filter((part) => Boolean(part))
244
+ .join("\n")
245
+ .trim();
246
+ return normalized.length > 0 ? normalized : null;
247
+ }
248
+ return null;
249
+ }
250
+ function extractGeminiSummary(data) {
251
+ const messages = Array.isArray(data.messages) ? data.messages : [];
252
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
253
+ const message = messages[index];
254
+ if (message?.type !== "gemini")
255
+ continue;
256
+ const content = extractGeminiMessageText(message);
257
+ if (content) {
258
+ return { summary: content, summaryIsFallback: false };
259
+ }
260
+ }
261
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
262
+ const thought = messages[index]?.thoughts?.find((entry) => entry?.description?.trim());
263
+ if (thought?.description) {
264
+ return { summary: thought.description.trim(), summaryIsFallback: true };
265
+ }
266
+ }
267
+ for (const message of messages) {
268
+ if (message?.type !== "user")
269
+ continue;
270
+ const content = extractGeminiMessageText(message);
271
+ if (content) {
272
+ return { summary: content, summaryIsFallback: true };
273
+ }
274
+ }
275
+ return { summary: null, summaryIsFallback: true };
276
+ }
277
+ function extractGeminiModel(data) {
278
+ const messages = Array.isArray(data.messages) ? data.messages : [];
279
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
280
+ const model = messages[index]?.model?.trim();
281
+ if (model)
282
+ return model;
283
+ }
284
+ return null;
285
+ }
286
+ function resolveGeminiTimestamp(data, fallback) {
287
+ const timestamp = data.lastUpdated ?? data.startTime;
288
+ if (!timestamp)
289
+ return fallback;
290
+ const parsed = new Date(timestamp);
291
+ return Number.isNaN(parsed.getTime()) ? fallback : parsed;
292
+ }
160
293
  // =============================================================================
161
294
  // Terminal Output Detection
162
295
  // =============================================================================
@@ -208,17 +341,12 @@ function createGeminiAgent() {
208
341
  if (config.model) {
209
342
  parts.push("--model", shellEscape(config.model));
210
343
  }
211
- // Gemini CLI: --yolo auto-approves all tool calls
212
- // --approval-mode=auto_edit is a middle ground (auto-approve edits only)
213
344
  if (config.permissions === "skip") {
214
345
  parts.push("--yolo");
215
346
  }
216
- else {
217
- parts.push("--yolo");
218
- }
219
- // Gemini takes prompt as positional argument for one-shot execution
347
+ // Keep Gemini interactive so follow-up turns can reuse the same runtime.
220
348
  if (config.prompt) {
221
- parts.push(shellEscape(config.prompt));
349
+ parts.push("--prompt-interactive", shellEscape(config.prompt));
222
350
  }
223
351
  return parts.join(" ");
224
352
  },
@@ -234,13 +362,37 @@ function createGeminiAgent() {
234
362
  return classifyGeminiTerminal(terminalOutput);
235
363
  },
236
364
  async getActivityState(session, readyThresholdMs) {
237
- void (readyThresholdMs ?? DEFAULT_READY_THRESHOLD_MS);
238
365
  if (!session.runtimeHandle)
239
366
  return { state: "exited", timestamp: new Date() };
240
367
  const running = await this.isProcessRunning(session.runtimeHandle);
241
368
  if (!running)
242
369
  return { state: "exited", timestamp: new Date() };
243
- // Gemini doesn't write JSONL session files — rely on terminal output
370
+ const threshold = readyThresholdMs ?? DEFAULT_READY_THRESHOLD_MS;
371
+ const sessionFile = session.workspacePath
372
+ ? await findGeminiSessionFileCached(session.workspacePath)
373
+ : null;
374
+ if (sessionFile) {
375
+ try {
376
+ const sessionData = await readGeminiSessionFile(sessionFile);
377
+ const stats = await stat(sessionFile);
378
+ const timestamp = resolveGeminiTimestamp(sessionData ?? {}, stats.mtime);
379
+ const ageMs = Date.now() - timestamp.getTime();
380
+ if (ageMs <= threshold) {
381
+ return { state: "active", timestamp };
382
+ }
383
+ const termOutput = await captureTmuxPane(session.runtimeHandle);
384
+ if (termOutput) {
385
+ const state = classifyGeminiTerminal(termOutput);
386
+ if (state === "active" || state === "waiting_input") {
387
+ return { state, timestamp: new Date() };
388
+ }
389
+ }
390
+ return { state: "ready", timestamp };
391
+ }
392
+ catch {
393
+ // Fall through to terminal heuristics.
394
+ }
395
+ }
244
396
  const termOutput = await captureTmuxPane(session.runtimeHandle);
245
397
  if (termOutput) {
246
398
  const state = classifyGeminiTerminal(termOutput);
@@ -287,6 +439,21 @@ function createGeminiAgent() {
287
439
  }
288
440
  },
289
441
  async getSessionInfo(session) {
442
+ if (session.workspacePath) {
443
+ const sessionFile = await findGeminiSessionFileCached(session.workspacePath);
444
+ if (sessionFile) {
445
+ const data = await readGeminiSessionFile(sessionFile);
446
+ if (data) {
447
+ const summary = extractGeminiSummary(data);
448
+ return {
449
+ summary: summary.summary,
450
+ summaryIsFallback: summary.summaryIsFallback,
451
+ agentSessionId: data.sessionId ?? null,
452
+ cost: undefined,
453
+ };
454
+ }
455
+ }
456
+ }
290
457
  if (!session.runtimeHandle)
291
458
  return null;
292
459
  const termOutput = await captureTmuxPane(session.runtimeHandle, 50);
@@ -300,11 +467,23 @@ function createGeminiAgent() {
300
467
  .substring(0, 200) || null;
301
468
  return { summary, summaryIsFallback: true, agentSessionId: session.id, cost: undefined };
302
469
  },
303
- async getRestoreCommand(_session, project) {
304
- const parts = [GEMINI_BIN, "--yolo"];
305
- if (project.agentConfig?.model)
306
- parts.push("--model", shellEscape(project.agentConfig.model));
307
- parts.push("--resume", "latest");
470
+ async getRestoreCommand(session, project) {
471
+ if (!session.workspacePath)
472
+ return null;
473
+ const sessionFile = await findGeminiSessionFileCached(session.workspacePath);
474
+ if (!sessionFile)
475
+ return null;
476
+ const data = await readGeminiSessionFile(sessionFile);
477
+ if (!data?.sessionId)
478
+ return null;
479
+ const parts = [GEMINI_BIN];
480
+ if (project.agentConfig?.permissions === "skip") {
481
+ parts.push("--yolo");
482
+ }
483
+ const model = session.metadata["model"] || project.agentConfig?.model || extractGeminiModel(data);
484
+ if (model)
485
+ parts.push("--model", shellEscape(model));
486
+ parts.push("--resume", shellEscape(data.sessionId));
308
487
  return parts.join(" ");
309
488
  },
310
489
  async setupWorkspaceHooks(workspacePath, config) {
@@ -337,4 +516,11 @@ function createGeminiAgent() {
337
516
  export function create() {
338
517
  return createGeminiAgent();
339
518
  }
519
+ export const __test__ = {
520
+ extractGeminiMessageText,
521
+ extractGeminiSummary,
522
+ findGeminiSessionFile,
523
+ readGeminiProjectsIndex,
524
+ resolveGeminiProjectAlias,
525
+ };
340
526
  export default { manifest, create };
@@ -4,7 +4,7 @@
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "dependencies": {
7
- "@conductor-oss/core": "0.3.1"
7
+ "@conductor-oss/core": "0.3.3"
8
8
  },
9
9
  "types": "dist/index.d.ts"
10
10
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1",
8
+ "@conductor-oss/core": "0.3.3",
9
9
  "@modelcontextprotocol/sdk": "^1.27.1",
10
10
  "zod": "^4.3.6"
11
11
  },
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@conductor-oss/core": "0.3.1"
8
+ "@conductor-oss/core": "0.3.3"
9
9
  },
10
10
  "types": "dist/index.d.ts"
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-oss",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/launcher.js",
@@ -33,31 +33,32 @@
33
33
  "directory": "packages/cli"
34
34
  },
35
35
  "dependencies": {
36
- "@conductor-oss/core": "0.3.1",
37
- "@conductor-oss/plugin-agent-claude-code": "0.3.1",
38
- "@conductor-oss/plugin-agent-codex": "0.3.1",
39
- "@conductor-oss/plugin-agent-gemini": "0.3.1",
40
- "@conductor-oss/plugin-agent-amp": "0.3.1",
41
- "@conductor-oss/plugin-agent-cursor-cli": "0.3.1",
42
- "@conductor-oss/plugin-agent-opencode": "0.3.1",
43
- "@conductor-oss/plugin-agent-droid": "0.3.1",
44
- "@conductor-oss/plugin-agent-qwen-code": "0.3.1",
45
- "@conductor-oss/plugin-agent-ccr": "0.3.1",
46
- "@conductor-oss/plugin-agent-github-copilot": "0.3.1",
47
- "@conductor-oss/plugin-mcp-server": "0.3.1",
48
- "@conductor-oss/plugin-notifier-desktop": "0.3.1",
49
- "@conductor-oss/plugin-notifier-discord": "0.3.1",
50
- "@conductor-oss/plugin-runtime-tmux": "0.3.1",
51
- "@conductor-oss/plugin-scm-github": "0.3.1",
52
- "@conductor-oss/plugin-terminal-web": "0.3.1",
53
- "@conductor-oss/plugin-tracker-github": "0.3.1",
54
- "@conductor-oss/plugin-workspace-worktree": "0.3.1",
36
+ "@conductor-oss/core": "0.3.3",
37
+ "@conductor-oss/plugin-agent-claude-code": "0.3.3",
38
+ "@conductor-oss/plugin-agent-codex": "0.3.3",
39
+ "@conductor-oss/plugin-agent-gemini": "0.3.3",
40
+ "@conductor-oss/plugin-agent-amp": "0.3.3",
41
+ "@conductor-oss/plugin-agent-cursor-cli": "0.3.3",
42
+ "@conductor-oss/plugin-agent-opencode": "0.3.3",
43
+ "@conductor-oss/plugin-agent-droid": "0.3.3",
44
+ "@conductor-oss/plugin-agent-qwen-code": "0.3.3",
45
+ "@conductor-oss/plugin-agent-ccr": "0.3.3",
46
+ "@conductor-oss/plugin-agent-github-copilot": "0.3.3",
47
+ "@conductor-oss/plugin-mcp-server": "0.3.3",
48
+ "@conductor-oss/plugin-notifier-desktop": "0.3.3",
49
+ "@conductor-oss/plugin-notifier-discord": "0.3.3",
50
+ "@conductor-oss/plugin-runtime-tmux": "0.3.3",
51
+ "@conductor-oss/plugin-scm-github": "0.3.3",
52
+ "@conductor-oss/plugin-terminal-web": "0.3.3",
53
+ "@conductor-oss/plugin-tracker-github": "0.3.3",
54
+ "@conductor-oss/plugin-workspace-worktree": "0.3.3",
55
55
  "chalk": "^5.6.2",
56
56
  "commander": "^14.0.3",
57
57
  "ora": "^9.3.0",
58
58
  "yaml": "^2.8.2",
59
59
  "zod": "^4.3.6",
60
60
  "@modelcontextprotocol/sdk": "^1.27.1",
61
+ "@primer/octicons-react": "^19.15.0",
61
62
  "@clerk/nextjs": "^6.39.0",
62
63
  "@radix-ui/react-dialog": "^1.1.15",
63
64
  "@radix-ui/react-dropdown-menu": "^2.1.16",
@@ -80,9 +81,9 @@
80
81
  "tailwind-merge": "^3.5.0"
81
82
  },
82
83
  "optionalDependencies": {
83
- "conductor-oss-native-darwin-universal": "0.3.1",
84
- "conductor-oss-native-linux-x64": "0.3.1",
85
- "conductor-oss-native-win32-x64": "0.3.1"
84
+ "conductor-oss-native-darwin-universal": "0.3.3",
85
+ "conductor-oss-native-linux-x64": "0.3.3",
86
+ "conductor-oss-native-win32-x64": "0.3.3"
86
87
  },
87
88
  "files": [
88
89
  "dist/",
@@ -1 +1 @@
1
- oFTStwDpHHac4pinj0rAJ
1
+ -Z2NIcYE-i0soCDJ1TgtS
@@ -7,8 +7,8 @@
7
7
  "static/chunks/a6dad97d9634a72d.js"
8
8
  ],
9
9
  "lowPriorityFiles": [
10
- "static/oFTStwDpHHac4pinj0rAJ/_ssgManifest.js",
11
- "static/oFTStwDpHHac4pinj0rAJ/_buildManifest.js"
10
+ "static/-Z2NIcYE-i0soCDJ1TgtS/_ssgManifest.js",
11
+ "static/-Z2NIcYE-i0soCDJ1TgtS/_buildManifest.js"
12
12
  ],
13
13
  "rootMainFiles": [
14
14
  "static/chunks/ba2aa8b54e912820.js",
@@ -107,8 +107,8 @@
107
107
  "dynamicRoutes": {},
108
108
  "notFoundRoutes": [],
109
109
  "preview": {
110
- "previewModeId": "d34ce7a3ec45b91f3d30b2d2e11c7187",
111
- "previewModeSigningKey": "54021a90947064af03426112dec196e71594c5a5b438d055511de556a82278d9",
112
- "previewModeEncryptionKey": "17e60ba3bd84494a80fd7c1dc48ca8d840c46815634a9f163020a38b43372e7f"
110
+ "previewModeId": "824a486ec61583470739df2602cac8fe",
111
+ "previewModeSigningKey": "e885d14710c6bee5ac474567a28390fbc914c5c89314cdea41a17ed9f7f3106c",
112
+ "previewModeEncryptionKey": "0d59d6f8d89c3393c8955e78ad94953e69b2dd7cbc653de802c912a6acd03397"
113
113
  }
114
114
  }