@michael-joseph-miller/ant-bot 0.1.5 → 0.2.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.
- package/CHANGELOG.md +30 -0
- package/README.md +9 -5
- package/dist/{chunk-4XML2GPY.js → chunk-RMDMUCVS.js} +50 -4
- package/dist/chunk-RMDMUCVS.js.map +7 -0
- package/dist/index.js +229 -1
- package/dist/index.js.map +3 -3
- package/dist/server.js +426 -10
- package/dist/server.js.map +4 -4
- package/package.json +1 -1
- package/web/dist/assets/index-B90EjIDl.css +2 -0
- package/web/dist/assets/index-nnI9BOXM.js +130 -0
- package/web/dist/index.html +2 -2
- package/dist/chunk-4XML2GPY.js.map +0 -7
- package/web/dist/assets/index-BCKrSQY_.js +0 -130
- package/web/dist/assets/index-e3_GBdXi.css +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,36 @@ All notable changes to ant-bot are recorded here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
5
|
[semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.2.0] — 2026-08-23
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **MCP connectors.** External MCP servers can be registered account-wide and assigned to
|
|
12
|
+
individual Bots, the way skills are. Assignment *is* the permission: a Bot that has not been
|
|
13
|
+
given a connector never has the server mounted, so its tools do not exist for that Bot.
|
|
14
|
+
Disabling a connector withdraws it from every Bot at once.
|
|
15
|
+
- Manage them on the new **Connectors** screen, over `/api/connectors`, or with
|
|
16
|
+
`antbot connector list|add|enable|disable|remove|test`.
|
|
17
|
+
- `antbot connector test` connects to the server and lists the tools it offers, so a broken
|
|
18
|
+
command or a wrong URL is visible before a Bot ever tries to use it.
|
|
19
|
+
- stdio, http and sse transports; http and sse accept an optional per-tool allowlist.
|
|
20
|
+
- Tools reach Bots as `mcp__<name>__<tool>` and pass the permission gateway unchanged — the
|
|
21
|
+
first call raises an approval card, and you allow what you trust with a rule.
|
|
22
|
+
- **Credentials by reference.** Any connector env value or header may contain `{{secret:NAME}}`.
|
|
23
|
+
The daemon resolves it from the keychain when the server starts; the value lives only in that
|
|
24
|
+
subprocess's environment or its outbound headers, never in the database, an API response, a log
|
|
25
|
+
line, or a Bot's context. A reference with nothing behind it is flagged in the UI and CLI, and
|
|
26
|
+
the connector is skipped for the turn rather than failing it.
|
|
27
|
+
- This gives `SecretsService` a scoped `resolve()`; the unscoped `envOverlay()` remains unused.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- `docs/USER-GUIDE.md` gains §11 (Connectors); later sections renumbered, §23 is now the
|
|
32
|
+
known-limitations list. `docs/API-CONTRACT.md` documents seven new endpoints — a deliberate
|
|
33
|
+
change to a frozen contract. `docs/SECURITY.md` gains a connectors section covering what the
|
|
34
|
+
workspace boundary does not cover, why allow rules should be fully qualified, and the fact that
|
|
35
|
+
a credential does reach the connector's own process.
|
|
36
|
+
|
|
7
37
|
## [0.1.5] — 2026-08-23
|
|
8
38
|
|
|
9
39
|
### Fixed
|
package/README.md
CHANGED
|
@@ -14,6 +14,9 @@ subscription login rather than a metered `ANTHROPIC_API_KEY`.
|
|
|
14
14
|
and a memory directory that survives daemon restarts.
|
|
15
15
|
- **A shared computer** — one workspace directory, one persistent browser profile, one terminal;
|
|
16
16
|
every Bot can reach what every other Bot can reach.
|
|
17
|
+
- **Connectors** — attach an MCP server (GitHub, filesystem, your own) once, then assign it per Bot.
|
|
18
|
+
A Bot without the assignment cannot see its tools; credentials stay in the keychain as
|
|
19
|
+
`{{secret:NAME}}` references.
|
|
17
20
|
- **Approvals** — every tool call a Bot proposes passes a Permission Gateway: deterministic rules,
|
|
18
21
|
optional Haiku auto-review, or a human approval card in the thread.
|
|
19
22
|
- **Skills** — standard Claude skills (`SKILL.md`), installed with `antbot skill add <source>` from
|
|
@@ -91,6 +94,7 @@ web assets. There's no separate frontend server to run.
|
|
|
91
94
|
| `antbot restart` | Stop and start again |
|
|
92
95
|
| `antbot status` | Whether it's running, on what port, with how many bots |
|
|
93
96
|
| `antbot doctor` | Diagnose the environment; every failure prints its fix |
|
|
97
|
+
| `antbot connector` | Manage the MCP servers your bots can use (`list`/`add`/`test`/`remove`) |
|
|
94
98
|
| `antbot update` | Update to the latest published version (`--check` to look without installing) |
|
|
95
99
|
|
|
96
100
|
Run `antbot --help` for the full list, or `antbot <command> --help` for one command.
|
|
@@ -275,11 +279,11 @@ Current totals, as run against this checkout:
|
|
|
275
279
|
|
|
276
280
|
| Package | Test files | Tests |
|
|
277
281
|
|---|---|---|
|
|
278
|
-
| `@antbot/contract` | 1 |
|
|
279
|
-
| `@antbot/daemon` |
|
|
280
|
-
| `@antbot/ui` |
|
|
281
|
-
| `@antbot/cli` |
|
|
282
|
-
| **Total** | **
|
|
282
|
+
| `@antbot/contract` | 1 | 34 |
|
|
283
|
+
| `@antbot/daemon` | 23 | 528 |
|
|
284
|
+
| `@antbot/ui` | 9 | 80 |
|
|
285
|
+
| `@antbot/cli` | 8 | 133 |
|
|
286
|
+
| **Total** | **41** | **775** |
|
|
283
287
|
|
|
284
288
|
## Status / not built
|
|
285
289
|
|
|
@@ -33,9 +33,6 @@ var LimitError = class extends Error {
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
// contract/dist/events.js
|
|
37
|
-
import { z as z2 } from "zod";
|
|
38
|
-
|
|
39
36
|
// contract/dist/entities.js
|
|
40
37
|
import { z } from "zod";
|
|
41
38
|
var BotStateSchema = z.enum([
|
|
@@ -157,6 +154,40 @@ var SkillSchema = z.object({
|
|
|
157
154
|
source: z.enum(["user", "taught", "imported"]).default("user"),
|
|
158
155
|
createdAt: z.number()
|
|
159
156
|
});
|
|
157
|
+
var CONNECTOR_NAME_RE = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
158
|
+
var RESERVED_CONNECTOR_NAMES = ["antbot", "browser"];
|
|
159
|
+
var ConnectorConfigSchema = z.discriminatedUnion("transport", [
|
|
160
|
+
z.object({
|
|
161
|
+
transport: z.literal("stdio"),
|
|
162
|
+
command: z.string().min(1),
|
|
163
|
+
args: z.array(z.string()).default([]),
|
|
164
|
+
env: z.record(z.string(), z.string()).default({})
|
|
165
|
+
}),
|
|
166
|
+
z.object({
|
|
167
|
+
transport: z.literal("http"),
|
|
168
|
+
url: z.string().url(),
|
|
169
|
+
headers: z.record(z.string(), z.string()).default({}),
|
|
170
|
+
/** Optional allowlist passed through to the SDK. Omit to expose every tool the server offers. */
|
|
171
|
+
tools: z.array(z.string()).optional()
|
|
172
|
+
}),
|
|
173
|
+
z.object({
|
|
174
|
+
transport: z.literal("sse"),
|
|
175
|
+
url: z.string().url(),
|
|
176
|
+
headers: z.record(z.string(), z.string()).default({}),
|
|
177
|
+
tools: z.array(z.string()).optional()
|
|
178
|
+
})
|
|
179
|
+
]);
|
|
180
|
+
var ConnectorSchema = z.object({
|
|
181
|
+
id: z.string(),
|
|
182
|
+
name: z.string().regex(CONNECTOR_NAME_RE, "lowercase letters, digits and hyphens only, max 32 characters").refine((n) => !RESERVED_CONNECTOR_NAMES.includes(n), {
|
|
183
|
+
message: `"antbot" and "browser" are reserved for the built-in servers`
|
|
184
|
+
}),
|
|
185
|
+
description: z.string().default(""),
|
|
186
|
+
/** Account-wide switch. A disabled connector mounts for nobody, whatever the assignments say. */
|
|
187
|
+
enabled: z.boolean().default(true),
|
|
188
|
+
config: ConnectorConfigSchema,
|
|
189
|
+
createdAt: z.number()
|
|
190
|
+
});
|
|
160
191
|
var RoutineSchema = z.object({
|
|
161
192
|
id: z.string(),
|
|
162
193
|
botId: z.string(),
|
|
@@ -202,6 +233,7 @@ var UsageRowSchema = z.object({
|
|
|
202
233
|
var TurnOriginSchema = z.enum(["user", "bot", "routine", "system"]);
|
|
203
234
|
|
|
204
235
|
// contract/dist/events.js
|
|
236
|
+
import { z as z2 } from "zod";
|
|
205
237
|
var base = { seq: z2.number(), threadId: z2.string().nullable(), botId: z2.string().nullable() };
|
|
206
238
|
var ServerEventSchema = z2.discriminatedUnion("type", [
|
|
207
239
|
/** Connection handshake. Carries the current seq so a client can detect gaps. */
|
|
@@ -308,6 +340,17 @@ var CreateSkillRequest = z3.object({
|
|
|
308
340
|
bodyMd: z3.string().min(1),
|
|
309
341
|
source: z3.enum(["user", "taught", "imported"]).optional()
|
|
310
342
|
});
|
|
343
|
+
var CreateConnectorRequest = z3.object({
|
|
344
|
+
name: ConnectorSchema.shape.name,
|
|
345
|
+
description: z3.string().default(""),
|
|
346
|
+
config: ConnectorConfigSchema,
|
|
347
|
+
enabled: z3.boolean().optional()
|
|
348
|
+
});
|
|
349
|
+
var UpdateConnectorRequest = z3.object({
|
|
350
|
+
description: z3.string().optional(),
|
|
351
|
+
config: ConnectorConfigSchema.optional(),
|
|
352
|
+
enabled: z3.boolean().optional()
|
|
353
|
+
});
|
|
311
354
|
var settingsFields = {
|
|
312
355
|
timezone: z3.string(),
|
|
313
356
|
maxConcurrentSessions: z3.number().min(1).max(8),
|
|
@@ -345,6 +388,7 @@ export {
|
|
|
345
388
|
LIMITS,
|
|
346
389
|
LIMIT_ERROR,
|
|
347
390
|
LimitError,
|
|
391
|
+
ConnectorConfigSchema,
|
|
348
392
|
ScreencastClientFrameSchema,
|
|
349
393
|
CreateBotRequest,
|
|
350
394
|
UpdateBotRequest,
|
|
@@ -354,7 +398,9 @@ export {
|
|
|
354
398
|
CreateRuleRequest,
|
|
355
399
|
CreateRoutineRequest,
|
|
356
400
|
CreateSkillRequest,
|
|
401
|
+
CreateConnectorRequest,
|
|
402
|
+
UpdateConnectorRequest,
|
|
357
403
|
SettingsSchema,
|
|
358
404
|
SettingsPatchSchema
|
|
359
405
|
};
|
|
360
|
-
//# sourceMappingURL=chunk-
|
|
406
|
+
//# sourceMappingURL=chunk-RMDMUCVS.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../contract/src/limits.ts", "../../contract/src/entities.ts", "../../contract/src/events.ts", "../../contract/src/api.ts"],
|
|
4
|
+
"sourcesContent": ["/** Operational limits \u2014 mirrors grok-bot-system-outline.md \u00A713. */\nexport const LIMITS = {\n MAX_BOTS_AND_GROUPS: 50,\n MIN_GROUP_MEMBERS: 2,\n MAX_GROUP_MEMBERS: 6,\n MAX_ROUTINES_PER_BOT: 50,\n ROUTINE_RUNS_RETAINED: 20,\n MAX_ATTACHMENTS_PER_MESSAGE: 6,\n MAX_ATTACHMENT_BYTES: 25 * 1024 * 1024,\n MAX_VIDEO_ATTACHMENT_BYTES: 200 * 1024 * 1024,\n MAX_BOT_TO_BOT_HOPS: 5,\n DEFAULT_MAX_CONCURRENT_SESSIONS: 2,\n APPROVAL_TIMEOUT_MS: 15 * 60 * 1000,\n TEACH_RECORDING_MAX_MS: 10 * 60 * 1000,\n} as const;\n\n/** Error codes returned by the service layer when a limit is violated. */\nexport const LIMIT_ERROR = {\n TOO_MANY_BOTS: 'TOO_MANY_BOTS',\n GROUP_SIZE: 'GROUP_SIZE',\n TOO_MANY_ROUTINES: 'TOO_MANY_ROUTINES',\n TOO_MANY_ATTACHMENTS: 'TOO_MANY_ATTACHMENTS',\n ATTACHMENT_TOO_LARGE: 'ATTACHMENT_TOO_LARGE',\n HOP_LIMIT: 'HOP_LIMIT',\n} as const;\nexport type LimitErrorCode = (typeof LIMIT_ERROR)[keyof typeof LIMIT_ERROR];\n\nexport class LimitError extends Error {\n constructor(\n public code: LimitErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'LimitError';\n }\n}\n", "import { z } from 'zod';\n\nexport const BotStateSchema = z.enum([\n 'idle',\n 'queued',\n 'running',\n 'waiting_approval',\n 'waiting_input',\n 'interrupted',\n]);\nexport type BotState = z.infer<typeof BotStateSchema>;\n\nexport const AttentionSchema = z.enum(['none', 'unread', 'needs_attention']);\nexport type Attention = z.infer<typeof AttentionSchema>;\n\n/**\n * Model tiers a Bot can run on, ordered most to least capable \u2014 this is also the order the UI\n * renders them in, so both pickers stay consistent without repeating the list.\n *\n * Each value is a `claude` CLI model alias, passed through verbatim by `resolveModel()`. Adding a\n * tier here means adding an alias the CLI accepts (`claude --model`), not an API model ID.\n */\nexport const MODEL_TIERS = ['fable', 'opus', 'sonnet', 'haiku'] as const;\nexport const ModelTierSchema = z.enum(MODEL_TIERS);\nexport type ModelTier = z.infer<typeof ModelTierSchema>;\n\nexport const BotSchema = z.object({\n id: z.string(),\n slug: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n name: z.string().min(1).max(60),\n title: z.string().max(120).default(''),\n description: z.string().max(8000).default(''),\n avatarEmoji: z.string().max(8).default('\uD83E\uDD16'),\n modelTier: ModelTierSchema.default('sonnet'),\n pinned: z.boolean().default(false),\n hidden: z.boolean().default(false),\n notifications: z.boolean().default(true),\n sessionId: z.string().nullable().default(null),\n state: BotStateSchema.default('idle'),\n attention: AttentionSchema.default('none'),\n threadId: z.string().nullable().default(null),\n createdAt: z.number(),\n deletedAt: z.number().nullable().default(null),\n});\nexport type Bot = z.infer<typeof BotSchema>;\n\nexport const ThreadKindSchema = z.enum(['dm', 'group']);\nexport type ThreadKind = z.infer<typeof ThreadKindSchema>;\n\nexport const ThreadSchema = z.object({\n id: z.string(),\n kind: ThreadKindSchema,\n title: z.string().default(''),\n memberBotIds: z.array(z.string()).default([]),\n pinned: z.boolean().default(false),\n hidden: z.boolean().default(false),\n lastReadAt: z.number().default(0),\n createdAt: z.number(),\n});\nexport type Thread = z.infer<typeof ThreadSchema>;\n\n/** Cards render structured, non-prose content inside a message. */\nexport const CardSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('tool'),\n toolName: z.string(),\n summary: z.string(),\n input: z.unknown().optional(),\n result: z.string().optional(),\n status: z.enum(['running', 'ok', 'error', 'denied']),\n }),\n z.object({\n type: z.literal('file'),\n path: z.string(),\n name: z.string(),\n mime: z.string(),\n bytes: z.number(),\n action: z.enum(['created', 'modified']).default('created'),\n }),\n z.object({ type: z.literal('approval'), approvalId: z.string() }),\n z.object({ type: z.literal('handoff'), fromBotId: z.string(), toBotId: z.string(), note: z.string() }),\n z.object({ type: z.literal('error'), message: z.string() }),\n]);\nexport type Card = z.infer<typeof CardSchema>;\n\nexport const AuthorKindSchema = z.enum(['user', 'bot', 'system']);\nexport type AuthorKind = z.infer<typeof AuthorKindSchema>;\n\nexport const MessageSchema = z.object({\n id: z.string(),\n threadId: z.string(),\n authorKind: AuthorKindSchema,\n authorBotId: z.string().nullable().default(null),\n replyToId: z.string().nullable().default(null),\n contentMd: z.string().default(''),\n cards: z.array(CardSchema).default([]),\n streaming: z.boolean().default(false),\n createdAt: z.number(),\n});\nexport type Message = z.infer<typeof MessageSchema>;\n\nexport const AttachmentSchema = z.object({\n id: z.string(),\n messageId: z.string().nullable(),\n path: z.string(),\n name: z.string(),\n mime: z.string(),\n bytes: z.number(),\n createdAt: z.number(),\n});\nexport type Attachment = z.infer<typeof AttachmentSchema>;\n\nexport const ApprovalStatusSchema = z.enum(['pending', 'allowed', 'denied', 'expired']);\nexport type ApprovalStatus = z.infer<typeof ApprovalStatusSchema>;\n\nexport const ApprovalSchema = z.object({\n id: z.string(),\n botId: z.string(),\n threadId: z.string(),\n toolName: z.string(),\n inputSummary: z.string(),\n rawInput: z.unknown(),\n status: ApprovalStatusSchema.default('pending'),\n decidedBy: z.enum(['user', 'rule', 'auto_review']).nullable().default(null),\n reason: z.string().default(''),\n ruleId: z.string().nullable().default(null),\n createdAt: z.number(),\n decidedAt: z.number().nullable().default(null),\n});\nexport type Approval = z.infer<typeof ApprovalSchema>;\n\nexport const RuleKindSchema = z.enum(['require', 'allow']);\nexport type RuleKind = z.infer<typeof RuleKindSchema>;\n\nexport const RuleSchema = z.object({\n id: z.string(),\n kind: RuleKindSchema,\n /** Glob over tool name, e.g. \"Bash\", \"browser_*\", \"*\" */\n toolPattern: z.string().default('*'),\n /** Optional regex tested against the serialized tool input. */\n inputPattern: z.string().default(''),\n scopeNote: z.string().default(''),\n builtin: z.boolean().default(false),\n enabled: z.boolean().default(true),\n createdAt: z.number(),\n});\nexport type Rule = z.infer<typeof RuleSchema>;\n\nexport const SkillSchema = z.object({\n id: z.string(),\n slug: z.string(),\n name: z.string(),\n description: z.string().default(''),\n path: z.string(),\n source: z.enum(['user', 'taught', 'imported']).default('user'),\n createdAt: z.number(),\n});\nexport type Skill = z.infer<typeof SkillSchema>;\n\n/* ------------------------------ MCP connectors ------------------------------ */\n\n/**\n * Connector names become the middle segment of every tool name the model sees:\n * `mcp__<name>__<tool>`. Underscores are banned outright because `toolNameAliases()`\n * splits on the first `__` pair \u2014 a name containing one would make a connector's tools\n * unmatchable by the rules that are supposed to gate them.\n */\nexport const CONNECTOR_NAME_RE = /^[a-z0-9][a-z0-9-]{0,31}$/;\n\n/** Taken by the built-in servers; a connector using one would overwrite it in the turn's server map. */\nexport const RESERVED_CONNECTOR_NAMES = ['antbot', 'browser'] as const;\n\n/**\n * How to reach an MCP server. Mirrors the Agent SDK's own `McpServerConfig` minus the\n * in-process `sdk` variant, which only the built-in servers use.\n *\n * Secret values are never stored here. An env value or header may embed `{{secret:NAME}}`,\n * resolved against the keychain at mount time \u2014 see `daemon/src/bots/connectors.ts`.\n */\nexport const ConnectorConfigSchema = z.discriminatedUnion('transport', [\n z.object({\n transport: z.literal('stdio'),\n command: z.string().min(1),\n args: z.array(z.string()).default([]),\n env: z.record(z.string(), z.string()).default({}),\n }),\n z.object({\n transport: z.literal('http'),\n url: z.string().url(),\n headers: z.record(z.string(), z.string()).default({}),\n /** Optional allowlist passed through to the SDK. Omit to expose every tool the server offers. */\n tools: z.array(z.string()).optional(),\n }),\n z.object({\n transport: z.literal('sse'),\n url: z.string().url(),\n headers: z.record(z.string(), z.string()).default({}),\n tools: z.array(z.string()).optional(),\n }),\n]);\nexport type ConnectorConfig = z.infer<typeof ConnectorConfigSchema>;\n\nexport const ConnectorSchema = z.object({\n id: z.string(),\n name: z\n .string()\n .regex(CONNECTOR_NAME_RE, 'lowercase letters, digits and hyphens only, max 32 characters')\n .refine((n) => !(RESERVED_CONNECTOR_NAMES as readonly string[]).includes(n), {\n message: `\"antbot\" and \"browser\" are reserved for the built-in servers`,\n }),\n description: z.string().default(''),\n /** Account-wide switch. A disabled connector mounts for nobody, whatever the assignments say. */\n enabled: z.boolean().default(true),\n config: ConnectorConfigSchema,\n createdAt: z.number(),\n});\nexport type Connector = z.infer<typeof ConnectorSchema>;\n\nexport const RoutineSchema = z.object({\n id: z.string(),\n botId: z.string(),\n name: z.string().min(1),\n cronExpr: z.string(),\n timezone: z.string().default('UTC'),\n instructionMd: z.string(),\n enabled: z.boolean().default(true),\n lastRunAt: z.number().nullable().default(null),\n nextRunAt: z.number().nullable().default(null),\n createdAt: z.number(),\n});\nexport type Routine = z.infer<typeof RoutineSchema>;\n\nexport const RoutineRunSchema = z.object({\n id: z.string(),\n routineId: z.string(),\n startedAt: z.number(),\n finishedAt: z.number().nullable().default(null),\n status: z.enum(['running', 'ok', 'failed', 'interrupted']),\n summary: z.string().default(''),\n threadId: z.string().nullable().default(null),\n isTest: z.boolean().default(false),\n});\nexport type RoutineRun = z.infer<typeof RoutineRunSchema>;\n\nexport const MailboxEntrySchema = z.object({\n id: z.string(),\n fromBotId: z.string(),\n toBotId: z.string(),\n contentMd: z.string(),\n hops: z.number().default(1),\n delivered: z.boolean().default(false),\n createdAt: z.number(),\n});\nexport type MailboxEntry = z.infer<typeof MailboxEntrySchema>;\n\nexport const UsageRowSchema = z.object({\n id: z.string(),\n botId: z.string(),\n turnId: z.string(),\n model: z.string(),\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n costEstimate: z.number().default(0),\n createdAt: z.number(),\n});\nexport type UsageRow = z.infer<typeof UsageRowSchema>;\n\nexport const TurnOriginSchema = z.enum(['user', 'bot', 'routine', 'system']);\nexport type TurnOrigin = z.infer<typeof TurnOriginSchema>;\n", "import { z } from 'zod';\nimport { BotStateSchema, AttentionSchema, CardSchema, MessageSchema, ApprovalSchema, RoutineRunSchema } from './entities.js';\n\n/** Every server\u2192client event carries {threadId, botId, seq} for ordering/reconciliation. */\nconst base = { seq: z.number(), threadId: z.string().nullable(), botId: z.string().nullable() };\n\nexport const ServerEventSchema = z.discriminatedUnion('type', [\n /** Connection handshake. Carries the current seq so a client can detect gaps. */\n z.object({ ...base, type: z.literal('hello') }),\n z.object({ ...base, type: z.literal('message.created'), message: MessageSchema }),\n z.object({ ...base, type: z.literal('message.delta'), messageId: z.string(), delta: z.string() }),\n z.object({ ...base, type: z.literal('message.done'), messageId: z.string(), contentMd: z.string() }),\n z.object({ ...base, type: z.literal('message.card'), messageId: z.string(), card: CardSchema, cardIndex: z.number() }),\n z.object({ ...base, type: z.literal('bot.state'), state: BotStateSchema, attention: AttentionSchema }),\n z.object({ ...base, type: z.literal('approval.pending'), approval: ApprovalSchema }),\n z.object({ ...base, type: z.literal('approval.resolved'), approval: ApprovalSchema }),\n z.object({ ...base, type: z.literal('routine.run'), run: RoutineRunSchema }),\n z.object({ ...base, type: z.literal('usage.tick'), inputTokens: z.number(), outputTokens: z.number(), model: z.string() }),\n z.object({ ...base, type: z.literal('notify'), title: z.string(), body: z.string(), level: z.enum(['info', 'warn', 'error']) }),\n z.object({ ...base, type: z.literal('secret.request'), requestId: z.string(), name: z.string(), reason: z.string() }),\n z.object({ ...base, type: z.literal('thread.updated'), threadId2: z.string() }),\n]);\nexport type ServerEvent = z.infer<typeof ServerEventSchema>;\nexport type ServerEventType = ServerEvent['type'];\n\n/* ------------------------- screencast input (client \u2192 server) ------------------------- */\n\n/**\n * Human input forwarded over the screencast websocket while a screen is taken over.\n *\n * Coordinates are **normalised** (0\u20131, fractions of the rendered frame) rather than pixels: the\n * screencast is capped at 1280px wide and the browser then scales the image to fit the pane, so\n * the client cannot know the page's real viewport and the server cannot know the client's. Each\n * side converts against what it does know.\n *\n * The daemon dispatches these only while `takeOver()` is active for that bot \u2014 see\n * `docs/SECURITY.md`. Input is a human acting as themselves, so it does not pass the Permission\n * Gateway; the gateway governs what *bots* do.\n */\nexport const ScreencastInputSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('mouse'),\n action: z.enum(['move', 'down', 'up', 'wheel']),\n x: z.number().min(0).max(1),\n y: z.number().min(0).max(1),\n button: z.enum(['left', 'middle', 'right']).default('left'),\n clickCount: z.number().int().min(0).max(3).default(1),\n /** Wheel deltas, in CSS pixels. Only read for `action: 'wheel'`. */\n deltaX: z.number().default(0),\n deltaY: z.number().default(0),\n }),\n z.object({\n kind: z.literal('key'),\n action: z.enum(['down', 'up']),\n /** A KeyboardEvent.key value \u2014 Playwright's keyboard maps these to the right key codes. */\n key: z.string().min(1).max(32),\n }),\n z.object({\n kind: z.literal('text'),\n /** Committed text (IME, paste, or a printable keypress), inserted verbatim. */\n text: z.string().min(1).max(4096),\n }),\n]);\nexport type ScreencastInput = z.infer<typeof ScreencastInputSchema>;\n\n/** Frames the client may send on the screencast socket. */\nexport const ScreencastClientFrameSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('input'), input: ScreencastInputSchema }),\n /**\n * Asks for the remote page's current text selection, so the human can copy out of it.\n *\n * A round trip is needed because the two clipboards are different: pressing Ctrl+C in the\n * viewer copies whatever is selected in *your* browser (nothing \u2014 the page is a JPEG), and\n * forwarding Ctrl+C to the page would write to the headless browser's clipboard, which you\n * have no way to read. So the daemon reads the selection and hands the text back for the\n * viewer to put on your clipboard.\n */\n z.object({ type: z.literal('selection-request') }),\n]);\nexport type ScreencastClientFrame = z.infer<typeof ScreencastClientFrameSchema>;\n", "import { z } from 'zod';\nimport {\n BotSchema, ThreadSchema, MessageSchema, ApprovalSchema, RuleSchema,\n SkillSchema, RoutineSchema, RoutineRunSchema, UsageRowSchema, ModelTierSchema,\n ConnectorSchema, ConnectorConfigSchema, type Connector,\n} from './entities.js';\n\nexport const CreateBotRequest = z.object({\n name: z.string().min(1).max(60),\n title: z.string().max(120).optional(),\n description: z.string().max(8000).optional(),\n avatarEmoji: z.string().max(8).optional(),\n modelTier: ModelTierSchema.optional(),\n});\nexport type CreateBotRequest = z.infer<typeof CreateBotRequest>;\n\nexport const UpdateBotRequest = CreateBotRequest.partial().extend({\n pinned: z.boolean().optional(),\n hidden: z.boolean().optional(),\n notifications: z.boolean().optional(),\n});\nexport type UpdateBotRequest = z.infer<typeof UpdateBotRequest>;\n\nexport const CreateThreadRequest = z.object({\n kind: z.enum(['dm', 'group']),\n title: z.string().optional(),\n memberBotIds: z.array(z.string()),\n});\nexport type CreateThreadRequest = z.infer<typeof CreateThreadRequest>;\n\nexport const PostMessageRequest = z.object({\n contentMd: z.string(),\n attachmentIds: z.array(z.string()).optional(),\n replyToId: z.string().nullable().optional(),\n /** explicit @-mention targets resolved by the client */\n mentionBotIds: z.array(z.string()).optional(),\n mentionEveryone: z.boolean().optional(),\n});\nexport type PostMessageRequest = z.infer<typeof PostMessageRequest>;\n\nexport const ApprovalDecisionRequest = z.object({\n decision: z.enum(['allow', 'deny']),\n alwaysRule: z\n .object({ toolPattern: z.string(), inputPattern: z.string().default(''), scopeNote: z.string().default('') })\n .optional(),\n});\nexport type ApprovalDecisionRequest = z.infer<typeof ApprovalDecisionRequest>;\n\nexport const CreateRuleRequest = z.object({\n kind: z.enum(['require', 'allow']),\n toolPattern: z.string().min(1),\n inputPattern: z.string().default(''),\n scopeNote: z.string().default(''),\n});\nexport type CreateRuleRequest = z.infer<typeof CreateRuleRequest>;\n\nexport const CreateRoutineRequest = z.object({\n botId: z.string(),\n name: z.string().min(1),\n cronExpr: z.string().min(1),\n timezone: z.string().optional(),\n instructionMd: z.string().min(1),\n enabled: z.boolean().optional(),\n});\nexport type CreateRoutineRequest = z.infer<typeof CreateRoutineRequest>;\n\nexport const CreateSkillRequest = z.object({\n name: z.string().min(1),\n description: z.string().default(''),\n bodyMd: z.string().min(1),\n source: z.enum(['user', 'taught', 'imported']).optional(),\n});\nexport type CreateSkillRequest = z.infer<typeof CreateSkillRequest>;\n\nexport const CreateConnectorRequest = z.object({\n name: ConnectorSchema.shape.name,\n description: z.string().default(''),\n config: ConnectorConfigSchema,\n enabled: z.boolean().optional(),\n});\nexport type CreateConnectorRequest = z.infer<typeof CreateConnectorRequest>;\n\n/**\n * No `name`: renaming a connector renames every tool the model and the rules see\n * (`mcp__<name>__<tool>`), silently orphaning any rule written against the old one.\n * Delete and re-add instead.\n */\nexport const UpdateConnectorRequest = z.object({\n description: z.string().optional(),\n config: ConnectorConfigSchema.optional(),\n enabled: z.boolean().optional(),\n});\nexport type UpdateConnectorRequest = z.infer<typeof UpdateConnectorRequest>;\n\n/**\n * A connector as the API returns it. `missingSecrets` names the `{{secret:\u2026}}` references\n * that have nothing behind them \u2014 surfaced so a connector that will silently fail to mount\n * says so in the UI before a turn runs, rather than going quiet at turn time.\n */\nexport type ApiConnector = Connector & { missingSecrets: string[] };\n\n/** What `POST /api/connectors/:id/test` reports. Tool names and descriptions only \u2014 never config. */\nexport interface ConnectorProbeResult {\n ok: boolean;\n tools: { name: string; description: string }[];\n error?: string;\n}\n\n/**\n * Field types, declared once and without defaults. `SettingsSchema` layers the\n * defaults on for reads; `SettingsPatchSchema` deliberately leaves them off.\n */\nconst settingsFields = {\n timezone: z.string(),\n maxConcurrentSessions: z.number().min(1).max(8),\n autoReviewEnabled: z.boolean(),\n theme: z.enum(['system', 'light', 'dark']),\n localExecution: z.enum(['ask', 'always', 'never']),\n dailyTokenBudget: z.number(),\n notificationsEnabled: z.boolean(),\n billingMode: z.enum(['subscription', 'api']),\n computerMode: z.enum(['host', 'container']),\n};\n\nexport const SettingsSchema = z.object({\n timezone: settingsFields.timezone.default('UTC'),\n maxConcurrentSessions: settingsFields.maxConcurrentSessions.default(2),\n autoReviewEnabled: settingsFields.autoReviewEnabled.default(true),\n theme: settingsFields.theme.default('system'),\n localExecution: settingsFields.localExecution.default('ask'),\n dailyTokenBudget: settingsFields.dailyTokenBudget.default(0),\n notificationsEnabled: settingsFields.notificationsEnabled.default(true),\n billingMode: settingsFields.billingMode.default('subscription'),\n computerMode: settingsFields.computerMode.default('host'),\n});\nexport type Settings = z.infer<typeof SettingsSchema>;\n\n/**\n * Body schema for `PATCH /api/settings`. It must NOT carry defaults: parsing a\n * one-field patch through a defaulted schema yields a complete object, and\n * persisting that would reset every setting the client didn't mention \u2014 including\n * `localExecution`, which is a security control (see docs/SECURITY.md).\n */\nexport const SettingsPatchSchema = z.object(settingsFields).partial();\nexport type SettingsPatch = z.infer<typeof SettingsPatchSchema>;\n\nexport const SearchResultSchema = z.object({\n kind: z.enum(['message', 'file', 'routine', 'bot']),\n id: z.string(),\n threadId: z.string().nullable(),\n botId: z.string().nullable(),\n title: z.string(),\n snippet: z.string(),\n createdAt: z.number(),\n});\nexport type SearchResult = z.infer<typeof SearchResultSchema>;\n\nexport type ApiBot = z.infer<typeof BotSchema>;\nexport type ApiThread = z.infer<typeof ThreadSchema>;\nexport type ApiMessage = z.infer<typeof MessageSchema>;\nexport type ApiApproval = z.infer<typeof ApprovalSchema>;\nexport type ApiRule = z.infer<typeof RuleSchema>;\nexport type ApiSkill = z.infer<typeof SkillSchema>;\nexport type ApiRoutine = z.infer<typeof RoutineSchema>;\nexport type ApiRoutineRun = z.infer<typeof RoutineRunSchema>;\nexport type ApiUsageRow = z.infer<typeof UsageRowSchema>;\n\nexport interface RosterEntry { bot: ApiBot; thread: ApiThread | null; lastMessageAt: number }\nexport interface ThreadWithMessages { thread: ApiThread; messages: ApiMessage[] }\nexport interface UsageSummary {\n totals: { inputTokens: number; outputTokens: number; cacheReadTokens: number };\n byBot: Array<{ botId: string; botName: string; inputTokens: number; outputTokens: number }>;\n byDay: Array<{ day: string; inputTokens: number; outputTokens: number }>;\n byModel: Array<{ model: string; inputTokens: number; outputTokens: number }>;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["z", "z", "z", "z"]
|
|
7
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire as __antbotCreateRequire } from 'node:module';
|
|
|
3
3
|
const require = __antbotCreateRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
SettingsSchema
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RMDMUCVS.js";
|
|
7
7
|
|
|
8
8
|
// cli/src/index.ts
|
|
9
9
|
import fs10 from "node:fs";
|
|
@@ -19,6 +19,7 @@ var KNOWN_COMMANDS = [
|
|
|
19
19
|
"doctor",
|
|
20
20
|
"open",
|
|
21
21
|
"skill",
|
|
22
|
+
"connector",
|
|
22
23
|
"backup",
|
|
23
24
|
"restore",
|
|
24
25
|
"update"
|
|
@@ -39,6 +40,7 @@ var COMMAND_FLAGS = {
|
|
|
39
40
|
doctor: {},
|
|
40
41
|
open: {},
|
|
41
42
|
skill: {},
|
|
43
|
+
connector: {},
|
|
42
44
|
backup: {
|
|
43
45
|
out: { type: "string" }
|
|
44
46
|
},
|
|
@@ -50,6 +52,7 @@ var COMMAND_FLAGS = {
|
|
|
50
52
|
yes: { type: "boolean", default: false }
|
|
51
53
|
}
|
|
52
54
|
};
|
|
55
|
+
var PASSTHROUGH_COMMANDS = /* @__PURE__ */ new Set(["connector"]);
|
|
53
56
|
function isKnownCommand(value) {
|
|
54
57
|
return KNOWN_COMMANDS.includes(value);
|
|
55
58
|
}
|
|
@@ -87,6 +90,10 @@ Run "antbot --help" for usage.`);
|
|
|
87
90
|
help = true;
|
|
88
91
|
continue;
|
|
89
92
|
}
|
|
93
|
+
if (PASSTHROUGH_COMMANDS.has(command)) {
|
|
94
|
+
positionals.push(tok);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
90
97
|
if (tok.startsWith("--")) {
|
|
91
98
|
let name = tok.slice(2);
|
|
92
99
|
let inlineValue;
|
|
@@ -142,6 +149,7 @@ Daemon:
|
|
|
142
149
|
|
|
143
150
|
Data:
|
|
144
151
|
skill <subcommand> Manage the skills your bots can use
|
|
152
|
+
connector <subcmd> Manage the MCP servers your bots can use
|
|
145
153
|
backup [--out PATH] Archive the database, config, skills, and bot memory
|
|
146
154
|
restore <path> Restore from a backup archive
|
|
147
155
|
|
|
@@ -256,6 +264,27 @@ live database handle and may be mid-turn.
|
|
|
256
264
|
|
|
257
265
|
In a git checkout there is nothing for a package manager to update \u2014 use
|
|
258
266
|
\`git pull && pnpm install\` instead.`,
|
|
267
|
+
connector: `antbot connector \u2014 manage the MCP servers your bots can use
|
|
268
|
+
|
|
269
|
+
Usage: antbot connector <subcommand>
|
|
270
|
+
|
|
271
|
+
list Show every connector, with a warning for any missing secret
|
|
272
|
+
add <name> \u2026 Add one: --stdio "<cmd>" or --url <url>
|
|
273
|
+
enable|disable <n> Turn one on or off for every bot at once
|
|
274
|
+
remove <name> Delete it, and every bot's assignment to it
|
|
275
|
+
test <name> Connect and list the tools it offers
|
|
276
|
+
|
|
277
|
+
A connector is an MCP server registered once for the account and then assigned to
|
|
278
|
+
individual bots in Bot settings \u2014 a bot with no assignment cannot see its tools at
|
|
279
|
+
all. Its tools reach bots as \`mcp__<name>__<tool>\` and pass the permission gateway
|
|
280
|
+
like any other tool, so the first call asks you for approval.
|
|
281
|
+
|
|
282
|
+
Credentials stay in the keychain: write {{secret:NAME}} in any --env or --header
|
|
283
|
+
value and the daemon substitutes it when the connector is mounted.
|
|
284
|
+
|
|
285
|
+
antbot connector add fs --stdio "npx -y @modelcontextprotocol/server-filesystem /tmp"
|
|
286
|
+
antbot connector add gh --url https://api.example.com/mcp \\
|
|
287
|
+
--header "Authorization=Bearer {{secret:GH_TOKEN}}"`,
|
|
259
288
|
restore: `antbot restore \u2014 restore from a backup archive
|
|
260
289
|
|
|
261
290
|
Usage: antbot restore <path> [--yes]
|
|
@@ -536,6 +565,16 @@ async function postJson(port, path12, body) {
|
|
|
536
565
|
})
|
|
537
566
|
);
|
|
538
567
|
}
|
|
568
|
+
async function patchJson(port, path12, body) {
|
|
569
|
+
return unwrap(
|
|
570
|
+
await fetch(`${BASE(port)}${path12}`, {
|
|
571
|
+
method: "PATCH",
|
|
572
|
+
headers: { "content-type": "application/json" },
|
|
573
|
+
body: JSON.stringify(body),
|
|
574
|
+
signal: AbortSignal.timeout(1e4)
|
|
575
|
+
})
|
|
576
|
+
);
|
|
577
|
+
}
|
|
539
578
|
async function deleteJson(port, path12) {
|
|
540
579
|
return unwrap(
|
|
541
580
|
await fetch(`${BASE(port)}${path12}`, { method: "DELETE", signal: AbortSignal.timeout(1e4) })
|
|
@@ -1160,6 +1199,190 @@ async function lintSkills(args) {
|
|
|
1160
1199
|
return 0;
|
|
1161
1200
|
}
|
|
1162
1201
|
|
|
1202
|
+
// cli/src/connector.ts
|
|
1203
|
+
function collectPairs(argv, flag) {
|
|
1204
|
+
const out = {};
|
|
1205
|
+
for (let i = 0; i < argv.length; i++) {
|
|
1206
|
+
if (argv[i] !== flag) continue;
|
|
1207
|
+
const raw = argv[i + 1] ?? "";
|
|
1208
|
+
const eq = raw.indexOf("=");
|
|
1209
|
+
if (eq > 0) out[raw.slice(0, eq)] = raw.slice(eq + 1);
|
|
1210
|
+
i++;
|
|
1211
|
+
}
|
|
1212
|
+
return out;
|
|
1213
|
+
}
|
|
1214
|
+
function flagValue(argv, flag) {
|
|
1215
|
+
const i = argv.indexOf(flag);
|
|
1216
|
+
return i >= 0 ? argv[i + 1] : void 0;
|
|
1217
|
+
}
|
|
1218
|
+
function splitCommand(input) {
|
|
1219
|
+
const parts = input.match(/"[^"]*"|'[^']*'|\S+/g) ?? [];
|
|
1220
|
+
const clean = parts.map(
|
|
1221
|
+
(p) => p.startsWith('"') && p.endsWith('"') || p.startsWith("'") && p.endsWith("'") ? p.slice(1, -1) : p
|
|
1222
|
+
);
|
|
1223
|
+
return { command: clean[0] ?? "", args: clean.slice(1) };
|
|
1224
|
+
}
|
|
1225
|
+
function buildConfigFromFlags(argv) {
|
|
1226
|
+
const stdio = flagValue(argv, "--stdio");
|
|
1227
|
+
const url = flagValue(argv, "--url");
|
|
1228
|
+
if (stdio && url) return { error: "Use either --stdio or --url, not both." };
|
|
1229
|
+
if (stdio) {
|
|
1230
|
+
const { command, args } = splitCommand(stdio);
|
|
1231
|
+
if (!command) return { error: '--stdio needs a command, e.g. --stdio "npx -y @scope/server"' };
|
|
1232
|
+
return { config: { transport: "stdio", command, args, env: collectPairs(argv, "--env") } };
|
|
1233
|
+
}
|
|
1234
|
+
if (url) {
|
|
1235
|
+
const transport = flagValue(argv, "--transport") ?? "http";
|
|
1236
|
+
if (transport !== "http" && transport !== "sse") return { error: "--transport must be http or sse" };
|
|
1237
|
+
const tools = flagValue(argv, "--tools");
|
|
1238
|
+
return {
|
|
1239
|
+
config: {
|
|
1240
|
+
transport,
|
|
1241
|
+
url,
|
|
1242
|
+
headers: collectPairs(argv, "--header"),
|
|
1243
|
+
...tools ? { tools: tools.split(",").map((t) => t.trim()).filter(Boolean) } : {}
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
return { error: 'Give either --stdio "<command>" or --url <url>.' };
|
|
1248
|
+
}
|
|
1249
|
+
var transportOf = (c) => String(c.config.transport ?? "?");
|
|
1250
|
+
async function findByName(port, name) {
|
|
1251
|
+
return (await getJson(port, "/api/connectors")).find((c) => c.name === name);
|
|
1252
|
+
}
|
|
1253
|
+
async function runConnectorCommand(argv, port) {
|
|
1254
|
+
const sub = argv[0];
|
|
1255
|
+
const hint = () => {
|
|
1256
|
+
console.error(dim("Subcommands: list, add, enable, disable, remove, test."));
|
|
1257
|
+
console.error(dim("Run `antbot connector --help` for the full usage."));
|
|
1258
|
+
};
|
|
1259
|
+
if (!sub) {
|
|
1260
|
+
console.error(red("antbot connector needs a subcommand."));
|
|
1261
|
+
hint();
|
|
1262
|
+
return 2;
|
|
1263
|
+
}
|
|
1264
|
+
let rows;
|
|
1265
|
+
const load = async () => {
|
|
1266
|
+
try {
|
|
1267
|
+
rows = await getJson(port, "/api/connectors");
|
|
1268
|
+
return true;
|
|
1269
|
+
} catch (err) {
|
|
1270
|
+
console.error(red(`Could not reach the daemon on port ${port}: ${err.message}`));
|
|
1271
|
+
console.error(dim("Start it with `antbot start`."));
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
switch (sub) {
|
|
1276
|
+
case "list": {
|
|
1277
|
+
if (!await load()) return 1;
|
|
1278
|
+
if (!rows.length) {
|
|
1279
|
+
console.log(dim("No connectors yet. Add one with `antbot connector add`."));
|
|
1280
|
+
return 0;
|
|
1281
|
+
}
|
|
1282
|
+
for (const c of rows) {
|
|
1283
|
+
const state = c.enabled ? "" : dim(" (disabled)");
|
|
1284
|
+
console.log(`${bold(c.name)} ${dim(transportOf(c))}${state}`);
|
|
1285
|
+
if (c.description) console.log(` ${c.description}`);
|
|
1286
|
+
if (c.missingSecrets.length) {
|
|
1287
|
+
console.log(yellow(` missing secret(s): ${c.missingSecrets.join(", ")} \u2014 this connector will not mount`));
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
return 0;
|
|
1291
|
+
}
|
|
1292
|
+
case "add": {
|
|
1293
|
+
const name = argv[1];
|
|
1294
|
+
if (!name || name.startsWith("--")) {
|
|
1295
|
+
console.error(red('Usage: antbot connector add <name> (--stdio "<cmd>" | --url <url>)'));
|
|
1296
|
+
return 2;
|
|
1297
|
+
}
|
|
1298
|
+
const built = buildConfigFromFlags(argv);
|
|
1299
|
+
if ("error" in built) {
|
|
1300
|
+
console.error(red(built.error));
|
|
1301
|
+
return 2;
|
|
1302
|
+
}
|
|
1303
|
+
try {
|
|
1304
|
+
const created = await postJson(port, "/api/connectors", {
|
|
1305
|
+
name,
|
|
1306
|
+
description: flagValue(argv, "--desc") ?? "",
|
|
1307
|
+
config: built.config
|
|
1308
|
+
});
|
|
1309
|
+
console.log(green(`Added connector "${created.name}".`));
|
|
1310
|
+
console.log(dim("Assign it to a bot in Bot settings, then `antbot connector test` to check it."));
|
|
1311
|
+
return 0;
|
|
1312
|
+
} catch (err) {
|
|
1313
|
+
console.error(red(err.message));
|
|
1314
|
+
return 1;
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
case "enable":
|
|
1318
|
+
case "disable": {
|
|
1319
|
+
const name = argv[1];
|
|
1320
|
+
if (!name) {
|
|
1321
|
+
console.error(red(`Usage: antbot connector ${sub} <name>`));
|
|
1322
|
+
return 2;
|
|
1323
|
+
}
|
|
1324
|
+
if (!await load()) return 1;
|
|
1325
|
+
const match = rows.find((c) => c.name === name);
|
|
1326
|
+
if (!match) {
|
|
1327
|
+
console.error(red(`No connector named "${name}".`));
|
|
1328
|
+
return 1;
|
|
1329
|
+
}
|
|
1330
|
+
await patchJson(port, `/api/connectors/${match.id}`, { enabled: sub === "enable" });
|
|
1331
|
+
console.log(green(`Connector "${name}" ${sub}d.`));
|
|
1332
|
+
return 0;
|
|
1333
|
+
}
|
|
1334
|
+
case "remove": {
|
|
1335
|
+
const name = argv[1];
|
|
1336
|
+
if (!name) {
|
|
1337
|
+
console.error(red("Usage: antbot connector remove <name>"));
|
|
1338
|
+
return 2;
|
|
1339
|
+
}
|
|
1340
|
+
if (!await load()) return 1;
|
|
1341
|
+
const match = rows.find((c) => c.name === name);
|
|
1342
|
+
if (!match) {
|
|
1343
|
+
console.error(red(`No connector named "${name}".`));
|
|
1344
|
+
return 1;
|
|
1345
|
+
}
|
|
1346
|
+
await deleteJson(port, `/api/connectors/${match.id}`);
|
|
1347
|
+
console.log(green(`Removed connector "${name}". Bot assignments for it are gone too.`));
|
|
1348
|
+
return 0;
|
|
1349
|
+
}
|
|
1350
|
+
case "test": {
|
|
1351
|
+
const name = argv[1];
|
|
1352
|
+
if (!name) {
|
|
1353
|
+
console.error(red("Usage: antbot connector test <name>"));
|
|
1354
|
+
return 2;
|
|
1355
|
+
}
|
|
1356
|
+
let match;
|
|
1357
|
+
try {
|
|
1358
|
+
match = await findByName(port, name);
|
|
1359
|
+
} catch (err) {
|
|
1360
|
+
console.error(red(`Could not reach the daemon on port ${port}: ${err.message}`));
|
|
1361
|
+
return 1;
|
|
1362
|
+
}
|
|
1363
|
+
if (!match) {
|
|
1364
|
+
console.error(red(`No connector named "${name}".`));
|
|
1365
|
+
return 1;
|
|
1366
|
+
}
|
|
1367
|
+
const result = await postJson(port, `/api/connectors/${match.id}/test`, {});
|
|
1368
|
+
if (!result.ok) {
|
|
1369
|
+
console.error(red(`${name}: ${result.error ?? "could not connect"}`));
|
|
1370
|
+
return 1;
|
|
1371
|
+
}
|
|
1372
|
+
console.log(green(`${name}: connected, ${result.tools.length} tool(s)`));
|
|
1373
|
+
for (const t of result.tools) {
|
|
1374
|
+
console.log(` ${bold(`mcp__${name}__${t.name}`)}`);
|
|
1375
|
+
if (t.description) console.log(` ${dim(t.description)}`);
|
|
1376
|
+
}
|
|
1377
|
+
return 0;
|
|
1378
|
+
}
|
|
1379
|
+
default:
|
|
1380
|
+
console.error(red(`Unknown subcommand "${sub}".`));
|
|
1381
|
+
hint();
|
|
1382
|
+
return 2;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1163
1386
|
// cli/src/updateCommand.ts
|
|
1164
1387
|
import fs9 from "node:fs";
|
|
1165
1388
|
import path10 from "node:path";
|
|
@@ -1538,6 +1761,11 @@ async function main() {
|
|
|
1538
1761
|
process.exit(await runSkillCommand(parsed.positionals, cfg.port));
|
|
1539
1762
|
return;
|
|
1540
1763
|
}
|
|
1764
|
+
case "connector": {
|
|
1765
|
+
const cfg = loadConfig();
|
|
1766
|
+
process.exit(await runConnectorCommand(parsed.positionals, cfg.port));
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1541
1769
|
case "backup":
|
|
1542
1770
|
process.exit(await runBackupCommand(typeof parsed.flags.out === "string" ? parsed.flags.out : void 0));
|
|
1543
1771
|
return;
|