mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-25 17:54:34 +08:00
feat(cli): make clb web the primary web command
This commit is contained in:
1 parent
c6db9f0c4c
commit
47299a94cb
64 files changed
+264
-270
No files matched your search
@@ -9,7 +9,7 @@ RUN test -n "$CHATLAB_VERSION" \
|
||||
&& apt-get update \
|
||||
&& apt-get install --yes --no-install-recommends g++ make python3 \
|
||||
&& npm install --global --omit=dev "chatlab-cli@${CHATLAB_VERSION}" \
|
||||
&& CHATLAB_SKIP_UPDATE_CHECK=1 chatlab runtime install local-embedding \
|
||||
&& CHATLAB_SKIP_UPDATE_CHECK=1 clb runtime install local-embedding \
|
||||
&& npm cache clean --force \
|
||||
&& apt-get purge --yes --auto-remove g++ make python3 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
@@ -23,5 +23,5 @@ USER node
|
||||
|
||||
EXPOSE 3110
|
||||
|
||||
ENTRYPOINT ["chatlab"]
|
||||
CMD ["start", "--no-open", "--host", "0.0.0.0"]
|
||||
ENTRYPOINT ["clb"]
|
||||
CMD ["web", "--no-open", "--host", "0.0.0.0"]
|
||||
@@ -43,9 +43,9 @@ npm i chatlab-cli -g
|
||||
Start ChatLab:
|
||||
|
||||
```bash
|
||||
chatlab start # Start API + Web UI, auto-open in browser
|
||||
chatlab start --no-open # Start API + Web UI, skip auto-open
|
||||
chatlab start --headless # API only, no Web UI (for scripts / AI Agents)
|
||||
clb web # Start API + Web UI, auto-open in browser
|
||||
clb web --no-open # Start API + Web UI, skip auto-open
|
||||
clb web --headless # API only, no Web UI (for scripts / AI Agents)
|
||||
```
|
||||
|
||||
Common options: `--port <port>` (default 3110), `--host <address>`, `--token <token>`.
|
||||
@@ -53,9 +53,9 @@ Common options: `--port <port>` (default 3110), `--host <address>`, `--token <to
|
||||
To run as a persistent background service (auto-start on login + auto-restart on crash):
|
||||
|
||||
```bash
|
||||
chatlab start --daemon # Install as system service (macOS / Linux)
|
||||
chatlab status # Check service status
|
||||
chatlab stop # Stop and uninstall service
|
||||
clb web --daemon # Install as system service (macOS / Linux)
|
||||
clb status # Check service status
|
||||
clb stop # Stop and uninstall service
|
||||
```
|
||||
|
||||
For a full walkthrough, see the [Quick Start guide](https://docs.chatlab.fun/usage/quick-start).
|
||||
|
||||
+6
-6
@@ -43,9 +43,9 @@ npm i chatlab-cli -g
|
||||
启动 ChatLab:
|
||||
|
||||
```bash
|
||||
chatlab start # 启动 API + Web UI,并在浏览器中打开
|
||||
chatlab start --no-open # 启动 API + Web UI,但不自动打开浏览器
|
||||
chatlab start --headless # 仅启动 API,不挂载 Web UI(供脚本 / AI Agent 调用)
|
||||
clb web # 启动 API + Web UI,并在浏览器中打开
|
||||
clb web --no-open # 启动 API + Web UI,但不自动打开浏览器
|
||||
clb web --headless # 仅启动 API,不挂载 Web UI(供脚本 / AI Agent 调用)
|
||||
```
|
||||
|
||||
常用选项:`--port <端口>`(默认 3110)、`--host <地址>`、`--token <令牌>`。
|
||||
@@ -53,9 +53,9 @@ chatlab start --headless # 仅启动 API,不挂载 Web UI(供脚本 / AI Age
|
||||
如果希望服务常驻后台(开机自启 + 崩溃自动重启):
|
||||
|
||||
```bash
|
||||
chatlab start --daemon # 注册为系统服务(macOS / Linux)
|
||||
chatlab status # 查看常驻状态
|
||||
chatlab stop # 停止并取消常驻
|
||||
clb web --daemon # 注册为系统服务(macOS / Linux)
|
||||
clb status # 查看常驻状态
|
||||
clb stop # 停止并取消常驻
|
||||
```
|
||||
|
||||
完整使用说明请见[快速开始指南](https://docs.chatlab.fun/cn/usage/quick-start)。
|
||||
|
||||
@@ -113,9 +113,9 @@ function resolveSingleSessionId(dbManager: DatabaseManager): string {
|
||||
const sessionIds = dbManager.listSessionIds()
|
||||
if (sessionIds.length === 1) return sessionIds[0]!
|
||||
if (sessionIds.length === 0) {
|
||||
throw new Error('No chat sessions found. Import data first or run `chatlab sessions` to verify available sessions.')
|
||||
throw new Error('No chat sessions found. Import data first or run `clb sessions` to verify available sessions.')
|
||||
}
|
||||
throw new Error('Missing --session-id. Run `chatlab sessions` to choose a session ID.')
|
||||
throw new Error('Missing --session-id. Run `clb sessions` to choose a session ID.')
|
||||
}
|
||||
|
||||
function assertSessionExists(dbManager: DatabaseManager, sessionId: string): void {
|
||||
|
||||
+8
-7
@@ -21,7 +21,7 @@ import { registerRuntimeCommand } from './semantic-index/runtime-command'
|
||||
|
||||
const program = new Command()
|
||||
|
||||
program.name('chatlab').description('ChatLab - Chat history analysis tool').version(getVersion(), '-v, --version')
|
||||
program.name('clb').description('ChatLab - Chat history analysis tool').version(getVersion(), '-v, --version')
|
||||
|
||||
program.hook('preAction', async (_thisCommand, actionCommand) => {
|
||||
if (actionCommand.name() === 'update' || actionCommand.parent?.name() === 'runtime') return
|
||||
@@ -39,7 +39,7 @@ program
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
console.error(' Updated successfully. Please restart chatlab to use the new version.\n')
|
||||
console.error(' Updated successfully. Please restart clb to use the new version.\n')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -114,7 +114,8 @@ program
|
||||
})
|
||||
|
||||
program
|
||||
.command('start')
|
||||
.command('web')
|
||||
.alias('start')
|
||||
.description('Start ChatLab (HTTP API + Web UI)')
|
||||
.option('--port <port>', 'Server port', String(DEFAULT_API_PORT))
|
||||
.option('--host <host>', 'Listen address', '127.0.0.1')
|
||||
@@ -227,7 +228,7 @@ configCmd
|
||||
|
||||
configCmd
|
||||
.command('set <key> <value>')
|
||||
.description('Set a config field, e.g. `chatlab config set cli.allow_raw true`')
|
||||
.description('Set a config field, e.g. `clb config set cli.allow_raw true`')
|
||||
.action((key: string, value: string) => {
|
||||
try {
|
||||
const result = setConfigField(key, value)
|
||||
@@ -244,7 +245,7 @@ configCmd
|
||||
|
||||
program
|
||||
.command('stop')
|
||||
.description('Stop the resident service and remove auto-start (reverse of start --daemon)')
|
||||
.description('Stop the resident service and remove auto-start (reverse of web --daemon)')
|
||||
.action(async () => {
|
||||
const { serviceUninstall } = await import('./daemon/service')
|
||||
serviceUninstall()
|
||||
@@ -266,11 +267,11 @@ program
|
||||
console.log(` Service: ${svc.running ? 'running' : 'installed (not running)'}`)
|
||||
if (portStr) console.log(` Address: ${portStr}`)
|
||||
console.log(` Auto-start: enabled`)
|
||||
console.log(`\n Use \`chatlab stop\` to remove the service.\n`)
|
||||
console.log(`\n Use \`clb stop\` to remove the service.\n`)
|
||||
} else {
|
||||
console.log(` Service: not installed`)
|
||||
console.log(` Auto-start: disabled`)
|
||||
console.log(`\n Use \`chatlab start --daemon\` to install as a system service.\n`)
|
||||
console.log(`\n Use \`clb web --daemon\` to install as a system service.\n`)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ function buildPlist(options: ServiceInstallOptions): string {
|
||||
const port = options.port ?? 3110
|
||||
const host = options.host ?? '127.0.0.1'
|
||||
const cliEntry = resolveCliPath('bin/chatlab.mjs')
|
||||
const args = ['start', '--no-open', '--port', String(port), '--host', host]
|
||||
const args = ['web', '--no-open', '--port', String(port), '--host', host]
|
||||
if (options.token) args.push('--token', options.token)
|
||||
if (options.headless) args.push('--headless')
|
||||
if (options.requireAuth) args.push('--require-auth')
|
||||
@@ -150,7 +150,7 @@ function installMacos(options: ServiceInstallOptions): void {
|
||||
console.log(` API: http://${host}:${port}`)
|
||||
console.log(` Logs: ${LOG_FILE}`)
|
||||
console.log(` Service: ${SERVICE_LABEL} (launchd)`)
|
||||
console.log(`\nAuto-starts on login. Use \`chatlab stop\` to remove.\n`)
|
||||
console.log(`\nAuto-starts on login. Use \`clb stop\` to remove.\n`)
|
||||
}
|
||||
|
||||
function uninstallMacos(): void {
|
||||
@@ -192,7 +192,7 @@ function buildUnit(options: ServiceInstallOptions): string {
|
||||
const port = options.port ?? 3110
|
||||
const host = options.host ?? '127.0.0.1'
|
||||
const cliEntry = resolveCliPath('bin/chatlab.mjs')
|
||||
const args = ['start', '--no-open', '--port', String(port), '--host', host]
|
||||
const args = ['web', '--no-open', '--port', String(port), '--host', host]
|
||||
if (options.token) args.push('--token', options.token)
|
||||
if (options.headless) args.push('--headless')
|
||||
if (options.requireAuth) args.push('--require-auth')
|
||||
@@ -235,7 +235,7 @@ function installLinux(options: ServiceInstallOptions): void {
|
||||
console.log(` API: http://${host}:${port}`)
|
||||
console.log(` Logs: ${LOG_FILE}`)
|
||||
console.log(` Unit: ${SYSTEMD_SERVICE} (systemd)`)
|
||||
console.log(`\nAuto-starts on login. Use \`chatlab stop\` to remove.\n`)
|
||||
console.log(`\nAuto-starts on login. Use \`clb stop\` to remove.\n`)
|
||||
}
|
||||
|
||||
function uninstallLinux(): void {
|
||||
@@ -282,7 +282,7 @@ export function serviceInstall(options: ServiceInstallOptions): void {
|
||||
return installLinux(options)
|
||||
default:
|
||||
console.error('Windows is not yet supported for daemon mode.')
|
||||
console.error('Please use `chatlab start` to run in the foreground instead.')
|
||||
console.error('Please use `clb web` to run in the foreground instead.')
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export function formatPortInUseError(port: number): string {
|
||||
` ✖ Error: port ${port} is already in use.`,
|
||||
``,
|
||||
` Another process (possibly a ChatLab instance) is using this port. You can:`,
|
||||
` • Use another port: chatlab start --port <port>`,
|
||||
` • Use another port: clb web --port <port>`,
|
||||
` • Find the process: lsof -iTCP:${port} -sTCP:LISTEN`,
|
||||
``,
|
||||
].join('\n')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 反向代理路由 — /_proxy/chatlab.fun/*
|
||||
*
|
||||
* 在 Web 生产模式(chatlab start)下,将 /_proxy/chatlab.fun/* 代理到
|
||||
* 在 Web 生产模式(clb web)下,将 /_proxy/chatlab.fun/* 代理到
|
||||
* https://chatlab.fun,行为与 vite.cli-web.config.mts 中的 dev proxy 保持一致,
|
||||
* 以解决浏览器 CORS 限制。
|
||||
*
|
||||
|
||||
@@ -53,7 +53,7 @@ function normalizeImportError(message: string): NonNullable<ImportCommandEnvelop
|
||||
return {
|
||||
code: 'UNRECOGNIZED_FORMAT',
|
||||
message: 'The chat export format could not be recognized.',
|
||||
hint: 'Run "chatlab formats" and retry with --format <id>.',
|
||||
hint: 'Run "clb formats" and retry with --format <id>.',
|
||||
}
|
||||
}
|
||||
if (message.includes('sessionId contains invalid characters')) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* sessions / members query command groups.
|
||||
*
|
||||
* Parent actions keep the legacy top-level behavior (`chatlab sessions`,
|
||||
* `chatlab members <session-id>`) as deprecated aliases for one major version.
|
||||
* Parent actions keep the legacy top-level behavior (`clb sessions`,
|
||||
* `clb members <session-id>`) as deprecated aliases for one major version.
|
||||
*/
|
||||
|
||||
import type { Command } from 'commander'
|
||||
@@ -29,8 +29,8 @@ export function registerSessionCommands(program: Command): void {
|
||||
.description('Chat sessions (list, show)')
|
||||
.option('--format <format>', 'Output format (table|json for legacy list; agent|json|text for subcommands)')
|
||||
.action((options: { format?: string }) => {
|
||||
// legacy alias: `chatlab sessions [--format table|json]`
|
||||
console.error('[Deprecated] `chatlab sessions` — use `chatlab sessions list`; alias kept for one major version')
|
||||
// legacy alias: `clb sessions [--format table|json]`
|
||||
console.error('[Deprecated] `clb sessions` — use `clb sessions list`; alias kept for one major version')
|
||||
legacySessionsList(options)
|
||||
})
|
||||
|
||||
@@ -133,7 +133,7 @@ export function registerMemberCommands(program: Command): void {
|
||||
return
|
||||
}
|
||||
console.error(
|
||||
'[Deprecated] `chatlab members <session-id>` — use `chatlab members list --session <id>`; alias kept for one major version'
|
||||
'[Deprecated] `clb members <session-id>` — use `clb members list --session <id>`; alias kept for one major version'
|
||||
)
|
||||
legacyMembersList(sessionId, options)
|
||||
})
|
||||
|
||||
@@ -72,7 +72,7 @@ export function registerStatsCommands(program: Command): void {
|
||||
return
|
||||
}
|
||||
console.error(
|
||||
'[Deprecated] `chatlab stats <session-id>` — use `chatlab stats overview --session <id>`; alias kept for one major version'
|
||||
'[Deprecated] `clb stats <session-id>` — use `clb stats overview --session <id>`; alias kept for one major version'
|
||||
)
|
||||
legacyStats(sessionId, options)
|
||||
})
|
||||
|
||||
@@ -208,7 +208,7 @@ export function registerTopicCommands(program: Command): void {
|
||||
if (items.length === 0) {
|
||||
const any = getSegmentSummaries(ctx.db, { limit: 1 })
|
||||
if (any.length === 0) {
|
||||
const hint = 'Run summary generation in the ChatLab app, or use `chatlab stats keywords` as a fallback.'
|
||||
const hint = 'Run summary generation in the ChatLab app, or use `clb stats keywords` as a fallback.'
|
||||
return {
|
||||
data:
|
||||
format === 'agent'
|
||||
@@ -273,7 +273,7 @@ export function registerTopicCommands(program: Command): void {
|
||||
throw new QueryError({
|
||||
code: 'INVALID_ARGUMENT',
|
||||
message: `Invalid --id value: ${options.id}`,
|
||||
hint: 'Segment ids come from `chatlab topics list`',
|
||||
hint: 'Segment ids come from `clb topics list`',
|
||||
})
|
||||
}
|
||||
const ctx = createQueryContext(options)
|
||||
@@ -285,7 +285,7 @@ export function registerTopicCommands(program: Command): void {
|
||||
throw new QueryError({
|
||||
code: 'SEGMENT_NOT_FOUND',
|
||||
message: `Segment ${segmentId} not found`,
|
||||
hint: 'Run `chatlab topics list` to see available segments',
|
||||
hint: 'Run `clb topics list` to see available segments',
|
||||
})
|
||||
}
|
||||
const meta: Record<string, unknown> = {
|
||||
@@ -327,7 +327,7 @@ export function registerSqlCommands(program: Command): void {
|
||||
throw new QueryError({
|
||||
code: 'SQL_DISABLED',
|
||||
message: 'The sql command is disabled by configuration',
|
||||
hint: 'The user can re-enable it with `chatlab config set cli.allow_sql true`',
|
||||
hint: 'The user can re-enable it with `clb config set cli.allow_sql true`',
|
||||
})
|
||||
}
|
||||
assertRawAllowed(ctx, options)
|
||||
@@ -341,7 +341,7 @@ export function registerSqlCommands(program: Command): void {
|
||||
throw new QueryError({
|
||||
code: 'SQL_ERROR',
|
||||
message: err instanceof Error ? err.message : String(err),
|
||||
hint: 'Run `chatlab schema` to inspect available tables and columns',
|
||||
hint: 'Run `clb schema` to inspect available tables and columns',
|
||||
})
|
||||
}
|
||||
assertSqlResultPrivacyAllowed(result.columns, !!options.raw)
|
||||
|
||||
@@ -60,7 +60,7 @@ export function assertRawAllowed(ctx: Pick<QueryContext, 'allowRaw'>, options: R
|
||||
throw new QueryError({
|
||||
code: 'RAW_DISABLED',
|
||||
message: '--raw output is disabled by default',
|
||||
hint: 'The user must opt in: set CHATLAB_CLI_ALLOW_RAW=1 or `chatlab config set cli.allow_raw true`',
|
||||
hint: 'The user must opt in: set CHATLAB_CLI_ALLOW_RAW=1 or `clb config set cli.allow_raw true`',
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import { buildManifest } from './manifest'
|
||||
|
||||
function buildProgram(): Command {
|
||||
const program = new Command()
|
||||
program.name('chatlab').description('test program')
|
||||
program.name('clb').description('test program')
|
||||
|
||||
const messages = program.command('messages').description('Query messages')
|
||||
messages
|
||||
@@ -27,6 +27,7 @@ function buildProgram(): Command {
|
||||
.option('--limit <n>', 'Max results', '20')
|
||||
|
||||
program.command('import <file>').description('Import a chat history file')
|
||||
program.command('web').alias('start').description('Start ChatLab')
|
||||
|
||||
return program
|
||||
}
|
||||
@@ -51,10 +52,13 @@ describe('buildManifest', () => {
|
||||
|
||||
it('lists non-query commands by name only', () => {
|
||||
assert.ok(manifest.appCommands.some((c) => c.name === 'import'))
|
||||
assert.ok(manifest.appCommands.some((c) => c.name === 'web'))
|
||||
assert.ok(!manifest.appCommands.some((c) => c.name === 'start'))
|
||||
assert.ok(!manifest.commands.some((c) => c.name === 'import'))
|
||||
})
|
||||
|
||||
it('carries the envelope contract: exit codes, formats and version', () => {
|
||||
assert.equal(manifest.name, 'clb')
|
||||
assert.equal(manifest.version, '1.2.3')
|
||||
assert.equal(manifest.apiVersion, 1)
|
||||
assert.deepEqual(manifest.formats, ['agent', 'json', 'text'])
|
||||
@@ -66,5 +70,6 @@ describe('buildManifest', () => {
|
||||
assert.ok(manifest.examples.length >= 5)
|
||||
assert.ok(manifest.examples.every((e) => !e.command.includes('--raw')))
|
||||
assert.ok(manifest.examples.some((e) => e.command.includes('--format agent')))
|
||||
assert.ok(manifest.examples.every((e) => e.command.startsWith('clb ')))
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* `chatlab manifest`: machine-readable command tree generated from commander
|
||||
* `clb manifest`: machine-readable command tree generated from commander
|
||||
* registration (design §7 discovery). One call replaces N --help probes.
|
||||
* Query commands carry full arg/option detail; app-level commands (import,
|
||||
* start, ...) are listed by name only and stay out of the query section.
|
||||
@@ -60,31 +60,31 @@ const EXIT_CODES: Record<string, string> = {
|
||||
// Curated task recipes (design §13): agent format for message bodies,
|
||||
// json for structural scouting; --raw never appears here.
|
||||
const EXAMPLES: ManifestExample[] = [
|
||||
{ task: 'What did this group talk about today?', command: 'chatlab messages list --since today --format agent' },
|
||||
{ task: 'What did this group talk about today?', command: 'clb messages list --since today --format agent' },
|
||||
{
|
||||
task: 'Search a topic within a time range',
|
||||
command: 'chatlab messages search 旅游 --since 2026-01-01 --limit 20 --format agent',
|
||||
command: 'clb messages search 旅游 --since 2026-01-01 --limit 20 --format agent',
|
||||
},
|
||||
{
|
||||
task: 'Who mentioned it first (message ids)?',
|
||||
command: 'chatlab messages search 报销 --sort asc --limit 5 --format agent',
|
||||
command: 'clb messages search 报销 --sort asc --limit 5 --format agent',
|
||||
},
|
||||
{
|
||||
task: 'Follow up a single [#id] marker with context',
|
||||
command: 'chatlab messages context --id 1021 --window 10 --format agent',
|
||||
command: 'clb messages context --id 1021 --window 10 --format agent',
|
||||
},
|
||||
{
|
||||
task: 'Conversation between me and a member last month',
|
||||
command: 'chatlab messages between --member me --member 小红 --last 30d --format agent',
|
||||
command: 'clb messages between --member me --member 小红 --last 30d --format agent',
|
||||
},
|
||||
{ task: 'Most active members', command: 'chatlab stats activity --top 10 --format json' },
|
||||
{ task: 'Monthly hot topics', command: 'chatlab topics list --since 2026-06-01 --until 2026-06-30 --format agent' },
|
||||
{ task: 'High-frequency words', command: 'chatlab stats keywords --last 30d --top 20 --format json' },
|
||||
{ task: 'Most active members', command: 'clb stats activity --top 10 --format json' },
|
||||
{ task: 'Monthly hot topics', command: 'clb topics list --since 2026-06-01 --until 2026-06-30 --format agent' },
|
||||
{ task: 'High-frequency words', command: 'clb stats keywords --last 30d --top 20 --format json' },
|
||||
{
|
||||
task: 'Structural scouting without content',
|
||||
command: 'chatlab messages list --last 7d --no-content --fields id,senderName,time --format json',
|
||||
command: 'clb messages list --last 7d --no-content --fields id,senderName,time --format json',
|
||||
},
|
||||
{ task: 'Discover sessions first', command: 'chatlab sessions list --format json' },
|
||||
{ task: 'Discover sessions first', command: 'clb sessions list --format json' },
|
||||
]
|
||||
|
||||
const NOTES: string[] = [
|
||||
@@ -162,7 +162,7 @@ export function buildManifest(program: Command, version: string): Manifest {
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'chatlab',
|
||||
name: 'clb',
|
||||
version,
|
||||
apiVersion: API_VERSION,
|
||||
formats: ['agent', 'json', 'text'],
|
||||
|
||||
@@ -33,7 +33,7 @@ export function assertLegacySqlAllowed(config: Pick<ChatLabConfig, 'cli'>, sql?:
|
||||
throw new QueryError({
|
||||
code: 'SQL_DISABLED',
|
||||
message: 'The sql command is disabled by configuration',
|
||||
hint: 'The user can re-enable it with `chatlab config set cli.allow_sql true`',
|
||||
hint: 'The user can re-enable it with `clb config set cli.allow_sql true`',
|
||||
})
|
||||
}
|
||||
if (sql) assertSqlPrivacyAllowed(sql, false)
|
||||
@@ -44,12 +44,12 @@ export function assertLegacySqlAllowed(config: Pick<ChatLabConfig, 'cli'>, sql?:
|
||||
function registerLegacyAliases(program: Command): void {
|
||||
program
|
||||
.command('search <session-id> <keyword>', { hidden: true })
|
||||
.description('Deprecated: use `chatlab messages search`')
|
||||
.description('Deprecated: use `clb messages search`')
|
||||
.option('--limit <n>', 'Max results to return', '20')
|
||||
.option('--format <format>', 'Output format (table|json)', 'table')
|
||||
.action((sessionId: string, keyword: string, options: { limit: string; format: string }) => {
|
||||
console.error(
|
||||
'[Deprecated] `chatlab search` — use `chatlab messages search <keyword> --session <id>`; alias kept for one major version'
|
||||
'[Deprecated] `clb search` — use `clb messages search <keyword> --session <id>`; alias kept for one major version'
|
||||
)
|
||||
const { dbManager } = initRuntime()
|
||||
const db = dbManager.open(sessionId)
|
||||
@@ -78,12 +78,12 @@ function registerLegacyAliases(program: Command): void {
|
||||
|
||||
program
|
||||
.command('query <session-id>', { hidden: true })
|
||||
.description('Deprecated: use `chatlab sql`')
|
||||
.description('Deprecated: use `clb sql`')
|
||||
.requiredOption('--sql <sql>', 'SQL query statement')
|
||||
.option('--format <format>', 'Output format (table|json)', 'table')
|
||||
.action((sessionId: string, options: { sql: string; format: string }) => {
|
||||
console.error(
|
||||
'[Deprecated] `chatlab query` — use `chatlab sql "<SELECT ...>" --session <id>`; alias kept for one major version'
|
||||
'[Deprecated] `clb query` — use `clb sql "<SELECT ...>" --session <id>`; alias kept for one major version'
|
||||
)
|
||||
const { config, dbManager } = initRuntime()
|
||||
const db = dbManager.open(sessionId)
|
||||
|
||||
@@ -61,7 +61,7 @@ export function resolveSession(source: SessionSource, ref?: string): ResolvedSes
|
||||
throw new QueryError({
|
||||
code: 'SESSION_NOT_FOUND',
|
||||
message: 'No chat sessions found',
|
||||
hint: 'Import a chat export first (chatlab import <file>)',
|
||||
hint: 'Import a chat export first (clb import <file>)',
|
||||
})
|
||||
}
|
||||
throw new QueryError({
|
||||
@@ -98,7 +98,7 @@ export function resolveSession(source: SessionSource, ref?: string): ResolvedSes
|
||||
throw new QueryError({
|
||||
code: 'SESSION_NOT_FOUND',
|
||||
message: `Session '${ref}' not found`,
|
||||
hint: 'Run `chatlab sessions list` to see available sessions',
|
||||
hint: 'Run `clb sessions list` to see available sessions',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ export function resolveMember(db: DatabaseAdapter, ref: string): ResolvedMember
|
||||
throw new QueryError({
|
||||
code: 'MEMBER_NOT_FOUND',
|
||||
message: `Member id ${ref} not found`,
|
||||
hint: 'Run `chatlab members list` to see available members',
|
||||
hint: 'Run `clb members list` to see available members',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -157,6 +157,6 @@ export function resolveMember(db: DatabaseAdapter, ref: string): ResolvedMember
|
||||
throw new QueryError({
|
||||
code: 'MEMBER_NOT_FOUND',
|
||||
message: `Member '${ref}' not found`,
|
||||
hint: 'Run `chatlab members list` to see available members',
|
||||
hint: 'Run `clb members list` to see available members',
|
||||
})
|
||||
}
|
||||
@@ -260,9 +260,7 @@ export async function checkForUpdatesInteractive(): Promise<void> {
|
||||
if (choice === 1) {
|
||||
const result = await performCliSelfUpdate()
|
||||
if (result.success) {
|
||||
process.stderr.write(
|
||||
` \x1b[32m🎉 Updated successfully! Please restart chatlab to use the new version.\x1b[0m\n\n`
|
||||
)
|
||||
process.stderr.write(` \x1b[32m🎉 Updated successfully! Please restart clb to use the new version.\x1b[0m\n\n`)
|
||||
process.exit(0)
|
||||
} else {
|
||||
process.stderr.write(` ❌ Update failed: ${result.error}\n\n`)
|
||||
|
||||
@@ -31,7 +31,7 @@ function buildEnvelope(report: ChatLabValidationReport): ValidateCommandEnvelope
|
||||
error: {
|
||||
code: 'INVALID_CHATLAB_FORMAT',
|
||||
message: `Validation found ${report.errorCount} error(s).`,
|
||||
hint: 'Fix every error, rerun validation, then preview the import with "chatlab import <file> --dry-run --json".',
|
||||
hint: 'Fix every error, rerun validation, then preview the import with "clb import <file> --dry-run --json".',
|
||||
},
|
||||
meta: { apiVersion: 1 },
|
||||
}
|
||||
|
||||
+2
-2
@@ -844,8 +844,8 @@
|
||||
"消息分析视图拆分为「类型分析」和「时间分析」两个标签页,增加丰富统计洞察卡片",
|
||||
"批量重建会话索引前新增确认弹窗,防止误操作清空现有摘要",
|
||||
"演示数据扩展为 4 个文件,覆盖群组及多个私聊场景",
|
||||
"【CLI】新增统一启动命令 chatlab start,支持 --headless 和 --no-open 参数",
|
||||
"【CLI】新增后台服务模式,支持 chatlab start --daemon 安装为系统服务,以及 stop/status 命令"
|
||||
"【CLI】新增统一启动命令 clb web,支持 --headless 和 --no-open 参数",
|
||||
"【CLI】新增后台服务模式,支持 clb web --daemon 安装为系统服务,以及 stop/status 命令"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+2
-2
@@ -654,8 +654,8 @@
|
||||
- 消息分析视图拆分为「类型分析」和「时间分析」两个标签页,增加丰富统计洞察卡片
|
||||
- 批量重建会话索引前新增确认弹窗,防止误操作清空现有摘要
|
||||
- 演示数据扩展为 4 个文件,覆盖群组及多个私聊场景
|
||||
- 【CLI】新增统一启动命令 chatlab start,支持 --headless 和 --no-open 参数
|
||||
- 【CLI】新增后台服务模式,支持 chatlab start --daemon 安装为系统服务,以及 stop/status 命令
|
||||
- 【CLI】新增统一启动命令 clb web,支持 --headless 和 --no-open 参数
|
||||
- 【CLI】新增后台服务模式,支持 clb web --daemon 安装为系统服务,以及 stop/status 命令
|
||||
|
||||
### 🐛 修复
|
||||
|
||||
|
||||
+2
-2
@@ -868,8 +868,8 @@
|
||||
"Split the message analysis view into Type Analysis and Time Analysis tabs, each with enriched statistical insight cards",
|
||||
"Add a confirmation dialog before regenerating all session indexes to prevent accidental data loss",
|
||||
"Expand demo data to 4 files covering group and multiple private chat scenarios",
|
||||
"【CLI】Add unified chatlab start command with --headless and --no-open flags",
|
||||
"【CLI】Add daemon mode via chatlab start --daemon to install as a system service, with stop and status commands"
|
||||
"【CLI】Add unified clb web command with --headless and --no-open flags",
|
||||
"【CLI】Add daemon mode via clb web --daemon to install as a system service, with stop and status commands"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+2
-2
@@ -654,8 +654,8 @@
|
||||
- Split the message analysis view into Type Analysis and Time Analysis tabs, each with enriched statistical insight cards
|
||||
- Add a confirmation dialog before regenerating all session indexes to prevent accidental data loss
|
||||
- Expand demo data to 4 files covering group and multiple private chat scenarios
|
||||
- 【CLI】Add unified chatlab start command with --headless and --no-open flags
|
||||
- 【CLI】Add daemon mode via chatlab start --daemon to install as a system service, with stop and status commands
|
||||
- 【CLI】Add unified clb web command with --headless and --no-open flags
|
||||
- 【CLI】Add daemon mode via clb web --daemon to install as a system service, with stop and status commands
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
|
||||
+2
-2
@@ -860,8 +860,8 @@
|
||||
"メッセージ分析ビューを「タイプ分析」と「時間分析」の2タブに分割し、統計インサイトカードを強化",
|
||||
"セッションインデックスの一括再生成前に確認ダイアログを追加し、既存サマリーの誤削除を防止",
|
||||
"デモデータを4ファイルに拡充し、グループおよび複数のプライベートチャットシナリオをカバー",
|
||||
"【CLI】統一起動コマンド chatlab start を追加。--headlessおよび--no-openフラグに対応",
|
||||
"【CLI】chatlab start --daemonでシステムサービスとして登録するデーモンモードを追加。stopおよびstatusコマンドも利用可能"
|
||||
"【CLI】統一起動コマンド clb web を追加。--headlessおよび--no-openフラグに対応",
|
||||
"【CLI】clb web --daemonでシステムサービスとして登録するデーモンモードを追加。stopおよびstatusコマンドも利用可能"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+2
-2
@@ -654,8 +654,8 @@
|
||||
- メッセージ分析ビューを「タイプ分析」と「時間分析」の2タブに分割し、統計インサイトカードを強化
|
||||
- セッションインデックスの一括再生成前に確認ダイアログを追加し、既存サマリーの誤削除を防止
|
||||
- デモデータを4ファイルに拡充し、グループおよび複数のプライベートチャットシナリオをカバー
|
||||
- 【CLI】統一起動コマンド chatlab start を追加。--headlessおよび--no-openフラグに対応
|
||||
- 【CLI】chatlab start --daemonでシステムサービスとして登録するデーモンモードを追加。stopおよびstatusコマンドも利用可能
|
||||
- 【CLI】統一起動コマンド clb web を追加。--headlessおよび--no-openフラグに対応
|
||||
- 【CLI】clb web --daemonでシステムサービスとして登録するデーモンモードを追加。stopおよびstatusコマンドも利用可能
|
||||
|
||||
### 🐛 バグ修正
|
||||
|
||||
|
||||
+2
-2
@@ -844,8 +844,8 @@
|
||||
"訊息分析檢視拆分為「類型分析」與「時間分析」兩個分頁,提供豐富統計洞察卡片",
|
||||
"批次重建對話索引前新增確認彈窗,防止誤操作清空現有摘要",
|
||||
"示範資料擴充為 4 個檔案,涵蓋群組及多個私訊場景",
|
||||
"【CLI】新增統一啟動指令 chatlab start,支援 --headless 和 --no-open 參數",
|
||||
"【CLI】新增背景服務模式,支援 chatlab start --daemon 安裝為系統服務,以及 stop/status 指令"
|
||||
"【CLI】新增統一啟動指令 clb web,支援 --headless 和 --no-open 參數",
|
||||
"【CLI】新增背景服務模式,支援 clb web --daemon 安裝為系統服務,以及 stop/status 指令"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+2
-2
@@ -654,8 +654,8 @@
|
||||
- 訊息分析檢視拆分為「類型分析」與「時間分析」兩個分頁,提供豐富統計洞察卡片
|
||||
- 批次重建對話索引前新增確認彈窗,防止誤操作清空現有摘要
|
||||
- 示範資料擴充為 4 個檔案,涵蓋群組及多個私訊場景
|
||||
- 【CLI】新增統一啟動指令 chatlab start,支援 --headless 和 --no-open 參數
|
||||
- 【CLI】新增背景服務模式,支援 chatlab start --daemon 安裝為系統服務,以及 stop/status 指令
|
||||
- 【CLI】新增統一啟動指令 clb web,支援 --headless 和 --no-open 參數
|
||||
- 【CLI】新增背景服務模式,支援 clb web --daemon 安裝為系統服務,以及 stop/status 指令
|
||||
|
||||
### 🐛 修復
|
||||
|
||||
|
||||
@@ -21,31 +21,31 @@ npx skills add ChatLab/ChatLab --skill chatlab-analyze-cn -g
|
||||
chatlab-analyze-cn 帮我分析我和小红的聊天记录
|
||||
```
|
||||
|
||||
这个技能会引导 Agent 先执行 `chatlab manifest` 获取机读命令清单,再用安全的 `--format agent/json` 查询聊天记录。
|
||||
这个技能会引导 Agent 先执行 `clb manifest` 获取机读命令清单,再用安全的 `--format agent/json` 查询聊天记录。
|
||||
|
||||
`chatlab-analyze-cn` 始终只读。如果你希望 Agent 导入新的聊天导出文件,请改用独立的 `chatlab-import-cn` Skill;它会先预览导入计划,再自动新建或增量导入,详见[导入聊天记录指南](/cn/usage/how-to-import)。
|
||||
|
||||
## 命令总览
|
||||
|
||||
```bash
|
||||
chatlab sessions list # 列出已导入的会话
|
||||
chatlab sessions show # 查看单个会话详情
|
||||
chatlab members list # 会话成员列表
|
||||
chatlab members history # 成员改名历史
|
||||
chatlab messages list # 按时间窗口列消息
|
||||
chatlab messages search <关键词...> # 关键词搜索(支持多词、上下文、翻页)
|
||||
chatlab messages context --id <id> # 查看某条消息前后现场
|
||||
chatlab messages between # 两个成员之间的对话
|
||||
chatlab stats overview # 会话概览统计
|
||||
chatlab stats activity # 成员活跃度排行
|
||||
chatlab stats time --by day # 时间分布(hour/weekday/day/month)
|
||||
chatlab stats keywords # 高频词(已过隐私过滤)
|
||||
chatlab stats response # 回复速度排行
|
||||
chatlab topics list # AI 分段摘要列表
|
||||
chatlab topics show --id <id> # 某个分段的原始消息
|
||||
chatlab sql "<SELECT ...>" # 只读 SQL 兜底(字符串默认脱敏)
|
||||
chatlab schema # 查看数据库表结构
|
||||
chatlab manifest # 机读命令清单(给 Agent 一次读全)
|
||||
clb sessions list # 列出已导入的会话
|
||||
clb sessions show # 查看单个会话详情
|
||||
clb members list # 会话成员列表
|
||||
clb members history # 成员改名历史
|
||||
clb messages list # 按时间窗口列消息
|
||||
clb messages search <关键词...> # 关键词搜索(支持多词、上下文、翻页)
|
||||
clb messages context --id <id> # 查看某条消息前后现场
|
||||
clb messages between # 两个成员之间的对话
|
||||
clb stats overview # 会话概览统计
|
||||
clb stats activity # 成员活跃度排行
|
||||
clb stats time --by day # 时间分布(hour/weekday/day/month)
|
||||
clb stats keywords # 高频词(已过隐私过滤)
|
||||
clb stats response # 回复速度排行
|
||||
clb topics list # AI 分段摘要列表
|
||||
clb topics show --id <id> # 某个分段的原始消息
|
||||
clb sql "<SELECT ...>" # 只读 SQL 兜底(字符串默认脱敏)
|
||||
clb schema # 查看数据库表结构
|
||||
clb manifest # 机读命令清单(给 Agent 一次读全)
|
||||
```
|
||||
|
||||
只有一个会话时可省略 `--session`;多个会话时命令会返回候选列表提示消歧。
|
||||
@@ -81,15 +81,15 @@ agent/json 模式下 stdout 只包含一个 JSON 响应信封,日志一律走
|
||||
## 隐私边界
|
||||
|
||||
- 所有查询命令默认应用你在 ChatLab 设置中的脱敏规则与黑名单,包括 `stats keywords` 的词表、`topics list` 的摘要和 `sql` 结果中的字符串字段;`sql` 读取消息 `content` 列需要显式 `--raw`。
|
||||
- `--raw`(绕过预处理)默认禁用,仅当你显式执行 `chatlab config set cli.allow_raw true` 或设置 `CHATLAB_CLI_ALLOW_RAW=1` 后可用。
|
||||
- 不需要 SQL 兜底能力时,可用 `chatlab config set cli.allow_sql false` 关闭 `sql` 命令。
|
||||
- `--raw`(绕过预处理)默认禁用,仅当你显式执行 `clb config set cli.allow_raw true` 或设置 `CHATLAB_CLI_ALLOW_RAW=1` 后可用。
|
||||
- 不需要 SQL 兜底能力时,可用 `clb config set cli.allow_sql false` 关闭 `sql` 命令。
|
||||
|
||||
## 查询示例
|
||||
|
||||
典型配方——"谁最早提到某个问题?查看现场":
|
||||
|
||||
```bash
|
||||
chatlab messages search "服务器迁移" --sort asc --limit 5 --context 3 --format agent
|
||||
clb messages search "服务器迁移" --sort asc --limit 5 --context 3 --format agent
|
||||
# 从返回文本的单条消息标记 [#1021*] 拿到消息 id,再深挖现场:
|
||||
chatlab messages context --id 1021 --window 10 --format agent
|
||||
clb messages context --id 1021 --window 10 --format agent
|
||||
```
|
||||
@@ -45,7 +45,7 @@ pnpm install
|
||||
|
||||
## 平台术语
|
||||
|
||||
- **CLI Web**:由 `chatlab start` 运行,包含 Node.js 后端和 Web UI。
|
||||
- **CLI Web**:由 `clb web` 运行,包含 Node.js 后端和 Web UI。
|
||||
- **Web WASM**:无 Node.js 后端,解析、存储和查询均在浏览器内运行。
|
||||
- “Web”是两者的上位概念。上下文无法区分时,默认指 **Web WASM**。
|
||||
- “后端”或“API Server”只指 Node.js 进程,不等于完整的 CLI Web。
|
||||
|
||||
@@ -53,8 +53,8 @@ Skill 会自动选择电脑上已有的 Node.js、Python 或 Shell 工具,完
|
||||
转换完成前,Agent 必须依次执行:
|
||||
|
||||
```bash
|
||||
chatlab validate "/转换后的文件.jsonl" --json
|
||||
chatlab import "/转换后的文件.jsonl" --dry-run --json
|
||||
clb validate "/转换后的文件.jsonl" --json
|
||||
clb import "/转换后的文件.jsonl" --dry-run --json
|
||||
```
|
||||
|
||||
只有严格验证和导入预览都成功,并且源消息数与输出消息数核对一致,才会报告转换成功。转换脚本和输出文件都会保留,方便以后重新转换更新后的聊天记录。
|
||||
|
||||
@@ -386,10 +386,10 @@ JSONL(JSON Lines)格式适用于**超大规模聊天记录**(>100 万条
|
||||
ChatLab CLI 可以在不导入、不写入数据库的情况下严格验证 JSON/JSONL。它会检查坏行、协议版本、必填字段、秒级时间戳、成员引用、消息类型、消息 ID 和回复关系,并且不会输出消息正文:
|
||||
|
||||
```bash
|
||||
chatlab validate "/转换后的文件.jsonl" --json
|
||||
clb validate "/转换后的文件.jsonl" --json
|
||||
```
|
||||
|
||||
验证通过后,再使用 `chatlab import <file> --dry-run --json` 确认 ChatLab 能够完整识别该文件。
|
||||
验证通过后,再使用 `clb import <file> --dry-run --json` 确认 ChatLab 能够完整识别该文件。
|
||||
|
||||
## 版本历史
|
||||
|
||||
|
||||
@@ -92,10 +92,10 @@ docker run --name chatlab \
|
||||
容器的默认命令是:
|
||||
|
||||
```bash
|
||||
chatlab start --no-open --host 0.0.0.0
|
||||
clb web --no-open --host 0.0.0.0
|
||||
```
|
||||
|
||||
`chatlab start` 按 CLI 中的声明顺序支持以下选项:
|
||||
`clb web` 按 CLI 中的声明顺序支持以下选项:
|
||||
|
||||
| 选项 | 说明 |
|
||||
| --- | --- |
|
||||
|
||||
@@ -45,7 +45,7 @@ npm install -g chatlab-cli
|
||||
最简单的用法是直接导入一个文件:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json"
|
||||
clb import "/absolute/path/to/chat-export.json"
|
||||
```
|
||||
|
||||
### 指定已有会话
|
||||
@@ -53,7 +53,7 @@ chatlab import "/absolute/path/to/chat-export.json"
|
||||
需要明确追加到某个会话时,使用 `--session-id`:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json" --session-id <session-id>
|
||||
clb import "/absolute/path/to/chat-export.json" --session-id <session-id>
|
||||
```
|
||||
|
||||
## 自动化:使用 API 或自动同步
|
||||
|
||||
@@ -23,9 +23,9 @@ npm install --global chatlab-cli
|
||||
安装后运行:
|
||||
|
||||
```bash
|
||||
chatlab start # 启动 API + Web UI,并在浏览器中打开
|
||||
chatlab start --no-open # 启动 API + Web UI,但不自动打开浏览器
|
||||
chatlab start --headless # 仅启动 API,不提供 Web UI(供脚本 / AI Agent 调用)
|
||||
clb web # 启动 API + Web UI,并在浏览器中打开
|
||||
clb web --no-open # 启动 API + Web UI,但不自动打开浏览器
|
||||
clb web --headless # 仅启动 API,不提供 Web UI(供脚本 / AI Agent 调用)
|
||||
```
|
||||
|
||||
常用选项:`--port <端口>`(默认 `3110`)、`--host <地址>`、`--token <令牌>`。
|
||||
@@ -33,13 +33,13 @@ chatlab start --headless # 仅启动 API,不提供 Web UI(供脚本 / AI Ag
|
||||
如果希望服务常驻后台,可以使用:
|
||||
|
||||
```bash
|
||||
chatlab start --daemon # 注册为系统服务,开机自启(macOS / Linux)
|
||||
chatlab status # 查看常驻状态
|
||||
chatlab stop # 停止并取消常驻
|
||||
clb web --daemon # 注册为系统服务,开机自启(macOS / Linux)
|
||||
clb status # 查看常驻状态
|
||||
clb stop # 停止并取消常驻
|
||||
```
|
||||
|
||||
::: tip
|
||||
`clb` 是 `chatlab` 的简写,两者完全等价。
|
||||
推荐使用 `clb`。旧的 `chatlab` 命令仍会保留,以兼容已有脚本和使用习惯。
|
||||
:::
|
||||
|
||||
## Docker
|
||||
|
||||
@@ -21,31 +21,31 @@ After installation, ask Codex, Claude Code, Cursor, or another external agent:
|
||||
chatlab-analyze help me analyze my chat history with Alice
|
||||
```
|
||||
|
||||
The skill tells the agent to run `chatlab manifest` first, then query chat records safely with explicit `--format agent/json` commands.
|
||||
The skill tells the agent to run `clb manifest` first, then query chat records safely with explicit `--format agent/json` commands.
|
||||
|
||||
`chatlab-analyze` always remains read-only. To let an agent import a new chat export, use the separate `chatlab-import` skill; it previews the import, then automatically creates or incrementally updates a session. See the [Import Chat Records Guide](/usage/how-to-import).
|
||||
|
||||
## Command overview
|
||||
|
||||
```bash
|
||||
chatlab sessions list # List imported sessions
|
||||
chatlab sessions show # Session details
|
||||
chatlab members list # Session members
|
||||
chatlab members history # Member name history
|
||||
chatlab messages list # List messages in a time window
|
||||
chatlab messages search <keywords...> # Keyword search (multi-word, context, paging)
|
||||
chatlab messages context --id <id> # Messages around a specific id
|
||||
chatlab messages between # Conversation between two members
|
||||
chatlab stats overview # Session overview
|
||||
chatlab stats activity # Member activity ranking
|
||||
chatlab stats time --by day # Time distribution (hour/weekday/day/month)
|
||||
chatlab stats keywords # High-frequency words (privacy-filtered)
|
||||
chatlab stats response # Reply speed ranking
|
||||
chatlab topics list # AI segment summaries
|
||||
chatlab topics show --id <id> # Original messages of one segment
|
||||
chatlab sql "<SELECT ...>" # Read-only SQL fallback (strings desensitized)
|
||||
chatlab schema # Database schema
|
||||
chatlab manifest # Machine-readable command manifest for agents
|
||||
clb sessions list # List imported sessions
|
||||
clb sessions show # Session details
|
||||
clb members list # Session members
|
||||
clb members history # Member name history
|
||||
clb messages list # List messages in a time window
|
||||
clb messages search <keywords...> # Keyword search (multi-word, context, paging)
|
||||
clb messages context --id <id> # Messages around a specific id
|
||||
clb messages between # Conversation between two members
|
||||
clb stats overview # Session overview
|
||||
clb stats activity # Member activity ranking
|
||||
clb stats time --by day # Time distribution (hour/weekday/day/month)
|
||||
clb stats keywords # High-frequency words (privacy-filtered)
|
||||
clb stats response # Reply speed ranking
|
||||
clb topics list # AI segment summaries
|
||||
clb topics show --id <id> # Original messages of one segment
|
||||
clb sql "<SELECT ...>" # Read-only SQL fallback (strings desensitized)
|
||||
clb schema # Database schema
|
||||
clb manifest # Machine-readable command manifest for agents
|
||||
```
|
||||
|
||||
With a single session `--session` can be omitted; with multiple sessions, commands return candidates for disambiguation.
|
||||
@@ -81,15 +81,15 @@ Failures return `{ "ok": false, "error": { "code", "message", "hint", "candidate
|
||||
## Privacy boundaries
|
||||
|
||||
- All query commands apply your ChatLab desensitize rules and blacklist by default — including the `stats keywords` vocabulary, `topics list` summaries, and string cells in `sql` results; reading the message `content` column with `sql` requires explicit `--raw`.
|
||||
- `--raw` (bypassing preprocessing) is disabled by default; it only works after you explicitly run `chatlab config set cli.allow_raw true` or set `CHATLAB_CLI_ALLOW_RAW=1`.
|
||||
- If you don't need the SQL fallback, disable it with `chatlab config set cli.allow_sql false`.
|
||||
- `--raw` (bypassing preprocessing) is disabled by default; it only works after you explicitly run `clb config set cli.allow_raw true` or set `CHATLAB_CLI_ALLOW_RAW=1`.
|
||||
- If you don't need the SQL fallback, disable it with `clb config set cli.allow_sql false`.
|
||||
|
||||
## Query example
|
||||
|
||||
A typical recipe — "who mentioned this first? inspect the surrounding context":
|
||||
|
||||
```bash
|
||||
chatlab messages search "server migration" --sort asc --limit 5 --context 3 --format agent
|
||||
clb messages search "server migration" --sort asc --limit 5 --context 3 --format agent
|
||||
# Take the message id from a single-message [#1021*] marker in the returned text, then dig in:
|
||||
chatlab messages context --id 1021 --window 10 --format agent
|
||||
clb messages context --id 1021 --window 10 --format agent
|
||||
```
|
||||
@@ -45,7 +45,7 @@ For small changes, prefer targeted checks for the files or package you changed.
|
||||
|
||||
## Platform Terminology
|
||||
|
||||
- **CLI Web** runs through `chatlab start` and includes a Node.js backend plus the Web UI.
|
||||
- **CLI Web** runs through `clb web` and includes a Node.js backend plus the Web UI.
|
||||
- **Web WASM** has no Node.js backend; parsing, storage, and queries run in the browser.
|
||||
- "Web" is the umbrella term. When context cannot distinguish the platform, it defaults to **Web WASM**.
|
||||
- "Backend" and "API Server" refer only to the Node.js process, not the complete CLI Web platform.
|
||||
|
||||
@@ -53,8 +53,8 @@ If one source contains multiple conversations, the skill creates one output per
|
||||
Before reporting success, the agent must run both commands:
|
||||
|
||||
```bash
|
||||
chatlab validate "/absolute/path/to/converted.jsonl" --json
|
||||
chatlab import "/absolute/path/to/converted.jsonl" --dry-run --json
|
||||
clb validate "/absolute/path/to/converted.jsonl" --json
|
||||
clb import "/absolute/path/to/converted.jsonl" --dry-run --json
|
||||
```
|
||||
|
||||
Success requires strict validation, a successful import preview, and matching source/output message counts. The converter and outputs remain available so a newer export can be converted again.
|
||||
|
||||
@@ -309,10 +309,10 @@ JSONL (JSON Lines) format is suitable for **very large chat records** (>1 millio
|
||||
The ChatLab CLI can strictly validate JSON/JSONL without importing or writing to the database. It checks malformed lines, protocol version, required fields, second-based timestamps, member references, message types, message IDs, and reply relationships without printing message bodies:
|
||||
|
||||
```bash
|
||||
chatlab validate "/absolute/path/to/converted.jsonl" --json
|
||||
clb validate "/absolute/path/to/converted.jsonl" --json
|
||||
```
|
||||
|
||||
After validation passes, use `chatlab import <file> --dry-run --json` to confirm ChatLab can fully recognize the file.
|
||||
After validation passes, use `clb import <file> --dry-run --json` to confirm ChatLab can fully recognize the file.
|
||||
|
||||
## Version History
|
||||
|
||||
|
||||
@@ -101,10 +101,10 @@ Desktop, CLI, and Docker on the same version can share the database. Before chan
|
||||
The default container command is:
|
||||
|
||||
```bash
|
||||
chatlab start --no-open --host 0.0.0.0
|
||||
clb web --no-open --host 0.0.0.0
|
||||
```
|
||||
|
||||
The `chatlab start` options, in CLI declaration order, are:
|
||||
The `clb web` options, in CLI declaration order, are:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
|
||||
@@ -45,7 +45,7 @@ npm install -g chatlab-cli
|
||||
The simplest command imports one file directly:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json"
|
||||
clb import "/absolute/path/to/chat-export.json"
|
||||
```
|
||||
|
||||
### Target an existing session
|
||||
@@ -53,7 +53,7 @@ chatlab import "/absolute/path/to/chat-export.json"
|
||||
To append to a specific session, use `--session-id`:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json" --session-id <session-id>
|
||||
clb import "/absolute/path/to/chat-export.json" --session-id <session-id>
|
||||
```
|
||||
|
||||
## Automation: Use an API or automatic sync
|
||||
|
||||
@@ -23,9 +23,9 @@ npm install --global chatlab-cli
|
||||
After installation, run:
|
||||
|
||||
```bash
|
||||
chatlab start # Start API + Web UI and open it in a browser
|
||||
chatlab start --no-open # Start API + Web UI without opening a browser
|
||||
chatlab start --headless # Start the API without serving the Web UI (for scripts / AI Agents)
|
||||
clb web # Start API + Web UI and open it in a browser
|
||||
clb web --no-open # Start API + Web UI without opening a browser
|
||||
clb web --headless # Start the API without serving the Web UI (for scripts / AI Agents)
|
||||
```
|
||||
|
||||
Common options: `--port <port>` (default `3110`), `--host <address>`, and `--token <token>`.
|
||||
@@ -33,13 +33,13 @@ Common options: `--port <port>` (default `3110`), `--host <address>`, and `--tok
|
||||
To keep ChatLab running as a background service:
|
||||
|
||||
```bash
|
||||
chatlab start --daemon # Install as a system service (macOS / Linux)
|
||||
chatlab status # Check service status
|
||||
chatlab stop # Stop and remove the service
|
||||
clb web --daemon # Install as a system service (macOS / Linux)
|
||||
clb status # Check service status
|
||||
clb stop # Stop and remove the service
|
||||
```
|
||||
|
||||
::: tip
|
||||
`clb` is a shorthand alias for `chatlab`; both are equivalent.
|
||||
`clb` is the recommended command. The legacy `chatlab` command remains available for compatibility.
|
||||
:::
|
||||
|
||||
## Docker
|
||||
|
||||
@@ -53,8 +53,8 @@ Skill 會自動選擇電腦上已有的 Node.js、Python 或 Shell 工具,完
|
||||
轉換完成前,Agent 必須依序執行:
|
||||
|
||||
```bash
|
||||
chatlab validate "/轉換後的檔案.jsonl" --json
|
||||
chatlab import "/轉換後的檔案.jsonl" --dry-run --json
|
||||
clb validate "/轉換後的檔案.jsonl" --json
|
||||
clb import "/轉換後的檔案.jsonl" --dry-run --json
|
||||
```
|
||||
|
||||
只有嚴格驗證和匯入預覽都成功,而且來源訊息數與輸出訊息數核對一致,才會回報轉換成功。轉換腳本和輸出檔案都會保留,方便之後重新轉換更新後的聊天記錄。
|
||||
|
||||
@@ -385,10 +385,10 @@ JSONL(JSON Lines)格式適用於**超大規模聊天記錄**(>100 萬條
|
||||
ChatLab CLI 可以在不匯入、不寫入資料庫的情況下嚴格驗證 JSON/JSONL。它會檢查損壞行、協議版本、必填欄位、秒級時間戳、成員引用、訊息類型、訊息 ID 和回覆關係,並且不會輸出訊息正文:
|
||||
|
||||
```bash
|
||||
chatlab validate "/轉換後的檔案.jsonl" --json
|
||||
clb validate "/轉換後的檔案.jsonl" --json
|
||||
```
|
||||
|
||||
驗證通過後,再使用 `chatlab import <file> --dry-run --json` 確認 ChatLab 能夠完整識別該檔案。
|
||||
驗證通過後,再使用 `clb import <file> --dry-run --json` 確認 ChatLab 能夠完整識別該檔案。
|
||||
|
||||
## 版本歷史
|
||||
|
||||
|
||||
@@ -92,10 +92,10 @@ docker run --name chatlab \
|
||||
容器的預設命令是:
|
||||
|
||||
```bash
|
||||
chatlab start --no-open --host 0.0.0.0
|
||||
clb web --no-open --host 0.0.0.0
|
||||
```
|
||||
|
||||
`chatlab start` 按照 CLI 中的宣告順序支援以下選項:
|
||||
`clb web` 按照 CLI 中的宣告順序支援以下選項:
|
||||
|
||||
| 選項 | 說明 |
|
||||
| --- | --- |
|
||||
|
||||
@@ -45,7 +45,7 @@ npm install -g chatlab-cli
|
||||
最簡單的用法是直接匯入一個檔案:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json"
|
||||
clb import "/absolute/path/to/chat-export.json"
|
||||
```
|
||||
|
||||
### 指定現有工作階段
|
||||
@@ -53,7 +53,7 @@ chatlab import "/absolute/path/to/chat-export.json"
|
||||
需要明確追加到某個工作階段時,使用 `--session-id`:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json" --session-id <session-id>
|
||||
clb import "/absolute/path/to/chat-export.json" --session-id <session-id>
|
||||
```
|
||||
|
||||
## 自動化:使用 API 或自動同步
|
||||
|
||||
@@ -23,9 +23,9 @@ npm install --global chatlab-cli
|
||||
安裝完成後執行:
|
||||
|
||||
```bash
|
||||
chatlab start # 啟動 API + Web UI,並在瀏覽器中開啟
|
||||
chatlab start --no-open # 啟動 API + Web UI,但不自動開啟瀏覽器
|
||||
chatlab start --headless # 僅啟動 API,不提供 Web UI(供腳本 / AI Agent 呼叫)
|
||||
clb web # 啟動 API + Web UI,並在瀏覽器中開啟
|
||||
clb web --no-open # 啟動 API + Web UI,但不自動開啟瀏覽器
|
||||
clb web --headless # 僅啟動 API,不提供 Web UI(供腳本 / AI Agent 呼叫)
|
||||
```
|
||||
|
||||
常用選項:`--port <連接埠>`(預設 `3110`)、`--host <位址>`、`--token <令牌>`。
|
||||
@@ -33,13 +33,13 @@ chatlab start --headless # 僅啟動 API,不提供 Web UI(供腳本 / AI Ag
|
||||
若要讓服務常駐後台,可以使用:
|
||||
|
||||
```bash
|
||||
chatlab start --daemon # 註冊為系統服務,登入時自動啟動(macOS / Linux)
|
||||
chatlab status # 查看常駐狀態
|
||||
chatlab stop # 停止並移除系統服務
|
||||
clb web --daemon # 註冊為系統服務,登入時自動啟動(macOS / Linux)
|
||||
clb status # 查看常駐狀態
|
||||
clb stop # 停止並移除系統服務
|
||||
```
|
||||
|
||||
::: tip
|
||||
`clb` 是 `chatlab` 的簡寫,兩者完全相同。
|
||||
建議使用 `clb`。舊的 `chatlab` 指令仍會保留,以相容既有腳本與使用習慣。
|
||||
:::
|
||||
|
||||
## Docker
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Safe config field writer for `chatlab config set`.
|
||||
* Safe config field writer for `clb config set`.
|
||||
*
|
||||
* Wraps writeConfigField with guardrails: only schema-defined keys are accepted,
|
||||
* values are parsed by schema type, and the file is validated after writing with
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Wraps expensive analytics / NLP computations with the platform-agnostic
|
||||
* analytics cache (cacheDir/query/{sessionId}.cache.json). Used by both CLI Web
|
||||
* (`chatlab start`) and the Electron internal server so the two share one cache
|
||||
* (`clb web`) and the Electron internal server so the two share one cache
|
||||
* implementation. Validity is keyed to the product version plus the session DB
|
||||
* file fingerprint, so any release that changes query logic, and any import /
|
||||
* incremental import / member edit, transparently invalidates entries.
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@
|
||||
* Any write to the chat DB (import, incremental import, member merge/rename,
|
||||
* owner change, summary generation) changes the file and thus the fingerprint,
|
||||
* forcing a recompute. This makes the cache self-validating even across
|
||||
* processes — e.g. when `chatlab start` is serving while a separate
|
||||
* `chatlab import` mutates the same database file.
|
||||
* processes — e.g. when `clb web` is serving while a separate
|
||||
* `clb import` mutates the same database file.
|
||||
*/
|
||||
|
||||
import * as fs from 'fs'
|
||||
|
||||
@@ -3,17 +3,7 @@ import { spawnSync } from 'node:child_process'
|
||||
export function createChatlabStartCommand({ serverDir, backendPort, nodeExecutable = process.execPath }) {
|
||||
return {
|
||||
command: nodeExecutable,
|
||||
args: [
|
||||
'--watch',
|
||||
'--import',
|
||||
'tsx',
|
||||
'src/cli.ts',
|
||||
'start',
|
||||
'--headless',
|
||||
'--no-open',
|
||||
'--port',
|
||||
String(backendPort),
|
||||
],
|
||||
args: ['--watch', '--import', 'tsx', 'src/cli.ts', 'web', '--headless', '--no-open', '--port', String(backendPort)],
|
||||
options: {
|
||||
cwd: serverDir,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
|
||||
@@ -19,7 +19,7 @@ test('web dev backend runs through the current Node executable with the tsx load
|
||||
'--import',
|
||||
'tsx',
|
||||
'src/cli.ts',
|
||||
'start',
|
||||
'web',
|
||||
'--headless',
|
||||
'--no-open',
|
||||
'--port',
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
name: chatlab-analyze-cn
|
||||
description: 通过 chatlab CLI 分析本地 ChatLab 聊天记录。当用户要求外部 Agent 检查对话、查找证据、总结话题、比较成员,或基于已导入的 ChatLab 数据分析指定人物或群组关系时使用。
|
||||
description: 通过 clb CLI 分析本地 ChatLab 聊天记录。当用户要求外部 Agent 检查对话、查找证据、总结话题、比较成员,或基于已导入的 ChatLab 数据分析指定人物或群组关系时使用。
|
||||
---
|
||||
|
||||
# ChatLab 聊天分析
|
||||
|
||||
通过只读 `chatlab` CLI 查询和分析已经导入 ChatLab 的聊天记录。
|
||||
通过只读 `clb` CLI 查询和分析已经导入 ChatLab 的聊天记录。
|
||||
|
||||
## 适用场景
|
||||
|
||||
@@ -28,9 +28,9 @@ npx skills add ChatLab/ChatLab --skill chatlab-analyze-cn -g
|
||||
检查 CLI、读取当前命令契约并列出会话:
|
||||
|
||||
```bash
|
||||
chatlab --help
|
||||
chatlab manifest
|
||||
chatlab sessions list --format json
|
||||
clb --help
|
||||
clb manifest
|
||||
clb sessions list --format json
|
||||
```
|
||||
|
||||
只有一个相关会话时直接使用;多个会话或成员都可能匹配时,让用户从返回的候选项中选择。
|
||||
@@ -40,9 +40,9 @@ chatlab sessions list --format json
|
||||
先使用能直接回答问题的最简单命令:
|
||||
|
||||
```bash
|
||||
chatlab messages search "<keyword>" --session <session-id> --format agent
|
||||
chatlab messages between --member me --member <member> --session <session-id> --last 90d --format agent
|
||||
chatlab topics list --session <session-id> --last 30d --format agent
|
||||
clb messages search "<keyword>" --session <session-id> --format agent
|
||||
clb messages between --member me --member <member> --session <session-id> --last 90d --format agent
|
||||
clb topics list --session <session-id> --last 30d --format agent
|
||||
```
|
||||
|
||||
读取消息文本时使用 `--format agent`;侦察会话、成员、数量和 `--no-content` 搜索等结构时使用 `--format json`。
|
||||
@@ -52,8 +52,8 @@ chatlab topics list --session <session-id> --last 30d --format agent
|
||||
只有第一步结果不足时再深入:
|
||||
|
||||
```bash
|
||||
chatlab messages context --id 1021 --session <session-id> --window 10 --format agent
|
||||
chatlab stats keywords --session <session-id> --member <member> --last 90d --top 20 --format json
|
||||
clb messages context --id 1021 --session <session-id> --window 10 --format agent
|
||||
clb stats keywords --session <session-id> --member <member> --last 90d --top 20 --format json
|
||||
```
|
||||
|
||||
当 `meta.hasMore` 为 true 时,保持相同查询条件并使用 `--cursor <meta.nextCursor>` 继续。通过数量和 Token 参数只获取回答问题所需的上下文。
|
||||
@@ -63,8 +63,8 @@ chatlab stats keywords --session <session-id> --member <member> --last 90d --top
|
||||
只有专用命令无法回答时,才使用只读 SQL:
|
||||
|
||||
```bash
|
||||
chatlab schema --session <session-id> --format json
|
||||
chatlab sql "SELECT COUNT(*) AS n FROM message" --session <session-id> --format json
|
||||
clb schema --session <session-id> --format json
|
||||
clb sql "SELECT COUNT(*) AS n FROM message" --session <session-id> --format json
|
||||
```
|
||||
|
||||
## 隐私与回答
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
name: chatlab-analyze
|
||||
description: Analyze local ChatLab chat records through the chatlab CLI. Use when the user asks an external agent to inspect conversations, find evidence, summarize topics, compare members, or analyze a named relationship from imported ChatLab data.
|
||||
description: Analyze local ChatLab chat records through the clb CLI. Use when the user asks an external agent to inspect conversations, find evidence, summarize topics, compare members, or analyze a named relationship from imported ChatLab data.
|
||||
---
|
||||
|
||||
# ChatLab Analyze
|
||||
|
||||
Query and analyze records already imported into ChatLab through the read-only `chatlab` CLI.
|
||||
Query and analyze records already imported into ChatLab through the read-only `clb` CLI.
|
||||
|
||||
## Good Fit
|
||||
|
||||
@@ -28,9 +28,9 @@ npx skills add ChatLab/ChatLab --skill chatlab-analyze -g
|
||||
Check the CLI, load its current command contract, and list sessions:
|
||||
|
||||
```bash
|
||||
chatlab --help
|
||||
chatlab manifest
|
||||
chatlab sessions list --format json
|
||||
clb --help
|
||||
clb manifest
|
||||
clb sessions list --format json
|
||||
```
|
||||
|
||||
Use the only relevant session. If multiple sessions or members match the request, ask the user to choose from the returned candidates.
|
||||
@@ -40,9 +40,9 @@ Use the only relevant session. If multiple sessions or members match the request
|
||||
Use the simplest command that directly answers the question:
|
||||
|
||||
```bash
|
||||
chatlab messages search "<keyword>" --session <session-id> --format agent
|
||||
chatlab messages between --member me --member <member> --session <session-id> --last 90d --format agent
|
||||
chatlab topics list --session <session-id> --last 30d --format agent
|
||||
clb messages search "<keyword>" --session <session-id> --format agent
|
||||
clb messages between --member me --member <member> --session <session-id> --last 90d --format agent
|
||||
clb topics list --session <session-id> --last 30d --format agent
|
||||
```
|
||||
|
||||
Use `--format agent` for message text and `--format json` for structural scouting such as sessions, members, counts, and `--no-content` searches.
|
||||
@@ -52,8 +52,8 @@ Use `--format agent` for message text and `--format json` for structural scoutin
|
||||
Only deepen the query when the first result is insufficient:
|
||||
|
||||
```bash
|
||||
chatlab messages context --id 1021 --session <session-id> --window 10 --format agent
|
||||
chatlab stats keywords --session <session-id> --member <member> --last 90d --top 20 --format json
|
||||
clb messages context --id 1021 --session <session-id> --window 10 --format agent
|
||||
clb stats keywords --session <session-id> --member <member> --last 90d --top 20 --format json
|
||||
```
|
||||
|
||||
When `meta.hasMore` is true, continue with `--cursor <meta.nextCursor>` and the same query conditions. Use limits and token controls to retrieve only the context needed.
|
||||
@@ -63,8 +63,8 @@ When `meta.hasMore` is true, continue with `--cursor <meta.nextCursor>` and the
|
||||
Use read-only SQL only when no dedicated command can answer the question:
|
||||
|
||||
```bash
|
||||
chatlab schema --session <session-id> --format json
|
||||
chatlab sql "SELECT COUNT(*) AS n FROM message" --session <session-id> --format json
|
||||
clb schema --session <session-id> --format json
|
||||
clb sql "SELECT COUNT(*) AS n FROM message" --session <session-id> --format json
|
||||
```
|
||||
|
||||
## Privacy and Answers
|
||||
|
||||
@@ -29,20 +29,20 @@ npx skills add ChatLab/ChatLab --skill chatlab-convert-cn -g
|
||||
确认唯一、准确的源路径。存在多个候选文件时询问用户,不要猜测。每条命令都要给路径加引号。
|
||||
|
||||
```bash
|
||||
chatlab --help
|
||||
chatlab validate --help
|
||||
chatlab formats
|
||||
chatlab import "/absolute/path/to/source" --dry-run --json
|
||||
clb --help
|
||||
clb validate --help
|
||||
clb formats
|
||||
clb import "/absolute/path/to/source" --dry-run --json
|
||||
```
|
||||
|
||||
如果 dry-run 已经识别源文件,不要重复转换,改用 `chatlab-import-cn` 完成导入。
|
||||
|
||||
如果 `chatlab` 不存在,或已有版本没有 `validate` 命令:
|
||||
如果 `clb` 不存在,或已有版本没有 `validate` 命令:
|
||||
|
||||
1. 告诉用户未检测到可用的 ChatLab CLI,但仍可使用本 Skill 内置的严格验证器继续转换;
|
||||
2. 建议安装或更新 CLI,并在执行前征得用户同意:`npm install -g chatlab-cli@latest`;
|
||||
3. 用户跳过安装、安装失败或当前无法联网时,不要阻断转换,改用 `scripts/validate-chatlab.mjs`;
|
||||
4. 跳过 `chatlab formats` 和源文件 dry-run,并明确说明无法确认 ChatLab 是否已原生支持该源格式。
|
||||
4. 跳过 `clb formats` 和源文件 dry-run,并明确说明无法确认 ChatLab 是否已原生支持该源格式。
|
||||
|
||||
内置验证器需要 Node.js 20 或更高版本。如果 `node --version` 也不可用,可以继续编写转换器,但必须把结果标记为“尚未验证”,并引导用户安装 Node.js 和 `chatlab-cli`;未经同意不要自行安装。
|
||||
|
||||
@@ -104,7 +104,7 @@ chatlab import "/absolute/path/to/source" --dry-run --json
|
||||
先对受限的本地样本或脚本的 sample 模式运行转换器,然后验证。有 CLI 时运行:
|
||||
|
||||
```bash
|
||||
chatlab validate "/absolute/path/to/sample.jsonl" --json
|
||||
clb validate "/absolute/path/to/sample.jsonl" --json
|
||||
```
|
||||
|
||||
没有 CLI 时,定位本 `SKILL.md` 所在目录,并使用随 Skill 分发的验证器:
|
||||
@@ -120,8 +120,8 @@ node "/absolute/path/to/chatlab-convert-cn/scripts/validate-chatlab.mjs" "/absol
|
||||
运行完整转换,然后使用 CLI 或内置验证器验证每一个输出文件。有 CLI 时继续执行导入 dry-run:
|
||||
|
||||
```bash
|
||||
chatlab validate "/absolute/path/to/converted.jsonl" --json
|
||||
chatlab import "/absolute/path/to/converted.jsonl" --dry-run --json
|
||||
clb validate "/absolute/path/to/converted.jsonl" --json
|
||||
clb import "/absolute/path/to/converted.jsonl" --dry-run --json
|
||||
```
|
||||
|
||||
没有 CLI 时运行:
|
||||
@@ -133,7 +133,7 @@ node "/absolute/path/to/chatlab-convert-cn/scripts/validate-chatlab.mjs" "/absol
|
||||
按验证能力区分结果,不能混用结论:
|
||||
|
||||
- **格式验证通过**:CLI 或内置严格验证器返回 `ok: true`,转换器输出消息数等于验证器消息数,源消息数等于输出消息数加上用户明确接受的跳过数,且没有隐藏源解析错误;
|
||||
- **导入验证通过**:在格式验证通过的基础上,`chatlab import --dry-run --json` 也返回 `ok: true`。
|
||||
- **导入验证通过**:在格式验证通过的基础上,`clb import --dry-run --json` 也返回 `ok: true`。
|
||||
|
||||
没有 CLI 时只能报告“格式验证通过”,并提醒用户之后可以安装 CLI 完成 dry-run,或将结果文件拖入 ChatLab;不能声称已经通过导入验证。
|
||||
|
||||
@@ -152,7 +152,7 @@ node "/absolute/path/to/chatlab-convert-cn/scripts/validate-chatlab.mjs" "/absol
|
||||
如果用户明确要求导入,使用同一个已验证文件移除 `--dry-run`:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/converted.jsonl" --json
|
||||
clb import "/absolute/path/to/converted.jsonl" --json
|
||||
```
|
||||
|
||||
如果此时仍没有 CLI,说明自动导入需要 `chatlab-cli`,建议安装并征得用户同意;不能把“格式验证通过”当成已经导入。
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
生成 ChatLab Format `0.0.2` 时遵循本协议。这里只保留转换器需要的内容;生成文件以 ChatLab CLI 或本 Skill 内置严格验证器的结果为准:
|
||||
|
||||
```bash
|
||||
chatlab validate "/absolute/path/to/output.jsonl" --json
|
||||
clb validate "/absolute/path/to/output.jsonl" --json
|
||||
node "/absolute/path/to/chatlab-convert-cn/scripts/validate-chatlab.mjs" "/absolute/path/to/output.jsonl"
|
||||
```
|
||||
|
||||
两条命令按环境选择其一,不需要重复运行;内置验证器只验证格式,不代替 `chatlab import --dry-run --json` 的导入验证。
|
||||
两条命令按环境选择其一,不需要重复运行;内置验证器只验证格式,不代替 `clb import --dry-run --json` 的导入验证。
|
||||
|
||||
## 核心约束
|
||||
|
||||
@@ -141,4 +141,4 @@ node "/absolute/path/to/chatlab-convert-cn/scripts/validate-chatlab.mjs" "/absol
|
||||
- 映射为类型 `99` 的记录数;
|
||||
- 跳过数和失败数。
|
||||
|
||||
跳过数和失败数默认为零。只有源消息数等于输出消息数加用户明确接受的跳过数、严格验证通过,并且 `chatlab import <output> --dry-run --json` 成功,转换才算完成。
|
||||
跳过数和失败数默认为零。只有源消息数等于输出消息数加用户明确接受的跳过数、严格验证通过,并且 `clb import <output> --dry-run --json` 成功,转换才算完成。
|
||||
@@ -29,20 +29,20 @@ npx skills add ChatLab/ChatLab --skill chatlab-convert -g
|
||||
Resolve the exact source path. If several files could be the export, ask the user instead of guessing. Quote paths in every command.
|
||||
|
||||
```bash
|
||||
chatlab --help
|
||||
chatlab validate --help
|
||||
chatlab formats
|
||||
chatlab import "/absolute/path/to/source" --dry-run --json
|
||||
clb --help
|
||||
clb validate --help
|
||||
clb formats
|
||||
clb import "/absolute/path/to/source" --dry-run --json
|
||||
```
|
||||
|
||||
If the dry run recognizes the source, do not convert it. Use `chatlab-import` for the supported file.
|
||||
|
||||
If `chatlab` is missing, or the installed version has no `validate` command:
|
||||
If `clb` is missing, or the installed version has no `validate` command:
|
||||
|
||||
1. Tell the user that ChatLab CLI was not detected but conversion can continue with this Skill's bundled strict validator.
|
||||
2. Recommend installing or updating the CLI, and obtain permission before running `npm install -g chatlab-cli@latest`.
|
||||
3. If the user skips installation, installation fails, or the network is unavailable, continue with `scripts/validate-chatlab.mjs`.
|
||||
4. Skip `chatlab formats` and the source dry run, and state that native ChatLab support for the source format could not be checked.
|
||||
4. Skip `clb formats` and the source dry run, and state that native ChatLab support for the source format could not be checked.
|
||||
|
||||
The bundled validator requires Node.js 20 or later. If `node --version` is also unavailable, the converter may still be written, but mark the result as “not yet validated” and guide the user to install Node.js and `chatlab-cli`. Do not install either without permission.
|
||||
|
||||
@@ -104,7 +104,7 @@ Default `skipped` to zero. Mapping an unknown message to type `99` is preservati
|
||||
Run the converter on a bounded local sample or sample mode first. With the CLI available, validate that output with:
|
||||
|
||||
```bash
|
||||
chatlab validate "/absolute/path/to/sample.jsonl" --json
|
||||
clb validate "/absolute/path/to/sample.jsonl" --json
|
||||
```
|
||||
|
||||
Without the CLI, locate the directory containing this `SKILL.md` and use the bundled validator:
|
||||
@@ -120,8 +120,8 @@ Fix every validation error before running the full conversion. Review warnings a
|
||||
Run the full converter, then validate every generated file with the CLI or bundled validator. With the CLI available, also run the import dry run:
|
||||
|
||||
```bash
|
||||
chatlab validate "/absolute/path/to/converted.jsonl" --json
|
||||
chatlab import "/absolute/path/to/converted.jsonl" --dry-run --json
|
||||
clb validate "/absolute/path/to/converted.jsonl" --json
|
||||
clb import "/absolute/path/to/converted.jsonl" --dry-run --json
|
||||
```
|
||||
|
||||
Without the CLI, run:
|
||||
@@ -133,7 +133,7 @@ node "/absolute/path/to/chatlab-convert/scripts/validate-chatlab.mjs" "/absolute
|
||||
Keep the result levels distinct:
|
||||
|
||||
- **Format validated**: the CLI or bundled strict validator returns `ok: true`; converter and validator message counts match; source messages equal output messages plus explicitly accepted skipped records; and no source parse error was hidden.
|
||||
- **Import validated**: format validation passed and `chatlab import --dry-run --json` also returns `ok: true`.
|
||||
- **Import validated**: format validation passed and `clb import --dry-run --json` also returns `ok: true`.
|
||||
|
||||
Without the CLI, report only “format validated.” Tell the user they can install the CLI later to run the dry-run or drag the result into ChatLab. Do not claim import validation passed.
|
||||
|
||||
@@ -152,7 +152,7 @@ If the user asked only to convert, stop after all validation available in the cu
|
||||
If the user explicitly asked to import, run the same validated file without `--dry-run`:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/converted.jsonl" --json
|
||||
clb import "/absolute/path/to/converted.jsonl" --json
|
||||
```
|
||||
|
||||
If the CLI is still unavailable, explain that automatic import requires `chatlab-cli`, recommend installation, and obtain permission before installing it. Never treat “format validated” as already imported.
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
Use this contract when generating ChatLab Format `0.0.2`. It is intentionally limited to what a converter needs. The ChatLab CLI or this Skill's bundled strict validator is authoritative for generated files:
|
||||
|
||||
```bash
|
||||
chatlab validate "/absolute/path/to/output.jsonl" --json
|
||||
clb validate "/absolute/path/to/output.jsonl" --json
|
||||
node "/absolute/path/to/chatlab-convert/scripts/validate-chatlab.mjs" "/absolute/path/to/output.jsonl"
|
||||
```
|
||||
|
||||
Choose one command based on the environment; running both is unnecessary. The bundled validator checks the format only and does not replace import validation with `chatlab import --dry-run --json`.
|
||||
Choose one command based on the environment; running both is unnecessary. The bundled validator checks the format only and does not replace import validation with `clb import --dry-run --json`.
|
||||
|
||||
## Core invariants
|
||||
|
||||
@@ -141,4 +141,4 @@ The converter must report these numbers without message bodies:
|
||||
- records mapped to type `99`;
|
||||
- skipped and failed records.
|
||||
|
||||
Default skipped and failed records to zero. The conversion is not complete until source messages equal output messages plus user-accepted skipped records, strict validation passes, and `chatlab import <output> --dry-run --json` succeeds.
|
||||
Default skipped and failed records to zero. The conversion is not complete until source messages equal output messages plus user-accepted skipped records, strict validation passes, and `clb import <output> --dry-run --json` succeeds.
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
name: chatlab-import-cn
|
||||
description: 通过 chatlab CLI 安全预览并将本地聊天导出文件导入 ChatLab。当用户要求外部 Agent 从本地 QQ、微信、Telegram、WhatsApp、LINE、Discord、Instagram、Google Chat、ChatLab JSON/JSONL 或其他受支持的聊天导出文件执行首次导入、重新导入或增量更新时使用。
|
||||
description: 通过 clb CLI 安全预览并将本地聊天导出文件导入 ChatLab。当用户要求外部 Agent 从本地 QQ、微信、Telegram、WhatsApp、LINE、Discord、Instagram、Google Chat、ChatLab JSON/JSONL 或其他受支持的聊天导出文件执行首次导入、重新导入或增量更新时使用。
|
||||
---
|
||||
|
||||
# ChatLab 聊天导入
|
||||
|
||||
通过 `chatlab` CLI 导入本地聊天导出文件。始终先预览准确的写入计划。将用户明确提出的导入请求视为授权,预览成功后继续执行,不再请求二次确认。
|
||||
通过 `clb` CLI 导入本地聊天导出文件。始终先预览准确的写入计划。将用户明确提出的导入请求视为授权,预览成功后继续执行,不再请求二次确认。
|
||||
|
||||
## 适用场景
|
||||
|
||||
@@ -26,7 +26,7 @@ npx skills add ChatLab/ChatLab --skill chatlab-import-cn -g
|
||||
1. 检查 CLI,并确认唯一、准确的文件路径:
|
||||
|
||||
```bash
|
||||
chatlab --help
|
||||
clb --help
|
||||
```
|
||||
|
||||
如果 CLI 未安装,告诉用户运行 `npm install -g chatlab-cli`。未经批准不要自行安装软件。存在多个候选文件时不要猜测,每条命令中的路径都要加引号。
|
||||
@@ -34,7 +34,7 @@ chatlab --help
|
||||
2. 只读预览导入计划:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json" --dry-run --json
|
||||
clb import "/absolute/path/to/chat-export.json" --dry-run --json
|
||||
```
|
||||
|
||||
如果用户选择了已有会话,在预览和正式导入中都加入 `--session-id <session-id>`。
|
||||
@@ -52,7 +52,7 @@ chatlab import "/absolute/path/to/chat-export.json" --dry-run --json
|
||||
5. 根据上一步可以写入时,使用相同文件、目标和格式移除 `--dry-run`:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json" --json
|
||||
clb import "/absolute/path/to/chat-export.json" --json
|
||||
```
|
||||
|
||||
根据最终 JSON 信封报告结果会话 ID、导入模式、新增消息数和重复消息数。
|
||||
@@ -63,5 +63,5 @@ chatlab import "/absolute/path/to/chat-export.json" --json
|
||||
- 绝不泄露完整聊天导出文件或消息正文。
|
||||
- 绝不编造文件路径、解析格式或会话 ID。
|
||||
- 仅在修正方式明确时遵循 `error.hint`。
|
||||
- `FILE_NOT_FOUND` 要求正确路径;`UNRECOGNIZED_FORMAT` 查看 `chatlab formats`;`IMPORT_IN_PROGRESS` 稍后重试;`INVALID_SESSION_ID` 要求有效 ID。
|
||||
- `FILE_NOT_FOUND` 要求正确路径;`UNRECOGNIZED_FORMAT` 查看 `clb formats`;`IMPORT_IN_PROGRESS` 稍后重试;`INVALID_SESSION_ID` 要求有效 ID。
|
||||
- 优先使用用户当前使用的中文变体回答,命令、参数、JSON 字段和错误码保持原样。
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
name: chatlab-import
|
||||
description: Safely preview and import local chat export files into ChatLab through the chatlab CLI. Use when a user asks an external agent to import, re-import, or incrementally update ChatLab from a local QQ, WeChat, Telegram, WhatsApp, LINE, Discord, Instagram, Google Chat, ChatLab JSON/JSONL, or other supported chat export.
|
||||
description: Safely preview and import local chat export files into ChatLab through the clb CLI. Use when a user asks an external agent to import, re-import, or incrementally update ChatLab from a local QQ, WeChat, Telegram, WhatsApp, LINE, Discord, Instagram, Google Chat, ChatLab JSON/JSONL, or other supported chat export.
|
||||
---
|
||||
|
||||
# ChatLab Import
|
||||
|
||||
Import local chat exports through the `chatlab` CLI. Always preview the exact write. Treat an explicit request to import as authorization to continue after a successful preview; do not ask for a second confirmation.
|
||||
Import local chat exports through the `clb` CLI. Always preview the exact write. Treat an explicit request to import as authorization to continue after a successful preview; do not ask for a second confirmation.
|
||||
|
||||
## Good Fit
|
||||
|
||||
@@ -26,7 +26,7 @@ npx skills add ChatLab/ChatLab --skill chatlab-import -g
|
||||
1. Check the CLI and resolve one exact file path:
|
||||
|
||||
```bash
|
||||
chatlab --help
|
||||
clb --help
|
||||
```
|
||||
|
||||
If the CLI is missing, tell the user to install it with `npm install -g chatlab-cli`. Do not install software without approval. Do not guess between multiple files, and quote the path in every command.
|
||||
@@ -34,7 +34,7 @@ If the CLI is missing, tell the user to install it with `npm install -g chatlab-
|
||||
2. Preview the import without writing:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json" --dry-run --json
|
||||
clb import "/absolute/path/to/chat-export.json" --dry-run --json
|
||||
```
|
||||
|
||||
If the user selected an existing session, include `--session-id <session-id>` in both preview and import.
|
||||
@@ -52,7 +52,7 @@ If the user selected an existing session, include `--session-id <session-id>` in
|
||||
5. When the decision permits writing, run the same command without `--dry-run`, keeping the file, target, and format unchanged:
|
||||
|
||||
```bash
|
||||
chatlab import "/absolute/path/to/chat-export.json" --json
|
||||
clb import "/absolute/path/to/chat-export.json" --json
|
||||
```
|
||||
|
||||
Report the resulting session ID, import mode, new-message count, and duplicate count from the final JSON envelope.
|
||||
@@ -63,4 +63,4 @@ Report the resulting session ID, import mode, new-message count, and duplicate c
|
||||
- Never reveal a full chat export or message bodies.
|
||||
- Never invent a file path, parser format, or session ID.
|
||||
- Follow `error.hint` only when the correction is unambiguous.
|
||||
- For `FILE_NOT_FOUND`, request the correct path. For `UNRECOGNIZED_FORMAT`, inspect `chatlab formats`. For `IMPORT_IN_PROGRESS`, retry later. For `INVALID_SESSION_ID`, request a valid ID.
|
||||
- For `FILE_NOT_FOUND`, request the correct path. For `UNRECOGNIZED_FORMAT`, inspect `clb formats`. For `IMPORT_IN_PROGRESS`, retry later. For `INVALID_SESSION_ID`, request a valid ID.
|
||||
@@ -18,7 +18,7 @@ const clientOptions = computed(() => [
|
||||
])
|
||||
|
||||
const configText = computed(() => {
|
||||
const command = 'chatlab'
|
||||
const command = 'clb'
|
||||
const args = ['mcp']
|
||||
switch (selectedClient.value) {
|
||||
case 'codex':
|
||||
|
||||
@@ -8,7 +8,7 @@ const skillInstallCommand = computed(() => {
|
||||
const skillName = locale.value === 'zh-CN' || locale.value === 'zh-TW' ? 'chatlab-import-cn' : 'chatlab-import'
|
||||
return `npx skills add ChatLab/ChatLab --skill ${skillName} -g`
|
||||
})
|
||||
const cliImportCommand = 'chatlab import ~/Downloads/chat-export.json'
|
||||
const cliImportCommand = 'clb import ~/Downloads/chat-export.json'
|
||||
const { copy: copySkillCommand, copied: skillCommandCopied } = useClipboard({ copiedDuring: 2000 })
|
||||
const { copy: copyCliCommand, copied: cliCommandCopied } = useClipboard({ copiedDuring: 2000 })
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* CLI Web 模式下的 AIAdapter 实现
|
||||
*
|
||||
* 通过 HTTP 调用 chatlab start 后端的 /_web/ai/* 端点。
|
||||
* 通过 HTTP 调用 clb web 后端的 /_web/ai/* 端点。
|
||||
* 不支持 Web 模式的功能(文件导出等)返回安全的降级响应。
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* FetchDataAdapter — 通过 HTTP 调用 /_web/ 内部 API
|
||||
*
|
||||
* 用于 CLI Web 场景:前端通过 fetch 访问 chatlab start 后端。
|
||||
* 用于 CLI Web 场景:前端通过 fetch 访问 clb web 后端。
|
||||
*/
|
||||
|
||||
import type { AnalysisSession, MessageType } from '@/types/base'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* CLI Web Vite 构建配置
|
||||
*
|
||||
* 用于构建 CLI Web 的 SPA 前端(不含 Electron 依赖)。
|
||||
* 输出到 dist-cli-web/,由 chatlab start 托管。
|
||||
* 输出到 dist-cli-web/,由 clb web 托管。
|
||||
*
|
||||
* 与 Electron renderer 构建的关键区别:
|
||||
* - __IS_ELECTRON__ = false(使用 FetchAdapter 而非 window.chatApi)
|
||||
@@ -53,7 +53,7 @@ async function isChatlabBackendResponsive(port: number, timeoutMs = 800): Promis
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动启动 chatlab start 后端的插件
|
||||
* 自动启动 clb web 后端的插件
|
||||
* 仅在 CHATLAB_AUTO_SERVE=1 时生效(由 dev:cli-web 脚本设置)
|
||||
*/
|
||||
function chatlabServePlugin(): Plugin {
|
||||
@@ -102,11 +102,11 @@ function chatlabServePlugin(): Plugin {
|
||||
if (inUse) {
|
||||
const responsive = await isChatlabBackendResponsive(BACKEND_PORT)
|
||||
if (responsive) {
|
||||
console.log(`[chatlab start] Port ${BACKEND_PORT} already has a responsive ChatLab API, skipping`)
|
||||
console.log(`[clb web] Port ${BACKEND_PORT} already has a responsive ChatLab API, skipping`)
|
||||
return
|
||||
}
|
||||
throw new Error(
|
||||
`[chatlab start] Port ${BACKEND_PORT} is in use, but ChatLab API did not respond. Stop the stale process and restart dev:cli-web.`
|
||||
`[clb web] Port ${BACKEND_PORT} is in use, but ChatLab API did not respond. Stop the stale process and restart dev:cli-web.`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -119,15 +119,15 @@ function chatlabServePlugin(): Plugin {
|
||||
|
||||
serverProcess.stdout?.on('data', (data: Buffer) => {
|
||||
const line = data.toString().trim()
|
||||
if (line) console.log(`[chatlab start] ${line}`)
|
||||
if (line) console.log(`[clb web] ${line}`)
|
||||
})
|
||||
serverProcess.stderr?.on('data', (data: Buffer) => {
|
||||
const line = data.toString().trim()
|
||||
if (line) console.error(`[chatlab start] ${line}`)
|
||||
if (line) console.error(`[clb web] ${line}`)
|
||||
})
|
||||
serverProcess.on('exit', (code) => {
|
||||
if (code !== null && code !== 0) {
|
||||
console.error(`[chatlab start] exited with code ${code}`)
|
||||
console.error(`[clb web] exited with code ${code}`)
|
||||
}
|
||||
serverProcess = null
|
||||
unregisterProcessCleanup()
|
||||
|
||||
Reference in new issue
Block a user