@kenkaiiii/ggcoder 5.14.0 → 5.15.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.
@@ -22,7 +22,7 @@ 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";
25
+ import { CHAT_AGENT_IDS, chatAgentSessionsDir, createChatAgent, parseChatAgentId, sessionsDirForChatAgent, switchChatAgent, } from "./chat-agents/index.js";
26
26
  import { buildMemoryTools, MemoryStore } from "./chat-agents/memory.js";
27
27
  import { buildKenSystemPrompt, buildKenAutopilotSystemPrompt } from "./core/ken-prompt.js";
28
28
  import { buildKenDigest, buildKenAutopilotContext, buildKenAutopilotPlanContext, } from "./core/ken-context.js";
@@ -889,7 +889,7 @@ async function createSession(deps, opts) {
889
889
  const { auth, progress, memoryStore } = deps;
890
890
  const paths = deps.paths;
891
891
  const mode = opts.mode;
892
- const chatAgent = opts.chatAgent;
892
+ let chatAgent = opts.chatAgent;
893
893
  const cwd = opts.cwd;
894
894
  // Base host for parsing request-URL query params (value is irrelevant to
895
895
  // parsing); the daemon owns the real listen host.
@@ -1009,6 +1009,15 @@ async function createSession(deps, opts) {
1009
1009
  sessionsDir: paths.sessionsDir,
1010
1010
  additionalTools: buildMemoryTools(memoryStore),
1011
1011
  getSystemPromptTail: () => memoryStore.renderForPrompt(),
1012
+ onAgentChange: async (nextAgent) => {
1013
+ chatAgent = nextAgent;
1014
+ broadcast("chat_agent_change", { chatAgent: nextAgent });
1015
+ await session.persistAppMarker("agent_handoff", { chatAgent: nextAgent }).catch((error) => {
1016
+ log("WARN", "app-sidecar", "agent handoff marker persist failed", {
1017
+ message: error instanceof Error ? error.message : String(error),
1018
+ });
1019
+ });
1020
+ },
1012
1021
  });
1013
1022
  }
1014
1023
  else {
@@ -1036,6 +1045,15 @@ async function createSession(deps, opts) {
1036
1045
  });
1037
1046
  }
1038
1047
  await session.initialize();
1048
+ if (mode === "chat") {
1049
+ const restoredAgent = [...session.getAppMarkers()]
1050
+ .reverse()
1051
+ .find((marker) => marker.kind === "agent_handoff")?.data.chatAgent;
1052
+ if (typeof restoredAgent === "string") {
1053
+ chatAgent = parseChatAgentId(restoredAgent);
1054
+ await switchChatAgent(session, chatAgent, false);
1055
+ }
1056
+ }
1039
1057
  log("INFO", "app-sidecar", "session ready", { provider, model, mode, chatAgent, cwd });
1040
1058
  // Footer extras (context window, git branch, background tasks). The git
1041
1059
  // branch is resolved once at startup and refreshed lazily; the context
@@ -1952,6 +1970,28 @@ async function createSession(deps, opts) {
1952
1970
  return;
1953
1971
  }
1954
1972
  const requestedAgent = new URL(url, `http://${host}`).searchParams.get("chatAgent");
1973
+ if (requestedAgent === "all") {
1974
+ void Promise.all(CHAT_AGENT_IDS.map(async (agentId) => {
1975
+ const agentSessions = await listRecentSessions(target, 5, chatAgentSessionsDir(paths.sessionsDir, agentId));
1976
+ return agentSessions.map((item) => ({ ...item, chatAgent: agentId }));
1977
+ }))
1978
+ .then(async (groups) => {
1979
+ const dated = await Promise.all(groups.flat().map(async (item) => ({
1980
+ item,
1981
+ mtime: await fs
1982
+ .stat(item.path)
1983
+ .then((stat) => stat.mtimeMs)
1984
+ .catch(() => 0),
1985
+ })));
1986
+ const recent = dated
1987
+ .sort((left, right) => right.mtime - left.mtime)
1988
+ .slice(0, 5)
1989
+ .map(({ item }) => item);
1990
+ json(res, 200, { sessions: recent });
1991
+ })
1992
+ .catch(() => json(res, 200, { sessions: [] }));
1993
+ return;
1994
+ }
1955
1995
  const sessionsDir = mode === "chat" || requestedAgent
1956
1996
  ? sessionsDirForChatAgent(paths.sessionsDir, requestedAgent ?? chatAgent)
1957
1997
  : paths.sessionsDir;
@@ -2824,7 +2864,10 @@ async function createSession(deps, opts) {
2824
2864
  }
2825
2865
  void session
2826
2866
  .newSession()
2827
- .then(() => {
2867
+ .then(async () => {
2868
+ if (mode === "chat") {
2869
+ await session.persistAppMarker("agent_handoff", { chatAgent });
2870
+ }
2828
2871
  injectedAutopilotPrompts = [];
2829
2872
  clearPendingPlan();
2830
2873
  broadcast("session_reset", {});
@@ -3324,7 +3367,9 @@ async function createSession(deps, opts) {
3324
3367
  return {
3325
3368
  id: opts.id,
3326
3369
  mode,
3327
- chatAgent,
3370
+ get chatAgent() {
3371
+ return chatAgent;
3372
+ },
3328
3373
  cwd,
3329
3374
  sessionPath: opts.sessionPath,
3330
3375
  session,