@kenkaiiii/ggcoder 5.13.3 → 5.14.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 +112 -47
- package/dist/app-sidecar.js.map +1 -1
- package/dist/chat-agents/general.d.ts +7 -0
- package/dist/chat-agents/general.d.ts.map +1 -0
- package/dist/chat-agents/general.js +16 -0
- package/dist/chat-agents/general.js.map +1 -0
- package/dist/chat-agents/general.test.d.ts +2 -0
- package/dist/chat-agents/general.test.d.ts.map +1 -0
- package/dist/chat-agents/general.test.js +47 -0
- package/dist/chat-agents/general.test.js.map +1 -0
- package/dist/chat-agents/index.d.ts +9 -0
- package/dist/chat-agents/index.d.ts.map +1 -0
- package/dist/chat-agents/index.js +99 -0
- package/dist/chat-agents/index.js.map +1 -0
- package/dist/chat-agents/memory.d.ts +53 -0
- package/dist/chat-agents/memory.d.ts.map +1 -0
- package/dist/chat-agents/memory.js +362 -0
- package/dist/chat-agents/memory.js.map +1 -0
- package/dist/chat-agents/memory.test.d.ts +2 -0
- package/dist/chat-agents/memory.test.d.ts.map +1 -0
- package/dist/chat-agents/memory.test.js +155 -0
- package/dist/chat-agents/memory.test.js.map +1 -0
- package/dist/chat-agents/research.d.ts +7 -0
- package/dist/chat-agents/research.d.ts.map +1 -0
- package/dist/chat-agents/research.js +18 -0
- package/dist/chat-agents/research.js.map +1 -0
- package/dist/chat-agents/shared.d.ts +9 -0
- package/dist/chat-agents/shared.d.ts.map +1 -0
- package/dist/chat-agents/shared.js +44 -0
- package/dist/chat-agents/shared.js.map +1 -0
- package/dist/chat-agents/specialists.test.d.ts +2 -0
- package/dist/chat-agents/specialists.test.d.ts.map +1 -0
- package/dist/chat-agents/specialists.test.js +63 -0
- package/dist/chat-agents/specialists.test.js.map +1 -0
- package/dist/chat-agents/therapist.d.ts +7 -0
- package/dist/chat-agents/therapist.d.ts.map +1 -0
- package/dist/chat-agents/therapist.js +20 -0
- package/dist/chat-agents/therapist.js.map +1 -0
- package/dist/chat-agents/types.d.ts +4 -0
- package/dist/chat-agents/types.d.ts.map +1 -0
- package/dist/chat-agents/types.js +7 -0
- package/dist/chat-agents/types.js.map +1 -0
- package/dist/core/agent-session-memory-tail.test.d.ts +2 -0
- package/dist/core/agent-session-memory-tail.test.d.ts.map +1 -0
- package/dist/core/agent-session-memory-tail.test.js +122 -0
- package/dist/core/agent-session-memory-tail.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +23 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +112 -65
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/agents.d.ts +1 -1
- package/dist/core/agents.d.ts.map +1 -1
- package/dist/core/agents.js +4 -2
- package/dist/core/agents.js.map +1 -1
- package/dist/core/progress/rebuild.d.ts +3 -3
- package/dist/core/progress/rebuild.d.ts.map +1 -1
- package/dist/core/progress/rebuild.js +33 -27
- package/dist/core/progress/rebuild.js.map +1 -1
- package/dist/core/progress/rebuild.test.js +15 -0
- package/dist/core/progress/rebuild.test.js.map +1 -1
- package/dist/core/project-discovery.d.ts +1 -1
- package/dist/core/project-discovery.d.ts.map +1 -1
- package/dist/core/project-discovery.js +1 -2
- package/dist/core/project-discovery.js.map +1 -1
- package/dist/core/project-discovery.test.js +14 -1
- package/dist/core/project-discovery.test.js.map +1 -1
- package/dist/core/subagent-manager.d.ts.map +1 -1
- package/dist/core/subagent-manager.js +4 -0
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/subagent-manager.test.js +5 -1
- package/dist/core/subagent-manager.test.js.map +1 -1
- package/dist/tools/generate-image.d.ts.map +1 -1
- package/dist/tools/generate-image.js +10 -3
- package/dist/tools/generate-image.js.map +1 -1
- package/dist/tools/generate-image.test.js +17 -0
- package/dist/tools/generate-image.test.js.map +1 -1
- package/dist/tools/web-fetch.d.ts +1 -0
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +112 -35
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-fetch.test.js +146 -1
- package/dist/tools/web-fetch.test.js.map +1 -1
- package/dist/tools/web-search.d.ts +10 -0
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +236 -28
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools/web-search.test.js +77 -6
- package/dist/tools/web-search.test.js.map +1 -1
- package/package.json +4 -4
package/dist/app-sidecar.js
CHANGED
|
@@ -22,6 +22,8 @@ import { formatError } from "@kenkaiiii/gg-ai";
|
|
|
22
22
|
import { runJsonMode } from "./modes/json-mode.js";
|
|
23
23
|
import { runSubagentWorkerMode } from "./modes/subagent-worker-mode.js";
|
|
24
24
|
import { AgentSession } from "./core/agent-session.js";
|
|
25
|
+
import { CHAT_AGENT_IDS, chatAgentSessionsDir, createChatAgent, parseChatAgentId, sessionsDirForChatAgent, } from "./chat-agents/index.js";
|
|
26
|
+
import { buildMemoryTools, MemoryStore } from "./chat-agents/memory.js";
|
|
25
27
|
import { buildKenSystemPrompt, buildKenAutopilotSystemPrompt } from "./core/ken-prompt.js";
|
|
26
28
|
import { buildKenDigest, buildKenAutopilotContext, buildKenAutopilotPlanContext, } from "./core/ken-context.js";
|
|
27
29
|
import { parseAutopilotVerdict } from "./core/autopilot-verdict.js";
|
|
@@ -508,6 +510,13 @@ async function main() {
|
|
|
508
510
|
// request to its window's session via the `x-gg-session` header (and the
|
|
509
511
|
// `?session=` query for the SSE /events stream).
|
|
510
512
|
const sessions = new Map();
|
|
513
|
+
const memoryStore = new MemoryStore({
|
|
514
|
+
onChange: ({ memories }) => {
|
|
515
|
+
for (const ctx of sessions.values()) {
|
|
516
|
+
ctx.broadcast("memory_change", { count: memories.length });
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
});
|
|
511
520
|
// XP/rank progress — loaded once per daemon; awards fan out to every window.
|
|
512
521
|
// Each frame is tagged `origin: true` only for the session that earned the
|
|
513
522
|
// XP, so that window alone plays sounds/chips while the rest just re-render.
|
|
@@ -606,7 +615,7 @@ async function main() {
|
|
|
606
615
|
return;
|
|
607
616
|
}
|
|
608
617
|
// ── Daemon-level routes (session lifecycle) ──────────────────────────
|
|
609
|
-
// Create a session for a window: { cwd, sessionPath? } → { sessionId }.
|
|
618
|
+
// Create a session for a window: { mode?, cwd, sessionPath? } → { sessionId }.
|
|
610
619
|
if (method === "POST" && url === "/session") {
|
|
611
620
|
void daemonReadBody(req).then(async (raw) => {
|
|
612
621
|
let body = {};
|
|
@@ -616,15 +625,22 @@ async function main() {
|
|
|
616
625
|
catch {
|
|
617
626
|
/* empty/invalid body → defaults below */
|
|
618
627
|
}
|
|
628
|
+
const mode = body.mode === "chat" ? "chat" : "code";
|
|
629
|
+
const chatAgent = parseChatAgentId(body.chatAgent);
|
|
619
630
|
const sessionCwd = typeof body.cwd === "string" && body.cwd
|
|
620
631
|
? body.cwd
|
|
621
632
|
: (process.env.GG_APP_CWD ?? process.cwd());
|
|
622
633
|
const sessionPath = typeof body.sessionPath === "string" && body.sessionPath ? body.sessionPath : undefined;
|
|
623
634
|
const id = randomUUID();
|
|
624
635
|
try {
|
|
625
|
-
const ctx = await createSession({ auth, paths, progress }, { id, cwd: sessionCwd, sessionPath });
|
|
636
|
+
const ctx = await createSession({ auth, paths, progress, memoryStore }, { id, mode, chatAgent, cwd: sessionCwd, sessionPath });
|
|
626
637
|
sessions.set(id, ctx);
|
|
627
|
-
log("INFO", "app-sidecar", "session created", {
|
|
638
|
+
log("INFO", "app-sidecar", "session created", {
|
|
639
|
+
id,
|
|
640
|
+
mode,
|
|
641
|
+
chatAgent,
|
|
642
|
+
cwd: sessionCwd,
|
|
643
|
+
});
|
|
628
644
|
daemonJson(res, 200, { sessionId: id });
|
|
629
645
|
}
|
|
630
646
|
catch (err) {
|
|
@@ -775,8 +791,14 @@ function buildKenContext(buildSession, cwd, gitBranch, question, workflowCommand
|
|
|
775
791
|
});
|
|
776
792
|
}
|
|
777
793
|
async function createProgressManager(agentDir, broadcastAll) {
|
|
778
|
-
// Boot: recovery chain main → backup →
|
|
779
|
-
|
|
794
|
+
// Boot: recovery chain main → backup → coding + chat session rebuild → empty.
|
|
795
|
+
const coderSessionsDir = path.join(agentDir, "sessions");
|
|
796
|
+
let file = await loadProgress({
|
|
797
|
+
rebuild: () => rebuildFromSessions([
|
|
798
|
+
coderSessionsDir,
|
|
799
|
+
...CHAT_AGENT_IDS.map((agentId) => chatAgentSessionsDir(coderSessionsDir, agentId)),
|
|
800
|
+
]),
|
|
801
|
+
});
|
|
780
802
|
// Don't re-celebrate an old levelUp event on boot.
|
|
781
803
|
let lastSeenNonce = file.lastEvent?.nonce ?? null;
|
|
782
804
|
log("INFO", "app-sidecar", "progress loaded", {
|
|
@@ -864,8 +886,10 @@ async function createProgressManager(agentDir, broadcastAll) {
|
|
|
864
886
|
* logger, PATH, shared auth file, and radio live at the daemon level.
|
|
865
887
|
*/
|
|
866
888
|
async function createSession(deps, opts) {
|
|
867
|
-
const { auth, progress } = deps;
|
|
889
|
+
const { auth, progress, memoryStore } = deps;
|
|
868
890
|
const paths = deps.paths;
|
|
891
|
+
const mode = opts.mode;
|
|
892
|
+
const chatAgent = opts.chatAgent;
|
|
869
893
|
const cwd = opts.cwd;
|
|
870
894
|
// Base host for parsing request-URL query params (value is irrelevant to
|
|
871
895
|
// parsing); the daemon owns the real listen host.
|
|
@@ -968,51 +992,51 @@ async function createSession(deps, opts) {
|
|
|
968
992
|
// empty/unset starts a fresh session.
|
|
969
993
|
const resumeSessionPath = opts.sessionPath;
|
|
970
994
|
let abort = new AbortController();
|
|
971
|
-
const
|
|
995
|
+
const baseSessionOptions = {
|
|
972
996
|
provider,
|
|
973
997
|
model,
|
|
974
998
|
cwd,
|
|
975
999
|
thinkingLevel,
|
|
976
1000
|
sessionId: resumeSessionPath,
|
|
977
1001
|
signal: abort.signal,
|
|
978
|
-
//
|
|
979
|
-
// can't fire until initialize() resolves. Connect MCP in the background so a
|
|
980
|
-
// slow or hanging stdio server (e.g. a first-run `npx -y @playwright/mcp`
|
|
981
|
-
// download) can't delay the sidecar past the webview's startup timeout
|
|
982
|
-
// ("sidecar did not start in time"). Tools attach when the servers come up.
|
|
1002
|
+
// Keep MCP startup off the readiness path in both modes.
|
|
983
1003
|
backgroundMcpConnect: true,
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1004
|
+
};
|
|
1005
|
+
let session;
|
|
1006
|
+
if (mode === "chat") {
|
|
1007
|
+
session = createChatAgent(chatAgent, {
|
|
1008
|
+
...baseSessionOptions,
|
|
1009
|
+
sessionsDir: paths.sessionsDir,
|
|
1010
|
+
additionalTools: buildMemoryTools(memoryStore),
|
|
1011
|
+
getSystemPromptTail: () => memoryStore.renderForPrompt(),
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
else {
|
|
1015
|
+
session = new AgentSession({
|
|
1016
|
+
...baseSessionOptions,
|
|
1017
|
+
// Plan mode belongs only to the coding agent.
|
|
1018
|
+
onEnterPlan: async (reason) => {
|
|
1019
|
+
await session.setPlanMode(true);
|
|
1020
|
+
broadcast("plan_enter", { reason: reason ?? "" });
|
|
1021
|
+
void session.persistAppMarker("plan", { reason: reason ?? "" }).catch(() => { });
|
|
1022
|
+
},
|
|
1023
|
+
onExitPlan: async (planPath) => {
|
|
1024
|
+
await session.setPlanMode(false);
|
|
1025
|
+
let content;
|
|
1026
|
+
try {
|
|
1027
|
+
content = await fs.readFile(planPath, "utf-8");
|
|
1028
|
+
}
|
|
1029
|
+
catch {
|
|
1030
|
+
content = "";
|
|
1031
|
+
}
|
|
1032
|
+
setPendingPlan(planPath, content);
|
|
1033
|
+
broadcast("plan_exit", { planPath, content });
|
|
1034
|
+
return "Plan submitted for user review. Wait for the user to approve, reject, or dismiss it before implementing.";
|
|
1035
|
+
},
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1014
1038
|
await session.initialize();
|
|
1015
|
-
log("INFO", "app-sidecar", "session ready", { provider, model, cwd });
|
|
1039
|
+
log("INFO", "app-sidecar", "session ready", { provider, model, mode, chatAgent, cwd });
|
|
1016
1040
|
// Footer extras (context window, git branch, background tasks). The git
|
|
1017
1041
|
// branch is resolved once at startup and refreshed lazily; the context
|
|
1018
1042
|
// window follows the active model.
|
|
@@ -1081,7 +1105,7 @@ async function createSession(deps, opts) {
|
|
|
1081
1105
|
// gg-app.json on boot; flipped via POST /autopilot. When on, POST /prompt runs
|
|
1082
1106
|
// runAutopilotCycle after the user's turn settles — Ken auto-reviews the work
|
|
1083
1107
|
// and drives the review→prompt→review loop.
|
|
1084
|
-
let autopilot = await loadAutopilot(cwd);
|
|
1108
|
+
let autopilot = mode === "code" && (await loadAutopilot(cwd));
|
|
1085
1109
|
// True while an autopilot review is in flight (used to defer kenAuto model
|
|
1086
1110
|
// switches, like kenRunning does for chat Ken, and to drive the spinner).
|
|
1087
1111
|
let autopilotReviewing = false;
|
|
@@ -1758,6 +1782,8 @@ async function createSession(deps, opts) {
|
|
|
1758
1782
|
const st = session.getState();
|
|
1759
1783
|
json(res, 200, {
|
|
1760
1784
|
...st,
|
|
1785
|
+
mode,
|
|
1786
|
+
chatAgent,
|
|
1761
1787
|
running,
|
|
1762
1788
|
ready: true,
|
|
1763
1789
|
thinkingLevel: session.getThinkingLevel() ?? null,
|
|
@@ -1773,6 +1799,26 @@ async function createSession(deps, opts) {
|
|
|
1773
1799
|
json(res, 200, progress.snapshot());
|
|
1774
1800
|
return;
|
|
1775
1801
|
}
|
|
1802
|
+
if (method === "GET" && url === "/memories") {
|
|
1803
|
+
void memoryStore
|
|
1804
|
+
.snapshot()
|
|
1805
|
+
.then((snapshot) => json(res, 200, snapshot))
|
|
1806
|
+
.catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
|
|
1807
|
+
return;
|
|
1808
|
+
}
|
|
1809
|
+
if (method === "DELETE" && url.startsWith("/memories/")) {
|
|
1810
|
+
const id = decodeURIComponent(url.slice("/memories/".length));
|
|
1811
|
+
if (!id) {
|
|
1812
|
+
json(res, 400, { error: "memory id is required" });
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
1815
|
+
void memoryStore
|
|
1816
|
+
.forget(id)
|
|
1817
|
+
.then(() => memoryStore.snapshot())
|
|
1818
|
+
.then((snapshot) => json(res, 200, snapshot))
|
|
1819
|
+
.catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1776
1822
|
if (method === "GET" && (url === "/events" || url.startsWith("/events?"))) {
|
|
1777
1823
|
res.writeHead(200, {
|
|
1778
1824
|
"content-type": "text/event-stream",
|
|
@@ -1788,6 +1834,8 @@ async function createSession(deps, opts) {
|
|
|
1788
1834
|
type: "ready",
|
|
1789
1835
|
data: {
|
|
1790
1836
|
...st,
|
|
1837
|
+
mode,
|
|
1838
|
+
chatAgent,
|
|
1791
1839
|
running,
|
|
1792
1840
|
thinkingLevel: session.getThinkingLevel() ?? null,
|
|
1793
1841
|
supportedThinkingLevels: getSupportedThinkingLevels(st.provider, st.model),
|
|
@@ -1903,7 +1951,11 @@ async function createSession(deps, opts) {
|
|
|
1903
1951
|
json(res, 400, { error: "missing cwd query param" });
|
|
1904
1952
|
return;
|
|
1905
1953
|
}
|
|
1906
|
-
|
|
1954
|
+
const requestedAgent = new URL(url, `http://${host}`).searchParams.get("chatAgent");
|
|
1955
|
+
const sessionsDir = mode === "chat" || requestedAgent
|
|
1956
|
+
? sessionsDirForChatAgent(paths.sessionsDir, requestedAgent ?? chatAgent)
|
|
1957
|
+
: paths.sessionsDir;
|
|
1958
|
+
void listRecentSessions(target, 5, sessionsDir)
|
|
1907
1959
|
.then((sessions) => json(res, 200, { sessions }))
|
|
1908
1960
|
.catch(() => json(res, 200, { sessions: [] }));
|
|
1909
1961
|
return;
|
|
@@ -2210,9 +2262,12 @@ async function createSession(deps, opts) {
|
|
|
2210
2262
|
return;
|
|
2211
2263
|
}
|
|
2212
2264
|
if (method === "GET" && url === "/commands") {
|
|
2265
|
+
if (mode === "chat") {
|
|
2266
|
+
json(res, 200, { commands: [] });
|
|
2267
|
+
return;
|
|
2268
|
+
}
|
|
2213
2269
|
// Workflow commands with agent functionality: built-in prompt templates +
|
|
2214
|
-
// the user's own `.gg/commands/*.md`.
|
|
2215
|
-
// handled webview-side and intentionally excluded.
|
|
2270
|
+
// the user's own `.gg/commands/*.md`.
|
|
2216
2271
|
void (async () => {
|
|
2217
2272
|
const builtins = PROMPT_COMMANDS.map((c) => ({
|
|
2218
2273
|
name: c.name,
|
|
@@ -2350,6 +2405,10 @@ async function createSession(deps, opts) {
|
|
|
2350
2405
|
// webview keeps the bubbles separate. The context digest is assembled fresh
|
|
2351
2406
|
// from the BUILD session's transcript each turn (one-way mirror).
|
|
2352
2407
|
if (method === "POST" && url === "/ken/prompt") {
|
|
2408
|
+
if (mode === "chat") {
|
|
2409
|
+
json(res, 404, { error: "Ken is not available in GG Chat." });
|
|
2410
|
+
return;
|
|
2411
|
+
}
|
|
2353
2412
|
void readBody(req).then(async (raw) => {
|
|
2354
2413
|
let text;
|
|
2355
2414
|
try {
|
|
@@ -2405,6 +2464,10 @@ async function createSession(deps, opts) {
|
|
|
2405
2464
|
return;
|
|
2406
2465
|
}
|
|
2407
2466
|
if (method === "POST" && url === "/autopilot") {
|
|
2467
|
+
if (mode === "chat") {
|
|
2468
|
+
json(res, 404, { error: "Autopilot is not available in GG Chat." });
|
|
2469
|
+
return;
|
|
2470
|
+
}
|
|
2408
2471
|
void readBody(req).then(async (raw) => {
|
|
2409
2472
|
let enabled;
|
|
2410
2473
|
try {
|
|
@@ -3260,6 +3323,8 @@ async function createSession(deps, opts) {
|
|
|
3260
3323
|
}
|
|
3261
3324
|
return {
|
|
3262
3325
|
id: opts.id,
|
|
3326
|
+
mode,
|
|
3327
|
+
chatAgent,
|
|
3263
3328
|
cwd,
|
|
3264
3329
|
sessionPath: opts.sessionPath,
|
|
3265
3330
|
session,
|