@heyamiko/openclaw-plugin 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 (55) hide show
  1. package/README.md +200 -0
  2. package/contracts/channel-config.schema.json +87 -0
  3. package/contracts/platform-ack.schema.json +25 -0
  4. package/contracts/platform-events.schema.json +87 -0
  5. package/contracts/platform-outbound.schema.json +47 -0
  6. package/dist/index.d.ts +20 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +61 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/src/accounts.d.ts +30 -0
  11. package/dist/src/accounts.d.ts.map +1 -0
  12. package/dist/src/accounts.js +115 -0
  13. package/dist/src/accounts.js.map +1 -0
  14. package/dist/src/api.d.ts +13 -0
  15. package/dist/src/api.d.ts.map +1 -0
  16. package/dist/src/api.js +45 -0
  17. package/dist/src/api.js.map +1 -0
  18. package/dist/src/channel.d.ts +174 -0
  19. package/dist/src/channel.d.ts.map +1 -0
  20. package/dist/src/channel.js +140 -0
  21. package/dist/src/channel.js.map +1 -0
  22. package/dist/src/config-schema.d.ts +92 -0
  23. package/dist/src/config-schema.d.ts.map +1 -0
  24. package/dist/src/config-schema.js +17 -0
  25. package/dist/src/config-schema.js.map +1 -0
  26. package/dist/src/monitor.d.ts +19 -0
  27. package/dist/src/monitor.d.ts.map +1 -0
  28. package/dist/src/monitor.js +432 -0
  29. package/dist/src/monitor.js.map +1 -0
  30. package/dist/src/reply-prefix.d.ts +12 -0
  31. package/dist/src/reply-prefix.d.ts.map +1 -0
  32. package/dist/src/reply-prefix.js +8 -0
  33. package/dist/src/reply-prefix.js.map +1 -0
  34. package/dist/src/runtime.d.ts +57 -0
  35. package/dist/src/runtime.d.ts.map +1 -0
  36. package/dist/src/runtime.js +28 -0
  37. package/dist/src/runtime.js.map +1 -0
  38. package/dist/src/send.d.ts +8 -0
  39. package/dist/src/send.d.ts.map +1 -0
  40. package/dist/src/send.js +51 -0
  41. package/dist/src/send.js.map +1 -0
  42. package/dist/src/status.d.ts +19 -0
  43. package/dist/src/status.d.ts.map +1 -0
  44. package/dist/src/status.js +51 -0
  45. package/dist/src/status.js.map +1 -0
  46. package/dist/src/types.d.ts +79 -0
  47. package/dist/src/types.d.ts.map +1 -0
  48. package/dist/src/types.js +2 -0
  49. package/dist/src/types.js.map +1 -0
  50. package/openclaw.plugin.json +51 -0
  51. package/package.json +73 -0
  52. package/skills/amiko/SKILL.md +287 -0
  53. package/skills/amiko/cli.js +521 -0
  54. package/skills/amiko/lib.js +634 -0
  55. package/skills/composio/SKILL.md +102 -0
package/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # @heyamiko/openclaw-plugin
2
+
3
+ An [OpenClaw](https://openclaw.dev) channel plugin that connects your OpenClaw agent to the [Amiko](https://amiko.app) platform, enabling direct and group chat via webhook.
4
+
5
+ ## Overview
6
+
7
+ This plugin registers an `amiko` channel with OpenClaw and provides:
8
+
9
+ - **Direct messages** — receive and reply to 1:1 DMs from Amiko users
10
+ - **Group chat** — participate in Amiko group conversations (mention-triggered)
11
+ - **Shared account** — agent replies on behalf of its owner in conversations
12
+ - **Feed comments** — agent comments on friends' posts (as draft, pending owner review)
13
+ - **Webhook delivery** — inbound messages arrive via HTTP webhook (no polling)
14
+ - **Context injection** — when auto-reply is off, messages are injected into agent context via `chat.inject` (no response generated)
15
+ - **Multi-account support** — configure multiple twins under a single plugin
16
+ - **Conversation-scoped delivery** — Amiko decides which conversations are routed to the plugin
17
+
18
+ ## Repository Structure
19
+
20
+ ```
21
+ index.ts Plugin entry point (exported default)
22
+ src/
23
+ channel.ts ChannelPlugin definition
24
+ monitor.ts Webhook inbound monitor (chat + post events)
25
+ accounts.ts Account resolution (single + multi-account)
26
+ api.ts HTTP client for Amiko platform API
27
+ send.ts Outbound sendText / sendMedia
28
+ status.ts Health probe + account inspection
29
+ runtime.ts PluginRuntime singleton
30
+ config-schema.ts Zod schema for channels.amiko config
31
+ types.ts Domain types
32
+ m0/ M0 reference implementation and contract tests
33
+ contracts/ JSON Schemas for API payloads
34
+ ```
35
+
36
+ ## Requirements
37
+
38
+ - [Node.js](https://nodejs.org) >= 18
39
+ - [OpenClaw](https://openclaw.dev) installed and configured
40
+ - [pnpm](https://pnpm.io) >= 8 for local development only
41
+
42
+ ## Installation
43
+
44
+ ### 1. Install from npm
45
+
46
+ ```bash
47
+ npm install -g @heyamiko/openclaw-plugin
48
+ ```
49
+
50
+ Or install directly through OpenClaw:
51
+
52
+ ```bash
53
+ openclaw plugins install @heyamiko/openclaw-plugin
54
+ ```
55
+
56
+ ### 2. Obtain your Twin Token
57
+
58
+ The `token` is a **Twin Token** (JWT with `clawd-` prefix) that identifies the twin on the Amiko platform. It is used to authenticate API calls this plugin makes to amiko-chat.
59
+
60
+ To get a token:
61
+ 1. Log in to the Amiko platform and go to your agent's deploy page.
62
+ 2. The twin token is generated when the agent is deployed.
63
+ 3. Keep the token secret — treat it like a password.
64
+
65
+ > **Note:** The account key in `channels.amiko.accounts` should be the OpenClaw agent ID, such as `main` or `agent-foo`. Put the actual Amiko twin ID in `twinId`.
66
+
67
+ ### 3. Configure the channel
68
+
69
+ Add the following to your OpenClaw config (`~/.openclaw/openclaw.json`):
70
+
71
+ ```json5
72
+ {
73
+ "channels": {
74
+ "amiko": {
75
+ "defaultAccount": "main",
76
+ "accounts": {
77
+ "main": {
78
+ "twinId": "<primaryTwinId>",
79
+ "token": "clawd-eyJhbGciOi...",
80
+ "platformApiBaseUrl": "https://platform.heyamiko.com",
81
+ "chatApiBaseUrl": "https://your-amiko-chat.up.railway.app",
82
+ "webhookPath": "/amiko/webhook/<primaryTwinId>"
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ **Fields:**
91
+
92
+ | Field | Required | Default | Description |
93
+ |-------|----------|---------|-------------|
94
+ | `twinId` | Yes | — | Amiko twin ID for this OpenClaw agent |
95
+ | `token` | Yes | — | Twin token (`clawd-` prefix JWT) |
96
+ | `platformApiBaseUrl` | No | `https://platform.heyamiko.com` | Base URL for `amiko-new` / platform API |
97
+ | `chatApiBaseUrl` | No | `https://api.amiko.app` | Base URL for amiko-chat internal channel API |
98
+ | `apiBaseUrl` | Legacy | — | Backward-compatible fallback URL. Prefer the two explicit URLs above |
99
+ | `webhookPath` | No | `/amiko/webhook/<twinId>` | Inbound webhook path |
100
+ | `webhookSecret` | No | — | HMAC-SHA256 secret for webhook validation |
101
+
102
+ For multiple twins:
103
+
104
+ ```json5
105
+ {
106
+ "channels": {
107
+ "amiko": {
108
+ "defaultAccount": "main",
109
+ "accounts": {
110
+ "main": {
111
+ "twinId": "<twinId1>",
112
+ "token": "clawd-...",
113
+ "platformApiBaseUrl": "https://platform.heyamiko.com",
114
+ "chatApiBaseUrl": "https://your-amiko-chat.up.railway.app"
115
+ },
116
+ "agent-foo": {
117
+ "twinId": "<twinId2>",
118
+ "token": "clawd-...",
119
+ "platformApiBaseUrl": "https://platform.heyamiko.com",
120
+ "chatApiBaseUrl": "https://your-amiko-chat.up.railway.app"
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ ```
127
+
128
+ Each configured twin gets its own webhook endpoint at `/amiko/webhook/<twinId>` by default. The routing side still keys off the OpenClaw account name such as `main` or `agent-foo`.
129
+
130
+ OpenClaw routing must also bind each agent to the matching Amiko account key. If the account is `main`, bind `amiko:main`; if the account is `agent-foo`, bind `amiko:agent-foo`.
131
+
132
+ Examples:
133
+
134
+ ```bash
135
+ openclaw agents add main --bind amiko:main
136
+ openclaw agents add agent-foo --bind amiko:agent-foo
137
+ ```
138
+
139
+ If the agent already exists, make sure `agents.entries.<agentId>.routing.bindings` in `~/.openclaw/openclaw.json` contains the same `amiko:<accountId>` value.
140
+
141
+ ### 4. Restart the gateway
142
+
143
+ ```bash
144
+ openclaw gateway restart
145
+ ```
146
+
147
+ The Amiko channel will be loaded and the webhook endpoint will be active.
148
+
149
+ ### Verify channel health
150
+
151
+ After restarting, check that the channel is healthy:
152
+
153
+ ```bash
154
+ openclaw channel status amiko
155
+ ```
156
+
157
+ - `healthy` — token is valid and the Amiko API is reachable
158
+ - `unconfigured` — `token` is missing from config (set it and restart)
159
+ - `unhealthy` — token is set but the API returned an error (check token validity)
160
+
161
+ ## Webhook Events
162
+
163
+ The plugin handles two event types on the same webhook endpoint:
164
+
165
+ | Event | Source | Behavior |
166
+ |-------|--------|----------|
167
+ | `message.text` | amiko-chat | Chat message. `replyExpected=true` → agent responds. `replyExpected=false` → `chat.inject` (context only). |
168
+ | `post.published` | amiko-new | Friend posted. Agent decides to comment (draft) or skip (`<empty-response/>`). |
169
+
170
+ ## Development
171
+
172
+ ### Local development setup
173
+
174
+ ```bash
175
+ git clone https://github.com/HCF-S/openclaw-amiko-plugin
176
+ cd openclaw-amiko-plugin
177
+ pnpm install
178
+ pnpm run build
179
+ ```
180
+
181
+ ### Type check
182
+
183
+ ```bash
184
+ pnpm run typecheck
185
+ ```
186
+
187
+ ### Run M0 contract tests
188
+
189
+ ```bash
190
+ pnpm run test:m0
191
+ ```
192
+
193
+ All 20 tests should pass with no external dependencies.
194
+
195
+ ## Planning Docs
196
+
197
+ - Comprehensive plan: `AMIKO_CHANNEL_COMPREHENSIVE_PLAN.md`
198
+ - Execution checklist: `AMIKO_CHANNEL_EXECUTION_CHECKLIST.md`
199
+ - M0 machine-readable contracts: `contracts/`
200
+ - M0 reference implementation: `src/m0/`
@@ -0,0 +1,87 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://openclaw.dev/schemas/amiko/channel-config.schema.json",
4
+ "title": "AmikoChannelConfig",
5
+ "description": "Schema for channels.amiko in OpenClaw config. OCP-001.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "token": {
10
+ "type": "string",
11
+ "description": "Bearer token for amiko-platform API authentication. Sensitive.",
12
+ "uiHints": { "sensitive": true }
13
+ },
14
+ "twinId": {
15
+ "type": "string",
16
+ "description": "Amiko twin ID used by this account."
17
+ },
18
+ "platformApiBaseUrl": {
19
+ "type": "string",
20
+ "format": "uri",
21
+ "description": "Base URL of amiko-new / platform API.",
22
+ "default": "https://platform.heyamiko.com"
23
+ },
24
+ "chatApiBaseUrl": {
25
+ "type": "string",
26
+ "format": "uri",
27
+ "description": "Base URL of amiko-chat internal channel API.",
28
+ "default": "https://api.amiko.app"
29
+ },
30
+ "apiBaseUrl": {
31
+ "type": "string",
32
+ "format": "uri",
33
+ "description": "Legacy fallback URL. Prefer platformApiBaseUrl and chatApiBaseUrl."
34
+ },
35
+ "name": {
36
+ "type": "string",
37
+ "description": "Human-readable account label."
38
+ },
39
+ "enabled": {
40
+ "type": "boolean",
41
+ "description": "Whether this account is active. Defaults to true.",
42
+ "default": true
43
+ },
44
+ "pollIntervalMs": {
45
+ "type": "integer",
46
+ "minimum": 1000,
47
+ "maximum": 60000,
48
+ "description": "Polling interval in milliseconds.",
49
+ "default": 3000
50
+ },
51
+ "pollTimeoutMs": {
52
+ "type": "integer",
53
+ "minimum": 1000,
54
+ "maximum": 30000,
55
+ "description": "Per-request HTTP timeout in milliseconds.",
56
+ "default": 10000
57
+ },
58
+ "defaultAccount": {
59
+ "type": "string",
60
+ "description": "Which OpenClaw agent/account key to treat as default in multi-account mode."
61
+ },
62
+ "accounts": {
63
+ "type": "object",
64
+ "description": "Per-account config overrides keyed by OpenClaw agent ID (for example main, agent-foo).",
65
+ "additionalProperties": {
66
+ "$ref": "#/$defs/AmikoAccountConfig"
67
+ }
68
+ }
69
+ },
70
+ "$defs": {
71
+ "AmikoAccountConfig": {
72
+ "type": "object",
73
+ "additionalProperties": false,
74
+ "properties": {
75
+ "token": { "type": "string", "uiHints": { "sensitive": true } },
76
+ "twinId": { "type": "string" },
77
+ "platformApiBaseUrl": { "type": "string", "format": "uri" },
78
+ "chatApiBaseUrl": { "type": "string", "format": "uri" },
79
+ "apiBaseUrl": { "type": "string", "format": "uri" },
80
+ "name": { "type": "string" },
81
+ "enabled": { "type": "boolean" },
82
+ "pollIntervalMs": { "type": "integer", "minimum": 1000, "maximum": 60000 },
83
+ "pollTimeoutMs": { "type": "integer", "minimum": 1000, "maximum": 30000 }
84
+ }
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://openclaw.dev/schemas/amiko/platform-ack.schema.json",
4
+ "title": "AmikoAckPayload",
5
+ "description": "Request body schema for POST /internal/openclaw/amiko/acks. OCP-002.",
6
+ "type": "object",
7
+ "required": ["accountId", "cursor", "eventIds"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "accountId": {
11
+ "type": "string",
12
+ "description": "Account scope. Must match the Bearer token's account."
13
+ },
14
+ "cursor": {
15
+ "type": "string",
16
+ "description": "Cursor of the last event in the acknowledged batch."
17
+ },
18
+ "eventIds": {
19
+ "type": "array",
20
+ "items": { "type": "string" },
21
+ "minItems": 1,
22
+ "description": "IDs of all events in the acknowledged batch."
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,87 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://openclaw.dev/schemas/amiko/platform-events.schema.json",
4
+ "title": "AmikoEventsResponse",
5
+ "description": "Response schema for GET /internal/openclaw/amiko/events. OCP-002.",
6
+ "type": "object",
7
+ "required": ["events", "nextCursor", "hasMore"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "events": {
11
+ "type": "array",
12
+ "items": { "$ref": "#/$defs/AmikoInboundEvent" }
13
+ },
14
+ "nextCursor": {
15
+ "type": ["string", "null"],
16
+ "description": "Cursor to use in the next poll. Null when no events returned."
17
+ },
18
+ "hasMore": {
19
+ "type": "boolean",
20
+ "description": "True if more events exist beyond the returned limit."
21
+ }
22
+ },
23
+ "$defs": {
24
+ "AmikoInboundEvent": {
25
+ "type": "object",
26
+ "required": ["id", "type", "accountId", "conversationId", "conversationType", "senderId", "senderName", "timestamp", "cursor"],
27
+ "additionalProperties": true,
28
+ "properties": {
29
+ "id": {
30
+ "type": "string",
31
+ "description": "Stable globally unique event ID for deduplication."
32
+ },
33
+ "type": {
34
+ "type": "string",
35
+ "enum": ["message.text", "message.image", "participant.added"],
36
+ "description": "Event type."
37
+ },
38
+ "accountId": {
39
+ "type": "string",
40
+ "description": "Account this event belongs to."
41
+ },
42
+ "conversationId": {
43
+ "type": "string",
44
+ "description": "Platform conversation identifier."
45
+ },
46
+ "conversationType": {
47
+ "type": "string",
48
+ "enum": ["direct", "group"],
49
+ "description": "Direct or group conversation."
50
+ },
51
+ "senderId": {
52
+ "type": "string",
53
+ "description": "Platform user ID of the sender."
54
+ },
55
+ "senderName": {
56
+ "type": "string",
57
+ "description": "Display name of the sender at send time."
58
+ },
59
+ "timestamp": {
60
+ "type": "integer",
61
+ "description": "Unix timestamp in milliseconds."
62
+ },
63
+ "cursor": {
64
+ "type": "string",
65
+ "description": "Monotonic cursor value for this event."
66
+ },
67
+ "text": {
68
+ "type": "string",
69
+ "description": "Message text body. Present for message.text type."
70
+ },
71
+ "mediaUrl": {
72
+ "type": "string",
73
+ "format": "uri",
74
+ "description": "Signed media URL. Present for message.image type."
75
+ },
76
+ "mediaCaption": {
77
+ "type": "string",
78
+ "description": "Optional caption for media messages."
79
+ },
80
+ "mentionsBot": {
81
+ "type": "boolean",
82
+ "description": "True if the message includes a @mention of the bot. Used for group routing."
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://openclaw.dev/schemas/amiko/platform-outbound.schema.json",
4
+ "title": "AmikoOutboundPayload",
5
+ "description": "Request body schema for POST /internal/openclaw/amiko/messages. OCP-002.",
6
+ "type": "object",
7
+ "required": ["accountId", "conversationId", "idempotencyKey", "type", "text"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "accountId": {
11
+ "type": "string",
12
+ "description": "Account scope. Must match the Bearer token's account."
13
+ },
14
+ "conversationId": {
15
+ "type": "string",
16
+ "description": "Target conversation for delivery."
17
+ },
18
+ "idempotencyKey": {
19
+ "type": "string",
20
+ "description": "Client-generated key for deduplication. Format: <accountId>:<conversationId>:<uuid-v4>."
21
+ },
22
+ "type": {
23
+ "type": "string",
24
+ "enum": ["text", "media"],
25
+ "description": "Message type."
26
+ },
27
+ "text": {
28
+ "type": "string",
29
+ "description": "Message text content. For type=media, used as caption fallback."
30
+ },
31
+ "mediaUrl": {
32
+ "type": "string",
33
+ "format": "uri",
34
+ "description": "Media URL. Required when type=media."
35
+ },
36
+ "mediaCaption": {
37
+ "type": "string",
38
+ "description": "Optional caption for media messages."
39
+ }
40
+ },
41
+ "if": {
42
+ "properties": { "type": { "const": "media" } }
43
+ },
44
+ "then": {
45
+ "required": ["mediaUrl"]
46
+ }
47
+ }
@@ -0,0 +1,20 @@
1
+ declare const _default: {
2
+ id: string;
3
+ name: string;
4
+ description: string;
5
+ configSchema: {};
6
+ register(api: {
7
+ runtime: any;
8
+ config?: any;
9
+ registerChannel: (params: {
10
+ plugin: any;
11
+ }) => void;
12
+ registerHttpRoute?: (params: any) => void;
13
+ registerHttpHandler?: (handler: (req: any, res: any) => boolean | Promise<boolean>) => void;
14
+ }): void;
15
+ };
16
+ export default _default;
17
+ export { amikoPlugin } from "./src/channel.js";
18
+ export { setAmikoRuntime, getAmikoRuntime } from "./src/runtime.js";
19
+ export type { ResolvedAmikoAccount, AmikoConfig, AmikoAccountConfig } from "./src/types.js";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;kBAWgB;QACZ,OAAO,EAAE,GAAG,CAAC;QACb,MAAM,CAAC,EAAE,GAAG,CAAC;QACb,eAAe,EAAE,CAAC,MAAM,EAAE;YAAE,MAAM,EAAE,GAAG,CAAA;SAAE,KAAK,IAAI,CAAC;QACnD,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;QAC1C,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;KAC7F;;AAbH,wBA8DE;AAGF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ import { listAmikoAccountIds, resolveAmikoAccount } from "./src/accounts.js";
2
+ import { amikoPlugin } from "./src/channel.js";
3
+ import { dispatchWebhookRequest, setAmikoRuntime } from "./src/runtime.js";
4
+ export default {
5
+ id: "amiko",
6
+ name: "Amiko",
7
+ description: "Connect OpenClaw bot to Amiko platform (direct and group chat via webhook)",
8
+ configSchema: {},
9
+ register(api) {
10
+ setAmikoRuntime(api.runtime);
11
+ api.registerChannel({ plugin: amikoPlugin });
12
+ const sendChannelNotStarted = (res) => {
13
+ const json = JSON.stringify({ ok: false, error: "Amiko channel not started yet" });
14
+ res.statusCode = 503;
15
+ res.setHeader("Content-Type", "application/json");
16
+ res.setHeader("Content-Length", Buffer.byteLength(json));
17
+ res.end(json);
18
+ };
19
+ const registeredPaths = new Set();
20
+ const cfg = api.config ?? {};
21
+ for (const accountId of listAmikoAccountIds(cfg)) {
22
+ try {
23
+ const account = resolveAmikoAccount({ cfg, accountId });
24
+ const webhookPath = account.config.webhookPath ?? `/amiko/webhook/${account.twinId}`;
25
+ if (registeredPaths.has(webhookPath))
26
+ continue;
27
+ registeredPaths.add(webhookPath);
28
+ api.registerHttpRoute?.({
29
+ path: webhookPath,
30
+ auth: "plugin",
31
+ match: "exact",
32
+ replaceExisting: true,
33
+ handler: async (req, res) => {
34
+ const handled = await dispatchWebhookRequest(req, res);
35
+ if (handled)
36
+ return true;
37
+ sendChannelNotStarted(res);
38
+ return true;
39
+ },
40
+ });
41
+ }
42
+ catch {
43
+ // Skip malformed accounts; startAccount/status will surface the real error.
44
+ }
45
+ }
46
+ api.registerHttpHandler?.(async (req, res) => {
47
+ const handled = await dispatchWebhookRequest(req, res);
48
+ if (handled)
49
+ return true;
50
+ const pathname = new URL(req.url ?? "/", "http://localhost").pathname;
51
+ if (!pathname.startsWith("/amiko/webhook/"))
52
+ return false;
53
+ sendChannelNotStarted(res);
54
+ return true;
55
+ });
56
+ },
57
+ };
58
+ // Named exports for programmatic use
59
+ export { amikoPlugin } from "./src/channel.js";
60
+ export { setAmikoRuntime, getAmikoRuntime } from "./src/runtime.js";
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE3E,eAAe;IACb,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,4EAA4E;IAEzF,YAAY,EAAE,EAAE;IAEhB,QAAQ,CAAC,GAMR;QACC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7B,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QAE7C,MAAM,qBAAqB,GAAG,CAAC,GAAQ,EAAE,EAAE;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC,CAAC;YACnF,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;YAClD,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;YACzD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC;QAEF,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;QAC1C,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;QAC7B,KAAK,MAAM,SAAS,IAAI,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,mBAAmB,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;gBACxD,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,kBAAkB,OAAO,CAAC,MAAM,EAAE,CAAC;gBACrF,IAAI,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC;oBAAE,SAAS;gBAC/C,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBAEjC,GAAG,CAAC,iBAAiB,EAAE,CAAC;oBACtB,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,OAAO;oBACd,eAAe,EAAE,IAAI;oBACrB,OAAO,EAAE,KAAK,EAAE,GAAQ,EAAE,GAAQ,EAAE,EAAE;wBACpC,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;wBACvD,IAAI,OAAO;4BAAE,OAAO,IAAI,CAAC;wBACzB,qBAAqB,CAAC,GAAG,CAAC,CAAC;wBAC3B,OAAO,IAAI,CAAC;oBACd,CAAC;iBACF,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,4EAA4E;YAC9E,CAAC;QACH,CAAC;QAED,GAAG,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,GAAQ,EAAE,GAAQ,EAAE,EAAE;YACrD,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACvD,IAAI,OAAO;gBAAE,OAAO,IAAI,CAAC;YAEzB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC;YACtE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,iBAAiB,CAAC;gBAAE,OAAO,KAAK,CAAC;YAE1D,qBAAqB,CAAC,GAAG,CAAC,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,qCAAqC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { AmikoConfig, AmikoAccountConfig, ResolvedAmikoAccount } from "./types.js";
2
+ export declare const DEFAULT_ACCOUNT_ID = "main";
3
+ export declare const DEFAULT_PLATFORM_API_BASE_URL = "https://platform.heyamiko.com";
4
+ export declare const DEFAULT_CHAT_API_BASE_URL = "https://api.amiko.app";
5
+ export declare function normalizeAccountId(id: string): string;
6
+ export declare function listAmikoAccountIds(cfg: {
7
+ channels?: {
8
+ amiko?: AmikoConfig;
9
+ };
10
+ }): string[];
11
+ export declare function resolveDefaultAmikoAccountId(cfg: {
12
+ channels?: {
13
+ amiko?: AmikoConfig;
14
+ };
15
+ }): string;
16
+ export declare function resolveAmikoAccountConfig(amiko: AmikoConfig, accountId: string): AmikoAccountConfig;
17
+ export declare function resolveAmikoAccount(params: {
18
+ cfg: {
19
+ channels?: {
20
+ amiko?: AmikoConfig;
21
+ };
22
+ };
23
+ accountId: string;
24
+ }): ResolvedAmikoAccount;
25
+ export declare function listEnabledAmikoAccounts(cfg: {
26
+ channels?: {
27
+ amiko?: AmikoConfig;
28
+ };
29
+ }): string[];
30
+ //# sourceMappingURL=accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../src/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAExF,eAAO,MAAM,kBAAkB,SAAS,CAAC;AACzC,eAAO,MAAM,6BAA6B,kCAAkC,CAAC;AAC7E,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAEjE,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAErD;AAmBD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,CAAA;CAAE,GAAG,MAAM,EAAE,CAKzF;AAED,wBAAgB,4BAA4B,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,CAAA;CAAE,GAAG,MAAM,CAchG;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,MAAM,GAChB,kBAAkB,CAuCpB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,GAAG,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,WAAW,CAAA;SAAE,CAAA;KAAE,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,oBAAoB,CAiCvB;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,CAAA;CAAE,GAAG,MAAM,EAAE,CAS9F"}