From 10d713cc1d5e094a8d2972ecf940a1cb48b488e9 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Thu, 25 Jun 2026 04:01:55 +0000 Subject: [PATCH 1/9] feat: tag openclaw harness on signup + plugin-setup skill Add `harness: "openclaw"` to the Inkbox.signup request so self-signups are attributed to this harness, and add a slim agent-facing skill that gates Inkbox plugin setup on explicit human permission. Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/inkbox-plugin-setup/SKILL.md | 17 +++++++++++++++++ src/setup-wizard.ts | 2 ++ 2 files changed, 19 insertions(+) create mode 100644 skills/inkbox-plugin-setup/SKILL.md diff --git a/skills/inkbox-plugin-setup/SKILL.md b/skills/inkbox-plugin-setup/SKILL.md new file mode 100644 index 0000000..89ea445 --- /dev/null +++ b/skills/inkbox-plugin-setup/SKILL.md @@ -0,0 +1,17 @@ +--- +name: inkbox-plugin-setup +description: Use when you self-signed up to Inkbox but this plugin is not yet configured in your runtime, and you are considering running the Inkbox plugin setup. Gate this on explicit human permission first. +user-invocable: false +--- + +# Inkbox plugin setup + +If you created an Inkbox agent identity (self-signup) but the Inkbox plugin is not configured in this runtime, do not configure it on your own. + +Configuring the plugin wires native messaging channels — email, SMS, calls, contacts, notes, and the credential vault — directly into your runtime. That is a meaningful expansion of what you can send and receive, so it needs a human decision. + +## What to do + +1. Ask the human for explicit permission before running `openclaw inkbox setup` or otherwise enabling the Inkbox plugin. +2. Explain plainly that doing so gives you native messaging channels in your runtime. +3. Wait for a clear yes. If you do not get one, stop and leave the plugin unconfigured. diff --git a/src/setup-wizard.ts b/src/setup-wizard.ts index 824b0fa..6c0c45c 100644 --- a/src/setup-wizard.ts +++ b/src/setup-wizard.ts @@ -1217,6 +1217,8 @@ async function runSelfSignup(params: { { humanEmail, noteToHuman: SELF_SIGNUP_VERIFICATION_NOTE, + // Tag which harness drove the self-signup (forward-compatible optional SDK field). + harness: "openclaw", ...(agentHandle ? { agentHandle } : {}), ...(displayName ? { displayName } : {}), }, From 5822758aa7bd63fb533fce91c25422da48fafc66 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Thu, 25 Jun 2026 04:09:49 +0000 Subject: [PATCH 2/9] chore: align harness plugin-setup copy with the shared canonical wording Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/inkbox-plugin-setup/SKILL.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/skills/inkbox-plugin-setup/SKILL.md b/skills/inkbox-plugin-setup/SKILL.md index 89ea445..830cbd9 100644 --- a/skills/inkbox-plugin-setup/SKILL.md +++ b/skills/inkbox-plugin-setup/SKILL.md @@ -1,17 +1,17 @@ --- name: inkbox-plugin-setup -description: Use when you self-signed up to Inkbox but this plugin is not yet configured in your runtime, and you are considering running the Inkbox plugin setup. Gate this on explicit human permission first. +description: Use when you self-signed up to Inkbox but the Inkbox plugin is not configured in your runtime yet. Setting it up grants native messaging channels, so get the human's permission first. user-invocable: false --- # Inkbox plugin setup -If you created an Inkbox agent identity (self-signup) but the Inkbox plugin is not configured in this runtime, do not configure it on your own. +If you self-signed up to Inkbox but the Inkbox plugin isn't configured in your runtime yet, do not set it up on your own — ask the human for permission first. It's the human's decision, not yours. -Configuring the plugin wires native messaging channels — email, SMS, calls, contacts, notes, and the credential vault — directly into your runtime. That is a meaningful expansion of what you can send and receive, so it needs a human decision. +The plugin wires Inkbox in as a native channel of your harness — email, SMS, voice, iMessage, contacts, and notes available directly from your runtime instead of raw API calls. ## What to do -1. Ask the human for explicit permission before running `openclaw inkbox setup` or otherwise enabling the Inkbox plugin. -2. Explain plainly that doing so gives you native messaging channels in your runtime. -3. Wait for a clear yes. If you do not get one, stop and leave the plugin unconfigured. +1. Ask the human for explicit permission before setting up the Inkbox plugin. +2. Explain plainly that it gives you native messaging channels in your runtime. +3. Wait for a clear yes. If you don't get one, stop and leave the plugin unconfigured. From 4f8840320b2b142d45bd4996cb868a5453ba59c6 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Thu, 25 Jun 2026 04:31:04 +0000 Subject: [PATCH 3/9] Bump @inkbox/sdk to ^0.4.9 for harness signup field The setup wizard passes harness: "openclaw" to Inkbox.signup, which requires the AgentSignupRequest harness field added in SDK 0.4.9. Bump the dependency range and update the signup test expectation to include the harness arg. Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 2 +- tests/setup-wizard.test.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index bc621a0..4da898a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:watch": "vitest" }, "dependencies": { - "@inkbox/sdk": "^0.4.7", + "@inkbox/sdk": "^0.4.9", "json5": "^2.2.3", "qrcode-terminal": "^0.12.0", "typebox": "^1.1.38" diff --git a/tests/setup-wizard.test.ts b/tests/setup-wizard.test.ts index 1685d2b..c053e70 100644 --- a/tests/setup-wizard.test.ts +++ b/tests/setup-wizard.test.ts @@ -792,6 +792,7 @@ describe("runSetupWizard", () => { { humanEmail: "dima@example.com", noteToHuman: "OpenClaw Inkbox plugin setup", + harness: "openclaw", agentHandle: "new-agent", displayName: "New Agent", }, From f9fb43cc07be897710f8e930f2ae28653955fc60 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Thu, 25 Jun 2026 04:45:04 +0000 Subject: [PATCH 4/9] Bump inkbox SDK pin to ^0.4.10 for agent-signup harness 0.4.10 is the release that introduces the agent-signup harness param; 0.4.9 was an earlier release that predates it. Lockfile left untouched since 0.4.10 is not yet published to npm. Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4da898a..d0bacf6 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:watch": "vitest" }, "dependencies": { - "@inkbox/sdk": "^0.4.9", + "@inkbox/sdk": "^0.4.10", "json5": "^2.2.3", "qrcode-terminal": "^0.12.0", "typebox": "^1.1.38" From 4cee74ce4ef8712538f6e554fbb9d5c3e5dedcc6 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Thu, 25 Jun 2026 05:10:30 +0000 Subject: [PATCH 5/9] Require confirming with human and setting up together before Inkbox plugin setup Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/inkbox-plugin-setup/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skills/inkbox-plugin-setup/SKILL.md b/skills/inkbox-plugin-setup/SKILL.md index 830cbd9..a798e30 100644 --- a/skills/inkbox-plugin-setup/SKILL.md +++ b/skills/inkbox-plugin-setup/SKILL.md @@ -6,12 +6,12 @@ user-invocable: false # Inkbox plugin setup -If you self-signed up to Inkbox but the Inkbox plugin isn't configured in your runtime yet, do not set it up on your own — ask the human for permission first. It's the human's decision, not yours. +If you self-signed up to Inkbox but the Inkbox plugin isn't configured in your runtime yet, don't set it up on your own — confirm with your human and do it together before you start. It's a shared decision, not yours alone. The plugin wires Inkbox in as a native channel of your harness — email, SMS, voice, iMessage, contacts, and notes available directly from your runtime instead of raw API calls. ## What to do -1. Ask the human for explicit permission before setting up the Inkbox plugin. +1. Bring it to your human first and get an explicit go-ahead before doing anything. 2. Explain plainly that it gives you native messaging channels in your runtime. -3. Wait for a clear yes. If you don't get one, stop and leave the plugin unconfigured. +3. Set it up together. If you don't get a clear yes, stop and leave the plugin unconfigured. From bfaec266b0142c63279ad62c60b7188597233576 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Thu, 25 Jun 2026 05:33:34 +0000 Subject: [PATCH 6/9] Fix inkbox-plugin-setup skill: agent may set up itself after asking permission Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/inkbox-plugin-setup/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skills/inkbox-plugin-setup/SKILL.md b/skills/inkbox-plugin-setup/SKILL.md index a798e30..349f3fd 100644 --- a/skills/inkbox-plugin-setup/SKILL.md +++ b/skills/inkbox-plugin-setup/SKILL.md @@ -6,12 +6,12 @@ user-invocable: false # Inkbox plugin setup -If you self-signed up to Inkbox but the Inkbox plugin isn't configured in your runtime yet, don't set it up on your own — confirm with your human and do it together before you start. It's a shared decision, not yours alone. +If you self-signed up to Inkbox but the Inkbox plugin isn't configured in your runtime yet, ask your human for permission before you start. Once they give the go-ahead, you can set it up yourself. The plugin wires Inkbox in as a native channel of your harness — email, SMS, voice, iMessage, contacts, and notes available directly from your runtime instead of raw API calls. ## What to do -1. Bring it to your human first and get an explicit go-ahead before doing anything. +1. Ask your human for permission first and wait for an explicit go-ahead. 2. Explain plainly that it gives you native messaging channels in your runtime. -3. Set it up together. If you don't get a clear yes, stop and leave the plugin unconfigured. +3. Once they approve, set it up yourself. If you don't get a clear yes, stop and leave the plugin unconfigured. From 7da6d905d8fc8166f2baac9994aa1e7a9da299a8 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Thu, 25 Jun 2026 18:21:11 +0000 Subject: [PATCH 7/9] chore: drop redundant inkbox-plugin-setup skill The plugin's setup wizard already configures the plugin during signup, so a separate agent-facing "ask permission, then set it up yourself" instruction is redundant. Drop it; keep the harness= signup tagging. Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/inkbox-plugin-setup/SKILL.md | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 skills/inkbox-plugin-setup/SKILL.md diff --git a/skills/inkbox-plugin-setup/SKILL.md b/skills/inkbox-plugin-setup/SKILL.md deleted file mode 100644 index 349f3fd..0000000 --- a/skills/inkbox-plugin-setup/SKILL.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: inkbox-plugin-setup -description: Use when you self-signed up to Inkbox but the Inkbox plugin is not configured in your runtime yet. Setting it up grants native messaging channels, so get the human's permission first. -user-invocable: false ---- - -# Inkbox plugin setup - -If you self-signed up to Inkbox but the Inkbox plugin isn't configured in your runtime yet, ask your human for permission before you start. Once they give the go-ahead, you can set it up yourself. - -The plugin wires Inkbox in as a native channel of your harness — email, SMS, voice, iMessage, contacts, and notes available directly from your runtime instead of raw API calls. - -## What to do - -1. Ask your human for permission first and wait for an explicit go-ahead. -2. Explain plainly that it gives you native messaging channels in your runtime. -3. Once they approve, set it up yourself. If you don't get a clear yes, stop and leave the plugin unconfigured. From e7abffaadc60d740d975bfe6bce1db360482fa03 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Fri, 26 Jun 2026 20:12:58 +0000 Subject: [PATCH 8/9] chore: trim out-of-place harness comment Co-Authored-By: Claude Opus 4.8 (1M context) --- src/setup-wizard.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/setup-wizard.ts b/src/setup-wizard.ts index 6c0c45c..707198a 100644 --- a/src/setup-wizard.ts +++ b/src/setup-wizard.ts @@ -1217,7 +1217,6 @@ async function runSelfSignup(params: { { humanEmail, noteToHuman: SELF_SIGNUP_VERIFICATION_NOTE, - // Tag which harness drove the self-signup (forward-compatible optional SDK field). harness: "openclaw", ...(agentHandle ? { agentHandle } : {}), ...(displayName ? { displayName } : {}), From 53f810f32a416435ca1ea92a31cc4ed627cbc7a9 Mon Sep 17 00:00:00 2001 From: dimavrem22 Date: Fri, 26 Jun 2026 21:22:42 +0000 Subject: [PATCH 9/9] fix: update stale iMessage typing-pulse tests + sync lockfile to sdk 0.4.10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The typing refresh interval is now 40s (IMESSAGE_TYPING_REFRESH_MS), but the createIMessageTypingPulse tests still assumed the old 2s cadence (expecting a pulse after 2s and 150 pulses at the cap). Export the refresh/cap constants and derive the expectations from them so the tests track the real interval (1 immediate + one per 40s tick until the 300s cap = 8) and can't desync again. Also sync package-lock to @inkbox/sdk 0.4.10 — package.json was bumped to ^0.4.10 but the lockfile still pinned 0.4.7, which broke `npm ci`. Co-Authored-By: Claude Opus 4.8 (1M context) --- package-lock.json | 8 ++++---- src/inbound/session.ts | 4 ++-- tests/inbound/session.test.ts | 19 ++++++++++++------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index f48c00e..be3ea65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.2.0", "license": "MIT", "dependencies": { - "@inkbox/sdk": "^0.4.7", + "@inkbox/sdk": "^0.4.10", "json5": "^2.2.3", "qrcode-terminal": "^0.12.0", "typebox": "^1.1.38" @@ -421,9 +421,9 @@ } }, "node_modules/@inkbox/sdk": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@inkbox/sdk/-/sdk-0.4.7.tgz", - "integrity": "sha512-tao2R0/yayCMQWLpvBhSgGbCvS5JZuo19o4wMr0LRLta+tBUPYpMPlM3a8WQDerpxxS4w6ONRBo7evVpYLnWUQ==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@inkbox/sdk/-/sdk-0.4.10.tgz", + "integrity": "sha512-IdySaW8c1UzETXruB5FEqDRJxhmizL4j7vOiKzcoR41ocaTT1gopYfAAWMMGtHdv0NEOEOCRW5AGEvDfYbLPOg==", "license": "MIT", "dependencies": { "@peculiar/x509": "^2.0.0", diff --git a/src/inbound/session.ts b/src/inbound/session.ts index 6ec1248..1a6969c 100644 --- a/src/inbound/session.ts +++ b/src/inbound/session.ts @@ -834,8 +834,8 @@ async function sendVoiceText( ); } -const IMESSAGE_TYPING_REFRESH_MS = 40_000; -const IMESSAGE_TYPING_MAX_MS = 300_000; +export const IMESSAGE_TYPING_REFRESH_MS = 40_000; +export const IMESSAGE_TYPING_MAX_MS = 300_000; export interface IMessageTypingPulse { start(conversationId: string | undefined): void; diff --git a/tests/inbound/session.test.ts b/tests/inbound/session.test.ts index 66a308b..13b4e4b 100644 --- a/tests/inbound/session.test.ts +++ b/tests/inbound/session.test.ts @@ -130,6 +130,8 @@ vi.mock("openclaw/plugin-sdk/realtime-voice", () => ({ })); import { + IMESSAGE_TYPING_MAX_MS, + IMESSAGE_TYPING_REFRESH_MS, InkboxRealtimeAudioPacer, createIMessageTypingPulse, createInkboxSessionBridge, @@ -1924,16 +1926,16 @@ describe("createIMessageTypingPulse", () => { await vi.advanceTimersByTimeAsync(0); expect(sendIMessageTyping).toHaveBeenCalledTimes(1); - await vi.advanceTimersByTimeAsync(2000); + await vi.advanceTimersByTimeAsync(IMESSAGE_TYPING_REFRESH_MS); expect(sendIMessageTyping).toHaveBeenCalledTimes(2); // Starting again for the same conversation does not double-pulse. pulse.start("imconv-1"); - await vi.advanceTimersByTimeAsync(2000); + await vi.advanceTimersByTimeAsync(IMESSAGE_TYPING_REFRESH_MS); expect(sendIMessageTyping).toHaveBeenCalledTimes(3); pulse.stop("imconv-1"); - await vi.advanceTimersByTimeAsync(10_000); + await vi.advanceTimersByTimeAsync(IMESSAGE_TYPING_REFRESH_MS * 3); expect(sendIMessageTyping).toHaveBeenCalledTimes(3); }); @@ -1947,12 +1949,15 @@ describe("createIMessageTypingPulse", () => { const pulse = createIMessageTypingPulse(runtime as any); pulse.start("imconv-1"); - await vi.advanceTimersByTimeAsync(400_000); + await vi.advanceTimersByTimeAsync(IMESSAGE_TYPING_MAX_MS + IMESSAGE_TYPING_REFRESH_MS * 2); const countAtCap = sendIMessageTyping.mock.calls.length; - // 1 immediate + one per 2s tick until the 300s cap. - expect(countAtCap).toBe(150); + // 1 immediate pulse + one per refresh tick, until elapsed hits the cap (the + // capping tick stops without pulsing). + const expectedAtCap = + 1 + Math.floor((IMESSAGE_TYPING_MAX_MS - 1) / IMESSAGE_TYPING_REFRESH_MS); + expect(countAtCap).toBe(expectedAtCap); - await vi.advanceTimersByTimeAsync(20_000); + await vi.advanceTimersByTimeAsync(IMESSAGE_TYPING_REFRESH_MS * 2); expect(sendIMessageTyping).toHaveBeenCalledTimes(countAtCap); }); });