@jcheesepkg/nanobot 0.7.2 → 0.7.4

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.
@@ -101,23 +101,21 @@ var ExecTool = class extends Tool {
101
101
  ]) if (command.includes(pattern)) return `Error: Command blocked for safety: ${pattern}`;
102
102
  }
103
103
  let env;
104
- let finalCommand = command;
105
104
  if (!this.restrictToWorkspace) env = {
106
105
  ...process.env,
107
106
  HOME: process.env.HOME ?? ""
108
107
  };
109
- else if (isTrustedCommand(command)) {
110
- env = buildSkillEnv();
111
- finalCommand = `echo "Z_AI_API_KEY=$Z_AI_API_KEY" && ${command}`;
112
- } else env = buildSafeEnv();
108
+ else if (isTrustedCommand(command)) env = buildSkillEnv();
109
+ else env = buildSafeEnv();
113
110
  return new Promise((resolve) => {
114
- exec(finalCommand, {
111
+ exec(command, {
115
112
  cwd: this.workingDir,
116
113
  timeout: timeout * 1e3,
117
114
  maxBuffer: 1024 * 1024,
118
115
  env
119
116
  }, (error, stdout, stderr) => {
120
117
  const parts = [];
118
+ console.log(`Exec: command=${command}, env=${JSON.stringify(env)}, stdout=${stdout}, stderr=${stderr}, error=${error}`);
121
119
  if (stdout) parts.push(stdout);
122
120
  if (stderr) parts.push(`[stderr]\n${stderr}`);
123
121
  if (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"shell.mjs","names":[],"sources":["../../../src/agent/tools/shell.ts"],"sourcesContent":["import { exec, spawn } from \"node:child_process\";\nimport { Tool } from \"./base.js\";\n\n/** Env var patterns that should never leak to user-invoked commands. */\nconst SENSITIVE_ENV_PATTERNS = [\n /api[_-]?key/i,\n /api[_-]?token/i,\n /api[_-]?secret/i,\n /secret/i,\n /token/i,\n /password/i,\n /credential/i,\n /^LLM_/i,\n /^OPENROUTER_/i,\n /^OPENAI_/i,\n /^ANTHROPIC_/i,\n /^STRIPE_/i,\n /^LINE_CHANNEL/i,\n /^APIFY_/i,\n /^Z_AI_/i,\n /^BRAVE_/i,\n /^AWS_/i,\n /^GOOGLE_/i,\n /^AZURE_/i,\n /^NANOBOT_/i,\n];\n\n/**\n * Trusted commands that receive skill-specific env vars.\n * Only the first word (binary name) of the command is matched.\n * These commands still do NOT get the core LLM/channel secrets.\n */\nconst TRUSTED_COMMANDS = [\"summarize\"];\n\n/** Env vars injected for trusted commands only. */\nconst SKILL_ENV_KEYS = [\n \"Z_AI_API_KEY\",\n \"Z_AI_BASE_URL\",\n \"APIFY_API_TOKEN\",\n \"BRAVE_API_KEY\",\n];\n\n/** Build a sanitized env for child processes — strips all secrets. */\nfunction buildSafeEnv(): Record<string, string> {\n const safe: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (!value) continue;\n if (SENSITIVE_ENV_PATTERNS.some((re) => re.test(key))) continue;\n safe[key] = value;\n }\n return safe;\n}\n\n/** Build env for trusted skill commands — safe env + skill-specific keys. */\nfunction buildSkillEnv(): Record<string, string> {\n const env = buildSafeEnv();\n for (const key of SKILL_ENV_KEYS) {\n const value = process.env[key];\n if (value) env[key] = value;\n }\n return env;\n}\n\n/** Check if a command starts with a trusted binary. */\nfunction isTrustedCommand(command: string): boolean {\n // Extract the first word, stripping common prefixes like timeout, env, etc.\n const stripped = command.replace(/^\\s*(timeout\\s+\\d+\\s+|env\\s+\\S+=\\S+\\s+)*/, \"\");\n const firstWord = stripped.trim().split(/\\s+/)[0];\n return TRUSTED_COMMANDS.includes(firstWord);\n}\n\nexport class ExecTool extends Tool {\n readonly name = \"exec\";\n readonly description =\n \"Execute a shell command and return its output. Use for running programs, scripts, git, etc.\";\n readonly parameters = {\n type: \"object\",\n properties: {\n command: { type: \"string\", description: \"Shell command to execute\" },\n timeout: {\n type: \"integer\",\n description: \"Timeout in seconds (default: 60)\",\n },\n },\n required: [\"command\"],\n };\n\n private workingDir: string;\n private defaultTimeout: number;\n private restrictToWorkspace: boolean;\n\n constructor(params?: {\n workingDir?: string;\n timeout?: number;\n restrictToWorkspace?: boolean;\n }) {\n super();\n this.workingDir = params?.workingDir ?? process.cwd();\n this.defaultTimeout = params?.timeout ?? 60;\n this.restrictToWorkspace = params?.restrictToWorkspace ?? false;\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const command = String(args.command);\n const timeout = args.timeout ? Number(args.timeout) : this.defaultTimeout;\n\n if (!command.trim()) {\n return \"Error: Empty command\";\n }\n\n // Safety checks when restricted to workspace\n if (this.restrictToWorkspace) {\n const dangerous = [\"rm -rf /\", \"mkfs\", \"dd if=\", \"> /dev/\"];\n for (const pattern of dangerous) {\n if (command.includes(pattern)) {\n return `Error: Command blocked for safety: ${pattern}`;\n }\n }\n }\n\n // Build env: scrub secrets when restricted, pass through when unrestricted\n let env: Record<string, string>;\n let finalCommand = command;\n if (!this.restrictToWorkspace) {\n env = { ...process.env, HOME: process.env.HOME ?? \"\" } as Record<string, string>;\n } else if (isTrustedCommand(command)) {\n env = buildSkillEnv();\n // DEBUG: echo the key so we can verify it reaches the child process\n finalCommand = `echo \"Z_AI_API_KEY=$Z_AI_API_KEY\" && ${command}`;\n } else {\n env = buildSafeEnv();\n }\n\n return new Promise<string>((resolve) => {\n exec(\n finalCommand,\n {\n cwd: this.workingDir,\n timeout: timeout * 1000,\n maxBuffer: 1024 * 1024, // 1MB\n env,\n },\n (error, stdout, stderr) => {\n const parts: string[] = [];\n\n if (stdout) parts.push(stdout);\n if (stderr) parts.push(`[stderr]\\n${stderr}`);\n\n if (error) {\n if (error.killed) {\n parts.push(`\\n[Timed out after ${timeout}s]`);\n } else if (error.code !== undefined) {\n parts.push(`\\n[Exit code: ${error.code}]`);\n }\n }\n\n const output = parts.join(\"\\n\").trim();\n // Truncate large output\n if (output.length > 50000) {\n resolve(\n output.slice(0, 50000) + \"\\n... (truncated, output too large)\",\n );\n } else {\n resolve(output || \"(no output)\");\n }\n },\n );\n\n });\n }\n}\n"],"mappings":";;;;;AAIA,MAAM,yBAAyB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;AAOD,MAAM,mBAAmB,CAAC,YAAY;;AAGtC,MAAM,iBAAiB;CACrB;CACA;CACA;CACA;CACD;;AAGD,SAAS,eAAuC;CAC9C,MAAM,OAA+B,EAAE;AACvC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,IAAI,EAAE;AACtD,MAAI,CAAC,MAAO;AACZ,MAAI,uBAAuB,MAAM,OAAO,GAAG,KAAK,IAAI,CAAC,CAAE;AACvD,OAAK,OAAO;;AAEd,QAAO;;;AAIT,SAAS,gBAAwC;CAC/C,MAAM,MAAM,cAAc;AAC1B,MAAK,MAAM,OAAO,gBAAgB;EAChC,MAAM,QAAQ,QAAQ,IAAI;AAC1B,MAAI,MAAO,KAAI,OAAO;;AAExB,QAAO;;;AAIT,SAAS,iBAAiB,SAA0B;CAGlD,MAAM,YADW,QAAQ,QAAQ,4CAA4C,GAAG,CACrD,MAAM,CAAC,MAAM,MAAM,CAAC;AAC/C,QAAO,iBAAiB,SAAS,UAAU;;AAG7C,IAAa,WAAb,cAA8B,KAAK;CACjC,AAAS,OAAO;CAChB,AAAS,cACP;CACF,AAAS,aAAa;EACpB,MAAM;EACN,YAAY;GACV,SAAS;IAAE,MAAM;IAAU,aAAa;IAA4B;GACpE,SAAS;IACP,MAAM;IACN,aAAa;IACd;GACF;EACD,UAAU,CAAC,UAAU;EACtB;CAED,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,YAAY,QAIT;AACD,SAAO;AACP,OAAK,aAAa,QAAQ,cAAc,QAAQ,KAAK;AACrD,OAAK,iBAAiB,QAAQ,WAAW;AACzC,OAAK,sBAAsB,QAAQ,uBAAuB;;CAG5D,MAAM,QAAQ,MAAgD;EAC5D,MAAM,UAAU,OAAO,KAAK,QAAQ;EACpC,MAAM,UAAU,KAAK,UAAU,OAAO,KAAK,QAAQ,GAAG,KAAK;AAE3D,MAAI,CAAC,QAAQ,MAAM,CACjB,QAAO;AAIT,MAAI,KAAK,qBAEP;QAAK,MAAM,WADO;IAAC;IAAY;IAAQ;IAAU;IAAU,CAEzD,KAAI,QAAQ,SAAS,QAAQ,CAC3B,QAAO,sCAAsC;;EAMnD,IAAI;EACJ,IAAI,eAAe;AACnB,MAAI,CAAC,KAAK,oBACR,OAAM;GAAE,GAAG,QAAQ;GAAK,MAAM,QAAQ,IAAI,QAAQ;GAAI;WAC7C,iBAAiB,QAAQ,EAAE;AACpC,SAAM,eAAe;AAErB,kBAAe,wCAAwC;QAEvD,OAAM,cAAc;AAGtB,SAAO,IAAI,SAAiB,YAAY;AACtC,QACE,cACA;IACE,KAAK,KAAK;IACV,SAAS,UAAU;IACnB,WAAW,OAAO;IAClB;IACD,GACA,OAAO,QAAQ,WAAW;IACzB,MAAM,QAAkB,EAAE;AAE1B,QAAI,OAAQ,OAAM,KAAK,OAAO;AAC9B,QAAI,OAAQ,OAAM,KAAK,aAAa,SAAS;AAE7C,QAAI,OACF;SAAI,MAAM,OACR,OAAM,KAAK,sBAAsB,QAAQ,IAAI;cACpC,MAAM,SAAS,OACxB,OAAM,KAAK,iBAAiB,MAAM,KAAK,GAAG;;IAI9C,MAAM,SAAS,MAAM,KAAK,KAAK,CAAC,MAAM;AAEtC,QAAI,OAAO,SAAS,IAClB,SACE,OAAO,MAAM,GAAG,IAAM,GAAG,sCAC1B;QAED,SAAQ,UAAU,cAAc;KAGrC;IAED"}
1
+ {"version":3,"file":"shell.mjs","names":[],"sources":["../../../src/agent/tools/shell.ts"],"sourcesContent":["import { exec, spawn } from \"node:child_process\";\nimport { Tool } from \"./base.js\";\n\n/** Env var patterns that should never leak to user-invoked commands. */\nconst SENSITIVE_ENV_PATTERNS = [\n /api[_-]?key/i,\n /api[_-]?token/i,\n /api[_-]?secret/i,\n /secret/i,\n /token/i,\n /password/i,\n /credential/i,\n /^LLM_/i,\n /^OPENROUTER_/i,\n /^OPENAI_/i,\n /^ANTHROPIC_/i,\n /^STRIPE_/i,\n /^LINE_CHANNEL/i,\n /^APIFY_/i,\n /^Z_AI_/i,\n /^BRAVE_/i,\n /^AWS_/i,\n /^GOOGLE_/i,\n /^AZURE_/i,\n /^NANOBOT_/i,\n];\n\n/**\n * Trusted commands that receive skill-specific env vars.\n * Only the first word (binary name) of the command is matched.\n * These commands still do NOT get the core LLM/channel secrets.\n */\nconst TRUSTED_COMMANDS = [\"summarize\"];\n\n/** Env vars injected for trusted commands only. */\nconst SKILL_ENV_KEYS = [\n \"Z_AI_API_KEY\",\n \"Z_AI_BASE_URL\",\n \"APIFY_API_TOKEN\",\n \"BRAVE_API_KEY\",\n];\n\n/** Build a sanitized env for child processes — strips all secrets. */\nfunction buildSafeEnv(): Record<string, string> {\n const safe: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (!value) continue;\n if (SENSITIVE_ENV_PATTERNS.some((re) => re.test(key))) continue;\n safe[key] = value;\n }\n return safe;\n}\n\n/** Build env for trusted skill commands — safe env + skill-specific keys. */\nfunction buildSkillEnv(): Record<string, string> {\n const env = buildSafeEnv();\n for (const key of SKILL_ENV_KEYS) {\n const value = process.env[key];\n if (value) env[key] = value;\n }\n return env;\n}\n\n/** Check if a command starts with a trusted binary. */\nfunction isTrustedCommand(command: string): boolean {\n // Extract the first word, stripping common prefixes like timeout, env, etc.\n const stripped = command.replace(/^\\s*(timeout\\s+\\d+\\s+|env\\s+\\S+=\\S+\\s+)*/, \"\");\n const firstWord = stripped.trim().split(/\\s+/)[0];\n return TRUSTED_COMMANDS.includes(firstWord);\n}\n\nexport class ExecTool extends Tool {\n readonly name = \"exec\";\n readonly description =\n \"Execute a shell command and return its output. Use for running programs, scripts, git, etc.\";\n readonly parameters = {\n type: \"object\",\n properties: {\n command: { type: \"string\", description: \"Shell command to execute\" },\n timeout: {\n type: \"integer\",\n description: \"Timeout in seconds (default: 60)\",\n },\n },\n required: [\"command\"],\n };\n\n private workingDir: string;\n private defaultTimeout: number;\n private restrictToWorkspace: boolean;\n\n constructor(params?: {\n workingDir?: string;\n timeout?: number;\n restrictToWorkspace?: boolean;\n }) {\n super();\n this.workingDir = params?.workingDir ?? process.cwd();\n this.defaultTimeout = params?.timeout ?? 60;\n this.restrictToWorkspace = params?.restrictToWorkspace ?? false;\n }\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const command = String(args.command);\n const timeout = args.timeout ? Number(args.timeout) : this.defaultTimeout;\n\n if (!command.trim()) {\n return \"Error: Empty command\";\n }\n\n // Safety checks when restricted to workspace\n if (this.restrictToWorkspace) {\n const dangerous = [\"rm -rf /\", \"mkfs\", \"dd if=\", \"> /dev/\"];\n for (const pattern of dangerous) {\n if (command.includes(pattern)) {\n return `Error: Command blocked for safety: ${pattern}`;\n }\n }\n }\n\n // Build env: scrub secrets when restricted, pass through when unrestricted\n let env: Record<string, string>;\n if (!this.restrictToWorkspace) {\n env = { ...process.env, HOME: process.env.HOME ?? \"\" } as Record<string, string>;\n } else if (isTrustedCommand(command)) {\n env = buildSkillEnv();\n // DEBUG: echo the key so we can verify it reaches the child process\n } else {\n env = buildSafeEnv();\n }\n\n return new Promise<string>((resolve) => {\n exec(\n command,\n {\n cwd: this.workingDir,\n timeout: timeout * 1000,\n maxBuffer: 1024 * 1024, // 1MB\n env,\n },\n (error, stdout, stderr) => {\n const parts: string[] = [];\n\n console.log(`Exec: command=${command}, env=${JSON.stringify(env)}, stdout=${stdout}, stderr=${stderr}, error=${error}`);\n\n if (stdout) parts.push(stdout);\n if (stderr) parts.push(`[stderr]\\n${stderr}`);\n\n if (error) {\n if (error.killed) {\n parts.push(`\\n[Timed out after ${timeout}s]`);\n } else if (error.code !== undefined) {\n parts.push(`\\n[Exit code: ${error.code}]`);\n }\n }\n\n const output = parts.join(\"\\n\").trim();\n // Truncate large output\n if (output.length > 50000) {\n resolve(\n output.slice(0, 50000) + \"\\n... (truncated, output too large)\",\n );\n } else {\n resolve(output || \"(no output)\");\n }\n },\n );\n\n });\n }\n}\n"],"mappings":";;;;;AAIA,MAAM,yBAAyB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;AAOD,MAAM,mBAAmB,CAAC,YAAY;;AAGtC,MAAM,iBAAiB;CACrB;CACA;CACA;CACA;CACD;;AAGD,SAAS,eAAuC;CAC9C,MAAM,OAA+B,EAAE;AACvC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,IAAI,EAAE;AACtD,MAAI,CAAC,MAAO;AACZ,MAAI,uBAAuB,MAAM,OAAO,GAAG,KAAK,IAAI,CAAC,CAAE;AACvD,OAAK,OAAO;;AAEd,QAAO;;;AAIT,SAAS,gBAAwC;CAC/C,MAAM,MAAM,cAAc;AAC1B,MAAK,MAAM,OAAO,gBAAgB;EAChC,MAAM,QAAQ,QAAQ,IAAI;AAC1B,MAAI,MAAO,KAAI,OAAO;;AAExB,QAAO;;;AAIT,SAAS,iBAAiB,SAA0B;CAGlD,MAAM,YADW,QAAQ,QAAQ,4CAA4C,GAAG,CACrD,MAAM,CAAC,MAAM,MAAM,CAAC;AAC/C,QAAO,iBAAiB,SAAS,UAAU;;AAG7C,IAAa,WAAb,cAA8B,KAAK;CACjC,AAAS,OAAO;CAChB,AAAS,cACP;CACF,AAAS,aAAa;EACpB,MAAM;EACN,YAAY;GACV,SAAS;IAAE,MAAM;IAAU,aAAa;IAA4B;GACpE,SAAS;IACP,MAAM;IACN,aAAa;IACd;GACF;EACD,UAAU,CAAC,UAAU;EACtB;CAED,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,YAAY,QAIT;AACD,SAAO;AACP,OAAK,aAAa,QAAQ,cAAc,QAAQ,KAAK;AACrD,OAAK,iBAAiB,QAAQ,WAAW;AACzC,OAAK,sBAAsB,QAAQ,uBAAuB;;CAG5D,MAAM,QAAQ,MAAgD;EAC5D,MAAM,UAAU,OAAO,KAAK,QAAQ;EACpC,MAAM,UAAU,KAAK,UAAU,OAAO,KAAK,QAAQ,GAAG,KAAK;AAE3D,MAAI,CAAC,QAAQ,MAAM,CACjB,QAAO;AAIT,MAAI,KAAK,qBAEP;QAAK,MAAM,WADO;IAAC;IAAY;IAAQ;IAAU;IAAU,CAEzD,KAAI,QAAQ,SAAS,QAAQ,CAC3B,QAAO,sCAAsC;;EAMnD,IAAI;AACJ,MAAI,CAAC,KAAK,oBACR,OAAM;GAAE,GAAG,QAAQ;GAAK,MAAM,QAAQ,IAAI,QAAQ;GAAI;WAC7C,iBAAiB,QAAQ,CAClC,OAAM,eAAe;MAGrB,OAAM,cAAc;AAGtB,SAAO,IAAI,SAAiB,YAAY;AACtC,QACE,SACA;IACE,KAAK,KAAK;IACV,SAAS,UAAU;IACnB,WAAW,OAAO;IAClB;IACD,GACA,OAAO,QAAQ,WAAW;IACzB,MAAM,QAAkB,EAAE;AAE1B,YAAQ,IAAI,iBAAiB,QAAQ,QAAQ,KAAK,UAAU,IAAI,CAAC,WAAW,OAAO,WAAW,OAAO,UAAU,QAAQ;AAEvH,QAAI,OAAQ,OAAM,KAAK,OAAO;AAC9B,QAAI,OAAQ,OAAM,KAAK,aAAa,SAAS;AAE7C,QAAI,OACF;SAAI,MAAM,OACR,OAAM,KAAK,sBAAsB,QAAQ,IAAI;cACpC,MAAM,SAAS,OACxB,OAAM,KAAK,iBAAiB,MAAM,KAAK,GAAG;;IAI9C,MAAM,SAAS,MAAM,KAAK,KAAK,CAAC,MAAM;AAEtC,QAAI,OAAO,SAAS,IAClB,SACE,OAAO,MAAM,GAAG,IAAM,GAAG,sCAC1B;QAED,SAAQ,UAAU,cAAc;KAGrC;IAED"}
@@ -539,15 +539,15 @@ declare const ToolsConfigSchema: z.ZodObject<{
539
539
  export?: string | undefined;
540
540
  }>, "many">>;
541
541
  }, "strip", z.ZodTypeAny, {
542
+ exec: {
543
+ timeout: number;
544
+ };
542
545
  web: {
543
546
  search: {
544
547
  apiKey: string;
545
548
  maxResults: number;
546
549
  };
547
550
  };
548
- exec: {
549
- timeout: number;
550
- };
551
551
  restrictToWorkspace: boolean;
552
552
  enabled?: string[] | undefined;
553
553
  disabled?: string[] | undefined;
@@ -557,6 +557,9 @@ declare const ToolsConfigSchema: z.ZodObject<{
557
557
  export?: string | undefined;
558
558
  }[] | undefined;
559
559
  }, {
560
+ exec?: {
561
+ timeout?: number | undefined;
562
+ } | undefined;
560
563
  enabled?: string[] | undefined;
561
564
  web?: {
562
565
  search?: {
@@ -564,9 +567,6 @@ declare const ToolsConfigSchema: z.ZodObject<{
564
567
  maxResults?: number | undefined;
565
568
  } | undefined;
566
569
  } | undefined;
567
- exec?: {
568
- timeout?: number | undefined;
569
- } | undefined;
570
570
  restrictToWorkspace?: boolean | undefined;
571
571
  disabled?: string[] | undefined;
572
572
  custom?: {
@@ -988,15 +988,15 @@ declare const ConfigSchema: z.ZodObject<{
988
988
  export?: string | undefined;
989
989
  }>, "many">>;
990
990
  }, "strip", z.ZodTypeAny, {
991
+ exec: {
992
+ timeout: number;
993
+ };
991
994
  web: {
992
995
  search: {
993
996
  apiKey: string;
994
997
  maxResults: number;
995
998
  };
996
999
  };
997
- exec: {
998
- timeout: number;
999
- };
1000
1000
  restrictToWorkspace: boolean;
1001
1001
  enabled?: string[] | undefined;
1002
1002
  disabled?: string[] | undefined;
@@ -1006,6 +1006,9 @@ declare const ConfigSchema: z.ZodObject<{
1006
1006
  export?: string | undefined;
1007
1007
  }[] | undefined;
1008
1008
  }, {
1009
+ exec?: {
1010
+ timeout?: number | undefined;
1011
+ } | undefined;
1009
1012
  enabled?: string[] | undefined;
1010
1013
  web?: {
1011
1014
  search?: {
@@ -1013,9 +1016,6 @@ declare const ConfigSchema: z.ZodObject<{
1013
1016
  maxResults?: number | undefined;
1014
1017
  } | undefined;
1015
1018
  } | undefined;
1016
- exec?: {
1017
- timeout?: number | undefined;
1018
- } | undefined;
1019
1019
  restrictToWorkspace?: boolean | undefined;
1020
1020
  disabled?: string[] | undefined;
1021
1021
  custom?: {
@@ -1110,15 +1110,15 @@ declare const ConfigSchema: z.ZodObject<{
1110
1110
  port: number;
1111
1111
  };
1112
1112
  tools: {
1113
+ exec: {
1114
+ timeout: number;
1115
+ };
1113
1116
  web: {
1114
1117
  search: {
1115
1118
  apiKey: string;
1116
1119
  maxResults: number;
1117
1120
  };
1118
1121
  };
1119
- exec: {
1120
- timeout: number;
1121
- };
1122
1122
  restrictToWorkspace: boolean;
1123
1123
  enabled?: string[] | undefined;
1124
1124
  disabled?: string[] | undefined;
@@ -1214,6 +1214,9 @@ declare const ConfigSchema: z.ZodObject<{
1214
1214
  port?: number | undefined;
1215
1215
  } | undefined;
1216
1216
  tools?: {
1217
+ exec?: {
1218
+ timeout?: number | undefined;
1219
+ } | undefined;
1217
1220
  enabled?: string[] | undefined;
1218
1221
  web?: {
1219
1222
  search?: {
@@ -1221,9 +1224,6 @@ declare const ConfigSchema: z.ZodObject<{
1221
1224
  maxResults?: number | undefined;
1222
1225
  } | undefined;
1223
1226
  } | undefined;
1224
- exec?: {
1225
- timeout?: number | undefined;
1226
- } | undefined;
1227
1227
  restrictToWorkspace?: boolean | undefined;
1228
1228
  disabled?: string[] | undefined;
1229
1229
  custom?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jcheesepkg/nanobot",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "Lightweight AI assistant - TypeScript port",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -21,20 +21,18 @@ Always use `--model zai/glm-5` for summarization.
21
21
 
22
22
  ```bash
23
23
  summarize "https://example.com" --model zai/glm-5
24
- summarize "https://youtu.be/dQw4w9WgXcQ" --youtube apify --model zai/glm-5 --no-cache
24
+ summarize "https://youtu.be/dQw4w9WgXcQ" --youtube apify --model zai/glm-5
25
25
  summarize "/path/to/file.pdf" --model zai/glm-5
26
26
  ```
27
27
 
28
- ## YouTube: summary vs transcript
28
+ ## YouTube
29
29
 
30
- Best-effort transcript (URLs only):
30
+ Always use `--youtube apify` for YouTube summarization.
31
31
 
32
32
  ```bash
33
- summarize "https://youtu.be/dQw4w9WgXcQ" --youtube apify --extract-only --no-cache
33
+ summarize "https://youtu.be/dQw4w9WgXcQ" --youtube apify --model zai/glm-5
34
34
  ```
35
35
 
36
- If the user asked for a transcript but it's huge, return a tight summary first, then ask which section to expand.
37
-
38
36
  ## Model configuration
39
37
 
40
38
  Uses `Z_AI_API_KEY` environment variable (already configured).
@@ -45,6 +43,6 @@ Always pass `--model zai/glm-5`.
45
43
 
46
44
  - `--length short|medium|long|xl` — summary length
47
45
  - `--extract-only` — extract text only, no summarization
48
- - `--youtube auto` — enable YouTube transcript extraction
46
+ - `--youtube apify` — enable YouTube transcript extraction
49
47
  - `--json` — machine-readable output
50
48
  - `--language <lang>` — output language (e.g. `ja` for Japanese)