Repository navigation
web: chat, the wallet and chat screens, and a build that works - #14
Open
ryannzander wants to merge 6 commits into
Open
ryannzander wants to merge 6 commits into
ryannzander wants to merge 6 commits into
Conversation
Owner
Author
|
A background security review flagged this branch, and it is right on all three counts. They are one root cause: No money moves without the human's press. What does break on a public URL:
Not covered by DECISIONS #10, which is about the agent's tools. Documented in the router and in |
The transcript and the model's history are one table. `text` is what the human reads, `items` is the raw Responses output the turn produced, and a row cannot half-commit, so the two cannot drift. A model that saw a different conversation from the one on screen is the worst bug this app could have, because every symptom of it reads as the model being stupid. `sendChatTurn` writes the user's row before running the turn, not with the reply afterwards. A turn can fail after the model has already written a proposal, and a proposal no message asked for is worse than a dangling user row. The loop prepends the same message to the items it returns, so that copy is dropped, and it is asserted rather than assumed. History goes to the model newest-N-rows-then-sorted. Sliced by row because a row holds a whole turn, so a function_call can never be separated from the output that answers it. `agentToolsFromEnv` throws by name: ChainReader and ShopReader have no implementation while nothing is deployed (issue #5), and a loop that quietly runs with no tools would report sending money it never sent. `verify:chat` drives the turn against a real Postgres with a scripted model. Written, not run: no database on this machine.
Both procedures are publicProcedure and there is no middleware anywhere in the app, so on a public URL a stranger can read the transcript and write into it. No money moves without the human's press, but the demo is grief-able: one stranger proposal at PENDING_HUMAN locks out the real one for ten minutes, and the transcript is global, so their text is in the history the model reads on the operator's next turn. Not covered by DECISIONS #10, which is about the agent's tools. trpc.ts already draws this line for the bridge. No scheme picked here: the answer shapes how the UI talks to the server, and that is Ryan's call.
Three things are missing and none of them are our code: nothing is deployed, the Flipper spike is unrun, and there is no OpenAI budget. mock.ts stands in for all three behind the interfaces that already existed, so the rest of the app can be built and shown. ScriptedResponses matches keywords and calls the real tools through the real loop, so everything except the choice of tool is exercised for real. It is not a model and the file says so in capitals. AGENT_MODE gates it and defaults to live. A machine meant to be talking to Sepolia should stop rather than quietly serve an invented balance, because an invented balance looks exactly like a real one. chat.mode exists so the UI can say which it is. The mock addresses are repeated digits so that one turning up in a proposal on a live machine says what happened faster than an error would. A test caught the routing reading an amount of 0 out of the digits inside a recipient address, so "send some eth to 0x7099..." would have proposed sending nothing. The address comes out before the amount goes looking.
The device is the hero, not the balance. The wallet screen leads with a panel drawn as the Flipper's amber LCD, and when something is waiting that panel becomes the request, so the screen and the device in your hand show the same words at the same time. Everything else is quiet: no cards, no shadows, no gradients. Statuses are worded for a person, so a proposal reads "Waiting on you" rather than PENDING_HUMAN. The chat opens empty with the pitch in two sentences, per Ryan's call on the layout: wallet as the main screen, navbar to the chat. `next build` had never succeeded in this repo, on any commit. Two causes, both pre-existing and both confirmed against the tree before these changes. `@tappy/protocol` imports its own modules as `./types.js`, which Node and tsc resolve and webpack does not, so the resolver now maps `.js` to `.ts`. And lint had never run, so a dozen errors had piled up in loop.ts, approvals.ts and schema.ts. Turbopack serves `dev` and is more forgiving, which is why nobody hit either one. CI ran neither the web tests, nor lint, nor the build. Fifty-two tests only ever ran on somebody's laptop. All three are in the workflow now, and the build is the only check that resolves modules the way Vercel will.
next lint loads next.config.js, which imports env.js and validates. The build step already had it and the lint step did not, so CI failed on a missing DATABASE_URL rather than on anything in the code.
This branch has not been deployed
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.
chat.sendandchat.history, themessagestable, a mock layer that runs the whole thing with nothing real behind it, and two screens. Plus the discovery thatnext buildhas never worked in this repo.Screens. Wallet is the main one, navbar leads to the chat, per Ryan. The wallet leads with a panel drawn as the Flipper's amber LCD, and when a proposal is waiting that panel becomes the request, so the screen and the device in your hand show the same words at the same time. Statuses are worded for a person: "Waiting on you", not
PENDING_HUMAN.AGENT_MODE=mockstands in for the chain, the device and the model at once, since all three are missing and none of them are our code.ScriptedResponsesmatches keywords and calls the real tools through the real loop, so only the choice of tool is fake. Opt-in, because an invented balance looks exactly like a real one, and both screens say so when it is on.Design calls in the chat layer
Two bugs found on the way
0out of the digits inside a recipient address, so "send some eth to 0x7099…" would have proposed sending nothing. Caught by a test.next buildhas never succeeded, on any commit. Confirmed against the tree before these changes, not assumed.@tappy/protocolimports its own modules as./types.js, which Node and tsc resolve and webpack does not. And lint had never run, so errors had piled up inloop.ts,approvals.tsandschema.ts. Turbopack servesdevand is more forgiving, which is why nobody hit either.CI ran neither the web tests, nor lint, nor the build. 52 tests only ever ran on somebody's laptop. All three are in the workflow now. The build is the only check that resolves modules the way Vercel will.
Checked: 52 web tests, 8 protocol tests, typecheck, lint, and a production build all pass locally.
Not checked, and this is what to do before merging. Nobody has seen either screen,
verify:chathas never run, and migration0001has never been applied. This machine had no Postgres, no Docker and no.env. All three need a database and nothing else:pnpm --filter @tappy/web db:migrate pnpm --filter @tappy/web verify:chat # scripted model, no API key needed AGENT_MODE=mock pnpm --filter @tappy/web devStill open:
chat.sendandchat.historyare unauthenticated. See the comment at the top ofchat.tsand the earlier comment on this PR. Blocks deploying, not merging.