@pedroaugusto04/kb-cli 1.1.9 → 1.1.10

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.
@@ -3,7 +3,7 @@ import path from 'node:path';
3
3
  import pc from 'picocolors';
4
4
  import { text as clackText, isCancel, spinner } from '@clack/prompts';
5
5
  import { client, ApiClientError } from '../client.js';
6
- function getMimeType(filePath) {
6
+ function getMimeType(filePath, buffer) {
7
7
  const ext = path.extname(filePath).toLowerCase();
8
8
  const map = {
9
9
  '.png': 'image/png',
@@ -28,7 +28,22 @@ function getMimeType(filePath) {
28
28
  '.py': 'text/x-python',
29
29
  '.sh': 'text/x-shellscript',
30
30
  };
31
- return map[ext] || 'application/octet-stream';
31
+ if (map[ext])
32
+ return map[ext];
33
+ if (buffer) {
34
+ const limit = Math.min(buffer.length, 1024);
35
+ let isBinary = false;
36
+ for (let i = 0; i < limit; i++) {
37
+ if (buffer[i] === 0) {
38
+ isBinary = true;
39
+ break;
40
+ }
41
+ }
42
+ if (!isBinary) {
43
+ return 'text/plain';
44
+ }
45
+ }
46
+ return 'application/octet-stream';
32
47
  }
33
48
  export async function runNote(noteText, options) {
34
49
  let media;
@@ -43,7 +58,7 @@ export async function runNote(noteText, options) {
43
58
  const buffer = fs.readFileSync(filePath);
44
59
  media = {
45
60
  fileName: path.basename(filePath),
46
- mimeType: getMimeType(filePath),
61
+ mimeType: getMimeType(filePath, buffer),
47
62
  sizeBytes: stats.size,
48
63
  dataBase64: buffer.toString('base64'),
49
64
  };
@@ -1 +1 @@
1
- {"version":3,"file":"note.js","sourceRoot":"","sources":["../../src/commands/note.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport pc from 'picocolors';\nimport { text as clackText, isCancel, spinner } from '@clack/prompts';\nimport { client, ApiClientError } from '../client.js';\n\nfunction getMimeType(filePath: string): string {\n const ext = path.extname(filePath).toLowerCase();\n const map: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.webp': 'image/webp',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.pdf': 'application/pdf',\n '.txt': 'text/plain',\n '.md': 'text/markdown',\n '.json': 'application/json',\n '.csv': 'text/csv',\n '.log': 'text/plain',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n '.xml': 'text/xml',\n '.js': 'application/javascript',\n '.ts': 'application/typescript',\n '.html': 'text/html',\n '.css': 'text/css',\n '.py': 'text/x-python',\n '.sh': 'text/x-shellscript',\n };\n return map[ext] || 'application/octet-stream';\n}\n\nexport async function runNote(noteText: string, options: { file?: string; project?: string }): Promise<void> {\n let media: { fileName: string; mimeType: string; sizeBytes: number; dataBase64: string } | undefined;\n\n if (options.file) {\n const filePath = path.resolve(options.file);\n if (!fs.existsSync(filePath)) {\n console.error(pc.red(`Error: File not found at ${options.file}`));\n process.exit(1);\n }\n try {\n const stats = fs.statSync(filePath);\n const buffer = fs.readFileSync(filePath);\n media = {\n fileName: path.basename(filePath),\n mimeType: getMimeType(filePath),\n sizeBytes: stats.size,\n dataBase64: buffer.toString('base64'),\n };\n } catch (err: any) {\n console.error(pc.red(`Error reading file: ${err.message}`));\n process.exit(1);\n }\n }\n\n const s = spinner();\n s.start('Sending message to agent...');\n\n try {\n let response = await client.sendAgentMessage(noteText, media, options.project);\n \n // Clear media after first turn so we don't re-upload on subsequent clarification turns\n media = undefined;\n\n while (response) {\n const action = response.action;\n const replyText = response.replyText || '';\n\n if (action === 'submit') {\n s.stop(pc.green('Success!'));\n console.log('\\n' + pc.cyan(replyText) + '\\n');\n break;\n }\n\n if (action === 'cancel') {\n s.stop(pc.yellow('Cancelled'));\n console.log('\\n' + pc.yellow(replyText) + '\\n');\n break;\n }\n\n if (action === 'ask') {\n s.stop(pc.cyan('Clarification needed'));\n console.log('\\n' + pc.magenta('🤖 ' + replyText));\n\n const userReply = await clackText({\n message: 'Your reply:',\n validate: (val) => {\n if (!val || !val.trim()) return 'Reply cannot be empty. Type \"cancel\" to abort.';\n return;\n },\n });\n\n if (isCancel(userReply)) {\n s.start('Cancelling session...');\n response = await client.sendAgentMessage('cancel', undefined, options.project);\n continue;\n }\n\n s.start('Sending reply...');\n response = await client.sendAgentMessage(String(userReply), undefined, options.project);\n } else {\n // Fallback for unexpected states\n s.stop(pc.green('Response received'));\n console.log('\\n' + replyText + '\\n');\n break;\n }\n }\n } catch (error: any) {\n s.stop(pc.red('Error processing agent conversation'));\n if (error instanceof ApiClientError) {\n console.error(pc.red(`Error (${error.status}): ${(error.body as any)?.message || error.message}`));\n } else {\n console.error(pc.red(`Error: ${error.message || 'Failed to communicate with agent'}`));\n }\n process.exit(1);\n }\n}\n"]}
1
+ {"version":3,"file":"note.js","sourceRoot":"","sources":["../../src/commands/note.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport pc from 'picocolors';\nimport { text as clackText, isCancel, spinner } from '@clack/prompts';\nimport { client, ApiClientError } from '../client.js';\n\nfunction getMimeType(filePath: string, buffer?: Buffer): string {\n const ext = path.extname(filePath).toLowerCase();\n const map: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.webp': 'image/webp',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.pdf': 'application/pdf',\n '.txt': 'text/plain',\n '.md': 'text/markdown',\n '.json': 'application/json',\n '.csv': 'text/csv',\n '.log': 'text/plain',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n '.xml': 'text/xml',\n '.js': 'application/javascript',\n '.ts': 'application/typescript',\n '.html': 'text/html',\n '.css': 'text/css',\n '.py': 'text/x-python',\n '.sh': 'text/x-shellscript',\n };\n \n if (map[ext]) return map[ext];\n\n if (buffer) {\n const limit = Math.min(buffer.length, 1024);\n let isBinary = false;\n for (let i = 0; i < limit; i++) {\n if (buffer[i] === 0) {\n isBinary = true;\n break;\n }\n }\n if (!isBinary) {\n return 'text/plain';\n }\n }\n\n return 'application/octet-stream';\n}\n\nexport async function runNote(noteText: string, options: { file?: string; project?: string }): Promise<void> {\n let media: { fileName: string; mimeType: string; sizeBytes: number; dataBase64: string } | undefined;\n\n if (options.file) {\n const filePath = path.resolve(options.file);\n if (!fs.existsSync(filePath)) {\n console.error(pc.red(`Error: File not found at ${options.file}`));\n process.exit(1);\n }\n try {\n const stats = fs.statSync(filePath);\n const buffer = fs.readFileSync(filePath);\n media = {\n fileName: path.basename(filePath),\n mimeType: getMimeType(filePath, buffer),\n sizeBytes: stats.size,\n dataBase64: buffer.toString('base64'),\n };\n } catch (err: any) {\n console.error(pc.red(`Error reading file: ${err.message}`));\n process.exit(1);\n }\n }\n\n const s = spinner();\n s.start('Sending message to agent...');\n\n try {\n let response = await client.sendAgentMessage(noteText, media, options.project);\n \n // Clear media after first turn so we don't re-upload on subsequent clarification turns\n media = undefined;\n\n while (response) {\n const action = response.action;\n const replyText = response.replyText || '';\n\n if (action === 'submit') {\n s.stop(pc.green('Success!'));\n console.log('\\n' + pc.cyan(replyText) + '\\n');\n break;\n }\n\n if (action === 'cancel') {\n s.stop(pc.yellow('Cancelled'));\n console.log('\\n' + pc.yellow(replyText) + '\\n');\n break;\n }\n\n if (action === 'ask') {\n s.stop(pc.cyan('Clarification needed'));\n console.log('\\n' + pc.magenta('🤖 ' + replyText));\n\n const userReply = await clackText({\n message: 'Your reply:',\n validate: (val) => {\n if (!val || !val.trim()) return 'Reply cannot be empty. Type \"cancel\" to abort.';\n return;\n },\n });\n\n if (isCancel(userReply)) {\n s.start('Cancelling session...');\n response = await client.sendAgentMessage('cancel', undefined, options.project);\n continue;\n }\n\n s.start('Sending reply...');\n response = await client.sendAgentMessage(String(userReply), undefined, options.project);\n } else {\n // Fallback for unexpected states\n s.stop(pc.green('Response received'));\n console.log('\\n' + replyText + '\\n');\n break;\n }\n }\n } catch (error: any) {\n s.stop(pc.red('Error processing agent conversation'));\n if (error instanceof ApiClientError) {\n console.error(pc.red(`Error (${error.status}): ${(error.body as any)?.message || error.message}`));\n } else {\n console.error(pc.red(`Error: ${error.message || 'Failed to communicate with agent'}`));\n }\n process.exit(1);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pedroaugusto04/kb-cli",
3
- "version": "1.1.9",
3
+ "version": "1.1.10",
4
4
  "description": "CLI client for the Knowledge Base AI system",
5
5
  "type": "module",
6
6
  "bin": {