cngkit 1.1.20 → 1.1.22
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 +198 -4
- package/README.md +8 -12
- package/dist/{chunk-NGEWD4BW.js → chunk-25Q463MH.js} +1 -2
- package/dist/{chunk-SMTQ3W3F.js → chunk-3BATDTKU.js} +131 -112
- package/dist/chunk-3BATDTKU.js.map +1 -0
- package/dist/chunk-AS7FIJWP.js +88 -0
- package/dist/chunk-AS7FIJWP.js.map +1 -0
- package/dist/chunk-BRFWVQI4.js +18 -0
- package/dist/chunk-BRFWVQI4.js.map +1 -0
- package/dist/{chunk-WDI43VPW.js → chunk-DCW4RKLC.js} +63 -234
- package/dist/chunk-DCW4RKLC.js.map +1 -0
- package/dist/{chunk-SKK2XLRZ.js → chunk-JNHW72SU.js} +21 -15
- package/dist/chunk-JNHW72SU.js.map +1 -0
- package/dist/{chunk-E2GLGGKO.js → chunk-KURN5BJ6.js} +300 -143
- package/dist/chunk-KURN5BJ6.js.map +1 -0
- package/dist/{chunk-CIZBVLN5.js → chunk-N255PYL7.js} +2 -2
- package/dist/chunk-N255PYL7.js.map +1 -0
- package/dist/chunk-NLAANOBW.js +67 -0
- package/dist/chunk-NLAANOBW.js.map +1 -0
- package/dist/chunk-TIY4RTXC.js +268 -0
- package/dist/chunk-TIY4RTXC.js.map +1 -0
- package/dist/chunk-VMTXY4KQ.js +111 -0
- package/dist/chunk-VMTXY4KQ.js.map +1 -0
- package/dist/chunk-YALWTRIP.js +102 -0
- package/dist/chunk-YALWTRIP.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/coderoom/index.js +4 -4
- package/dist/commands/coderoom/join.js +5 -5
- package/dist/commands/coderoom/share.js +8 -11
- package/dist/commands/coderoom/share.js.map +1 -1
- package/dist/commands/hookify/index.js +4 -4
- package/dist/commands/hookify/ingest.js +4 -4
- package/dist/commands/hooks/index.js +4 -4
- package/dist/commands/hooks/install.js +4 -4
- package/dist/commands/hooks/uninstall.js +4 -4
- package/dist/commands/index.js +3 -3
- package/dist/commands/knowledges/audiences.js +26 -8
- package/dist/commands/knowledges/audiences.js.map +1 -1
- package/dist/commands/knowledges/cat.js +26 -7
- package/dist/commands/knowledges/cat.js.map +1 -1
- package/dist/commands/knowledges/files.js +39 -8
- package/dist/commands/knowledges/files.js.map +1 -1
- package/dist/commands/knowledges/find.js +48 -8
- package/dist/commands/knowledges/find.js.map +1 -1
- package/dist/commands/knowledges/glob.js +41 -8
- package/dist/commands/knowledges/glob.js.map +1 -1
- package/dist/commands/knowledges/grep.js +73 -8
- package/dist/commands/knowledges/grep.js.map +1 -1
- package/dist/commands/knowledges/head.js +31 -8
- package/dist/commands/knowledges/head.js.map +1 -1
- package/dist/commands/knowledges/index.js +4 -4
- package/dist/commands/knowledges/list.js +39 -8
- package/dist/commands/knowledges/list.js.map +1 -1
- package/dist/commands/knowledges/ls.js +47 -8
- package/dist/commands/knowledges/ls.js.map +1 -1
- package/dist/commands/knowledges/read.js +46 -8
- package/dist/commands/knowledges/read.js.map +1 -1
- package/dist/commands/knowledges/realpath.js +23 -8
- package/dist/commands/knowledges/realpath.js.map +1 -1
- package/dist/commands/knowledges/search.js +34 -8
- package/dist/commands/knowledges/search.js.map +1 -1
- package/dist/commands/knowledges/stat.js +32 -8
- package/dist/commands/knowledges/stat.js.map +1 -1
- package/dist/commands/knowledges/status.js +26 -8
- package/dist/commands/knowledges/status.js.map +1 -1
- package/dist/commands/knowledges/tail.js +30 -8
- package/dist/commands/knowledges/tail.js.map +1 -1
- package/dist/commands/knowledges/tree.js +38 -8
- package/dist/commands/knowledges/tree.js.map +1 -1
- package/dist/commands/login.js +3 -3
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/scrub.js +3 -3
- package/dist/commands/scrub.js.map +1 -1
- package/dist/commands/transcripts.js +137 -119
- package/dist/commands/transcripts.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-CIZBVLN5.js.map +0 -1
- package/dist/chunk-E2GLGGKO.js.map +0 -1
- package/dist/chunk-MRXGD6TC.js +0 -42
- package/dist/chunk-MRXGD6TC.js.map +0 -1
- package/dist/chunk-NODJM6SH.js +0 -658
- package/dist/chunk-NODJM6SH.js.map +0 -1
- package/dist/chunk-SKK2XLRZ.js.map +0 -1
- package/dist/chunk-SMTQ3W3F.js.map +0 -1
- package/dist/chunk-WDI43VPW.js.map +0 -1
- /package/dist/{chunk-NGEWD4BW.js.map → chunk-25Q463MH.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/coderoom/run-coderoom-command.ts","../src/features/coderoom/sync/client.ts","../src/features/coderoom/sync/files.ts","../src/features/coderoom/sync/paths.ts","../src/features/coderoom/sync/local-events.ts","../src/features/coderoom/sync/session.ts","../src/features/coderoom/sync/protocol.ts","../src/features/coderoom/sync/remote-handler.ts"],"sourcesContent":["import process from \"node:process\";\n\nimport { createCngApiClient, readBackendHealth } from \"../../shared/api-client.js\";\nimport { resolveApiBaseUrl, type GlobalCommandOptions } from \"../../shared/config.js\";\nimport type { CommandOutput } from \"../../shared/output/types.js\";\nimport { startSyncSession, type SyncSessionRole } from \"./sync/client.js\";\n\nexport type CoderoomCommandOptions = GlobalCommandOptions;\n\nexport type ShareCommandOptions = GlobalCommandOptions;\n\nexport async function runCoderoomCommand(\n args: string[] | undefined,\n options: CoderoomCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const [subcommand, ...subcommandArgs] = args ?? [];\n\n switch (subcommand) {\n case \"share\":\n return runShareCommand(options, output);\n case \"join\":\n return runJoinCommand(subcommandArgs[0], options, output);\n default:\n throw new Error(\"Missing coderoom command. Usage: cngkit coderoom <share|join>\");\n }\n}\n\nexport async function runShareCommand(\n options: ShareCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const room = await createCoderoomRoom(options);\n\n output.success(`Share code: ${room.roomCode}`);\n await printBackendStatus(options, output);\n await runSyncSession(\"host\", room.roomCode, room.creatorToken, options, output);\n}\n\nexport async function runJoinCommand(\n roomCode: string | undefined,\n options: GlobalCommandOptions,\n output: CommandOutput\n): Promise<void> {\n if (!roomCode) {\n throw new Error(\"Missing room code. Usage: cngkit coderoom join <room-code>\");\n }\n\n await printBackendStatus(options, output);\n await runSyncSession(\"guest\", roomCode, undefined, options, output);\n}\n\nasync function printBackendStatus(\n options: GlobalCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const health = await readBackendHealth(options);\n if (health.ok) {\n output.success(`API: ${health.service} ready`);\n return;\n }\n\n output.warning(`API: unavailable (${health.message})`);\n}\n\nasync function runSyncSession(\n role: SyncSessionRole,\n roomCode: string,\n creatorToken: string | undefined,\n options: GlobalCommandOptions,\n output: CommandOutput\n): Promise<void> {\n await startSyncSession({\n apiBaseUrl: resolveApiBaseUrl(options),\n roomCode,\n creatorToken,\n role,\n cwd: process.cwd(),\n output,\n });\n}\n\nasync function createCoderoomRoom(options: GlobalCommandOptions): Promise<{\n roomCode: string;\n creatorToken: string;\n}> {\n const client = createCngApiClient(options);\n return client.coderoom.createCoderoomRoom();\n}\n","// Public API entrypoint for the coderoom sync client. Implementation lives in\n// `./session.ts` (WebSocket lifecycle), `./local-events.ts` (file watcher +\n// outbound events), and `./remote-handler.ts` (inbound message dispatch).\n\nimport WebSocket from \"ws\";\n\nimport { createSuppressionTracker } from \"./files.js\";\nimport {\n createRepoWatcher,\n sendInitialSnapshot,\n type WatcherContext,\n} from \"./local-events.js\";\nimport { resolveRepoContext } from \"./paths.js\";\nimport { handleServerMessage } from \"./remote-handler.js\";\nimport { createSyncWebSocketUrl, waitForSessionClose } from \"./session.js\";\nimport type { CommandOutput } from \"../../../shared/output/types.js\";\n\nexport type SyncSessionRole = \"host\" | \"guest\";\n\nexport type StartSyncSessionOptions = {\n apiBaseUrl: string;\n roomCode: string;\n creatorToken?: string;\n role: SyncSessionRole;\n cwd: string;\n output: CommandOutput;\n};\n\nexport async function startSyncSession(options: StartSyncSessionOptions): Promise<void> {\n const repoContext = await resolveRepoContext(options.cwd);\n const suppressionTracker = createSuppressionTracker();\n const webSocketUrl = createSyncWebSocketUrl(options);\n const socket = new WebSocket(webSocketUrl);\n const state = {\n approved: options.role === \"host\",\n participantId: undefined as string | undefined,\n };\n\n options.output.success(`Room: ${options.roomCode}`);\n options.output.info(`Repo: ${repoContext.rootDir}`);\n\n const watcherContext: WatcherContext = {\n repoContext,\n socket,\n state,\n suppressionTracker,\n output: options.output,\n };\n const watcher = createRepoWatcher(watcherContext);\n\n socket.on(\"open\", () => {\n if (options.role === \"host\") {\n void sendInitialSnapshot(socket, repoContext, options.output);\n return;\n }\n\n options.output.info(\"Waiting for host approval...\");\n });\n\n socket.on(\"message\", (data) => {\n void handleServerMessage({\n data,\n socket,\n repoContext,\n state,\n suppressionTracker,\n output: options.output,\n });\n });\n\n await waitForSessionClose(socket, watcher);\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { ClientMessage, ServerFileMutationMessage } from \"./protocol.js\";\nimport {\n resolveRepoPath,\n shouldSyncRelativePath,\n toRepoRelativePath,\n type RepoContext,\n} from \"./paths.js\";\n\nexport type SuppressionTracker = {\n suppress(relativePath: string): void;\n isSuppressed(relativePath: string): boolean;\n};\n\nexport function createSuppressionTracker(windowMs = 1500): SuppressionTracker {\n const suppressedUntilByPath = new Map<string, number>();\n\n return {\n suppress(relativePath: string) {\n suppressedUntilByPath.set(relativePath, Date.now() + windowMs);\n },\n isSuppressed(relativePath: string) {\n const suppressedUntil = suppressedUntilByPath.get(relativePath);\n if (!suppressedUntil) {\n return false;\n }\n if (suppressedUntil < Date.now()) {\n suppressedUntilByPath.delete(relativePath);\n return false;\n }\n return true;\n },\n };\n}\n\nexport async function* collectSnapshotMessages(context: RepoContext): AsyncGenerator<ClientMessage> {\n yield* collectDirectorySnapshot(context, context.rootDir);\n}\n\nasync function* collectDirectorySnapshot(\n context: RepoContext,\n directoryPath: string\n): AsyncGenerator<ClientMessage> {\n const entries = await fs.opendir(directoryPath);\n\n for await (const entry of entries) {\n const absolutePath = path.join(directoryPath, entry.name);\n const relativePath = toRepoRelativePath(context.rootDir, absolutePath);\n\n if (!relativePath || !(await shouldSyncRelativePath(context, relativePath))) {\n continue;\n }\n\n if (entry.isDirectory()) {\n yield* collectDirectorySnapshot(context, absolutePath);\n continue;\n }\n\n if (!entry.isFile()) {\n continue;\n }\n\n const [content, stat] = await Promise.all([fs.readFile(absolutePath), fs.stat(absolutePath)]);\n yield {\n type: \"file\",\n path: relativePath,\n contentBase64: content.toString(\"base64\"),\n mtimeMs: stat.mtimeMs,\n };\n }\n}\n\nexport async function buildFileMessage(\n context: RepoContext,\n relativePath: string\n): Promise<ClientMessage | undefined> {\n if (!(await shouldSyncRelativePath(context, relativePath))) {\n return undefined;\n }\n\n const absolutePath = resolveRepoPath(context.rootDir, relativePath);\n if (!absolutePath) {\n return undefined;\n }\n\n const stat = await fs.stat(absolutePath);\n if (!stat.isFile()) {\n return undefined;\n }\n\n const content = await fs.readFile(absolutePath);\n return {\n type: \"file\",\n path: relativePath,\n contentBase64: content.toString(\"base64\"),\n mtimeMs: stat.mtimeMs,\n };\n}\n\nexport async function applyRemoteMessage(\n context: RepoContext,\n message: ServerFileMutationMessage,\n suppressionTracker: SuppressionTracker\n): Promise<void> {\n const absolutePath = resolveRepoPath(context.rootDir, message.path);\n if (!absolutePath || !(await shouldSyncRelativePath(context, message.path))) {\n return;\n }\n\n suppressionTracker.suppress(message.path);\n\n if (message.type === \"delete\") {\n await fs.rm(absolutePath, { force: true });\n return;\n }\n\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n await fs.writeFile(absolutePath, Buffer.from(message.contentBase64, \"base64\"));\n}\n","import { execFile } from \"node:child_process\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type RepoContext = {\n rootDir: string;\n};\n\nexport async function resolveRepoContext(cwd: string): Promise<RepoContext> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n });\n return { rootDir: path.resolve(stdout.trim()) };\n } catch {\n return { rootDir: path.resolve(cwd) };\n }\n}\n\nexport function toRepoRelativePath(rootDir: string, absolutePath: string): string | undefined {\n const relativePath = path.relative(rootDir, absolutePath);\n\n if (!relativePath || relativePath.startsWith(\"..\") || path.isAbsolute(relativePath)) {\n return undefined;\n }\n\n return relativePath.split(path.sep).join(\"/\");\n}\n\nexport function resolveRepoPath(rootDir: string, relativePath: string): string | undefined {\n if (!isSafeRelativePath(relativePath)) {\n return undefined;\n }\n\n const absolutePath = path.resolve(rootDir, relativePath);\n const normalizedRoot = `${path.resolve(rootDir)}${path.sep}`;\n\n if (absolutePath !== path.resolve(rootDir) && !absolutePath.startsWith(normalizedRoot)) {\n return undefined;\n }\n\n return absolutePath;\n}\n\nexport function isSafeRelativePath(relativePath: string): boolean {\n if (!relativePath || relativePath.startsWith(\"/\") || relativePath.includes(\"\\0\")) {\n return false;\n }\n\n const normalizedParts = relativePath.split(/[\\\\/]+/).filter(Boolean);\n if (normalizedParts.includes(\"..\")) {\n return false;\n }\n\n return normalizedParts[0] !== \".git\";\n}\n\nexport async function shouldSyncRelativePath(\n context: RepoContext,\n relativePath: string\n): Promise<boolean> {\n if (!isSafeRelativePath(relativePath)) {\n return false;\n }\n\n try {\n await execFileAsync(\"git\", [\"check-ignore\", \"--quiet\", \"--\", relativePath], {\n cwd: context.rootDir,\n });\n return false;\n } catch (error) {\n const exitCode =\n typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n return exitCode === 1;\n }\n}\n","import fs from \"node:fs\";\n\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport WebSocket from \"ws\";\n\nimport type { CommandOutput } from \"../../../shared/output/types.js\";\nimport { buildFileMessage, collectSnapshotMessages, type SuppressionTracker } from \"./files.js\";\nimport { shouldSyncRelativePath, toRepoRelativePath, type RepoContext } from \"./paths.js\";\nimport { sendMessage } from \"./session.js\";\n\ntype SessionState = {\n approved: boolean;\n participantId?: string;\n};\n\nexport type WatcherContext = {\n repoContext: RepoContext;\n socket: WebSocket;\n state: SessionState;\n suppressionTracker: SuppressionTracker;\n output: CommandOutput;\n};\n\nexport function createRepoWatcher(context: WatcherContext): FSWatcher {\n const watcher = chokidar.watch(context.repoContext.rootDir, {\n ignoreInitial: true,\n ignored: (candidatePath) => {\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, candidatePath);\n if (relativePath?.split(\"/\").includes(\".git\") ?? false) {\n return true;\n }\n try {\n const stat = fs.statSync(candidatePath);\n return !stat.isFile() && !stat.isDirectory();\n } catch {\n return false;\n }\n },\n });\n\n watcher.on(\"add\", (absolutePath) => {\n void sendLocalFileChange(context, absolutePath);\n });\n watcher.on(\"change\", (absolutePath) => {\n void sendLocalFileChange(context, absolutePath);\n });\n watcher.on(\"unlink\", (absolutePath) => {\n void sendLocalDelete(context, absolutePath);\n });\n watcher.on(\"error\", (watcherError) => {\n context.output.warning(\n `watcher error: ${watcherError instanceof Error ? watcherError.message : String(watcherError)}`\n );\n });\n\n return watcher;\n}\n\nexport async function sendInitialSnapshot(\n socket: WebSocket,\n repoContext: RepoContext,\n output: CommandOutput\n): Promise<void> {\n let fileCount = 0;\n\n for await (const message of collectSnapshotMessages(repoContext)) {\n sendMessage(socket, message);\n fileCount += 1;\n }\n\n output.success(`sent snapshot ${fileCount} files`);\n}\n\nasync function sendLocalFileChange(context: WatcherContext, absolutePath: string): Promise<void> {\n if (!context.state.approved) {\n return;\n }\n\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, absolutePath);\n if (!relativePath || context.suppressionTracker.isSuppressed(relativePath)) {\n return;\n }\n\n const message = await buildFileMessage(context.repoContext, relativePath);\n if (!message) {\n return;\n }\n\n sendMessage(context.socket, message);\n context.output.muted(`sent file ${relativePath}`);\n}\n\nasync function sendLocalDelete(context: WatcherContext, absolutePath: string): Promise<void> {\n if (!context.state.approved) {\n return;\n }\n\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, absolutePath);\n if (!relativePath || context.suppressionTracker.isSuppressed(relativePath)) {\n return;\n }\n\n if (!(await shouldSyncRelativePath(context.repoContext, relativePath))) {\n return;\n }\n\n sendMessage(context.socket, {\n type: \"delete\",\n path: relativePath,\n mtimeMs: Date.now(),\n });\n context.output.warning(`sent delete ${relativePath}`);\n}\n","import os from \"node:os\";\nimport process from \"node:process\";\n\nimport { type FSWatcher } from \"chokidar\";\nimport WebSocket from \"ws\";\n\nimport { encodeClientMessage, type ClientMessage } from \"./protocol.js\";\nimport type { StartSyncSessionOptions } from \"./client.js\";\n\nexport function createSyncWebSocketUrl(options: StartSyncSessionOptions): string {\n const url = new URL(options.apiBaseUrl);\n url.protocol = url.protocol === \"http:\" ? \"ws:\" : \"wss:\";\n url.pathname = `/api/cng/coderoom/rooms/${encodeURIComponent(options.roomCode)}/ws`;\n url.search = \"\";\n url.hash = \"\";\n url.searchParams.set(\"role\", options.role);\n url.searchParams.set(\"displayName\", createDisplayName());\n if (options.creatorToken) {\n url.searchParams.set(\"creatorToken\", options.creatorToken);\n }\n return url.toString();\n}\n\nexport function sendMessage(socket: WebSocket, message: ClientMessage): void {\n if (socket.readyState === WebSocket.OPEN) {\n socket.send(encodeClientMessage(message));\n }\n}\n\nexport function createDisplayName(): string {\n const username = os.userInfo().username || \"user\";\n return `${username}@${os.hostname()}`;\n}\n\nexport async function waitForSessionClose(socket: WebSocket, watcher: FSWatcher): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n\n const closeSession = async (): Promise<void> => {\n await watcher.close();\n if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {\n socket.close();\n }\n };\n\n const finish = async (): Promise<void> => {\n if (settled) {\n return;\n }\n settled = true;\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n await closeSession();\n resolve();\n };\n\n const onSignal = (): void => {\n void finish();\n };\n\n socket.on(\"error\", async (error) => {\n if (settled) {\n return;\n }\n settled = true;\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n await closeSession();\n reject(error);\n });\n\n socket.on(\"close\", () => {\n void finish();\n });\n\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n });\n}\n","import { z } from \"zod\";\n\nexport const ClientFileMessageSchema = z.object({\n type: z.literal(\"file\"),\n path: z.string().min(1),\n contentBase64: z.string(),\n mtimeMs: z.number().finite(),\n});\n\nexport const ClientDeleteMessageSchema = z.object({\n type: z.literal(\"delete\"),\n path: z.string().min(1),\n mtimeMs: z.number().finite(),\n});\n\nexport const ClientJoinApprovalMessageSchema = z.object({\n type: z.literal(\"join-approval\"),\n joinRequestId: z.string().min(1),\n approved: z.boolean(),\n});\n\nexport const ClientMessageSchema = z.discriminatedUnion(\"type\", [\n ClientFileMessageSchema,\n ClientDeleteMessageSchema,\n ClientJoinApprovalMessageSchema,\n]);\n\nexport const ServerConnectedMessageSchema = z.object({\n type: z.literal(\"connected\"),\n roomCode: z.string(),\n participantId: z.string(),\n role: z.union([z.literal(\"host\"), z.literal(\"guest\")]),\n status: z.union([z.literal(\"approved\"), z.literal(\"pending\"), z.literal(\"denied\")]),\n});\n\nexport const ServerJoinPendingMessageSchema = z.object({\n type: z.literal(\"join-pending\"),\n participantId: z.string(),\n joinRequestId: z.string(),\n roomCode: z.string(),\n});\n\nexport const ServerJoinRequestMessageSchema = z.object({\n type: z.literal(\"join-request\"),\n joinRequestId: z.string(),\n participantId: z.string(),\n displayName: z.string(),\n requestedAt: z.number().finite(),\n});\n\nexport const ServerJoinApprovedMessageSchema = z.object({\n type: z.literal(\"join-approved\"),\n participantId: z.string(),\n});\n\nexport const ServerJoinDeniedMessageSchema = z.object({\n type: z.literal(\"join-denied\"),\n participantId: z.string(),\n reason: z.string(),\n});\n\nexport const ServerFileMessageSchema = z.object({\n type: z.literal(\"file\"),\n fileId: z.string(),\n path: z.string().min(1),\n sha256: z.string(),\n size: z.number().int().nonnegative(),\n contentBase64: z.string(),\n mtimeMs: z.number().finite(),\n updatedByParticipantId: z.string(),\n});\n\nexport const ServerDeleteMessageSchema = z.object({\n type: z.literal(\"delete\"),\n fileId: z.string().optional(),\n path: z.string().min(1),\n mtimeMs: z.number().finite(),\n updatedByParticipantId: z.string(),\n});\n\nexport const ServerFileAckMessageSchema = z.object({\n type: z.literal(\"file-ack\"),\n fileId: z.string(),\n path: z.string().min(1),\n sha256: z.string(),\n size: z.number().int().nonnegative(),\n storage: z.union([z.literal(\"durable-object\"), z.literal(\"r2\")]),\n});\n\nexport const ServerTreeStartMessageSchema = z.object({\n type: z.literal(\"tree-start\"),\n fileCount: z.number().int().nonnegative(),\n});\n\nexport const ServerTreeCompleteMessageSchema = z.object({\n type: z.literal(\"tree-complete\"),\n fileCount: z.number().int().nonnegative(),\n});\n\nexport const ServerErrorMessageSchema = z.object({\n type: z.literal(\"error\"),\n error: z.string(),\n});\n\nexport const ServerMessageSchema = z.discriminatedUnion(\"type\", [\n ServerConnectedMessageSchema,\n ServerJoinPendingMessageSchema,\n ServerJoinRequestMessageSchema,\n ServerJoinApprovedMessageSchema,\n ServerJoinDeniedMessageSchema,\n ServerFileMessageSchema,\n ServerDeleteMessageSchema,\n ServerFileAckMessageSchema,\n ServerTreeStartMessageSchema,\n ServerTreeCompleteMessageSchema,\n ServerErrorMessageSchema,\n]);\n\nexport type ClientMessage = z.infer<typeof ClientMessageSchema>;\nexport type ServerMessage = z.infer<typeof ServerMessageSchema>;\nexport type ServerFileMutationMessage = Extract<ServerMessage, { type: \"file\" | \"delete\" }>;\n\nexport function encodeClientMessage(message: ClientMessage): string {\n return JSON.stringify(ClientMessageSchema.parse(message));\n}\n\nexport function decodeServerMessage(value: unknown): ServerMessage | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n try {\n return ServerMessageSchema.parse(JSON.parse(value));\n } catch {\n return undefined;\n }\n}\n","import process from \"node:process\";\nimport readline from \"node:readline/promises\";\n\nimport WebSocket, { type RawData } from \"ws\";\n\nimport type { CommandOutput } from \"../../../shared/output/types.js\";\nimport { applyRemoteMessage, type SuppressionTracker } from \"./files.js\";\nimport type { RepoContext } from \"./paths.js\";\nimport { decodeServerMessage, type ServerMessage } from \"./protocol.js\";\nimport { sendMessage } from \"./session.js\";\n\ntype SessionState = {\n approved: boolean;\n participantId?: string;\n};\n\nexport type HandleServerMessageOptions = {\n data: RawData;\n socket: WebSocket;\n repoContext: RepoContext;\n state: SessionState;\n suppressionTracker: SuppressionTracker;\n output: CommandOutput;\n};\n\nexport async function handleServerMessage(options: HandleServerMessageOptions): Promise<void> {\n const decodedMessage = decodeServerMessage(options.data.toString());\n if (!decodedMessage) {\n return;\n }\n\n if (decodedMessage.type === \"connected\") {\n options.state.participantId = decodedMessage.participantId;\n options.state.approved = decodedMessage.status === \"approved\";\n options.output.muted(`Participant: ${decodedMessage.participantId}`);\n return;\n }\n\n if (decodedMessage.type === \"join-pending\") {\n options.output.info(`Join request sent: ${decodedMessage.joinRequestId}`);\n return;\n }\n\n if (decodedMessage.type === \"join-request\") {\n await approveJoinRequest(options.socket, decodedMessage, options.output);\n return;\n }\n\n if (decodedMessage.type === \"join-approved\") {\n options.state.approved = true;\n options.output.success(\"Join approved. Applying room file tree...\");\n return;\n }\n\n if (decodedMessage.type === \"join-denied\") {\n options.output.warning(`Join denied: ${decodedMessage.reason}`);\n options.socket.close();\n return;\n }\n\n if (decodedMessage.type === \"tree-start\") {\n options.output.info(`receiving room tree ${decodedMessage.fileCount} files`);\n return;\n }\n\n if (decodedMessage.type === \"tree-complete\") {\n options.output.success(`room tree complete ${decodedMessage.fileCount} files`);\n return;\n }\n\n if (decodedMessage.type === \"file-ack\") {\n options.output.muted(\n `stored ${decodedMessage.storage} ${decodedMessage.path} ${decodedMessage.sha256}`\n );\n return;\n }\n\n if (decodedMessage.type === \"error\") {\n options.output.warning(`server error: ${decodedMessage.error}`);\n return;\n }\n\n await applyRemoteMessage(options.repoContext, decodedMessage, options.suppressionTracker);\n options.output.success(`applied ${decodedMessage.type} ${decodedMessage.path}`);\n}\n\nasync function approveJoinRequest(\n socket: WebSocket,\n message: Extract<ServerMessage, { type: \"join-request\" }>,\n output: CommandOutput\n): Promise<void> {\n const approved = await askForApproval(message, output);\n sendMessage(socket, {\n type: \"join-approval\",\n joinRequestId: message.joinRequestId,\n approved,\n });\n output[approved ? \"success\" : \"warning\"](\n `${approved ? \"approved\" : \"denied\"} ${message.displayName}`\n );\n}\n\nasync function askForApproval(\n message: Extract<ServerMessage, { type: \"join-request\" }>,\n output: CommandOutput\n): Promise<boolean> {\n output.info(`Join request: ${message.displayName} (${message.joinRequestId})`);\n if (!process.stdin.isTTY) {\n output.warning(\"No interactive terminal available. Denying join request.\");\n return false;\n }\n\n const interfaceReader = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n try {\n const answer = await interfaceReader.question(\"Approve join request? [y/N] \");\n return answer.trim().toLowerCase() === \"y\" || answer.trim().toLowerCase() === \"yes\";\n } finally {\n interfaceReader.close();\n }\n}\n"],"mappings":"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","names":["process","WebSocket","path","path","fs","fs","process","process","WebSocket","process"]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
CngApiClient,
|
|
3
3
|
formatError,
|
|
4
4
|
resolveApiBaseUrl
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DCW4RKLC.js";
|
|
6
6
|
|
|
7
7
|
// src/shared/api-client.ts
|
|
8
8
|
function createCngApiClient(options) {
|
|
@@ -32,4 +32,4 @@ export {
|
|
|
32
32
|
createCngApiClient,
|
|
33
33
|
readBackendHealth
|
|
34
34
|
};
|
|
35
|
-
//# sourceMappingURL=chunk-
|
|
35
|
+
//# sourceMappingURL=chunk-N255PYL7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/api-client.ts"],"sourcesContent":["import { CngApiClient } from \"@cng/client\";\n\nimport { resolveApiBaseUrl, type GlobalCommandOptions } from \"./config.js\";\nimport { formatError } from \"./output/errors.js\";\n\nexport type BackendHealthStatus =\n | {\n ok: true;\n service: string;\n }\n | {\n ok: false;\n message: string;\n };\n\nexport function createCngApiClient(options: GlobalCommandOptions): CngApiClient {\n return new CngApiClient({\n baseUrl: resolveApiBaseUrl(options),\n timeoutInSeconds: 15,\n maxRetries: 1,\n });\n}\n\nexport async function readBackendHealth(\n options: GlobalCommandOptions\n): Promise<BackendHealthStatus> {\n try {\n const client = createCngApiClient(options);\n const health = await client.system.getHealth();\n return {\n ok: true,\n service: health.service,\n };\n } catch (error) {\n return {\n ok: false,\n message: formatError(error),\n };\n }\n}\n"],"mappings":";;;;;;;AAeO,SAAS,mBAAmB,SAA6C;AAC9E,SAAO,IAAI,aAAa;AAAA,IACtB,SAAS,kBAAkB,OAAO;AAAA,IAClC,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACd,CAAC;AACH;AAEA,eAAsB,kBACpB,SAC8B;AAC9B,MAAI;AACF,UAAM,SAAS,mBAAmB,OAAO;AACzC,UAAM,SAAS,MAAM,OAAO,OAAO,UAAU;AAC7C,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,YAAY,KAAK;AAAA,IAC5B;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCngApiClient
|
|
3
|
+
} from "./chunk-N255PYL7.js";
|
|
4
|
+
|
|
5
|
+
// src/features/knowledges/knowledges-api.ts
|
|
6
|
+
function createKnowledgesApi(options) {
|
|
7
|
+
const client = createCngApiClient(options);
|
|
8
|
+
return {
|
|
9
|
+
getCatalog: () => client.harnessKnowledges.getHarnessKnowledgesCatalog(),
|
|
10
|
+
listAudiences: () => client.harnessKnowledges.listHarnessKnowledgesAudiences(),
|
|
11
|
+
search: (query, limit) => client.harnessKnowledges.searchHarnessKnowledges({
|
|
12
|
+
q: query,
|
|
13
|
+
limit
|
|
14
|
+
}),
|
|
15
|
+
listTopics: () => client.harnessKnowledges.listHarnessKnowledgesTopics(),
|
|
16
|
+
listFiles: ({ query, audience, limit }) => client.harnessKnowledges.listHarnessTopicAssets({
|
|
17
|
+
...query ? { q: query } : {},
|
|
18
|
+
...audience ? { audience } : {},
|
|
19
|
+
limit
|
|
20
|
+
}),
|
|
21
|
+
read: ({ filePath, offset, limit }) => client.harnessFilesystem.getHarnessFilesystemRead({
|
|
22
|
+
file_path: filePath,
|
|
23
|
+
offset,
|
|
24
|
+
limit
|
|
25
|
+
}),
|
|
26
|
+
grep: ({ pattern, path, include, mode, context, ignoreCase }) => client.harnessFilesystem.getHarnessFilesystemGrep({
|
|
27
|
+
pattern,
|
|
28
|
+
path,
|
|
29
|
+
include,
|
|
30
|
+
output_mode: mode,
|
|
31
|
+
context,
|
|
32
|
+
case_insensitive: ignoreCase ? "true" : void 0
|
|
33
|
+
}),
|
|
34
|
+
glob: ({ pattern, path }) => client.harnessFilesystem.getHarnessFilesystemGlob({
|
|
35
|
+
pattern,
|
|
36
|
+
path
|
|
37
|
+
}),
|
|
38
|
+
listDirectory: ({ path, limit }) => client.harnessFilesystem.getHarnessFilesystemLs({
|
|
39
|
+
path,
|
|
40
|
+
limit
|
|
41
|
+
}),
|
|
42
|
+
tree: ({ path, depth, limit }) => client.harnessFilesystem.getHarnessFilesystemTree({
|
|
43
|
+
path,
|
|
44
|
+
depth,
|
|
45
|
+
limit
|
|
46
|
+
}),
|
|
47
|
+
find: ({ path, name, type, maxDepth, limit }) => client.harnessFilesystem.getHarnessFilesystemFind({
|
|
48
|
+
path,
|
|
49
|
+
...name ? { name } : {},
|
|
50
|
+
...type ? { type } : {},
|
|
51
|
+
...maxDepth !== void 0 ? { max_depth: maxDepth } : {},
|
|
52
|
+
limit
|
|
53
|
+
}),
|
|
54
|
+
tail: ({ filePath, lines }) => client.harnessFilesystem.getHarnessFilesystemTail({
|
|
55
|
+
file_path: filePath,
|
|
56
|
+
lines
|
|
57
|
+
}),
|
|
58
|
+
statPath: ({ path }) => client.harnessFilesystem.getHarnessFilesystemStat({
|
|
59
|
+
path
|
|
60
|
+
})
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export {
|
|
65
|
+
createKnowledgesApi
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=chunk-NLAANOBW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/knowledges/knowledges-api.ts"],"sourcesContent":["import type { CngApi } from \"@cng/client\";\n\nimport { createCngApiClient } from \"../../shared/api-client.js\";\nimport type { GlobalCommandOptions } from \"../../shared/config.js\";\n\nexport type KnowCommandDependencies = {\n api?: KnowledgesApi;\n};\n\nexport type KnowledgesApi = {\n getCatalog(): Promise<CngApi.HarnessCatalogSummaryApiResponse>;\n listAudiences(): Promise<CngApi.HarnessAudiencesApiResponse>;\n search(query: string, limit: number): Promise<CngApi.HarnessSemanticSearchApiResponse>;\n listTopics(): Promise<CngApi.HarnessTopicsApiResponse>;\n listFiles(options: {\n query?: string;\n audience?: CngApi.HarnessAudienceId;\n limit: number;\n }): Promise<CngApi.HarnessTopicAssetsApiResponse>;\n read(options: {\n filePath: string;\n offset?: number;\n limit: number;\n }): Promise<CngApi.HarnessReadApiResponse>;\n grep(options: {\n pattern: string;\n path: string;\n include: string;\n mode: CngApi.HarnessGrepOutputMode;\n context: number;\n ignoreCase: boolean;\n }): Promise<CngApi.HarnessGrepApiResponse>;\n glob(options: { pattern: string; path: string }): Promise<CngApi.HarnessGlobApiResponse>;\n listDirectory(options: {\n path: string;\n limit: number;\n }): Promise<CngApi.HarnessFilesystemLsApiResponse>;\n tree(options: {\n path: string;\n depth: number;\n limit: number;\n }): Promise<CngApi.HarnessFilesystemTreeApiResponse>;\n find(options: {\n path: string;\n name?: string;\n type?: CngApi.HarnessFilesystemFindType;\n maxDepth?: number;\n limit: number;\n }): Promise<CngApi.HarnessFilesystemFindApiResponse>;\n tail(options: {\n filePath: string;\n lines: number;\n }): Promise<CngApi.HarnessFilesystemTailApiResponse>;\n statPath(options: { path: string }): Promise<CngApi.HarnessFilesystemStatApiResponse>;\n};\n\nexport function createKnowledgesApi(options: GlobalCommandOptions): KnowledgesApi {\n const client = createCngApiClient(options);\n\n return {\n getCatalog: () => client.harnessKnowledges.getHarnessKnowledgesCatalog(),\n listAudiences: () => client.harnessKnowledges.listHarnessKnowledgesAudiences(),\n search: (query, limit) =>\n client.harnessKnowledges.searchHarnessKnowledges({\n q: query,\n limit,\n }),\n listTopics: () => client.harnessKnowledges.listHarnessKnowledgesTopics(),\n listFiles: ({ query, audience, limit }) =>\n client.harnessKnowledges.listHarnessTopicAssets({\n ...(query ? { q: query } : {}),\n ...(audience ? { audience } : {}),\n limit,\n }),\n read: ({ filePath, offset, limit }) =>\n client.harnessFilesystem.getHarnessFilesystemRead({\n file_path: filePath,\n offset,\n limit,\n }),\n grep: ({ pattern, path, include, mode, context, ignoreCase }) =>\n client.harnessFilesystem.getHarnessFilesystemGrep({\n pattern,\n path,\n include,\n output_mode: mode,\n context,\n case_insensitive: ignoreCase ? \"true\" : undefined,\n }),\n glob: ({ pattern, path }) =>\n client.harnessFilesystem.getHarnessFilesystemGlob({\n pattern,\n path,\n }),\n listDirectory: ({ path, limit }) =>\n client.harnessFilesystem.getHarnessFilesystemLs({\n path,\n limit,\n }),\n tree: ({ path, depth, limit }) =>\n client.harnessFilesystem.getHarnessFilesystemTree({\n path,\n depth,\n limit,\n }),\n find: ({ path, name, type, maxDepth, limit }) =>\n client.harnessFilesystem.getHarnessFilesystemFind({\n path,\n ...(name ? { name } : {}),\n ...(type ? { type } : {}),\n ...(maxDepth !== undefined ? { max_depth: maxDepth } : {}),\n limit,\n }),\n tail: ({ filePath, lines }) =>\n client.harnessFilesystem.getHarnessFilesystemTail({\n file_path: filePath,\n lines,\n }),\n statPath: ({ path }) =>\n client.harnessFilesystem.getHarnessFilesystemStat({\n path,\n }),\n };\n}\n"],"mappings":";;;;;AAwDO,SAAS,oBAAoB,SAA8C;AAChF,QAAM,SAAS,mBAAmB,OAAO;AAEzC,SAAO;AAAA,IACL,YAAY,MAAM,OAAO,kBAAkB,4BAA4B;AAAA,IACvE,eAAe,MAAM,OAAO,kBAAkB,+BAA+B;AAAA,IAC7E,QAAQ,CAAC,OAAO,UACd,OAAO,kBAAkB,wBAAwB;AAAA,MAC/C,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAAA,IACH,YAAY,MAAM,OAAO,kBAAkB,4BAA4B;AAAA,IACvE,WAAW,CAAC,EAAE,OAAO,UAAU,MAAM,MACnC,OAAO,kBAAkB,uBAAuB;AAAA,MAC9C,GAAI,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC;AAAA,MAC5B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,MAC/B;AAAA,IACF,CAAC;AAAA,IACH,MAAM,CAAC,EAAE,UAAU,QAAQ,MAAM,MAC/B,OAAO,kBAAkB,yBAAyB;AAAA,MAChD,WAAW;AAAA,MACX;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,MAAM,CAAC,EAAE,SAAS,MAAM,SAAS,MAAM,SAAS,WAAW,MACzD,OAAO,kBAAkB,yBAAyB;AAAA,MAChD;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA,kBAAkB,aAAa,SAAS;AAAA,IAC1C,CAAC;AAAA,IACH,MAAM,CAAC,EAAE,SAAS,KAAK,MACrB,OAAO,kBAAkB,yBAAyB;AAAA,MAChD;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,eAAe,CAAC,EAAE,MAAM,MAAM,MAC5B,OAAO,kBAAkB,uBAAuB;AAAA,MAC9C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,MAAM,CAAC,EAAE,MAAM,OAAO,MAAM,MAC1B,OAAO,kBAAkB,yBAAyB;AAAA,MAChD;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,MAAM,CAAC,EAAE,MAAM,MAAM,MAAM,UAAU,MAAM,MACzC,OAAO,kBAAkB,yBAAyB;AAAA,MAChD;AAAA,MACA,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,aAAa,SAAY,EAAE,WAAW,SAAS,IAAI,CAAC;AAAA,MACxD;AAAA,IACF,CAAC;AAAA,IACH,MAAM,CAAC,EAAE,UAAU,MAAM,MACvB,OAAO,kBAAkB,yBAAyB;AAAA,MAChD,WAAW;AAAA,MACX;AAAA,IACF,CAAC;AAAA,IACH,UAAU,CAAC,EAAE,KAAK,MAChB,OAAO,kBAAkB,yBAAyB;AAAA,MAChD;AAAA,IACF,CAAC;AAAA,EACL;AACF;","names":[]}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatError,
|
|
3
|
+
resolveOutputFormat
|
|
4
|
+
} from "./chunk-DCW4RKLC.js";
|
|
5
|
+
|
|
6
|
+
// src/cli/command-runner.tsx
|
|
7
|
+
import { useCallback, useEffect as useEffect2, useRef, useState } from "react";
|
|
8
|
+
import { useApp } from "ink";
|
|
9
|
+
|
|
10
|
+
// src/shared/output/factory.ts
|
|
11
|
+
import process2 from "process";
|
|
12
|
+
|
|
13
|
+
// src/shared/output/markdown.ts
|
|
14
|
+
function prepareMarkdownForTerminal(markdown) {
|
|
15
|
+
if (!markdown.startsWith("---\n")) {
|
|
16
|
+
return markdown;
|
|
17
|
+
}
|
|
18
|
+
const frontmatterEndIndex = markdown.indexOf("\n---", 4);
|
|
19
|
+
if (frontmatterEndIndex < 0) {
|
|
20
|
+
return formatFrontmatterForTerminal(markdown.slice(4).trimEnd());
|
|
21
|
+
}
|
|
22
|
+
const frontmatter = markdown.slice(4, frontmatterEndIndex).trimEnd();
|
|
23
|
+
const body = markdown.slice(frontmatterEndIndex + "\n---".length).replace(/^\n+/, "");
|
|
24
|
+
return `${formatFrontmatterForTerminal(frontmatter)}
|
|
25
|
+
|
|
26
|
+
${body}`;
|
|
27
|
+
}
|
|
28
|
+
function formatFrontmatterForTerminal(frontmatter) {
|
|
29
|
+
return `## Metadata
|
|
30
|
+
|
|
31
|
+
\`\`\`yaml
|
|
32
|
+
${frontmatter}
|
|
33
|
+
\`\`\``;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/shared/output/factory.ts
|
|
37
|
+
function createCommandOutput(sink) {
|
|
38
|
+
const stdout = sink.stdout ?? process2.stdout;
|
|
39
|
+
const stderr = sink.stderr ?? process2.stderr;
|
|
40
|
+
return {
|
|
41
|
+
info(message) {
|
|
42
|
+
appendStyledMessage(sink, stdout, "stdout", "info", message);
|
|
43
|
+
},
|
|
44
|
+
success(message) {
|
|
45
|
+
appendStyledMessage(sink, stdout, "stdout", "success", message);
|
|
46
|
+
},
|
|
47
|
+
warning(message) {
|
|
48
|
+
appendStyledMessage(sink, stdout, "stdout", "warning", message);
|
|
49
|
+
},
|
|
50
|
+
muted(message) {
|
|
51
|
+
appendStyledMessage(sink, stdout, "stdout", "muted", message);
|
|
52
|
+
},
|
|
53
|
+
markdown(message) {
|
|
54
|
+
if (resolveOutputFormat() === "markdown") {
|
|
55
|
+
stdout.write(`${message}
|
|
56
|
+
`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (sink.appendMessage) {
|
|
60
|
+
sink.appendMessage({ kind: "markdown", message: prepareMarkdownForTerminal(message) });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
stdout.write(`${message}
|
|
64
|
+
`);
|
|
65
|
+
},
|
|
66
|
+
component(element) {
|
|
67
|
+
if (sink.appendMessage) {
|
|
68
|
+
sink.appendMessage({ kind: "component", element });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
stdout.write("\n");
|
|
72
|
+
},
|
|
73
|
+
raw(message) {
|
|
74
|
+
stdout.write(`${message}
|
|
75
|
+
`);
|
|
76
|
+
},
|
|
77
|
+
error(message) {
|
|
78
|
+
appendStyledMessage(sink, stderr, "stderr", "error", message);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function appendStyledMessage(sink, stream, streamName, style, message) {
|
|
83
|
+
if (sink.appendMessage) {
|
|
84
|
+
sink.appendMessage({ kind: "styled", stream: streamName, style, message });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
stream.write(`${message}
|
|
88
|
+
`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/shared/output/renderer.tsx
|
|
92
|
+
import process3 from "process";
|
|
93
|
+
import { createElement, useEffect } from "react";
|
|
94
|
+
import { Static, Text, useStderr, useStdout } from "ink";
|
|
95
|
+
import Markdown from "@inkkit/ink-markdown";
|
|
96
|
+
|
|
97
|
+
// src/shared/theme.ts
|
|
98
|
+
import { Chalk } from "chalk";
|
|
99
|
+
var statusStylePropsByOutputStyle = {
|
|
100
|
+
info: {
|
|
101
|
+
color: "cyan"
|
|
102
|
+
},
|
|
103
|
+
success: {
|
|
104
|
+
color: "green",
|
|
105
|
+
bold: true
|
|
106
|
+
},
|
|
107
|
+
warning: {
|
|
108
|
+
color: "yellow",
|
|
109
|
+
bold: true
|
|
110
|
+
},
|
|
111
|
+
muted: {
|
|
112
|
+
dimColor: true
|
|
113
|
+
},
|
|
114
|
+
error: {
|
|
115
|
+
color: "red",
|
|
116
|
+
bold: true
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
function createMarkdownTheme(useColor) {
|
|
120
|
+
const chalk = new Chalk({ level: useColor ? 1 : 0 });
|
|
121
|
+
const identity = (value) => value;
|
|
122
|
+
return {
|
|
123
|
+
code: chalk.green,
|
|
124
|
+
blockquote: chalk.dim.italic,
|
|
125
|
+
html: chalk.gray,
|
|
126
|
+
heading: chalk.blueBright.bold,
|
|
127
|
+
firstHeading: chalk.magentaBright.bold,
|
|
128
|
+
hr: chalk.gray,
|
|
129
|
+
listitem: identity,
|
|
130
|
+
table: identity,
|
|
131
|
+
paragraph: identity,
|
|
132
|
+
strong: chalk.bold,
|
|
133
|
+
em: chalk.italic,
|
|
134
|
+
codespan: chalk.cyanBright,
|
|
135
|
+
del: chalk.dim.strikethrough,
|
|
136
|
+
link: chalk.blueBright,
|
|
137
|
+
href: chalk.blue.underline,
|
|
138
|
+
text: identity,
|
|
139
|
+
showSectionPrefix: false,
|
|
140
|
+
reflowText: true,
|
|
141
|
+
unescape: true,
|
|
142
|
+
emoji: false,
|
|
143
|
+
tab: 2
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/shared/output/renderer.tsx
|
|
148
|
+
function CommandOutputMessages({
|
|
149
|
+
messages
|
|
150
|
+
}) {
|
|
151
|
+
const { stdout } = useStdout();
|
|
152
|
+
const width = clampMarkdownWidth(stdout.columns);
|
|
153
|
+
const useColor = shouldRenderColor(stdout);
|
|
154
|
+
if (messages.length === 0) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
return createElement(
|
|
158
|
+
Static,
|
|
159
|
+
{
|
|
160
|
+
items: [...messages],
|
|
161
|
+
style: { flexDirection: "column" },
|
|
162
|
+
children: (message) => createElement(CommandOutputMessageView, {
|
|
163
|
+
key: message.id,
|
|
164
|
+
message,
|
|
165
|
+
useColor,
|
|
166
|
+
width
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
function CommandOutputMessageView({
|
|
172
|
+
message,
|
|
173
|
+
useColor,
|
|
174
|
+
width
|
|
175
|
+
}) {
|
|
176
|
+
if (message.kind === "styled") {
|
|
177
|
+
if (message.stream === "stderr") {
|
|
178
|
+
return createElement(StderrLine, { message: message.message });
|
|
179
|
+
}
|
|
180
|
+
return createElement(
|
|
181
|
+
Text,
|
|
182
|
+
{
|
|
183
|
+
...statusStylePropsByOutputStyle[message.style],
|
|
184
|
+
wrap: "wrap"
|
|
185
|
+
},
|
|
186
|
+
message.message
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
if (message.kind === "markdown") {
|
|
190
|
+
return createElement(
|
|
191
|
+
Markdown,
|
|
192
|
+
{
|
|
193
|
+
...createMarkdownTheme(useColor),
|
|
194
|
+
width
|
|
195
|
+
},
|
|
196
|
+
message.message
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
return message.element;
|
|
200
|
+
}
|
|
201
|
+
function StderrLine({ message }) {
|
|
202
|
+
const { write } = useStderr();
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
write(`${message}
|
|
205
|
+
`);
|
|
206
|
+
}, [message, write]);
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
function shouldRenderColor(stream) {
|
|
210
|
+
if (process3.env.CNGKIT_NO_COLOR === "1") {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
const colorMode = process3.env.CNGKIT_COLOR?.toLowerCase();
|
|
214
|
+
if (colorMode === "never" || colorMode === "0" || colorMode === "false") {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
if (colorMode === "always" || colorMode === "1" || colorMode === "true") {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
if (process3.env.FORCE_COLOR !== void 0 && process3.env.FORCE_COLOR !== "0") {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
if (process3.env.NO_COLOR !== void 0) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
return stream.isTTY === true;
|
|
227
|
+
}
|
|
228
|
+
function clampMarkdownWidth(columns) {
|
|
229
|
+
if (columns === void 0) {
|
|
230
|
+
return 100;
|
|
231
|
+
}
|
|
232
|
+
return Math.max(72, Math.min(columns, 120));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/cli/command-runner.tsx
|
|
236
|
+
import { jsx } from "react/jsx-runtime";
|
|
237
|
+
function CommandRunner({ run }) {
|
|
238
|
+
const { exit } = useApp();
|
|
239
|
+
const nextMessageIdRef = useRef(1);
|
|
240
|
+
const [messages, setMessages] = useState([]);
|
|
241
|
+
const appendMessage = useCallback((message) => {
|
|
242
|
+
const nextMessage = {
|
|
243
|
+
...message,
|
|
244
|
+
id: nextMessageIdRef.current
|
|
245
|
+
};
|
|
246
|
+
nextMessageIdRef.current += 1;
|
|
247
|
+
setMessages((currentMessages) => [...currentMessages, nextMessage]);
|
|
248
|
+
}, []);
|
|
249
|
+
useEffect2(() => {
|
|
250
|
+
const output = createCommandOutput({
|
|
251
|
+
appendMessage,
|
|
252
|
+
stdout: process.stdout,
|
|
253
|
+
stderr: process.stderr
|
|
254
|
+
});
|
|
255
|
+
void run(output).catch((error) => {
|
|
256
|
+
process.exitCode = 1;
|
|
257
|
+
output.error(formatError(error));
|
|
258
|
+
}).finally(() => {
|
|
259
|
+
setTimeout(() => exit(), 0);
|
|
260
|
+
});
|
|
261
|
+
}, [appendMessage, exit, run]);
|
|
262
|
+
return /* @__PURE__ */ jsx(CommandOutputMessages, { messages });
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export {
|
|
266
|
+
CommandRunner
|
|
267
|
+
};
|
|
268
|
+
//# sourceMappingURL=chunk-TIY4RTXC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/command-runner.tsx","../src/shared/output/factory.ts","../src/shared/output/markdown.ts","../src/shared/output/renderer.tsx","../src/shared/theme.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useApp } from \"ink\";\n\nimport {\n CommandOutputMessages,\n createCommandOutput,\n formatError,\n type CommandOutput,\n type CommandOutputMessage,\n type CommandOutputMessagePayload,\n} from \"../shared/output/index.js\";\n\ntype CommandRunnerProps = {\n readonly run: (output: CommandOutput) => Promise<void>;\n};\n\nexport function CommandRunner({ run }: CommandRunnerProps) {\n const { exit } = useApp();\n const nextMessageIdRef = useRef(1);\n const [messages, setMessages] = useState<CommandOutputMessage[]>([]);\n const appendMessage = useCallback((message: CommandOutputMessagePayload) => {\n const nextMessage: CommandOutputMessage = {\n ...message,\n id: nextMessageIdRef.current,\n };\n nextMessageIdRef.current += 1;\n setMessages((currentMessages) => [...currentMessages, nextMessage]);\n }, []);\n\n useEffect(() => {\n const output = createCommandOutput({\n appendMessage,\n stdout: process.stdout,\n stderr: process.stderr,\n });\n\n void run(output)\n .catch((error: unknown) => {\n process.exitCode = 1;\n output.error(formatError(error));\n })\n .finally(() => {\n setTimeout(() => exit(), 0);\n });\n }, [appendMessage, exit, run]);\n\n return <CommandOutputMessages messages={messages} />;\n}\n","import process from \"node:process\";\n\nimport { resolveOutputFormat } from \"../config.js\";\nimport { prepareMarkdownForTerminal } from \"./markdown.js\";\nimport type {\n CommandOutput,\n CommandOutputSink,\n OutputStream,\n} from \"./types.js\";\n\nexport function createCommandOutput(sink: CommandOutputSink): CommandOutput {\n const stdout = sink.stdout ?? process.stdout;\n const stderr = sink.stderr ?? process.stderr;\n\n return {\n info(message) {\n appendStyledMessage(sink, stdout, \"stdout\", \"info\", message);\n },\n success(message) {\n appendStyledMessage(sink, stdout, \"stdout\", \"success\", message);\n },\n warning(message) {\n appendStyledMessage(sink, stdout, \"stdout\", \"warning\", message);\n },\n muted(message) {\n appendStyledMessage(sink, stdout, \"stdout\", \"muted\", message);\n },\n markdown(message) {\n if (resolveOutputFormat() === \"markdown\") {\n stdout.write(`${message}\\n`);\n return;\n }\n\n if (sink.appendMessage) {\n sink.appendMessage({ kind: \"markdown\", message: prepareMarkdownForTerminal(message) });\n return;\n }\n\n stdout.write(`${message}\\n`);\n },\n component(element) {\n if (sink.appendMessage) {\n sink.appendMessage({ kind: \"component\", element });\n return;\n }\n\n stdout.write(\"\\n\");\n },\n raw(message) {\n stdout.write(`${message}\\n`);\n },\n error(message) {\n appendStyledMessage(sink, stderr, \"stderr\", \"error\", message);\n },\n };\n}\n\nfunction appendStyledMessage(\n sink: CommandOutputSink,\n stream: OutputStream,\n streamName: \"stdout\" | \"stderr\",\n style: \"info\" | \"success\" | \"warning\" | \"muted\" | \"error\",\n message: string\n): void {\n if (sink.appendMessage) {\n sink.appendMessage({ kind: \"styled\", stream: streamName, style, message });\n return;\n }\n\n stream.write(`${message}\\n`);\n}\n","export function prepareMarkdownForTerminal(markdown: string): string {\n if (!markdown.startsWith(\"---\\n\")) {\n return markdown;\n }\n\n const frontmatterEndIndex = markdown.indexOf(\"\\n---\", 4);\n if (frontmatterEndIndex < 0) {\n return formatFrontmatterForTerminal(markdown.slice(4).trimEnd());\n }\n\n const frontmatter = markdown.slice(4, frontmatterEndIndex).trimEnd();\n const body = markdown.slice(frontmatterEndIndex + \"\\n---\".length).replace(/^\\n+/, \"\");\n\n return `${formatFrontmatterForTerminal(frontmatter)}\\n\\n${body}`;\n}\n\nexport function formatFrontmatterForTerminal(frontmatter: string): string {\n return `## Metadata\\n\\n\\`\\`\\`yaml\\n${frontmatter}\\n\\`\\`\\``;\n}\n","import process from \"node:process\";\nimport { createElement, useEffect, type ReactElement } from \"react\";\nimport { Static, Text, useStderr, useStdout } from \"ink\";\nimport Markdown from \"@inkkit/ink-markdown\";\n\nimport { createMarkdownTheme, statusStylePropsByOutputStyle } from \"../theme.js\";\nimport type { CommandOutputMessage, OutputStream } from \"./types.js\";\n\nexport function CommandOutputMessages({\n messages,\n}: {\n readonly messages: readonly CommandOutputMessage[];\n}): ReactElement | null {\n const { stdout } = useStdout();\n const width = clampMarkdownWidth(stdout.columns);\n const useColor = shouldRenderColor(stdout);\n\n if (messages.length === 0) {\n return null;\n }\n\n return createElement(\n Static<CommandOutputMessage>,\n {\n items: [...messages],\n style: { flexDirection: \"column\" },\n children: (message: CommandOutputMessage) =>\n createElement(CommandOutputMessageView, {\n key: message.id,\n message,\n useColor,\n width,\n }),\n }\n );\n}\n\nfunction CommandOutputMessageView({\n message,\n useColor,\n width,\n}: {\n readonly message: CommandOutputMessage;\n readonly useColor: boolean;\n readonly width: number;\n}): ReactElement {\n if (message.kind === \"styled\") {\n if (message.stream === \"stderr\") {\n return createElement(StderrLine, { message: message.message });\n }\n\n return createElement(\n Text,\n {\n ...statusStylePropsByOutputStyle[message.style],\n wrap: \"wrap\",\n },\n message.message\n );\n }\n\n if (message.kind === \"markdown\") {\n return createElement(\n Markdown,\n {\n ...createMarkdownTheme(useColor),\n width,\n },\n message.message\n );\n }\n\n return message.element;\n}\n\nfunction StderrLine({ message }: { readonly message: string }): null {\n const { write } = useStderr();\n\n useEffect(() => {\n write(`${message}\\n`);\n }, [message, write]);\n\n return null;\n}\n\nfunction shouldRenderColor(stream: OutputStream): boolean {\n if (process.env.CNGKIT_NO_COLOR === \"1\") {\n return false;\n }\n\n const colorMode = process.env.CNGKIT_COLOR?.toLowerCase();\n\n if (colorMode === \"never\" || colorMode === \"0\" || colorMode === \"false\") {\n return false;\n }\n\n if (colorMode === \"always\" || colorMode === \"1\" || colorMode === \"true\") {\n return true;\n }\n\n if (process.env.FORCE_COLOR !== undefined && process.env.FORCE_COLOR !== \"0\") {\n return true;\n }\n\n if (process.env.NO_COLOR !== undefined) {\n return false;\n }\n\n return stream.isTTY === true;\n}\n\nfunction clampMarkdownWidth(columns: number | undefined): number {\n if (columns === undefined) {\n return 100;\n }\n\n return Math.max(72, Math.min(columns, 120));\n}\n","import { Chalk } from \"chalk\";\nimport type { TextProps } from \"ink\";\n\nexport type OutputStyle = \"info\" | \"success\" | \"warning\" | \"muted\" | \"error\";\n\nexport const statusStylePropsByOutputStyle = {\n info: {\n color: \"cyan\",\n },\n success: {\n color: \"green\",\n bold: true,\n },\n warning: {\n color: \"yellow\",\n bold: true,\n },\n muted: {\n dimColor: true,\n },\n error: {\n color: \"red\",\n bold: true,\n },\n} satisfies Record<OutputStyle, TextProps>;\n\nexport function createMarkdownTheme(useColor: boolean) {\n const chalk = new Chalk({ level: useColor ? 1 : 0 });\n const identity = (value: string) => value;\n\n return {\n code: chalk.green,\n blockquote: chalk.dim.italic,\n html: chalk.gray,\n heading: chalk.blueBright.bold,\n firstHeading: chalk.magentaBright.bold,\n hr: chalk.gray,\n listitem: identity,\n table: identity,\n paragraph: identity,\n strong: chalk.bold,\n em: chalk.italic,\n codespan: chalk.cyanBright,\n del: chalk.dim.strikethrough,\n link: chalk.blueBright,\n href: chalk.blue.underline,\n text: identity,\n showSectionPrefix: false,\n reflowText: true,\n unescape: true,\n emoji: false,\n tab: 2,\n };\n}\n"],"mappings":"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","names":["useEffect","process","process","process","process","useEffect"]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatCatalogPathForDisplay
|
|
3
|
+
} from "./chunk-AS7FIJWP.js";
|
|
4
|
+
import {
|
|
5
|
+
singleLine
|
|
6
|
+
} from "./chunk-XQGLUQFM.js";
|
|
7
|
+
|
|
8
|
+
// src/features/knowledges/knowledges-output.tsx
|
|
9
|
+
import { Box, Text } from "ink";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
function KnowCatalogSummary({ catalog }) {
|
|
12
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
13
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
14
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Catalog: " }),
|
|
15
|
+
catalog.name
|
|
16
|
+
] }),
|
|
17
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
18
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Files: " }),
|
|
19
|
+
catalog.files
|
|
20
|
+
] }),
|
|
21
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
22
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Blobs: " }),
|
|
23
|
+
catalog.blobs
|
|
24
|
+
] }),
|
|
25
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
26
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Database: " }),
|
|
27
|
+
catalog.database.engine,
|
|
28
|
+
" (",
|
|
29
|
+
catalog.database.binding,
|
|
30
|
+
")"
|
|
31
|
+
] })
|
|
32
|
+
] });
|
|
33
|
+
}
|
|
34
|
+
function KnowAudienceList({ audiences }) {
|
|
35
|
+
if (audiences.length === 0) {
|
|
36
|
+
return /* @__PURE__ */ jsx(Text, { color: "yellow", children: "No audiences available." });
|
|
37
|
+
}
|
|
38
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: audiences.map((audience) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
39
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
40
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: audience.id }),
|
|
41
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
42
|
+
" - ",
|
|
43
|
+
audience.label
|
|
44
|
+
] })
|
|
45
|
+
] }),
|
|
46
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: singleLine(audience.help) })
|
|
47
|
+
] }, audience.id)) });
|
|
48
|
+
}
|
|
49
|
+
function KnowSearchResults({
|
|
50
|
+
results
|
|
51
|
+
}) {
|
|
52
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: results.map((result, index) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
53
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
54
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
55
|
+
index + 1,
|
|
56
|
+
". "
|
|
57
|
+
] }),
|
|
58
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: result.title }),
|
|
59
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
60
|
+
" (",
|
|
61
|
+
result.topicName,
|
|
62
|
+
")"
|
|
63
|
+
] })
|
|
64
|
+
] }),
|
|
65
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
66
|
+
"score ",
|
|
67
|
+
result.score.toFixed(3),
|
|
68
|
+
" | ",
|
|
69
|
+
formatCatalogPathForDisplay(result.path)
|
|
70
|
+
] }),
|
|
71
|
+
/* @__PURE__ */ jsx(Text, { children: singleLine(result.description || result.contentPreview) })
|
|
72
|
+
] }, result.id)) });
|
|
73
|
+
}
|
|
74
|
+
function KnowTopicList({ topics }) {
|
|
75
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: topics.map((topic) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
76
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
77
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: topic.name }),
|
|
78
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
79
|
+
" [",
|
|
80
|
+
topic.type,
|
|
81
|
+
"]"
|
|
82
|
+
] })
|
|
83
|
+
] }),
|
|
84
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
85
|
+
topic.title,
|
|
86
|
+
" | files ",
|
|
87
|
+
topic.fileCount,
|
|
88
|
+
" | rating ",
|
|
89
|
+
topic.rating
|
|
90
|
+
] }),
|
|
91
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: singleLine(topic.description) })
|
|
92
|
+
] }, topic.id)) });
|
|
93
|
+
}
|
|
94
|
+
function KnowTopicFileList({ files }) {
|
|
95
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: files.map((file) => {
|
|
96
|
+
const title = file.display_title ?? file.title ?? file.topic_name ?? "Untitled";
|
|
97
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
98
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: formatCatalogPathForDisplay(file.path) }),
|
|
99
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: title })
|
|
100
|
+
] }, `${file.path}-${file.sha256}`);
|
|
101
|
+
}) });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export {
|
|
105
|
+
KnowCatalogSummary,
|
|
106
|
+
KnowAudienceList,
|
|
107
|
+
KnowSearchResults,
|
|
108
|
+
KnowTopicList,
|
|
109
|
+
KnowTopicFileList
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=chunk-VMTXY4KQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/knowledges/knowledges-output.tsx"],"sourcesContent":["import type { CngApi } from \"@cng/client\";\nimport { Box, Text } from \"ink\";\n\nimport { singleLine } from \"../../shared/command-utils.js\";\nimport { formatCatalogPathForDisplay } from \"./knowledges-input.js\";\n\nexport function KnowCatalogSummary({ catalog }: { readonly catalog: CngApi.HarnessCatalogSummary }) {\n return (\n <Box flexDirection=\"column\">\n <Text>\n <Text bold>Catalog: </Text>\n {catalog.name}\n </Text>\n <Text>\n <Text bold>Files: </Text>\n {catalog.files}\n </Text>\n <Text>\n <Text bold>Blobs: </Text>\n {catalog.blobs}\n </Text>\n <Text>\n <Text bold>Database: </Text>\n {catalog.database.engine} ({catalog.database.binding})\n </Text>\n </Box>\n );\n}\n\nexport function KnowAudienceList({ audiences }: { readonly audiences: readonly CngApi.HarnessAudience[] }) {\n if (audiences.length === 0) {\n return <Text color=\"yellow\">No audiences available.</Text>;\n }\n\n return (\n <Box flexDirection=\"column\">\n {audiences.map((audience) => (\n <Box flexDirection=\"column\" key={audience.id} marginBottom={1}>\n <Text>\n <Text color=\"cyan\">{audience.id}</Text>\n <Text> - {audience.label}</Text>\n </Text>\n <Text dimColor>{singleLine(audience.help)}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n\nexport function KnowSearchResults({\n results,\n}: {\n readonly results: readonly CngApi.HarnessSemanticSearchResult[];\n}) {\n return (\n <Box flexDirection=\"column\">\n {results.map((result, index) => (\n <Box flexDirection=\"column\" key={result.id} marginBottom={1}>\n <Text>\n <Text color=\"cyan\">{index + 1}. </Text>\n <Text bold>{result.title}</Text>\n <Text dimColor> ({result.topicName})</Text>\n </Text>\n <Text dimColor>\n score {result.score.toFixed(3)} | {formatCatalogPathForDisplay(result.path)}\n </Text>\n <Text>{singleLine(result.description || result.contentPreview)}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n\nexport function KnowTopicList({ topics }: { readonly topics: readonly CngApi.HarnessTopicSummary[] }) {\n return (\n <Box flexDirection=\"column\">\n {topics.map((topic) => (\n <Box flexDirection=\"column\" key={topic.id} marginBottom={1}>\n <Text>\n <Text color=\"cyan\">{topic.name}</Text>\n <Text dimColor> [{topic.type}]</Text>\n </Text>\n <Text>\n {topic.title} | files {topic.fileCount} | rating {topic.rating}\n </Text>\n <Text dimColor>{singleLine(topic.description)}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n\nexport function KnowTopicFileList({ files }: { readonly files: readonly CngApi.HarnessTopicAsset[] }) {\n return (\n <Box flexDirection=\"column\">\n {files.map((file) => {\n const title = file.display_title ?? file.title ?? file.topic_name ?? \"Untitled\";\n\n return (\n <Box flexDirection=\"column\" key={`${file.path}-${file.sha256}`} marginBottom={1}>\n <Text color=\"cyan\">{formatCatalogPathForDisplay(file.path)}</Text>\n <Text dimColor>{title}</Text>\n </Box>\n );\n })}\n </Box>\n );\n}\n"],"mappings":"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","names":[]}
|