@vsuryav/agent-sim 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +25 -0
  2. package/bin/agent-sim.js +25 -0
  3. package/package.json +72 -0
  4. package/src/app-paths.ts +29 -0
  5. package/src/app-sync.test.ts +75 -0
  6. package/src/app-sync.ts +110 -0
  7. package/src/cli.ts +129 -0
  8. package/src/collector/claude-code.test.ts +102 -0
  9. package/src/collector/claude-code.ts +133 -0
  10. package/src/collector/codex-cli.test.ts +116 -0
  11. package/src/collector/codex-cli.ts +149 -0
  12. package/src/collector/db.test.ts +59 -0
  13. package/src/collector/db.ts +125 -0
  14. package/src/collector/names.test.ts +21 -0
  15. package/src/collector/names.ts +28 -0
  16. package/src/collector/personality.test.ts +40 -0
  17. package/src/collector/personality.ts +46 -0
  18. package/src/collector/remote-sync.test.ts +31 -0
  19. package/src/collector/remote-sync.ts +171 -0
  20. package/src/collector/sync.test.ts +67 -0
  21. package/src/collector/sync.ts +148 -0
  22. package/src/collector/types.ts +1 -0
  23. package/src/engine/bootstrap/state.ts +3 -0
  24. package/src/engine/buddy/CompanionSprite.tsx +371 -0
  25. package/src/engine/buddy/companion.ts +133 -0
  26. package/src/engine/buddy/prompt.ts +36 -0
  27. package/src/engine/buddy/sprites.ts +514 -0
  28. package/src/engine/buddy/types.ts +148 -0
  29. package/src/engine/buddy/useBuddyNotification.tsx +98 -0
  30. package/src/engine/ink/Ansi.tsx +292 -0
  31. package/src/engine/ink/bidi.ts +139 -0
  32. package/src/engine/ink/clearTerminal.ts +74 -0
  33. package/src/engine/ink/colorize.ts +231 -0
  34. package/src/engine/ink/components/AlternateScreen.tsx +80 -0
  35. package/src/engine/ink/components/App.tsx +658 -0
  36. package/src/engine/ink/components/AppContext.ts +21 -0
  37. package/src/engine/ink/components/Box.tsx +214 -0
  38. package/src/engine/ink/components/Button.tsx +192 -0
  39. package/src/engine/ink/components/ClockContext.tsx +112 -0
  40. package/src/engine/ink/components/CursorDeclarationContext.ts +32 -0
  41. package/src/engine/ink/components/ErrorOverview.tsx +109 -0
  42. package/src/engine/ink/components/Link.tsx +42 -0
  43. package/src/engine/ink/components/Newline.tsx +39 -0
  44. package/src/engine/ink/components/NoSelect.tsx +68 -0
  45. package/src/engine/ink/components/RawAnsi.tsx +57 -0
  46. package/src/engine/ink/components/ScrollBox.tsx +237 -0
  47. package/src/engine/ink/components/Spacer.tsx +20 -0
  48. package/src/engine/ink/components/StdinContext.ts +49 -0
  49. package/src/engine/ink/components/TerminalFocusContext.tsx +52 -0
  50. package/src/engine/ink/components/TerminalSizeContext.tsx +7 -0
  51. package/src/engine/ink/components/Text.tsx +254 -0
  52. package/src/engine/ink/constants.ts +2 -0
  53. package/src/engine/ink/dom.ts +484 -0
  54. package/src/engine/ink/events/click-event.ts +38 -0
  55. package/src/engine/ink/events/dispatcher.ts +233 -0
  56. package/src/engine/ink/events/emitter.ts +39 -0
  57. package/src/engine/ink/events/event-handlers.ts +73 -0
  58. package/src/engine/ink/events/event.ts +11 -0
  59. package/src/engine/ink/events/focus-event.ts +21 -0
  60. package/src/engine/ink/events/input-event.ts +205 -0
  61. package/src/engine/ink/events/keyboard-event.ts +51 -0
  62. package/src/engine/ink/events/terminal-event.ts +107 -0
  63. package/src/engine/ink/events/terminal-focus-event.ts +19 -0
  64. package/src/engine/ink/focus.ts +181 -0
  65. package/src/engine/ink/frame.ts +124 -0
  66. package/src/engine/ink/get-max-width.ts +27 -0
  67. package/src/engine/ink/global.d.ts +18 -0
  68. package/src/engine/ink/hit-test.ts +130 -0
  69. package/src/engine/ink/hooks/use-animation-frame.ts +57 -0
  70. package/src/engine/ink/hooks/use-app.ts +8 -0
  71. package/src/engine/ink/hooks/use-declared-cursor.ts +73 -0
  72. package/src/engine/ink/hooks/use-input.ts +92 -0
  73. package/src/engine/ink/hooks/use-interval.ts +67 -0
  74. package/src/engine/ink/hooks/use-search-highlight.ts +53 -0
  75. package/src/engine/ink/hooks/use-selection.ts +104 -0
  76. package/src/engine/ink/hooks/use-stdin.ts +8 -0
  77. package/src/engine/ink/hooks/use-tab-status.ts +72 -0
  78. package/src/engine/ink/hooks/use-terminal-focus.ts +16 -0
  79. package/src/engine/ink/hooks/use-terminal-title.ts +31 -0
  80. package/src/engine/ink/hooks/use-terminal-viewport.ts +96 -0
  81. package/src/engine/ink/ink.tsx +1723 -0
  82. package/src/engine/ink/instances.ts +10 -0
  83. package/src/engine/ink/layout/engine.ts +6 -0
  84. package/src/engine/ink/layout/geometry.ts +97 -0
  85. package/src/engine/ink/layout/node.ts +152 -0
  86. package/src/engine/ink/layout/yoga.ts +308 -0
  87. package/src/engine/ink/line-width-cache.ts +24 -0
  88. package/src/engine/ink/log-update.ts +773 -0
  89. package/src/engine/ink/measure-element.ts +23 -0
  90. package/src/engine/ink/measure-text.ts +47 -0
  91. package/src/engine/ink/node-cache.ts +54 -0
  92. package/src/engine/ink/optimizer.ts +93 -0
  93. package/src/engine/ink/output.ts +797 -0
  94. package/src/engine/ink/parse-keypress.ts +801 -0
  95. package/src/engine/ink/reconciler.ts +512 -0
  96. package/src/engine/ink/render-border.ts +231 -0
  97. package/src/engine/ink/render-node-to-output.ts +1462 -0
  98. package/src/engine/ink/render-to-screen.ts +231 -0
  99. package/src/engine/ink/renderer.ts +178 -0
  100. package/src/engine/ink/root.ts +184 -0
  101. package/src/engine/ink/screen.ts +1486 -0
  102. package/src/engine/ink/searchHighlight.ts +93 -0
  103. package/src/engine/ink/selection.ts +917 -0
  104. package/src/engine/ink/squash-text-nodes.ts +92 -0
  105. package/src/engine/ink/stringWidth.ts +222 -0
  106. package/src/engine/ink/styles.ts +771 -0
  107. package/src/engine/ink/supports-hyperlinks.ts +57 -0
  108. package/src/engine/ink/tabstops.ts +46 -0
  109. package/src/engine/ink/terminal-focus-state.ts +47 -0
  110. package/src/engine/ink/terminal-querier.ts +212 -0
  111. package/src/engine/ink/terminal.ts +248 -0
  112. package/src/engine/ink/termio/ansi.ts +75 -0
  113. package/src/engine/ink/termio/csi.ts +319 -0
  114. package/src/engine/ink/termio/dec.ts +60 -0
  115. package/src/engine/ink/termio/esc.ts +67 -0
  116. package/src/engine/ink/termio/osc.ts +493 -0
  117. package/src/engine/ink/termio/parser.ts +394 -0
  118. package/src/engine/ink/termio/sgr.ts +308 -0
  119. package/src/engine/ink/termio/tokenize.ts +319 -0
  120. package/src/engine/ink/termio/types.ts +236 -0
  121. package/src/engine/ink/useTerminalNotification.ts +126 -0
  122. package/src/engine/ink/warn.ts +9 -0
  123. package/src/engine/ink/widest-line.ts +19 -0
  124. package/src/engine/ink/wrap-text.ts +74 -0
  125. package/src/engine/ink/wrapAnsi.ts +20 -0
  126. package/src/engine/native-ts/yoga-layout/enums.ts +134 -0
  127. package/src/engine/native-ts/yoga-layout/index.ts +2578 -0
  128. package/src/engine/stubs/bootstrap-state.ts +4 -0
  129. package/src/engine/stubs/debug.ts +6 -0
  130. package/src/engine/stubs/log.ts +4 -0
  131. package/src/engine/utils/debug.ts +5 -0
  132. package/src/engine/utils/earlyInput.ts +4 -0
  133. package/src/engine/utils/env.ts +15 -0
  134. package/src/engine/utils/envUtils.ts +4 -0
  135. package/src/engine/utils/execFileNoThrow.ts +24 -0
  136. package/src/engine/utils/fullscreen.ts +4 -0
  137. package/src/engine/utils/intl.ts +9 -0
  138. package/src/engine/utils/log.ts +3 -0
  139. package/src/engine/utils/semver.ts +13 -0
  140. package/src/engine/utils/sliceAnsi.ts +10 -0
  141. package/src/engine/utils/theme.ts +17 -0
  142. package/src/game/App.tsx +141 -0
  143. package/src/game/agents/behavior.ts +249 -0
  144. package/src/game/agents/speech.ts +57 -0
  145. package/src/game/canvas.ts +98 -0
  146. package/src/game/launch.ts +36 -0
  147. package/src/game/ship/ShipView.tsx +145 -0
  148. package/src/game/ship/ship-map.ts +172 -0
  149. package/src/game/ui/AgentBio.tsx +72 -0
  150. package/src/game/ui/HUD.tsx +63 -0
  151. package/src/game/ui/StatusBar.tsx +49 -0
  152. package/src/game/useKeyboard.ts +62 -0
  153. package/src/main.tsx +22 -0
  154. package/src/run-interactive.ts +74 -0
@@ -0,0 +1,23 @@
1
+ import type { DOMElement } from './dom.js'
2
+
3
+ type Output = {
4
+ /**
5
+ * Element width.
6
+ */
7
+ width: number
8
+
9
+ /**
10
+ * Element height.
11
+ */
12
+ height: number
13
+ }
14
+
15
+ /**
16
+ * Measure the dimensions of a particular `<Box>` element.
17
+ */
18
+ const measureElement = (node: DOMElement): Output => ({
19
+ width: node.yogaNode?.getComputedWidth() ?? 0,
20
+ height: node.yogaNode?.getComputedHeight() ?? 0,
21
+ })
22
+
23
+ export default measureElement
@@ -0,0 +1,47 @@
1
+ import { lineWidth } from './line-width-cache.js'
2
+
3
+ type Output = {
4
+ width: number
5
+ height: number
6
+ }
7
+
8
+ // Single-pass measurement: computes both width and height in one
9
+ // iteration instead of two (widestLine + countVisualLines).
10
+ // Uses indexOf to avoid array allocation from split('\n').
11
+ function measureText(text: string, maxWidth: number): Output {
12
+ if (text.length === 0) {
13
+ return {
14
+ width: 0,
15
+ height: 0,
16
+ }
17
+ }
18
+
19
+ // Infinite or non-positive width means no wrapping — each line is one visual line.
20
+ // Must check before the loop since Math.ceil(w / Infinity) = 0.
21
+ const noWrap = maxWidth <= 0 || !Number.isFinite(maxWidth)
22
+
23
+ let height = 0
24
+ let width = 0
25
+ let start = 0
26
+
27
+ while (start <= text.length) {
28
+ const end = text.indexOf('\n', start)
29
+ const line = end === -1 ? text.substring(start) : text.substring(start, end)
30
+
31
+ const w = lineWidth(line)
32
+ width = Math.max(width, w)
33
+
34
+ if (noWrap) {
35
+ height++
36
+ } else {
37
+ height += w === 0 ? 1 : Math.ceil(w / maxWidth)
38
+ }
39
+
40
+ if (end === -1) break
41
+ start = end + 1
42
+ }
43
+
44
+ return { width, height }
45
+ }
46
+
47
+ export default measureText
@@ -0,0 +1,54 @@
1
+ import type { DOMElement } from './dom.js'
2
+ import type { Rectangle } from './layout/geometry.js'
3
+
4
+ /**
5
+ * Cached layout bounds for each rendered node (used for blit + clearing).
6
+ * `top` is the yoga-local getComputedTop() — stored so ScrollBox viewport
7
+ * culling can skip yoga reads for clean children whose position hasn't
8
+ * shifted (O(dirty) instead of O(mounted) first-pass).
9
+ */
10
+ export type CachedLayout = {
11
+ x: number
12
+ y: number
13
+ width: number
14
+ height: number
15
+ top?: number
16
+ }
17
+
18
+ export const nodeCache = new WeakMap<DOMElement, CachedLayout>()
19
+
20
+ /** Rects of removed children that need clearing on next render */
21
+ export const pendingClears = new WeakMap<DOMElement, Rectangle[]>()
22
+
23
+ /**
24
+ * Set when a pendingClear is added for an absolute-positioned node.
25
+ * Signals renderer to disable blit for the next frame: the removed node
26
+ * may have painted over non-siblings (e.g. an overlay over a ScrollBox
27
+ * earlier in tree order), so their blits from prevScreen would restore
28
+ * the overlay's pixels. Normal-flow removals are already handled by
29
+ * hasRemovedChild at the parent level; only absolute positioning paints
30
+ * cross-subtree. Reset at the start of each render.
31
+ */
32
+ let absoluteNodeRemoved = false
33
+
34
+ export function addPendingClear(
35
+ parent: DOMElement,
36
+ rect: Rectangle,
37
+ isAbsolute: boolean,
38
+ ): void {
39
+ const existing = pendingClears.get(parent)
40
+ if (existing) {
41
+ existing.push(rect)
42
+ } else {
43
+ pendingClears.set(parent, [rect])
44
+ }
45
+ if (isAbsolute) {
46
+ absoluteNodeRemoved = true
47
+ }
48
+ }
49
+
50
+ export function consumeAbsoluteRemovedFlag(): boolean {
51
+ const had = absoluteNodeRemoved
52
+ absoluteNodeRemoved = false
53
+ return had
54
+ }
@@ -0,0 +1,93 @@
1
+ import type { Diff } from './frame.js'
2
+
3
+ /**
4
+ * Optimize a diff by applying all optimization rules in a single pass.
5
+ * This reduces the number of patches that need to be written to the terminal.
6
+ *
7
+ * Rules applied:
8
+ * - Remove empty stdout patches
9
+ * - Merge consecutive cursorMove patches
10
+ * - Remove no-op cursorMove (0,0) patches
11
+ * - Concat adjacent style patches (transition diffs — can't drop either)
12
+ * - Dedupe consecutive hyperlinks with same URI
13
+ * - Cancel cursor hide/show pairs
14
+ * - Remove clear patches with count 0
15
+ */
16
+ export function optimize(diff: Diff): Diff {
17
+ if (diff.length <= 1) {
18
+ return diff
19
+ }
20
+
21
+ const result: Diff = []
22
+ let len = 0
23
+
24
+ for (const patch of diff) {
25
+ const type = patch.type
26
+
27
+ // Skip no-ops
28
+ if (type === 'stdout') {
29
+ if (patch.content === '') continue
30
+ } else if (type === 'cursorMove') {
31
+ if (patch.x === 0 && patch.y === 0) continue
32
+ } else if (type === 'clear') {
33
+ if (patch.count === 0) continue
34
+ }
35
+
36
+ // Try to merge with previous patch
37
+ if (len > 0) {
38
+ const lastIdx = len - 1
39
+ const last = result[lastIdx]!
40
+ const lastType = last.type
41
+
42
+ // Merge consecutive cursorMove
43
+ if (type === 'cursorMove' && lastType === 'cursorMove') {
44
+ result[lastIdx] = {
45
+ type: 'cursorMove',
46
+ x: last.x + patch.x,
47
+ y: last.y + patch.y,
48
+ }
49
+ continue
50
+ }
51
+
52
+ // Collapse consecutive cursorTo (only the last one matters)
53
+ if (type === 'cursorTo' && lastType === 'cursorTo') {
54
+ result[lastIdx] = patch
55
+ continue
56
+ }
57
+
58
+ // Concat adjacent style patches. styleStr is a transition diff
59
+ // (computed by diffAnsiCodes(from, to)), not a setter — dropping
60
+ // the first is only sound if its undo-codes are a subset of the
61
+ // second's, which is NOT guaranteed. e.g. [\e[49m, \e[2m]: dropping
62
+ // the bg reset leaks it into the next \e[2J/\e[2K via BCE.
63
+ if (type === 'styleStr' && lastType === 'styleStr') {
64
+ result[lastIdx] = { type: 'styleStr', str: last.str + patch.str }
65
+ continue
66
+ }
67
+
68
+ // Dedupe hyperlinks
69
+ if (
70
+ type === 'hyperlink' &&
71
+ lastType === 'hyperlink' &&
72
+ patch.uri === last.uri
73
+ ) {
74
+ continue
75
+ }
76
+
77
+ // Cancel cursor hide/show pairs
78
+ if (
79
+ (type === 'cursorShow' && lastType === 'cursorHide') ||
80
+ (type === 'cursorHide' && lastType === 'cursorShow')
81
+ ) {
82
+ result.pop()
83
+ len--
84
+ continue
85
+ }
86
+ }
87
+
88
+ result.push(patch)
89
+ len++
90
+ }
91
+
92
+ return result
93
+ }