@kenkaiiii/ggcoder 5.16.0 → 5.17.0
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/dist/app-sidecar.js +129 -44
- package/dist/app-sidecar.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +15 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-review-coverage.test.d.ts +2 -0
- package/dist/core/agent-session-review-coverage.test.d.ts.map +1 -0
- package/dist/core/agent-session-review-coverage.test.js +57 -0
- package/dist/core/agent-session-review-coverage.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +11 -4
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +133 -22
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compactor.test.js +1 -1
- package/dist/core/compaction/compactor.test.js.map +1 -1
- package/dist/core/event-bus.d.ts +2 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/ideal-review.d.ts +27 -0
- package/dist/core/ideal-review.d.ts.map +1 -1
- package/dist/core/ideal-review.js +64 -0
- package/dist/core/ideal-review.js.map +1 -1
- package/dist/core/ideal-review.test.js +34 -1
- package/dist/core/ideal-review.test.js.map +1 -1
- package/dist/core/lsp/client.d.ts +3 -0
- package/dist/core/lsp/client.d.ts.map +1 -1
- package/dist/core/lsp/client.js +20 -0
- package/dist/core/lsp/client.js.map +1 -1
- package/dist/core/lsp/manager.d.ts +32 -9
- package/dist/core/lsp/manager.d.ts.map +1 -1
- package/dist/core/lsp/manager.js +89 -37
- package/dist/core/lsp/manager.js.map +1 -1
- package/dist/core/lsp/manager.test.js +56 -4
- package/dist/core/lsp/manager.test.js.map +1 -1
- package/dist/core/run-lifecycle.d.ts +40 -0
- package/dist/core/run-lifecycle.d.ts.map +1 -0
- package/dist/core/run-lifecycle.js +95 -0
- package/dist/core/run-lifecycle.js.map +1 -0
- package/dist/core/run-lifecycle.test.d.ts +2 -0
- package/dist/core/run-lifecycle.test.d.ts.map +1 -0
- package/dist/core/run-lifecycle.test.js +64 -0
- package/dist/core/run-lifecycle.test.js.map +1 -0
- package/dist/core/session-manager.d.ts +25 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +66 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-manager.test.js +80 -2
- package/dist/core/session-manager.test.js.map +1 -1
- package/dist/core/subagent-manager.d.ts +40 -3
- package/dist/core/subagent-manager.d.ts.map +1 -1
- package/dist/core/subagent-manager.js +342 -30
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/subagent-manager.test.js +189 -3
- package/dist/core/subagent-manager.test.js.map +1 -1
- package/dist/core/subagent-store.d.ts +20 -0
- package/dist/core/subagent-store.d.ts.map +1 -0
- package/dist/core/subagent-store.js +177 -0
- package/dist/core/subagent-store.js.map +1 -0
- package/dist/core/subagent-store.test.d.ts +2 -0
- package/dist/core/subagent-store.test.d.ts.map +1 -0
- package/dist/core/subagent-store.test.js +94 -0
- package/dist/core/subagent-store.test.js.map +1 -0
- package/dist/modes/agent-home-mode.d.ts.map +1 -1
- package/dist/modes/agent-home-mode.js +10 -3
- package/dist/modes/agent-home-mode.js.map +1 -1
- package/dist/modes/serve-mode.d.ts.map +1 -1
- package/dist/modes/serve-mode.js +10 -3
- package/dist/modes/serve-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.d.ts +2 -0
- package/dist/modes/subagent-worker-mode.d.ts.map +1 -1
- package/dist/modes/subagent-worker-mode.js +13 -3
- package/dist/modes/subagent-worker-mode.js.map +1 -1
- package/dist/tools/tasks.d.ts +1 -1
- package/dist/tools/web-fetch.d.ts +1 -1
- package/dist/ui/App.d.ts +7 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +63 -17
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/components/Footer.d.ts +1 -0
- package/dist/ui/components/Footer.d.ts.map +1 -1
- package/dist/ui/components/Footer.js +3 -3
- package/dist/ui/components/Footer.js.map +1 -1
- package/dist/ui/components/Footer.test.d.ts +2 -0
- package/dist/ui/components/Footer.test.d.ts.map +1 -0
- package/dist/ui/components/Footer.test.js +16 -0
- package/dist/ui/components/Footer.test.js.map +1 -0
- package/dist/ui/hooks/useAgentLoop.d.ts +8 -3
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +64 -8
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/hooks/useSessionPersistence.d.ts +4 -2
- package/dist/ui/hooks/useSessionPersistence.d.ts.map +1 -1
- package/dist/ui/hooks/useSessionPersistence.js +7 -1
- package/dist/ui/hooks/useSessionPersistence.js.map +1 -1
- package/dist/ui/render.d.ts +7 -0
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +4 -0
- package/dist/ui/render.js.map +1 -1
- package/package.json +4 -4
package/dist/ui/App.js
CHANGED
|
@@ -12,6 +12,7 @@ import { useTaskBarStore, useTaskBarPolling, focusTaskBar, exitTaskBar, expandTa
|
|
|
12
12
|
import { playNotificationSound } from "../utils/sound.js";
|
|
13
13
|
import {} from "@kenkaiiii/gg-ai";
|
|
14
14
|
import { downscaleForPreview, extractMediaPaths } from "../utils/image.js";
|
|
15
|
+
import { buildSubAgentCompletionFollowUp, } from "../core/subagent-manager.js";
|
|
15
16
|
import { useAgentLoop } from "./hooks/useAgentLoop.js";
|
|
16
17
|
import { useTranscriptHistory } from "./hooks/useTranscriptHistory.js";
|
|
17
18
|
import { createWebSearchTool } from "../tools/web-search.js";
|
|
@@ -247,6 +248,7 @@ export function App(props) {
|
|
|
247
248
|
const sessionManagerRef = useRef(props.sessionsDir ? new SessionManager(props.sessionsDir) : null);
|
|
248
249
|
const sessionPathRef = useRef(props.sessionStore?.sessionPath ?? props.sessionPath);
|
|
249
250
|
const persistedIndexRef = useRef(messagesRef.current.length);
|
|
251
|
+
const turnMetricsRef = useRef(props.sessionStore?.turnMetrics ?? []);
|
|
250
252
|
const sessionStatsRef = useRef(props.sessionStore?.sessionStats ??
|
|
251
253
|
createSessionStats({ sessionId: props.sessionStore?.sessionId ?? props.sessionId }));
|
|
252
254
|
const [idealReviewEnabled, setIdealReviewEnabled] = useState(props.sessionStore?.idealReviewEnabled ?? props.idealReviewEnabled ?? true);
|
|
@@ -410,9 +412,9 @@ export function App(props) {
|
|
|
410
412
|
.map((key) => props.credentialsByProvider?.[key])
|
|
411
413
|
.find((c) => c !== undefined);
|
|
412
414
|
const activeApiKey = currentCreds?.accessToken ?? props.apiKey;
|
|
413
|
-
const activeAccountId = currentCreds
|
|
414
|
-
const activeProjectId = currentCreds
|
|
415
|
-
const activeBaseUrl = currentProvider === "gemini" ? undefined :
|
|
415
|
+
const activeAccountId = currentCreds ? currentCreds.accountId : props.accountId;
|
|
416
|
+
const activeProjectId = currentCreds ? currentCreds.projectId : props.projectId;
|
|
417
|
+
const activeBaseUrl = currentProvider === "gemini" ? undefined : currentCreds ? currentCreds.baseUrl : props.baseUrl;
|
|
416
418
|
const contextWindowOptions = useMemo(() => ({ provider: currentProvider, accountId: activeAccountId }), [currentProvider, activeAccountId]);
|
|
417
419
|
// Load git branch — re-runs whenever the displayed cwd changes.
|
|
418
420
|
useEffect(() => {
|
|
@@ -544,16 +546,19 @@ export function App(props) {
|
|
|
544
546
|
useEffect(() => {
|
|
545
547
|
void applyLanguageDetectionRef.current("initial");
|
|
546
548
|
}, []);
|
|
549
|
+
const rebindSubagentsAfterCompaction = useCallback((sessionId) => props.subAgentManager?.rebindParentSession(sessionId) ?? Promise.resolve(), [props.subAgentManager]);
|
|
547
550
|
const { persistCompactedSession, persistNewMessages } = useSessionPersistence({
|
|
548
551
|
sessionManagerRef,
|
|
549
552
|
sessionPathRef,
|
|
550
553
|
sessionStatsRef,
|
|
551
554
|
persistedIndexRef,
|
|
552
555
|
messagesRef,
|
|
556
|
+
turnMetricsRef,
|
|
553
557
|
cwdRef,
|
|
554
558
|
currentProvider,
|
|
555
559
|
currentModel,
|
|
556
560
|
sessionStore,
|
|
561
|
+
onCompactedSession: rebindSubagentsAfterCompaction,
|
|
557
562
|
});
|
|
558
563
|
/**
|
|
559
564
|
* Run the language detector against the current cwd. If the detected set is a
|
|
@@ -657,6 +662,8 @@ export function App(props) {
|
|
|
657
662
|
projectId: activeProjectId,
|
|
658
663
|
resolveCredentials,
|
|
659
664
|
transformContext,
|
|
665
|
+
lspManager: props.lspManager,
|
|
666
|
+
reviewCoverageTracker: props.reviewCoverageTracker,
|
|
660
667
|
getIdealReviewMessage: (stats, touchedFiles) => {
|
|
661
668
|
if (!idealReviewEnabledRef.current)
|
|
662
669
|
return null;
|
|
@@ -1243,14 +1250,37 @@ export function App(props) {
|
|
|
1243
1250
|
return remaining;
|
|
1244
1251
|
});
|
|
1245
1252
|
}, [queueFlush]),
|
|
1246
|
-
onTurnEnd: useCallback((turn, stopReason, usage) => {
|
|
1253
|
+
onTurnEnd: useCallback((turn, stopReason, usage, timing) => {
|
|
1247
1254
|
recordTurnEnd(sessionStatsRef.current, usage);
|
|
1255
|
+
const metric = {
|
|
1256
|
+
version: 1,
|
|
1257
|
+
turn,
|
|
1258
|
+
provider: currentProvider,
|
|
1259
|
+
model: currentModel,
|
|
1260
|
+
stopReason,
|
|
1261
|
+
usage: { ...usage },
|
|
1262
|
+
timing: { ...timing },
|
|
1263
|
+
cost: {
|
|
1264
|
+
status: "unavailable",
|
|
1265
|
+
reason: "No authoritative effective-dated provider pricing is available",
|
|
1266
|
+
},
|
|
1267
|
+
};
|
|
1268
|
+
turnMetricsRef.current.push(metric);
|
|
1269
|
+
if (sessionStore)
|
|
1270
|
+
sessionStore.turnMetrics = [...turnMetricsRef.current];
|
|
1271
|
+
const metricSessionPath = sessionPathRef.current;
|
|
1272
|
+
const metricManager = sessionManagerRef.current;
|
|
1273
|
+
if (metricSessionPath && metricManager) {
|
|
1274
|
+
void metricManager.appendTurnMetric(metricSessionPath, metric);
|
|
1275
|
+
}
|
|
1248
1276
|
log("INFO", "turn", `Turn ${turn} ended`, {
|
|
1249
1277
|
stopReason,
|
|
1250
1278
|
inputTokens: String(usage.inputTokens),
|
|
1251
1279
|
outputTokens: String(usage.outputTokens),
|
|
1252
1280
|
...(usage.cacheRead != null && { cacheRead: String(usage.cacheRead) }),
|
|
1253
1281
|
...(usage.cacheWrite != null && { cacheWrite: String(usage.cacheWrite) }),
|
|
1282
|
+
providerDurationMs: String(timing.providerDurationMs),
|
|
1283
|
+
...(timing.ttftMs != null && { ttftMs: String(timing.ttftMs) }),
|
|
1254
1284
|
});
|
|
1255
1285
|
// Track actual token count for compaction decisions.
|
|
1256
1286
|
// Anthropic has separate input/output limits — only count input.
|
|
@@ -1268,7 +1298,7 @@ export function App(props) {
|
|
|
1268
1298
|
}
|
|
1269
1299
|
return remaining;
|
|
1270
1300
|
});
|
|
1271
|
-
}, [queueFlush]),
|
|
1301
|
+
}, [currentModel, currentProvider, queueFlush, sessionStore]),
|
|
1272
1302
|
onDone: useCallback((durationMs, toolsUsed, runStats) => {
|
|
1273
1303
|
log("INFO", "agent", `Agent done`, {
|
|
1274
1304
|
duration: `${durationMs}ms`,
|
|
@@ -1398,6 +1428,9 @@ export function App(props) {
|
|
|
1398
1428
|
// natural completion boundary regardless. The stuck-guard caps
|
|
1399
1429
|
// nudges per step so a genuinely blocked agent surfaces.
|
|
1400
1430
|
getFollowUpMessages: useCallback(() => {
|
|
1431
|
+
const childCompletionFollowUp = buildSubAgentCompletionFollowUp(props.subAgentManager);
|
|
1432
|
+
if (childCompletionFollowUp)
|
|
1433
|
+
return childCompletionFollowUp;
|
|
1401
1434
|
const steps = planStepsRef.current;
|
|
1402
1435
|
if (steps.length === 0 || !approvedPlanPathRef.current)
|
|
1403
1436
|
return null;
|
|
@@ -1421,7 +1454,7 @@ export function App(props) {
|
|
|
1421
1454
|
`or you genuinely need user input.`,
|
|
1422
1455
|
},
|
|
1423
1456
|
];
|
|
1424
|
-
}, []),
|
|
1457
|
+
}, [props.subAgentManager]),
|
|
1425
1458
|
onRetry: useCallback(() => {
|
|
1426
1459
|
// Roll back any pending progressive flushes from the aborted attempt.
|
|
1427
1460
|
// Without this, a stall retry regenerates the preamble and the old
|
|
@@ -2140,6 +2173,10 @@ export function App(props) {
|
|
|
2140
2173
|
try {
|
|
2141
2174
|
const session = await sm.create(taskCwd, currentProvider, currentModel);
|
|
2142
2175
|
newSessionPath = session.path;
|
|
2176
|
+
sessionStatsRef.current.sessionId = session.id;
|
|
2177
|
+
if (props.sessionStore)
|
|
2178
|
+
props.sessionStore.sessionId = session.id;
|
|
2179
|
+
await props.subAgentManager?.resetParentSession(session.id);
|
|
2143
2180
|
log("INFO", "tasks", "New session for task", { path: session.path });
|
|
2144
2181
|
}
|
|
2145
2182
|
catch {
|
|
@@ -2165,22 +2202,27 @@ export function App(props) {
|
|
|
2165
2202
|
agentLoop.reset();
|
|
2166
2203
|
persistedIndexRef.current = messagesRef.current.length;
|
|
2167
2204
|
const sm = sessionManagerRef.current;
|
|
2168
|
-
if (sm) {
|
|
2169
|
-
void sm.create(taskCwd, currentProvider, currentModel).then((session) => {
|
|
2170
|
-
sessionPathRef.current = session.path;
|
|
2171
|
-
log("INFO", "tasks", "New session for task", { path: session.path });
|
|
2172
|
-
});
|
|
2173
|
-
}
|
|
2174
2205
|
const taskItem = { kind: "task", title, id: getId() };
|
|
2175
2206
|
setLastUserMessage(title);
|
|
2176
2207
|
setDoneStatus(null);
|
|
2177
2208
|
setLiveItems([taskItem]);
|
|
2178
|
-
void
|
|
2179
|
-
|
|
2180
|
-
|
|
2209
|
+
void (async () => {
|
|
2210
|
+
try {
|
|
2211
|
+
if (sm) {
|
|
2212
|
+
const session = await sm.create(taskCwd, currentProvider, currentModel);
|
|
2213
|
+
sessionPathRef.current = session.path;
|
|
2214
|
+
sessionStatsRef.current.sessionId = session.id;
|
|
2215
|
+
await props.subAgentManager?.resetParentSession(session.id);
|
|
2216
|
+
log("INFO", "tasks", "New session for task", { path: session.path });
|
|
2217
|
+
}
|
|
2218
|
+
await agentLoop.run(fullPrompt);
|
|
2181
2219
|
}
|
|
2182
|
-
|
|
2183
|
-
|
|
2220
|
+
catch (err) {
|
|
2221
|
+
if (agentLoop.isRunning)
|
|
2222
|
+
agentLoop.reset();
|
|
2223
|
+
setLiveItems((prev) => [...prev, toErrorItem(err, getId())]);
|
|
2224
|
+
}
|
|
2225
|
+
})();
|
|
2184
2226
|
}, [agentLoop, currentModel, currentProvider, props]);
|
|
2185
2227
|
// Keep the ref in sync so stale closures (task picker, onDone run-all) can
|
|
2186
2228
|
// start a task without being recreated each render.
|
|
@@ -2549,6 +2591,10 @@ export function App(props) {
|
|
|
2549
2591
|
if (sm) {
|
|
2550
2592
|
const s = await sm.create(props.cwd, currentProvider, currentModel);
|
|
2551
2593
|
newSessionPath = s.path;
|
|
2594
|
+
sessionStatsRef.current.sessionId = s.id;
|
|
2595
|
+
if (props.sessionStore)
|
|
2596
|
+
props.sessionStore.sessionId = s.id;
|
|
2597
|
+
await props.subAgentManager?.resetParentSession(s.id);
|
|
2552
2598
|
}
|
|
2553
2599
|
if (props.resetUI && props.sessionStore) {
|
|
2554
2600
|
// Clear the overlay so the new mount lands on the chat,
|