@jmoyers/harness 0.1.11 → 0.1.20

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 (232) hide show
  1. package/README.md +31 -39
  2. package/package.json +31 -11
  3. package/packages/harness-ai/src/anthropic-protocol.ts +68 -68
  4. package/packages/harness-ai/src/stream-text.ts +13 -91
  5. package/packages/harness-ui/src/frame-primitives.ts +158 -0
  6. package/packages/harness-ui/src/index.ts +18 -0
  7. package/packages/harness-ui/src/interaction/conversation-input-forwarder.ts +221 -0
  8. package/packages/harness-ui/src/interaction/conversation-selection-input.ts +213 -0
  9. package/packages/harness-ui/src/interaction/global-shortcut-input.ts +172 -0
  10. package/{src/ui → packages/harness-ui/src/interaction}/input-preflight.ts +10 -12
  11. package/{src/ui → packages/harness-ui/src/interaction}/input-token-router.ts +120 -69
  12. package/packages/harness-ui/src/interaction/input.ts +420 -0
  13. package/packages/harness-ui/src/interaction/left-nav-input.ts +166 -0
  14. package/{src/ui → packages/harness-ui/src/interaction}/main-pane-pointer-input.ts +91 -23
  15. package/{src/ui → packages/harness-ui/src/interaction}/pointer-routing-input.ts +112 -48
  16. package/packages/harness-ui/src/interaction/rail-pointer-input.ts +62 -0
  17. package/packages/harness-ui/src/interaction/repository-fold-input.ts +118 -0
  18. package/packages/harness-ui/src/kit.ts +476 -0
  19. package/packages/harness-ui/src/layout.ts +238 -0
  20. package/packages/harness-ui/src/modal-manager.ts +222 -0
  21. package/{src/ui → packages/harness-ui/src}/screen.ts +53 -26
  22. package/packages/harness-ui/src/surface.ts +252 -0
  23. package/packages/harness-ui/src/text-layout.ts +210 -0
  24. package/packages/nim-core/src/contracts.ts +239 -0
  25. package/packages/nim-core/src/event-store.ts +299 -0
  26. package/packages/nim-core/src/events.ts +53 -0
  27. package/packages/nim-core/src/index.ts +9 -0
  28. package/packages/nim-core/src/provider-router.ts +129 -0
  29. package/packages/nim-core/src/providers/anthropic-driver.ts +291 -0
  30. package/packages/nim-core/src/runtime-factory.ts +49 -0
  31. package/packages/nim-core/src/runtime.ts +1797 -0
  32. package/packages/nim-core/src/session-store.ts +516 -0
  33. package/packages/nim-core/src/telemetry.ts +48 -0
  34. package/packages/nim-test-tui/src/index.ts +150 -0
  35. package/packages/nim-ui-core/src/index.ts +1 -0
  36. package/packages/nim-ui-core/src/projection.ts +87 -0
  37. package/scripts/codex-live-mux-runtime.ts +2 -3872
  38. package/scripts/control-plane-daemon.ts +11 -0
  39. package/scripts/harness-bin.js +5 -0
  40. package/scripts/harness-commands.ts +300 -0
  41. package/scripts/harness-runtime.ts +82 -0
  42. package/scripts/harness.ts +33 -3019
  43. package/scripts/nim-tui-smoke.ts +748 -0
  44. package/src/cli/auth/runtime.ts +948 -0
  45. package/src/cli/gateway/runtime.ts +1872 -0
  46. package/src/cli/parsing/flags.ts +23 -0
  47. package/src/cli/parsing/session.ts +42 -0
  48. package/src/cli/runtime/context.ts +193 -0
  49. package/src/cli/runtime-app/application.ts +392 -0
  50. package/src/cli/runtime-infra/gateway-control.ts +729 -0
  51. package/{scripts/harness-inspector.ts → src/cli/workflows/inspector.ts} +14 -11
  52. package/src/cli/workflows/runtime.ts +965 -0
  53. package/src/clients/tui/left-rail-interactions.ts +519 -0
  54. package/src/clients/tui/main-pane-interactions.ts +509 -0
  55. package/src/clients/tui/modal-input-routing.ts +71 -0
  56. package/src/clients/tui/render-snapshot-adapter.ts +88 -0
  57. package/src/clients/web/synced-selectors.ts +132 -0
  58. package/src/codex/live-session.ts +82 -29
  59. package/src/config/config-core.ts +348 -8
  60. package/src/config/harness.config.template.jsonc +33 -0
  61. package/src/control-plane/agent-realtime-api.ts +82 -427
  62. package/src/control-plane/session-summary.ts +10 -81
  63. package/src/control-plane/status/reducer-base.ts +12 -12
  64. package/src/control-plane/status/reducers/claude-status-reducer.ts +3 -3
  65. package/src/control-plane/status/reducers/codex-status-reducer.ts +4 -4
  66. package/src/control-plane/status/reducers/cursor-status-reducer.ts +3 -3
  67. package/src/control-plane/stream-client.ts +12 -2
  68. package/src/control-plane/stream-command-parser.ts +83 -143
  69. package/src/control-plane/stream-protocol.ts +53 -37
  70. package/src/control-plane/stream-server-command.ts +376 -69
  71. package/src/control-plane/stream-server-session-runtime.ts +3 -2
  72. package/src/control-plane/stream-server.ts +864 -70
  73. package/src/control-plane/stream-session-runtime-types.ts +41 -0
  74. package/src/{mux/live-mux/control-plane-records.ts → core/contracts/records.ts} +24 -97
  75. package/src/core/state/observed-stream-cursor.ts +43 -0
  76. package/src/core/state/synced-observed-state.ts +273 -0
  77. package/src/core/store/harness-synced-store.ts +81 -0
  78. package/src/diff/budget.ts +136 -0
  79. package/src/diff/build.ts +289 -0
  80. package/src/diff/chunker.ts +146 -0
  81. package/src/diff/git-invoke.ts +315 -0
  82. package/src/diff/git-parse.ts +472 -0
  83. package/src/diff/hash.ts +70 -0
  84. package/src/diff/index.ts +24 -0
  85. package/src/diff/normalize.ts +134 -0
  86. package/src/diff/types.ts +178 -0
  87. package/src/diff-ui/args.ts +346 -0
  88. package/src/diff-ui/commands.ts +123 -0
  89. package/src/diff-ui/finder.ts +94 -0
  90. package/src/diff-ui/highlight.ts +127 -0
  91. package/src/diff-ui/index.ts +2 -0
  92. package/src/diff-ui/model.ts +141 -0
  93. package/src/diff-ui/pager.ts +412 -0
  94. package/src/diff-ui/render.ts +337 -0
  95. package/src/diff-ui/runtime.ts +379 -0
  96. package/src/diff-ui/state.ts +224 -0
  97. package/src/diff-ui/types.ts +236 -0
  98. package/src/domain/workspace.ts +68 -5
  99. package/src/mux/control-plane-op-queue.ts +93 -7
  100. package/src/mux/conversation-rail.ts +28 -71
  101. package/src/mux/dual-pane-core.ts +13 -13
  102. package/src/mux/harness-core-ui.ts +313 -42
  103. package/src/mux/input-shortcuts.ts +13 -131
  104. package/src/mux/keybinding-catalog.ts +340 -0
  105. package/src/mux/keybinding-registry.ts +103 -0
  106. package/src/mux/live-mux/command-menu-open-in.ts +280 -0
  107. package/src/mux/live-mux/command-menu.ts +167 -4
  108. package/src/mux/live-mux/conversation-state.ts +13 -0
  109. package/src/mux/live-mux/directory-resolution.ts +1 -1
  110. package/src/mux/live-mux/git-snapshot.ts +33 -2
  111. package/src/mux/live-mux/global-shortcut-handlers.ts +6 -0
  112. package/src/mux/live-mux/home-pane-drop.ts +1 -1
  113. package/src/mux/live-mux/home-pane-pointer.ts +10 -0
  114. package/src/mux/live-mux/input-forwarding.ts +59 -2
  115. package/src/mux/live-mux/left-nav-activation.ts +124 -7
  116. package/src/mux/live-mux/left-nav.ts +35 -0
  117. package/src/mux/live-mux/link-click.ts +292 -0
  118. package/src/mux/live-mux/modal-command-menu-handler.ts +46 -9
  119. package/src/mux/live-mux/modal-conversation-handlers.ts +5 -1
  120. package/src/mux/live-mux/modal-input-reducers.ts +77 -12
  121. package/src/mux/live-mux/modal-overlays.ts +168 -34
  122. package/src/mux/live-mux/modal-pointer.ts +3 -7
  123. package/src/mux/live-mux/modal-prompt-handlers.ts +23 -2
  124. package/src/mux/live-mux/modal-release-notes-handler.ts +111 -0
  125. package/src/mux/live-mux/modal-task-editor-handler.ts +16 -11
  126. package/src/mux/live-mux/pointer-routing.ts +5 -2
  127. package/src/mux/live-mux/project-pane-pointer.ts +8 -0
  128. package/src/mux/live-mux/rail-layout.ts +33 -30
  129. package/src/mux/live-mux/release-notes.ts +383 -0
  130. package/src/mux/live-mux/render-trace-analysis.ts +52 -7
  131. package/src/mux/live-mux/repository-folding.ts +3 -0
  132. package/src/mux/live-mux/selection.ts +0 -4
  133. package/src/mux/live-mux/session-diagnostics-paths.ts +21 -0
  134. package/src/mux/project-pane-github-review.ts +271 -0
  135. package/src/mux/render-frame.ts +4 -0
  136. package/src/mux/runtime-app/codex-live-mux-runtime.ts +5191 -0
  137. package/src/mux/task-composer.ts +21 -14
  138. package/src/mux/task-focused-pane.ts +118 -117
  139. package/src/mux/task-screen-keybindings.ts +10 -101
  140. package/src/mux/workspace-rail-model.ts +270 -104
  141. package/src/mux/workspace-rail.ts +45 -22
  142. package/src/pty/session-broker.ts +1 -1
  143. package/{scripts → src/recording}/terminal-recording-gif-lib.ts +2 -2
  144. package/src/services/control-plane.ts +50 -32
  145. package/src/services/conversation-lifecycle.ts +118 -87
  146. package/src/services/conversation-startup-hydration.ts +20 -12
  147. package/src/services/directory-hydration.ts +21 -16
  148. package/src/services/event-persistence.ts +7 -0
  149. package/src/services/left-rail-pointer-handler.ts +329 -0
  150. package/src/services/mux-ui-state-persistence.ts +5 -1
  151. package/src/services/recording.ts +34 -26
  152. package/src/services/runtime-command-menu-agent-tools.ts +1 -1
  153. package/src/services/runtime-control-actions.ts +79 -61
  154. package/src/services/runtime-control-plane-ops.ts +122 -83
  155. package/src/services/runtime-conversation-actions.ts +40 -26
  156. package/src/services/runtime-conversation-activation.ts +73 -46
  157. package/src/services/runtime-conversation-starter.ts +53 -45
  158. package/src/services/runtime-conversation-title-edit.ts +91 -80
  159. package/src/services/runtime-envelope-handler.ts +107 -105
  160. package/src/services/runtime-git-state.ts +42 -29
  161. package/src/services/runtime-layout-resize.ts +3 -1
  162. package/src/services/runtime-left-rail-render.ts +99 -63
  163. package/src/services/runtime-nim-cli-session.ts +438 -0
  164. package/src/services/runtime-nim-session.ts +705 -0
  165. package/src/services/runtime-nim-tool-bridge.ts +141 -0
  166. package/src/services/runtime-observed-event-projection-pipeline.ts +45 -0
  167. package/src/services/runtime-process-wiring.ts +29 -36
  168. package/src/services/runtime-project-pane-github-review-cache.ts +164 -0
  169. package/src/services/runtime-render-flush.ts +63 -70
  170. package/src/services/runtime-render-lifecycle.ts +65 -64
  171. package/src/services/runtime-render-orchestrator.ts +55 -45
  172. package/src/services/runtime-render-pipeline.ts +106 -103
  173. package/src/services/runtime-render-state.ts +62 -49
  174. package/src/services/runtime-repository-actions.ts +97 -72
  175. package/src/services/runtime-right-pane-render.ts +80 -53
  176. package/src/services/runtime-shutdown.ts +38 -35
  177. package/src/services/runtime-stream-subscriptions.ts +35 -27
  178. package/src/services/runtime-task-composer-persistence.ts +71 -59
  179. package/src/services/runtime-task-composer-snapshot.ts +14 -0
  180. package/src/services/runtime-task-editor-actions.ts +46 -29
  181. package/src/services/runtime-task-pane-actions.ts +220 -134
  182. package/src/services/runtime-task-pane-shortcuts.ts +323 -123
  183. package/src/services/runtime-workspace-observed-effect-queue.ts +25 -0
  184. package/src/services/runtime-workspace-observed-events.ts +33 -184
  185. package/src/services/runtime-workspace-observed-transition-policy.ts +228 -0
  186. package/src/services/session-diagnostics-store.ts +217 -0
  187. package/src/services/startup-background-resume.ts +26 -21
  188. package/src/services/startup-orchestrator.ts +16 -13
  189. package/src/services/startup-paint-tracker.ts +29 -21
  190. package/src/services/startup-persisted-conversation-queue.ts +19 -13
  191. package/src/services/startup-settled-gate.ts +25 -15
  192. package/src/services/startup-shutdown.ts +18 -22
  193. package/src/services/startup-state-hydration.ts +44 -34
  194. package/src/services/startup-visibility.ts +12 -4
  195. package/src/services/task-pane-selection-actions.ts +89 -72
  196. package/src/services/task-planning-hydration.ts +24 -18
  197. package/src/services/task-planning-observed-events.ts +50 -52
  198. package/src/services/workspace-observed-events.ts +66 -63
  199. package/src/storage/storage-lifecycle-core.ts +438 -0
  200. package/src/store/control-plane-store-normalize.ts +33 -242
  201. package/src/store/control-plane-store-types.ts +1 -35
  202. package/src/store/control-plane-store.ts +360 -56
  203. package/src/store/event-store.ts +366 -8
  204. package/src/terminal/snapshot-oracle.ts +207 -94
  205. package/src/ui/mux-theme.ts +112 -8
  206. package/src/ui/panes/home-gridfire.ts +40 -31
  207. package/src/ui/panes/home.ts +10 -2
  208. package/src/ui/panes/nim.ts +315 -0
  209. package/src/mux/live-mux/actions-task.ts +0 -115
  210. package/src/mux/live-mux/left-rail-actions.ts +0 -118
  211. package/src/mux/live-mux/left-rail-conversation-click.ts +0 -85
  212. package/src/mux/live-mux/left-rail-pointer.ts +0 -74
  213. package/src/mux/live-mux/task-pane-shortcuts.ts +0 -206
  214. package/src/services/runtime-directory-actions.ts +0 -164
  215. package/src/services/runtime-input-pipeline.ts +0 -50
  216. package/src/services/runtime-input-router.ts +0 -195
  217. package/src/services/runtime-main-pane-input.ts +0 -230
  218. package/src/services/runtime-modal-input.ts +0 -137
  219. package/src/services/runtime-navigation-input.ts +0 -197
  220. package/src/services/runtime-rail-input.ts +0 -279
  221. package/src/services/runtime-task-pane.ts +0 -62
  222. package/src/services/runtime-workspace-actions.ts +0 -158
  223. package/src/ui/conversation-input-forwarder.ts +0 -114
  224. package/src/ui/conversation-selection-input.ts +0 -103
  225. package/src/ui/global-shortcut-input.ts +0 -89
  226. package/src/ui/input.ts +0 -269
  227. package/src/ui/kit.ts +0 -509
  228. package/src/ui/left-nav-input.ts +0 -80
  229. package/src/ui/left-rail-pointer-input.ts +0 -148
  230. package/src/ui/modals/manager.ts +0 -218
  231. package/src/ui/repository-fold-input.ts +0 -91
  232. package/src/ui/surface.ts +0 -224
@@ -1,195 +0,0 @@
1
- import { RuntimeMainPaneInput } from './runtime-main-pane-input.ts';
2
- import { RuntimeModalInput } from './runtime-modal-input.ts';
3
- import { RuntimeRailInput } from './runtime-rail-input.ts';
4
- import type { CommandMenuActionDescriptor } from '../mux/live-mux/command-menu.ts';
5
-
6
- type RuntimeModalInputOptions = ConstructorParameters<typeof RuntimeModalInput>[0];
7
- type RuntimeRailInputOptions = ConstructorParameters<typeof RuntimeRailInput>[0];
8
- type RuntimeMainPaneInputOptions = ConstructorParameters<typeof RuntimeMainPaneInput>[0];
9
- type RuntimeMainPaneInputWithoutLeftRail = Omit<
10
- RuntimeMainPaneInputOptions,
11
- 'leftRailPointerInput'
12
- >;
13
- type RuntimeWorkspaceActions = RuntimeModalInputOptions['workspaceActions'] &
14
- RuntimeRailInputOptions['runtimeWorkspaceActions'] &
15
- RuntimeMainPaneInputWithoutLeftRail['workspaceActions'];
16
- type RuntimeTaskEditorActions = RuntimeModalInputOptions['taskEditorActions'];
17
- type RuntimeShortcutBindings = RuntimeRailInputOptions['shortcutBindings'];
18
- type RuntimeConversationRecord = {
19
- title: string;
20
- directoryId: string | null;
21
- };
22
-
23
- interface RuntimeInputRouterOptions {
24
- readonly workspace: RuntimeModalInputOptions['workspace'];
25
- readonly conversations: ReadonlyMap<string, RuntimeConversationRecord>;
26
- readonly runtimeWorkspaceActions: RuntimeWorkspaceActions;
27
- readonly runtimeTaskEditorActions: RuntimeTaskEditorActions;
28
- readonly detectShortcut: (input: Buffer, bindings: RuntimeShortcutBindings) => string | null;
29
- readonly modalDismissShortcutBindings: RuntimeShortcutBindings;
30
- readonly shortcutBindings: RuntimeShortcutBindings;
31
- readonly dismissOnOutsideClick: RuntimeModalInputOptions['dismissOnOutsideClick'];
32
- readonly buildCommandMenuModalOverlay: RuntimeModalInputOptions['buildCommandMenuModalOverlay'];
33
- readonly buildConversationTitleModalOverlay: RuntimeModalInputOptions['buildConversationTitleModalOverlay'];
34
- readonly buildNewThreadModalOverlay: RuntimeModalInputOptions['buildNewThreadModalOverlay'];
35
- readonly resolveNewThreadPromptAgentByRow: RuntimeModalInputOptions['resolveNewThreadPromptAgentByRow'];
36
- readonly stopConversationTitleEdit: (persistPending: boolean) => void;
37
- readonly queueControlPlaneOp: RuntimeModalInputOptions['queueControlPlaneOp'];
38
- readonly normalizeGitHubRemoteUrl: RuntimeModalInputOptions['normalizeGitHubRemoteUrl'];
39
- readonly repositoriesHas: (repositoryId: string) => boolean;
40
- readonly markDirty: () => void;
41
- readonly scheduleConversationTitlePersist: () => void;
42
- readonly resolveCommandMenuActions: () => readonly CommandMenuActionDescriptor[];
43
- readonly executeCommandMenuAction: (actionId: string) => void;
44
- readonly persistApiKey?: RuntimeModalInputOptions['persistApiKey'];
45
- readonly requestStop: RuntimeRailInputOptions['requestStop'];
46
- readonly resolveDirectoryForAction: RuntimeRailInputOptions['resolveDirectoryForAction'];
47
- readonly toggleCommandMenu: RuntimeRailInputOptions['toggleCommandMenu'];
48
- readonly openNewThreadPrompt: RuntimeRailInputOptions['openNewThreadPrompt'];
49
- readonly firstDirectoryForRepositoryGroup: RuntimeRailInputOptions['firstDirectoryForRepositoryGroup'];
50
- readonly enterHomePane: RuntimeRailInputOptions['enterHomePane'];
51
- readonly enterProjectPane: RuntimeRailInputOptions['enterProjectPane'];
52
- readonly queuePersistMuxUiState: RuntimeRailInputOptions['queuePersistMuxUiState'];
53
- readonly repositoryGroupIdForDirectory: RuntimeRailInputOptions['repositoryGroupIdForDirectory'];
54
- readonly toggleRepositoryGroup: RuntimeRailInputOptions['toggleRepositoryGroup'];
55
- readonly collapseRepositoryGroup: RuntimeRailInputOptions['collapseRepositoryGroup'];
56
- readonly expandRepositoryGroup: RuntimeRailInputOptions['expandRepositoryGroup'];
57
- readonly collapseAllRepositoryGroups: RuntimeRailInputOptions['collapseAllRepositoryGroups'];
58
- readonly expandAllRepositoryGroups: RuntimeRailInputOptions['expandAllRepositoryGroups'];
59
- readonly directoriesHas: RuntimeRailInputOptions['directoriesHas'];
60
- readonly conversationDirectoryId: RuntimeRailInputOptions['conversationDirectoryId'];
61
- readonly conversationsHas: RuntimeRailInputOptions['conversationsHas'];
62
- readonly getMainPaneMode: RuntimeRailInputOptions['getMainPaneMode'];
63
- readonly getActiveConversationId: RuntimeRailInputOptions['getActiveConversationId'];
64
- readonly getActiveDirectoryId: RuntimeRailInputOptions['getActiveDirectoryId'];
65
- readonly chordTimeoutMs: RuntimeRailInputOptions['chordTimeoutMs'];
66
- readonly collapseAllChordPrefix: RuntimeRailInputOptions['collapseAllChordPrefix'];
67
- readonly releaseViewportPinForSelection: RuntimeRailInputOptions['releaseViewportPinForSelection'];
68
- readonly beginConversationTitleEdit: RuntimeRailInputOptions['beginConversationTitleEdit'];
69
- readonly resetConversationPaneFrameCache: RuntimeRailInputOptions['resetConversationPaneFrameCache'];
70
- readonly conversationTitleEditDoubleClickWindowMs: RuntimeRailInputOptions['conversationTitleEditDoubleClickWindowMs'];
71
- readonly projectPaneActionAtRow: RuntimeMainPaneInputWithoutLeftRail['projectPaneActionAtRow'];
72
- readonly queueCloseDirectory: RuntimeMainPaneInputWithoutLeftRail['queueCloseDirectory'];
73
- readonly selectTaskById: RuntimeMainPaneInputWithoutLeftRail['selectTaskById'];
74
- readonly selectRepositoryById: RuntimeMainPaneInputWithoutLeftRail['selectRepositoryById'];
75
- readonly taskPaneActionAtCell: RuntimeMainPaneInputWithoutLeftRail['taskPaneActionAtCell'];
76
- readonly taskPaneActionAtRow: RuntimeMainPaneInputWithoutLeftRail['taskPaneActionAtRow'];
77
- readonly taskPaneTaskIdAtRow: RuntimeMainPaneInputWithoutLeftRail['taskPaneTaskIdAtRow'];
78
- readonly taskPaneRepositoryIdAtRow: RuntimeMainPaneInputWithoutLeftRail['taskPaneRepositoryIdAtRow'];
79
- readonly applyPaneDividerAtCol: RuntimeMainPaneInputWithoutLeftRail['applyPaneDividerAtCol'];
80
- readonly pinViewportForSelection: RuntimeMainPaneInputWithoutLeftRail['pinViewportForSelection'];
81
- readonly homePaneEditDoubleClickWindowMs: RuntimeMainPaneInputWithoutLeftRail['homePaneEditDoubleClickWindowMs'];
82
- }
83
-
84
- export class RuntimeInputRouter {
85
- private readonly modalInput: RuntimeModalInput;
86
- private readonly railInput: RuntimeRailInput;
87
- private readonly mainPaneInput: RuntimeMainPaneInput;
88
-
89
- constructor(options: RuntimeInputRouterOptions) {
90
- this.modalInput = new RuntimeModalInput({
91
- workspace: options.workspace,
92
- conversations: options.conversations,
93
- workspaceActions: options.runtimeWorkspaceActions,
94
- taskEditorActions: options.runtimeTaskEditorActions,
95
- isModalDismissShortcut: (input) =>
96
- options.detectShortcut(input, options.modalDismissShortcutBindings) === 'mux.app.quit',
97
- isCommandMenuToggleShortcut: (input) =>
98
- options.detectShortcut(input, options.shortcutBindings) === 'mux.command-menu.toggle',
99
- isArchiveConversationShortcut: (input) => {
100
- const action = options.detectShortcut(input, options.shortcutBindings);
101
- return action === 'mux.conversation.archive' || action === 'mux.conversation.delete';
102
- },
103
- dismissOnOutsideClick: options.dismissOnOutsideClick,
104
- buildCommandMenuModalOverlay: options.buildCommandMenuModalOverlay,
105
- buildConversationTitleModalOverlay: options.buildConversationTitleModalOverlay,
106
- buildNewThreadModalOverlay: options.buildNewThreadModalOverlay,
107
- resolveNewThreadPromptAgentByRow: options.resolveNewThreadPromptAgentByRow,
108
- stopConversationTitleEdit: options.stopConversationTitleEdit,
109
- queueControlPlaneOp: options.queueControlPlaneOp,
110
- normalizeGitHubRemoteUrl: options.normalizeGitHubRemoteUrl,
111
- repositoriesHas: options.repositoriesHas,
112
- markDirty: options.markDirty,
113
- scheduleConversationTitlePersist: options.scheduleConversationTitlePersist,
114
- resolveCommandMenuActions: options.resolveCommandMenuActions,
115
- executeCommandMenuAction: options.executeCommandMenuAction,
116
- ...(options.persistApiKey === undefined
117
- ? {}
118
- : {
119
- persistApiKey: options.persistApiKey,
120
- }),
121
- });
122
- const runtimeRailOptions: RuntimeRailInputOptions = {
123
- workspace: options.workspace,
124
- shortcutBindings: options.shortcutBindings,
125
- queueControlPlaneOp: options.queueControlPlaneOp,
126
- runtimeWorkspaceActions: options.runtimeWorkspaceActions,
127
- requestStop: options.requestStop,
128
- resolveDirectoryForAction: options.resolveDirectoryForAction,
129
- openNewThreadPrompt: options.openNewThreadPrompt,
130
- toggleCommandMenu: options.toggleCommandMenu,
131
- firstDirectoryForRepositoryGroup: options.firstDirectoryForRepositoryGroup,
132
- enterHomePane: options.enterHomePane,
133
- enterProjectPane: options.enterProjectPane,
134
- markDirty: options.markDirty,
135
- queuePersistMuxUiState: options.queuePersistMuxUiState,
136
- conversations: options.conversations,
137
- repositoryGroupIdForDirectory: options.repositoryGroupIdForDirectory,
138
- toggleRepositoryGroup: options.toggleRepositoryGroup,
139
- collapseRepositoryGroup: options.collapseRepositoryGroup,
140
- expandRepositoryGroup: options.expandRepositoryGroup,
141
- collapseAllRepositoryGroups: options.collapseAllRepositoryGroups,
142
- expandAllRepositoryGroups: options.expandAllRepositoryGroups,
143
- directoriesHas: options.directoriesHas,
144
- conversationDirectoryId: options.conversationDirectoryId,
145
- conversationsHas: options.conversationsHas,
146
- getMainPaneMode: options.getMainPaneMode,
147
- getActiveConversationId: options.getActiveConversationId,
148
- getActiveDirectoryId: options.getActiveDirectoryId,
149
- repositoriesHas: options.repositoriesHas,
150
- chordTimeoutMs: options.chordTimeoutMs,
151
- collapseAllChordPrefix: options.collapseAllChordPrefix,
152
- stopConversationTitleEdit: options.stopConversationTitleEdit,
153
- releaseViewportPinForSelection: options.releaseViewportPinForSelection,
154
- beginConversationTitleEdit: options.beginConversationTitleEdit,
155
- resetConversationPaneFrameCache: options.resetConversationPaneFrameCache,
156
- conversationTitleEditDoubleClickWindowMs: options.conversationTitleEditDoubleClickWindowMs,
157
- };
158
- this.railInput = new RuntimeRailInput(runtimeRailOptions);
159
- this.mainPaneInput = new RuntimeMainPaneInput({
160
- workspace: options.workspace,
161
- workspaceActions: options.runtimeWorkspaceActions,
162
- projectPaneActionAtRow: options.projectPaneActionAtRow,
163
- openNewThreadPrompt: options.openNewThreadPrompt,
164
- queueCloseDirectory: options.queueCloseDirectory,
165
- selectTaskById: options.selectTaskById,
166
- selectRepositoryById: options.selectRepositoryById,
167
- taskPaneActionAtCell: options.taskPaneActionAtCell,
168
- taskPaneActionAtRow: options.taskPaneActionAtRow,
169
- taskPaneTaskIdAtRow: options.taskPaneTaskIdAtRow,
170
- taskPaneRepositoryIdAtRow: options.taskPaneRepositoryIdAtRow,
171
- applyPaneDividerAtCol: options.applyPaneDividerAtCol,
172
- pinViewportForSelection: options.pinViewportForSelection,
173
- releaseViewportPinForSelection: options.releaseViewportPinForSelection,
174
- markDirty: options.markDirty,
175
- homePaneEditDoubleClickWindowMs: options.homePaneEditDoubleClickWindowMs,
176
- leftRailPointerInput: this.railInput,
177
- });
178
- }
179
-
180
- routeModalInput(input: Buffer): boolean {
181
- return this.modalInput.routeModalInput(input);
182
- }
183
-
184
- handleRepositoryFoldInput(input: Buffer): boolean {
185
- return this.railInput.handleRepositoryFoldInput(input);
186
- }
187
-
188
- handleGlobalShortcutInput(input: Buffer): boolean {
189
- return this.railInput.handleGlobalShortcutInput(input);
190
- }
191
-
192
- inputTokenRouter(): Pick<RuntimeMainPaneInput, 'routeTokens'> {
193
- return this.mainPaneInput;
194
- }
195
- }
@@ -1,230 +0,0 @@
1
- import type { WorkspaceModel } from '../domain/workspace.ts';
2
- import type { LeftRailPointerInput } from '../ui/left-rail-pointer-input.ts';
3
- import { MainPanePointerInput } from '../ui/main-pane-pointer-input.ts';
4
- import { PointerRoutingInput } from '../ui/pointer-routing-input.ts';
5
- import { ConversationSelectionInput } from '../ui/conversation-selection-input.ts';
6
- import { InputTokenRouter } from '../ui/input-token-router.ts';
7
-
8
- type ProjectPaneSnapshot = NonNullable<WorkspaceModel['projectPaneSnapshot']>;
9
- type MainPanePointerInputOptions = ConstructorParameters<
10
- typeof MainPanePointerInput<ProjectPaneSnapshot>
11
- >[0];
12
- type PointerRoutingInputOptions = ConstructorParameters<typeof PointerRoutingInput>[0];
13
- type ConversationSelectionInputOptions = ConstructorParameters<
14
- typeof ConversationSelectionInput
15
- >[0];
16
- type InputTokenRouterOptions = ConstructorParameters<typeof InputTokenRouter>[0];
17
-
18
- type RouteTokensInput = Parameters<InputTokenRouter['routeTokens']>[0];
19
- type RouteTokensResult = ReturnType<InputTokenRouter['routeTokens']>;
20
-
21
- interface RuntimeMainPaneWorkspaceActions {
22
- runTaskPaneAction(action: 'task.ready' | 'task.draft' | 'task.complete'): void;
23
- openTaskEditPrompt(taskId: string): void;
24
- openRepositoryPromptForEdit(repositoryId: string): void;
25
- reorderTaskByDrop(draggedTaskId: string, targetTaskId: string): void;
26
- reorderRepositoryByDrop(draggedRepositoryId: string, targetRepositoryId: string): void;
27
- }
28
-
29
- interface RuntimeMainPaneInputOptions {
30
- readonly workspace: WorkspaceModel;
31
- readonly leftRailPointerInput: Pick<LeftRailPointerInput, 'handlePointerClick'>;
32
- readonly workspaceActions: RuntimeMainPaneWorkspaceActions;
33
- readonly projectPaneActionAtRow: MainPanePointerInputOptions['projectPaneActionAtRow'];
34
- readonly openNewThreadPrompt: MainPanePointerInputOptions['openNewThreadPrompt'];
35
- readonly queueCloseDirectory: MainPanePointerInputOptions['queueCloseDirectory'];
36
- readonly selectTaskById: MainPanePointerInputOptions['selectTaskById'];
37
- readonly selectRepositoryById: MainPanePointerInputOptions['selectRepositoryById'];
38
- readonly taskPaneActionAtCell: (
39
- view: WorkspaceModel['latestTaskPaneView'],
40
- rowIndex: number,
41
- colIndex: number,
42
- ) => ReturnType<MainPanePointerInputOptions['actionAtCell']>;
43
- readonly taskPaneActionAtRow: (
44
- view: WorkspaceModel['latestTaskPaneView'],
45
- rowIndex: number,
46
- ) => ReturnType<MainPanePointerInputOptions['actionAtRow']>;
47
- readonly taskPaneTaskIdAtRow: (
48
- view: WorkspaceModel['latestTaskPaneView'],
49
- rowIndex: number,
50
- ) => ReturnType<MainPanePointerInputOptions['taskIdAtRow']>;
51
- readonly taskPaneRepositoryIdAtRow: (
52
- view: WorkspaceModel['latestTaskPaneView'],
53
- rowIndex: number,
54
- ) => ReturnType<MainPanePointerInputOptions['repositoryIdAtRow']>;
55
- readonly applyPaneDividerAtCol: PointerRoutingInputOptions['applyPaneDividerAtCol'];
56
- readonly pinViewportForSelection: ConversationSelectionInputOptions['pinViewportForSelection'];
57
- readonly releaseViewportPinForSelection: ConversationSelectionInputOptions['releaseViewportPinForSelection'];
58
- readonly markDirty: () => void;
59
- readonly homePaneEditDoubleClickWindowMs: number;
60
- readonly nowMs?: () => number;
61
- }
62
-
63
- interface RuntimeMainPaneInputDependencies {
64
- readonly createMainPanePointerInput?: (
65
- options: MainPanePointerInputOptions,
66
- ) => Pick<
67
- MainPanePointerInput<ProjectPaneSnapshot>,
68
- 'handleProjectPanePointerClick' | 'handleHomePanePointerClick'
69
- >;
70
- readonly createPointerRoutingInput?: (
71
- options: PointerRoutingInputOptions,
72
- ) => Pick<
73
- PointerRoutingInput,
74
- | 'handlePaneDividerDrag'
75
- | 'handleHomePaneDragRelease'
76
- | 'handleSeparatorPointerPress'
77
- | 'handleMainPaneWheel'
78
- | 'handleHomePaneDragMove'
79
- >;
80
- readonly createConversationSelectionInput?: (
81
- options: ConversationSelectionInputOptions,
82
- ) => Pick<ConversationSelectionInput, 'clearSelectionOnTextToken' | 'handleMouseSelection'>;
83
- readonly createInputTokenRouter?: (
84
- options: InputTokenRouterOptions,
85
- ) => Pick<InputTokenRouter, 'routeTokens'>;
86
- }
87
-
88
- export class RuntimeMainPaneInput {
89
- private readonly inputTokenRouter: Pick<InputTokenRouter, 'routeTokens'>;
90
-
91
- constructor(
92
- options: RuntimeMainPaneInputOptions,
93
- dependencies: RuntimeMainPaneInputDependencies = {},
94
- ) {
95
- const nowMs = options.nowMs ?? (() => Date.now());
96
- const createMainPanePointerInput =
97
- dependencies.createMainPanePointerInput ??
98
- ((mainPaneOptions: MainPanePointerInputOptions) => new MainPanePointerInput(mainPaneOptions));
99
- const createPointerRoutingInput =
100
- dependencies.createPointerRoutingInput ??
101
- ((pointerOptions: PointerRoutingInputOptions) => new PointerRoutingInput(pointerOptions));
102
- const createConversationSelectionInput =
103
- dependencies.createConversationSelectionInput ??
104
- ((selectionOptions: ConversationSelectionInputOptions) =>
105
- new ConversationSelectionInput(selectionOptions));
106
- const createInputTokenRouter =
107
- dependencies.createInputTokenRouter ??
108
- ((tokenRouterOptions: InputTokenRouterOptions) => new InputTokenRouter(tokenRouterOptions));
109
-
110
- const mainPanePointerInput = createMainPanePointerInput({
111
- getMainPaneMode: () => options.workspace.mainPaneMode,
112
- getProjectPaneSnapshot: () => options.workspace.projectPaneSnapshot,
113
- getProjectPaneScrollTop: () => options.workspace.projectPaneScrollTop,
114
- projectPaneActionAtRow: options.projectPaneActionAtRow,
115
- openNewThreadPrompt: options.openNewThreadPrompt,
116
- queueCloseDirectory: options.queueCloseDirectory,
117
- actionAtCell: (rowIndex, colIndex) =>
118
- options.taskPaneActionAtCell(options.workspace.latestTaskPaneView, rowIndex, colIndex),
119
- actionAtRow: (rowIndex) =>
120
- options.taskPaneActionAtRow(options.workspace.latestTaskPaneView, rowIndex),
121
- clearTaskEditClickState: () => {
122
- options.workspace.taskPaneTaskEditClickState = null;
123
- },
124
- clearRepositoryEditClickState: () => {
125
- options.workspace.taskPaneRepositoryEditClickState = null;
126
- },
127
- clearHomePaneDragState: () => {
128
- options.workspace.homePaneDragState = null;
129
- },
130
- getTaskRepositoryDropdownOpen: () => options.workspace.taskRepositoryDropdownOpen,
131
- setTaskRepositoryDropdownOpen: (open) => {
132
- options.workspace.taskRepositoryDropdownOpen = open;
133
- },
134
- taskIdAtRow: (rowIndex) =>
135
- options.taskPaneTaskIdAtRow(options.workspace.latestTaskPaneView, rowIndex),
136
- repositoryIdAtRow: (rowIndex) =>
137
- options.taskPaneRepositoryIdAtRow(options.workspace.latestTaskPaneView, rowIndex),
138
- selectTaskById: options.selectTaskById,
139
- selectRepositoryById: options.selectRepositoryById,
140
- runTaskPaneAction: (action) => {
141
- options.workspaceActions.runTaskPaneAction(action);
142
- },
143
- nowMs,
144
- homePaneEditDoubleClickWindowMs: options.homePaneEditDoubleClickWindowMs,
145
- getTaskEditClickState: () => options.workspace.taskPaneTaskEditClickState,
146
- getRepositoryEditClickState: () => options.workspace.taskPaneRepositoryEditClickState,
147
- clearTaskPaneNotice: () => {
148
- options.workspace.taskPaneNotice = null;
149
- },
150
- setTaskEditClickState: (next) => {
151
- options.workspace.taskPaneTaskEditClickState = next;
152
- },
153
- setRepositoryEditClickState: (next) => {
154
- options.workspace.taskPaneRepositoryEditClickState = next;
155
- },
156
- setHomePaneDragState: (next) => {
157
- options.workspace.homePaneDragState = next;
158
- },
159
- openTaskEditPrompt: (taskId) => {
160
- options.workspaceActions.openTaskEditPrompt(taskId);
161
- },
162
- openRepositoryPromptForEdit: (repositoryId) => {
163
- options.workspaceActions.openRepositoryPromptForEdit(repositoryId);
164
- },
165
- markDirty: options.markDirty,
166
- });
167
-
168
- const pointerRoutingInput = createPointerRoutingInput({
169
- getPaneDividerDragActive: () => options.workspace.paneDividerDragActive,
170
- setPaneDividerDragActive: (active) => {
171
- options.workspace.paneDividerDragActive = active;
172
- },
173
- applyPaneDividerAtCol: options.applyPaneDividerAtCol,
174
- getHomePaneDragState: () => options.workspace.homePaneDragState,
175
- setHomePaneDragState: (next) => {
176
- options.workspace.homePaneDragState = next;
177
- },
178
- getMainPaneMode: () => options.workspace.mainPaneMode,
179
- taskIdAtRow: (index) =>
180
- options.taskPaneTaskIdAtRow(options.workspace.latestTaskPaneView, index),
181
- repositoryIdAtRow: (index) =>
182
- options.taskPaneRepositoryIdAtRow(options.workspace.latestTaskPaneView, index),
183
- reorderTaskByDrop: (draggedTaskId, targetTaskId) => {
184
- options.workspaceActions.reorderTaskByDrop(draggedTaskId, targetTaskId);
185
- },
186
- reorderRepositoryByDrop: (draggedRepositoryId, targetRepositoryId) => {
187
- options.workspaceActions.reorderRepositoryByDrop(draggedRepositoryId, targetRepositoryId);
188
- },
189
- onProjectWheel: (delta) => {
190
- options.workspace.projectPaneScrollTop = Math.max(
191
- 0,
192
- options.workspace.projectPaneScrollTop + delta,
193
- );
194
- },
195
- onHomeWheel: (delta) => {
196
- options.workspace.taskPaneScrollTop = Math.max(
197
- 0,
198
- options.workspace.taskPaneScrollTop + delta,
199
- );
200
- },
201
- markDirty: options.markDirty,
202
- });
203
-
204
- const conversationSelectionInput = createConversationSelectionInput({
205
- getSelection: () => options.workspace.selection,
206
- setSelection: (next) => {
207
- options.workspace.selection = next;
208
- },
209
- getSelectionDrag: () => options.workspace.selectionDrag,
210
- setSelectionDrag: (next) => {
211
- options.workspace.selectionDrag = next;
212
- },
213
- pinViewportForSelection: options.pinViewportForSelection,
214
- releaseViewportPinForSelection: options.releaseViewportPinForSelection,
215
- markDirty: options.markDirty,
216
- });
217
-
218
- this.inputTokenRouter = createInputTokenRouter({
219
- getMainPaneMode: () => options.workspace.mainPaneMode,
220
- pointerRoutingInput,
221
- mainPanePointerInput,
222
- leftRailPointerInput: options.leftRailPointerInput,
223
- conversationSelectionInput,
224
- });
225
- }
226
-
227
- routeTokens(input: RouteTokensInput): RouteTokensResult {
228
- return this.inputTokenRouter.routeTokens(input);
229
- }
230
- }
@@ -1,137 +0,0 @@
1
- import type { WorkspaceModel } from '../domain/workspace.ts';
2
- import type { CommandMenuActionDescriptor } from '../mux/live-mux/command-menu.ts';
3
- import { InputRouter } from '../ui/input.ts';
4
-
5
- type InputRouterOptions = ConstructorParameters<typeof InputRouter>[0];
6
-
7
- interface RuntimeModalInputWorkspaceActions {
8
- archiveConversation(sessionId: string): Promise<void>;
9
- createAndActivateConversationInDirectory(directoryId: string, agentType: string): Promise<void>;
10
- addDirectoryByPath(rawPath: string): Promise<void>;
11
- upsertRepositoryByRemoteUrl(remoteUrl: string, existingRepositoryId?: string): Promise<void>;
12
- }
13
-
14
- interface RuntimeModalInputTaskEditorActions {
15
- submitTaskEditorPayload(
16
- payload: Parameters<InputRouterOptions['submitTaskEditorPayload']>[0],
17
- ): void;
18
- }
19
-
20
- interface RuntimeModalInputOptions {
21
- readonly workspace: WorkspaceModel;
22
- readonly conversations: ReadonlyMap<string, { title: string }>;
23
- readonly workspaceActions: RuntimeModalInputWorkspaceActions;
24
- readonly taskEditorActions: RuntimeModalInputTaskEditorActions;
25
- readonly isModalDismissShortcut: (input: Buffer) => boolean;
26
- readonly isCommandMenuToggleShortcut: (input: Buffer) => boolean;
27
- readonly isArchiveConversationShortcut: (input: Buffer) => boolean;
28
- readonly dismissOnOutsideClick: InputRouterOptions['dismissOnOutsideClick'];
29
- readonly buildCommandMenuModalOverlay: InputRouterOptions['buildCommandMenuModalOverlay'];
30
- readonly buildConversationTitleModalOverlay: InputRouterOptions['buildConversationTitleModalOverlay'];
31
- readonly buildNewThreadModalOverlay: InputRouterOptions['buildNewThreadModalOverlay'];
32
- readonly resolveNewThreadPromptAgentByRow: InputRouterOptions['resolveNewThreadPromptAgentByRow'];
33
- readonly stopConversationTitleEdit: (persistPending: boolean) => void;
34
- readonly queueControlPlaneOp: (task: () => Promise<void>, label: string) => void;
35
- readonly normalizeGitHubRemoteUrl: (remoteUrl: string) => string | null;
36
- readonly repositoriesHas: (repositoryId: string) => boolean;
37
- readonly scheduleConversationTitlePersist: () => void;
38
- readonly resolveCommandMenuActions: () => readonly CommandMenuActionDescriptor[];
39
- readonly executeCommandMenuAction: (actionId: string) => void;
40
- readonly persistApiKey?: (keyName: string, value: string) => void;
41
- readonly markDirty: () => void;
42
- }
43
-
44
- interface RuntimeModalInputDependencies {
45
- readonly createInputRouter?: (
46
- options: InputRouterOptions,
47
- ) => Pick<InputRouter, 'routeModalInput'>;
48
- }
49
-
50
- export class RuntimeModalInput {
51
- private readonly inputRouter: Pick<InputRouter, 'routeModalInput'>;
52
-
53
- constructor(options: RuntimeModalInputOptions, dependencies: RuntimeModalInputDependencies = {}) {
54
- const createInputRouter =
55
- dependencies.createInputRouter ??
56
- ((routerOptions: InputRouterOptions) => new InputRouter(routerOptions));
57
- this.inputRouter = createInputRouter({
58
- isModalDismissShortcut: options.isModalDismissShortcut,
59
- isCommandMenuToggleShortcut: options.isCommandMenuToggleShortcut,
60
- isArchiveConversationShortcut: options.isArchiveConversationShortcut,
61
- dismissOnOutsideClick: options.dismissOnOutsideClick,
62
- buildCommandMenuModalOverlay: options.buildCommandMenuModalOverlay,
63
- buildConversationTitleModalOverlay: options.buildConversationTitleModalOverlay,
64
- buildNewThreadModalOverlay: options.buildNewThreadModalOverlay,
65
- resolveNewThreadPromptAgentByRow: options.resolveNewThreadPromptAgentByRow,
66
- stopConversationTitleEdit: options.stopConversationTitleEdit,
67
- queueControlPlaneOp: options.queueControlPlaneOp,
68
- archiveConversation: async (sessionId) => {
69
- await options.workspaceActions.archiveConversation(sessionId);
70
- },
71
- createAndActivateConversationInDirectory: async (directoryId, agentType) => {
72
- await options.workspaceActions.createAndActivateConversationInDirectory(
73
- directoryId,
74
- agentType,
75
- );
76
- },
77
- addDirectoryByPath: async (rawPath) => {
78
- await options.workspaceActions.addDirectoryByPath(rawPath);
79
- },
80
- normalizeGitHubRemoteUrl: options.normalizeGitHubRemoteUrl,
81
- upsertRepositoryByRemoteUrl: async (remoteUrl, existingRepositoryId) => {
82
- await options.workspaceActions.upsertRepositoryByRemoteUrl(remoteUrl, existingRepositoryId);
83
- },
84
- repositoriesHas: options.repositoriesHas,
85
- markDirty: options.markDirty,
86
- conversations: options.conversations,
87
- scheduleConversationTitlePersist: options.scheduleConversationTitlePersist,
88
- getCommandMenu: () => options.workspace.commandMenu,
89
- setCommandMenu: (menu) => {
90
- options.workspace.commandMenu = menu;
91
- },
92
- resolveCommandMenuActions: options.resolveCommandMenuActions,
93
- executeCommandMenuAction: options.executeCommandMenuAction,
94
- getTaskEditorPrompt: () => options.workspace.taskEditorPrompt,
95
- setTaskEditorPrompt: (next) => {
96
- options.workspace.taskEditorPrompt = next;
97
- },
98
- submitTaskEditorPayload: (payload) => {
99
- options.taskEditorActions.submitTaskEditorPayload(payload);
100
- },
101
- ...(options.persistApiKey === undefined
102
- ? {}
103
- : {
104
- getApiKeyPrompt: () => options.workspace.apiKeyPrompt,
105
- setApiKeyPrompt: (
106
- next: {
107
- keyName: string;
108
- displayName: string;
109
- value: string;
110
- error: string | null;
111
- hasExistingValue: boolean;
112
- } | null,
113
- ) => {
114
- options.workspace.apiKeyPrompt = next;
115
- },
116
- persistApiKey: options.persistApiKey,
117
- }),
118
- getConversationTitleEdit: () => options.workspace.conversationTitleEdit,
119
- getNewThreadPrompt: () => options.workspace.newThreadPrompt,
120
- setNewThreadPrompt: (prompt) => {
121
- options.workspace.newThreadPrompt = prompt;
122
- },
123
- getAddDirectoryPrompt: () => options.workspace.addDirectoryPrompt,
124
- setAddDirectoryPrompt: (next) => {
125
- options.workspace.addDirectoryPrompt = next;
126
- },
127
- getRepositoryPrompt: () => options.workspace.repositoryPrompt,
128
- setRepositoryPrompt: (next) => {
129
- options.workspace.repositoryPrompt = next;
130
- },
131
- });
132
- }
133
-
134
- routeModalInput(input: Buffer): boolean {
135
- return this.inputRouter.routeModalInput(input);
136
- }
137
- }