@kenkaiiii/ggcoder 5.22.2 → 5.22.4
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/assets/skills/evidence-led-ui/SKILL.md +1 -1
- package/dist/app-sidecar.js +86 -7
- package/dist/app-sidecar.js.map +1 -1
- package/dist/chat-agents/memory.d.ts.map +1 -1
- package/dist/chat-agents/memory.js +14 -5
- package/dist/chat-agents/memory.js.map +1 -1
- package/dist/chat-agents/memory.test.js +11 -1
- package/dist/chat-agents/memory.test.js.map +1 -1
- package/dist/chat-agents/shared.js +1 -1
- package/dist/chat-agents/shared.js.map +1 -1
- package/dist/core/agent-session-marker-anchors.test.d.ts +2 -0
- package/dist/core/agent-session-marker-anchors.test.d.ts.map +1 -0
- package/dist/core/agent-session-marker-anchors.test.js +150 -0
- package/dist/core/agent-session-marker-anchors.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +13 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +19 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +8 -3
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/grep.test.js +6 -0
- package/dist/tools/grep.test.js.map +1 -1
- package/dist/tools/source-path.d.ts.map +1 -1
- package/dist/tools/source-path.js +9 -0
- package/dist/tools/source-path.js.map +1 -1
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +13 -2
- package/dist/tools/web-search.js.map +1 -1
- package/dist/ui/components/ActivityIndicator.d.ts.map +1 -1
- package/dist/ui/components/ActivityIndicator.js +1 -0
- package/dist/ui/components/ActivityIndicator.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/utils/github.d.ts +20 -0
- package/dist/utils/github.d.ts.map +1 -0
- package/dist/utils/github.js +65 -0
- package/dist/utils/github.js.map +1 -0
- package/dist/utils/github.test.d.ts +2 -0
- package/dist/utils/github.test.d.ts.map +1 -0
- package/dist/utils/github.test.js +23 -0
- package/dist/utils/github.test.js.map +1 -0
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: evidence-led-ui
|
|
3
|
-
description: Use for web/mobile UI
|
|
3
|
+
description: Use for broad or design-sensitive web/mobile UI work: net-new pages/screens, redesigns, design-system work, visual polish, responsive or accessibility overhauls, and UI quality review/critique. Do NOT use for small UI edits that follow existing patterns (bug fixes, minor styling tweaks, wiring, copy changes, small component additions matching neighbors); just match the surrounding code for those. Also exclude database/API schemas, CLI output, standalone image/SVG generation, and description-only tasks.
|
|
4
4
|
license: See LICENSES.md
|
|
5
5
|
compatibility: Full review requires filesystem inspection and rendered screenshots; web research and browser/device tooling are optional and unavailable checks must be reported honestly.
|
|
6
6
|
---
|
package/dist/app-sidecar.js
CHANGED
|
@@ -21,6 +21,7 @@ import { parseArgs } from "node:util";
|
|
|
21
21
|
import { environmentSecrets, formatError, redactValue, } from "@kenkaiiii/gg-ai";
|
|
22
22
|
import { runJsonMode } from "./modes/json-mode.js";
|
|
23
23
|
import { runSubagentWorkerMode } from "./modes/subagent-worker-mode.js";
|
|
24
|
+
import { setStreamDiagnostic } from "@kenkaiiii/gg-agent";
|
|
24
25
|
import { AgentSession } from "./core/agent-session.js";
|
|
25
26
|
import { RunLifecycle } from "./core/run-lifecycle.js";
|
|
26
27
|
import { CHAT_AGENT_IDS, chatAgentSessionsDir, createChatAgent, parseChatAgentId, switchChatAgent, } from "./chat-agents/index.js";
|
|
@@ -47,6 +48,7 @@ import { SettingsManager } from "./core/settings-manager.js";
|
|
|
47
48
|
import { getModel, getDefaultThinkingLevel, getContextWindow, MODELS, } from "./core/model-registry.js";
|
|
48
49
|
import { resolveStartOrFallback } from "./core/resolve-start.js";
|
|
49
50
|
import { getGitBranch, getGitDirtyFileCount, isGitRepo } from "./utils/git.js";
|
|
51
|
+
import { getGitHubOpenCounts, getGitHubRepoSlug } from "./utils/github.js";
|
|
50
52
|
import { extractPlanSteps } from "./utils/plan-steps.js";
|
|
51
53
|
import { getNextThinkingLevel, getSupportedThinkingLevels, isThinkingLevelSupported, } from "./core/thinking-level.js";
|
|
52
54
|
import { PROMPT_COMMANDS } from "./core/prompt-commands.js";
|
|
@@ -518,6 +520,31 @@ async function main() {
|
|
|
518
520
|
// ~/.gg/debug.log (initLogger truncates on each start).
|
|
519
521
|
const sidecarLog = path.join(paths.agentDir, "gg-app-sidecar.log");
|
|
520
522
|
initLogger(sidecarLog);
|
|
523
|
+
// The desktop sidecar previously omitted the stream diagnostic hook used by
|
|
524
|
+
// the CLI, leaving device-specific provider stalls impossible to distinguish from
|
|
525
|
+
// event-loop starvation or a broken streaming network path. Keep routine
|
|
526
|
+
// phases lightweight; timeout phases include non-sensitive runtime context.
|
|
527
|
+
setStreamDiagnostic((phase, data) => {
|
|
528
|
+
const includeRuntime = phase === "idle_timeout_fired" ||
|
|
529
|
+
phase === "hard_timeout_fired" ||
|
|
530
|
+
phase === "stall_exhausted";
|
|
531
|
+
log("INFO", "stream", phase, {
|
|
532
|
+
...(data ?? {}),
|
|
533
|
+
...(includeRuntime
|
|
534
|
+
? {
|
|
535
|
+
platform: process.platform,
|
|
536
|
+
arch: process.arch,
|
|
537
|
+
osRelease: os.release(),
|
|
538
|
+
node: process.version,
|
|
539
|
+
logicalCpus: os.cpus().length,
|
|
540
|
+
totalMemoryMb: Math.round(os.totalmem() / 1024 / 1024),
|
|
541
|
+
freeMemoryMb: Math.round(os.freemem() / 1024 / 1024),
|
|
542
|
+
rssMb: Math.round(process.memoryUsage().rss / 1024 / 1024),
|
|
543
|
+
processUptimeSec: Math.round(process.uptime()),
|
|
544
|
+
}
|
|
545
|
+
: {}),
|
|
546
|
+
});
|
|
547
|
+
});
|
|
521
548
|
// Global last-resort guards, installed as early as the logger allows so they
|
|
522
549
|
// cover the WHOLE lifecycle — including startup/initialize, the phase the
|
|
523
550
|
// "sidecar did not start in time" bug lives in. The sidecar is a long-lived
|
|
@@ -576,11 +603,14 @@ async function main() {
|
|
|
576
603
|
});
|
|
577
604
|
const usageCache = new Map();
|
|
578
605
|
const usageRequests = new Map();
|
|
579
|
-
// 429 backoff:
|
|
580
|
-
//
|
|
581
|
-
//
|
|
606
|
+
// 429 backoff: quota endpoints are auxiliary UI data. Honor Retry-After when
|
|
607
|
+
// provided; otherwise retain the unavailable snapshot for 30 minutes. Clamp
|
|
608
|
+
// the provider value so a malformed header can neither hammer the endpoint
|
|
609
|
+
// nor suppress usage data forever.
|
|
582
610
|
const usageRateLimitedUntil = new Map();
|
|
583
|
-
const
|
|
611
|
+
const USAGE_RATE_LIMIT_FALLBACK_BACKOFF_MS = 30 * 60_000;
|
|
612
|
+
const USAGE_RATE_LIMIT_MIN_BACKOFF_MS = 60_000;
|
|
613
|
+
const USAGE_RATE_LIMIT_MAX_BACKOFF_MS = 24 * 60 * 60_000;
|
|
584
614
|
async function fetchUsageProvider(provider) {
|
|
585
615
|
const displayName = provider === "anthropic" ? "Anthropic" : provider === "openai" ? "Codex" : "Kimi";
|
|
586
616
|
// Kimi plan usage is tracked on the OAuth credential specifically — the
|
|
@@ -619,10 +649,16 @@ async function main() {
|
|
|
619
649
|
if (shouldCaptureUsagePollingError(error)) {
|
|
620
650
|
captureSidecarError(error, "app-sidecar.usage.fetch", { provider });
|
|
621
651
|
}
|
|
622
|
-
|
|
652
|
+
let backoffMs;
|
|
623
653
|
if (error instanceof SubscriptionUsageError && error.status === 429) {
|
|
624
|
-
|
|
654
|
+
backoffMs = Math.min(USAGE_RATE_LIMIT_MAX_BACKOFF_MS, Math.max(USAGE_RATE_LIMIT_MIN_BACKOFF_MS, error.retryAfterMs ?? USAGE_RATE_LIMIT_FALLBACK_BACKOFF_MS));
|
|
655
|
+
usageRateLimitedUntil.set(provider, Date.now() + backoffMs);
|
|
625
656
|
}
|
|
657
|
+
log("WARN", "app-sidecar", "subscription usage fetch failed", {
|
|
658
|
+
provider,
|
|
659
|
+
message,
|
|
660
|
+
...(backoffMs !== undefined && { backoffMs: String(backoffMs) }),
|
|
661
|
+
});
|
|
626
662
|
const connected = await auth.hasProviderAuth(authKey);
|
|
627
663
|
return {
|
|
628
664
|
provider,
|
|
@@ -1183,14 +1219,20 @@ async function createSession(deps, opts) {
|
|
|
1183
1219
|
// Workspace extras (context window, git status, background tasks). Git state
|
|
1184
1220
|
// is resolved once at startup and refreshed after every run; the context
|
|
1185
1221
|
// window follows the active model.
|
|
1186
|
-
const [initialGitBranch, initialGitIsRepo, initialDirtyFileCount] = await Promise.all([
|
|
1222
|
+
const [initialGitBranch, initialGitIsRepo, initialDirtyFileCount, initialGitHubSlug] = await Promise.all([
|
|
1187
1223
|
getGitBranch(cwd).catch(() => null),
|
|
1188
1224
|
isGitRepo(cwd).catch(() => false),
|
|
1189
1225
|
getGitDirtyFileCount(cwd).catch(() => 0),
|
|
1226
|
+
getGitHubRepoSlug(cwd).catch(() => null),
|
|
1190
1227
|
]);
|
|
1191
1228
|
let gitBranch = initialGitBranch;
|
|
1192
1229
|
let gitIsRepo = initialGitIsRepo;
|
|
1193
1230
|
let gitDirtyFileCount = initialDirtyFileCount;
|
|
1231
|
+
// Open issue/PR counts for the origin repo's GitHub slug, via the `gh` CLI's
|
|
1232
|
+
// auth. null = unknown (gh missing/unauthed, non-GitHub origin) → chips hidden.
|
|
1233
|
+
const gitHubSlug = initialGitHubSlug;
|
|
1234
|
+
let gitHubIssues = null;
|
|
1235
|
+
let gitHubPRs = null;
|
|
1194
1236
|
function currentContextWindow() {
|
|
1195
1237
|
const st = session.getState();
|
|
1196
1238
|
return getContextWindow(st.model, { provider: st.provider, accountId: st.accountId });
|
|
@@ -1203,9 +1245,26 @@ async function createSession(deps, opts) {
|
|
|
1203
1245
|
gitBranch,
|
|
1204
1246
|
isGitRepo: gitIsRepo,
|
|
1205
1247
|
gitDirtyFileCount,
|
|
1248
|
+
gitHubIssues,
|
|
1249
|
+
gitHubPRs,
|
|
1250
|
+
gitHubRepoUrl: gitHubSlug ? `https://github.com/${gitHubSlug}` : null,
|
|
1206
1251
|
tasks: session.listBackgroundProcesses(),
|
|
1207
1252
|
};
|
|
1208
1253
|
}
|
|
1254
|
+
// Refresh the GitHub counts and broadcast only on change. Transient failures
|
|
1255
|
+
// keep the last-known numbers so the chips don't flicker off on a timeout.
|
|
1256
|
+
async function refreshGitHubCounts() {
|
|
1257
|
+
if (!gitHubSlug)
|
|
1258
|
+
return;
|
|
1259
|
+
const counts = await getGitHubOpenCounts(gitHubSlug);
|
|
1260
|
+
if (!counts)
|
|
1261
|
+
return;
|
|
1262
|
+
if (counts.issues !== gitHubIssues || counts.prs !== gitHubPRs) {
|
|
1263
|
+
gitHubIssues = counts.issues;
|
|
1264
|
+
gitHubPRs = counts.prs;
|
|
1265
|
+
broadcast("extras", footerExtras());
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1209
1268
|
// tool_call_end carries no tool name (only the id), so remember each call's
|
|
1210
1269
|
// name from tool_call_start to log a useful line on completion. Mirrors the
|
|
1211
1270
|
// CLI's logging so the app sidecar's ~/.gg/gg-app-sidecar.log records tool
|
|
@@ -1641,6 +1700,9 @@ async function createSession(deps, opts) {
|
|
|
1641
1700
|
isGitRepo(cwd).catch(() => gitIsRepo),
|
|
1642
1701
|
getGitDirtyFileCount(cwd).catch(() => gitDirtyFileCount),
|
|
1643
1702
|
]);
|
|
1703
|
+
// A run may have opened/closed issues or PRs — refresh fire-and-forget so
|
|
1704
|
+
// teardown isn't delayed by the network. Broadcasts itself on change.
|
|
1705
|
+
void refreshGitHubCounts();
|
|
1644
1706
|
// Serialize behind any marker/tool-triggered refresh so the terminal
|
|
1645
1707
|
// progress snapshot uses the live plan file. Once every canonical step
|
|
1646
1708
|
// is complete, remove the approved plan from future system prompts and
|
|
@@ -2093,6 +2155,20 @@ async function createSession(deps, opts) {
|
|
|
2093
2155
|
gitPoll.unref?.();
|
|
2094
2156
|
};
|
|
2095
2157
|
scheduleGitPoll(5000);
|
|
2158
|
+
// GitHub issue/PR counts change outside the app (web UI, teammates), so poll
|
|
2159
|
+
// on a slow cadence. Network-bound, so keep it well under the search API's
|
|
2160
|
+
// rate budget (2 calls per tick). No-op when the origin isn't a GitHub repo.
|
|
2161
|
+
let gitHubPoll;
|
|
2162
|
+
let gitHubPollStopped = false;
|
|
2163
|
+
const scheduleGitHubPoll = (delay) => {
|
|
2164
|
+
if (gitHubPollStopped)
|
|
2165
|
+
return;
|
|
2166
|
+
gitHubPoll = setTimeout(() => {
|
|
2167
|
+
void refreshGitHubCounts().finally(() => scheduleGitHubPoll(60_000));
|
|
2168
|
+
}, delay);
|
|
2169
|
+
gitHubPoll.unref?.();
|
|
2170
|
+
};
|
|
2171
|
+
scheduleGitHubPoll(2000);
|
|
2096
2172
|
function readBody(req, res) {
|
|
2097
2173
|
return readCappedBody(req, res);
|
|
2098
2174
|
}
|
|
@@ -3786,6 +3862,9 @@ async function createSession(deps, opts) {
|
|
|
3786
3862
|
gitPollStopped = true;
|
|
3787
3863
|
if (gitPoll)
|
|
3788
3864
|
clearTimeout(gitPoll);
|
|
3865
|
+
gitHubPollStopped = true;
|
|
3866
|
+
if (gitHubPoll)
|
|
3867
|
+
clearTimeout(gitHubPoll);
|
|
3789
3868
|
// Stop the Telegram serve loop + dispose its per-chat sessions.
|
|
3790
3869
|
if (serveController)
|
|
3791
3870
|
await serveController.stop().catch(() => { });
|