Skip to content

Support text and file attachments from applets - #145

Merged
tonyfresher merged 25 commits into
mainfrom
tinkering/chat-context
Sep 22, 2026
Merged

tonyfresher merged 25 commits into
mainfrom
tinkering/chat-context

Conversation

@tonyfresher

Copy link
Copy Markdown
Collaborator

Summary

  • Replace applet chat context events with validated text and file attachments
  • Support workspace-relative file paths and uploads up to 32 MB
  • Update composer state, sending, rendering, fixtures, and attachment tests

Testing

  • Not run (not requested)

@tonyfresher
tonyfresher force-pushed the tinkering/chat-context branch from 26e8c01 to ab254a3 Compare September 16, 2026 15:18
@tonyfresher
tonyfresher marked this pull request as ready for review September 16, 2026 16:29
Comment thread workspace/.claude/skills/moi-workspace/SKILL.md Outdated
Comment thread DESIGN.md
Comment thread workspace/.claude/skills/moi-workspace/references/INTENTS.md Outdated
Comment thread workspace/.claude/skills/moi-workspace/references/INTENTS.md
Comment thread server/moi-scaffold.ts
Comment thread server/api.ts
@molefrog

Copy link
Copy Markdown
Owner

Some other findings from Claude code review:

  • The agent is never told what is. Text attachments now ride inside the user message as a JSON block, but neither SKILL.md nor INTENTS.md mentions the block, and the envelope's "Applet message" section (lib/moi-context.ts:156) no longer describes attached data. The model will mostly infer it from label and text, but one paragraph in the skill, like the one for , would make the behavior reliable across harnesses.
    1. No limit on how many attachments one message can carry. Each text attachment is capped at 5,000 characters and each file at 32 MB. Nothing caps the number of them. Before this PR, all applet context on a message together was capped at 2,000 characters. Now an applet that maps a big table to one text attachment per row produces thousands of attachments that each pass validation on their own. The message sent to the agent can then be megabytes of JSON, which costs tokens or fails to send. With files, it means thousands of parallel uploads. The server validator has the same gap, so it can't stop this either. A cap on count and total text length in both places would close it.
  1. Staging attachments has none of the protection that sending has. The runtime deliberately guards sendChatMessage against a common applet mistake: calling it inside the render body, which fires once per render. Identical messages within two seconds are dropped and there is a per-minute cap. addChatAttachment has no such guard. Called during render, it stages a new chip on every re-render. Identical text is deduped, but text that varies per render, such as a timestamp, produces a chip each time. A file attachment starts a fresh upload or a server read of up to 32 MB on every render. Reusing the same rate limiter for staging would fix it.

  2. The docs list three tab ids, the code accepts four. focusTab accepts overview, agent, scratchpad and view:, and the generated type declarations in each workspace still say so. The new INTENTS.md lists only three and drops agent, which is the chat tab. The section it replaced in SKILL.md listed all four. So an agent reading the new docs won't know it can open the chat tab this way, and two documents moi ships now disagree. Either add agent back, or if dropping it is intentional because the chat intents already open chat, remove it from the type declaration comment too.

@tonyfresher
tonyfresher merged commit 9cb7e8f into main Sep 22, 2026
2 checks passed
@tonyfresher
tonyfresher deleted the tinkering/chat-context branch September 22, 2026 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants