@jcheesepkg/nanobot 0.1.3 → 0.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.mts","names":[],"sources":["../../src/agent/skills.ts"],"mappings":";UAWU,SAAA;EACR,IAAA;EACA,IAAA;EACA,MAAA;AAAA;AAAA,UAGQ,SAAA;EACR,WAAA;EACA,MAAA;EACA,QAAA;EAAA,CACC,GAAA;AAAA;;;;;cAOU,YAAA;EAAA,QACH,SAAA;EAAA,QACA,eAAA;EAAA,QACA,aAAA;cAEI,SAAA,UAAmB,gBAAA;EALpB;EAYX,UAAA,CAAW,iBAAA,aAA2B,SAAA;;EAsCtC,SAAA,CAAU,IAAA;EAjDF;EAgER,oBAAA,CAAqB,UAAA;EA9Db;EA2ER,kBAAA,CAAA;EAzEY;EA0GZ,eAAA,CAAA;EAnGA;EAgHA,gBAAA,CAAiB,IAAA,WAAe,SAAA;EAAA,QAsBxB,gBAAA;EAAA,QAQA,oBAAA;EAAA,QAWA,iBAAA;EAAA,QAWA,YAAA;EAAA,QAKA,mBAAA;EAAA,QAKA,sBAAA;AAAA"}
1
+ {"version":3,"file":"skills.d.mts","names":[],"sources":["../../src/agent/skills.ts"],"mappings":";UAeU,SAAA;EACR,IAAA;EACA,IAAA;EACA,MAAA;AAAA;AAAA,UAGQ,SAAA;EACR,WAAA;EACA,MAAA;EACA,QAAA;EAAA,CACC,GAAA;AAAA;;;;;cAOU,YAAA;EAAA,QACH,SAAA;EAAA,QACA,eAAA;EAAA,QACA,aAAA;cAEI,SAAA,UAAmB,gBAAA;EALpB;EAYX,UAAA,CAAW,iBAAA,aAA2B,SAAA;;EAsCtC,SAAA,CAAU,IAAA;EAjDF;EAgER,oBAAA,CAAqB,UAAA;EA9Db;EA2ER,kBAAA,CAAA;EAzEY;EA0GZ,eAAA,CAAA;EAnGA;EAgHA,gBAAA,CAAiB,IAAA,WAAe,SAAA;EAAA,QAsBxB,gBAAA;EAAA,QAQA,oBAAA;EAAA,QAWA,iBAAA;EAAA,QAWA,YAAA;EAAA,QAKA,mBAAA;EAAA,QAKA,sBAAA;AAAA"}
@@ -1,8 +1,10 @@
1
1
  import { which } from "../utils/which.mjs";
2
2
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
4
5
 
5
6
  //#region src/agent/skills.ts
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
8
  /** Default builtin skills directory (relative to this file in dist). */
7
9
  function getBuiltinSkillsDir() {
8
10
  return join(dirname(dirname(__dirname)), "skills");
@@ -1 +1 @@
1
- {"version":3,"file":"skills.mjs","names":[],"sources":["../../src/agent/skills.ts"],"sourcesContent":["import { readFileSync, existsSync, readdirSync, statSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { which } from \"../utils/which.js\";\n\n/** Default builtin skills directory (relative to this file in dist). */\nfunction getBuiltinSkillsDir(): string {\n // In dist: dist/agent/skills.js -> ../../skills\n // In src: src/agent/skills.ts -> ../../skills\n return join(dirname(dirname(__dirname)), \"skills\");\n}\n\ninterface SkillInfo {\n name: string;\n path: string;\n source: \"workspace\" | \"builtin\";\n}\n\ninterface SkillMeta {\n description?: string;\n always?: string;\n metadata?: string;\n [key: string]: string | undefined;\n}\n\n/**\n * Loader for agent skills.\n * Skills are markdown files (SKILL.md) that teach the agent specific capabilities.\n */\nexport class SkillsLoader {\n private workspace: string;\n private workspaceSkills: string;\n private builtinSkills: string;\n\n constructor(workspace: string, builtinSkillsDir?: string) {\n this.workspace = workspace;\n this.workspaceSkills = join(workspace, \"skills\");\n this.builtinSkills = builtinSkillsDir ?? getBuiltinSkillsDir();\n }\n\n /** List all available skills. */\n listSkills(filterUnavailable = true): SkillInfo[] {\n const skills: SkillInfo[] = [];\n\n // Workspace skills (highest priority)\n if (existsSync(this.workspaceSkills)) {\n for (const entry of readdirSync(this.workspaceSkills)) {\n const skillDir = join(this.workspaceSkills, entry);\n const skillFile = join(skillDir, \"SKILL.md\");\n if (statSync(skillDir).isDirectory() && existsSync(skillFile)) {\n skills.push({ name: entry, path: skillFile, source: \"workspace\" });\n }\n }\n }\n\n // Built-in skills\n if (existsSync(this.builtinSkills)) {\n for (const entry of readdirSync(this.builtinSkills)) {\n const skillDir = join(this.builtinSkills, entry);\n const skillFile = join(skillDir, \"SKILL.md\");\n if (\n statSync(skillDir).isDirectory() &&\n existsSync(skillFile) &&\n !skills.some((s) => s.name === entry)\n ) {\n skills.push({ name: entry, path: skillFile, source: \"builtin\" });\n }\n }\n }\n\n if (filterUnavailable) {\n return skills.filter((s) =>\n this.checkRequirements(this.getSkillMeta(s.name)),\n );\n }\n return skills;\n }\n\n /** Load a skill by name. */\n loadSkill(name: string): string | null {\n const wsSkill = join(this.workspaceSkills, name, \"SKILL.md\");\n if (existsSync(wsSkill)) {\n return readFileSync(wsSkill, \"utf-8\");\n }\n\n const builtinSkill = join(this.builtinSkills, name, \"SKILL.md\");\n if (existsSync(builtinSkill)) {\n return readFileSync(builtinSkill, \"utf-8\");\n }\n\n return null;\n }\n\n /** Load specific skills for inclusion in agent context. */\n loadSkillsForContext(skillNames: string[]): string {\n const parts: string[] = [];\n for (const name of skillNames) {\n const content = this.loadSkill(name);\n if (content) {\n const stripped = this.stripFrontmatter(content);\n parts.push(`### Skill: ${name}\\n\\n${stripped}`);\n }\n }\n return parts.join(\"\\n\\n---\\n\\n\");\n }\n\n /** Build a summary of all skills. */\n buildSkillsSummary(): string {\n const allSkills = this.listSkills(false);\n if (allSkills.length === 0) return \"\";\n\n const escapeXml = (s: string) =>\n s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n\n const lines = [\"<skills>\"];\n for (const s of allSkills) {\n const name = escapeXml(s.name);\n const desc = escapeXml(this.getSkillDescription(s.name));\n const meta = this.getSkillMeta(s.name);\n const available = this.checkRequirements(meta);\n\n lines.push(` <skill available=\"${available}\">`);\n lines.push(` <name>${name}</name>`);\n lines.push(` <description>${desc}</description>`);\n lines.push(` <location>${s.path}</location>`);\n\n if (!available) {\n const missing = this.getMissingRequirements(meta);\n if (missing) {\n lines.push(` <requires>${escapeXml(missing)}</requires>`);\n }\n }\n\n lines.push(\" </skill>\");\n }\n lines.push(\"</skills>\");\n return lines.join(\"\\n\");\n }\n\n /** Get skills marked as always=true. */\n getAlwaysSkills(): string[] {\n const result: string[] = [];\n for (const s of this.listSkills(true)) {\n const meta = this.getSkillMetadata(s.name);\n const skillMeta = this.parseNanobotMetadata(meta?.metadata ?? \"\");\n if (skillMeta.always || meta?.always) {\n result.push(s.name);\n }\n }\n return result;\n }\n\n /** Get metadata from a skill's frontmatter. */\n getSkillMetadata(name: string): SkillMeta | null {\n const content = this.loadSkill(name);\n if (!content) return null;\n\n if (content.startsWith(\"---\")) {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (match) {\n const metadata: SkillMeta = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx !== -1) {\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim().replace(/^[\"']|[\"']$/g, \"\");\n metadata[key] = value;\n }\n }\n return metadata;\n }\n }\n return null;\n }\n\n private stripFrontmatter(content: string): string {\n if (content.startsWith(\"---\")) {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n/);\n if (match) return content.slice(match[0].length).trim();\n }\n return content;\n }\n\n private parseNanobotMetadata(raw: string): Record<string, unknown> {\n try {\n const data = JSON.parse(raw);\n return typeof data === \"object\" && data !== null\n ? (data.nanobot ?? {})\n : {};\n } catch {\n return {};\n }\n }\n\n private checkRequirements(meta: Record<string, unknown>): boolean {\n const requires = (meta.requires ?? {}) as Record<string, string[]>;\n for (const bin of requires.bins ?? []) {\n if (!which(bin)) return false;\n }\n for (const env of requires.env ?? []) {\n if (!process.env[env]) return false;\n }\n return true;\n }\n\n private getSkillMeta(name: string): Record<string, unknown> {\n const meta = this.getSkillMetadata(name) ?? {};\n return this.parseNanobotMetadata(String(meta.metadata ?? \"\"));\n }\n\n private getSkillDescription(name: string): string {\n const meta = this.getSkillMetadata(name);\n return meta?.description ?? name;\n }\n\n private getMissingRequirements(meta: Record<string, unknown>): string {\n const missing: string[] = [];\n const requires = (meta.requires ?? {}) as Record<string, string[]>;\n for (const bin of requires.bins ?? []) {\n if (!which(bin)) missing.push(`CLI: ${bin}`);\n }\n for (const env of requires.env ?? []) {\n if (!process.env[env]) missing.push(`ENV: ${env}`);\n }\n return missing.join(\", \");\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"skills.mjs","names":[],"sources":["../../src/agent/skills.ts"],"sourcesContent":["import { readFileSync, existsSync, readdirSync, statSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { which } from \"../utils/which.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/** Default builtin skills directory (relative to this file in dist). */\nfunction getBuiltinSkillsDir(): string {\n // In dist: dist/agent/skills.js -> ../../skills\n // In src: src/agent/skills.ts -> ../../skills\n return join(dirname(dirname(__dirname)), \"skills\");\n}\n\ninterface SkillInfo {\n name: string;\n path: string;\n source: \"workspace\" | \"builtin\";\n}\n\ninterface SkillMeta {\n description?: string;\n always?: string;\n metadata?: string;\n [key: string]: string | undefined;\n}\n\n/**\n * Loader for agent skills.\n * Skills are markdown files (SKILL.md) that teach the agent specific capabilities.\n */\nexport class SkillsLoader {\n private workspace: string;\n private workspaceSkills: string;\n private builtinSkills: string;\n\n constructor(workspace: string, builtinSkillsDir?: string) {\n this.workspace = workspace;\n this.workspaceSkills = join(workspace, \"skills\");\n this.builtinSkills = builtinSkillsDir ?? getBuiltinSkillsDir();\n }\n\n /** List all available skills. */\n listSkills(filterUnavailable = true): SkillInfo[] {\n const skills: SkillInfo[] = [];\n\n // Workspace skills (highest priority)\n if (existsSync(this.workspaceSkills)) {\n for (const entry of readdirSync(this.workspaceSkills)) {\n const skillDir = join(this.workspaceSkills, entry);\n const skillFile = join(skillDir, \"SKILL.md\");\n if (statSync(skillDir).isDirectory() && existsSync(skillFile)) {\n skills.push({ name: entry, path: skillFile, source: \"workspace\" });\n }\n }\n }\n\n // Built-in skills\n if (existsSync(this.builtinSkills)) {\n for (const entry of readdirSync(this.builtinSkills)) {\n const skillDir = join(this.builtinSkills, entry);\n const skillFile = join(skillDir, \"SKILL.md\");\n if (\n statSync(skillDir).isDirectory() &&\n existsSync(skillFile) &&\n !skills.some((s) => s.name === entry)\n ) {\n skills.push({ name: entry, path: skillFile, source: \"builtin\" });\n }\n }\n }\n\n if (filterUnavailable) {\n return skills.filter((s) =>\n this.checkRequirements(this.getSkillMeta(s.name)),\n );\n }\n return skills;\n }\n\n /** Load a skill by name. */\n loadSkill(name: string): string | null {\n const wsSkill = join(this.workspaceSkills, name, \"SKILL.md\");\n if (existsSync(wsSkill)) {\n return readFileSync(wsSkill, \"utf-8\");\n }\n\n const builtinSkill = join(this.builtinSkills, name, \"SKILL.md\");\n if (existsSync(builtinSkill)) {\n return readFileSync(builtinSkill, \"utf-8\");\n }\n\n return null;\n }\n\n /** Load specific skills for inclusion in agent context. */\n loadSkillsForContext(skillNames: string[]): string {\n const parts: string[] = [];\n for (const name of skillNames) {\n const content = this.loadSkill(name);\n if (content) {\n const stripped = this.stripFrontmatter(content);\n parts.push(`### Skill: ${name}\\n\\n${stripped}`);\n }\n }\n return parts.join(\"\\n\\n---\\n\\n\");\n }\n\n /** Build a summary of all skills. */\n buildSkillsSummary(): string {\n const allSkills = this.listSkills(false);\n if (allSkills.length === 0) return \"\";\n\n const escapeXml = (s: string) =>\n s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n\n const lines = [\"<skills>\"];\n for (const s of allSkills) {\n const name = escapeXml(s.name);\n const desc = escapeXml(this.getSkillDescription(s.name));\n const meta = this.getSkillMeta(s.name);\n const available = this.checkRequirements(meta);\n\n lines.push(` <skill available=\"${available}\">`);\n lines.push(` <name>${name}</name>`);\n lines.push(` <description>${desc}</description>`);\n lines.push(` <location>${s.path}</location>`);\n\n if (!available) {\n const missing = this.getMissingRequirements(meta);\n if (missing) {\n lines.push(` <requires>${escapeXml(missing)}</requires>`);\n }\n }\n\n lines.push(\" </skill>\");\n }\n lines.push(\"</skills>\");\n return lines.join(\"\\n\");\n }\n\n /** Get skills marked as always=true. */\n getAlwaysSkills(): string[] {\n const result: string[] = [];\n for (const s of this.listSkills(true)) {\n const meta = this.getSkillMetadata(s.name);\n const skillMeta = this.parseNanobotMetadata(meta?.metadata ?? \"\");\n if (skillMeta.always || meta?.always) {\n result.push(s.name);\n }\n }\n return result;\n }\n\n /** Get metadata from a skill's frontmatter. */\n getSkillMetadata(name: string): SkillMeta | null {\n const content = this.loadSkill(name);\n if (!content) return null;\n\n if (content.startsWith(\"---\")) {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (match) {\n const metadata: SkillMeta = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx !== -1) {\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim().replace(/^[\"']|[\"']$/g, \"\");\n metadata[key] = value;\n }\n }\n return metadata;\n }\n }\n return null;\n }\n\n private stripFrontmatter(content: string): string {\n if (content.startsWith(\"---\")) {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n/);\n if (match) return content.slice(match[0].length).trim();\n }\n return content;\n }\n\n private parseNanobotMetadata(raw: string): Record<string, unknown> {\n try {\n const data = JSON.parse(raw);\n return typeof data === \"object\" && data !== null\n ? (data.nanobot ?? {})\n : {};\n } catch {\n return {};\n }\n }\n\n private checkRequirements(meta: Record<string, unknown>): boolean {\n const requires = (meta.requires ?? {}) as Record<string, string[]>;\n for (const bin of requires.bins ?? []) {\n if (!which(bin)) return false;\n }\n for (const env of requires.env ?? []) {\n if (!process.env[env]) return false;\n }\n return true;\n }\n\n private getSkillMeta(name: string): Record<string, unknown> {\n const meta = this.getSkillMetadata(name) ?? {};\n return this.parseNanobotMetadata(String(meta.metadata ?? \"\"));\n }\n\n private getSkillDescription(name: string): string {\n const meta = this.getSkillMetadata(name);\n return meta?.description ?? name;\n }\n\n private getMissingRequirements(meta: Record<string, unknown>): string {\n const missing: string[] = [];\n const requires = (meta.requires ?? {}) as Record<string, string[]>;\n for (const bin of requires.bins ?? []) {\n if (!which(bin)) missing.push(`CLI: ${bin}`);\n }\n for (const env of requires.env ?? []) {\n if (!process.env[env]) missing.push(`ENV: ${env}`);\n }\n return missing.join(\", \");\n }\n}\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -16,7 +16,7 @@ import { HeartbeatService } from "./heartbeat/service.mjs";
16
16
  import { OpenAIProvider } from "./providers/openai-provider.mjs";
17
17
 
18
18
  //#region src/index.d.ts
19
- declare const VERSION = "0.1.3";
19
+ declare const VERSION = "0.1.4";
20
20
  declare const LOGO = "\uD83D\uDC08";
21
21
  //#endregion
22
22
  export { AgentLoop, ChannelManager, type Config, ContextBuilder, CronService, HeartbeatService, type InboundMessage, type LLMProvider, type LLMResponse, LOGO, MemoryStore, MessageBus, OpenAIProvider, type OutboundMessage, SessionManager, SkillsLoader, SubagentManager, TelegramChannel, type ToolCallRequest, VERSION, loadConfig, saveConfig };
package/dist/index.mjs CHANGED
@@ -15,7 +15,7 @@ import { HeartbeatService } from "./heartbeat/service.mjs";
15
15
  //#region src/index.ts
16
16
  init_telegram();
17
17
  init_service();
18
- const VERSION = "0.1.3";
18
+ const VERSION = "0.1.4";
19
19
  const LOGO = "🐈";
20
20
 
21
21
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export const VERSION = \"0.1.3\";\nexport const LOGO = \"\\u{1F408}\";\n\n// Core exports\nexport { AgentLoop } from \"./agent/loop.js\";\nexport { ContextBuilder } from \"./agent/context.js\";\nexport { MemoryStore } from \"./agent/memory.js\";\nexport { SkillsLoader } from \"./agent/skills.js\";\nexport { SubagentManager } from \"./agent/subagent.js\";\n\n// Bus\nexport { MessageBus } from \"./bus/queue.js\";\nexport type { InboundMessage, OutboundMessage } from \"./bus/events.js\";\n\n// Config\nexport { loadConfig, saveConfig } from \"./config/loader.js\";\nexport type { Config } from \"./config/schema.js\";\n\n// Providers\nexport { OpenAIProvider } from \"./providers/openai-provider.js\";\nexport type { LLMProvider, LLMResponse, ToolCallRequest } from \"./providers/base.js\";\n\n// Channels\nexport { TelegramChannel } from \"./channels/telegram.js\";\nexport { ChannelManager } from \"./channels/manager.js\";\n\n// Services\nexport { CronService } from \"./cron/service.js\";\nexport { HeartbeatService } from \"./heartbeat/service.js\";\nexport { SessionManager } from \"./session/manager.js\";\n"],"mappings":";;;;;;;;;;;;;;;eAuByD;cAIT;AA3BhD,MAAa,UAAU;AACvB,MAAa,OAAO"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export const VERSION = \"0.1.4\";\nexport const LOGO = \"\\u{1F408}\";\n\n// Core exports\nexport { AgentLoop } from \"./agent/loop.js\";\nexport { ContextBuilder } from \"./agent/context.js\";\nexport { MemoryStore } from \"./agent/memory.js\";\nexport { SkillsLoader } from \"./agent/skills.js\";\nexport { SubagentManager } from \"./agent/subagent.js\";\n\n// Bus\nexport { MessageBus } from \"./bus/queue.js\";\nexport type { InboundMessage, OutboundMessage } from \"./bus/events.js\";\n\n// Config\nexport { loadConfig, saveConfig } from \"./config/loader.js\";\nexport type { Config } from \"./config/schema.js\";\n\n// Providers\nexport { OpenAIProvider } from \"./providers/openai-provider.js\";\nexport type { LLMProvider, LLMResponse, ToolCallRequest } from \"./providers/base.js\";\n\n// Channels\nexport { TelegramChannel } from \"./channels/telegram.js\";\nexport { ChannelManager } from \"./channels/manager.js\";\n\n// Services\nexport { CronService } from \"./cron/service.js\";\nexport { HeartbeatService } from \"./heartbeat/service.js\";\nexport { SessionManager } from \"./session/manager.js\";\n"],"mappings":";;;;;;;;;;;;;;;eAuByD;cAIT;AA3BhD,MAAa,UAAU;AACvB,MAAa,OAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jcheesepkg/nanobot",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Lightweight AI assistant - TypeScript port",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",