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.
- package/node_modules/@conductor-oss/plugin-agent-amp/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-ccr/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-claude-code/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-codex/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-cursor-cli/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-droid/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-gemini/dist/index.d.ts +44 -2
- package/node_modules/@conductor-oss/plugin-agent-gemini/dist/index.js +203 -17
- package/node_modules/@conductor-oss/plugin-agent-gemini/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-github-copilot/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-opencode/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-qwen-code/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-mcp-server/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-notifier-desktop/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-notifier-discord/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-runtime-tmux/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-scm-github/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-terminal-web/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-tracker-github/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-workspace-worktree/package.json +1 -1
- package/package.json +24 -23
- package/web/.next/standalone/packages/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/packages/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/packages/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/index.rsc +4 -4
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/page/react-loadable-manifest.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__6622b514._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__869d9ac0._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__9dc23e5a._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__c3eb4913._.js → [root-of-the-server]__a324b6db._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__b388693f._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_0e1412de._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_3acfb388._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_668c9201._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_69e05fca._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_80efe193._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_b6d31783._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_c0f0e227._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_f36ddaa9._.js +1 -1
- 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
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_9e576054._.js +3 -0
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_f2ebd7a9._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_79316445._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_a078c137._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_app_page_tsx_cd282e82._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{packages_web_src_components_aad7de7c._.js → packages_web_src_components_80ce6eea._.js} +1 -1
- package/web/.next/standalone/packages/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.json +8 -8
- package/web/.next/standalone/packages/web/.next/static/chunks/25438e9094804f85.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/{5c5637796e242130.js → 34d660195aaf8635.js} +2 -2
- package/web/.next/standalone/packages/web/.next/static/chunks/{07a5ac7389686572.js → 3814813ead38f9ae.js} +1 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/524a7c2a8e85ea2f.js +1 -0
- package/web/.next/{static/chunks/e8d146cc2723147b.js → standalone/packages/web/.next/static/chunks/5672ef74a562c5dd.js} +1 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/77d150e9b7dda43c.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/8ec81b945f12169b.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/aa158726d4a10331.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/d3cd3cf58c908ec9.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/df9658182f4f7d54.css +3 -0
- package/web/.next/standalone/packages/web/package.json +1 -0
- package/web/.next/standalone/packages/web/src/components/layout/Sidebar.tsx +20 -2
- package/web/.next/standalone/packages/web/src/components/layout/WorkspaceSidebarPanel.tsx +64 -74
- package/web/.next/standalone/packages/web/src/components/sessions/SessionOverview.tsx +114 -50
- package/web/.next/standalone/packages/web/src/features/dashboard/DashboardClient.tsx +459 -115
- package/web/.next/standalone/packages/web/src/features/dashboard/components/WorkspaceOverview.tsx +13 -31
- package/web/.next/standalone/packages/web/src/features/sessions/SessionPageClient.tsx +4 -1
- package/web/.next/standalone/packages/web/src/hooks/useSessions.ts +13 -0
- package/web/.next/standalone/packages/web/src/lib/types.ts +3 -0
- package/web/.next/static/chunks/25438e9094804f85.js +1 -0
- package/web/.next/static/chunks/{5c5637796e242130.js → 34d660195aaf8635.js} +2 -2
- package/web/.next/static/chunks/{07a5ac7389686572.js → 3814813ead38f9ae.js} +1 -1
- package/web/.next/static/chunks/524a7c2a8e85ea2f.js +1 -0
- package/web/.next/{standalone/packages/web/.next/static/chunks/e8d146cc2723147b.js → static/chunks/5672ef74a562c5dd.js} +1 -1
- package/web/.next/static/chunks/77d150e9b7dda43c.js +1 -0
- package/web/.next/static/chunks/8ec81b945f12169b.js +1 -0
- package/web/.next/static/chunks/aa158726d4a10331.js +1 -0
- package/web/.next/static/chunks/d3cd3cf58c908ec9.js +1 -0
- package/web/.next/static/chunks/df9658182f4f7d54.css +3 -0
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_1776df7f._.js +0 -3
- package/web/.next/standalone/packages/web/.next/static/chunks/3603312f8407bd12.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/382be8f0b30c5f08.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/479b8cb58c95a8a0.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/53e4f3b495e423c9.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/5e05e67a26b7ecbc.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/6d083840413686dd.css +0 -3
- package/web/.next/standalone/packages/web/.next/static/chunks/c7c1bd729f17c8bf.js +0 -1
- package/web/.next/static/chunks/3603312f8407bd12.js +0 -1
- package/web/.next/static/chunks/382be8f0b30c5f08.js +0 -1
- package/web/.next/static/chunks/479b8cb58c95a8a0.js +0 -1
- package/web/.next/static/chunks/53e4f3b495e423c9.js +0 -1
- package/web/.next/static/chunks/5e05e67a26b7ecbc.js +0 -1
- package/web/.next/static/chunks/6d083840413686dd.css +0 -3
- package/web/.next/static/chunks/c7c1bd729f17c8bf.js +0 -1
- /package/web/.next/standalone/packages/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_buildManifest.js +0 -0
- /package/web/.next/standalone/packages/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/packages/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_ssgManifest.js +0 -0
- /package/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_buildManifest.js +0 -0
- /package/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{oFTStwDpHHac4pinj0rAJ → -Z2NIcYE-i0soCDJ1TgtS}/_ssgManifest.js +0 -0
|
@@ -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
|
|
6
|
-
* - getLaunchCommand: `gemini --
|
|
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
|
|
6
|
-
* - getLaunchCommand: `gemini --
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor-oss",
|
|
3
|
-
"version": "0.3.
|
|
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.
|
|
37
|
-
"@conductor-oss/plugin-agent-claude-code": "0.3.
|
|
38
|
-
"@conductor-oss/plugin-agent-codex": "0.3.
|
|
39
|
-
"@conductor-oss/plugin-agent-gemini": "0.3.
|
|
40
|
-
"@conductor-oss/plugin-agent-amp": "0.3.
|
|
41
|
-
"@conductor-oss/plugin-agent-cursor-cli": "0.3.
|
|
42
|
-
"@conductor-oss/plugin-agent-opencode": "0.3.
|
|
43
|
-
"@conductor-oss/plugin-agent-droid": "0.3.
|
|
44
|
-
"@conductor-oss/plugin-agent-qwen-code": "0.3.
|
|
45
|
-
"@conductor-oss/plugin-agent-ccr": "0.3.
|
|
46
|
-
"@conductor-oss/plugin-agent-github-copilot": "0.3.
|
|
47
|
-
"@conductor-oss/plugin-mcp-server": "0.3.
|
|
48
|
-
"@conductor-oss/plugin-notifier-desktop": "0.3.
|
|
49
|
-
"@conductor-oss/plugin-notifier-discord": "0.3.
|
|
50
|
-
"@conductor-oss/plugin-runtime-tmux": "0.3.
|
|
51
|
-
"@conductor-oss/plugin-scm-github": "0.3.
|
|
52
|
-
"@conductor-oss/plugin-terminal-web": "0.3.
|
|
53
|
-
"@conductor-oss/plugin-tracker-github": "0.3.
|
|
54
|
-
"@conductor-oss/plugin-workspace-worktree": "0.3.
|
|
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.
|
|
84
|
-
"conductor-oss-native-linux-x64": "0.3.
|
|
85
|
-
"conductor-oss-native-win32-x64": "0.3.
|
|
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
|
-
|
|
1
|
+
-Z2NIcYE-i0soCDJ1TgtS
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
"static/chunks/a6dad97d9634a72d.js"
|
|
8
8
|
],
|
|
9
9
|
"lowPriorityFiles": [
|
|
10
|
-
"static/
|
|
11
|
-
"static/
|
|
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": "
|
|
111
|
-
"previewModeSigningKey": "
|
|
112
|
-
"previewModeEncryptionKey": "
|
|
110
|
+
"previewModeId": "824a486ec61583470739df2602cac8fe",
|
|
111
|
+
"previewModeSigningKey": "e885d14710c6bee5ac474567a28390fbc914c5c89314cdea41a17ed9f7f3106c",
|
|
112
|
+
"previewModeEncryptionKey": "0d59d6f8d89c3393c8955e78ad94953e69b2dd7cbc653de802c912a6acd03397"
|
|
113
113
|
}
|
|
114
114
|
}
|