Skip to content

Comments

feature: hoon evaluation in chat#5434

Open
jamesacklin wants to merge 11 commits intodevelopfrom
ja/hoon-eval
Open

feature: hoon evaluation in chat#5434
jamesacklin wants to merge 11 commits intodevelopfrom
ja/hoon-eval

Conversation

@jamesacklin
Copy link
Member

@jamesacklin jamesacklin commented Jan 20, 2026

This PR resurrects the inline Hoon evaluation feature from the old Landscape (pkg/landscape in urbit/urbit) and adapts it for the modern environment.

This is feature-flagged for now and will require a lockstep update to both the back-end and the client.

Original PR made by @wca4a's Clawdbot implementation in #5428

Plan here: https://gist.github.com/wca4a/4274ee015c5de2ca320a5c67da92cf4d

Changes

Ship-side (Hoon)

  • /ted/eval.hoon - Spider thread that evaluates Hoon code in a sandboxed environment
  • /sur/eval.hoon - Structures for eval input/output
  • /mar/eval/input.hoon and /mar/eval/output.hoon - Marks for JSON serialization

UI (TypeScript/React)

  • evalApi.ts - API function to call the eval thread
  • BareChatInput/index.tsx - Added eval mode state and handling
  • MessageInputBase.tsx - Added eval mode toggle button (Code icon)

How it works

  1. User clicks the Code icon to enter eval mode (button turns green)
  2. User types Hoon code in the input
  3. On send, the code is evaluated via the /ted/eval spider thread
  4. The result is posted as a formatted message with the code and output

Security Model

  • Code runs in a sandboxed environment with only [our now eny ..zuse] in the subject
  • Scry (.^) is disabled - returns crash if attempted
  • Uses mule for double-virtualization to catch crashes
  • No side effects possible - pure computation only

Screenshots / videos

image

@jamesacklin jamesacklin marked this pull request as ready for review January 20, 2026 21:07
@jamesacklin
Copy link
Member Author

@Fang- said the slop is fine. Since this has to wait for the back-end to update before the client, let's hold for now.

Copy link
Member

@Fang- Fang- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fang said the slop is fine

Yeah but I haven't reviewed your changes yet. (;

Comment on lines +10 to +14
:: handle both CLI [~ cord] and HTTP cord
=+ !<(arg-data=?(~ [~ cord]) arg)
=/ input=cord
?~ arg-data ''
+.arg-data
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the !< is right? Isn't it always going to be [~ cord]? The empty string default doesn't make sense anyway, that'll syntax error.

Suggested change
:: handle both CLI [~ cord] and HTTP cord
=+ !<(arg-data=?(~ [~ cord]) arg)
=/ input=cord
?~ arg-data ''
+.arg-data
:: unpack arg with leading ~
::
=+ !<([~ input=cord] arg)

Comment on lines +1 to +5
:: /sur/eval.hoon
::
|%
+$ eval-output (each cord cord)
--
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coin-toss on whether it makes sense to have a file for this one definition lol. Fine as-is, but it is funny.

?- -.toon
%0
=/ result=tape
(of-wall:format (~(win re (sell type.p.minted p.toon)) 0 80))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(of-wall:format (~(win re (sell type.p.minted p.toon)) 0 80))
(of-wall:format (wash [0 80] (sell type.p.minted p.toon)))

I guess I should also give a heads-up that the outer +of-walls throughout the file will append trailing newlines. If that's objectionable you'll want to (zing (join "\0a" the-walls)) instead, to only insert newlines in between the lines.

Comment on lines +37 to +40
%0
=/ result=tape
(of-wall:format (~(win re (sell type.p.minted p.toon)) 0 80))
[%& (crip result)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kingside or queenside formatting for ?-, take your pick. (For %2 too.)

Suggested change
%0
=/ result=tape
(of-wall:format (~(win re (sell type.p.minted p.toon)) 0 80))
[%& (crip result)]
%0
=/ result=tape
(of-wall:format (~(win re (sell type.p.minted p.toon)) 0 80))
[%& (crip result)]
::
Suggested change
%0
=/ result=tape
(of-wall:format (~(win re (sell type.p.minted p.toon)) 0 80))
[%& (crip result)]
%0 =/ result=tape
(of-wall:format (~(win re (sell type.p.minted p.toon)) 0 80))
[%& (crip result)]

Comment on lines +11 to +14
?- -.eval-output
%& (pairs:enjs:format ~[['status' s+'ok'] ['output' s+p.eval-output]])
%| (pairs:enjs:format ~[['status' s+'error'] ['output' s+p.eval-output]])
==
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous implementation was fine structurally, just needed to swap out the status value.

Suggested change
?- -.eval-output
%& (pairs:enjs:format ~[['status' s+'ok'] ['output' s+p.eval-output]])
%| (pairs:enjs:format ~[['status' s+'error'] ['output' s+p.eval-output]])
==
%- pairs:enjs:format
:~ ['status' ?-(-.eval-output %& s+'ok', %| s+'error')]
['output' s+p.eval-output]
==

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants