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.
@@ -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;AA2VD,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"}
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
- const output = runGitCapture(repoPath, [
319
- "for-each-ref",
320
- "--format=%(refname:short)",
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 === "origin/HEAD" || trimmed === "HEAD") {
327
+ if (!trimmed || trimmed === "HEAD") {
331
328
  continue;
332
329
  }
333
- const normalized = trimmed.startsWith("origin/") ? trimmed.slice("origin/".length) : trimmed;
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;AAi9BD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAErG"}
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 buildOpenCodePluginContent(reviewCommand, toInProgressCommand) {
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.__kanbanOpencodePluginV2) return {};
116
- globalThis.__kanbanOpencodePluginV2 = true;
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 notifyReview = async () => {
125
- try {
126
- await $\`${reviewCmd}\`;
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 notifyInprogress = async () => {
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
- await $\`${toInProgressCmd}\`;
220
+ return Buffer.from(JSON.stringify(payload), "utf8").toString("base64");
135
221
  } catch {
136
- // Best effort: hook errors should never break OpenCode event handling.
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 notifyInprogress();
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
- if (currentState === "busy") {
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" || event.type === "session.error") {
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
- await notifyReview();
207
- currentState = "idle";
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", activityText: "Waiting for review" }), buildHookCommand("to_in_progress", { source: "opencode", activityText: "Agent active" }));
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, buildClineHookScriptContent("activity"), executable);
842
- await ensureTextFile(postToolUseHookPath, buildClineHookScriptContent("activity"), executable);
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
  }