Repository navigation
feat(kiro-extension): self-contained floating Doraemon companion - #34
Merged
Merged
Conversation
Ships Doraemon as a Kiro extension with a bundled 792 KB native companion, so one install gives a transparent always-on-top desktop mascot with nothing else to download. Companion (kiro-extension/companion, Rust + tao/wry) - Borrows the OS webview instead of bundling Chromium: 792 KB vs Electron's 274 MB - Small transparent window that Rust repositions as the mascot walks, rather than a fullscreen click-through overlay. Removes the need for mouse-event forwarding, which Electron only supports on macOS and Windows. - Serves sprites over a custom dora:// protocol from the extension's media dir - Lifetime tied to the IDE's pid, so a hard kill leaves no orphaned window - macOS transparency needs wry's `transparent` feature and no window shadow Extension - Three surfaces sharing one engine: bundled companion, detached editor window, sidebar. Default `auto` resolves companion then window, so the mascot appears outside the IDE on first install with no configuration. - 33 activity signals from first-party editor APIs - Kiro agent state via hooks writing .kiro/doraemon/agent-state.json, installed automatically with platform-correct shell commands. Kiro only loads hooks/**/*.kiro.hook, so .json hooks are silently ignored. - "Awaiting approval" is inferred from the agent going quiet; Kiro exposes no such trigger and a slow tool is indistinguishable from outside - Clicking the bubble raises the IDE, which an extension cannot do for itself - Reuses shimeji.ts, sprites.ts and the thought pools by import, not by copy Desktop app - New env-gated DORAEMON_EXTENSION_MODE renders mascot only, starting no OpenClaw, gateway, memory, experience, voice or MCP subsystems. Default behaviour is unchanged. Drag regression fix - update() checked the animation lock before applyPhysics, so a dropped mascot never fell. Drag now emits lean states, carries throw momentum, and releases the lock. Covered by 24 engine tests. Also - CI matrix builds and packages darwin-arm64/x64, win32-x64, linux-x64 and publishes per-target to Open VSX on a kiro-extension-v* tag - electron-builder mac packaging was failing on an empty build/icons directory
All four platform builds failed on typecheck with: error TS2688: Cannot find type definition file for 'node' tsconfig sets `types: ["node", "vscode"]` but only @types/vscode was declared. Locally tsc walks up to the parent repo's node_modules and finds @types/node, so it passed here and failed everywhere else. CI installs kiro-extension only. - Declare @types/node 20.19.30, matching the version the parent already resolved - Add scripts/verify-deps.mjs, run as part of typecheck: asserts every tsconfig `types` entry has a matching @types package, and every bare import in src/ and scripts/ is declared here rather than hoisted from the parent Verified by running the full CI pipeline against a fresh clone with no parent node_modules present: npm ci, typecheck, build, cargo companion, verify-sprites, smoke, package all pass. The guard was also confirmed to fail with exit 1 when @types/node is removed again.
An audit of the animation table against reactions.ts found 11 of the 40 generated
sprite sets had nothing that could ever trigger them. They shipped in the VSIX
and never played, which is invisible by definition.
Six action sets had no route at all:
- action_research -> reviewing code (12+ line selection), replacing coding_thinking
- action_gadget_surprise -> a file being created
- action_eating / action_hungry -> break reminder, picked at random
- action_take_copter -> git push and deploy commands, recognised in describeCommand
- action_explain_gadget -> agent finished, presenting the result
- action_walk -> window blurred, he wanders off
- action_angry -> a terminal command exiting non-zero
- action_chat_answer -> a task passing, reporting back
Five emotions were never set, so their sets were only reachable through engine
idle aliases rather than any editor event:
- confusion -> 1-2 errors, turning the error reaction into a ladder
(1-2 confused, 3-4 concerned, 5+ frustrated)
- hope -> task started, before the outcome is known
- awe -> the whole project going error-free
- longing -> window blurred
- gratitude -> agent finished
Adds scripts/verify-coverage.mjs, run as part of build: fails if any generated
set has no route to the screen. Counterpart to verify-sprites, which checks the
other direction that every referenced frame exists on disk.
Behaviour changes, all deliberate and covered by updated assertions:
- window blur reads as longing/action_walk rather than calm/action_rest
- agent completion reads as gratitude/action_explain_gadget rather than
pride/action_chat_answer
- 1-2 errors read as confusion rather than concern
- task start reads as hope, project-clean as awe
Four problems from the first CI run.
win32-x64 failed: release.mjs shells out with spawnSync('npx', ...), but npx is
npx.cmd on Windows and spawnSync cannot exec a .cmd without a shell, so the job
died on a bare ENOENT. Passes shell:true on win32.
darwin-x64 hung: macos-13 is a deprecated image that frequently sits queued.
darwin-x64 is now cross-compiled from the macos-14 arm64 runner via
--target x86_64-apple-darwin, removing that runner from the matrix entirely.
Verified locally: the staged binary reports "Mach-O 64-bit executable x86_64".
Every push ran the matrix twice: `push: branches: ['**']` plus `pull_request`
both fire for a branch with an open PR. Push is now limited to the default
branch and release tags, with pull_request covering branches. Adds a concurrency
group that supersedes in-flight runs but never cancels a tag.
Publishing waited for all four platforms because a separate job used
`needs: build`. Package, upload and publish now all happen inside each matrix
job, so a platform ships the moment it is ready and one broken or slow target
cannot hold up a healthy one.
Also:
- matrix.rust-target would have been evaluated as subtraction in a GitHub
expression; renamed to matrix.rustTarget
- build-companion.mjs and release.mjs read DORAEMON_RUST_TARGET and
DORAEMON_VSIX_TARGET, so one `npm run build` serves both native and
cross-compiled jobs without extra steps
- timeout-minutes: 40 so a hung runner fails instead of blocking the queue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ships Doraemon as a Kiro extension with a bundled 792 KB native companion, so one install gives a transparent always-on-top desktop mascot with nothing else to download.
Companion (kiro-extension/companion, Rust + tao/wry)
transparentfeature and no window shadowExtension
autoresolves companion then window, so the mascot appears outside the IDE on first install with no configuration.Desktop app
Drag regression fix
Also