kanban 0.1.19 → 0.1.20
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/state/workspace-state.d.ts.map +1 -1
- package/dist/state/workspace-state.js +5 -12
- package/dist/state/workspace-state.js.map +1 -1
- package/dist/terminal/agent-session-adapters.d.ts.map +1 -1
- package/dist/terminal/agent-session-adapters.js +290 -23
- package/dist/terminal/agent-session-adapters.js.map +1 -1
- package/dist/web-ui/assets/{index-BW6yopCq.js → index-C-z3g54p.js} +1352 -1349
- package/dist/web-ui/index.html +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-state.d.ts","sourceRoot":"","sources":["../../src/state/workspace-state.ts"],"names":[],"mappings":"AAOA,OAAO,EAGN,KAAK,wBAAwB,EAE7B,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EAIrC,MAAM,yBAAyB,CAAC;AAyBjC,MAAM,WAAW,0BAA0B;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAkFD,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,wBAAwB,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC3C,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAqBD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAMD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;
|
|
1
|
+
{"version":3,"file":"workspace-state.d.ts","sourceRoot":"","sources":["../../src/state/workspace-state.ts"],"names":[],"mappings":"AAOA,OAAO,EAGN,KAAK,wBAAwB,EAE7B,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EAIrC,MAAM,yBAAyB,CAAC;AAyBjC,MAAM,WAAW,0BAA0B;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAkFD,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,wBAAwB,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC3C,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAqBD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAMD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;AAoVD,qBAAa,2BAA4B,SAAQ,KAAK;IACrD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAErB,gBAAgB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;CAK7D;AAED,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,2BAAgC,GACvC,OAAO,CAAC,uBAAuB,CAAC,CA+BlC;AAED,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAW3G;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,0BAA0B,EAAE,CAAC,CAQvF;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUrF;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKlF;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAM5F;AAED,wBAAsB,kBAAkB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,gCAAgC,GACvC,OAAO,CAAC,6BAA6B,CAAC,CA2BxC"}
|
|
@@ -315,26 +315,19 @@ function detectGitCurrentBranch(repoPath) {
|
|
|
315
315
|
return runGitCapture(repoPath, ["symbolic-ref", "--quiet", "--short", "HEAD"]);
|
|
316
316
|
}
|
|
317
317
|
function detectGitBranches(repoPath) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
"refs/heads",
|
|
322
|
-
"refs/remotes/origin",
|
|
323
|
-
]);
|
|
318
|
+
// TODO: support showing remote branches again once worktree creation can safely fetch/pull
|
|
319
|
+
// and resolve missing local tracking branches automatically.
|
|
320
|
+
const output = runGitCapture(repoPath, ["for-each-ref", "--format=%(refname:short)", "refs/heads"]);
|
|
324
321
|
if (!output) {
|
|
325
322
|
return [];
|
|
326
323
|
}
|
|
327
324
|
const unique = new Set();
|
|
328
325
|
for (const line of output.split("\n")) {
|
|
329
326
|
const trimmed = line.trim();
|
|
330
|
-
if (!trimmed || trimmed === "
|
|
327
|
+
if (!trimmed || trimmed === "HEAD") {
|
|
331
328
|
continue;
|
|
332
329
|
}
|
|
333
|
-
|
|
334
|
-
if (!normalized || normalized === "HEAD") {
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
unique.add(normalized);
|
|
330
|
+
unique.add(trimmed);
|
|
338
331
|
}
|
|
339
332
|
return Array.from(unique).sort((left, right) => left.localeCompare(right));
|
|
340
333
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-state.js","sourceRoot":"","sources":["../../src/state/workspace-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { randomBytes, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, realpath, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { z } from \"zod\";\n\nimport {\n\ttype RuntimeBoardColumnId,\n\ttype RuntimeBoardData,\n\ttype RuntimeGitRepositoryInfo,\n\ttype RuntimeTaskSessionSummary,\n\ttype RuntimeWorkspaceStateResponse,\n\ttype RuntimeWorkspaceStateSaveRequest,\n\truntimeBoardDataSchema,\n\truntimeTaskSessionSummarySchema,\n\truntimeWorkspaceStateSaveRequestSchema,\n} from \"../core/api-contract.js\";\nimport { createGitProcessEnv } from \"../core/git-process-env.js\";\nimport { updateTaskDependencies } from \"../core/task-board-mutations.js\";\n\nconst RUNTIME_HOME_DIR = \".kanban\";\nconst WORKSPACES_DIR = \"workspaces\";\nconst INDEX_FILENAME = \"index.json\";\nconst BOARD_FILENAME = \"board.json\";\nconst SESSIONS_FILENAME = \"sessions.json\";\nconst META_FILENAME = \"meta.json\";\nconst INDEX_VERSION = 1;\nconst WORKSPACE_ID_COLLISION_SUFFIX_LENGTH = 4;\n\nconst BOARD_COLUMNS: Array<{ id: RuntimeBoardColumnId; title: string }> = [\n\t{ id: \"backlog\", title: \"Backlog\" },\n\t{ id: \"in_progress\", title: \"In Progress\" },\n\t{ id: \"review\", title: \"Review\" },\n\t{ id: \"trash\", title: \"Trash\" },\n];\n\ninterface WorkspaceIndexEntry {\n\tworkspaceId: string;\n\trepoPath: string;\n}\n\nexport interface RuntimeWorkspaceIndexEntry {\n\tworkspaceId: string;\n\trepoPath: string;\n}\n\ninterface WorkspaceIndexFile {\n\tversion: number;\n\tentries: Record<string, WorkspaceIndexEntry>;\n\trepoPathToId: Record<string, string>;\n}\n\ninterface WorkspaceStateMeta {\n\trevision: number;\n\tupdatedAt: number;\n}\n\nconst workspaceStateMetaSchema = z.object({\n\trevision: z.number().int().nonnegative(),\n\tupdatedAt: z.number(),\n});\n\nconst workspaceIndexEntrySchema = z.object({\n\tworkspaceId: z.string().min(1, \"Workspace ID cannot be empty.\"),\n\trepoPath: z.string().min(1, \"Workspace repository path cannot be empty.\"),\n});\n\nconst workspaceIndexFileSchema = z\n\t.object({\n\t\tversion: z.literal(INDEX_VERSION),\n\t\tentries: z.record(z.string(), workspaceIndexEntrySchema),\n\t\trepoPathToId: z.record(z.string(), z.string().min(1, \"Workspace ID cannot be empty.\")),\n\t})\n\t.superRefine((index, context) => {\n\t\tfor (const [workspaceId, entry] of Object.entries(index.entries)) {\n\t\t\tif (entry.workspaceId !== workspaceId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"entries\", workspaceId, \"workspaceId\"],\n\t\t\t\t\tmessage: `Workspace ID must match entry key \"${workspaceId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst mappedWorkspaceId = index.repoPathToId[entry.repoPath];\n\t\t\tif (mappedWorkspaceId !== workspaceId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"entries\", workspaceId, \"repoPath\"],\n\t\t\t\t\tmessage: `Missing repoPathToId mapping for \"${entry.repoPath}\" to \"${workspaceId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const [repoPath, workspaceId] of Object.entries(index.repoPathToId)) {\n\t\t\tconst entry = index.entries[workspaceId];\n\t\t\tif (!entry) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"repoPathToId\", repoPath],\n\t\t\t\t\tmessage: `Mapped workspace \"${workspaceId}\" does not exist in entries.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (entry.repoPath !== repoPath) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"repoPathToId\", repoPath],\n\t\t\t\t\tmessage: `Mapped repoPath does not match workspace entry path \"${entry.repoPath}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\nconst workspaceSessionsSchema = z\n\t.record(z.string(), runtimeTaskSessionSummarySchema)\n\t.superRefine((sessions, context) => {\n\t\tfor (const [taskId, session] of Object.entries(sessions)) {\n\t\t\tif (session.taskId !== taskId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [taskId, \"taskId\"],\n\t\t\t\t\tmessage: `Session taskId must match record key \"${taskId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\nexport interface RuntimeWorkspaceContext {\n\trepoPath: string;\n\tworkspaceId: string;\n\tstatePath: string;\n\tgit: RuntimeGitRepositoryInfo;\n}\n\nexport interface LoadWorkspaceContextOptions {\n\tautoCreateIfMissing?: boolean;\n}\n\nfunction createEmptyBoard(): RuntimeBoardData {\n\treturn {\n\t\tcolumns: BOARD_COLUMNS.map((column) => ({\n\t\t\tid: column.id,\n\t\t\ttitle: column.title,\n\t\t\tcards: [],\n\t\t})),\n\t\tdependencies: [],\n\t};\n}\n\nfunction createEmptyWorkspaceIndex(): WorkspaceIndexFile {\n\treturn {\n\t\tversion: INDEX_VERSION,\n\t\tentries: {},\n\t\trepoPathToId: {},\n\t};\n}\n\nexport function getRuntimeHomePath(): string {\n\treturn join(homedir(), RUNTIME_HOME_DIR);\n}\n\nexport function getWorkspacesRootPath(): string {\n\treturn join(getRuntimeHomePath(), WORKSPACES_DIR);\n}\n\nfunction getWorkspaceIndexPath(): string {\n\treturn join(getWorkspacesRootPath(), INDEX_FILENAME);\n}\n\nexport function getWorkspaceDirectoryPath(workspaceId: string): string {\n\treturn join(getWorkspacesRootPath(), workspaceId);\n}\n\nfunction getWorkspaceBoardPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), BOARD_FILENAME);\n}\n\nfunction getWorkspaceSessionsPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), SESSIONS_FILENAME);\n}\n\nfunction getWorkspaceMetaPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), META_FILENAME);\n}\n\nfunction isNodeErrorWithCode(error: unknown, code: string): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: unknown }).code === code;\n}\n\nasync function readJsonFile(path: string): Promise<unknown | null> {\n\ttry {\n\t\tconst raw = await readFile(path, \"utf8\");\n\t\ttry {\n\t\t\treturn JSON.parse(raw) as unknown;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Malformed JSON in ${path}. ${message}`);\n\t\t}\n\t} catch (error) {\n\t\tif (isNodeErrorWithCode(error, \"ENOENT\")) {\n\t\t\treturn null;\n\t\t}\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Could not read JSON file at ${path}. ${message}`);\n\t}\n}\n\nasync function writeJsonFileAtomic(path: string, payload: unknown): Promise<void> {\n\tawait mkdir(dirname(path), { recursive: true });\n\tconst tempPath = `${path}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;\n\tawait writeFile(tempPath, JSON.stringify(payload, null, 2), \"utf8\");\n\tawait rename(tempPath, path);\n}\n\nfunction formatSchemaIssuePath(pathSegments: PropertyKey[]): string {\n\tif (pathSegments.length === 0) {\n\t\treturn \"root\";\n\t}\n\treturn pathSegments\n\t\t.map((segment) => {\n\t\t\tif (typeof segment === \"number\") {\n\t\t\t\treturn `[${segment}]`;\n\t\t\t}\n\t\t\treturn String(segment);\n\t\t})\n\t\t.join(\".\");\n}\n\nfunction formatSchemaIssues(error: z.ZodError): string {\n\treturn error.issues.map((issue) => `${formatSchemaIssuePath(issue.path)}: ${issue.message}`).join(\"; \");\n}\n\nfunction parsePersistedStateFile<T>(\n\tfilePath: string,\n\tfileLabel: string,\n\traw: unknown | null,\n\tschema: z.ZodType<T>,\n\tdefaultValue: T,\n): T {\n\tif (raw === null) {\n\t\treturn defaultValue;\n\t}\n\tconst parsed = schema.safeParse(raw);\n\tif (!parsed.success) {\n\t\tthrow new Error(\n\t\t\t`Invalid ${fileLabel} file at ${filePath}. ` +\n\t\t\t\t`Fix or remove the file. Validation errors: ${formatSchemaIssues(parsed.error)}`,\n\t\t);\n\t}\n\treturn parsed.data;\n}\n\nfunction parseWorkspaceIndex(rawIndex: unknown | null): WorkspaceIndexFile {\n\tconst indexPath = getWorkspaceIndexPath();\n\treturn parsePersistedStateFile(\n\t\tindexPath,\n\t\tINDEX_FILENAME,\n\t\trawIndex,\n\t\tworkspaceIndexFileSchema,\n\t\tcreateEmptyWorkspaceIndex(),\n\t);\n}\n\nfunction parseWorkspaceStateSavePayload(payload: RuntimeWorkspaceStateSaveRequest): RuntimeWorkspaceStateSaveRequest {\n\tconst parsed = runtimeWorkspaceStateSaveRequestSchema.safeParse(payload);\n\tif (!parsed.success) {\n\t\tthrow new Error(`Invalid workspace state save payload. ${formatSchemaIssues(parsed.error)}`);\n\t}\n\treturn parsed.data;\n}\n\nasync function readWorkspaceBoard(workspaceId: string): Promise<RuntimeBoardData> {\n\tconst boardPath = getWorkspaceBoardPath(workspaceId);\n\tconst rawBoard = await readJsonFile(boardPath);\n\treturn updateTaskDependencies(\n\t\tparsePersistedStateFile(boardPath, BOARD_FILENAME, rawBoard, runtimeBoardDataSchema, createEmptyBoard()),\n\t);\n}\n\nasync function readWorkspaceSessions(workspaceId: string): Promise<Record<string, RuntimeTaskSessionSummary>> {\n\tconst sessionsPath = getWorkspaceSessionsPath(workspaceId);\n\tconst rawSessions = await readJsonFile(sessionsPath);\n\treturn parsePersistedStateFile(sessionsPath, SESSIONS_FILENAME, rawSessions, workspaceSessionsSchema, {});\n}\n\nasync function readWorkspaceMeta(workspaceId: string): Promise<WorkspaceStateMeta> {\n\tconst metaPath = getWorkspaceMetaPath(workspaceId);\n\tconst rawMeta = await readJsonFile(metaPath);\n\treturn parsePersistedStateFile(metaPath, META_FILENAME, rawMeta, workspaceStateMetaSchema, {\n\t\trevision: 0,\n\t\tupdatedAt: 0,\n\t});\n}\n\nasync function readWorkspaceIndex(): Promise<WorkspaceIndexFile> {\n\tconst raw = await readJsonFile(getWorkspaceIndexPath());\n\treturn parseWorkspaceIndex(raw);\n}\n\nasync function writeWorkspaceIndex(index: WorkspaceIndexFile): Promise<void> {\n\tawait writeJsonFileAtomic(getWorkspaceIndexPath(), index);\n}\n\nfunction toWorkspaceIdBase(repoPath: string): string {\n\tconst trimmed = repoPath.trim().replace(/[\\\\/]+$/g, \"\");\n\tconst folderName = basename(trimmed) || \"project\";\n\tconst normalized = folderName\n\t\t.normalize(\"NFKD\")\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\");\n\treturn normalized || \"project\";\n}\n\nfunction createWorkspaceIdCollisionSuffix(length: number): string {\n\tconst alphabet = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n\tlet suffix = \"\";\n\twhile (suffix.length < length) {\n\t\tconst bytes = randomBytes(length);\n\t\tfor (const byte of bytes) {\n\t\t\tsuffix += alphabet[byte % alphabet.length] ?? \"\";\n\t\t\tif (suffix.length === length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn suffix;\n}\n\nfunction createWorkspaceId(index: WorkspaceIndexFile, repoPath: string): string {\n\tconst baseId = toWorkspaceIdBase(repoPath);\n\tif (!index.entries[baseId] || index.entries[baseId]?.repoPath === repoPath) {\n\t\treturn baseId;\n\t}\n\n\tfor (let attempt = 0; attempt < 256; attempt += 1) {\n\t\tconst candidate = `${baseId}-${createWorkspaceIdCollisionSuffix(WORKSPACE_ID_COLLISION_SUFFIX_LENGTH)}`;\n\t\tif (!index.entries[candidate] || index.entries[candidate]?.repoPath === repoPath) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\n\tthrow new Error(`Could not generate a unique workspace ID for ${repoPath}.`);\n}\n\nfunction ensureWorkspaceEntry(\n\tindex: WorkspaceIndexFile,\n\trepoPath: string,\n): { index: WorkspaceIndexFile; entry: WorkspaceIndexEntry; changed: boolean } {\n\tconst existingWorkspaceId = index.repoPathToId[repoPath];\n\tif (existingWorkspaceId) {\n\t\tconst existingEntry = index.entries[existingWorkspaceId];\n\t\tif (existingEntry && existingEntry.repoPath === repoPath) {\n\t\t\treturn {\n\t\t\t\tindex,\n\t\t\t\tentry: existingEntry,\n\t\t\t\tchanged: false,\n\t\t\t};\n\t\t}\n\t}\n\n\tconst workspaceId = createWorkspaceId(index, repoPath);\n\n\tconst entry: WorkspaceIndexEntry = {\n\t\tworkspaceId,\n\t\trepoPath,\n\t};\n\n\treturn {\n\t\tindex: {\n\t\t\tversion: INDEX_VERSION,\n\t\t\tentries: {\n\t\t\t\t...index.entries,\n\t\t\t\t[workspaceId]: entry,\n\t\t\t},\n\t\t\trepoPathToId: {\n\t\t\t\t...index.repoPathToId,\n\t\t\t\t[repoPath]: workspaceId,\n\t\t\t},\n\t\t},\n\t\tentry,\n\t\tchanged: true,\n\t};\n}\n\nfunction findWorkspaceEntry(index: WorkspaceIndexFile, repoPath: string): WorkspaceIndexEntry | null {\n\tconst workspaceId = index.repoPathToId[repoPath];\n\tif (!workspaceId) {\n\t\treturn null;\n\t}\n\tconst entry = index.entries[workspaceId];\n\tif (!entry || entry.repoPath !== repoPath) {\n\t\treturn null;\n\t}\n\treturn entry;\n}\n\nfunction runGitCapture(cwd: string, args: string[]): string | null {\n\tconst result = spawnSync(\"git\", args, {\n\t\tcwd,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\tif (result.status !== 0 || typeof result.stdout !== \"string\") {\n\t\treturn null;\n\t}\n\tconst value = result.stdout.trim();\n\treturn value.length > 0 ? value : null;\n}\n\nfunction detectGitRoot(cwd: string): string | null {\n\treturn runGitCapture(cwd, [\"rev-parse\", \"--show-toplevel\"]);\n}\n\nfunction detectGitCurrentBranch(repoPath: string): string | null {\n\treturn runGitCapture(repoPath, [\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"]);\n}\n\nfunction detectGitBranches(repoPath: string): string[] {\n\tconst output = runGitCapture(repoPath, [\n\t\t\"for-each-ref\",\n\t\t\"--format=%(refname:short)\",\n\t\t\"refs/heads\",\n\t\t\"refs/remotes/origin\",\n\t]);\n\tif (!output) {\n\t\treturn [];\n\t}\n\n\tconst unique = new Set<string>();\n\tfor (const line of output.split(\"\\n\")) {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed || trimmed === \"origin/HEAD\" || trimmed === \"HEAD\") {\n\t\t\tcontinue;\n\t\t}\n\t\tconst normalized = trimmed.startsWith(\"origin/\") ? trimmed.slice(\"origin/\".length) : trimmed;\n\t\tif (!normalized || normalized === \"HEAD\") {\n\t\t\tcontinue;\n\t\t}\n\t\tunique.add(normalized);\n\t}\n\treturn Array.from(unique).sort((left, right) => left.localeCompare(right));\n}\n\nfunction detectGitDefaultBranch(repoPath: string, branches: string[]): string | null {\n\tconst remoteHead = runGitCapture(repoPath, [\"symbolic-ref\", \"--quiet\", \"--short\", \"refs/remotes/origin/HEAD\"]);\n\tif (remoteHead) {\n\t\tconst normalized = remoteHead.startsWith(\"origin/\") ? remoteHead.slice(\"origin/\".length) : remoteHead;\n\t\tif (normalized) {\n\t\t\treturn normalized;\n\t\t}\n\t}\n\tif (branches.includes(\"main\")) {\n\t\treturn \"main\";\n\t}\n\tif (branches.includes(\"master\")) {\n\t\treturn \"master\";\n\t}\n\treturn branches[0] ?? null;\n}\n\nfunction detectGitRepositoryInfo(repoPath: string): RuntimeGitRepositoryInfo {\n\tconst gitRoot = detectGitRoot(repoPath);\n\tif (!gitRoot) {\n\t\tthrow new Error(`No git repository detected at ${repoPath}`);\n\t}\n\n\tconst currentBranch = detectGitCurrentBranch(repoPath);\n\tconst branches = detectGitBranches(repoPath);\n\tconst orderedBranches = currentBranch && !branches.includes(currentBranch) ? [currentBranch, ...branches] : branches;\n\tconst defaultBranch = detectGitDefaultBranch(repoPath, orderedBranches);\n\n\treturn {\n\t\tcurrentBranch,\n\t\tdefaultBranch,\n\t\tbranches: orderedBranches,\n\t};\n}\n\nasync function resolveWorkspacePath(cwd: string): Promise<string> {\n\tconst resolvedCwd = resolve(cwd);\n\tlet canonicalCwd = resolvedCwd;\n\ttry {\n\t\tcanonicalCwd = await realpath(resolvedCwd);\n\t} catch {\n\t\tcanonicalCwd = resolvedCwd;\n\t}\n\n\tconst gitRoot = detectGitRoot(canonicalCwd);\n\tif (!gitRoot) {\n\t\tthrow new Error(`No git repository detected at ${canonicalCwd}`);\n\t}\n\n\tconst resolvedGitRoot = resolve(gitRoot);\n\ttry {\n\t\treturn await realpath(resolvedGitRoot);\n\t} catch {\n\t\treturn resolvedGitRoot;\n\t}\n}\n\nfunction toWorkspaceStateResponse(\n\tcontext: RuntimeWorkspaceContext,\n\tboard: RuntimeBoardData,\n\tsessions: Record<string, RuntimeTaskSessionSummary>,\n\trevision: number,\n): RuntimeWorkspaceStateResponse {\n\treturn {\n\t\trepoPath: context.repoPath,\n\t\tstatePath: context.statePath,\n\t\tgit: context.git,\n\t\tboard,\n\t\tsessions,\n\t\trevision,\n\t};\n}\n\nexport class WorkspaceStateConflictError extends Error {\n\treadonly currentRevision: number;\n\n\tconstructor(expectedRevision: number, currentRevision: number) {\n\t\tsuper(`Workspace state revision mismatch: expected ${expectedRevision}, current ${currentRevision}.`);\n\t\tthis.name = \"WorkspaceStateConflictError\";\n\t\tthis.currentRevision = currentRevision;\n\t}\n}\n\nexport async function loadWorkspaceContext(\n\tcwd: string,\n\toptions: LoadWorkspaceContextOptions = {},\n): Promise<RuntimeWorkspaceContext> {\n\tconst repoPath = await resolveWorkspacePath(cwd);\n\tconst autoCreateIfMissing = options.autoCreateIfMissing ?? true;\n\tlet index = await readWorkspaceIndex();\n\tconst existingEntry = findWorkspaceEntry(index, repoPath);\n\tif (!autoCreateIfMissing) {\n\t\tif (!existingEntry) {\n\t\t\tthrow new Error(`Project ${repoPath} is not added to Kanban yet.`);\n\t\t}\n\t\treturn {\n\t\t\trepoPath,\n\t\t\tworkspaceId: existingEntry.workspaceId,\n\t\t\tstatePath: getWorkspaceDirectoryPath(existingEntry.workspaceId),\n\t\t\tgit: detectGitRepositoryInfo(repoPath),\n\t\t};\n\t}\n\n\tconst ensured = existingEntry\n\t\t? { index, entry: existingEntry, changed: false }\n\t\t: ensureWorkspaceEntry(index, repoPath);\n\tindex = ensured.index;\n\tif (ensured.changed) {\n\t\tawait writeWorkspaceIndex(index);\n\t}\n\n\treturn {\n\t\trepoPath,\n\t\tworkspaceId: ensured.entry.workspaceId,\n\t\tstatePath: getWorkspaceDirectoryPath(ensured.entry.workspaceId),\n\t\tgit: detectGitRepositoryInfo(repoPath),\n\t};\n}\n\nexport async function loadWorkspaceContextById(workspaceId: string): Promise<RuntimeWorkspaceContext | null> {\n\tconst index = await readWorkspaceIndex();\n\tconst entry = index.entries[workspaceId];\n\tif (!entry) {\n\t\treturn null;\n\t}\n\ttry {\n\t\treturn await loadWorkspaceContext(entry.repoPath);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function listWorkspaceIndexEntries(): Promise<RuntimeWorkspaceIndexEntry[]> {\n\tconst index = await readWorkspaceIndex();\n\treturn Object.values(index.entries)\n\t\t.map((entry) => ({\n\t\t\tworkspaceId: entry.workspaceId,\n\t\t\trepoPath: entry.repoPath,\n\t\t}))\n\t\t.sort((left, right) => left.repoPath.localeCompare(right.repoPath));\n}\n\nexport async function removeWorkspaceIndexEntry(workspaceId: string): Promise<boolean> {\n\tconst index = await readWorkspaceIndex();\n\tconst entry = index.entries[workspaceId];\n\tif (!entry) {\n\t\treturn false;\n\t}\n\tdelete index.entries[workspaceId];\n\tdelete index.repoPathToId[entry.repoPath];\n\tawait writeWorkspaceIndex(index);\n\treturn true;\n}\n\nexport async function removeWorkspaceStateFiles(workspaceId: string): Promise<void> {\n\tawait rm(getWorkspaceDirectoryPath(workspaceId), {\n\t\trecursive: true,\n\t\tforce: true,\n\t});\n}\n\nexport async function loadWorkspaceState(cwd: string): Promise<RuntimeWorkspaceStateResponse> {\n\tconst context = await loadWorkspaceContext(cwd);\n\tconst board = await readWorkspaceBoard(context.workspaceId);\n\tconst sessions = await readWorkspaceSessions(context.workspaceId);\n\tconst meta = await readWorkspaceMeta(context.workspaceId);\n\treturn toWorkspaceStateResponse(context, board, sessions, meta.revision);\n}\n\nexport async function saveWorkspaceState(\n\tcwd: string,\n\tpayload: RuntimeWorkspaceStateSaveRequest,\n): Promise<RuntimeWorkspaceStateResponse> {\n\tconst parsedPayload = parseWorkspaceStateSavePayload(payload);\n\tconst context = await loadWorkspaceContext(cwd);\n\tconst metaPath = getWorkspaceMetaPath(context.workspaceId);\n\tconst currentMeta = await readWorkspaceMeta(context.workspaceId);\n\tconst expectedRevision = parsedPayload.expectedRevision;\n\tif (\n\t\ttypeof expectedRevision === \"number\" &&\n\t\tNumber.isInteger(expectedRevision) &&\n\t\texpectedRevision >= 0 &&\n\t\texpectedRevision !== currentMeta.revision\n\t) {\n\t\tthrow new WorkspaceStateConflictError(expectedRevision, currentMeta.revision);\n\t}\n\tconst board = parsedPayload.board;\n\tconst sessions = parsedPayload.sessions;\n\tconst nextRevision = currentMeta.revision + 1;\n\tconst nextMeta: WorkspaceStateMeta = {\n\t\trevision: nextRevision,\n\t\tupdatedAt: Date.now(),\n\t};\n\n\tawait writeJsonFileAtomic(getWorkspaceBoardPath(context.workspaceId), board);\n\tawait writeJsonFileAtomic(getWorkspaceSessionsPath(context.workspaceId), sessions);\n\tawait writeJsonFileAtomic(metaPath, nextMeta);\n\n\treturn toWorkspaceStateResponse(context, board, sessions, nextRevision);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workspace-state.js","sourceRoot":"","sources":["../../src/state/workspace-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { randomBytes, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, realpath, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { z } from \"zod\";\n\nimport {\n\ttype RuntimeBoardColumnId,\n\ttype RuntimeBoardData,\n\ttype RuntimeGitRepositoryInfo,\n\ttype RuntimeTaskSessionSummary,\n\ttype RuntimeWorkspaceStateResponse,\n\ttype RuntimeWorkspaceStateSaveRequest,\n\truntimeBoardDataSchema,\n\truntimeTaskSessionSummarySchema,\n\truntimeWorkspaceStateSaveRequestSchema,\n} from \"../core/api-contract.js\";\nimport { createGitProcessEnv } from \"../core/git-process-env.js\";\nimport { updateTaskDependencies } from \"../core/task-board-mutations.js\";\n\nconst RUNTIME_HOME_DIR = \".kanban\";\nconst WORKSPACES_DIR = \"workspaces\";\nconst INDEX_FILENAME = \"index.json\";\nconst BOARD_FILENAME = \"board.json\";\nconst SESSIONS_FILENAME = \"sessions.json\";\nconst META_FILENAME = \"meta.json\";\nconst INDEX_VERSION = 1;\nconst WORKSPACE_ID_COLLISION_SUFFIX_LENGTH = 4;\n\nconst BOARD_COLUMNS: Array<{ id: RuntimeBoardColumnId; title: string }> = [\n\t{ id: \"backlog\", title: \"Backlog\" },\n\t{ id: \"in_progress\", title: \"In Progress\" },\n\t{ id: \"review\", title: \"Review\" },\n\t{ id: \"trash\", title: \"Trash\" },\n];\n\ninterface WorkspaceIndexEntry {\n\tworkspaceId: string;\n\trepoPath: string;\n}\n\nexport interface RuntimeWorkspaceIndexEntry {\n\tworkspaceId: string;\n\trepoPath: string;\n}\n\ninterface WorkspaceIndexFile {\n\tversion: number;\n\tentries: Record<string, WorkspaceIndexEntry>;\n\trepoPathToId: Record<string, string>;\n}\n\ninterface WorkspaceStateMeta {\n\trevision: number;\n\tupdatedAt: number;\n}\n\nconst workspaceStateMetaSchema = z.object({\n\trevision: z.number().int().nonnegative(),\n\tupdatedAt: z.number(),\n});\n\nconst workspaceIndexEntrySchema = z.object({\n\tworkspaceId: z.string().min(1, \"Workspace ID cannot be empty.\"),\n\trepoPath: z.string().min(1, \"Workspace repository path cannot be empty.\"),\n});\n\nconst workspaceIndexFileSchema = z\n\t.object({\n\t\tversion: z.literal(INDEX_VERSION),\n\t\tentries: z.record(z.string(), workspaceIndexEntrySchema),\n\t\trepoPathToId: z.record(z.string(), z.string().min(1, \"Workspace ID cannot be empty.\")),\n\t})\n\t.superRefine((index, context) => {\n\t\tfor (const [workspaceId, entry] of Object.entries(index.entries)) {\n\t\t\tif (entry.workspaceId !== workspaceId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"entries\", workspaceId, \"workspaceId\"],\n\t\t\t\t\tmessage: `Workspace ID must match entry key \"${workspaceId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst mappedWorkspaceId = index.repoPathToId[entry.repoPath];\n\t\t\tif (mappedWorkspaceId !== workspaceId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"entries\", workspaceId, \"repoPath\"],\n\t\t\t\t\tmessage: `Missing repoPathToId mapping for \"${entry.repoPath}\" to \"${workspaceId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const [repoPath, workspaceId] of Object.entries(index.repoPathToId)) {\n\t\t\tconst entry = index.entries[workspaceId];\n\t\t\tif (!entry) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"repoPathToId\", repoPath],\n\t\t\t\t\tmessage: `Mapped workspace \"${workspaceId}\" does not exist in entries.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (entry.repoPath !== repoPath) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"repoPathToId\", repoPath],\n\t\t\t\t\tmessage: `Mapped repoPath does not match workspace entry path \"${entry.repoPath}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\nconst workspaceSessionsSchema = z\n\t.record(z.string(), runtimeTaskSessionSummarySchema)\n\t.superRefine((sessions, context) => {\n\t\tfor (const [taskId, session] of Object.entries(sessions)) {\n\t\t\tif (session.taskId !== taskId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [taskId, \"taskId\"],\n\t\t\t\t\tmessage: `Session taskId must match record key \"${taskId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\nexport interface RuntimeWorkspaceContext {\n\trepoPath: string;\n\tworkspaceId: string;\n\tstatePath: string;\n\tgit: RuntimeGitRepositoryInfo;\n}\n\nexport interface LoadWorkspaceContextOptions {\n\tautoCreateIfMissing?: boolean;\n}\n\nfunction createEmptyBoard(): RuntimeBoardData {\n\treturn {\n\t\tcolumns: BOARD_COLUMNS.map((column) => ({\n\t\t\tid: column.id,\n\t\t\ttitle: column.title,\n\t\t\tcards: [],\n\t\t})),\n\t\tdependencies: [],\n\t};\n}\n\nfunction createEmptyWorkspaceIndex(): WorkspaceIndexFile {\n\treturn {\n\t\tversion: INDEX_VERSION,\n\t\tentries: {},\n\t\trepoPathToId: {},\n\t};\n}\n\nexport function getRuntimeHomePath(): string {\n\treturn join(homedir(), RUNTIME_HOME_DIR);\n}\n\nexport function getWorkspacesRootPath(): string {\n\treturn join(getRuntimeHomePath(), WORKSPACES_DIR);\n}\n\nfunction getWorkspaceIndexPath(): string {\n\treturn join(getWorkspacesRootPath(), INDEX_FILENAME);\n}\n\nexport function getWorkspaceDirectoryPath(workspaceId: string): string {\n\treturn join(getWorkspacesRootPath(), workspaceId);\n}\n\nfunction getWorkspaceBoardPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), BOARD_FILENAME);\n}\n\nfunction getWorkspaceSessionsPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), SESSIONS_FILENAME);\n}\n\nfunction getWorkspaceMetaPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), META_FILENAME);\n}\n\nfunction isNodeErrorWithCode(error: unknown, code: string): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: unknown }).code === code;\n}\n\nasync function readJsonFile(path: string): Promise<unknown | null> {\n\ttry {\n\t\tconst raw = await readFile(path, \"utf8\");\n\t\ttry {\n\t\t\treturn JSON.parse(raw) as unknown;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Malformed JSON in ${path}. ${message}`);\n\t\t}\n\t} catch (error) {\n\t\tif (isNodeErrorWithCode(error, \"ENOENT\")) {\n\t\t\treturn null;\n\t\t}\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Could not read JSON file at ${path}. ${message}`);\n\t}\n}\n\nasync function writeJsonFileAtomic(path: string, payload: unknown): Promise<void> {\n\tawait mkdir(dirname(path), { recursive: true });\n\tconst tempPath = `${path}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;\n\tawait writeFile(tempPath, JSON.stringify(payload, null, 2), \"utf8\");\n\tawait rename(tempPath, path);\n}\n\nfunction formatSchemaIssuePath(pathSegments: PropertyKey[]): string {\n\tif (pathSegments.length === 0) {\n\t\treturn \"root\";\n\t}\n\treturn pathSegments\n\t\t.map((segment) => {\n\t\t\tif (typeof segment === \"number\") {\n\t\t\t\treturn `[${segment}]`;\n\t\t\t}\n\t\t\treturn String(segment);\n\t\t})\n\t\t.join(\".\");\n}\n\nfunction formatSchemaIssues(error: z.ZodError): string {\n\treturn error.issues.map((issue) => `${formatSchemaIssuePath(issue.path)}: ${issue.message}`).join(\"; \");\n}\n\nfunction parsePersistedStateFile<T>(\n\tfilePath: string,\n\tfileLabel: string,\n\traw: unknown | null,\n\tschema: z.ZodType<T>,\n\tdefaultValue: T,\n): T {\n\tif (raw === null) {\n\t\treturn defaultValue;\n\t}\n\tconst parsed = schema.safeParse(raw);\n\tif (!parsed.success) {\n\t\tthrow new Error(\n\t\t\t`Invalid ${fileLabel} file at ${filePath}. ` +\n\t\t\t\t`Fix or remove the file. Validation errors: ${formatSchemaIssues(parsed.error)}`,\n\t\t);\n\t}\n\treturn parsed.data;\n}\n\nfunction parseWorkspaceIndex(rawIndex: unknown | null): WorkspaceIndexFile {\n\tconst indexPath = getWorkspaceIndexPath();\n\treturn parsePersistedStateFile(\n\t\tindexPath,\n\t\tINDEX_FILENAME,\n\t\trawIndex,\n\t\tworkspaceIndexFileSchema,\n\t\tcreateEmptyWorkspaceIndex(),\n\t);\n}\n\nfunction parseWorkspaceStateSavePayload(payload: RuntimeWorkspaceStateSaveRequest): RuntimeWorkspaceStateSaveRequest {\n\tconst parsed = runtimeWorkspaceStateSaveRequestSchema.safeParse(payload);\n\tif (!parsed.success) {\n\t\tthrow new Error(`Invalid workspace state save payload. ${formatSchemaIssues(parsed.error)}`);\n\t}\n\treturn parsed.data;\n}\n\nasync function readWorkspaceBoard(workspaceId: string): Promise<RuntimeBoardData> {\n\tconst boardPath = getWorkspaceBoardPath(workspaceId);\n\tconst rawBoard = await readJsonFile(boardPath);\n\treturn updateTaskDependencies(\n\t\tparsePersistedStateFile(boardPath, BOARD_FILENAME, rawBoard, runtimeBoardDataSchema, createEmptyBoard()),\n\t);\n}\n\nasync function readWorkspaceSessions(workspaceId: string): Promise<Record<string, RuntimeTaskSessionSummary>> {\n\tconst sessionsPath = getWorkspaceSessionsPath(workspaceId);\n\tconst rawSessions = await readJsonFile(sessionsPath);\n\treturn parsePersistedStateFile(sessionsPath, SESSIONS_FILENAME, rawSessions, workspaceSessionsSchema, {});\n}\n\nasync function readWorkspaceMeta(workspaceId: string): Promise<WorkspaceStateMeta> {\n\tconst metaPath = getWorkspaceMetaPath(workspaceId);\n\tconst rawMeta = await readJsonFile(metaPath);\n\treturn parsePersistedStateFile(metaPath, META_FILENAME, rawMeta, workspaceStateMetaSchema, {\n\t\trevision: 0,\n\t\tupdatedAt: 0,\n\t});\n}\n\nasync function readWorkspaceIndex(): Promise<WorkspaceIndexFile> {\n\tconst raw = await readJsonFile(getWorkspaceIndexPath());\n\treturn parseWorkspaceIndex(raw);\n}\n\nasync function writeWorkspaceIndex(index: WorkspaceIndexFile): Promise<void> {\n\tawait writeJsonFileAtomic(getWorkspaceIndexPath(), index);\n}\n\nfunction toWorkspaceIdBase(repoPath: string): string {\n\tconst trimmed = repoPath.trim().replace(/[\\\\/]+$/g, \"\");\n\tconst folderName = basename(trimmed) || \"project\";\n\tconst normalized = folderName\n\t\t.normalize(\"NFKD\")\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\");\n\treturn normalized || \"project\";\n}\n\nfunction createWorkspaceIdCollisionSuffix(length: number): string {\n\tconst alphabet = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n\tlet suffix = \"\";\n\twhile (suffix.length < length) {\n\t\tconst bytes = randomBytes(length);\n\t\tfor (const byte of bytes) {\n\t\t\tsuffix += alphabet[byte % alphabet.length] ?? \"\";\n\t\t\tif (suffix.length === length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn suffix;\n}\n\nfunction createWorkspaceId(index: WorkspaceIndexFile, repoPath: string): string {\n\tconst baseId = toWorkspaceIdBase(repoPath);\n\tif (!index.entries[baseId] || index.entries[baseId]?.repoPath === repoPath) {\n\t\treturn baseId;\n\t}\n\n\tfor (let attempt = 0; attempt < 256; attempt += 1) {\n\t\tconst candidate = `${baseId}-${createWorkspaceIdCollisionSuffix(WORKSPACE_ID_COLLISION_SUFFIX_LENGTH)}`;\n\t\tif (!index.entries[candidate] || index.entries[candidate]?.repoPath === repoPath) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\n\tthrow new Error(`Could not generate a unique workspace ID for ${repoPath}.`);\n}\n\nfunction ensureWorkspaceEntry(\n\tindex: WorkspaceIndexFile,\n\trepoPath: string,\n): { index: WorkspaceIndexFile; entry: WorkspaceIndexEntry; changed: boolean } {\n\tconst existingWorkspaceId = index.repoPathToId[repoPath];\n\tif (existingWorkspaceId) {\n\t\tconst existingEntry = index.entries[existingWorkspaceId];\n\t\tif (existingEntry && existingEntry.repoPath === repoPath) {\n\t\t\treturn {\n\t\t\t\tindex,\n\t\t\t\tentry: existingEntry,\n\t\t\t\tchanged: false,\n\t\t\t};\n\t\t}\n\t}\n\n\tconst workspaceId = createWorkspaceId(index, repoPath);\n\n\tconst entry: WorkspaceIndexEntry = {\n\t\tworkspaceId,\n\t\trepoPath,\n\t};\n\n\treturn {\n\t\tindex: {\n\t\t\tversion: INDEX_VERSION,\n\t\t\tentries: {\n\t\t\t\t...index.entries,\n\t\t\t\t[workspaceId]: entry,\n\t\t\t},\n\t\t\trepoPathToId: {\n\t\t\t\t...index.repoPathToId,\n\t\t\t\t[repoPath]: workspaceId,\n\t\t\t},\n\t\t},\n\t\tentry,\n\t\tchanged: true,\n\t};\n}\n\nfunction findWorkspaceEntry(index: WorkspaceIndexFile, repoPath: string): WorkspaceIndexEntry | null {\n\tconst workspaceId = index.repoPathToId[repoPath];\n\tif (!workspaceId) {\n\t\treturn null;\n\t}\n\tconst entry = index.entries[workspaceId];\n\tif (!entry || entry.repoPath !== repoPath) {\n\t\treturn null;\n\t}\n\treturn entry;\n}\n\nfunction runGitCapture(cwd: string, args: string[]): string | null {\n\tconst result = spawnSync(\"git\", args, {\n\t\tcwd,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\tif (result.status !== 0 || typeof result.stdout !== \"string\") {\n\t\treturn null;\n\t}\n\tconst value = result.stdout.trim();\n\treturn value.length > 0 ? value : null;\n}\n\nfunction detectGitRoot(cwd: string): string | null {\n\treturn runGitCapture(cwd, [\"rev-parse\", \"--show-toplevel\"]);\n}\n\nfunction detectGitCurrentBranch(repoPath: string): string | null {\n\treturn runGitCapture(repoPath, [\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"]);\n}\n\nfunction detectGitBranches(repoPath: string): string[] {\n\t// TODO: support showing remote branches again once worktree creation can safely fetch/pull\n\t// and resolve missing local tracking branches automatically.\n\tconst output = runGitCapture(repoPath, [\"for-each-ref\", \"--format=%(refname:short)\", \"refs/heads\"]);\n\tif (!output) {\n\t\treturn [];\n\t}\n\n\tconst unique = new Set<string>();\n\tfor (const line of output.split(\"\\n\")) {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed || trimmed === \"HEAD\") {\n\t\t\tcontinue;\n\t\t}\n\t\tunique.add(trimmed);\n\t}\n\treturn Array.from(unique).sort((left, right) => left.localeCompare(right));\n}\n\nfunction detectGitDefaultBranch(repoPath: string, branches: string[]): string | null {\n\tconst remoteHead = runGitCapture(repoPath, [\"symbolic-ref\", \"--quiet\", \"--short\", \"refs/remotes/origin/HEAD\"]);\n\tif (remoteHead) {\n\t\tconst normalized = remoteHead.startsWith(\"origin/\") ? remoteHead.slice(\"origin/\".length) : remoteHead;\n\t\tif (normalized) {\n\t\t\treturn normalized;\n\t\t}\n\t}\n\tif (branches.includes(\"main\")) {\n\t\treturn \"main\";\n\t}\n\tif (branches.includes(\"master\")) {\n\t\treturn \"master\";\n\t}\n\treturn branches[0] ?? null;\n}\n\nfunction detectGitRepositoryInfo(repoPath: string): RuntimeGitRepositoryInfo {\n\tconst gitRoot = detectGitRoot(repoPath);\n\tif (!gitRoot) {\n\t\tthrow new Error(`No git repository detected at ${repoPath}`);\n\t}\n\n\tconst currentBranch = detectGitCurrentBranch(repoPath);\n\tconst branches = detectGitBranches(repoPath);\n\tconst orderedBranches = currentBranch && !branches.includes(currentBranch) ? [currentBranch, ...branches] : branches;\n\tconst defaultBranch = detectGitDefaultBranch(repoPath, orderedBranches);\n\n\treturn {\n\t\tcurrentBranch,\n\t\tdefaultBranch,\n\t\tbranches: orderedBranches,\n\t};\n}\n\nasync function resolveWorkspacePath(cwd: string): Promise<string> {\n\tconst resolvedCwd = resolve(cwd);\n\tlet canonicalCwd = resolvedCwd;\n\ttry {\n\t\tcanonicalCwd = await realpath(resolvedCwd);\n\t} catch {\n\t\tcanonicalCwd = resolvedCwd;\n\t}\n\n\tconst gitRoot = detectGitRoot(canonicalCwd);\n\tif (!gitRoot) {\n\t\tthrow new Error(`No git repository detected at ${canonicalCwd}`);\n\t}\n\n\tconst resolvedGitRoot = resolve(gitRoot);\n\ttry {\n\t\treturn await realpath(resolvedGitRoot);\n\t} catch {\n\t\treturn resolvedGitRoot;\n\t}\n}\n\nfunction toWorkspaceStateResponse(\n\tcontext: RuntimeWorkspaceContext,\n\tboard: RuntimeBoardData,\n\tsessions: Record<string, RuntimeTaskSessionSummary>,\n\trevision: number,\n): RuntimeWorkspaceStateResponse {\n\treturn {\n\t\trepoPath: context.repoPath,\n\t\tstatePath: context.statePath,\n\t\tgit: context.git,\n\t\tboard,\n\t\tsessions,\n\t\trevision,\n\t};\n}\n\nexport class WorkspaceStateConflictError extends Error {\n\treadonly currentRevision: number;\n\n\tconstructor(expectedRevision: number, currentRevision: number) {\n\t\tsuper(`Workspace state revision mismatch: expected ${expectedRevision}, current ${currentRevision}.`);\n\t\tthis.name = \"WorkspaceStateConflictError\";\n\t\tthis.currentRevision = currentRevision;\n\t}\n}\n\nexport async function loadWorkspaceContext(\n\tcwd: string,\n\toptions: LoadWorkspaceContextOptions = {},\n): Promise<RuntimeWorkspaceContext> {\n\tconst repoPath = await resolveWorkspacePath(cwd);\n\tconst autoCreateIfMissing = options.autoCreateIfMissing ?? true;\n\tlet index = await readWorkspaceIndex();\n\tconst existingEntry = findWorkspaceEntry(index, repoPath);\n\tif (!autoCreateIfMissing) {\n\t\tif (!existingEntry) {\n\t\t\tthrow new Error(`Project ${repoPath} is not added to Kanban yet.`);\n\t\t}\n\t\treturn {\n\t\t\trepoPath,\n\t\t\tworkspaceId: existingEntry.workspaceId,\n\t\t\tstatePath: getWorkspaceDirectoryPath(existingEntry.workspaceId),\n\t\t\tgit: detectGitRepositoryInfo(repoPath),\n\t\t};\n\t}\n\n\tconst ensured = existingEntry\n\t\t? { index, entry: existingEntry, changed: false }\n\t\t: ensureWorkspaceEntry(index, repoPath);\n\tindex = ensured.index;\n\tif (ensured.changed) {\n\t\tawait writeWorkspaceIndex(index);\n\t}\n\n\treturn {\n\t\trepoPath,\n\t\tworkspaceId: ensured.entry.workspaceId,\n\t\tstatePath: getWorkspaceDirectoryPath(ensured.entry.workspaceId),\n\t\tgit: detectGitRepositoryInfo(repoPath),\n\t};\n}\n\nexport async function loadWorkspaceContextById(workspaceId: string): Promise<RuntimeWorkspaceContext | null> {\n\tconst index = await readWorkspaceIndex();\n\tconst entry = index.entries[workspaceId];\n\tif (!entry) {\n\t\treturn null;\n\t}\n\ttry {\n\t\treturn await loadWorkspaceContext(entry.repoPath);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function listWorkspaceIndexEntries(): Promise<RuntimeWorkspaceIndexEntry[]> {\n\tconst index = await readWorkspaceIndex();\n\treturn Object.values(index.entries)\n\t\t.map((entry) => ({\n\t\t\tworkspaceId: entry.workspaceId,\n\t\t\trepoPath: entry.repoPath,\n\t\t}))\n\t\t.sort((left, right) => left.repoPath.localeCompare(right.repoPath));\n}\n\nexport async function removeWorkspaceIndexEntry(workspaceId: string): Promise<boolean> {\n\tconst index = await readWorkspaceIndex();\n\tconst entry = index.entries[workspaceId];\n\tif (!entry) {\n\t\treturn false;\n\t}\n\tdelete index.entries[workspaceId];\n\tdelete index.repoPathToId[entry.repoPath];\n\tawait writeWorkspaceIndex(index);\n\treturn true;\n}\n\nexport async function removeWorkspaceStateFiles(workspaceId: string): Promise<void> {\n\tawait rm(getWorkspaceDirectoryPath(workspaceId), {\n\t\trecursive: true,\n\t\tforce: true,\n\t});\n}\n\nexport async function loadWorkspaceState(cwd: string): Promise<RuntimeWorkspaceStateResponse> {\n\tconst context = await loadWorkspaceContext(cwd);\n\tconst board = await readWorkspaceBoard(context.workspaceId);\n\tconst sessions = await readWorkspaceSessions(context.workspaceId);\n\tconst meta = await readWorkspaceMeta(context.workspaceId);\n\treturn toWorkspaceStateResponse(context, board, sessions, meta.revision);\n}\n\nexport async function saveWorkspaceState(\n\tcwd: string,\n\tpayload: RuntimeWorkspaceStateSaveRequest,\n): Promise<RuntimeWorkspaceStateResponse> {\n\tconst parsedPayload = parseWorkspaceStateSavePayload(payload);\n\tconst context = await loadWorkspaceContext(cwd);\n\tconst metaPath = getWorkspaceMetaPath(context.workspaceId);\n\tconst currentMeta = await readWorkspaceMeta(context.workspaceId);\n\tconst expectedRevision = parsedPayload.expectedRevision;\n\tif (\n\t\ttypeof expectedRevision === \"number\" &&\n\t\tNumber.isInteger(expectedRevision) &&\n\t\texpectedRevision >= 0 &&\n\t\texpectedRevision !== currentMeta.revision\n\t) {\n\t\tthrow new WorkspaceStateConflictError(expectedRevision, currentMeta.revision);\n\t}\n\tconst board = parsedPayload.board;\n\tconst sessions = parsedPayload.sessions;\n\tconst nextRevision = currentMeta.revision + 1;\n\tconst nextMeta: WorkspaceStateMeta = {\n\t\trevision: nextRevision,\n\t\tupdatedAt: Date.now(),\n\t};\n\n\tawait writeJsonFileAtomic(getWorkspaceBoardPath(context.workspaceId), board);\n\tawait writeJsonFileAtomic(getWorkspaceSessionsPath(context.workspaceId), sessions);\n\tawait writeJsonFileAtomic(metaPath, nextMeta);\n\n\treturn toWorkspaceStateResponse(context, board, sessions, nextRevision);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-adapters.d.ts","sourceRoot":"","sources":["../../src/terminal/agent-session-adapters.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAoB,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAW3G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,6BAA6B,GAAG,CAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,yBAAyB,KAC9B,sBAAsB,GAAG,IAAI,CAAC;AAEnC,MAAM,MAAM,wCAAwC,GAAG,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC;AAEvG,MAAM,WAAW,mBAAmB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,sBAAsB,CAAC,EAAE,6BAA6B,CAAC;IACvD,gCAAgC,CAAC,EAAE,wCAAwC,CAAC;CAC5E;
|
|
1
|
+
{"version":3,"file":"agent-session-adapters.d.ts","sourceRoot":"","sources":["../../src/terminal/agent-session-adapters.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAoB,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAW3G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,6BAA6B,GAAG,CAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,yBAAyB,KAC9B,sBAAsB,GAAG,IAAI,CAAC;AAEnC,MAAM,MAAM,wCAAwC,GAAG,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC;AAEvG,MAAM,WAAW,mBAAmB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,sBAAsB,CAAC,EAAE,6BAA6B,CAAC;IACvD,gCAAgC,CAAC,EAAE,wCAAwC,CAAC;CAC5E;AAguCD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAErG"}
|
|
@@ -108,35 +108,169 @@ fi
|
|
|
108
108
|
echo '{"cancel":false}'
|
|
109
109
|
`;
|
|
110
110
|
}
|
|
111
|
-
function
|
|
111
|
+
function buildClinePreToolUseHookScriptContent() {
|
|
112
|
+
const activityCommand = buildHooksCommandParts(["notify", "--event", "activity", "--source", "cline"]);
|
|
113
|
+
const reviewCommand = buildHooksCommandParts(["notify", "--event", "to_review", "--source", "cline"]);
|
|
114
|
+
const inProgressCommand = buildHooksCommandParts(["notify", "--event", "to_in_progress", "--source", "cline"]);
|
|
115
|
+
if (process.platform === "win32") {
|
|
116
|
+
const activity = activityCommand.map(powerShellQuote).join(" ");
|
|
117
|
+
const review = reviewCommand.map(powerShellQuote).join(" ");
|
|
118
|
+
const inProgress = inProgressCommand.map(powerShellQuote).join(" ");
|
|
119
|
+
return `$inputText = [Console]::In.ReadToEnd()
|
|
120
|
+
$isUserQuestionTool = $inputText -match '"(toolName|tool)"\\s*:\\s*"(ask_followup_question|plan_mode_respond)"'
|
|
121
|
+
try {
|
|
122
|
+
$inputText | & ${activity} | Out-Null
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
if ($isUserQuestionTool) {
|
|
126
|
+
try {
|
|
127
|
+
$inputText | & ${review} | Out-Null
|
|
128
|
+
} catch {
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
try {
|
|
132
|
+
$inputText | & ${inProgress} | Out-Null
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
Write-Output '{"cancel":false}'
|
|
137
|
+
exit 0
|
|
138
|
+
`;
|
|
139
|
+
}
|
|
140
|
+
const activity = activityCommand.map(quoteShellArg).join(" ");
|
|
141
|
+
const review = reviewCommand.map(quoteShellArg).join(" ");
|
|
142
|
+
const inProgress = inProgressCommand.map(quoteShellArg).join(" ");
|
|
143
|
+
return `#!/usr/bin/env bash
|
|
144
|
+
INPUT="$(cat || true)"
|
|
145
|
+
printf '%s' "$INPUT" | ${activity} >/dev/null 2>&1 || true
|
|
146
|
+
if printf '%s' "$INPUT" | grep -Eq '"(toolName|tool)"[[:space:]]*:[[:space:]]*"(ask_followup_question|plan_mode_respond)"'; then
|
|
147
|
+
printf '%s' "$INPUT" | ${review} >/dev/null 2>&1 || true
|
|
148
|
+
else
|
|
149
|
+
printf '%s' "$INPUT" | ${inProgress} >/dev/null 2>&1 || true
|
|
150
|
+
fi
|
|
151
|
+
echo '{"cancel":false}'
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
function buildClinePostToolUseHookScriptContent() {
|
|
155
|
+
const activityCommand = buildHooksCommandParts(["notify", "--event", "activity", "--source", "cline"]);
|
|
156
|
+
const inProgressCommand = buildHooksCommandParts(["notify", "--event", "to_in_progress", "--source", "cline"]);
|
|
157
|
+
if (process.platform === "win32") {
|
|
158
|
+
const activity = activityCommand.map(powerShellQuote).join(" ");
|
|
159
|
+
const inProgress = inProgressCommand.map(powerShellQuote).join(" ");
|
|
160
|
+
return `$inputText = [Console]::In.ReadToEnd()
|
|
161
|
+
$isUserQuestionTool = $inputText -match '"(toolName|tool)"\\s*:\\s*"(ask_followup_question|plan_mode_respond)"'
|
|
162
|
+
try {
|
|
163
|
+
$inputText | & ${activity} | Out-Null
|
|
164
|
+
} catch {
|
|
165
|
+
}
|
|
166
|
+
if ($isUserQuestionTool) {
|
|
167
|
+
try {
|
|
168
|
+
$inputText | & ${inProgress} | Out-Null
|
|
169
|
+
} catch {
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
Write-Output '{"cancel":false}'
|
|
173
|
+
exit 0
|
|
174
|
+
`;
|
|
175
|
+
}
|
|
176
|
+
const activity = activityCommand.map(quoteShellArg).join(" ");
|
|
177
|
+
const inProgress = inProgressCommand.map(quoteShellArg).join(" ");
|
|
178
|
+
return `#!/usr/bin/env bash
|
|
179
|
+
INPUT="$(cat || true)"
|
|
180
|
+
printf '%s' "$INPUT" | ${activity} >/dev/null 2>&1 || true
|
|
181
|
+
if printf '%s' "$INPUT" | grep -Eq '"(toolName|tool)"[[:space:]]*:[[:space:]]*"(ask_followup_question|plan_mode_respond)"'; then
|
|
182
|
+
printf '%s' "$INPUT" | ${inProgress} >/dev/null 2>&1 || true
|
|
183
|
+
fi
|
|
184
|
+
echo '{"cancel":false}'
|
|
185
|
+
`;
|
|
186
|
+
}
|
|
187
|
+
function buildOpenCodePluginContent(reviewCommand, toInProgressCommand, activityCommand) {
|
|
112
188
|
const reviewCmd = escapeForTemplateLiteral(reviewCommand);
|
|
113
189
|
const toInProgressCmd = escapeForTemplateLiteral(toInProgressCommand);
|
|
190
|
+
const activityCmd = escapeForTemplateLiteral(activityCommand);
|
|
114
191
|
return `export const KanbanPlugin = async ({ $, client }) => {
|
|
115
|
-
if (globalThis.
|
|
116
|
-
globalThis.
|
|
192
|
+
if (globalThis.__kanbanOpencodePluginV3) return {};
|
|
193
|
+
globalThis.__kanbanOpencodePluginV3 = true;
|
|
117
194
|
|
|
118
195
|
if (!process?.env?.KANBAN_HOOK_TASK_ID) return {};
|
|
119
196
|
|
|
120
197
|
let currentState = "idle";
|
|
121
198
|
let rootSessionID = null;
|
|
122
199
|
const childSessionCache = new Map();
|
|
200
|
+
const messageRoleByID = new Map();
|
|
201
|
+
const assistantTextByMessageID = new Map();
|
|
202
|
+
const latestAssistantBySessionID = new Map();
|
|
203
|
+
const toolInputByCallID = new Map();
|
|
123
204
|
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
} catch {
|
|
128
|
-
// Best effort: hook errors should never break OpenCode event handling.
|
|
205
|
+
const asRecord = (value) => {
|
|
206
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
207
|
+
return null;
|
|
129
208
|
}
|
|
209
|
+
return value;
|
|
130
210
|
};
|
|
131
211
|
|
|
132
|
-
const
|
|
212
|
+
const getMessageKey = (sessionID, messageID) => String(sessionID) + ":" + String(messageID);
|
|
213
|
+
const getToolCallKey = (sessionID, callID) => String(sessionID) + ":" + String(callID);
|
|
214
|
+
|
|
215
|
+
const encodePayload = (payload) => {
|
|
216
|
+
if (!payload || typeof payload !== "object") {
|
|
217
|
+
return "";
|
|
218
|
+
}
|
|
133
219
|
try {
|
|
134
|
-
|
|
220
|
+
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64");
|
|
135
221
|
} catch {
|
|
136
|
-
|
|
222
|
+
return "";
|
|
137
223
|
}
|
|
138
224
|
};
|
|
139
225
|
|
|
226
|
+
const notify = async (kind, payload) => {
|
|
227
|
+
try {
|
|
228
|
+
const encoded = encodePayload(payload);
|
|
229
|
+
if (kind === "review") {
|
|
230
|
+
if (encoded) {
|
|
231
|
+
await $\`${reviewCmd} --metadata-base64 \${encoded}\`;
|
|
232
|
+
} else {
|
|
233
|
+
await $\`${reviewCmd}\`;
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (kind === "in_progress") {
|
|
238
|
+
if (encoded) {
|
|
239
|
+
await $\`${toInProgressCmd} --metadata-base64 \${encoded}\`;
|
|
240
|
+
} else {
|
|
241
|
+
await $\`${toInProgressCmd}\`;
|
|
242
|
+
}
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (encoded) {
|
|
246
|
+
await $\`${activityCmd} --metadata-base64 \${encoded}\`;
|
|
247
|
+
} else {
|
|
248
|
+
await $\`${activityCmd}\`;
|
|
249
|
+
}
|
|
250
|
+
} catch {
|
|
251
|
+
// Best effort: hook errors should never break OpenCode event handling.
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const notifyReview = async (sessionID, payload = {}) => {
|
|
256
|
+
const mergedPayload = {
|
|
257
|
+
...payload,
|
|
258
|
+
last_assistant_message:
|
|
259
|
+
typeof payload.last_assistant_message === "string"
|
|
260
|
+
? payload.last_assistant_message
|
|
261
|
+
: (latestAssistantBySessionID.get(sessionID) ?? undefined),
|
|
262
|
+
};
|
|
263
|
+
await notify("review", mergedPayload);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const notifyInProgress = async (payload = {}) => {
|
|
267
|
+
await notify("in_progress", payload);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const notifyActivity = async (payload = {}) => {
|
|
271
|
+
await notify("activity", payload);
|
|
272
|
+
};
|
|
273
|
+
|
|
140
274
|
const isChildSession = async (sessionID) => {
|
|
141
275
|
if (!sessionID) return true;
|
|
142
276
|
if (!client?.session?.list) return true;
|
|
@@ -155,6 +289,9 @@ function buildOpenCodePluginContent(reviewCommand, toInProgressCommand) {
|
|
|
155
289
|
};
|
|
156
290
|
|
|
157
291
|
const handleBusy = async (sessionID) => {
|
|
292
|
+
if (!sessionID) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
158
295
|
if (!rootSessionID) {
|
|
159
296
|
rootSessionID = sessionID;
|
|
160
297
|
}
|
|
@@ -163,23 +300,90 @@ function buildOpenCodePluginContent(reviewCommand, toInProgressCommand) {
|
|
|
163
300
|
}
|
|
164
301
|
if (currentState === "idle") {
|
|
165
302
|
currentState = "busy";
|
|
166
|
-
await
|
|
303
|
+
await notifyInProgress({
|
|
304
|
+
hook_event_name: "session.status",
|
|
305
|
+
});
|
|
167
306
|
}
|
|
168
307
|
};
|
|
169
308
|
|
|
170
|
-
const handleReview = async (sessionID) => {
|
|
309
|
+
const handleReview = async (sessionID, payload = {}, force = false) => {
|
|
310
|
+
if (!sessionID) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
if (!rootSessionID) {
|
|
314
|
+
rootSessionID = sessionID;
|
|
315
|
+
}
|
|
171
316
|
if (rootSessionID && sessionID !== rootSessionID) {
|
|
172
317
|
return;
|
|
173
318
|
}
|
|
174
|
-
|
|
319
|
+
|
|
320
|
+
const shouldNotify = force || currentState === "busy";
|
|
321
|
+
if (shouldNotify) {
|
|
175
322
|
currentState = "idle";
|
|
176
|
-
await notifyReview();
|
|
323
|
+
await notifyReview(sessionID, payload);
|
|
177
324
|
rootSessionID = null;
|
|
178
325
|
}
|
|
179
326
|
};
|
|
180
327
|
|
|
181
328
|
return {
|
|
182
329
|
event: async ({ event }) => {
|
|
330
|
+
if (event.type === "message.updated") {
|
|
331
|
+
const info = asRecord(event.properties?.info);
|
|
332
|
+
const sessionID = typeof info?.sessionID === "string" ? info.sessionID : null;
|
|
333
|
+
if (await isChildSession(sessionID)) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const messageID = typeof info?.id === "string" ? info.id : null;
|
|
338
|
+
const role = typeof info?.role === "string" ? info.role : null;
|
|
339
|
+
if (messageID && role) {
|
|
340
|
+
messageRoleByID.set(getMessageKey(sessionID, messageID), role);
|
|
341
|
+
if (role === "assistant" && !assistantTextByMessageID.has(getMessageKey(sessionID, messageID))) {
|
|
342
|
+
assistantTextByMessageID.set(getMessageKey(sessionID, messageID), "");
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (event.type === "message.part.updated") {
|
|
349
|
+
const part = asRecord(event.properties?.part);
|
|
350
|
+
if (!part) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const sessionID = typeof part.sessionID === "string" ? part.sessionID : null;
|
|
355
|
+
if (await isChildSession(sessionID)) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (part.type !== "text") {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const messageID = typeof part.messageID === "string" ? part.messageID : null;
|
|
364
|
+
if (!messageID) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const messageKey = getMessageKey(sessionID, messageID);
|
|
369
|
+
if (messageRoleByID.get(messageKey) !== "assistant") {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const delta = typeof event.properties?.delta === "string" ? event.properties.delta : "";
|
|
374
|
+
const fullText = typeof part.text === "string" ? part.text : "";
|
|
375
|
+
const previousText = assistantTextByMessageID.get(messageKey) ?? "";
|
|
376
|
+
const nextText = delta ? previousText + delta : (fullText || previousText);
|
|
377
|
+
const normalized = nextText.trim();
|
|
378
|
+
if (!normalized) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
assistantTextByMessageID.set(messageKey, normalized);
|
|
383
|
+
latestAssistantBySessionID.set(sessionID, normalized);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
183
387
|
const sessionID = event.properties?.sessionID;
|
|
184
388
|
if (await isChildSession(sessionID)) {
|
|
185
389
|
return;
|
|
@@ -190,21 +394,84 @@ function buildOpenCodePluginContent(reviewCommand, toInProgressCommand) {
|
|
|
190
394
|
if (status?.type === "busy") {
|
|
191
395
|
await handleBusy(sessionID);
|
|
192
396
|
} else if (status?.type === "idle") {
|
|
193
|
-
await handleReview(sessionID
|
|
397
|
+
await handleReview(sessionID, {
|
|
398
|
+
hook_event_name: "session.status",
|
|
399
|
+
});
|
|
194
400
|
}
|
|
195
401
|
}
|
|
196
402
|
|
|
197
403
|
if (event.type === "session.busy") {
|
|
198
404
|
await handleBusy(sessionID);
|
|
199
405
|
}
|
|
200
|
-
if (event.type === "session.idle"
|
|
201
|
-
await handleReview(sessionID
|
|
406
|
+
if (event.type === "session.idle") {
|
|
407
|
+
await handleReview(sessionID, {
|
|
408
|
+
hook_event_name: "session.idle",
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
if (event.type === "session.error") {
|
|
412
|
+
await handleReview(
|
|
413
|
+
sessionID,
|
|
414
|
+
{
|
|
415
|
+
hook_event_name: "session.error",
|
|
416
|
+
},
|
|
417
|
+
true,
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
"tool.execute.before": async (input, output) => {
|
|
422
|
+
const sessionID = typeof input?.sessionID === "string" ? input.sessionID : null;
|
|
423
|
+
if (await isChildSession(sessionID)) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
await handleBusy(sessionID);
|
|
428
|
+
|
|
429
|
+
const toolName = typeof input?.tool === "string" ? input.tool : undefined;
|
|
430
|
+
const callID = typeof input?.callID === "string" ? input.callID : "";
|
|
431
|
+
const toolInput = asRecord(output?.args);
|
|
432
|
+
if (callID) {
|
|
433
|
+
toolInputByCallID.set(getToolCallKey(sessionID, callID), toolInput);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
await notifyActivity({
|
|
437
|
+
hook_event_name: "BeforeTool",
|
|
438
|
+
tool_name: toolName,
|
|
439
|
+
tool_input: toolInput ?? undefined,
|
|
440
|
+
});
|
|
441
|
+
},
|
|
442
|
+
"tool.execute.after": async (input) => {
|
|
443
|
+
const sessionID = typeof input?.sessionID === "string" ? input.sessionID : null;
|
|
444
|
+
if (await isChildSession(sessionID)) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const toolName = typeof input?.tool === "string" ? input.tool : undefined;
|
|
449
|
+
const callID = typeof input?.callID === "string" ? input.callID : "";
|
|
450
|
+
const toolInput = callID ? toolInputByCallID.get(getToolCallKey(sessionID, callID)) : null;
|
|
451
|
+
if (callID) {
|
|
452
|
+
toolInputByCallID.delete(getToolCallKey(sessionID, callID));
|
|
202
453
|
}
|
|
454
|
+
|
|
455
|
+
await notifyActivity({
|
|
456
|
+
hook_event_name: "AfterTool",
|
|
457
|
+
tool_name: toolName,
|
|
458
|
+
tool_input: toolInput ?? undefined,
|
|
459
|
+
});
|
|
203
460
|
},
|
|
204
461
|
"permission.ask": async (_permission, output) => {
|
|
205
462
|
if (output?.status === "ask") {
|
|
206
|
-
|
|
207
|
-
|
|
463
|
+
const sessionID = typeof _permission?.sessionID === "string" ? _permission.sessionID : null;
|
|
464
|
+
if (await isChildSession(sessionID)) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
await handleReview(
|
|
468
|
+
sessionID,
|
|
469
|
+
{
|
|
470
|
+
hook_event_name: "PermissionRequest",
|
|
471
|
+
notification_type: "permission.asked",
|
|
472
|
+
},
|
|
473
|
+
true,
|
|
474
|
+
);
|
|
208
475
|
}
|
|
209
476
|
},
|
|
210
477
|
};
|
|
@@ -715,7 +982,7 @@ const opencodeAdapter = {
|
|
|
715
982
|
if (hooks) {
|
|
716
983
|
const pluginPath = join(getHookAgentDirectory("opencode"), "kanban.js");
|
|
717
984
|
const configPath = join(getHookAgentDirectory("opencode"), "opencode.json");
|
|
718
|
-
const pluginContent = buildOpenCodePluginContent(buildHookCommand("to_review", { source: "opencode"
|
|
985
|
+
const pluginContent = buildOpenCodePluginContent(buildHookCommand("to_review", { source: "opencode" }), buildHookCommand("to_in_progress", { source: "opencode" }), buildHookCommand("activity", { source: "opencode" }));
|
|
719
986
|
await ensureTextFile(pluginPath, pluginContent);
|
|
720
987
|
const pluginFileUrl = pathToFileURL(pluginPath).href;
|
|
721
988
|
const config = {
|
|
@@ -838,8 +1105,8 @@ const clineAdapter = {
|
|
|
838
1105
|
await ensureTextFile(notificationHookPath, buildClineNotificationHookScriptContent(), executable);
|
|
839
1106
|
await ensureTextFile(taskCompleteHookPath, buildClineHookScriptContent("to_review"), executable);
|
|
840
1107
|
await ensureTextFile(userPromptSubmitHookPath, buildClineHookScriptContent("to_in_progress"), executable);
|
|
841
|
-
await ensureTextFile(preToolUseHookPath,
|
|
842
|
-
await ensureTextFile(postToolUseHookPath,
|
|
1108
|
+
await ensureTextFile(preToolUseHookPath, buildClinePreToolUseHookScriptContent(), executable);
|
|
1109
|
+
await ensureTextFile(postToolUseHookPath, buildClinePostToolUseHookScriptContent(), executable);
|
|
843
1110
|
if (!hasCliOption(args, "--hooks-dir")) {
|
|
844
1111
|
args.push("--hooks-dir", hooksDir);
|
|
845
1112
|
}
|