@kenkaiiii/ggcoder 5.15.1 → 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/assets/end-notification.mp3 +0 -0
- package/assets/skills/evidence-led-ui/LICENSES.md +68 -0
- package/assets/skills/evidence-led-ui/SKILL.md +139 -0
- package/{LICENSE → assets/skills/evidence-led-ui/corpus/awesome-design-md/LICENSE} +1 -1
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/airbnb/DESIGN.md +545 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/airtable/DESIGN.md +554 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/apple/DESIGN.md +562 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/binance/DESIGN.md +634 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/bmw/DESIGN.md +544 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/bmw-m/DESIGN.md +503 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/bugatti/DESIGN.md +454 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/cal/DESIGN.md +542 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/claude/DESIGN.md +589 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/clay/DESIGN.md +541 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/clickhouse/DESIGN.md +544 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/cohere/DESIGN.md +451 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/coinbase/DESIGN.md +570 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/composio/DESIGN.md +506 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/cursor/DESIGN.md +537 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/dell-1996/DESIGN.md +632 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/elevenlabs/DESIGN.md +504 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/expo/DESIGN.md +526 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/ferrari/DESIGN.md +531 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/figma/DESIGN.md +578 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/framer/DESIGN.md +544 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/hashicorp/DESIGN.md +575 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/hp/DESIGN.md +670 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/ibm/DESIGN.md +550 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/intercom/DESIGN.md +546 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/kraken/DESIGN.md +125 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/lamborghini/DESIGN.md +288 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/linear.app/DESIGN.md +548 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/lovable/DESIGN.md +298 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/mastercard/DESIGN.md +365 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/meta/DESIGN.md +683 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/minimax/DESIGN.md +746 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/mintlify/DESIGN.md +852 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/miro/DESIGN.md +825 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/mistral.ai/DESIGN.md +773 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/mongodb/DESIGN.md +767 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/nike/DESIGN.md +575 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/nintendo-2001/DESIGN.md +649 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/notion/DESIGN.md +821 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/nvidia/DESIGN.md +640 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/ollama/DESIGN.md +539 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/opencode.ai/DESIGN.md +521 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/pinterest/DESIGN.md +597 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/playstation/DESIGN.md +661 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/posthog/DESIGN.md +690 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/raycast/DESIGN.md +669 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/renault/DESIGN.md +589 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/replicate/DESIGN.md +616 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/resend/DESIGN.md +585 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/revolut/DESIGN.md +636 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/runwayml/DESIGN.md +244 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/sanity/DESIGN.md +357 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/sentry/DESIGN.md +551 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/shopify/DESIGN.md +516 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/slack/DESIGN.md +482 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/spacex/DESIGN.md +363 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/spotify/DESIGN.md +246 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/starbucks/DESIGN.md +580 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/stripe/DESIGN.md +487 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/supabase/DESIGN.md +462 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/superhuman/DESIGN.md +448 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/tesla/DESIGN.md +286 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/theverge/DESIGN.md +339 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/together.ai/DESIGN.md +633 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/uber/DESIGN.md +636 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/vercel/DESIGN.md +736 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/vodafone/DESIGN.md +538 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/voltagent/DESIGN.md +521 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/warp/DESIGN.md +526 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/webflow/DESIGN.md +588 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/wired/DESIGN.md +497 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/wise/DESIGN.md +544 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/x.ai/DESIGN.md +465 -0
- package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/zapier/DESIGN.md +537 -0
- package/assets/skills/evidence-led-ui/data/corpus-manifest.json +768 -0
- package/assets/skills/evidence-led-ui/data/observations.json +47053 -0
- package/assets/skills/evidence-led-ui/references/anti-defaults.md +203 -0
- package/assets/skills/evidence-led-ui/references/archetypes.md +97 -0
- package/assets/skills/evidence-led-ui/references/craft-rulings.md +167 -0
- package/assets/skills/evidence-led-ui/references/methodology.md +72 -0
- package/assets/skills/evidence-led-ui/references/observed-patterns.md +68 -0
- package/assets/skills/evidence-led-ui/references/production-contract.md +120 -0
- package/assets/skills/evidence-led-ui/references/provenance.md +117 -0
- package/assets/skills/evidence-led-ui/references/quality-rubric.md +126 -0
- package/dist/app-sidecar.js +161 -48
- package/dist/app-sidecar.js.map +1 -1
- package/dist/chat-agents/general.test.js +3 -0
- package/dist/chat-agents/general.test.js.map +1 -1
- package/dist/chat-agents/jiwa.d.ts +53 -0
- package/dist/chat-agents/jiwa.d.ts.map +1 -0
- package/dist/chat-agents/jiwa.js +352 -0
- package/dist/chat-agents/jiwa.js.map +1 -0
- package/dist/chat-agents/jiwa.test.d.ts +2 -0
- package/dist/chat-agents/jiwa.test.d.ts.map +1 -0
- package/dist/chat-agents/jiwa.test.js +66 -0
- package/dist/chat-agents/jiwa.test.js.map +1 -0
- package/dist/chat-agents/shared.d.ts.map +1 -1
- package/dist/chat-agents/shared.js +5 -1
- package/dist/chat-agents/shared.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 +13 -7
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +143 -38
- 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/ken-prompt.d.ts +3 -3
- package/dist/core/ken-prompt.d.ts.map +1 -1
- package/dist/core/ken-prompt.js +10 -10
- package/dist/core/ken-prompt.js.map +1 -1
- package/dist/core/ken-prompt.test.js +17 -0
- package/dist/core/ken-prompt.test.js.map +1 -1
- package/dist/core/loop-breaker.d.ts +23 -16
- package/dist/core/loop-breaker.d.ts.map +1 -1
- package/dist/core/loop-breaker.js +52 -11
- package/dist/core/loop-breaker.js.map +1 -1
- package/dist/core/loop-breaker.test.js +37 -16
- package/dist/core/loop-breaker.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/skills-routing.test.d.ts +2 -0
- package/dist/core/skills-routing.test.d.ts.map +1 -0
- package/dist/core/skills-routing.test.js +70 -0
- package/dist/core/skills-routing.test.js.map +1 -0
- package/dist/core/skills.d.ts +2 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +32 -9
- package/dist/core/skills.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/system-prompt.js +2 -2
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +3 -0
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/skill.d.ts.map +1 -1
- package/dist/tools/skill.js +8 -3
- package/dist/tools/skill.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/components/SkillsOverlay.d.ts.map +1 -1
- package/dist/ui/components/SkillsOverlay.js +8 -3
- package/dist/ui/components/SkillsOverlay.js.map +1 -1
- 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 +71 -26
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.test.js +27 -0
- package/dist/ui/hooks/useAgentLoop.test.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 +6 -5
package/dist/app-sidecar.js
CHANGED
|
@@ -18,11 +18,13 @@ import os from "node:os";
|
|
|
18
18
|
import path from "node:path";
|
|
19
19
|
import { randomUUID } from "node:crypto";
|
|
20
20
|
import { parseArgs } from "node:util";
|
|
21
|
-
import { formatError } from "@kenkaiiii/gg-ai";
|
|
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
24
|
import { AgentSession } from "./core/agent-session.js";
|
|
25
|
+
import { RunLifecycle } from "./core/run-lifecycle.js";
|
|
25
26
|
import { CHAT_AGENT_IDS, chatAgentSessionsDir, createChatAgent, parseChatAgentId, sessionsDirForChatAgent, switchChatAgent, } from "./chat-agents/index.js";
|
|
27
|
+
import { buildJiwaTools, JiwaStore } from "./chat-agents/jiwa.js";
|
|
26
28
|
import { buildMemoryTools, MemoryStore } from "./chat-agents/memory.js";
|
|
27
29
|
import { buildKenSystemPrompt, buildKenAutopilotSystemPrompt } from "./core/ken-prompt.js";
|
|
28
30
|
import { buildKenDigest, buildKenAutopilotContext, buildKenAutopilotPlanContext, } from "./core/ken-context.js";
|
|
@@ -517,6 +519,13 @@ async function main() {
|
|
|
517
519
|
}
|
|
518
520
|
},
|
|
519
521
|
});
|
|
522
|
+
const jiwaStore = new JiwaStore({
|
|
523
|
+
onChange: ({ jiwa }) => {
|
|
524
|
+
for (const ctx of sessions.values()) {
|
|
525
|
+
ctx.broadcast("jiwa_change", { count: jiwa.length });
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
});
|
|
520
529
|
// XP/rank progress — loaded once per daemon; awards fan out to every window.
|
|
521
530
|
// Each frame is tagged `origin: true` only for the session that earned the
|
|
522
531
|
// XP, so that window alone plays sounds/chips while the rest just re-render.
|
|
@@ -633,7 +642,7 @@ async function main() {
|
|
|
633
642
|
const sessionPath = typeof body.sessionPath === "string" && body.sessionPath ? body.sessionPath : undefined;
|
|
634
643
|
const id = randomUUID();
|
|
635
644
|
try {
|
|
636
|
-
const ctx = await createSession({ auth, paths, progress, memoryStore }, { id, mode, chatAgent, cwd: sessionCwd, sessionPath });
|
|
645
|
+
const ctx = await createSession({ auth, paths, progress, memoryStore, jiwaStore }, { id, mode, chatAgent, cwd: sessionCwd, sessionPath });
|
|
637
646
|
sessions.set(id, ctx);
|
|
638
647
|
log("INFO", "app-sidecar", "session created", {
|
|
639
648
|
id,
|
|
@@ -886,7 +895,7 @@ async function createProgressManager(agentDir, broadcastAll) {
|
|
|
886
895
|
* logger, PATH, shared auth file, and radio live at the daemon level.
|
|
887
896
|
*/
|
|
888
897
|
async function createSession(deps, opts) {
|
|
889
|
-
const { auth, progress, memoryStore } = deps;
|
|
898
|
+
const { auth, progress, memoryStore, jiwaStore } = deps;
|
|
890
899
|
const paths = deps.paths;
|
|
891
900
|
const mode = opts.mode;
|
|
892
901
|
let chatAgent = opts.chatAgent;
|
|
@@ -921,7 +930,8 @@ async function createSession(deps, opts) {
|
|
|
921
930
|
const clients = new Set();
|
|
922
931
|
let clientSeq = 0;
|
|
923
932
|
function broadcast(type, data) {
|
|
924
|
-
const
|
|
933
|
+
const safePayload = redactValue({ type, data }, { secrets: environmentSecrets(process.env) });
|
|
934
|
+
const frame = `data: ${JSON.stringify(safePayload)}\n\n`;
|
|
925
935
|
for (const c of clients)
|
|
926
936
|
c.res.write(frame);
|
|
927
937
|
}
|
|
@@ -1007,8 +1017,8 @@ async function createSession(deps, opts) {
|
|
|
1007
1017
|
session = createChatAgent(chatAgent, {
|
|
1008
1018
|
...baseSessionOptions,
|
|
1009
1019
|
sessionsDir: paths.sessionsDir,
|
|
1010
|
-
additionalTools: buildMemoryTools(memoryStore),
|
|
1011
|
-
getSystemPromptTail: () => memoryStore.renderForPrompt()
|
|
1020
|
+
additionalTools: [...buildMemoryTools(memoryStore), ...buildJiwaTools(jiwaStore)],
|
|
1021
|
+
getSystemPromptTail: () => `${memoryStore.renderForPrompt()}\n\n${jiwaStore.renderForPrompt()}`,
|
|
1012
1022
|
onAgentChange: async (nextAgent) => {
|
|
1013
1023
|
chatAgent = nextAgent;
|
|
1014
1024
|
broadcast("chat_agent_change", { chatAgent: nextAgent });
|
|
@@ -1115,6 +1125,13 @@ async function createSession(deps, opts) {
|
|
|
1115
1125
|
session.eventBus.on("compaction_start", (d) => broadcast("compaction_start", d));
|
|
1116
1126
|
session.eventBus.on("compaction_end", (d) => broadcast("compaction_end", d));
|
|
1117
1127
|
let running = false;
|
|
1128
|
+
const runLifecycle = new RunLifecycle((runState) => {
|
|
1129
|
+
running = runState !== "idle";
|
|
1130
|
+
if (runState === "cancelling")
|
|
1131
|
+
broadcast("run_cancelling", { runState });
|
|
1132
|
+
});
|
|
1133
|
+
const cancelledRunEndGenerations = new Set();
|
|
1134
|
+
let pendingCancelDrain = null;
|
|
1118
1135
|
let titleGenerated = false;
|
|
1119
1136
|
// Bumped by /cancel — a run whose cancel generation changed mid-flight was
|
|
1120
1137
|
// canceled and earns no XP.
|
|
@@ -1137,6 +1154,7 @@ async function createSession(deps, opts) {
|
|
|
1137
1154
|
let autopilotCancelled = false;
|
|
1138
1155
|
// Hard cap on review→prompt→review rounds per user turn (loop safety).
|
|
1139
1156
|
const MAX_AUTOPILOT_ROUNDS = 3;
|
|
1157
|
+
const CANCEL_TIMEOUT_MS = 5_000;
|
|
1140
1158
|
// Prompt bodies Autopilot Ken injected into the BUILD session this
|
|
1141
1159
|
// conversation. Passed into every Ken digest so injected prompts render as
|
|
1142
1160
|
// "Ken autopilot (injected)" instead of `**User:**` — otherwise multi-round
|
|
@@ -1343,29 +1361,63 @@ async function createSession(deps, opts) {
|
|
|
1343
1361
|
});
|
|
1344
1362
|
}
|
|
1345
1363
|
}
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1364
|
+
function abortOwnedWork() {
|
|
1365
|
+
cancelGeneration++;
|
|
1366
|
+
abort.abort();
|
|
1367
|
+
// Stop a run-all sweep and every async child through AgentSession's signal.
|
|
1368
|
+
taskRunAll = false;
|
|
1369
|
+
autopilotCancelled = true;
|
|
1370
|
+
kenAutoAbort.abort();
|
|
1371
|
+
}
|
|
1372
|
+
function installFreshRunControllers() {
|
|
1373
|
+
abort = new AbortController();
|
|
1374
|
+
session.setSignal(abort.signal);
|
|
1375
|
+
kenAutoAbort = new AbortController();
|
|
1376
|
+
kenAutoSession?.setSignal(kenAutoAbort.signal);
|
|
1377
|
+
}
|
|
1378
|
+
function finishOwnedGeneration(generation, emitCancelledFallback) {
|
|
1379
|
+
const cancelled = runLifecycle.isCancellationRequested(generation);
|
|
1380
|
+
const settlement = runLifecycle.settle(generation);
|
|
1381
|
+
if (!settlement.settled)
|
|
1382
|
+
return cancelled;
|
|
1383
|
+
// A replacement signal is safe only after the provider-backed owner settled.
|
|
1384
|
+
installFreshRunControllers();
|
|
1385
|
+
if (cancelled && emitCancelledFallback && !cancelledRunEndGenerations.has(generation)) {
|
|
1386
|
+
cancelledRunEndGenerations.add(generation);
|
|
1387
|
+
broadcast("run_end", { cancelled: true, runState: runLifecycle.state });
|
|
1388
|
+
}
|
|
1389
|
+
return cancelled;
|
|
1390
|
+
}
|
|
1391
|
+
// Core provider-run bracket. Standalone runs own a lifecycle generation;
|
|
1392
|
+
// injected autopilot runs share the cycle's outer generation.
|
|
1350
1393
|
async function runAgent(label, run) {
|
|
1351
|
-
|
|
1394
|
+
const ownsGeneration = !runLifecycle.running;
|
|
1395
|
+
const generation = ownsGeneration
|
|
1396
|
+
? runLifecycle.begin(abortOwnedWork).generation
|
|
1397
|
+
: runLifecycle.generation;
|
|
1398
|
+
if (ownsGeneration)
|
|
1399
|
+
pendingCancelDrain = null;
|
|
1352
1400
|
// Progress (Ranks): completed, non-canceled runs with ≥1 assistant turn earn
|
|
1353
1401
|
// XP — prompt + any commits authored during the run window.
|
|
1354
1402
|
const runStartedAt = Date.now();
|
|
1355
1403
|
const cancelGenAtStart = cancelGeneration;
|
|
1356
1404
|
const assistantsBeforeRun = countAssistantMessages(session.getMessages());
|
|
1357
1405
|
let runSucceeded = false;
|
|
1358
|
-
broadcast("run_start", { text: label });
|
|
1406
|
+
broadcast("run_start", { text: label, runState: runLifecycle.state });
|
|
1359
1407
|
try {
|
|
1360
|
-
|
|
1408
|
+
if (!runLifecycle.isCancellationRequested(generation))
|
|
1409
|
+
await run();
|
|
1361
1410
|
runSucceeded = true;
|
|
1362
1411
|
}
|
|
1363
1412
|
catch (err) {
|
|
1364
|
-
|
|
1413
|
+
if (!runLifecycle.isCancellationRequested(generation)) {
|
|
1414
|
+
broadcastError("error", "run failed", err);
|
|
1415
|
+
}
|
|
1365
1416
|
}
|
|
1366
1417
|
finally {
|
|
1367
|
-
|
|
1418
|
+
const cancelled = runLifecycle.isCancellationRequested(generation);
|
|
1368
1419
|
if (runSucceeded &&
|
|
1420
|
+
!cancelled &&
|
|
1369
1421
|
cancelGeneration === cancelGenAtStart &&
|
|
1370
1422
|
countAssistantMessages(session.getMessages()) > assistantsBeforeRun) {
|
|
1371
1423
|
// Fire-and-forget — XP must never delay or break run teardown.
|
|
@@ -1375,21 +1427,24 @@ async function createSession(deps, opts) {
|
|
|
1375
1427
|
// background tasks — refresh the footer extras once it settles.
|
|
1376
1428
|
gitBranch = await getGitBranch(cwd).catch(() => gitBranch);
|
|
1377
1429
|
gitIsRepo = await isGitRepo(cwd).catch(() => gitIsRepo);
|
|
1378
|
-
|
|
1430
|
+
if (ownsGeneration)
|
|
1431
|
+
finishOwnedGeneration(generation, false);
|
|
1432
|
+
// A cancelled injected run is still owned by the surrounding autopilot
|
|
1433
|
+
// cycle; its outer finalizer emits the one terminal cancelled run_end.
|
|
1434
|
+
if (!(cancelled && !ownsGeneration)) {
|
|
1435
|
+
if (cancelled)
|
|
1436
|
+
cancelledRunEndGenerations.add(generation);
|
|
1437
|
+
broadcast("run_end", {
|
|
1438
|
+
...(cancelled ? { cancelled: true } : {}),
|
|
1439
|
+
runState: runLifecycle.state,
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1379
1442
|
// Autopilot's review loop is driven explicitly from POST /prompt (see
|
|
1380
|
-
// runAutopilotCycle), NOT from this shared finally — that keeps
|
|
1381
|
-
//
|
|
1382
|
-
// the loop through the same bracket.
|
|
1383
|
-
// The agent may have marked project tasks done during the run — prune the
|
|
1384
|
-
// completed ones so they drop out of the Tasks modal automatically (users
|
|
1385
|
-
// never have to delete finished tasks by hand).
|
|
1443
|
+
// runAutopilotCycle), NOT from this shared finally — that keeps injected
|
|
1444
|
+
// runs from recursively entering the same review loop.
|
|
1386
1445
|
broadcast("tasks_list", { tasks: pruneDoneTasksSync(cwd) });
|
|
1387
|
-
// Queue drains into the run as steering, so it's empty by run_end —
|
|
1388
|
-
// sync the webview indicator.
|
|
1389
1446
|
broadcast("queued", { count: session.getQueuedCount() });
|
|
1390
1447
|
broadcast("extras", footerExtras());
|
|
1391
|
-
// Generate a session title once, after the first run, for the title bar
|
|
1392
|
-
// (best-effort, async — don't block the response).
|
|
1393
1448
|
if (!titleGenerated) {
|
|
1394
1449
|
titleGenerated = true;
|
|
1395
1450
|
void session.generateTitle().then((title) => {
|
|
@@ -1422,7 +1477,8 @@ async function createSession(deps, opts) {
|
|
|
1422
1477
|
return parseAutopilotVerdict(lastAssistantText(ken.getMessages()));
|
|
1423
1478
|
}
|
|
1424
1479
|
catch (err) {
|
|
1425
|
-
|
|
1480
|
+
if (!autopilotCancelled)
|
|
1481
|
+
broadcastError("autopilot_error", "autopilot review failed", err);
|
|
1426
1482
|
return null;
|
|
1427
1483
|
}
|
|
1428
1484
|
finally {
|
|
@@ -1497,6 +1553,8 @@ async function createSession(deps, opts) {
|
|
|
1497
1553
|
async function runAutopilotCycle(originalRequest) {
|
|
1498
1554
|
if (!autopilot || autopilotCancelled)
|
|
1499
1555
|
return;
|
|
1556
|
+
const generation = runLifecycle.begin(abortOwnedWork).generation;
|
|
1557
|
+
pendingCancelDrain = null;
|
|
1500
1558
|
autopilotActive = true;
|
|
1501
1559
|
// Generation captured by the last plan review; acceptPlan re-checks it so
|
|
1502
1560
|
// a user Accept/Reject landing mid-review always wins.
|
|
@@ -1611,6 +1669,8 @@ async function createSession(deps, opts) {
|
|
|
1611
1669
|
}
|
|
1612
1670
|
finally {
|
|
1613
1671
|
autopilotActive = false;
|
|
1672
|
+
finishOwnedGeneration(generation, true);
|
|
1673
|
+
queueMicrotask(() => void runStrandedQueue());
|
|
1614
1674
|
}
|
|
1615
1675
|
}
|
|
1616
1676
|
// ── Stranded-queue drain ───────────────────────────────
|
|
@@ -1787,7 +1847,7 @@ async function createSession(deps, opts) {
|
|
|
1787
1847
|
});
|
|
1788
1848
|
}
|
|
1789
1849
|
function json(res, status, body) {
|
|
1790
|
-
const payload = JSON.stringify(body);
|
|
1850
|
+
const payload = JSON.stringify(redactValue(body, { secrets: environmentSecrets(process.env) }));
|
|
1791
1851
|
res.writeHead(status, {
|
|
1792
1852
|
"content-type": "application/json",
|
|
1793
1853
|
"access-control-allow-origin": "*",
|
|
@@ -1803,6 +1863,7 @@ async function createSession(deps, opts) {
|
|
|
1803
1863
|
mode,
|
|
1804
1864
|
chatAgent,
|
|
1805
1865
|
running,
|
|
1866
|
+
runState: runLifecycle.state,
|
|
1806
1867
|
ready: true,
|
|
1807
1868
|
thinkingLevel: session.getThinkingLevel() ?? null,
|
|
1808
1869
|
supportedThinkingLevels: getSupportedThinkingLevels(st.provider, st.model),
|
|
@@ -1837,6 +1898,26 @@ async function createSession(deps, opts) {
|
|
|
1837
1898
|
.catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
|
|
1838
1899
|
return;
|
|
1839
1900
|
}
|
|
1901
|
+
if (method === "GET" && url === "/jiwa") {
|
|
1902
|
+
void jiwaStore
|
|
1903
|
+
.snapshot()
|
|
1904
|
+
.then((snapshot) => json(res, 200, snapshot))
|
|
1905
|
+
.catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
|
|
1906
|
+
return;
|
|
1907
|
+
}
|
|
1908
|
+
if (method === "DELETE" && url.startsWith("/jiwa/")) {
|
|
1909
|
+
const id = decodeURIComponent(url.slice("/jiwa/".length));
|
|
1910
|
+
if (!id) {
|
|
1911
|
+
json(res, 400, { error: "Jiwa entry id is required" });
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
1914
|
+
void jiwaStore
|
|
1915
|
+
.forget(id)
|
|
1916
|
+
.then(() => jiwaStore.snapshot())
|
|
1917
|
+
.then((snapshot) => json(res, 200, snapshot))
|
|
1918
|
+
.catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
|
|
1919
|
+
return;
|
|
1920
|
+
}
|
|
1840
1921
|
if (method === "GET" && (url === "/events" || url.startsWith("/events?"))) {
|
|
1841
1922
|
res.writeHead(200, {
|
|
1842
1923
|
"content-type": "text/event-stream",
|
|
@@ -1855,6 +1936,7 @@ async function createSession(deps, opts) {
|
|
|
1855
1936
|
mode,
|
|
1856
1937
|
chatAgent,
|
|
1857
1938
|
running,
|
|
1939
|
+
runState: runLifecycle.state,
|
|
1858
1940
|
thinkingLevel: session.getThinkingLevel() ?? null,
|
|
1859
1941
|
supportedThinkingLevels: getSupportedThinkingLevels(st.provider, st.model),
|
|
1860
1942
|
supportsVideo: getModel(st.model)?.supportsVideo ?? false,
|
|
@@ -2350,6 +2432,13 @@ async function createSession(deps, opts) {
|
|
|
2350
2432
|
json(res, 400, { error: "empty prompt" });
|
|
2351
2433
|
return;
|
|
2352
2434
|
}
|
|
2435
|
+
if (runLifecycle.running && runLifecycle.isCancellationRequested(runLifecycle.generation)) {
|
|
2436
|
+
json(res, 409, {
|
|
2437
|
+
error: runLifecycle.state === "cancelling" ? "run_cancelling" : "cancel_failed",
|
|
2438
|
+
runState: runLifecycle.state,
|
|
2439
|
+
});
|
|
2440
|
+
return;
|
|
2441
|
+
}
|
|
2353
2442
|
if (running || autopilotActive) {
|
|
2354
2443
|
// Queue prompts as mid-run steering (mirrors the CLI). Also queue while
|
|
2355
2444
|
// an autopilot cycle is active but between injected runs (build idle,
|
|
@@ -2838,26 +2927,50 @@ async function createSession(deps, opts) {
|
|
|
2838
2927
|
return;
|
|
2839
2928
|
}
|
|
2840
2929
|
if (method === "POST" && url === "/cancel") {
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2930
|
+
void (async () => {
|
|
2931
|
+
// Even between task runs, cancellation stops the sweep. Active provider
|
|
2932
|
+
// ownership invokes the full abort hook exactly once through lifecycle.
|
|
2933
|
+
taskRunAll = false;
|
|
2934
|
+
autopilotCancelled = true;
|
|
2935
|
+
if (!runLifecycle.running) {
|
|
2936
|
+
kenAutoAbort.abort();
|
|
2937
|
+
kenAutoAbort = new AbortController();
|
|
2938
|
+
kenAutoSession?.setSignal(kenAutoAbort.signal);
|
|
2939
|
+
}
|
|
2940
|
+
const generation = runLifecycle.generation;
|
|
2941
|
+
if (!pendingCancelDrain || pendingCancelDrain.generation !== generation) {
|
|
2942
|
+
pendingCancelDrain = { generation, text: session.drainQueue() };
|
|
2943
|
+
broadcast("queued", { count: 0 });
|
|
2944
|
+
}
|
|
2945
|
+
const result = await runLifecycle.cancel(CANCEL_TIMEOUT_MS);
|
|
2946
|
+
const drained = pendingCancelDrain.text;
|
|
2947
|
+
if (result.status === "failed") {
|
|
2948
|
+
broadcast("cancel_failed", {
|
|
2949
|
+
error: "cancel_failed",
|
|
2950
|
+
reason: result.reason,
|
|
2951
|
+
runState: runLifecycle.state,
|
|
2952
|
+
});
|
|
2953
|
+
json(res, 504, {
|
|
2954
|
+
error: "cancel_failed",
|
|
2955
|
+
reason: result.reason,
|
|
2956
|
+
runState: runLifecycle.state,
|
|
2957
|
+
drained,
|
|
2958
|
+
});
|
|
2959
|
+
return;
|
|
2960
|
+
}
|
|
2961
|
+
json(res, 200, {
|
|
2962
|
+
cancelled: result.status === "cancelled",
|
|
2963
|
+
runState: runLifecycle.state,
|
|
2964
|
+
drained,
|
|
2965
|
+
});
|
|
2966
|
+
})().catch((error) => {
|
|
2967
|
+
broadcast("cancel_failed", { error: "cancel_failed", runState: runLifecycle.state });
|
|
2968
|
+
json(res, 500, {
|
|
2969
|
+
error: "cancel_failed",
|
|
2970
|
+
message: error instanceof Error ? error.message : String(error),
|
|
2971
|
+
runState: runLifecycle.state,
|
|
2972
|
+
});
|
|
2973
|
+
});
|
|
2861
2974
|
return;
|
|
2862
2975
|
}
|
|
2863
2976
|
if (method === "POST" && url === "/new-session") {
|