@pedroaugusto04/kb-cli 1.1.16 → 1.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -54,21 +54,23 @@ export class ApiClient {
54
54
  // If unauthorized, attempt token refresh if we have a refresh token
55
55
  if (response.status === 401 && !path.includes('auth/login') && !path.includes('auth/refresh')) {
56
56
  const config = loadConfig();
57
- if (config.cookies.kb_refresh_token) {
57
+ let refreshed = false;
58
+ if (config.cookies?.kb_refresh_token) {
58
59
  try {
59
60
  const refreshResponse = await this.request('/api/auth/refresh', { method: 'POST' });
60
61
  if (refreshResponse.ok) {
61
62
  // Token was refreshed (cookies saved automatically), retry original request
62
63
  response = await this.request(path, options);
63
- }
64
- else {
65
- clearConfigAuth();
64
+ refreshed = true;
66
65
  }
67
66
  }
68
67
  catch {
69
- clearConfigAuth();
68
+ // Ignore
70
69
  }
71
70
  }
71
+ if (!refreshed) {
72
+ clearConfigAuth();
73
+ }
72
74
  }
73
75
  if (!response.ok) {
74
76
  let body;
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { loadConfig, saveConfig, clearConfigAuth } from './config.js';\n\nexport class ApiClientError extends Error {\n constructor(public status: number, message: string, public body?: unknown) {\n super(message);\n this.name = 'ApiClientError';\n }\n}\n\nfunction parseSetCookie(cookieHeaders: string[]): Record<string, string> {\n const cookies: Record<string, string> = {};\n for (const header of cookieHeaders) {\n const parts = header.split(';')[0]?.trim().split('=') || [];\n if (parts[0] && parts[1] !== undefined) {\n cookies[parts[0]] = decodeURIComponent(parts[1]);\n }\n }\n return cookies;\n}\n\nexport class ApiClient {\n private async request(path: string, options: RequestInit = {}): Promise<Response> {\n const config = loadConfig();\n const apiBase = config.apiUrl.replace(/\\/$/, '');\n let cleanPath = path;\n if (apiBase.endsWith('/api') && path.startsWith('/api')) {\n cleanPath = path.substring(4);\n }\n const url = `${apiBase}/${cleanPath.replace(/^\\//, '')}`;\n\n const headers = new Headers(options.headers || {});\n if (config.cookies.kb_access_token || config.cookies.kb_refresh_token) {\n const cookieParts: string[] = [];\n if (config.cookies.kb_access_token) cookieParts.push(`kb_access_token=${config.cookies.kb_access_token}`);\n if (config.cookies.kb_refresh_token) cookieParts.push(`kb_refresh_token=${config.cookies.kb_refresh_token}`);\n headers.set('Cookie', cookieParts.join('; '));\n }\n\n const response = await fetch(url, { ...options, headers });\n\n // Extract cookies from Set-Cookie headers\n // getSetCookie() is available in Node.js 18+ global fetch Response\n const setCookieHeaders = typeof response.headers.getSetCookie === 'function' \n ? response.headers.getSetCookie() \n : [];\n\n if (setCookieHeaders.length > 0) {\n const newCookies = parseSetCookie(setCookieHeaders);\n saveConfig({ cookies: newCookies });\n }\n\n return response;\n }\n\n async fetch(path: string, options: RequestInit = {}): Promise<any> {\n let response = await this.request(path, options);\n\n // If unauthorized, attempt token refresh if we have a refresh token\n if (response.status === 401 && !path.includes('auth/login') && !path.includes('auth/refresh')) {\n const config = loadConfig();\n if (config.cookies.kb_refresh_token) {\n try {\n const refreshResponse = await this.request('/api/auth/refresh', { method: 'POST' });\n if (refreshResponse.ok) {\n // Token was refreshed (cookies saved automatically), retry original request\n response = await this.request(path, options);\n } else {\n clearConfigAuth();\n }\n } catch {\n clearConfigAuth();\n }\n }\n }\n\n if (!response.ok) {\n let body: any;\n try {\n body = await response.json();\n } catch {\n body = await response.text().catch(() => undefined);\n }\n throw new ApiClientError(\n response.status,\n body?.message || `Request failed with status ${response.status}`,\n body\n );\n }\n\n if (response.status === 204) {\n return null;\n }\n\n return response.json();\n }\n\n async login(email: string, password: string): Promise<any> {\n clearConfigAuth(); // Reset current auth cookies\n return this.fetch('/api/auth/login', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email, password }),\n });\n }\n\n async logout(): Promise<any> {\n try {\n await this.fetch('/api/auth/logout', { method: 'POST' });\n } finally {\n clearConfigAuth();\n }\n }\n\n async ask(question: string, projectSlug?: string): Promise<any> {\n const config = loadConfig();\n return this.fetch('/api/ask', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n question,\n projectSlug: projectSlug || undefined,\n workspaceSlug: config.workspaceSlug || undefined,\n }),\n });\n }\n\n async sendAgentMessage(\n text: string,\n media?: { fileName: string; mimeType: string; sizeBytes: number; dataBase64: string },\n projectSlug?: string\n ): Promise<any> {\n const config = loadConfig();\n const activeProject = projectSlug || config.defaultProjectSlug;\n const payload = {\n messageText: text,\n senderId: 'cli-user',\n chatId: 'cli-session',\n hasMedia: !!media,\n media: media || {},\n };\n let url = `/api/conversation/agent?workspaceSlug=${encodeURIComponent(config.workspaceSlug)}`;\n if (activeProject) {\n url += `&projectSlug=${encodeURIComponent(activeProject)}`;\n }\n return this.fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n }\n\n async listProjects(): Promise<any> {\n return this.fetch('/api/projects?limit=100');\n }\n\n async listWorkspaces(): Promise<any> {\n return this.fetch('/api/workspaces');\n }\n\n async createNote(body: any): Promise<any> {\n return this.fetch('/api/notes', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n\n async updateNote(id: string, body: any): Promise<any> {\n return this.fetch(`/api/notes/${encodeURIComponent(id)}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n}\n\nexport const client = new ApiClient();\n\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { loadConfig, saveConfig, clearConfigAuth } from './config.js';\n\nexport class ApiClientError extends Error {\n constructor(public status: number, message: string, public body?: unknown) {\n super(message);\n this.name = 'ApiClientError';\n }\n}\n\nfunction parseSetCookie(cookieHeaders: string[]): Record<string, string> {\n const cookies: Record<string, string> = {};\n for (const header of cookieHeaders) {\n const parts = header.split(';')[0]?.trim().split('=') || [];\n if (parts[0] && parts[1] !== undefined) {\n cookies[parts[0]] = decodeURIComponent(parts[1]);\n }\n }\n return cookies;\n}\n\nexport class ApiClient {\n private async request(path: string, options: RequestInit = {}): Promise<Response> {\n const config = loadConfig();\n const apiBase = config.apiUrl.replace(/\\/$/, '');\n let cleanPath = path;\n if (apiBase.endsWith('/api') && path.startsWith('/api')) {\n cleanPath = path.substring(4);\n }\n const url = `${apiBase}/${cleanPath.replace(/^\\//, '')}`;\n\n const headers = new Headers(options.headers || {});\n if (config.cookies.kb_access_token || config.cookies.kb_refresh_token) {\n const cookieParts: string[] = [];\n if (config.cookies.kb_access_token) cookieParts.push(`kb_access_token=${config.cookies.kb_access_token}`);\n if (config.cookies.kb_refresh_token) cookieParts.push(`kb_refresh_token=${config.cookies.kb_refresh_token}`);\n headers.set('Cookie', cookieParts.join('; '));\n }\n\n const response = await fetch(url, { ...options, headers });\n\n // Extract cookies from Set-Cookie headers\n // getSetCookie() is available in Node.js 18+ global fetch Response\n const setCookieHeaders = typeof response.headers.getSetCookie === 'function' \n ? response.headers.getSetCookie() \n : [];\n\n if (setCookieHeaders.length > 0) {\n const newCookies = parseSetCookie(setCookieHeaders);\n saveConfig({ cookies: newCookies });\n }\n\n return response;\n }\n\n async fetch(path: string, options: RequestInit = {}): Promise<any> {\n let response = await this.request(path, options);\n\n // If unauthorized, attempt token refresh if we have a refresh token\n if (response.status === 401 && !path.includes('auth/login') && !path.includes('auth/refresh')) {\n const config = loadConfig();\n let refreshed = false;\n if (config.cookies?.kb_refresh_token) {\n try {\n const refreshResponse = await this.request('/api/auth/refresh', { method: 'POST' });\n if (refreshResponse.ok) {\n // Token was refreshed (cookies saved automatically), retry original request\n response = await this.request(path, options);\n refreshed = true;\n }\n } catch {\n // Ignore\n }\n }\n if (!refreshed) {\n clearConfigAuth();\n }\n }\n\n if (!response.ok) {\n let body: any;\n try {\n body = await response.json();\n } catch {\n body = await response.text().catch(() => undefined);\n }\n throw new ApiClientError(\n response.status,\n body?.message || `Request failed with status ${response.status}`,\n body\n );\n }\n\n if (response.status === 204) {\n return null;\n }\n\n return response.json();\n }\n\n async login(email: string, password: string): Promise<any> {\n clearConfigAuth(); // Reset current auth cookies\n return this.fetch('/api/auth/login', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email, password }),\n });\n }\n\n async logout(): Promise<any> {\n try {\n await this.fetch('/api/auth/logout', { method: 'POST' });\n } finally {\n clearConfigAuth();\n }\n }\n\n async ask(question: string, projectSlug?: string): Promise<any> {\n const config = loadConfig();\n return this.fetch('/api/ask', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n question,\n projectSlug: projectSlug || undefined,\n workspaceSlug: config.workspaceSlug || undefined,\n }),\n });\n }\n\n async sendAgentMessage(\n text: string,\n media?: { fileName: string; mimeType: string; sizeBytes: number; dataBase64: string },\n projectSlug?: string\n ): Promise<any> {\n const config = loadConfig();\n const activeProject = projectSlug || config.defaultProjectSlug;\n const payload = {\n messageText: text,\n senderId: 'cli-user',\n chatId: 'cli-session',\n hasMedia: !!media,\n media: media || {},\n };\n let url = `/api/conversation/agent?workspaceSlug=${encodeURIComponent(config.workspaceSlug)}`;\n if (activeProject) {\n url += `&projectSlug=${encodeURIComponent(activeProject)}`;\n }\n return this.fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n }\n\n async listProjects(): Promise<any> {\n return this.fetch('/api/projects?limit=100');\n }\n\n async listWorkspaces(): Promise<any> {\n return this.fetch('/api/workspaces');\n }\n\n async createNote(body: any): Promise<any> {\n return this.fetch('/api/notes', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n\n async updateNote(id: string, body: any): Promise<any> {\n return this.fetch(`/api/notes/${encodeURIComponent(id)}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n}\n\nexport const client = new ApiClient();\n\n"]}
@@ -26,14 +26,13 @@ export async function runInit() {
26
26
  console.log('\n' + pc.cyan('Google OAuth Instructions:'));
27
27
  console.log(`1. Open the following URL in your browser to log in:`);
28
28
  console.log(` ${pc.underline(pc.bold(pc.blue(googleStartUrl)))}`);
29
- console.log(`2. Once logged in, open the Developer Tools (F12) in your browser.`);
30
- console.log(`3. Under the Application tab (Storage -> Cookies), find the cookie named "${pc.bold('kb_access_token')}".`);
31
- console.log(`4. Copy its value and paste it below:\n`);
29
+ console.log(`2. Once logged in, go to your Profile page and click "Reveal Connection Token".`);
30
+ console.log(`3. Copy the token and paste it below:\n`);
32
31
  const token = await password({
33
- message: 'Paste the kb_access_token cookie value:',
32
+ message: 'Paste your Connection Token:',
34
33
  validate: (value) => {
35
34
  if (!value || !value.trim())
36
- return 'Access token value is required';
35
+ return 'Connection Token is required';
37
36
  return;
38
37
  },
39
38
  });
@@ -41,11 +40,28 @@ export async function runInit() {
41
40
  outro(pc.red('Setup cancelled.'));
42
41
  return;
43
42
  }
44
- s.start('Validating Google access token...');
43
+ s.start('Validating Google Connection Token...');
44
+ const trimmed = token.trim();
45
+ let accessToken = trimmed;
46
+ let refreshToken = undefined;
47
+ if (trimmed.startsWith('kbc_')) {
48
+ try {
49
+ const payload = Buffer.from(trimmed.slice(4), 'base64').toString('utf8');
50
+ const parsed = JSON.parse(payload);
51
+ if (parsed.accessToken && parsed.refreshToken) {
52
+ accessToken = parsed.accessToken;
53
+ refreshToken = parsed.refreshToken;
54
+ }
55
+ }
56
+ catch {
57
+ // Fallback to raw token
58
+ }
59
+ }
45
60
  saveConfig({
46
61
  apiUrl,
47
62
  cookies: {
48
- kb_access_token: token.trim(),
63
+ kb_access_token: accessToken,
64
+ kb_refresh_token: refreshToken,
49
65
  },
50
66
  });
51
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { intro, outro, text, password, select, spinner, isCancel } from '@clack/prompts';\nimport pc from 'picocolors';\nimport { saveConfig } from '../config.js';\nimport { ApiClient } from '../client.js';\n\nexport async function runInit(): Promise<void> {\n intro(pc.cyan('Knowledge Base (kb) CLI Setup'));\n\n const apiUrl = 'https://pedro-duarte.ddns.net/knowledge-base/api';\n\n const authMethod = await select({\n message: 'Select authentication method:',\n options: [\n { value: 'google', label: '1 - Google OAuth (Browser Login)' },\n { value: 'email', label: '2 - Email & Password' },\n ],\n });\n\n if (isCancel(authMethod)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n\n // Save temporary URL so ApiClient can use it for requests\n saveConfig({ apiUrl, cookies: {} });\n const client = new ApiClient();\n const s = spinner();\n\n try {\n if (authMethod === 'google') {\n const googleStartUrl = `${apiUrl}/auth/google/start?returnTo=/knowledge-base/auth`;\n console.log('\\n' + pc.cyan('Google OAuth Instructions:'));\n console.log(`1. Open the following URL in your browser to log in:`);\n console.log(` ${pc.underline(pc.bold(pc.blue(googleStartUrl)))}`);\n console.log(`2. Once logged in, open the Developer Tools (F12) in your browser.`);\n console.log(`3. Under the Application tab (Storage -> Cookies), find the cookie named \"${pc.bold('kb_access_token')}\".`);\n console.log(`4. Copy its value and paste it below:\\n`);\n\n const token = await password({\n message: 'Paste the kb_access_token cookie value:',\n validate: (value) => {\n if (!value || !value.trim()) return 'Access token value is required';\n return;\n },\n });\n\n if (isCancel(token)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n\n s.start('Validating Google access token...');\n saveConfig({\n apiUrl,\n cookies: {\n kb_access_token: token.trim(),\n },\n });\n } else {\n // Email & Password login\n const email = await text({\n message: 'Enter your account email:',\n validate: (value) => {\n if (!value || !value.trim()) return 'Email is required';\n if (!value.includes('@')) return 'Enter a valid email address';\n return;\n },\n });\n\n if (isCancel(email)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n\n const userPassword = await password({\n message: 'Enter your password:',\n validate: (value) => {\n if (!value) return 'Password is required';\n return;\n },\n });\n\n if (isCancel(userPassword)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n\n s.start('Connecting and authenticating...');\n await client.login(email.trim(), userPassword);\n }\n\n s.message('Fetching workspaces...');\n const workspacesResult = await client.listWorkspaces();\n s.stop(pc.green('Authenticated successfully!'));\n\n let selectedWorkspace = 'default';\n if (workspacesResult && Array.isArray(workspacesResult.workspaces)) {\n const workspaces = workspacesResult.workspaces;\n if (workspaces.length > 1) {\n const workspaceSelection = await select({\n message: 'Select your default workspace:',\n options: workspaces.map((w: any) => ({\n value: w.workspaceSlug,\n label: w.displayName || w.workspaceSlug,\n })),\n });\n\n if (isCancel(workspaceSelection)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n selectedWorkspace = String(workspaceSelection);\n } else if (workspaces.length === 1 && workspaces[0]) {\n selectedWorkspace = workspaces[0].workspaceSlug;\n }\n }\n\n saveConfig({\n apiUrl,\n workspaceSlug: selectedWorkspace,\n defaultProjectSlug: 'inbox',\n });\n\n outro(pc.green(`Setup complete! CLI initialized and ready in workspace \"${selectedWorkspace}\".`));\n } catch (error: any) {\n s.stop(pc.red('Authentication failed'));\n const errorMsg = error?.body?.message || error?.message || 'Unknown error';\n outro(pc.red(`Error: ${errorMsg}. Please check your credentials and URL, and run 'kb init' again.`));\n }\n}\n"]}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { intro, outro, text, password, select, spinner, isCancel } from '@clack/prompts';\nimport pc from 'picocolors';\nimport { saveConfig } from '../config.js';\nimport { ApiClient } from '../client.js';\n\nexport async function runInit(): Promise<void> {\n intro(pc.cyan('Knowledge Base (kb) CLI Setup'));\n\n const apiUrl = 'https://pedro-duarte.ddns.net/knowledge-base/api';\n\n const authMethod = await select({\n message: 'Select authentication method:',\n options: [\n { value: 'google', label: '1 - Google OAuth (Browser Login)' },\n { value: 'email', label: '2 - Email & Password' },\n ],\n });\n\n if (isCancel(authMethod)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n\n // Save temporary URL so ApiClient can use it for requests\n saveConfig({ apiUrl, cookies: {} });\n const client = new ApiClient();\n const s = spinner();\n\n try {\n if (authMethod === 'google') {\n const googleStartUrl = `${apiUrl}/auth/google/start?returnTo=/knowledge-base/auth`;\n console.log('\\n' + pc.cyan('Google OAuth Instructions:'));\n console.log(`1. Open the following URL in your browser to log in:`);\n console.log(` ${pc.underline(pc.bold(pc.blue(googleStartUrl)))}`);\n console.log(`2. Once logged in, go to your Profile page and click \"Reveal Connection Token\".`);\n console.log(`3. Copy the token and paste it below:\\n`);\n\n const token = await password({\n message: 'Paste your Connection Token:',\n validate: (value) => {\n if (!value || !value.trim()) return 'Connection Token is required';\n return;\n },\n });\n\n if (isCancel(token)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n\n s.start('Validating Google Connection Token...');\n const trimmed = token.trim();\n let accessToken = trimmed;\n let refreshToken: string | undefined = undefined;\n\n if (trimmed.startsWith('kbc_')) {\n try {\n const payload = Buffer.from(trimmed.slice(4), 'base64').toString('utf8');\n const parsed = JSON.parse(payload);\n if (parsed.accessToken && parsed.refreshToken) {\n accessToken = parsed.accessToken;\n refreshToken = parsed.refreshToken;\n }\n } catch {\n // Fallback to raw token\n }\n }\n\n saveConfig({\n apiUrl,\n cookies: {\n kb_access_token: accessToken,\n kb_refresh_token: refreshToken,\n },\n });\n } else {\n // Email & Password login\n const email = await text({\n message: 'Enter your account email:',\n validate: (value) => {\n if (!value || !value.trim()) return 'Email is required';\n if (!value.includes('@')) return 'Enter a valid email address';\n return;\n },\n });\n\n if (isCancel(email)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n\n const userPassword = await password({\n message: 'Enter your password:',\n validate: (value) => {\n if (!value) return 'Password is required';\n return;\n },\n });\n\n if (isCancel(userPassword)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n\n s.start('Connecting and authenticating...');\n await client.login(email.trim(), userPassword);\n }\n\n s.message('Fetching workspaces...');\n const workspacesResult = await client.listWorkspaces();\n s.stop(pc.green('Authenticated successfully!'));\n\n let selectedWorkspace = 'default';\n if (workspacesResult && Array.isArray(workspacesResult.workspaces)) {\n const workspaces = workspacesResult.workspaces;\n if (workspaces.length > 1) {\n const workspaceSelection = await select({\n message: 'Select your default workspace:',\n options: workspaces.map((w: any) => ({\n value: w.workspaceSlug,\n label: w.displayName || w.workspaceSlug,\n })),\n });\n\n if (isCancel(workspaceSelection)) {\n outro(pc.red('Setup cancelled.'));\n return;\n }\n selectedWorkspace = String(workspaceSelection);\n } else if (workspaces.length === 1 && workspaces[0]) {\n selectedWorkspace = workspaces[0].workspaceSlug;\n }\n }\n\n saveConfig({\n apiUrl,\n workspaceSlug: selectedWorkspace,\n defaultProjectSlug: 'inbox',\n });\n\n outro(pc.green(`Setup complete! CLI initialized and ready in workspace \"${selectedWorkspace}\".`));\n } catch (error: any) {\n s.stop(pc.red('Authentication failed'));\n const errorMsg = error?.body?.message || error?.message || 'Unknown error';\n outro(pc.red(`Error: ${errorMsg}. Please check your credentials and URL, and run 'kb init' again.`));\n }\n}\n"]}
@@ -113,7 +113,16 @@ async function syncDirectory(targetDir, defaultProject, ledgerPath, dryRun, file
113
113
  if (noteId) {
114
114
  // Update existing note
115
115
  try {
116
- await client.updateNote(noteId, notePayload);
116
+ const updatePayload = {
117
+ title: notePayload.title,
118
+ rawText: notePayload.rawText,
119
+ tags: notePayload.tags,
120
+ canonicalType: notePayload.canonicalType,
121
+ };
122
+ if (notePayload.status === 'resolved' || notePayload.status === 'archived') {
123
+ updatePayload.status = notePayload.status;
124
+ }
125
+ await client.updateNote(noteId, updatePayload);
117
126
  stats.updated++;
118
127
  console.log(pc.cyan(`Updated: ${relativePath}`));
119
128
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport pc from 'picocolors';\nimport { spinner, outro } from '@clack/prompts';\nimport { client, ApiClientError } from '../client.js';\nimport { loadConfig } from '../config.js';\n\nexport interface SyncOptions {\n dir: string;\n project?: string;\n dryRun?: boolean;\n watch?: boolean;\n}\n\ninterface LedgerEntry {\n noteId: string;\n sha256: string;\n lastModified: string;\n}\n\ninterface SyncLedger {\n lastSyncedAt: string;\n files: Record<string, LedgerEntry>;\n}\n\nexport async function runSync(options: SyncOptions): Promise<void> {\n const targetPath = path.resolve(options.dir);\n if (!fs.existsSync(targetPath)) {\n console.error(pc.red(`Error: Path not found at ${options.dir}`));\n process.exit(1);\n }\n\n const isFile = fs.statSync(targetPath).isFile();\n const targetDir = isFile ? path.dirname(targetPath) : targetPath;\n const ledgerPath = path.join(targetDir, '.kb-sync.json');\n const filesList = isFile ? [targetPath] : undefined;\n\n const config = loadConfig();\n const defaultProject = options.project || config.defaultProjectSlug || 'inbox';\n\n if (options.dryRun) {\n console.log(pc.yellow('Running in DRY-RUN mode. No changes will be written or sent to the server.'));\n }\n\n if (options.watch) {\n console.log(pc.cyan(`Starting sync in WATCH mode for: ${targetPath}`));\n await syncDirectory(targetDir, defaultProject, ledgerPath, options.dryRun || false, filesList);\n \n // Watch logic\n let debounceTimer: NodeJS.Timeout | null = null;\n fs.watch(targetPath, { recursive: !isFile }, (eventType, filename) => {\n if (!isFile) {\n if (!filename || filename.endsWith('.kb-sync.json') || !filename.endsWith('.md')) return;\n }\n \n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(async () => {\n console.log(pc.blue(`\\nChange detected in ${filename || path.basename(targetPath)}. Syncing...`));\n try {\n await syncDirectory(targetDir, defaultProject, ledgerPath, options.dryRun || false, filesList);\n } catch (err: any) {\n console.error(pc.red(`Watch sync failed: ${err.message}`));\n }\n }, 500);\n });\n \n // Keep process alive in watch mode\n await new Promise(() => {});\n return;\n }\n\n const s = spinner();\n s.start('Synchronizing files...');\n\n try {\n const stats = await syncDirectory(targetDir, defaultProject, ledgerPath, options.dryRun || false, filesList);\n s.stop(pc.green('Sync complete!'));\n \n console.log('\\n' + pc.bold('Sync Summary:'));\n console.log(` - Created: ${pc.green(stats.created)}`);\n console.log(` - Updated: ${pc.cyan(stats.updated)}`);\n console.log(` - Skipped: ${pc.gray(stats.skipped)}`);\n console.log(` - Failed: ${pc.red(stats.failed)}\\n`);\n \n outro(pc.green('Files synced successfully.'));\n } catch (error: any) {\n s.stop(pc.red('Sync failed'));\n console.error(pc.red(`Error: ${error.message || 'Failed to sync folder.'}`));\n process.exit(1);\n }\n}\n\nasync function syncDirectory(\n targetDir: string,\n defaultProject: string,\n ledgerPath: string,\n dryRun: boolean,\n filesList?: string[]\n) {\n const ledger = loadLedger(ledgerPath);\n const files = filesList || getMarkdownFiles(targetDir);\n \n const stats = { created: 0, updated: 0, skipped: 0, failed: 0 };\n const updatedLedgerFiles: Record<string, LedgerEntry> = {};\n\n for (const filePath of files) {\n // Relative path to use as key in ledger\n const relativePath = path.relative(targetDir, filePath).replace(/\\\\/g, '/');\n if (relativePath === '.kb-sync.json') continue;\n\n try {\n const content = fs.readFileSync(filePath, 'utf8');\n const sha256 = calculateSha256(content);\n const mtime = fs.statSync(filePath).mtime.toISOString();\n const filename = path.basename(filePath, '.md');\n\n const parsed = parseMarkdown(content, filename);\n const targetProject = parsed.projectSlug || defaultProject;\n\n // Determine Note ID\n let noteId: string | undefined = parsed.id || ledger.files[relativePath]?.noteId;\n\n // Check if we need to sync\n const ledgerEntry = ledger.files[relativePath];\n if (ledgerEntry && ledgerEntry.sha256 === sha256 && noteId === ledgerEntry.noteId) {\n stats.skipped++;\n updatedLedgerFiles[relativePath] = ledgerEntry;\n continue;\n }\n\n if (dryRun) {\n if (noteId) {\n console.log(pc.cyan(`[Dry-run] Would UPDATE note ${noteId} (${relativePath})`));\n stats.updated++;\n } else {\n console.log(pc.green(`[Dry-run] Would CREATE note for ${relativePath}`));\n stats.created++;\n }\n continue;\n }\n\n // Sync payload\n const notePayload = {\n title: parsed.title,\n rawText: parsed.body,\n projectSlug: targetProject,\n tags: parsed.tags || [],\n status: parsed.status || 'active',\n canonicalType: parsed.canonicalType || 'event',\n };\n\n if (noteId) {\n // Update existing note\n try {\n await client.updateNote(noteId, notePayload);\n stats.updated++;\n console.log(pc.cyan(`Updated: ${relativePath}`));\n } catch (err: any) {\n if (err instanceof ApiClientError && err.status === 404) {\n // Note was deleted remotely, treat as new creation\n console.log(pc.yellow(`Note ${noteId} not found on server. Re-creating: ${relativePath}`));\n noteId = undefined;\n } else {\n throw err;\n }\n }\n }\n\n if (!noteId) {\n // Create new note\n const res = await client.createNote(notePayload);\n const createdId = res.noteId || res.id;\n if (!createdId) {\n throw new Error('Failed to retrieve note ID from server response');\n }\n noteId = createdId;\n stats.created++;\n console.log(pc.green(`Created: ${relativePath}`));\n \n // Inject ID back to frontmatter\n injectIdIntoFrontmatter(filePath, content, noteId as string);\n }\n\n // Record in ledger\n updatedLedgerFiles[relativePath] = {\n noteId: noteId as string,\n sha256: calculateSha256(fs.readFileSync(filePath, 'utf8')), // recalculate in case we injected id\n lastModified: mtime,\n };\n\n } catch (err: any) {\n stats.failed++;\n console.error(pc.red(`Failed to sync ${relativePath}: ${err.message}`));\n }\n }\n\n if (!dryRun) {\n saveLedger(ledgerPath, {\n lastSyncedAt: new Date().toISOString(),\n files: {\n ...ledger.files,\n ...updatedLedgerFiles,\n },\n });\n }\n\n return stats;\n}\n\nconst IGNORED_DIRS = new Set([\n 'node_modules',\n 'dist',\n 'build',\n 'out',\n 'coverage',\n '.git',\n '.next',\n]);\n\nfunction getMarkdownFiles(dir: string): string[] {\n let results: string[] = [];\n const list = fs.readdirSync(dir);\n for (const file of list) {\n if (file.startsWith('.')) continue; // skip hidden dirs/files\n const filePath = path.join(dir, file);\n const stat = fs.statSync(filePath);\n if (stat && stat.isDirectory()) {\n if (IGNORED_DIRS.has(file)) continue;\n results = results.concat(getMarkdownFiles(filePath));\n } else if (file.endsWith('.md')) {\n results.push(filePath);\n }\n }\n return results;\n}\n\nfunction calculateSha256(content: string): string {\n return crypto.createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\nfunction loadLedger(ledgerPath: string): SyncLedger {\n const defaults: SyncLedger = {\n lastSyncedAt: '',\n files: {},\n };\n try {\n if (!fs.existsSync(ledgerPath)) return defaults;\n const data = fs.readFileSync(ledgerPath, 'utf8');\n return JSON.parse(data) as SyncLedger;\n } catch {\n return defaults;\n }\n}\n\nfunction saveLedger(ledgerPath: string, ledger: SyncLedger): void {\n try {\n fs.writeFileSync(ledgerPath, JSON.stringify(ledger, null, 2), 'utf8');\n } catch (err: any) {\n console.error(pc.red(`Error saving sync ledger: ${err.message}`));\n }\n}\n\ninterface ParsedMarkdown {\n id?: string;\n title?: string;\n projectSlug?: string;\n tags?: string[];\n canonicalType?: string;\n status?: string;\n body: string;\n}\n\nfunction parseMarkdown(content: string, fallbackTitle: string): ParsedMarkdown {\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n const match = content.match(frontmatterRegex);\n if (!match) {\n return { body: content.trim(), title: fallbackTitle };\n }\n const yaml = match[1];\n const body = content.replace(frontmatterRegex, '').trim();\n const metadata: Record<string, string> = {};\n for (const line of yaml.split('\\n')) {\n const colonIdx = line.indexOf(':');\n if (colonIdx > 0) {\n const key = line.substring(0, colonIdx).trim();\n const val = line.substring(colonIdx + 1).trim();\n metadata[key] = val.replace(/^['\"]|['\"]$/g, '');\n }\n }\n return {\n id: metadata.id || undefined,\n title: metadata.title || fallbackTitle,\n projectSlug: metadata.project || undefined,\n tags: metadata.tags ? metadata.tags.split(',').map(t => t.trim()).filter(Boolean) : undefined,\n canonicalType: metadata.canonicalType || undefined,\n status: metadata.status || undefined,\n body,\n };\n}\n\nfunction injectIdIntoFrontmatter(filePath: string, content: string, id: string): void {\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n const match = content.match(frontmatterRegex);\n if (match) {\n const yaml = match[1];\n if (yaml.includes('id:')) {\n const updatedYaml = yaml.replace(/id:\\s*[^\\r\\n]*/, `id: ${id}`);\n const updatedContent = content.replace(frontmatterRegex, `---\\n${updatedYaml}\\n---`);\n fs.writeFileSync(filePath, updatedContent, 'utf8');\n } else {\n const updatedYaml = `id: ${id}\\n${yaml}`;\n const updatedContent = content.replace(frontmatterRegex, `---\\n${updatedYaml}\\n---`);\n fs.writeFileSync(filePath, updatedContent, 'utf8');\n }\n } else {\n const updatedContent = `---\\nid: ${id}\\n---\\n${content}`;\n fs.writeFileSync(filePath, updatedContent, 'utf8');\n }\n}\n"]}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport pc from 'picocolors';\nimport { spinner, outro } from '@clack/prompts';\nimport { client, ApiClientError } from '../client.js';\nimport { loadConfig } from '../config.js';\n\nexport interface SyncOptions {\n dir: string;\n project?: string;\n dryRun?: boolean;\n watch?: boolean;\n}\n\ninterface LedgerEntry {\n noteId: string;\n sha256: string;\n lastModified: string;\n}\n\ninterface SyncLedger {\n lastSyncedAt: string;\n files: Record<string, LedgerEntry>;\n}\n\nexport async function runSync(options: SyncOptions): Promise<void> {\n const targetPath = path.resolve(options.dir);\n if (!fs.existsSync(targetPath)) {\n console.error(pc.red(`Error: Path not found at ${options.dir}`));\n process.exit(1);\n }\n\n const isFile = fs.statSync(targetPath).isFile();\n const targetDir = isFile ? path.dirname(targetPath) : targetPath;\n const ledgerPath = path.join(targetDir, '.kb-sync.json');\n const filesList = isFile ? [targetPath] : undefined;\n\n const config = loadConfig();\n const defaultProject = options.project || config.defaultProjectSlug || 'inbox';\n\n if (options.dryRun) {\n console.log(pc.yellow('Running in DRY-RUN mode. No changes will be written or sent to the server.'));\n }\n\n if (options.watch) {\n console.log(pc.cyan(`Starting sync in WATCH mode for: ${targetPath}`));\n await syncDirectory(targetDir, defaultProject, ledgerPath, options.dryRun || false, filesList);\n\n // Watch logic\n let debounceTimer: NodeJS.Timeout | null = null;\n fs.watch(targetPath, { recursive: !isFile }, (eventType, filename) => {\n if (!isFile) {\n if (!filename || filename.endsWith('.kb-sync.json') || !filename.endsWith('.md')) return;\n }\n\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(async () => {\n console.log(pc.blue(`\\nChange detected in ${filename || path.basename(targetPath)}. Syncing...`));\n try {\n await syncDirectory(targetDir, defaultProject, ledgerPath, options.dryRun || false, filesList);\n } catch (err: any) {\n console.error(pc.red(`Watch sync failed: ${err.message}`));\n }\n }, 500);\n });\n\n // Keep process alive in watch mode\n await new Promise(() => { });\n return;\n }\n\n const s = spinner();\n s.start('Synchronizing files...');\n\n try {\n const stats = await syncDirectory(targetDir, defaultProject, ledgerPath, options.dryRun || false, filesList);\n s.stop(pc.green('Sync complete!'));\n\n console.log('\\n' + pc.bold('Sync Summary:'));\n console.log(` - Created: ${pc.green(stats.created)}`);\n console.log(` - Updated: ${pc.cyan(stats.updated)}`);\n console.log(` - Skipped: ${pc.gray(stats.skipped)}`);\n console.log(` - Failed: ${pc.red(stats.failed)}\\n`);\n\n outro(pc.green('Files synced successfully.'));\n } catch (error: any) {\n s.stop(pc.red('Sync failed'));\n console.error(pc.red(`Error: ${error.message || 'Failed to sync folder.'}`));\n process.exit(1);\n }\n}\n\nasync function syncDirectory(\n targetDir: string,\n defaultProject: string,\n ledgerPath: string,\n dryRun: boolean,\n filesList?: string[]\n) {\n const ledger = loadLedger(ledgerPath);\n const files = filesList || getMarkdownFiles(targetDir);\n\n const stats = { created: 0, updated: 0, skipped: 0, failed: 0 };\n const updatedLedgerFiles: Record<string, LedgerEntry> = {};\n\n for (const filePath of files) {\n // Relative path to use as key in ledger\n const relativePath = path.relative(targetDir, filePath).replace(/\\\\/g, '/');\n if (relativePath === '.kb-sync.json') continue;\n\n try {\n const content = fs.readFileSync(filePath, 'utf8');\n const sha256 = calculateSha256(content);\n const mtime = fs.statSync(filePath).mtime.toISOString();\n const filename = path.basename(filePath, '.md');\n\n const parsed = parseMarkdown(content, filename);\n const targetProject = parsed.projectSlug || defaultProject;\n\n // Determine Note ID\n let noteId: string | undefined = parsed.id || ledger.files[relativePath]?.noteId;\n\n // Check if we need to sync\n const ledgerEntry = ledger.files[relativePath];\n if (ledgerEntry && ledgerEntry.sha256 === sha256 && noteId === ledgerEntry.noteId) {\n stats.skipped++;\n updatedLedgerFiles[relativePath] = ledgerEntry;\n continue;\n }\n\n if (dryRun) {\n if (noteId) {\n console.log(pc.cyan(`[Dry-run] Would UPDATE note ${noteId} (${relativePath})`));\n stats.updated++;\n } else {\n console.log(pc.green(`[Dry-run] Would CREATE note for ${relativePath}`));\n stats.created++;\n }\n continue;\n }\n\n // Sync payload\n const notePayload = {\n title: parsed.title,\n rawText: parsed.body,\n projectSlug: targetProject,\n tags: parsed.tags || [],\n status: parsed.status || 'active',\n canonicalType: parsed.canonicalType || 'event',\n };\n\n if (noteId) {\n // Update existing note\n try {\n const updatePayload: any = {\n title: notePayload.title,\n rawText: notePayload.rawText,\n tags: notePayload.tags,\n canonicalType: notePayload.canonicalType,\n };\n if (notePayload.status === 'resolved' || notePayload.status === 'archived') {\n updatePayload.status = notePayload.status;\n }\n await client.updateNote(noteId, updatePayload);\n stats.updated++;\n console.log(pc.cyan(`Updated: ${relativePath}`));\n } catch (err: any) {\n if (err instanceof ApiClientError && err.status === 404) {\n // Note was deleted remotely, treat as new creation\n console.log(pc.yellow(`Note ${noteId} not found on server. Re-creating: ${relativePath}`));\n noteId = undefined;\n } else {\n throw err;\n }\n }\n }\n\n if (!noteId) {\n // Create new note\n const res = await client.createNote(notePayload);\n const createdId = res.noteId || res.id;\n if (!createdId) {\n throw new Error('Failed to retrieve note ID from server response');\n }\n noteId = createdId;\n stats.created++;\n console.log(pc.green(`Created: ${relativePath}`));\n\n // Inject ID back to frontmatter\n injectIdIntoFrontmatter(filePath, content, noteId as string);\n }\n\n // Record in ledger\n updatedLedgerFiles[relativePath] = {\n noteId: noteId as string,\n sha256: calculateSha256(fs.readFileSync(filePath, 'utf8')), // recalculate in case we injected id\n lastModified: mtime,\n };\n\n } catch (err: any) {\n stats.failed++;\n console.error(pc.red(`Failed to sync ${relativePath}: ${err.message}`));\n }\n }\n\n if (!dryRun) {\n saveLedger(ledgerPath, {\n lastSyncedAt: new Date().toISOString(),\n files: {\n ...ledger.files,\n ...updatedLedgerFiles,\n },\n });\n }\n\n return stats;\n}\n\nconst IGNORED_DIRS = new Set([\n 'node_modules',\n 'dist',\n 'build',\n 'out',\n 'coverage',\n '.git',\n '.next',\n]);\n\nfunction getMarkdownFiles(dir: string): string[] {\n let results: string[] = [];\n const list = fs.readdirSync(dir);\n for (const file of list) {\n if (file.startsWith('.')) continue; // skip hidden dirs/files\n const filePath = path.join(dir, file);\n const stat = fs.statSync(filePath);\n if (stat && stat.isDirectory()) {\n if (IGNORED_DIRS.has(file)) continue;\n results = results.concat(getMarkdownFiles(filePath));\n } else if (file.endsWith('.md')) {\n results.push(filePath);\n }\n }\n return results;\n}\n\nfunction calculateSha256(content: string): string {\n return crypto.createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\nfunction loadLedger(ledgerPath: string): SyncLedger {\n const defaults: SyncLedger = {\n lastSyncedAt: '',\n files: {},\n };\n try {\n if (!fs.existsSync(ledgerPath)) return defaults;\n const data = fs.readFileSync(ledgerPath, 'utf8');\n return JSON.parse(data) as SyncLedger;\n } catch {\n return defaults;\n }\n}\n\nfunction saveLedger(ledgerPath: string, ledger: SyncLedger): void {\n try {\n fs.writeFileSync(ledgerPath, JSON.stringify(ledger, null, 2), 'utf8');\n } catch (err: any) {\n console.error(pc.red(`Error saving sync ledger: ${err.message}`));\n }\n}\n\ninterface ParsedMarkdown {\n id?: string;\n title?: string;\n projectSlug?: string;\n tags?: string[];\n canonicalType?: string;\n status?: string;\n body: string;\n}\n\nfunction parseMarkdown(content: string, fallbackTitle: string): ParsedMarkdown {\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n const match = content.match(frontmatterRegex);\n if (!match) {\n return { body: content.trim(), title: fallbackTitle };\n }\n const yaml = match[1];\n const body = content.replace(frontmatterRegex, '').trim();\n const metadata: Record<string, string> = {};\n for (const line of yaml.split('\\n')) {\n const colonIdx = line.indexOf(':');\n if (colonIdx > 0) {\n const key = line.substring(0, colonIdx).trim();\n const val = line.substring(colonIdx + 1).trim();\n metadata[key] = val.replace(/^['\"]|['\"]$/g, '');\n }\n }\n return {\n id: metadata.id || undefined,\n title: metadata.title || fallbackTitle,\n projectSlug: metadata.project || undefined,\n tags: metadata.tags ? metadata.tags.split(',').map(t => t.trim()).filter(Boolean) : undefined,\n canonicalType: metadata.canonicalType || undefined,\n status: metadata.status || undefined,\n body,\n };\n}\n\nfunction injectIdIntoFrontmatter(filePath: string, content: string, id: string): void {\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n const match = content.match(frontmatterRegex);\n if (match) {\n const yaml = match[1];\n if (yaml.includes('id:')) {\n const updatedYaml = yaml.replace(/id:\\s*[^\\r\\n]*/, `id: ${id}`);\n const updatedContent = content.replace(frontmatterRegex, `---\\n${updatedYaml}\\n---`);\n fs.writeFileSync(filePath, updatedContent, 'utf8');\n } else {\n const updatedYaml = `id: ${id}\\n${yaml}`;\n const updatedContent = content.replace(frontmatterRegex, `---\\n${updatedYaml}\\n---`);\n fs.writeFileSync(filePath, updatedContent, 'utf8');\n }\n } else {\n const updatedContent = `---\\nid: ${id}\\n---\\n${content}`;\n fs.writeFileSync(filePath, updatedContent, 'utf8');\n }\n}\n"]}
package/dist/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pedroaugusto04/kb-cli",
3
- "version": "1.1.16",
3
+ "version": "1.1.18",
4
4
  "description": "CLI client for the Knowledge Base AI system",
5
5
  "type": "module",
6
6
  "bin": {