@kenkaiiii/ggcoder 5.72.0 → 5.74.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/skills/refactoring/SKILL.md +3 -1
- package/dist/app-error.d.ts +21 -0
- package/dist/app-error.js +39 -0
- package/dist/app-error.js.map +1 -0
- package/dist/app-sidecar.js +39 -35
- package/dist/app-sidecar.js.map +1 -1
- package/dist/core/agent-session.d.ts +2 -2
- package/dist/core/agent-session.js +17 -7
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/checklist-detection.d.ts +11 -0
- package/dist/core/checklist-detection.js +238 -0
- package/dist/core/checklist-detection.js.map +1 -0
- package/dist/core/checklist-items.d.ts +180 -0
- package/dist/core/checklist-items.js +204 -0
- package/dist/core/checklist-items.js.map +1 -0
- package/dist/core/checklist-prompt.d.ts +3 -0
- package/dist/core/checklist-prompt.js +34 -0
- package/dist/core/checklist-prompt.js.map +1 -0
- package/dist/core/checklist-snapshot.d.ts +13 -0
- package/dist/core/checklist-snapshot.js +29 -0
- package/dist/core/checklist-snapshot.js.map +1 -0
- package/dist/core/checklist-store.d.ts +59 -0
- package/dist/core/checklist-store.js +242 -0
- package/dist/core/checklist-store.js.map +1 -0
- package/dist/core/compaction/compactor.js +6 -0
- package/dist/core/compaction/compactor.js.map +1 -1
- package/dist/core/ken-context.js +7 -3
- package/dist/core/ken-context.js.map +1 -1
- package/dist/core/lsp/client.d.ts +4 -0
- package/dist/core/lsp/client.js +71 -3
- package/dist/core/lsp/client.js.map +1 -1
- package/dist/core/lsp/manager.d.ts +1 -0
- package/dist/core/lsp/manager.js +9 -3
- package/dist/core/lsp/manager.js.map +1 -1
- package/dist/core/lsp/project-root.d.ts +9 -0
- package/dist/core/lsp/project-root.js +75 -0
- package/dist/core/lsp/project-root.js.map +1 -0
- package/dist/core/lsp/reference-project.d.ts +6 -0
- package/dist/core/lsp/reference-project.js +110 -0
- package/dist/core/lsp/reference-project.js.map +1 -0
- package/dist/core/lsp/servers.js +1 -0
- package/dist/core/lsp/servers.js.map +1 -1
- package/dist/core/subagent-receipt.js +3 -1
- package/dist/core/subagent-receipt.js.map +1 -1
- package/dist/modes/acp-mode.d.ts +2 -1
- package/dist/modes/acp-mode.js +4 -1
- package/dist/modes/acp-mode.js.map +1 -1
- package/dist/motion-agent/motion-review-session.js +7 -3
- package/dist/motion-agent/motion-review-session.js.map +1 -1
- package/dist/system-prompt.js +14 -13
- package/dist/system-prompt.js.map +1 -1
- package/dist/tools/bash.d.ts +4 -1
- package/dist/tools/bash.js +32 -7
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/checklist.d.ts +56 -0
- package/dist/tools/checklist.js +178 -0
- package/dist/tools/checklist.js.map +1 -0
- package/dist/tools/code-nav.d.ts +1 -1
- package/dist/tools/code-nav.js +3 -2
- package/dist/tools/code-nav.js.map +1 -1
- package/dist/tools/edit-targets.d.ts +10 -0
- package/dist/tools/edit-targets.js +31 -0
- package/dist/tools/edit-targets.js.map +1 -0
- package/dist/tools/edit.d.ts +11 -3
- package/dist/tools/edit.js +386 -312
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/exit-plan.d.ts +2 -2
- package/dist/tools/exit-plan.js +7 -1
- package/dist/tools/exit-plan.js.map +1 -1
- package/dist/tools/index.d.ts +3 -2
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/prompt-hints.js +3 -1
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/skill.js +6 -3
- package/dist/tools/skill.js.map +1 -1
- package/dist/tools/subagent.js +2 -1
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/tool-tiers.js +1 -0
- package/dist/tools/tool-tiers.js.map +1 -1
- package/dist/tools/verification-review.d.ts +2 -0
- package/dist/tools/verification-review.js +41 -0
- package/dist/tools/verification-review.js.map +1 -0
- package/dist/ui/components/ToolExecution.js +3 -2
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/terminal-history.js +3 -1
- package/dist/ui/terminal-history.js.map +1 -1
- package/dist/ui/tool-line-summary.js +14 -2
- package/dist/ui/tool-line-summary.js.map +1 -1
- package/dist/ui/transcript/tool-presentation.js +1 -1
- package/dist/ui/transcript/tool-presentation.js.map +1 -1
- package/dist/utils/format.js +5 -1
- package/dist/utils/format.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: refactoring
|
|
3
|
-
description: Use
|
|
3
|
+
description: Use for behavior-preserving restructuring: extract, move, split, deduplicate, plan a refactor, or migrate an implementation behind an unchanged contract. Baseline tests, small steps, revert-on-red. Do NOT use for requested behavior or API-contract changes (including new return/error semantics), even when called a "refactor"; use the normal implementation workflow with regression tests and update affected callers together. Also exclude bug fixes (root-cause when stubborn), performance work (lean), data migrations (durable), styling/copy, TDD's refactor step (tdd), and rewrites.
|
|
4
4
|
license: Behavior-preservation methodology synthesized from public sources (Fowler's Refactoring catalog, Tidy First?, and community agent skills by bienhoang, wondelai, mattpocock, jeffallan, vasilyu1983), audited 2026-09-12.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Refactoring
|
|
8
8
|
|
|
9
|
+
**Scope gate:** Decide from the requested behavior, not the word "refactor". A requested change to return values, error handling, or an API contract is implementation work, not a behavior-preserving cleanup. Use the normal implementation workflow: inspect the affected callers, make the requested contract and caller changes together, add regression coverage, and run the checks. Do not manufacture a separate pure-rename stage merely to enter this skill. Existing authorization and safety controls still apply. For a genuine behavior-preserving refactor, use the gated loop below unchanged.
|
|
10
|
+
|
|
9
11
|
**Route first:**
|
|
10
12
|
|
|
11
13
|
| Situation | Mode | Next |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type FormattedChatError } from "@kenkaiiii/gg-ai";
|
|
3
|
+
declare const appErrorSchema: z.ZodObject<{
|
|
4
|
+
scope: z.ZodDefault<z.ZodString>;
|
|
5
|
+
headline: z.ZodString;
|
|
6
|
+
message: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
7
|
+
guidance: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
8
|
+
reason: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
9
|
+
source: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
10
|
+
provider: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
11
|
+
statusCode: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
|
|
12
|
+
requestId: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
13
|
+
occurredAt: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
|
|
14
|
+
resetsAt: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
export type AppErrorPayload = z.infer<typeof appErrorSchema>;
|
|
17
|
+
/** The same sanitized snapshot goes to SSE and the append-only history marker. */
|
|
18
|
+
export declare function createAppErrorPayload(error: FormattedChatError, scope: string, occurredAt: number, secrets: Iterable<string>): AppErrorPayload;
|
|
19
|
+
/** Backward-compatible read: no migration or reclassification of old saved text. */
|
|
20
|
+
export declare function restoreAppErrorPayload(value: unknown): AppErrorPayload | undefined;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { redactValue } from "@kenkaiiii/gg-ai";
|
|
3
|
+
const timestamp = z.number().int().nonnegative().max(8_640_000_000_000).optional().catch(undefined);
|
|
4
|
+
const optionalText = z.string().max(8_000).optional().catch(undefined);
|
|
5
|
+
const appErrorSchema = z.object({
|
|
6
|
+
scope: z.string().max(80).default("error"),
|
|
7
|
+
headline: z.string().min(1).max(1_000),
|
|
8
|
+
message: optionalText,
|
|
9
|
+
guidance: optionalText,
|
|
10
|
+
reason: z.string().max(40).optional().catch(undefined),
|
|
11
|
+
source: z.string().max(40).optional().catch(undefined),
|
|
12
|
+
provider: z.string().max(80).optional().catch(undefined),
|
|
13
|
+
statusCode: z.number().int().min(100).max(599).optional().catch(undefined),
|
|
14
|
+
requestId: z.string().max(300).optional().catch(undefined),
|
|
15
|
+
occurredAt: timestamp,
|
|
16
|
+
resetsAt: timestamp,
|
|
17
|
+
});
|
|
18
|
+
/** The same sanitized snapshot goes to SSE and the append-only history marker. */
|
|
19
|
+
export function createAppErrorPayload(error, scope, occurredAt, secrets) {
|
|
20
|
+
return redactValue({
|
|
21
|
+
scope,
|
|
22
|
+
headline: error.headline,
|
|
23
|
+
message: error.message,
|
|
24
|
+
guidance: error.guidance,
|
|
25
|
+
reason: error.reason,
|
|
26
|
+
source: error.source,
|
|
27
|
+
provider: error.provider,
|
|
28
|
+
statusCode: error.statusCode,
|
|
29
|
+
requestId: error.requestId,
|
|
30
|
+
occurredAt,
|
|
31
|
+
resetsAt: error.resetsAt,
|
|
32
|
+
}, { secrets, maxStringLength: 8_000 });
|
|
33
|
+
}
|
|
34
|
+
/** Backward-compatible read: no migration or reclassification of old saved text. */
|
|
35
|
+
export function restoreAppErrorPayload(value) {
|
|
36
|
+
const parsed = appErrorSchema.safeParse(value);
|
|
37
|
+
return parsed.success ? parsed.data : undefined;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=app-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-error.js","sourceRoot":"","sources":["../src/app-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAA2B,MAAM,kBAAkB,CAAC;AAExE,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACpG,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACvE,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;IACtC,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,YAAY;IACtB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;IACtD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;IACtD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;IACxD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;IAC1E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;IAC1D,UAAU,EAAE,SAAS;IACrB,QAAQ,EAAE,SAAS;CACpB,CAAC,CAAC;AAGH,kFAAkF;AAClF,MAAM,UAAU,qBAAqB,CACnC,KAAyB,EACzB,KAAa,EACb,UAAkB,EAClB,OAAyB;IAEzB,OAAO,WAAW,CAChB;QACE,KAAK;QACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,UAAU;QACV,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,EACD,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CACpC,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC"}
|
package/dist/app-sidecar.js
CHANGED
|
@@ -19,7 +19,8 @@ import path from "node:path";
|
|
|
19
19
|
import { randomUUID } from "node:crypto";
|
|
20
20
|
import { parseArgs } from "node:util";
|
|
21
21
|
import { spawn } from "node:child_process";
|
|
22
|
-
import { environmentSecrets,
|
|
22
|
+
import { environmentSecrets, formatChatError, redactValue, } from "@kenkaiiii/gg-ai";
|
|
23
|
+
import { createAppErrorPayload, restoreAppErrorPayload, } from "./app-error.js";
|
|
23
24
|
import { runJsonMode } from "./modes/json-mode.js";
|
|
24
25
|
import { runSubagentWorkerMode } from "./modes/subagent-worker-mode.js";
|
|
25
26
|
import { setStreamDiagnostic } from "@kenkaiiii/gg-agent";
|
|
@@ -68,6 +69,7 @@ import { loadCustomCommands } from "./core/custom-commands.js";
|
|
|
68
69
|
import { discoverProjects } from "./core/project-discovery.js";
|
|
69
70
|
import { listSidecarSessions } from "./app-sidecar-sessions.js";
|
|
70
71
|
import { loadTasksSync, saveTasksSync, pruneDoneTasksSync, getNextPendingTask, markTaskInProgress, } from "./core/tasks-store.js";
|
|
72
|
+
import { readChecklistSnapshot } from "./core/checklist-snapshot.js";
|
|
71
73
|
import { initLogger, log } from "./core/logger.js";
|
|
72
74
|
import { installTerminationHandlers } from "./core/shutdown.js";
|
|
73
75
|
import { KeepAwake } from "./core/keep-awake.js";
|
|
@@ -1319,35 +1321,21 @@ async function createSession(deps, opts) {
|
|
|
1319
1321
|
// `400 {"code":"400",...}` with no "is this me or them / when does it reset"
|
|
1320
1322
|
// context that the CLI has always given.
|
|
1321
1323
|
function broadcastError(type, logLabel, err) {
|
|
1322
|
-
const f =
|
|
1324
|
+
const f = formatChatError(err);
|
|
1323
1325
|
const message = f.message ? desktopGuidance(f.message) : undefined;
|
|
1324
1326
|
const guidance = localNetworkGuidance(f.source) ?? desktopGuidance(f.guidance);
|
|
1327
|
+
const payload = createAppErrorPayload({ ...f, ...(message ? { message } : {}), guidance }, type, Date.now(), environmentSecrets(process.env));
|
|
1325
1328
|
log("ERROR", "app-sidecar", logLabel, {
|
|
1326
|
-
headline:
|
|
1329
|
+
headline: payload.headline,
|
|
1327
1330
|
source: f.source,
|
|
1328
|
-
...(message ? { message } : {}),
|
|
1329
|
-
...(
|
|
1330
|
-
...(
|
|
1331
|
-
...(
|
|
1331
|
+
...(payload.message ? { message: payload.message } : {}),
|
|
1332
|
+
...(payload.provider ? { provider: payload.provider } : {}),
|
|
1333
|
+
...(payload.statusCode != null ? { statusCode: String(payload.statusCode) } : {}),
|
|
1334
|
+
...(payload.requestId ? { requestId: payload.requestId } : {}),
|
|
1332
1335
|
});
|
|
1333
|
-
broadcast(type,
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
guidance,
|
|
1337
|
-
...(f.provider ? { provider: f.provider } : {}),
|
|
1338
|
-
...(f.statusCode != null ? { statusCode: f.statusCode } : {}),
|
|
1339
|
-
...(f.resetsAt != null ? { resetsAt: f.resetsAt } : {}),
|
|
1340
|
-
});
|
|
1341
|
-
// Persist the error row (display-only marker) so a resumed session shows
|
|
1342
|
-
// the same headline/message/guidance the live run did. Best-effort.
|
|
1343
|
-
void session
|
|
1344
|
-
.persistAppMarker("error", {
|
|
1345
|
-
scope: type,
|
|
1346
|
-
headline: f.headline,
|
|
1347
|
-
...(message ? { message } : {}),
|
|
1348
|
-
guidance,
|
|
1349
|
-
})
|
|
1350
|
-
.catch(() => { });
|
|
1336
|
+
broadcast(type, payload);
|
|
1337
|
+
// Same sanitized snapshot for live and restored rows, including reset metadata.
|
|
1338
|
+
void session.persistAppMarker("error", payload).catch(() => { });
|
|
1351
1339
|
}
|
|
1352
1340
|
// ── MCP elicitation bridge ─────────────────────────────────
|
|
1353
1341
|
// An MCP server can ask for user input in the middle of a tool call. The
|
|
@@ -3412,16 +3400,9 @@ async function createSession(deps, opts) {
|
|
|
3412
3400
|
});
|
|
3413
3401
|
}
|
|
3414
3402
|
else if (marker.kind === "error" && typeof d.headline === "string") {
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
text: "",
|
|
3418
|
-
error: {
|
|
3419
|
-
scope: typeof d.scope === "string" ? d.scope : "error",
|
|
3420
|
-
headline: d.headline,
|
|
3421
|
-
...(typeof d.message === "string" ? { message: d.message } : {}),
|
|
3422
|
-
...(typeof d.guidance === "string" ? { guidance: d.guidance } : {}),
|
|
3423
|
-
},
|
|
3424
|
-
});
|
|
3403
|
+
const error = restoreAppErrorPayload(d);
|
|
3404
|
+
if (error)
|
|
3405
|
+
history.push({ role: "assistant", text: "", error });
|
|
3425
3406
|
}
|
|
3426
3407
|
else if (marker.kind === "interrupted_run") {
|
|
3427
3408
|
// Rendered as an error row: the run's tools already changed the
|
|
@@ -3968,6 +3949,29 @@ async function createSession(deps, opts) {
|
|
|
3968
3949
|
json(res, 200, { tasks: pruneDoneTasksSync(cwd) });
|
|
3969
3950
|
return;
|
|
3970
3951
|
}
|
|
3952
|
+
if (method === "GET" && url === "/checklist") {
|
|
3953
|
+
const controller = new AbortController();
|
|
3954
|
+
res.once("close", () => controller.abort());
|
|
3955
|
+
void (async () => {
|
|
3956
|
+
try {
|
|
3957
|
+
const result = await readChecklistSnapshot(cwd, new Date(), controller.signal);
|
|
3958
|
+
if (res.destroyed)
|
|
3959
|
+
return;
|
|
3960
|
+
if (!result.ok) {
|
|
3961
|
+
log("WARN", "app-sidecar", "checklist read failed", { error: result.error });
|
|
3962
|
+
json(res, 500, { error: result.error });
|
|
3963
|
+
return;
|
|
3964
|
+
}
|
|
3965
|
+
json(res, 200, result.value);
|
|
3966
|
+
}
|
|
3967
|
+
catch (error) {
|
|
3968
|
+
log("WARN", "app-sidecar", "checklist snapshot failed", { error: String(error) });
|
|
3969
|
+
if (!res.destroyed)
|
|
3970
|
+
json(res, 500, { error: "Could not read the project checklist" });
|
|
3971
|
+
}
|
|
3972
|
+
})();
|
|
3973
|
+
return;
|
|
3974
|
+
}
|
|
3971
3975
|
// ── Radio (app-wide) ──────────────────────────────────────
|
|
3972
3976
|
// Radio is now APP-WIDE: all windows share one daemon process, and the
|
|
3973
3977
|
// player lives in `core/radio.ts` module-level singletons (one stream for
|