@commentary-dev/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +303 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1660 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands.ts","../src/errors.ts","../src/sse.ts","../src/api-client.ts","../src/constants.ts","../src/config.ts","../src/content.ts","../src/files.ts","../src/hash.ts","../src/output.ts","../src/session.ts","../src/index.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport {\n commentsCommand,\n loginCommand,\n logoutCommand,\n openCommand,\n pullCommand,\n replyCommand,\n resolveCommand,\n reviewCommand,\n revisionsCommand,\n sessionsCommand,\n statusCommand,\n syncCommand,\n watchCommand,\n waitCommentCommand,\n whoamiCommand,\n type CommandRuntime,\n type GlobalOptions,\n} from \"./commands.js\";\nimport { PACKAGE_NAME } from \"./constants.js\";\nimport { CliError, ExitCode, toErrorMessage } from \"./errors.js\";\n\ntype RunOptions = Partial<CommandRuntime>;\n\nfunction collectOption(value: string, previous: string[] = []) {\n previous.push(value);\n return previous;\n}\n\nfunction runtimeFromOptions(options?: RunOptions): CommandRuntime {\n return {\n cwd: options?.cwd ?? process.cwd(),\n stdout: options?.stdout ?? process.stdout,\n stderr: options?.stderr ?? process.stderr,\n fetchImpl: options?.fetchImpl,\n isTty: options?.isTty ?? process.stdout.isTTY,\n };\n}\n\nfunction globalOptions(command: Command): GlobalOptions {\n return command.optsWithGlobals<GlobalOptions>();\n}\n\nfunction wrap(runtime: CommandRuntime, action: (options: GlobalOptions) => Promise<void>) {\n return async function wrapped(this: Command) {\n await action(globalOptions(this));\n };\n}\n\nfunction commandOptionsWithNoOpen(command: Command) {\n const options = command.opts();\n return {\n ...globalOptions(command),\n ...options,\n noOpen: (options as { open?: boolean }).open === false,\n };\n}\n\nexport function buildProgram(runtime: CommandRuntime) {\n const program = new Command();\n program\n .name(\"commentary\")\n .description(\"Create and manage Commentary draft review sessions from local files.\")\n .version(\"0.1.0\")\n .showHelpAfterError()\n .exitOverride();\n\n program\n .option(\"--base-url <url>\", \"Commentary base URL\")\n .option(\"--token <token>\", \"Commentary API token\")\n .option(\"--json\", \"Print JSON output\")\n .option(\"--verbose\", \"Print verbose diagnostics\")\n .option(\"--quiet\", \"Suppress non-essential output\")\n .option(\"--no-color\", \"Disable color output\")\n .option(\"--session-file <path>\", \"Path to project session metadata\");\n\n program\n .command(\"login\")\n .description(\"Authenticate with Commentary.\")\n .option(\"--token <token>\", \"Store an existing API token\")\n .option(\"--no-open\", \"Do not open the browser during device login\")\n .action(async function (this: Command) {\n await loginCommand(runtime, commandOptionsWithNoOpen(this));\n });\n\n program\n .command(\"logout\")\n .description(\"Remove the stored Commentary token for the selected base URL.\")\n .action(wrap(runtime, (options) => logoutCommand(runtime, options)));\n\n program\n .command(\"whoami\")\n .description(\"Validate the configured Commentary token.\")\n .action(wrap(runtime, (options) => whoamiCommand(runtime, options)));\n\n program\n .command(\"review\")\n .description(\"Create a draft review from files or folders.\")\n .argument(\"<paths...>\")\n .option(\"--title <title>\", \"Review title\")\n .option(\"--description <description>\", \"Review description\")\n .addOption(\n new Option(\"--content-type <type>\", \"Content type\")\n .choices([\"auto\", \"markdown\", \"html\", \"plain_text\"])\n .default(\"auto\"),\n )\n .option(\"--watch\", \"Watch files and sync after creating the review\")\n .option(\"--no-open\", \"Do not open the browser\")\n .option(\"--root <path>\", \"Root for relative review paths\")\n .option(\"--include <glob>\", \"Include glob for directory review\", collectOption)\n .option(\"--exclude <glob>\", \"Exclude glob for directory review\", collectOption)\n .action(async function (this: Command, paths: string[]) {\n await reviewCommand(runtime, paths, commandOptionsWithNoOpen(this));\n });\n\n const sync = program\n .command(\"sync\")\n .description(\"Upload current tracked files as a new revision.\")\n .option(\"--message <summary>\", \"Revision summary\")\n .option(\"--all\", \"Upload even when hashes have not changed\")\n .option(\"--dry-run\", \"Print pending changes without uploading\")\n .action(async function (this: Command) {\n await syncCommand(runtime, { ...globalOptions(this), ...this.opts() });\n });\n program\n .command(\"revision\")\n .description(\"Alias for sync.\")\n .option(\"--message <summary>\", \"Revision summary\")\n .option(\"--all\", \"Upload even when hashes have not changed\")\n .option(\"--dry-run\", \"Print pending changes without uploading\")\n .action(async function (this: Command) {\n await syncCommand(runtime, { ...globalOptions(this), ...this.opts() });\n });\n\n program\n .command(\"watch\")\n .description(\"Watch tracked files and sync revisions.\")\n .option(\"--debounce <ms>\", \"Debounce in milliseconds\", \"1500\")\n .option(\"--message <summary>\", \"Revision summary\")\n .action(async function (this: Command) {\n await watchCommand(runtime, { ...globalOptions(this), ...this.opts() });\n });\n\n program\n .command(\"comments\")\n .description(\"List draft review comments.\")\n .addOption(\n new Option(\"--format <format>\", \"Output format\")\n .choices([\"text\", \"markdown\", \"json\"])\n .default(\"text\"),\n )\n .option(\"--open\", \"Show open comments\")\n .option(\"--resolved\", \"Show resolved comments\")\n .option(\"--all\", \"Show all comments\")\n .option(\"--file <path>\", \"Filter by file path\")\n .option(\"--session <id>\", \"Explicit session id\")\n .action(async function (this: Command) {\n await commentsCommand(runtime, { ...globalOptions(this), ...this.opts() });\n });\n\n program\n .command(\"wait-comment\")\n .description(\"Wait for the next draft review comment event.\")\n .option(\"--session <id>\", \"Explicit session id\")\n .option(\"--file <path>\", \"Filter by file path\")\n .option(\"--include-replies\", \"Also return reply.created events\")\n .option(\"--cursor <id>\", \"Resume after a specific live event cursor\")\n .addOption(\n new Option(\"--from <position>\", \"Where to start when no cursor is provided\")\n .choices([\"beginning\", \"latest\"])\n .default(\"latest\"),\n )\n .option(\"--timeout <duration>\", \"Maximum wait time, e.g. 30m, 10s, or 0\", \"30m\")\n .addOption(\n new Option(\"--format <format>\", \"Output format\")\n .choices([\"text\", \"markdown\", \"json\"])\n .default(\"markdown\"),\n )\n .action(async function (this: Command) {\n await waitCommentCommand(runtime, { ...globalOptions(this), ...this.opts() });\n });\n\n program\n .command(\"reply\")\n .description(\"Reply to a comment thread.\")\n .argument(\"<comment-id>\")\n .argument(\"<message>\")\n .option(\"--session <id>\", \"Explicit session id\")\n .action(async function (this: Command, threadId: string, message: string) {\n await replyCommand(runtime, threadId, message, { ...globalOptions(this), ...this.opts() });\n });\n\n program\n .command(\"resolve\")\n .description(\"Resolve a comment thread.\")\n .argument(\"<comment-id>\")\n .option(\"--session <id>\", \"Explicit session id\")\n .option(\"--message <message>\", \"Reply before resolving\")\n .action(async function (this: Command, threadId: string) {\n await resolveCommand(runtime, threadId, { ...globalOptions(this), ...this.opts() });\n });\n\n program\n .command(\"pull\")\n .description(\"Download latest reviewed files safely.\")\n .option(\"--dry-run\", \"Show what would change\")\n .option(\"--yes\", \"Overwrite changed files\")\n .option(\"--backup\", \"Create .bak files before overwrite\")\n .option(\"--output <dir>\", \"Write files to a separate directory\")\n .action(async function (this: Command) {\n await pullCommand(runtime, { ...globalOptions(this), ...this.opts() });\n });\n\n program\n .command(\"open\")\n .description(\"Open the linked review in a browser, or print the URL in headless output.\")\n .option(\"--session <id>\", \"Explicit session id\")\n .action(async function (this: Command) {\n await openCommand(runtime, { ...globalOptions(this), ...this.opts() });\n });\n\n program\n .command(\"status\")\n .description(\"Show current linked review status.\")\n .action(wrap(runtime, (options) => statusCommand(runtime, options)));\n\n program\n .command(\"sessions\")\n .description(\"List draft review sessions for the authenticated account.\")\n .action(wrap(runtime, (options) => sessionsCommand(runtime, options)));\n\n program\n .command(\"revisions\")\n .description(\"List revisions for the linked or specified draft review.\")\n .option(\"--session <id>\", \"Explicit session id\")\n .action(async function (this: Command) {\n await revisionsCommand(runtime, { ...globalOptions(this), ...this.opts() });\n });\n\n sync.alias(\"upload\");\n program.addHelpText(\n \"after\",\n `\\nExamples:\\n npx ${PACKAGE_NAME} review ./docs/spec.md\\n commentary comments --format markdown --open\\n commentary wait-comment --json\\n`,\n );\n return program;\n}\n\nexport async function runCli(argv = process.argv.slice(2), options?: RunOptions) {\n const runtime = runtimeFromOptions(options);\n const program = buildProgram(runtime);\n try {\n await program.parseAsync(argv, { from: \"user\" });\n return ExitCode.Ok;\n } catch (error) {\n const commanderError = error as { code?: string; exitCode?: number; message?: string };\n if (\n commanderError.code === \"commander.helpDisplayed\" ||\n commanderError.code === \"commander.version\"\n ) {\n return ExitCode.Ok;\n }\n if (commanderError.code?.startsWith(\"commander.\")) {\n runtime.stderr.write(`${commanderError.message ?? \"Invalid command.\"}\\n`);\n return commanderError.exitCode ?? ExitCode.Usage;\n }\n if (error instanceof CliError) {\n runtime.stderr.write(`${error.message}\\n`);\n return error.exitCode;\n }\n runtime.stderr.write(`${toErrorMessage(error)}\\n`);\n return ExitCode.General;\n }\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport chokidar from \"chokidar\";\nimport open from \"open\";\nimport { CommentaryApiClient } from \"./api-client.js\";\nimport { CLIENT_ID, CLIENT_NAME, REQUIRED_SCOPES, SESSION_FILE } from \"./constants.js\";\nimport { normalizeBaseUrl, removeStoredToken, resolveToken, setStoredToken } from \"./config.js\";\nimport { normalizeReviewPath } from \"./content.js\";\nimport { CliError, ExitCode } from \"./errors.js\";\nimport { collectFiles, readTrackedFiles, toTrackedFiles } from \"./files.js\";\nimport { contentHash } from \"./hash.js\";\nimport {\n formatCommentsMarkdown,\n formatCommentsText,\n formatReviewCreated,\n formatRevision,\n formatWaitCommentMarkdown,\n formatWaitCommentText,\n publicSessionJson,\n writeJson,\n writeText,\n type Writer,\n} from \"./output.js\";\nimport {\n findSessionFile,\n loadSessionMetadata,\n saveSessionMetadata,\n sessionRoot,\n} from \"./session.js\";\nimport type { CollectedFile } from \"./files.js\";\nimport type {\n DraftReviewLiveEvent,\n DraftReviewRevision,\n RequestedContentType,\n SessionMetadata,\n TrackedFile,\n} from \"./types.js\";\n\nexport type CommandRuntime = {\n cwd: string;\n stdout: Writer;\n stderr: Writer;\n fetchImpl?: typeof fetch | undefined;\n isTty?: boolean | undefined;\n};\n\nexport type GlobalOptions = {\n baseUrl?: string | undefined;\n token?: string | undefined;\n json?: boolean | undefined;\n verbose?: boolean | undefined;\n quiet?: boolean | undefined;\n noColor?: boolean | undefined;\n sessionFile?: string | undefined;\n};\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nasync function makeClient(runtime: CommandRuntime, options: GlobalOptions) {\n const baseUrl = normalizeBaseUrl(options.baseUrl);\n const token = await resolveToken({ baseUrl, token: options.token });\n return new CommentaryApiClient({ baseUrl, token, fetchImpl: runtime.fetchImpl });\n}\n\nfunction apiFilesFromRevision(revision: DraftReviewRevision | null) {\n return revision?.files.map((file) => ({\n fileId: file.fileId,\n path: file.path,\n contentHash: file.contentHash,\n sizeBytes: file.sizeBytes,\n contentType: file.contentType,\n }));\n}\n\nfunction changedFiles(current: CollectedFile[], tracked: TrackedFile[]) {\n const trackedByPath = new Map(tracked.map((file) => [file.path, file]));\n return current.filter((file) => {\n const previous = trackedByPath.get(file.path);\n return (\n !previous ||\n previous.contentHash !== file.contentHash ||\n previous.contentType !== file.contentType\n );\n });\n}\n\nasync function loadSession(runtime: CommandRuntime, options: GlobalOptions) {\n return loadSessionMetadata(runtime.cwd, options.sessionFile);\n}\n\nfunction shouldOpen(runtime: CommandRuntime, noOpen?: boolean) {\n return !noOpen && runtime.isTty !== false && !process.env.CI;\n}\n\nfunction placeholderSessionMetadata(input: {\n sessionId: string;\n baseUrl: string;\n}): SessionMetadata {\n return {\n version: 1,\n reviewSessionId: input.sessionId,\n reviewUrl: `${input.baseUrl}/review/draft/${encodeURIComponent(input.sessionId)}`,\n baseUrl: input.baseUrl,\n rootPath: \".\",\n trackedFiles: [],\n source: [],\n createdAt: \"\",\n lastSyncedAt: \"\",\n lastKnownRevision: null,\n };\n}\n\nasync function openOrPrint(runtime: CommandRuntime, url: string, noOpen?: boolean) {\n if (!shouldOpen(runtime, noOpen)) {\n writeText(runtime.stdout, url);\n return;\n }\n try {\n await open(url);\n } catch {\n writeText(runtime.stdout, url);\n }\n}\n\nfunction parseDurationMs(value: string | undefined, defaultMs: number) {\n const raw = value?.trim();\n if (!raw) {\n return defaultMs;\n }\n if (raw === \"0\") {\n return 0;\n }\n const match = raw.match(/^(\\d+)(ms|s|m|h)?$/i);\n if (!match) {\n throw new CliError(\n \"Duration must be a number with optional ms, s, m, or h suffix.\",\n ExitCode.Usage,\n );\n }\n const amount = Number(match[1]);\n const unit = match[2]?.toLowerCase() ?? \"ms\";\n const multiplier = unit === \"h\" ? 3_600_000 : unit === \"m\" ? 60_000 : unit === \"s\" ? 1_000 : 1;\n return amount * multiplier;\n}\n\nfunction delay(ms: number, signal: AbortSignal) {\n return new Promise<void>((resolve) => {\n if (signal.aborted) {\n resolve();\n return;\n }\n const timeout = setTimeout(resolve, ms);\n signal.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timeout);\n resolve();\n },\n { once: true },\n );\n });\n}\n\nfunction payloadString(event: DraftReviewLiveEvent, key: string) {\n const value = event.payload[key];\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nfunction isWaitCommentMatch(input: {\n event: DraftReviewLiveEvent;\n includeReplies?: boolean | undefined;\n filePath?: string | undefined;\n}) {\n const allowed =\n input.event.type === \"comment.created\" ||\n (input.includeReplies === true && input.event.type === \"reply.created\");\n if (!allowed) {\n return false;\n }\n if (!input.filePath) {\n return true;\n }\n return (\n (input.event.thread?.filePath ?? payloadString(input.event, \"filePath\")) === input.filePath\n );\n}\n\nexport async function loginCommand(\n runtime: CommandRuntime,\n options: GlobalOptions & { token?: string | undefined; noOpen?: boolean | undefined },\n) {\n const baseUrl = normalizeBaseUrl(options.baseUrl);\n if (options.token?.trim()) {\n await setStoredToken(baseUrl, { accessToken: options.token.trim() });\n if (options.json) {\n writeJson(runtime.stdout, { ok: true, baseUrl });\n } else {\n writeText(runtime.stdout, `Stored Commentary token for ${baseUrl}.`);\n }\n return;\n }\n\n const client = new CommentaryApiClient({ baseUrl, fetchImpl: runtime.fetchImpl });\n const resource = `${baseUrl}/api`;\n const device = await client.requestDeviceCode({\n clientId: CLIENT_ID,\n clientName: CLIENT_NAME,\n scope: REQUIRED_SCOPES.join(\" \"),\n resource,\n });\n if (options.json) {\n writeJson(runtime.stdout, {\n verificationUri: device.verification_uri,\n verificationUriComplete: device.verification_uri_complete,\n userCode: device.user_code,\n expiresIn: device.expires_in,\n });\n } else {\n writeText(\n runtime.stdout,\n [\n \"Connect Commentary\",\n \"\",\n `Open: ${device.verification_uri_complete}`,\n `Code: ${device.user_code}`,\n \"\",\n \"Waiting for approval...\",\n ].join(\"\\n\"),\n );\n }\n if (shouldOpen(runtime, options.noOpen)) {\n await open(device.verification_uri_complete).catch(() => undefined);\n }\n\n const startedAt = Date.now();\n const intervalMs = Math.max(1, device.interval) * 1000;\n while (Date.now() - startedAt < device.expires_in * 1000) {\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n try {\n const token = await client.exchangeDeviceCode({ deviceCode: device.device_code, resource });\n await setStoredToken(baseUrl, {\n accessToken: token.access_token,\n refreshToken: token.refresh_token,\n expiresAt: new Date(Date.now() + token.expires_in * 1000).toISOString(),\n });\n if (!options.json) {\n writeText(runtime.stdout, `Logged in to ${baseUrl}.`);\n }\n return;\n } catch (error) {\n if (error instanceof CliError && error.message === \"authorization_pending\") {\n continue;\n }\n throw error;\n }\n }\n throw new CliError(\"Device authorization expired.\", ExitCode.Auth);\n}\n\nexport async function logoutCommand(runtime: CommandRuntime, options: GlobalOptions) {\n const baseUrl = normalizeBaseUrl(options.baseUrl);\n await removeStoredToken(baseUrl);\n if (options.json) {\n writeJson(runtime.stdout, { ok: true, baseUrl });\n } else {\n writeText(runtime.stdout, `Removed Commentary token for ${baseUrl}.`);\n }\n}\n\nexport async function whoamiCommand(runtime: CommandRuntime, options: GlobalOptions) {\n const client = await makeClient(runtime, options);\n const result = await client.listDraftReviews();\n const payload = {\n ok: true,\n baseUrl: client.baseUrl,\n token: \"valid\",\n accessibleDraftReviews: result.draftReviews.length,\n };\n if (options.json) {\n writeJson(runtime.stdout, payload);\n } else {\n writeText(\n runtime.stdout,\n `Authenticated for ${client.baseUrl}. Accessible draft reviews: ${result.draftReviews.length}`,\n );\n }\n}\n\nexport async function reviewCommand(\n runtime: CommandRuntime,\n paths: string[],\n options: GlobalOptions & {\n title?: string;\n description?: string;\n contentType?: RequestedContentType;\n watch?: boolean;\n noOpen?: boolean;\n include?: string[];\n exclude?: string[];\n root?: string;\n },\n) {\n const root = path.resolve(runtime.cwd, options.root ?? \".\");\n const files = await collectFiles(paths, {\n root,\n include: options.include,\n exclude: options.exclude,\n requestedContentType: options.contentType ?? \"auto\",\n });\n const title =\n options.title?.trim() ||\n (files.length === 1\n ? path.basename(files[0]!.path, path.extname(files[0]!.path))\n : path.basename(root)) ||\n \"Commentary review\";\n const client = await makeClient(runtime, options);\n const result = await client.createDraftReview({\n title,\n description: options.description ?? null,\n files,\n });\n const sessionFilePath = await findSessionFile(root, options.sessionFile ?? SESSION_FILE);\n const now = nowIso();\n const metadata: SessionMetadata = {\n version: 1,\n reviewSessionId: result.sessionId,\n reviewUrl: result.reviewUrl,\n baseUrl: client.baseUrl,\n rootPath: path.relative(path.dirname(sessionFilePath), root) || \".\",\n trackedFiles: toTrackedFiles(files, apiFilesFromRevision(result.draftReview.latestRevision)),\n source: [\"review\", ...paths],\n createdAt: now,\n lastSyncedAt: now,\n lastKnownRevision: result.draftReview.latestRevision?.revisionNumber ?? null,\n };\n await saveSessionMetadata(sessionFilePath, metadata);\n\n if (options.json) {\n writeJson(runtime.stdout, {\n ok: true,\n draftReview: result.draftReview,\n sessionFilePath,\n session: publicSessionJson(metadata),\n });\n } else {\n writeText(\n runtime.stdout,\n formatReviewCreated({\n draftReview: result.draftReview,\n sessionFilePath,\n fileCount: files.length,\n }),\n );\n }\n if (!options.noOpen) {\n await openOrPrint(runtime, result.reviewUrl, options.noOpen);\n }\n if (options.watch) {\n await watchCommand(runtime, { ...options, sessionFile: sessionFilePath });\n }\n}\n\nexport async function syncCommand(\n runtime: CommandRuntime,\n options: GlobalOptions & {\n message?: string;\n all?: boolean;\n dryRun?: boolean;\n },\n) {\n const loaded = await loadSession(runtime, options);\n const root = sessionRoot(loaded.filePath, loaded.metadata);\n const current = await readTrackedFiles(root, loaded.metadata.trackedFiles);\n const changed = changedFiles(current, loaded.metadata.trackedFiles);\n if (options.dryRun) {\n const payload = {\n ok: true,\n changedFiles: changed.map((file) => file.path),\n fileCount: current.length,\n };\n if (options.json) {\n writeJson(runtime.stdout, payload);\n } else {\n writeText(\n runtime.stdout,\n payload.changedFiles.length ? payload.changedFiles.join(\"\\n\") : \"No local changes.\",\n );\n }\n return;\n }\n if (!options.all && changed.length === 0) {\n const revision = {\n id: \"\",\n revisionNumber: loaded.metadata.lastKnownRevision ?? 0,\n files: [],\n };\n if (options.json) {\n writeJson(runtime.stdout, {\n ok: true,\n noOp: true,\n session: publicSessionJson(loaded.metadata),\n });\n } else {\n writeText(\n runtime.stdout,\n formatRevision({ metadata: loaded.metadata, revision, uploaded: 0, noOp: true }),\n );\n }\n return;\n }\n\n const client = await makeClient(runtime, { ...options, baseUrl: loaded.metadata.baseUrl });\n const result = await client.createRevision({\n sessionId: loaded.metadata.reviewSessionId,\n summary: options.message ?? null,\n files: current,\n });\n const nextMetadata: SessionMetadata = {\n ...loaded.metadata,\n trackedFiles: toTrackedFiles(current, apiFilesFromRevision(result.revision)),\n lastSyncedAt: nowIso(),\n lastKnownRevision: result.revision.revisionNumber,\n };\n await saveSessionMetadata(loaded.filePath, nextMetadata);\n\n if (options.json) {\n writeJson(runtime.stdout, {\n ok: true,\n revision: result.revision,\n noOp: Boolean(result.noOp),\n session: publicSessionJson(nextMetadata),\n });\n } else {\n writeText(\n runtime.stdout,\n formatRevision({\n metadata: nextMetadata,\n revision: result.revision,\n uploaded: current.length,\n noOp: result.noOp,\n }),\n );\n }\n}\n\nexport async function watchCommand(\n runtime: CommandRuntime,\n options: GlobalOptions & {\n debounce?: number;\n message?: string;\n },\n) {\n const loaded = await loadSession(runtime, options);\n const root = sessionRoot(loaded.filePath, loaded.metadata);\n const debounceMs = Number(options.debounce ?? 1500);\n let timer: NodeJS.Timeout | null = null;\n let syncing = false;\n const watcher = chokidar.watch(\n loaded.metadata.trackedFiles.map((file) => path.resolve(root, file.path)),\n {\n ignoreInitial: true,\n ignored:\n /(^|[/\\\\])(\\.git|node_modules|dist|build|\\.next|\\.commentary)([/\\\\]|$)|(~$|\\.tmp$|\\.swp$)/,\n },\n );\n\n const runSync = () => {\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => {\n if (syncing) {\n return;\n }\n syncing = true;\n syncCommand(runtime, { ...options, message: options.message ?? \"Watch sync\" })\n .catch((error: unknown) =>\n runtime.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`),\n )\n .finally(() => {\n syncing = false;\n });\n }, debounceMs);\n };\n\n watcher.on(\"add\", runSync).on(\"change\", runSync).on(\"unlink\", runSync);\n writeText(\n runtime.stdout,\n `Watching ${loaded.metadata.trackedFiles.length} file(s). Press Ctrl+C to stop.`,\n );\n await new Promise<void>((resolve) => {\n const close = () => {\n void watcher.close().finally(resolve);\n };\n process.once(\"SIGINT\", close);\n process.once(\"SIGTERM\", close);\n });\n}\n\nexport async function commentsCommand(\n runtime: CommandRuntime,\n options: GlobalOptions & {\n format?: \"text\" | \"markdown\" | \"json\";\n open?: boolean;\n resolved?: boolean;\n all?: boolean;\n file?: string;\n session?: string;\n },\n) {\n const loaded = options.session ? null : await loadSession(runtime, options);\n const metadata = loaded?.metadata;\n const sessionId = options.session ?? metadata?.reviewSessionId;\n if (!sessionId) {\n throw new CliError(\"A session id is required.\", ExitCode.Usage);\n }\n const baseUrl = metadata?.baseUrl ?? normalizeBaseUrl(options.baseUrl);\n const client = await makeClient(runtime, { ...options, baseUrl });\n const status = options.all ? undefined : options.resolved ? \"resolved\" : \"open\";\n const result = await client.listComments({\n sessionId,\n status,\n filePath: options.file ? normalizeReviewPath(options.file) : undefined,\n });\n const format = options.json ? \"json\" : (options.format ?? \"text\");\n if (format === \"json\") {\n writeJson(runtime.stdout, { ok: true, threads: result.threads });\n } else if (format === \"markdown\") {\n writeText(\n runtime.stdout,\n formatCommentsMarkdown({\n session: metadata ?? {\n version: 1,\n reviewSessionId: sessionId,\n reviewUrl: `${baseUrl}/review/draft/${encodeURIComponent(sessionId)}`,\n baseUrl,\n rootPath: \".\",\n trackedFiles: [],\n source: [],\n createdAt: \"\",\n lastSyncedAt: \"\",\n lastKnownRevision: null,\n },\n threads: result.threads,\n }),\n );\n } else {\n writeText(runtime.stdout, formatCommentsText(result.threads));\n }\n}\n\nexport async function waitCommentCommand(\n runtime: CommandRuntime,\n options: GlobalOptions & {\n session?: string;\n file?: string;\n includeReplies?: boolean;\n cursor?: string;\n from?: \"beginning\" | \"latest\";\n timeout?: string;\n format?: \"text\" | \"markdown\" | \"json\";\n },\n) {\n const loaded = options.session ? null : await loadSession(runtime, options);\n const sessionId = options.session ?? loaded?.metadata.reviewSessionId;\n if (!sessionId) {\n throw new CliError(\"A session id is required.\", ExitCode.Usage);\n }\n\n const baseUrl = loaded?.metadata.baseUrl ?? normalizeBaseUrl(options.baseUrl);\n const session = loaded?.metadata ?? placeholderSessionMetadata({ sessionId, baseUrl });\n const client = await makeClient(runtime, { ...options, baseUrl });\n const filePath = options.file ? normalizeReviewPath(options.file) : undefined;\n const timeoutMs = parseDurationMs(options.timeout, 30 * 60 * 1000);\n const abortController = new AbortController();\n let timedOut = false;\n let cursor = options.cursor ?? (options.from === \"beginning\" ? undefined : \"latest\");\n let reconnectDelayMs = 1000;\n const timeout =\n timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true;\n abortController.abort();\n }, timeoutMs)\n : null;\n\n try {\n while (!abortController.signal.aborted) {\n try {\n for await (const event of client.streamDraftReviewEvents({\n sessionId,\n cursor,\n signal: abortController.signal,\n })) {\n cursor = event.id;\n reconnectDelayMs = 1000;\n if (event.type === \"draft.deleted\") {\n throw new CliError(\"Draft review was deleted before a comment arrived.\", ExitCode.Api);\n }\n if (!isWaitCommentMatch({ event, includeReplies: options.includeReplies, filePath })) {\n continue;\n }\n\n const format = options.json ? \"json\" : (options.format ?? \"markdown\");\n if (format === \"json\") {\n writeJson(runtime.stdout, { ok: true, event });\n } else if (format === \"text\") {\n writeText(runtime.stdout, formatWaitCommentText(event));\n } else {\n writeText(runtime.stdout, formatWaitCommentMarkdown({ session, event }));\n }\n abortController.abort();\n return;\n }\n } catch (error) {\n if (abortController.signal.aborted) {\n break;\n }\n if (error instanceof CliError && error.exitCode !== ExitCode.Network) {\n throw error;\n }\n if (options.verbose) {\n runtime.stderr.write(\n `Event stream disconnected; reconnecting in ${reconnectDelayMs}ms.\\n`,\n );\n }\n }\n\n await delay(reconnectDelayMs, abortController.signal);\n reconnectDelayMs = Math.min(reconnectDelayMs * 2, 10_000);\n }\n } finally {\n if (timeout) {\n clearTimeout(timeout);\n }\n }\n\n throw new CliError(\n timedOut\n ? \"Timed out waiting for a draft review comment.\"\n : \"Stopped waiting for a draft review comment.\",\n timedOut ? ExitCode.Timeout : ExitCode.General,\n );\n}\n\nexport async function replyCommand(\n runtime: CommandRuntime,\n threadId: string,\n message: string,\n options: GlobalOptions & { session?: string },\n) {\n const loaded = options.session ? null : await loadSession(runtime, options);\n const sessionId = options.session ?? loaded?.metadata.reviewSessionId;\n if (!sessionId) {\n throw new CliError(\"A session id is required.\", ExitCode.Usage);\n }\n const client = await makeClient(runtime, {\n ...options,\n baseUrl: loaded?.metadata.baseUrl ?? options.baseUrl,\n });\n const result = await client.replyToComment({ sessionId, threadId, bodyMarkdown: message });\n if (options.json) {\n writeJson(runtime.stdout, { ok: true, thread: result.thread });\n } else {\n writeText(runtime.stdout, `Replied to ${threadId}.`);\n }\n}\n\nexport async function resolveCommand(\n runtime: CommandRuntime,\n threadId: string,\n options: GlobalOptions & {\n session?: string;\n message?: string;\n },\n) {\n const loaded = options.session ? null : await loadSession(runtime, options);\n const sessionId = options.session ?? loaded?.metadata.reviewSessionId;\n if (!sessionId) {\n throw new CliError(\"A session id is required.\", ExitCode.Usage);\n }\n const client = await makeClient(runtime, {\n ...options,\n baseUrl: loaded?.metadata.baseUrl ?? options.baseUrl,\n });\n if (options.message?.trim()) {\n await client.replyToComment({ sessionId, threadId, bodyMarkdown: options.message.trim() });\n }\n const result = await client.updateCommentStatus({ sessionId, threadId, status: \"resolved\" });\n if (options.json) {\n writeJson(runtime.stdout, { ok: true, thread: result.thread });\n } else {\n writeText(runtime.stdout, `Resolved ${threadId}.`);\n }\n}\n\nexport async function pullCommand(\n runtime: CommandRuntime,\n options: GlobalOptions & {\n dryRun?: boolean;\n yes?: boolean;\n backup?: boolean;\n output?: string;\n },\n) {\n const loaded = await loadSession(runtime, options);\n const root = sessionRoot(loaded.filePath, loaded.metadata);\n const client = await makeClient(runtime, { ...options, baseUrl: loaded.metadata.baseUrl });\n const session = await client.getDraftReview(loaded.metadata.reviewSessionId);\n const writes: Array<{ path: string; target: string; content: string; changed: boolean }> = [];\n for (const file of session.draftReview.files) {\n const content = await client.getFileContent({\n sessionId: loaded.metadata.reviewSessionId,\n fileId: file.id,\n });\n const targetRoot = options.output ? path.resolve(runtime.cwd, options.output) : root;\n const target = path.resolve(targetRoot, file.path);\n let current: string | null = null;\n try {\n current = await fs.readFile(target, \"utf8\");\n } catch {\n current = null;\n }\n writes.push({ path: file.path, target, content, changed: current !== content });\n }\n\n if (options.dryRun) {\n const changed = writes.filter((write) => write.changed).map((write) => write.path);\n if (options.json) {\n writeJson(runtime.stdout, { ok: true, changedFiles: changed });\n } else {\n writeText(runtime.stdout, changed.length ? changed.join(\"\\n\") : \"No remote changes.\");\n }\n return;\n }\n\n const changedWrites = writes.filter((write) => write.changed);\n if (changedWrites.length > 0 && !options.yes && !options.output) {\n throw new CliError(\n \"Pull would overwrite local files. Rerun with --yes, --backup, or --output <dir>.\",\n ExitCode.Safety,\n );\n }\n\n for (const write of writes) {\n if (!write.changed) {\n continue;\n }\n await fs.mkdir(path.dirname(write.target), { recursive: true });\n if (options.backup) {\n try {\n await fs.copyFile(write.target, `${write.target}.bak`);\n } catch {\n // No existing file to back up.\n }\n }\n await fs.writeFile(write.target, write.content, \"utf8\");\n }\n\n const nextTracked = loaded.metadata.trackedFiles.map((tracked) => {\n const write = writes.find((candidate) => candidate.path === tracked.path);\n return write\n ? {\n ...tracked,\n contentHash: contentHash(write.content),\n sizeBytes: Buffer.byteLength(write.content),\n }\n : tracked;\n });\n await saveSessionMetadata(loaded.filePath, { ...loaded.metadata, trackedFiles: nextTracked });\n\n if (options.json) {\n writeJson(runtime.stdout, { ok: true, filesWritten: changedWrites.length });\n } else {\n writeText(runtime.stdout, `Pulled ${changedWrites.length} file(s).`);\n }\n}\n\nexport async function openCommand(\n runtime: CommandRuntime,\n options: GlobalOptions & { session?: string },\n) {\n if (options.session) {\n const baseUrl = normalizeBaseUrl(options.baseUrl);\n await openOrPrint(runtime, `${baseUrl}/review/draft/${encodeURIComponent(options.session)}`);\n return;\n }\n const loaded = await loadSession(runtime, options);\n await openOrPrint(runtime, loaded.metadata.reviewUrl);\n}\n\nexport async function statusCommand(runtime: CommandRuntime, options: GlobalOptions) {\n const loaded = await loadSession(runtime, options);\n const root = sessionRoot(loaded.filePath, loaded.metadata);\n const current = await readTrackedFiles(root, loaded.metadata.trackedFiles);\n const changed = changedFiles(current, loaded.metadata.trackedFiles).map((file) => file.path);\n let openComments: number | null = null;\n try {\n const client = await makeClient(runtime, { ...options, baseUrl: loaded.metadata.baseUrl });\n openComments = (\n await client.listComments({ sessionId: loaded.metadata.reviewSessionId, status: \"open\" })\n ).threads.length;\n } catch {\n openComments = null;\n }\n const payload = { ...publicSessionJson(loaded.metadata), changedFiles: changed, openComments };\n if (options.json) {\n writeJson(runtime.stdout, payload);\n } else {\n writeText(\n runtime.stdout,\n [\n `Session: ${loaded.metadata.reviewSessionId}`,\n `URL: ${loaded.metadata.reviewUrl}`,\n `Base URL: ${loaded.metadata.baseUrl}`,\n `Tracked files: ${loaded.metadata.trackedFiles.length}`,\n `Last revision: ${loaded.metadata.lastKnownRevision ?? \"unknown\"}`,\n `Changed files: ${changed.length ? changed.join(\", \") : \"none\"}`,\n `Open comments: ${openComments ?? \"unknown\"}`,\n ].join(\"\\n\"),\n );\n }\n}\n\nexport async function sessionsCommand(runtime: CommandRuntime, options: GlobalOptions) {\n const client = await makeClient(runtime, options);\n const result = await client.listDraftReviews();\n if (options.json) {\n writeJson(runtime.stdout, result);\n } else {\n writeText(\n runtime.stdout,\n result.draftReviews\n .map((draft) => `${draft.id}\\t${draft.title}\\t${draft.reviewUrl}`)\n .join(\"\\n\") || \"No draft reviews found.\",\n );\n }\n}\n\nexport async function revisionsCommand(\n runtime: CommandRuntime,\n options: GlobalOptions & { session?: string },\n) {\n const loaded = options.session ? null : await loadSession(runtime, options);\n const sessionId = options.session ?? loaded?.metadata.reviewSessionId;\n if (!sessionId) {\n throw new CliError(\"A session id is required.\", ExitCode.Usage);\n }\n const client = await makeClient(runtime, {\n ...options,\n baseUrl: loaded?.metadata.baseUrl ?? options.baseUrl,\n });\n const result = await client.listRevisions(sessionId);\n if (options.json) {\n writeJson(runtime.stdout, result);\n } else {\n writeText(\n runtime.stdout,\n result.revisions\n .map(\n (revision) =>\n `#${revision.revisionNumber}\\t${revision.summary ?? \"\"}\\t${revision.createdAt ?? \"\"}`,\n )\n .join(\"\\n\") || \"No revisions found.\",\n );\n }\n}\n","export class CliError extends Error {\n readonly exitCode: number;\n\n constructor(message: string, exitCode = 1) {\n super(message);\n this.name = \"CliError\";\n this.exitCode = exitCode;\n }\n}\n\nexport const ExitCode = {\n Ok: 0,\n General: 1,\n Usage: 2,\n Auth: 3,\n Network: 4,\n Api: 5,\n Safety: 6,\n Timeout: 124,\n} as const;\n\nexport function toErrorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error);\n}\n","export type SseMessage = {\n id?: string | undefined;\n event?: string | undefined;\n data?: string | undefined;\n retry?: number | undefined;\n};\n\nexport class SseParser {\n private buffer = \"\";\n private id: string | undefined;\n private event: string | undefined;\n private dataLines: string[] = [];\n private retry: number | undefined;\n\n feed(chunk: string) {\n this.buffer += chunk;\n const messages: SseMessage[] = [];\n\n while (true) {\n const boundary = this.findBoundary();\n if (!boundary) {\n break;\n }\n const raw = this.buffer.slice(0, boundary.index);\n this.buffer = this.buffer.slice(boundary.index + boundary.length);\n const message = this.consumeBlock(raw);\n if (message) {\n messages.push(message);\n }\n }\n\n return messages;\n }\n\n flush() {\n if (!this.buffer.trim()) {\n this.buffer = \"\";\n return [];\n }\n const message = this.consumeBlock(this.buffer);\n this.buffer = \"\";\n return message ? [message] : [];\n }\n\n private findBoundary() {\n const candidates = [\n { index: this.buffer.indexOf(\"\\r\\n\\r\\n\"), length: 4 },\n { index: this.buffer.indexOf(\"\\n\\n\"), length: 2 },\n { index: this.buffer.indexOf(\"\\r\\r\"), length: 2 },\n ].filter((candidate) => candidate.index >= 0);\n return candidates.sort((a, b) => a.index - b.index)[0] ?? null;\n }\n\n private consumeBlock(raw: string): SseMessage | null {\n for (const line of raw.split(/\\r\\n|\\r|\\n/)) {\n this.consumeLine(line);\n }\n\n if (this.dataLines.length === 0) {\n this.event = undefined;\n this.dataLines = [];\n this.retry = undefined;\n return null;\n }\n\n const message: SseMessage = {\n id: this.id,\n event: this.event,\n data: this.dataLines.join(\"\\n\"),\n retry: this.retry,\n };\n this.event = undefined;\n this.dataLines = [];\n this.retry = undefined;\n return message;\n }\n\n private consumeLine(line: string) {\n if (!line || line.startsWith(\":\")) {\n return;\n }\n\n const separator = line.indexOf(\":\");\n const field = separator >= 0 ? line.slice(0, separator) : line;\n const value = separator >= 0 ? line.slice(separator + 1).replace(/^ /, \"\") : \"\";\n\n if (field === \"id\") {\n this.id = value;\n } else if (field === \"event\") {\n this.event = value;\n } else if (field === \"data\") {\n this.dataLines.push(value);\n } else if (field === \"retry\") {\n const retry = Number(value);\n if (Number.isInteger(retry) && retry >= 0) {\n this.retry = retry;\n }\n }\n }\n}\n","import { CliError, ExitCode } from \"./errors.js\";\nimport { SseParser } from \"./sse.js\";\nimport type {\n DraftFileInput,\n DraftReviewLiveEvent,\n DraftReviewRevision,\n DraftReviewSession,\n DraftThread,\n} from \"./types.js\";\n\nexport type FetchLike = typeof fetch;\n\ntype ApiClientOptions = {\n baseUrl: string;\n token?: string | null | undefined;\n fetchImpl?: FetchLike | undefined;\n};\n\ntype OAuthMetadata = {\n issuer: string;\n token_endpoint: string;\n device_authorization_endpoint: string;\n authorization_endpoint?: string;\n registration_endpoint?: string;\n};\n\nexport class CommentaryApiClient {\n readonly baseUrl: string;\n private readonly token: string | null;\n private readonly fetchImpl: FetchLike;\n\n constructor(options: ApiClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.token = options.token ?? null;\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n async getOAuthMetadata() {\n return this.rawJson<OAuthMetadata>(\"/.well-known/oauth-authorization-server\", { auth: false });\n }\n\n async requestDeviceCode(input: {\n clientId: string;\n clientName: string;\n scope: string;\n resource: string;\n }) {\n const metadata = await this.getOAuthMetadata();\n return this.rawJson<{\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n }>(metadata.device_authorization_endpoint, {\n auth: false,\n method: \"POST\",\n body: {\n client_id: input.clientId,\n client_name: input.clientName,\n scope: input.scope,\n resource: input.resource,\n },\n });\n }\n\n async exchangeDeviceCode(input: { deviceCode: string; resource: string }) {\n const metadata = await this.getOAuthMetadata();\n return this.rawJson<{\n access_token: string;\n refresh_token: string;\n token_type: \"Bearer\";\n expires_in: number;\n }>(metadata.token_endpoint, {\n auth: false,\n method: \"POST\",\n body: {\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n device_code: input.deviceCode,\n resource: input.resource,\n },\n });\n }\n\n async listDraftReviews() {\n return this.request<{ ok: true; draftReviews: DraftReviewSession[] }>(\"/api/v1/draft-reviews\");\n }\n\n async createDraftReview(input: {\n title: string;\n description?: string | null;\n files: DraftFileInput[];\n }) {\n return this.request<{\n ok: true;\n draftReview: DraftReviewSession;\n sessionId: string;\n reviewUrl: string;\n }>(\"/api/v1/draft-reviews\", {\n method: \"POST\",\n body: {\n title: input.title,\n description: input.description,\n sourceType: \"cli\",\n files: input.files.map((file) => ({\n path: file.path,\n content: file.content,\n contentType: file.contentType,\n })),\n },\n });\n }\n\n async getDraftReview(sessionId: string) {\n return this.request<{ ok: true; draftReview: DraftReviewSession }>(\n `/api/v1/draft-reviews/${encodeURIComponent(sessionId)}`,\n );\n }\n\n async createRevision(input: {\n sessionId: string;\n summary?: string | null;\n files: DraftFileInput[];\n }) {\n return this.request<{ ok: true; revision: DraftReviewRevision; noOp?: boolean }>(\n `/api/v1/draft-reviews/${encodeURIComponent(input.sessionId)}/revisions`,\n {\n method: \"POST\",\n body: {\n summary: input.summary,\n files: input.files.map((file) => ({\n fileId: file.fileId,\n path: file.path,\n content: file.content,\n contentType: file.contentType,\n })),\n },\n },\n );\n }\n\n async listRevisions(sessionId: string) {\n return this.request<{ ok: true; revisions: DraftReviewRevision[] }>(\n `/api/v1/draft-reviews/${encodeURIComponent(sessionId)}/revisions`,\n );\n }\n\n async listComments(input: {\n sessionId: string;\n status?: \"open\" | \"resolved\" | undefined;\n filePath?: string | undefined;\n fileId?: string | undefined;\n }) {\n const params = new URLSearchParams();\n if (input.status) {\n params.set(\"status\", input.status);\n }\n if (input.filePath) {\n params.set(\"filePath\", input.filePath);\n }\n if (input.fileId) {\n params.set(\"fileId\", input.fileId);\n }\n const suffix = params.size ? `?${params}` : \"\";\n return this.request<{ ok: true; threads: DraftThread[] }>(\n `/api/v1/draft-reviews/${encodeURIComponent(input.sessionId)}/comments${suffix}`,\n );\n }\n\n async replyToComment(input: { sessionId: string; threadId: string; bodyMarkdown: string }) {\n return this.request<{ ok: true; thread: DraftThread }>(\n `/api/v1/draft-reviews/${encodeURIComponent(input.sessionId)}/comments/${encodeURIComponent(input.threadId)}/replies`,\n {\n method: \"POST\",\n body: { bodyMarkdown: input.bodyMarkdown },\n },\n );\n }\n\n async updateCommentStatus(input: {\n sessionId: string;\n threadId: string;\n status: \"open\" | \"resolved\";\n }) {\n return this.request<{ ok: true; thread: DraftThread }>(\n `/api/v1/draft-reviews/${encodeURIComponent(input.sessionId)}/comments/${encodeURIComponent(input.threadId)}/status`,\n {\n method: \"POST\",\n body: { status: input.status },\n },\n );\n }\n\n async getFileContent(input: { sessionId: string; fileId: string }) {\n return this.rawText(\n `/api/v1/draft-reviews/${encodeURIComponent(input.sessionId)}/files/${encodeURIComponent(input.fileId)}/content`,\n { auth: true },\n );\n }\n\n async *streamDraftReviewEvents(input: {\n sessionId: string;\n cursor?: string | undefined;\n once?: boolean | undefined;\n signal?: AbortSignal | undefined;\n }): AsyncGenerator<DraftReviewLiveEvent> {\n const params = new URLSearchParams();\n if (input.cursor) {\n params.set(\"cursor\", input.cursor);\n }\n if (input.once) {\n params.set(\"once\", \"1\");\n }\n const suffix = params.size ? `?${params}` : \"\";\n const response = await this.doFetch(\n `/api/v1/draft-reviews/${encodeURIComponent(input.sessionId)}/events${suffix}`,\n { auth: true, accept: \"text/event-stream\", signal: input.signal },\n );\n if (!response.ok) {\n await this.throwApiError(response);\n }\n if (!response.body) {\n throw new CliError(\"Commentary event stream did not include a response body.\", ExitCode.Api);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const parser = new SseParser();\n let completed = false;\n try {\n while (true) {\n const { done, value } = await reader.read();\n completed = done;\n const messages = done\n ? parser.flush()\n : parser.feed(decoder.decode(value, { stream: true }));\n for (const message of messages) {\n if (message.event && message.event !== \"draft-review\") {\n continue;\n }\n if (!message.data) {\n continue;\n }\n yield JSON.parse(message.data) as DraftReviewLiveEvent;\n }\n if (done) {\n break;\n }\n }\n } catch (error) {\n if (input.signal?.aborted) {\n return;\n }\n throw new CliError(\n error instanceof Error ? error.message : \"Commentary event stream failed.\",\n ExitCode.Network,\n );\n } finally {\n if (!completed) {\n await reader.cancel().catch(() => undefined);\n }\n reader.releaseLock();\n }\n }\n\n private async request<T>(pathOrUrl: string, init?: { method?: string; body?: unknown }) {\n return this.rawJson<T>(pathOrUrl, { ...init, auth: true });\n }\n\n private async rawText(\n pathOrUrl: string,\n init: { auth: boolean; method?: string; body?: unknown },\n ) {\n const response = await this.doFetch(pathOrUrl, init);\n if (!response.ok) {\n await this.throwApiError(response);\n }\n return response.text();\n }\n\n private async rawJson<T>(\n pathOrUrl: string,\n init: { auth: boolean; method?: string; body?: unknown },\n ) {\n const response = await this.doFetch(pathOrUrl, init);\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n const payload = contentType.includes(\"application/json\")\n ? ((await response.json()) as unknown)\n : null;\n if (!response.ok) {\n this.throwPayloadError(response.status, payload);\n }\n return payload as T;\n }\n\n private async doFetch(\n pathOrUrl: string,\n init: {\n auth: boolean;\n method?: string;\n body?: unknown;\n accept?: string;\n signal?: AbortSignal | undefined;\n },\n ) {\n const url =\n pathOrUrl.startsWith(\"http://\") || pathOrUrl.startsWith(\"https://\")\n ? pathOrUrl\n : `${this.baseUrl}${pathOrUrl}`;\n const headers: Record<string, string> = {\n accept: init.accept ?? \"application/json\",\n };\n let body: string | undefined;\n if (init.body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n body = JSON.stringify(init.body);\n }\n if (init.auth) {\n if (!this.token) {\n throw new CliError(\n \"Authentication is required. Run commentary login or set COMMENTARY_TOKEN.\",\n ExitCode.Auth,\n );\n }\n headers.authorization = `Bearer ${this.token}`;\n }\n try {\n const requestInit: RequestInit = {\n method: init.method ?? \"GET\",\n headers,\n };\n if (init.signal) {\n requestInit.signal = init.signal;\n }\n if (body !== undefined) {\n requestInit.body = body;\n }\n return await this.fetchImpl(url, requestInit);\n } catch (error) {\n throw new CliError(\n error instanceof Error ? error.message : \"Network request failed.\",\n ExitCode.Network,\n );\n }\n }\n\n private async throwApiError(response: Response): Promise<never> {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"application/json\")) {\n this.throwPayloadError(response.status, await response.json());\n }\n throw new CliError(\n `Commentary API returned ${response.status}.`,\n response.status === 401 ? ExitCode.Auth : ExitCode.Api,\n );\n }\n\n private throwPayloadError(status: number, payload: unknown): never {\n const body =\n payload && typeof payload === \"object\"\n ? (payload as { error?: unknown; error_description?: unknown })\n : {};\n const message =\n typeof body.error === \"string\"\n ? body.error\n : typeof body.error_description === \"string\"\n ? body.error_description\n : `Commentary API returned ${status}.`;\n throw new CliError(message, status === 401 || status === 403 ? ExitCode.Auth : ExitCode.Api);\n }\n}\n","export const DEFAULT_BASE_URL = \"https://commentary.dev\";\nexport const SESSION_FILE = \".commentary/session.json\";\nexport const PACKAGE_NAME = \"@commentary-dev/cli\";\nexport const CLIENT_ID = \"commentary-cli\";\nexport const CLIENT_NAME = \"Commentary CLI\";\n\nexport const REQUIRED_SCOPES = [\n \"commentary.review.read\",\n \"commentary.comments.read\",\n \"commentary.comments.write\",\n \"commentary.comments.status\",\n] as const;\n\nexport const SUPPORTED_EXTENSIONS = [\".md\", \".markdown\", \".mdx\", \".html\", \".htm\", \".txt\"] as const;\nexport const DEFAULT_IGNORES = [\n \"**/.git/**\",\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/.nuxt/**\",\n \"**/coverage/**\",\n \"**/.commentary/**\",\n \"**/.DS_Store\",\n] as const;\n\nexport const DRAFT_REVIEW_MAX_FILES = 20;\nexport const DRAFT_REVIEW_MAX_FILE_BYTES = 512 * 1024;\nexport const DRAFT_REVIEW_MAX_TOTAL_BYTES = 2 * 1024 * 1024;\n","import fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { DEFAULT_BASE_URL } from \"./constants.js\";\n\ntype StoredToken = {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: string;\n};\n\ntype StoredConfig = {\n tokens?: Record<string, StoredToken>;\n};\n\nfunction configDir() {\n if (process.env.COMMENTARY_CONFIG_DIR) {\n return process.env.COMMENTARY_CONFIG_DIR;\n }\n if (process.platform === \"win32\" && process.env.APPDATA) {\n return path.join(process.env.APPDATA, \"commentary\");\n }\n if (process.env.XDG_CONFIG_HOME) {\n return path.join(process.env.XDG_CONFIG_HOME, \"commentary\");\n }\n return path.join(os.homedir(), \".config\", \"commentary\");\n}\n\nexport function configPath() {\n return path.join(configDir(), \"config.json\");\n}\n\nasync function readConfig(): Promise<StoredConfig> {\n try {\n return JSON.parse(await fs.readFile(configPath(), \"utf8\")) as StoredConfig;\n } catch {\n return {};\n }\n}\n\nasync function writeConfig(config: StoredConfig) {\n await fs.mkdir(configDir(), { recursive: true, mode: 0o700 });\n await fs.writeFile(configPath(), `${JSON.stringify(config, null, 2)}\\n`, {\n encoding: \"utf8\",\n mode: 0o600,\n });\n}\n\nexport function normalizeBaseUrl(baseUrl: string | undefined | null) {\n const value = baseUrl?.trim() || process.env.COMMENTARY_BASE_URL || DEFAULT_BASE_URL;\n const url = new URL(value);\n url.hash = \"\";\n url.search = \"\";\n return url.toString().replace(/\\/$/, \"\");\n}\n\nexport async function getStoredToken(baseUrl: string) {\n const config = await readConfig();\n return config.tokens?.[normalizeBaseUrl(baseUrl)] ?? null;\n}\n\nexport async function setStoredToken(baseUrl: string, token: StoredToken) {\n const config = await readConfig();\n config.tokens ??= {};\n config.tokens[normalizeBaseUrl(baseUrl)] = token;\n await writeConfig(config);\n}\n\nexport async function removeStoredToken(baseUrl: string) {\n const config = await readConfig();\n if (config.tokens) {\n delete config.tokens[normalizeBaseUrl(baseUrl)];\n }\n await writeConfig(config);\n}\n\nexport async function resolveToken(input: { baseUrl: string; token?: string | null | undefined }) {\n if (input.token?.trim()) {\n return input.token.trim();\n }\n if (process.env.COMMENTARY_TOKEN?.trim()) {\n return process.env.COMMENTARY_TOKEN.trim();\n }\n const stored = await getStoredToken(input.baseUrl);\n return stored?.accessToken ?? null;\n}\n","import path from \"node:path\";\nimport { CliError, ExitCode } from \"./errors.js\";\nimport type { DraftContentType, RequestedContentType } from \"./types.js\";\n\nconst MARKDOWN_EXTENSIONS = new Set([\".md\", \".markdown\", \".mdx\"]);\nconst HTML_EXTENSIONS = new Set([\".html\", \".htm\"]);\nconst PLAIN_EXTENSIONS = new Set([\".txt\"]);\nconst SUPPORTED_EXTENSIONS = new Set([\n ...MARKDOWN_EXTENSIONS,\n ...HTML_EXTENSIONS,\n ...PLAIN_EXTENSIONS,\n]);\n\nexport function normalizeSlashes(value: string) {\n return value.replaceAll(\"\\\\\", \"/\");\n}\n\nexport function normalizeReviewPath(filePath: string) {\n const normalized = normalizeSlashes(filePath).trim().replace(/^\\/+/, \"\");\n if (!normalized) {\n throw new CliError(\"Draft review file path is required.\", ExitCode.Usage);\n }\n if (\n /^[a-z]:\\//iu.test(normalized) ||\n filePath.trim().startsWith(\"/\") ||\n filePath.trim().startsWith(\"\\\\\")\n ) {\n throw new CliError(\"Draft review file paths must be relative.\", ExitCode.Usage);\n }\n if (normalized.split(\"/\").some((segment) => !segment || segment === \".\" || segment === \"..\")) {\n throw new CliError(\n \"Draft review file paths must not contain empty, current, or parent directory segments.\",\n ExitCode.Usage,\n );\n }\n return normalized;\n}\n\nexport function getPathExtension(filePath: string) {\n return path.posix.extname(normalizeSlashes(filePath)).toLowerCase();\n}\n\nexport function isSupportedPath(filePath: string) {\n return SUPPORTED_EXTENSIONS.has(getPathExtension(filePath));\n}\n\nexport function isLikelyHtml(content: string) {\n const trimmed = content.trimStart().toLowerCase();\n return (\n trimmed.startsWith(\"<!doctype html\") ||\n trimmed.startsWith(\"<html\") ||\n /<(head|body|main|article|section|div|p|h[1-6]|table|ul|ol)\\b[^>]*>[\\s\\S]*<\\/\\1>/iu.test(\n content,\n )\n );\n}\n\nexport function contentTypeFromPath(filePath: string): DraftContentType | null {\n const extension = getPathExtension(filePath);\n if (MARKDOWN_EXTENSIONS.has(extension)) {\n return \"markdown\";\n }\n if (HTML_EXTENSIONS.has(extension)) {\n return \"html\";\n }\n if (PLAIN_EXTENSIONS.has(extension)) {\n return \"plain_text\";\n }\n return null;\n}\n\nexport function detectContentType(input: {\n filePath: string;\n content: string;\n requested?: RequestedContentType | undefined;\n}): DraftContentType {\n const requested = input.requested ?? \"auto\";\n if (requested !== \"auto\") {\n if (![\"markdown\", \"html\", \"plain_text\"].includes(requested)) {\n throw new CliError(\"Choose a supported draft content type.\", ExitCode.Usage);\n }\n return requested;\n }\n\n const fromPath = contentTypeFromPath(input.filePath);\n if (fromPath) {\n return fromPath;\n }\n return isLikelyHtml(input.content) ? \"html\" : \"markdown\";\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport fg from \"fast-glob\";\nimport {\n DEFAULT_IGNORES,\n DRAFT_REVIEW_MAX_FILE_BYTES,\n DRAFT_REVIEW_MAX_FILES,\n DRAFT_REVIEW_MAX_TOTAL_BYTES,\n SUPPORTED_EXTENSIONS,\n} from \"./constants.js\";\nimport {\n detectContentType,\n isSupportedPath,\n normalizeReviewPath,\n normalizeSlashes,\n} from \"./content.js\";\nimport { CliError, ExitCode } from \"./errors.js\";\nimport { contentHash } from \"./hash.js\";\nimport type { DraftFileInput, RequestedContentType, TrackedFile } from \"./types.js\";\n\nexport type CollectOptions = {\n root: string;\n include?: string[] | undefined;\n exclude?: string[] | undefined;\n requestedContentType?: RequestedContentType | undefined;\n};\n\nexport type CollectedFile = DraftFileInput & {\n absolutePath: string;\n contentHash: string;\n sizeBytes: number;\n};\n\nfunction toPosixRelative(root: string, absolutePath: string) {\n const relative = path.relative(root, absolutePath);\n if (!relative || relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new CliError(`Path is outside the review root: ${absolutePath}`, ExitCode.Usage);\n }\n return normalizeReviewPath(relative);\n}\n\nasync function readUtf8File(absolutePath: string) {\n const bytes = await fs.readFile(absolutePath);\n const content = bytes.toString(\"utf8\");\n if (content.includes(\"\\u0000\")) {\n throw new CliError(\n `File must be UTF-8 text, not binary content: ${absolutePath}`,\n ExitCode.Usage,\n );\n }\n return content;\n}\n\nasync function collectPathEntries(inputPaths: string[], options: CollectOptions) {\n const root = path.resolve(options.root);\n const entries = new Set<string>();\n const includeExtensions = SUPPORTED_EXTENSIONS.map((extension) => extension.replace(\".\", \"\"));\n\n for (const inputPath of inputPaths) {\n const absolute = path.resolve(root, inputPath);\n let stat;\n try {\n stat = await fs.stat(absolute);\n } catch {\n throw new CliError(`Path does not exist: ${inputPath}`, ExitCode.Usage);\n }\n\n if (stat.isDirectory()) {\n const relativeDir = normalizeSlashes(path.relative(root, absolute)) || \".\";\n const patterns = options.include?.length\n ? options.include.map((pattern) => normalizeSlashes(path.posix.join(relativeDir, pattern)))\n : [`${relativeDir === \".\" ? \"\" : `${relativeDir}/`}**/*.{${includeExtensions.join(\",\")}}`];\n const matches = await fg(patterns, {\n cwd: root,\n onlyFiles: true,\n dot: false,\n ignore: [...DEFAULT_IGNORES, ...(options.exclude ?? [])],\n });\n matches.forEach((match) => entries.add(path.resolve(root, match)));\n continue;\n }\n\n if (stat.isFile()) {\n if (!isSupportedPath(absolute)) {\n throw new CliError(`Unsupported file type: ${inputPath}`, ExitCode.Usage);\n }\n entries.add(absolute);\n }\n }\n\n return [...entries].sort((left, right) => left.localeCompare(right));\n}\n\nexport async function collectFiles(\n inputPaths: string[],\n options: CollectOptions,\n): Promise<CollectedFile[]> {\n if (inputPaths.length === 0) {\n throw new CliError(\"At least one path is required.\", ExitCode.Usage);\n }\n\n const root = path.resolve(options.root);\n const absolutePaths = await collectPathEntries(inputPaths, options);\n if (absolutePaths.length === 0) {\n throw new CliError(\"No supported files were found.\", ExitCode.Usage);\n }\n if (absolutePaths.length > DRAFT_REVIEW_MAX_FILES) {\n throw new CliError(\n `Draft reviews support up to ${DRAFT_REVIEW_MAX_FILES} files per revision.`,\n ExitCode.Usage,\n );\n }\n\n let totalBytes = 0;\n const collected: CollectedFile[] = [];\n for (const absolutePath of absolutePaths) {\n const content = await readUtf8File(absolutePath);\n const sizeBytes = Buffer.byteLength(content);\n if (sizeBytes > DRAFT_REVIEW_MAX_FILE_BYTES) {\n throw new CliError(\n `Draft review file exceeds ${DRAFT_REVIEW_MAX_FILE_BYTES} bytes: ${absolutePath}`,\n ExitCode.Usage,\n );\n }\n totalBytes += sizeBytes;\n if (totalBytes > DRAFT_REVIEW_MAX_TOTAL_BYTES) {\n throw new CliError(\n `Draft review revisions support up to ${DRAFT_REVIEW_MAX_TOTAL_BYTES} total bytes.`,\n ExitCode.Usage,\n );\n }\n const reviewPath = toPosixRelative(root, absolutePath);\n const contentType = detectContentType({\n filePath: reviewPath,\n content,\n requested: options.requestedContentType,\n });\n collected.push({\n absolutePath,\n path: reviewPath,\n content,\n contentType,\n contentHash: contentHash(content),\n sizeBytes,\n });\n }\n\n return collected;\n}\n\nexport async function readTrackedFiles(\n root: string,\n trackedFiles: TrackedFile[],\n): Promise<CollectedFile[]> {\n const collected: CollectedFile[] = [];\n for (const tracked of trackedFiles) {\n const absolutePath = path.resolve(root, tracked.path);\n const content = await readUtf8File(absolutePath);\n const sizeBytes = Buffer.byteLength(content);\n collected.push({\n absolutePath,\n path: tracked.path,\n fileId: tracked.fileId,\n content,\n contentType: tracked.contentType,\n contentHash: contentHash(content),\n sizeBytes,\n });\n }\n return collected;\n}\n\nexport function toTrackedFiles(\n files: CollectedFile[],\n apiFiles?: Array<{\n fileId: string;\n path: string;\n contentHash: string;\n sizeBytes: number;\n contentType: string;\n }>,\n): TrackedFile[] {\n const apiByPath = new Map(apiFiles?.map((file) => [file.path, file]) ?? []);\n return files.map((file) => {\n const apiFile = apiByPath.get(file.path);\n return {\n path: file.path,\n fileId: apiFile?.fileId ?? file.fileId,\n contentType: file.contentType,\n contentHash: apiFile?.contentHash ?? file.contentHash,\n sizeBytes: apiFile?.sizeBytes ?? file.sizeBytes,\n };\n });\n}\n","import { createHash } from \"node:crypto\";\n\nexport function contentHash(content: string) {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n","import type {\n DraftReviewLiveEvent,\n DraftReviewRevision,\n DraftReviewSession,\n DraftThread,\n JsonObject,\n SessionMetadata,\n} from \"./types.js\";\n\nexport type Writer = {\n write(chunk: string): void;\n};\n\nexport function writeJson(stdout: Writer, value: unknown) {\n stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nexport function writeText(stdout: Writer, value: string) {\n stdout.write(`${value.trimEnd()}\\n`);\n}\n\nexport function formatReviewCreated(input: {\n draftReview: DraftReviewSession;\n sessionFilePath: string;\n fileCount: number;\n}) {\n return [\n \"Created Commentary review\",\n \"\",\n `Title: ${input.draftReview.title}`,\n `Files: ${input.fileCount}`,\n `Session: ${input.draftReview.id}`,\n `URL: ${input.draftReview.reviewUrl}`,\n \"\",\n `Saved local session metadata to ${input.sessionFilePath}`,\n ].join(\"\\n\");\n}\n\nexport function formatRevision(input: {\n metadata: SessionMetadata;\n revision: DraftReviewRevision;\n uploaded: number;\n noOp?: boolean | undefined;\n}) {\n return [\n input.noOp ? \"No changes to sync\" : \"Synced Commentary review\",\n \"\",\n `Session: ${input.metadata.reviewSessionId}`,\n `Revision: ${input.revision.revisionNumber}`,\n `Files uploaded: ${input.uploaded}`,\n `URL: ${input.metadata.reviewUrl}`,\n ].join(\"\\n\");\n}\n\nfunction commentBody(thread: DraftThread) {\n const first = thread.comments[0];\n return first?.bodyMarkdown ?? first?.body ?? \"\";\n}\n\nfunction commentAuthor(thread: DraftThread) {\n const first = thread.comments[0];\n return first?.authorLogin ?? first?.author ?? \"Unknown\";\n}\n\nexport function formatCommentsText(threads: DraftThread[]) {\n if (threads.length === 0) {\n return \"No comments found.\";\n }\n return threads\n .map((thread) =>\n [\n `[${thread.id}] ${thread.filePath}`,\n `Status: ${thread.status}`,\n thread.selectedText ? `Anchor: \"${thread.selectedText}\"` : null,\n `${commentAuthor(thread)}: ${commentBody(thread)}`,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n )\n .join(\"\\n\\n\");\n}\n\nexport function formatCommentsMarkdown(input: {\n session: SessionMetadata;\n threads: DraftThread[];\n}) {\n const lines = [\n \"# Commentary Review Comments\",\n \"\",\n `Session: ${input.session.reviewSessionId}`,\n `URL: ${input.session.reviewUrl}`,\n \"\",\n ];\n if (input.threads.length === 0) {\n lines.push(\"No comments found.\");\n return lines.join(\"\\n\");\n }\n for (const thread of input.threads) {\n lines.push(`## Comment ${thread.id}`, \"\");\n lines.push(`File: ${thread.filePath}`);\n lines.push(`Status: ${thread.status}`);\n if (thread.selectedText) {\n lines.push(`Anchor: \"${thread.selectedText}\"`);\n }\n if (thread.sourceLineStart) {\n lines.push(\n `Lines: ${thread.sourceLineStart}${thread.sourceLineEnd && thread.sourceLineEnd !== thread.sourceLineStart ? `-${thread.sourceLineEnd}` : \"\"}`,\n );\n }\n lines.push(\"\", \"User comment:\", `> ${commentBody(thread).replace(/\\n/g, \"\\n> \")}`, \"\");\n const replies = thread.comments.slice(1);\n if (replies.length > 0) {\n lines.push(\"Replies:\");\n replies.forEach((reply) => {\n lines.push(\n `- ${reply.authorLogin ?? reply.author ?? \"Unknown\"}: ${reply.bodyMarkdown ?? reply.body ?? \"\"}`,\n );\n });\n lines.push(\"\");\n }\n }\n return lines.join(\"\\n\").trimEnd();\n}\n\nexport function formatWaitCommentText(event: DraftReviewLiveEvent) {\n if (!event.thread) {\n return `Received ${event.type} (${event.id}).`;\n }\n const thread = event.thread;\n const body = commentBody(thread);\n return [\n `[${thread.id}] ${thread.filePath}`,\n `Event: ${event.type}`,\n `Status: ${thread.status}`,\n thread.selectedText ? `Anchor: \"${thread.selectedText}\"` : null,\n `${commentAuthor(thread)}: ${body}`,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nexport function formatWaitCommentMarkdown(input: {\n session: SessionMetadata;\n event: DraftReviewLiveEvent;\n}) {\n const lines = [\n \"# Commentary Comment\",\n \"\",\n `Session: ${input.session.reviewSessionId}`,\n `URL: ${input.session.reviewUrl}`,\n `Event: ${input.event.type}`,\n `Cursor: ${input.event.id}`,\n \"\",\n ];\n if (!input.event.thread) {\n lines.push(\"No thread payload was available for this event.\");\n return lines.join(\"\\n\");\n }\n lines.push(formatCommentsMarkdown({ session: input.session, threads: [input.event.thread] }));\n return lines.join(\"\\n\").trimEnd();\n}\n\nexport function publicSessionJson(metadata: SessionMetadata): JsonObject {\n return {\n reviewSessionId: metadata.reviewSessionId,\n reviewUrl: metadata.reviewUrl,\n baseUrl: metadata.baseUrl,\n rootPath: metadata.rootPath,\n trackedFiles: metadata.trackedFiles,\n createdAt: metadata.createdAt,\n lastSyncedAt: metadata.lastSyncedAt,\n lastKnownRevision: metadata.lastKnownRevision,\n };\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { SESSION_FILE } from \"./constants.js\";\nimport { CliError, ExitCode } from \"./errors.js\";\nimport type { SessionMetadata } from \"./types.js\";\n\nasync function pathExists(filePath: string) {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function findSessionFile(startDir: string, explicitPath?: string) {\n if (explicitPath) {\n return path.resolve(startDir, explicitPath);\n }\n\n let current = path.resolve(startDir);\n while (true) {\n const candidate = path.join(current, SESSION_FILE);\n if (await pathExists(candidate)) {\n return candidate;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return path.resolve(startDir, SESSION_FILE);\n }\n current = parent;\n }\n}\n\nexport async function loadSessionMetadata(startDir: string, explicitPath?: string) {\n const filePath = await findSessionFile(startDir, explicitPath);\n let raw;\n try {\n raw = await fs.readFile(filePath, \"utf8\");\n } catch {\n throw new CliError(\n `No Commentary session metadata found at ${filePath}. Run commentary review first.`,\n ExitCode.Usage,\n );\n }\n\n const metadata = JSON.parse(raw) as SessionMetadata;\n return {\n filePath,\n metadata,\n };\n}\n\nexport async function saveSessionMetadata(filePath: string, metadata: SessionMetadata) {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, `${JSON.stringify(metadata, null, 2)}\\n`, {\n encoding: \"utf8\",\n mode: 0o644,\n });\n}\n\nexport function sessionRoot(sessionFilePath: string, metadata: SessionMetadata) {\n return path.resolve(path.dirname(sessionFilePath), metadata.rootPath);\n}\n","#!/usr/bin/env node\nimport { runCli } from \"./cli.js\";\n\nconst exitCode = await runCli();\nif (exitCode !== 0) {\n process.exitCode = exitCode;\n}\n"],"mappings":"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","names":["fs","path","exitCode","path","SUPPORTED_EXTENSIONS","path","fs","path","path","fs","fs","path","fs","path","path","fs"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@commentary-dev/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Command-line companion for Commentary draft review sessions.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"commentary": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=22"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "tsx src/index.ts",
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"lint": "eslint .",
|
|
23
|
+
"public:check": "node scripts/public-readiness-check.mjs",
|
|
24
|
+
"format:check": "prettier --check .",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:unit": "vitest run",
|
|
27
|
+
"test:integration": "vitest run test/api-client.test.ts test/commands.test.ts",
|
|
28
|
+
"test:live": "tsx scripts/live-smoke.ts",
|
|
29
|
+
"pack:smoke": "npm pack --dry-run",
|
|
30
|
+
"verify": "npm run public:check && npm run typecheck && npm run lint && npm run format:check && npm run test && npm run build && npm run pack:smoke"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"chokidar": "^4.0.3",
|
|
34
|
+
"commander": "^14.0.2",
|
|
35
|
+
"fast-glob": "^3.3.3",
|
|
36
|
+
"open": "^10.2.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@eslint/js": "^9.39.1",
|
|
40
|
+
"@types/node": "^24.10.1",
|
|
41
|
+
"eslint": "^9.39.1",
|
|
42
|
+
"prettier": "^3.6.2",
|
|
43
|
+
"tsup": "^8.5.0",
|
|
44
|
+
"tsx": "^4.20.6",
|
|
45
|
+
"typescript": "^5.9.3",
|
|
46
|
+
"typescript-eslint": "^8.46.4",
|
|
47
|
+
"vitest": "^4.0.14"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/commentary-dev/commentary-cli.git"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public",
|
|
55
|
+
"provenance": true
|
|
56
|
+
}
|
|
57
|
+
}
|