nanobot-agent-sdk 0.1.0

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.
Files changed (129) hide show
  1. package/README.md +164 -0
  2. package/dist/core/agent.d.ts +60 -0
  3. package/dist/core/agent.d.ts.map +1 -0
  4. package/dist/core/agent.js +438 -0
  5. package/dist/core/agent.js.map +1 -0
  6. package/dist/core/engine.d.ts +20 -0
  7. package/dist/core/engine.d.ts.map +1 -0
  8. package/dist/core/engine.js +325 -0
  9. package/dist/core/engine.js.map +1 -0
  10. package/dist/core/system-prompt.d.ts +12 -0
  11. package/dist/core/system-prompt.d.ts.map +1 -0
  12. package/dist/core/system-prompt.js +108 -0
  13. package/dist/core/system-prompt.js.map +1 -0
  14. package/dist/index.d.ts +17 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +17 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/mcp/client.d.ts +10 -0
  19. package/dist/mcp/client.d.ts.map +1 -0
  20. package/dist/mcp/client.js +85 -0
  21. package/dist/mcp/client.js.map +1 -0
  22. package/dist/runtime/approval.d.ts +21 -0
  23. package/dist/runtime/approval.d.ts.map +1 -0
  24. package/dist/runtime/approval.js +100 -0
  25. package/dist/runtime/approval.js.map +1 -0
  26. package/dist/runtime/assistant.d.ts +9 -0
  27. package/dist/runtime/assistant.d.ts.map +1 -0
  28. package/dist/runtime/assistant.js +51 -0
  29. package/dist/runtime/assistant.js.map +1 -0
  30. package/dist/runtime/cron.d.ts +3 -0
  31. package/dist/runtime/cron.d.ts.map +1 -0
  32. package/dist/runtime/cron.js +112 -0
  33. package/dist/runtime/cron.js.map +1 -0
  34. package/dist/runtime/memory.d.ts +19 -0
  35. package/dist/runtime/memory.d.ts.map +1 -0
  36. package/dist/runtime/memory.js +89 -0
  37. package/dist/runtime/memory.js.map +1 -0
  38. package/dist/runtime/paths.d.ts +21 -0
  39. package/dist/runtime/paths.d.ts.map +1 -0
  40. package/dist/runtime/paths.js +52 -0
  41. package/dist/runtime/paths.js.map +1 -0
  42. package/dist/runtime/policy.d.ts +5 -0
  43. package/dist/runtime/policy.d.ts.map +1 -0
  44. package/dist/runtime/policy.js +44 -0
  45. package/dist/runtime/policy.js.map +1 -0
  46. package/dist/runtime/scheduler.d.ts +44 -0
  47. package/dist/runtime/scheduler.d.ts.map +1 -0
  48. package/dist/runtime/scheduler.js +192 -0
  49. package/dist/runtime/scheduler.js.map +1 -0
  50. package/dist/runtime/session.d.ts +6 -0
  51. package/dist/runtime/session.d.ts.map +1 -0
  52. package/dist/runtime/session.js +55 -0
  53. package/dist/runtime/session.js.map +1 -0
  54. package/dist/runtime/task-runtime.d.ts +51 -0
  55. package/dist/runtime/task-runtime.d.ts.map +1 -0
  56. package/dist/runtime/task-runtime.js +246 -0
  57. package/dist/runtime/task-runtime.js.map +1 -0
  58. package/dist/skills/loader.d.ts +11 -0
  59. package/dist/skills/loader.d.ts.map +1 -0
  60. package/dist/skills/loader.js +45 -0
  61. package/dist/skills/loader.js.map +1 -0
  62. package/dist/skills/parser.d.ts +3 -0
  63. package/dist/skills/parser.d.ts.map +1 -0
  64. package/dist/skills/parser.js +33 -0
  65. package/dist/skills/parser.js.map +1 -0
  66. package/dist/skills/tool.d.ts +3 -0
  67. package/dist/skills/tool.d.ts.map +1 -0
  68. package/dist/skills/tool.js +32 -0
  69. package/dist/skills/tool.js.map +1 -0
  70. package/dist/skills/types.d.ts +22 -0
  71. package/dist/skills/types.d.ts.map +1 -0
  72. package/dist/skills/types.js +2 -0
  73. package/dist/skills/types.js.map +1 -0
  74. package/dist/tools/builtin/agent-task.d.ts +2 -0
  75. package/dist/tools/builtin/agent-task.d.ts.map +1 -0
  76. package/dist/tools/builtin/agent-task.js +34 -0
  77. package/dist/tools/builtin/agent-task.js.map +1 -0
  78. package/dist/tools/builtin/bash.d.ts +2 -0
  79. package/dist/tools/builtin/bash.d.ts.map +1 -0
  80. package/dist/tools/builtin/bash.js +95 -0
  81. package/dist/tools/builtin/bash.js.map +1 -0
  82. package/dist/tools/builtin/brief.d.ts +2 -0
  83. package/dist/tools/builtin/brief.d.ts.map +1 -0
  84. package/dist/tools/builtin/brief.js +35 -0
  85. package/dist/tools/builtin/brief.js.map +1 -0
  86. package/dist/tools/builtin/edit.d.ts +2 -0
  87. package/dist/tools/builtin/edit.d.ts.map +1 -0
  88. package/dist/tools/builtin/edit.js +32 -0
  89. package/dist/tools/builtin/edit.js.map +1 -0
  90. package/dist/tools/builtin/glob.d.ts +2 -0
  91. package/dist/tools/builtin/glob.d.ts.map +1 -0
  92. package/dist/tools/builtin/glob.js +28 -0
  93. package/dist/tools/builtin/glob.js.map +1 -0
  94. package/dist/tools/builtin/grep.d.ts +2 -0
  95. package/dist/tools/builtin/grep.d.ts.map +1 -0
  96. package/dist/tools/builtin/grep.js +68 -0
  97. package/dist/tools/builtin/grep.js.map +1 -0
  98. package/dist/tools/builtin/read.d.ts +2 -0
  99. package/dist/tools/builtin/read.d.ts.map +1 -0
  100. package/dist/tools/builtin/read.js +32 -0
  101. package/dist/tools/builtin/read.js.map +1 -0
  102. package/dist/tools/builtin/schedule-tools.d.ts +9 -0
  103. package/dist/tools/builtin/schedule-tools.d.ts.map +1 -0
  104. package/dist/tools/builtin/schedule-tools.js +107 -0
  105. package/dist/tools/builtin/schedule-tools.js.map +1 -0
  106. package/dist/tools/builtin/task-tools.d.ts +13 -0
  107. package/dist/tools/builtin/task-tools.d.ts.map +1 -0
  108. package/dist/tools/builtin/task-tools.js +193 -0
  109. package/dist/tools/builtin/task-tools.js.map +1 -0
  110. package/dist/tools/builtin/write.d.ts +2 -0
  111. package/dist/tools/builtin/write.d.ts.map +1 -0
  112. package/dist/tools/builtin/write.js +35 -0
  113. package/dist/tools/builtin/write.js.map +1 -0
  114. package/dist/tools/index.d.ts +6 -0
  115. package/dist/tools/index.d.ts.map +1 -0
  116. package/dist/tools/index.js +101 -0
  117. package/dist/tools/index.js.map +1 -0
  118. package/dist/tools/types.d.ts +16 -0
  119. package/dist/tools/types.d.ts.map +1 -0
  120. package/dist/tools/types.js +29 -0
  121. package/dist/tools/types.js.map +1 -0
  122. package/dist/types.d.ts +435 -0
  123. package/dist/types.d.ts.map +1 -0
  124. package/dist/types.js +2 -0
  125. package/dist/types.js.map +1 -0
  126. package/docs/architecture.md +43 -0
  127. package/docs/business-requirements.md +92 -0
  128. package/docs/python-mcp-integration.md +100 -0
  129. package/package.json +39 -0
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # nanobot-agent-sdk
2
+
3
+ 一个可长期运行、可调度、可审批、可接 MCP 的**纯 Agent SDK 内核**。
4
+
5
+ > 说明:
6
+ > - 这个仓库不是酒店运营产品。
7
+ > - 酒店运营只是当前最早的参考场景之一。
8
+ > - 内核保持领域无关,你可以在外层包任意业务壳。
9
+
10
+ ## 它是什么
11
+
12
+ 它是一个纯 SDK,不做这些事情:
13
+
14
+ - 不做登录
15
+ - 不做账号体系
16
+ - 不做 Web 客户端壳
17
+ - 不做审批 UI
18
+ - 不做企业后台
19
+ - 不把某个行业的业务规则硬编码进内核
20
+
21
+ 它专注做这些核心能力:
22
+
23
+ - Agent loop
24
+ - Tools runtime
25
+ - Skills
26
+ - MCP 接入
27
+ - Background tasks
28
+ - Scheduler / Cron
29
+ - Daily memory
30
+ - Brief / 事件流
31
+ - Human-in-the-loop approval
32
+ - Policy / guardrails
33
+ - Session persistence
34
+
35
+ ## 适合怎么用
36
+
37
+ 你可以把它当成真正的“内核层”,外部再包:
38
+
39
+ - 酒店 OTA 运营机器人
40
+ - 内容运营机器人
41
+ - CRM / 销售助理
42
+ - 报表巡检机器人
43
+ - 企业内部自动化 agent
44
+ - 任意需要 Python MCP、Web 后台、IM 入口、审批台的 agent 产品
45
+
46
+ ## 设计原则
47
+
48
+ 1. **纯内核**:业务通过 MCP / 宿主注入
49
+ 2. **长期运行**:不只是一问一答
50
+ 3. **可恢复**:任务、schedule、session 都可持久化
51
+ 4. **可观察**:brief、notification、task event 全都往外发
52
+ 5. **可控**:policy + approval 控制高风险动作
53
+ 6. **可扩展**:skills、custom tools、MCP tools 都是一等公民
54
+
55
+ ## 当前已实现
56
+
57
+ - `Agent` / `createAgent()`
58
+ - Anthropic 驱动的 `QueryEngine`
59
+ - 内置工具注册与 preset
60
+ - 文件读写 / 搜索 / Bash / Brief
61
+ - 后台任务运行时
62
+ - 定时任务运行时
63
+ - Daily memory
64
+ - Approval manager
65
+ - Session 持久化
66
+ - Skills loader + Skill tool
67
+ - MCP client bridge
68
+
69
+ ## 快速开始
70
+
71
+ ```ts
72
+ import { createAgent } from 'nanobot-agent-sdk'
73
+
74
+ const agent = await createAgent({
75
+ model: 'claude-sonnet-4-20250514',
76
+ assistant: {
77
+ enabled: true,
78
+ id: 'main-agent',
79
+ name: 'Main Agent',
80
+ proactive: true,
81
+ brief: true,
82
+ },
83
+ tools: { type: 'preset', preset: 'operations' },
84
+ remoteApproval: {
85
+ enabled: true,
86
+ defaultDecision: 'deny',
87
+ },
88
+ onEvent(event) {
89
+ console.log('[event]', event)
90
+ },
91
+ })
92
+
93
+ const result = await agent.run('Read the workspace context and tell me what this project does.')
94
+ console.log(result.text)
95
+ ```
96
+
97
+ ## 接 Python MCP
98
+
99
+ 如果你已经有 Python 脚本,可以把它们暴露成 MCP server,然后直接交给 SDK 调用。
100
+
101
+ ```ts
102
+ import { createAgent } from 'nanobot-agent-sdk'
103
+
104
+ const agent = await createAgent({
105
+ assistant: true,
106
+ tools: { type: 'preset', preset: 'operations' },
107
+ mcpServers: {
108
+ hotelOps: {
109
+ type: 'stdio',
110
+ command: '/usr/local/bin/python3.9',
111
+ args: ['/path/to/your/mcp_server.py'],
112
+ env: {
113
+ PYTHONUNBUFFERED: '1',
114
+ },
115
+ },
116
+ },
117
+ })
118
+ ```
119
+
120
+ 这样 SDK 内核负责:
121
+
122
+ - reasoning
123
+ - tool orchestration
124
+ - approval
125
+ - background tasks
126
+ - scheduling
127
+ - memory
128
+
129
+ 你的 Python 负责:
130
+
131
+ - 开关房
132
+ - 调价
133
+ - 查订单
134
+ - 查库存
135
+ - 任意行业业务动作
136
+
137
+ ## 重要边界
138
+
139
+ ### SDK 内核负责
140
+ - agent loop
141
+ - runtime
142
+ - tools
143
+ - skills
144
+ - MCP bridge
145
+ - policy / approval
146
+ - persistence
147
+
148
+ ### 业务宿主负责
149
+ - 行业业务规则
150
+ - 后台管理台
151
+ - 审批页面
152
+ - IM / Web 接入
153
+ - 用户体系
154
+ - 数据库与配置中心
155
+
156
+ ## 文档
157
+
158
+ - `docs/architecture.md`
159
+ - `docs/business-requirements.md`
160
+ - `docs/python-mcp-integration.md`
161
+
162
+ ## 当前状态
163
+
164
+ 现在已经可以作为一个干净的纯 SDK 地基继续往上开发。
@@ -0,0 +1,60 @@
1
+ import type { AgentOptions, ApprovalDecision, QueryResult, RuntimeTask, SDKMessage, ScheduledTask } from '../types.js';
2
+ export declare class Agent {
3
+ private readonly baseOptions;
4
+ private readonly cwd;
5
+ private readonly sessionId;
6
+ private readonly history;
7
+ private readonly setupPromise;
8
+ private readonly mcpConnections;
9
+ private readonly skillRegistry;
10
+ private model;
11
+ private policy;
12
+ private assistantOptions?;
13
+ private assistant?;
14
+ private memoryRuntime?;
15
+ private taskRuntime;
16
+ private scheduler;
17
+ private approvalManager?;
18
+ private baseTools;
19
+ private loadedSkills;
20
+ private skillTool?;
21
+ private closed;
22
+ constructor(options?: AgentOptions);
23
+ ready(): Promise<this>;
24
+ query(prompt: string, overrides?: Partial<AgentOptions>): AsyncGenerator<SDKMessage, QueryResult>;
25
+ run(prompt: string, overrides?: Partial<AgentOptions>): Promise<QueryResult>;
26
+ runBackgroundPrompt(prompt: string, options: {
27
+ subject: string;
28
+ description?: string;
29
+ metadata?: Record<string, unknown>;
30
+ }): Promise<RuntimeTask>;
31
+ listTasks(): Promise<RuntimeTask[]>;
32
+ getTask(id: string): Promise<RuntimeTask | undefined>;
33
+ getTaskOutput(id: string, maxChars?: number): Promise<string>;
34
+ stopTask(id: string, reason?: string): Promise<boolean>;
35
+ listSchedules(): Promise<ScheduledTask[]>;
36
+ createSchedule(input: {
37
+ name: string;
38
+ schedule: string;
39
+ prompt: string;
40
+ metadata?: Record<string, unknown>;
41
+ }): Promise<ScheduledTask>;
42
+ runScheduleNow(id: string): Promise<boolean>;
43
+ deleteSchedule(id: string): Promise<boolean>;
44
+ listPendingApprovals(): import("../types.js").PermissionRequest[];
45
+ resolveApproval(requestId: string, result: ApprovalDecision): Promise<boolean>;
46
+ listSkills(): import("../skills/types.js").SkillDefinition[];
47
+ close(): Promise<void>;
48
+ private setup;
49
+ private buildBaseTools;
50
+ private connectMcpServers;
51
+ private mergeOptions;
52
+ private resolveTools;
53
+ private resolveSystemPrompt;
54
+ private buildCanUseTool;
55
+ private handleScheduledTask;
56
+ private emitEvent;
57
+ private ensureOpen;
58
+ }
59
+ export declare function createAgent(options?: AgentOptions): Promise<Agent>;
60
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAMhB,WAAW,EAEX,WAAW,EACX,UAAU,EACV,aAAa,EAEd,MAAM,aAAa,CAAA;AAIpB,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;IAErE,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,gBAAgB,CAAC,CAAyB;IAClD,OAAO,CAAC,SAAS,CAAC,CAAkB;IACpC,OAAO,CAAC,aAAa,CAAC,CAAoB;IAC1C,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAwB;IAChD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,SAAS,CAAC,CAAgB;IAClC,OAAO,CAAC,MAAM,CAAQ;gBAEV,OAAO,GAAE,YAAiB;IAQhC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,cAAc,CAAC,UAAU,EAAE,WAAW,CAAC;IAoFtG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAQhF,mBAAmB,CACvB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GACrF,OAAO,CAAC,WAAW,CAAC;IAmBjB,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAKnC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAKrD,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7D,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKvD,aAAa,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAKzC,cAAc,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAKrI,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5C,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlD,oBAAoB;IAId,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpF,UAAU;IAIJ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAkCd,KAAK;IAqDnB,OAAO,CAAC,cAAc;YAwBR,iBAAiB;IAQ/B,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,YAAY;YAyBN,mBAAmB;IA6BjC,OAAO,CAAC,eAAe;YAmCT,mBAAmB;YAQnB,SAAS;IAQvB,OAAO,CAAC,UAAU;CAGnB;AAiDD,wBAAsB,WAAW,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAG5E"}
@@ -0,0 +1,438 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { resolve } from 'path';
3
+ import { QueryEngine } from './engine.js';
4
+ import { buildSystemPrompt } from './system-prompt.js';
5
+ import { connectMCPServer, closeAllConnections } from '../mcp/client.js';
6
+ import { EventedApprovalManager } from '../runtime/approval.js';
7
+ import { createAssistantContext, resolveAssistantOptions } from '../runtime/assistant.js';
8
+ import { DailyMemoryRuntime } from '../runtime/memory.js';
9
+ import { ensureRuntimePaths } from '../runtime/paths.js';
10
+ import { applyPolicyToTools, resolvePolicy } from '../runtime/policy.js';
11
+ import { FileSchedulerRuntime } from '../runtime/scheduler.js';
12
+ import { loadSession, saveSession } from '../runtime/session.js';
13
+ import { FileTaskRuntime } from '../runtime/task-runtime.js';
14
+ import { createSkillRegistry } from '../skills/loader.js';
15
+ import { createSkillTool } from '../skills/tool.js';
16
+ import { dedupeTools, filterTools, getAllBaseTools, getToolPreset } from '../tools/index.js';
17
+ const DEFAULT_MODEL = 'claude-sonnet-4-20250514';
18
+ export class Agent {
19
+ baseOptions;
20
+ cwd;
21
+ sessionId;
22
+ history = [];
23
+ setupPromise;
24
+ mcpConnections = [];
25
+ skillRegistry = createSkillRegistry();
26
+ model;
27
+ policy;
28
+ assistantOptions;
29
+ assistant;
30
+ memoryRuntime;
31
+ taskRuntime;
32
+ scheduler;
33
+ approvalManager;
34
+ baseTools = [];
35
+ loadedSkills = [];
36
+ skillTool;
37
+ closed = false;
38
+ constructor(options = {}) {
39
+ this.baseOptions = { ...options };
40
+ this.cwd = resolve(options.cwd || process.cwd());
41
+ this.sessionId = options.sessionId || options.resume || randomUUID();
42
+ this.model = options.model || DEFAULT_MODEL;
43
+ this.setupPromise = this.setup();
44
+ }
45
+ async ready() {
46
+ await this.setupPromise;
47
+ return this;
48
+ }
49
+ async *query(prompt, overrides = {}) {
50
+ await this.setupPromise;
51
+ this.ensureOpen();
52
+ const merged = this.mergeOptions(overrides);
53
+ const tools = this.resolveTools(merged);
54
+ const systemPrompt = await this.resolveSystemPrompt(merged, tools);
55
+ const canUseTool = this.buildCanUseTool(merged);
56
+ if (this.assistant && this.memoryRuntime) {
57
+ await this.memoryRuntime.appendDaily({
58
+ category: 'user',
59
+ message: summarizePrompt(prompt),
60
+ }).catch(() => { });
61
+ }
62
+ const initEvent = {
63
+ type: 'system',
64
+ subtype: 'init',
65
+ session_id: this.sessionId,
66
+ tools: tools.map((tool) => tool.name),
67
+ model: this.model,
68
+ cwd: this.cwd,
69
+ mcp_servers: this.mcpConnections.map((connection) => ({ name: connection.name, status: connection.status })),
70
+ permission_mode: merged.permissionMode || 'default',
71
+ };
72
+ await this.emitEvent(initEvent, merged);
73
+ yield initEvent;
74
+ const engine = new QueryEngine({
75
+ cwd: this.cwd,
76
+ model: this.model,
77
+ apiKey: merged.apiKey,
78
+ baseURL: merged.baseURL,
79
+ tools,
80
+ systemPrompt,
81
+ maxTurns: merged.maxTurns || 12,
82
+ maxBudgetUsd: merged.maxBudgetUsd,
83
+ maxTokens: merged.maxTokens || 4096,
84
+ thinking: merged.thinking,
85
+ estimateCostUsd: merged.estimateCostUsd || defaultEstimateCostUsd,
86
+ jsonSchema: merged.jsonSchema,
87
+ canUseTool,
88
+ includePartialMessages: merged.includePartialMessages ?? true,
89
+ abortSignal: merged.abortSignal || merged.abortController?.signal || this.baseOptions.abortSignal || this.baseOptions.abortController?.signal,
90
+ sessionId: this.sessionId,
91
+ onEvent: (event) => this.emitEvent(event, merged),
92
+ taskRuntime: this.taskRuntime,
93
+ scheduler: this.scheduler,
94
+ approvalManager: this.approvalManager,
95
+ memoryRuntime: this.memoryRuntime,
96
+ assistant: this.assistant,
97
+ initialMessages: [...this.history],
98
+ startBackgroundAgentTask: (input) => this.runBackgroundPrompt(input.prompt, {
99
+ subject: input.subject,
100
+ description: input.description,
101
+ metadata: input.metadata,
102
+ }),
103
+ });
104
+ const iterator = engine.submit(prompt);
105
+ try {
106
+ while (true) {
107
+ const next = await iterator.next();
108
+ if (next.done) {
109
+ this.history.splice(0, this.history.length, ...engine.messages);
110
+ if (shouldPersistSession(merged)) {
111
+ await saveSession(this.sessionId, this.history, {
112
+ cwd: this.cwd,
113
+ model: this.model,
114
+ summary: summarizePrompt(prompt),
115
+ }).catch(() => { });
116
+ }
117
+ return next.value;
118
+ }
119
+ yield next.value;
120
+ }
121
+ }
122
+ finally {
123
+ if (engine.messages.length) {
124
+ this.history.splice(0, this.history.length, ...engine.messages);
125
+ }
126
+ }
127
+ }
128
+ async run(prompt, overrides = {}) {
129
+ const iterator = this.query(prompt, overrides);
130
+ while (true) {
131
+ const next = await iterator.next();
132
+ if (next.done)
133
+ return next.value;
134
+ }
135
+ }
136
+ async runBackgroundPrompt(prompt, options) {
137
+ await this.setupPromise;
138
+ this.ensureOpen();
139
+ if (!this.taskRuntime.startAgentTask) {
140
+ throw new Error('Task runtime does not support background agent tasks.');
141
+ }
142
+ return this.taskRuntime.startAgentTask({
143
+ subject: options.subject,
144
+ description: options.description,
145
+ metadata: options.metadata,
146
+ runner: async () => {
147
+ const result = await this.run(prompt, {
148
+ includePartialMessages: false,
149
+ });
150
+ return result.text || JSON.stringify(result, null, 2);
151
+ },
152
+ });
153
+ }
154
+ async listTasks() {
155
+ await this.setupPromise;
156
+ return this.taskRuntime.listTasks();
157
+ }
158
+ async getTask(id) {
159
+ await this.setupPromise;
160
+ return this.taskRuntime.getTask(id);
161
+ }
162
+ async getTaskOutput(id, maxChars) {
163
+ await this.setupPromise;
164
+ return this.taskRuntime.getOutput(id, maxChars);
165
+ }
166
+ async stopTask(id, reason) {
167
+ await this.setupPromise;
168
+ return this.taskRuntime.cancelTask(id, reason);
169
+ }
170
+ async listSchedules() {
171
+ await this.setupPromise;
172
+ return this.scheduler.listTasks();
173
+ }
174
+ async createSchedule(input) {
175
+ await this.setupPromise;
176
+ return this.scheduler.createTask({ ...input, enabled: true });
177
+ }
178
+ async runScheduleNow(id) {
179
+ await this.setupPromise;
180
+ return this.scheduler.runNow(id);
181
+ }
182
+ async deleteSchedule(id) {
183
+ await this.setupPromise;
184
+ return this.scheduler.deleteTask(id);
185
+ }
186
+ listPendingApprovals() {
187
+ return this.approvalManager?.listPending() || [];
188
+ }
189
+ async resolveApproval(requestId, result) {
190
+ if (!this.approvalManager)
191
+ return false;
192
+ return this.approvalManager.resolve(requestId, result);
193
+ }
194
+ listSkills() {
195
+ return [...this.loadedSkills];
196
+ }
197
+ async close() {
198
+ if (this.closed)
199
+ return;
200
+ this.closed = true;
201
+ const errors = [];
202
+ try {
203
+ await this.scheduler.stop();
204
+ }
205
+ catch (error) {
206
+ errors.push(`scheduler.stop: ${error?.message || String(error)}`);
207
+ }
208
+ try {
209
+ await this.approvalManager?.shutdown?.();
210
+ }
211
+ catch (error) {
212
+ errors.push(`approval.shutdown: ${error?.message || String(error)}`);
213
+ }
214
+ try {
215
+ await this.taskRuntime.shutdown?.('Agent shutting down');
216
+ }
217
+ catch (error) {
218
+ errors.push(`taskRuntime.shutdown: ${error?.message || String(error)}`);
219
+ }
220
+ try {
221
+ await closeAllConnections(this.mcpConnections);
222
+ }
223
+ catch (error) {
224
+ errors.push(`mcp.closeAllConnections: ${error?.message || String(error)}`);
225
+ }
226
+ if (errors.length) {
227
+ console.warn(`[nanobot-agent-sdk] close() completed with errors:\n${errors.join('\n')}`);
228
+ }
229
+ }
230
+ async setup() {
231
+ this.policy = await resolvePolicy(this.baseOptions.policy, this.cwd);
232
+ this.assistantOptions = this.policy.allowAssistantRuntime
233
+ ? resolveAssistantOptions(this.baseOptions.assistant, this.sessionId)
234
+ : undefined;
235
+ const paths = await ensureRuntimePaths({
236
+ assistantId: this.assistantOptions?.id || this.sessionId,
237
+ memoryDir: this.assistantOptions?.memoryDir,
238
+ });
239
+ this.assistant = createAssistantContext(this.assistantOptions, paths, this.sessionId);
240
+ this.memoryRuntime = this.assistant ? new DailyMemoryRuntime(this.assistant) : undefined;
241
+ this.taskRuntime = new FileTaskRuntime(paths, (event) => void this.emitEvent(event), this.memoryRuntime, this.assistant);
242
+ await this.taskRuntime.initialize();
243
+ this.approvalManager = this.policy.allowRemoteApproval
244
+ ? new EventedApprovalManager(this.baseOptions.remoteApproval, (event) => void this.emitEvent(event), this.memoryRuntime, this.assistant)
245
+ : undefined;
246
+ this.scheduler = new FileSchedulerRuntime(paths, (task) => this.handleScheduledTask(task), (event) => void this.emitEvent(event), this.memoryRuntime, this.assistant);
247
+ await this.scheduler.initialize();
248
+ if (this.baseOptions.resume) {
249
+ const loaded = await loadSession(this.baseOptions.resume);
250
+ if (loaded?.messages?.length) {
251
+ this.history.splice(0, this.history.length, ...loaded.messages);
252
+ }
253
+ }
254
+ this.loadedSkills = this.policy.allowSkills
255
+ ? this.skillRegistry.load(this.cwd, this.baseOptions.skillDirs || [])
256
+ : [];
257
+ this.skillTool = this.loadedSkills.length ? createSkillTool(this.skillRegistry) : undefined;
258
+ this.baseTools = this.buildBaseTools();
259
+ await this.connectMcpServers(this.baseOptions.mcpServers);
260
+ if (this.assistantOptions?.scheduledPrompts?.length && this.policy.allowScheduledTasks && this.scheduler.seedTasks) {
261
+ await this.scheduler.seedTasks(this.assistantOptions.scheduledPrompts);
262
+ }
263
+ if (this.assistantOptions?.enabled && this.assistantOptions.autoStartScheduler !== false && this.policy.allowScheduledTasks) {
264
+ await this.scheduler.start();
265
+ }
266
+ }
267
+ buildBaseTools() {
268
+ const raw = this.baseOptions.tools;
269
+ let pool;
270
+ if (!raw) {
271
+ pool = getToolPreset(this.assistant ? 'operations' : 'default');
272
+ }
273
+ else if (!Array.isArray(raw) && typeof raw === 'object' && 'type' in raw) {
274
+ pool = getToolPreset(raw.preset);
275
+ }
276
+ else if (Array.isArray(raw) && raw.length > 0 && typeof raw[0] === 'string') {
277
+ pool = filterTools(getAllBaseTools(), raw);
278
+ }
279
+ else {
280
+ pool = raw;
281
+ }
282
+ if (this.policy.allowSkills && this.skillTool) {
283
+ pool = [...pool, this.skillTool];
284
+ }
285
+ return applyPolicyToTools(filterTools(pool, this.baseOptions.allowedTools, this.baseOptions.disallowedTools), this.policy);
286
+ }
287
+ async connectMcpServers(mcpServers) {
288
+ if (!mcpServers)
289
+ return;
290
+ for (const [name, config] of Object.entries(mcpServers)) {
291
+ const connection = await connectMCPServer(name, config);
292
+ this.mcpConnections.push(connection);
293
+ }
294
+ }
295
+ mergeOptions(overrides) {
296
+ return {
297
+ ...this.baseOptions,
298
+ ...overrides,
299
+ env: { ...(this.baseOptions.env || {}), ...(overrides.env || {}) },
300
+ remoteApproval: overrides.remoteApproval || this.baseOptions.remoteApproval,
301
+ };
302
+ }
303
+ resolveTools(options) {
304
+ let pool = [...this.baseTools];
305
+ if (options.tools && options.tools !== this.baseOptions.tools) {
306
+ const raw = options.tools;
307
+ if (!Array.isArray(raw) && typeof raw === 'object' && 'type' in raw) {
308
+ pool = getToolPreset(raw.preset);
309
+ }
310
+ else if (Array.isArray(raw) && raw.length > 0 && typeof raw[0] === 'string') {
311
+ pool = filterTools(getAllBaseTools(), raw);
312
+ }
313
+ else if (Array.isArray(raw)) {
314
+ pool = raw;
315
+ }
316
+ if (this.policy.allowSkills && this.skillTool && !pool.find((tool) => tool.name === this.skillTool?.name)) {
317
+ pool.push(this.skillTool);
318
+ }
319
+ }
320
+ const merged = dedupeTools(filterTools(pool, options.allowedTools, options.disallowedTools).concat(this.mcpConnections.flatMap((connection) => connection.status === 'connected' ? connection.tools : [])));
321
+ return applyPolicyToTools(merged, this.policy);
322
+ }
323
+ async resolveSystemPrompt(options, tools) {
324
+ const systemInput = resolveSystemPromptInput(options.systemPrompt);
325
+ const skillAppend = this.policy.allowSkills && this.loadedSkills.length
326
+ ? [
327
+ '# Available Skills',
328
+ ...this.loadedSkills
329
+ .filter((skill) => skill.modelInvocable)
330
+ .map((skill) => `- ${skill.name}: ${skill.description}`),
331
+ ].join('\n')
332
+ : '';
333
+ const schemaAppend = options.jsonSchema
334
+ ? `Return JSON matching this schema when no tool call is required:\n${JSON.stringify(options.jsonSchema, null, 2)}`
335
+ : '';
336
+ return buildSystemPrompt({
337
+ cwd: this.cwd,
338
+ tools,
339
+ assistant: this.assistant,
340
+ memoryRuntime: this.memoryRuntime,
341
+ policy: this.policy,
342
+ promptPreset: systemInput.preset,
343
+ systemPrompt: systemInput.text,
344
+ appendSystemPrompt: [systemInput.append, options.appendSystemPrompt, skillAppend, schemaAppend]
345
+ .filter(Boolean)
346
+ .join('\n\n'),
347
+ });
348
+ }
349
+ buildCanUseTool(options) {
350
+ const permissionMode = options.permissionMode || 'default';
351
+ return async (tool, input) => {
352
+ if (this.policy.disabledTools.includes(tool.name)) {
353
+ return { behavior: 'deny', message: `Tool disabled by policy: ${tool.name}` };
354
+ }
355
+ const custom = await options.canUseTool?.(tool, input);
356
+ if (custom?.behavior === 'deny' || custom?.updatedInput !== undefined) {
357
+ return custom;
358
+ }
359
+ if (tool.isReadOnly?.())
360
+ return { behavior: 'allow' };
361
+ if (!this.policy.allowBackgroundTasks && isBackgroundTaskRequest(tool.name, input)) {
362
+ return { behavior: 'deny', message: 'Background tasks are disabled by policy.' };
363
+ }
364
+ if (this.approvalManager &&
365
+ this.policy.allowRemoteApproval &&
366
+ options.remoteApproval?.enabled &&
367
+ ['default', 'plan', 'acceptEdits'].includes(permissionMode)) {
368
+ return this.approvalManager.request({
369
+ toolName: tool.name,
370
+ toolInput: input,
371
+ message: `Approval required for ${tool.name}`,
372
+ });
373
+ }
374
+ return { behavior: 'allow' };
375
+ };
376
+ }
377
+ async handleScheduledTask(task) {
378
+ await this.runBackgroundPrompt(task.prompt, {
379
+ subject: `schedule:${task.name}`,
380
+ description: `Scheduled task ${task.name}`,
381
+ metadata: { scheduleId: task.id, kind: 'scheduled' },
382
+ });
383
+ }
384
+ async emitEvent(event, options) {
385
+ try {
386
+ await (options?.onEvent || this.baseOptions.onEvent)?.(event);
387
+ }
388
+ catch {
389
+ // ignore host callback failures
390
+ }
391
+ }
392
+ ensureOpen() {
393
+ if (this.closed)
394
+ throw new Error('Agent has been closed.');
395
+ }
396
+ }
397
+ function resolveSystemPromptInput(input) {
398
+ if (!input)
399
+ return { preset: 'default' };
400
+ if (typeof input === 'string')
401
+ return { preset: 'default', text: input };
402
+ return {
403
+ preset: input.preset,
404
+ append: input.append,
405
+ };
406
+ }
407
+ function shouldPersistSession(options) {
408
+ return options.persistSession !== false;
409
+ }
410
+ function summarizePrompt(prompt, maxChars = 240) {
411
+ const compact = prompt.replace(/\s+/g, ' ').trim();
412
+ return compact.length > maxChars ? `${compact.slice(0, maxChars - 3)}...` : compact;
413
+ }
414
+ function isBackgroundTaskRequest(toolName, input) {
415
+ if (toolName === 'AgentTask')
416
+ return true;
417
+ if (toolName === 'Bash')
418
+ return Boolean(input?.run_in_background);
419
+ return false;
420
+ }
421
+ const MODEL_PRICING = [
422
+ { match: /haiku/i, inputPerMillion: 0.8, outputPerMillion: 4 },
423
+ { match: /sonnet/i, inputPerMillion: 3, outputPerMillion: 15 },
424
+ { match: /opus/i, inputPerMillion: 15, outputPerMillion: 75 },
425
+ ];
426
+ const defaultEstimateCostUsd = ({ model, usage }) => {
427
+ const pricing = MODEL_PRICING.find((entry) => entry.match.test(model));
428
+ if (!pricing)
429
+ return 0;
430
+ const inputCost = (usage.input_tokens / 1_000_000) * pricing.inputPerMillion;
431
+ const outputCost = (usage.output_tokens / 1_000_000) * pricing.outputPerMillion;
432
+ return inputCost + outputCost;
433
+ };
434
+ export async function createAgent(options = {}) {
435
+ const agent = new Agent(options);
436
+ return agent.ready();
437
+ }
438
+ //# sourceMappingURL=agent.js.map