offsite 0.0.2 → 0.0.4

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 (114) hide show
  1. package/README.md +18 -7
  2. package/apps/server/dist/main.mjs +5767 -0
  3. package/apps/server/dist/main.mjs.map +1 -0
  4. package/apps/web/dist/assets/{angular-html-Oa9dnZbT.js → angular-html-prQpjz7s.js} +1 -1
  5. package/apps/web/dist/assets/{angular-ts-F_BIbY2H.js → angular-ts-BE4HJ5Uh.js} +1 -1
  6. package/apps/web/dist/assets/{apl-D7AuiKiV.js → apl-CJ-NIQ-7.js} +1 -1
  7. package/apps/web/dist/assets/{astro-DnpymQyW.js → astro-CVkyXRVY.js} +1 -1
  8. package/apps/web/dist/assets/{blade-CZZrW0iI.js → blade-CQFMHse_.js} +1 -1
  9. package/apps/web/dist/assets/{c-V_Rix0w2.js → c-gqNWYRL8.js} +1 -1
  10. package/apps/web/dist/assets/{chapel-fGtLLMYq.js → chapel-CQ9_BV4j.js} +1 -1
  11. package/apps/web/dist/assets/{cobol-BFOTnbFa.js → cobol-D-9v184m.js} +1 -1
  12. package/apps/web/dist/assets/{coffee-BdvfipEg.js → coffee-BE0tIOLL.js} +1 -1
  13. package/apps/web/dist/assets/{cpp-D_NFR3H2.js → cpp-CzOLC-NF.js} +1 -1
  14. package/apps/web/dist/assets/{crystal-BM2vkBPa.js → crystal-f1GcBNi_.js} +1 -1
  15. package/apps/web/dist/assets/{css-Byur6C5q.js → css-DlqRAumc.js} +1 -1
  16. package/apps/web/dist/assets/{edge-CP-KL2DQ.js → edge-DQkkPJaW.js} +1 -1
  17. package/apps/web/dist/assets/{elixir-CiO075Fh.js → elixir-ClG78o74.js} +1 -1
  18. package/apps/web/dist/assets/{elm-DIyG-d95.js → elm-DZDmCmuw.js} +1 -1
  19. package/apps/web/dist/assets/{erb-DHZK6WKc.js → erb-B1mu0-DN.js} +1 -1
  20. package/apps/web/dist/assets/{git-rebase-CxXKbwiy.js → git-rebase-x1gs-rK2.js} +1 -1
  21. package/apps/web/dist/assets/{glimmer-js-BUhQC_gD.js → glimmer-js-Cjos1igW.js} +1 -1
  22. package/apps/web/dist/assets/{glimmer-ts-D2lLByyw.js → glimmer-ts-CrR-PFvn.js} +1 -1
  23. package/apps/web/dist/assets/{glsl-BMvlWqE_.js → glsl-DR0G8e99.js} +1 -1
  24. package/apps/web/dist/assets/{graphql-D9UFk_fJ.js → graphql-DKmrBZt7.js} +1 -1
  25. package/apps/web/dist/assets/{hack-BZAO0Jc2.js → hack-Brs_j9Xv.js} +1 -1
  26. package/apps/web/dist/assets/{haml-Dm5wroII.js → haml-8Lc-lF96.js} +1 -1
  27. package/apps/web/dist/assets/{handlebars-C9L1Bn7f.js → handlebars-Ds8WdPdv.js} +1 -1
  28. package/apps/web/dist/assets/{html-Bz91Luf0.js → html-C0gvYDho.js} +1 -1
  29. package/apps/web/dist/assets/{html-derivative-hIdjVrpA.js → html-derivative-CU9dkErg.js} +1 -1
  30. package/apps/web/dist/assets/{http-AWG6aeFM.js → http-BE0w0Fty.js} +1 -1
  31. package/apps/web/dist/assets/{hurl-pSGcpqgh.js → hurl-DqZk6YcW.js} +1 -1
  32. package/apps/web/dist/assets/index-0B-Gdd7b.css +2 -0
  33. package/apps/web/dist/assets/index-rgKS_aMw.js +1148 -0
  34. package/apps/web/dist/assets/{java-D_CyC-X4.js → java-PSSQ0YmM.js} +1 -1
  35. package/apps/web/dist/assets/{javascript-PK4jkG9t.js → javascript-Ci3r4rzs.js} +1 -1
  36. package/apps/web/dist/assets/{jinja-Cu3wzgkz.js → jinja-lLTko9Wl.js} +1 -1
  37. package/apps/web/dist/assets/{jison-CHevE1W8.js → jison-1BpHD5UK.js} +1 -1
  38. package/apps/web/dist/assets/{json-DPTkd0bP.js → json-BAUn76M4.js} +1 -1
  39. package/apps/web/dist/assets/{jsx-DcsDzCOA.js → jsx-B8sFp1vz.js} +1 -1
  40. package/apps/web/dist/assets/{julia-B9tMVOL0.js → julia-C4TZ4EL9.js} +1 -1
  41. package/apps/web/dist/assets/{just-BHIhrE9N.js → just-D5qIrqkp.js} +1 -1
  42. package/apps/web/dist/assets/{latex-CY05HK-G.js → latex-BL7XYxFg.js} +1 -1
  43. package/apps/web/dist/assets/{liquid-DJaL8XK2.js → liquid-DBx9Hq7B.js} +1 -1
  44. package/apps/web/dist/assets/{lua-BfaWUinJ.js → lua-BqjicQyd.js} +1 -1
  45. package/apps/web/dist/assets/{marko-0Lc0z7w6.js → marko-CHgy7yaY.js} +1 -1
  46. package/apps/web/dist/assets/{mdc-DEhXNYDZ.js → mdc-DOloBwb8.js} +1 -1
  47. package/apps/web/dist/assets/{nginx-DLuBebI5.js → nginx-g7I1HPwV.js} +1 -1
  48. package/apps/web/dist/assets/{nim-BIJh7lZB.js → nim-O6zJV1LD.js} +1 -1
  49. package/apps/web/dist/assets/{org-BFpxb2WJ.js → org-HLg4-757.js} +1 -1
  50. package/apps/web/dist/assets/{perl-DHbDMq2q.js → perl-B3cDKTai.js} +1 -1
  51. package/apps/web/dist/assets/{php-BcVbiJpZ.js → php-2eDApoU3.js} +1 -1
  52. package/apps/web/dist/assets/{pug-bdfyK-rS.js → pug-itzGn-nK.js} +1 -1
  53. package/apps/web/dist/assets/{qml-BC2D8eWk.js → qml-sU0VtUmf.js} +1 -1
  54. package/apps/web/dist/assets/{r-O3zbZ-YT.js → r-C6mhPqgr.js} +1 -1
  55. package/apps/web/dist/assets/{razor-Ffnu5_vD.js → razor-CSzRtbW7.js} +1 -1
  56. package/apps/web/dist/assets/{regexp-dnbUAgjx.js → regexp-BmdBJRV9.js} +1 -1
  57. package/apps/web/dist/assets/{rst-DJfy2dSm.js → rst-BRxUd6sp.js} +1 -1
  58. package/apps/web/dist/assets/{ruby-DGEpA0mD.js → ruby-CQHHOfmX.js} +1 -1
  59. package/apps/web/dist/assets/{sas-CZvL8X8k.js → sas-DlaL8b25.js} +1 -1
  60. package/apps/web/dist/assets/{scss-BtNSCzZB.js → scss-Cc71ABWp.js} +1 -1
  61. package/apps/web/dist/assets/{shellscript-uR-sOZlr.js → shellscript-CzA_LIIm.js} +1 -1
  62. package/apps/web/dist/assets/{shellsession-BT-Jl4S5.js → shellsession-DESJlgp3.js} +1 -1
  63. package/apps/web/dist/assets/{soy-BjfL_vrj.js → soy-Nkvq88YN.js} +1 -1
  64. package/apps/web/dist/assets/{sql-fa1gAeRF.js → sql-CtPxrO7T.js} +1 -1
  65. package/apps/web/dist/assets/{stata-DgTOpGhg.js → stata-BacEfVTr.js} +1 -1
  66. package/apps/web/dist/assets/{surrealql-DVqEkJeu.js → surrealql-CYW10JNe.js} +1 -1
  67. package/apps/web/dist/assets/{svelte-CyQ5sU9I.js → svelte-D3_tCKGs.js} +1 -1
  68. package/apps/web/dist/assets/{templ-DrztMbAf.js → templ-BGKIfY_b.js} +1 -1
  69. package/apps/web/dist/assets/{tex-NAwM8Kkh.js → tex-BkkYOaXX.js} +1 -1
  70. package/apps/web/dist/assets/{ts-tags-DX96dDxh.js → ts-tags-B02tnbpZ.js} +1 -1
  71. package/apps/web/dist/assets/{tsx-D3PnhDHK.js → tsx-D3MB1IUf.js} +1 -1
  72. package/apps/web/dist/assets/{twig-FG0P9evf.js → twig-CPhw2wGK.js} +1 -1
  73. package/apps/web/dist/assets/{typescript-Crqeuw0P.js → typescript-B7U4faGm.js} +1 -1
  74. package/apps/web/dist/assets/{typst-CO_2MFRr.js → typst-CN9EZswy.js} +1 -1
  75. package/apps/web/dist/assets/{vue-fTNrS0Q3.js → vue-YH8dfjo_.js} +1 -1
  76. package/apps/web/dist/assets/{vue-html-E0ptmXwc.js → vue-html-NwX2xzgp.js} +1 -1
  77. package/apps/web/dist/assets/{vue-vine-C34_rJIu.js → vue-vine-DoRmnjLj.js} +1 -1
  78. package/apps/web/dist/assets/{xml-BB9WbMMU.js → xml-DgfgLpPc.js} +1 -1
  79. package/apps/web/dist/assets/{xsl-B3w2P7LL.js → xsl-CEwQRUK_.js} +1 -1
  80. package/apps/web/dist/assets/{yaml-BKGRKqBA.js → yaml-CEFOzF95.js} +1 -1
  81. package/apps/web/dist/icon.svg +5 -0
  82. package/apps/web/dist/index.html +2 -2
  83. package/apps/web/dist/sw.js +19 -8
  84. package/bin/offsite.js +1 -1
  85. package/package.json +6 -1
  86. package/apps/server/dist/args.js +0 -11
  87. package/apps/server/dist/claude.js +0 -207
  88. package/apps/server/dist/config.js +0 -185
  89. package/apps/server/dist/content.js +0 -172
  90. package/apps/server/dist/db.js +0 -13
  91. package/apps/server/dist/files.js +0 -50
  92. package/apps/server/dist/git.js +0 -133
  93. package/apps/server/dist/history.js +0 -137
  94. package/apps/server/dist/hub.js +0 -10
  95. package/apps/server/dist/main.js +0 -64
  96. package/apps/server/dist/projects.js +0 -92
  97. package/apps/server/dist/protocol.js +0 -20
  98. package/apps/server/dist/push.js +0 -152
  99. package/apps/server/dist/run.js +0 -375
  100. package/apps/server/dist/runs.js +0 -102
  101. package/apps/server/dist/schemes.js +0 -262
  102. package/apps/server/dist/sessions.js +0 -65
  103. package/apps/server/dist/socket.js +0 -149
  104. package/apps/server/dist/storage.js +0 -22
  105. package/apps/server/dist/terminal/alerts.js +0 -145
  106. package/apps/server/dist/terminal/process.js +0 -207
  107. package/apps/server/dist/terminal/shell-check.js +0 -91
  108. package/apps/server/dist/terminal/shell-integration.js +0 -112
  109. package/apps/server/dist/terminal/terminal.js +0 -402
  110. package/apps/web/dist/assets/index-BiLbXfDN.js +0 -899
  111. package/apps/web/dist/assets/index-DQIK-TpZ.css +0 -2
  112. /package/apps/server/src/{terminal → services/terminal}/shell-integration/bash/offsite.bash +0 -0
  113. /package/apps/server/src/{terminal → services/terminal}/shell-integration/fish/offsite.fish +0 -0
  114. /package/apps/server/src/{terminal → services/terminal}/shell-integration/zsh/.zshenv +0 -0
@@ -1,262 +0,0 @@
1
- export const schemes = [
2
- {
3
- id: 'one-dark-darker',
4
- name: 'One Dark Darker',
5
- background: '#15181C',
6
- foreground: '#ABB2BF',
7
- cursor: '#B3BAC5',
8
- selectionBackground: '#3B414D',
9
- palette: [
10
- '#4A4F5A',
11
- '#EE5D69',
12
- '#97C775',
13
- '#B68353',
14
- '#61AFEF',
15
- '#C678DD',
16
- '#56B6C2',
17
- '#CCCCCC',
18
- '#616A7B',
19
- '#FE808A',
20
- '#C2DEAD',
21
- '#D1A47A',
22
- '#93CFFF',
23
- '#E0A8F1',
24
- '#82D2DC',
25
- '#FFFFFF',
26
- ],
27
- },
28
- {
29
- id: 'one-dark-pro',
30
- name: 'One Dark Pro',
31
- background: '#282C34',
32
- foreground: '#ABB2BF',
33
- cursor: '#528BFF',
34
- selectionBackground: '#41454E',
35
- palette: [
36
- '#3F4451',
37
- '#E05561',
38
- '#8CC265',
39
- '#D18F52',
40
- '#4AA5F0',
41
- '#C162DE',
42
- '#42B3C2',
43
- '#D7DAE0',
44
- '#4F5666',
45
- '#FF616E',
46
- '#A5E075',
47
- '#F0A45D',
48
- '#4DC4FF',
49
- '#DE73FF',
50
- '#4CD1E0',
51
- '#E6E6E6',
52
- ],
53
- },
54
- {
55
- id: 'dracula',
56
- name: 'Dracula',
57
- background: '#282A36',
58
- foreground: '#F8F8F2',
59
- cursor: '#F8F8F2',
60
- selectionBackground: '#44475A',
61
- palette: [
62
- '#21222C',
63
- '#FF5555',
64
- '#50FA7B',
65
- '#F1FA8C',
66
- '#BD93F9',
67
- '#FF79C6',
68
- '#8BE9FD',
69
- '#F8F8F2',
70
- '#6272A4',
71
- '#FF6E6E',
72
- '#69FF94',
73
- '#FFFFA5',
74
- '#D6ACFF',
75
- '#FF92DF',
76
- '#A4FFFF',
77
- '#FFFFFF',
78
- ],
79
- },
80
- {
81
- id: 'tokyo-night',
82
- name: 'Tokyo Night',
83
- background: '#1A1B26',
84
- foreground: '#C0CAF5',
85
- cursor: '#C0CAF5',
86
- selectionBackground: '#33467C',
87
- palette: [
88
- '#15161E',
89
- '#F7768E',
90
- '#9ECE6A',
91
- '#E0AF68',
92
- '#7AA2F7',
93
- '#BB9AF7',
94
- '#7DCFFF',
95
- '#A9B1D6',
96
- '#414868',
97
- '#F7768E',
98
- '#9ECE6A',
99
- '#E0AF68',
100
- '#7AA2F7',
101
- '#BB9AF7',
102
- '#7DCFFF',
103
- '#C0CAF5',
104
- ],
105
- },
106
- {
107
- id: 'catppuccin-mocha',
108
- name: 'Catppuccin Mocha',
109
- background: '#1E1E2E',
110
- foreground: '#CDD6F4',
111
- cursor: '#F5E0DC',
112
- selectionBackground: '#585B70',
113
- palette: [
114
- '#45475A',
115
- '#F38BA8',
116
- '#A6E3A1',
117
- '#F9E2AF',
118
- '#89B4FA',
119
- '#F5C2E7',
120
- '#94E2D5',
121
- '#BAC2DE',
122
- '#585B70',
123
- '#F38BA8',
124
- '#A6E3A1',
125
- '#F9E2AF',
126
- '#89B4FA',
127
- '#F5C2E7',
128
- '#94E2D5',
129
- '#A6ADC8',
130
- ],
131
- },
132
- {
133
- id: 'nord',
134
- name: 'Nord',
135
- background: '#2E3440',
136
- foreground: '#D8DEE9',
137
- cursor: '#D8DEE9',
138
- selectionBackground: '#434C5E',
139
- palette: [
140
- '#3B4252',
141
- '#BF616A',
142
- '#A3BE8C',
143
- '#EBCB8B',
144
- '#81A1C1',
145
- '#B48EAD',
146
- '#88C0D0',
147
- '#E5E9F0',
148
- '#4C566A',
149
- '#BF616A',
150
- '#A3BE8C',
151
- '#EBCB8B',
152
- '#81A1C1',
153
- '#B48EAD',
154
- '#8FBCBB',
155
- '#ECEFF4',
156
- ],
157
- },
158
- {
159
- id: 'gruvbox-dark',
160
- name: 'Gruvbox Dark',
161
- background: '#282828',
162
- foreground: '#EBDBB2',
163
- cursor: '#EBDBB2',
164
- selectionBackground: '#504945',
165
- palette: [
166
- '#282828',
167
- '#CC241D',
168
- '#98971A',
169
- '#D79921',
170
- '#458588',
171
- '#B16286',
172
- '#689D6A',
173
- '#A89984',
174
- '#928374',
175
- '#FB4934',
176
- '#B8BB26',
177
- '#FABD2F',
178
- '#83A598',
179
- '#D3869B',
180
- '#8EC07C',
181
- '#EBDBB2',
182
- ],
183
- },
184
- {
185
- id: 'solarized-dark',
186
- name: 'Solarized Dark',
187
- background: '#002B36',
188
- foreground: '#839496',
189
- cursor: '#839496',
190
- selectionBackground: '#073642',
191
- palette: [
192
- '#073642',
193
- '#DC322F',
194
- '#859900',
195
- '#B58900',
196
- '#268BD2',
197
- '#D33682',
198
- '#2AA198',
199
- '#EEE8D5',
200
- '#002B36',
201
- '#CB4B16',
202
- '#586E75',
203
- '#657B83',
204
- '#839496',
205
- '#6C71C4',
206
- '#93A1A1',
207
- '#FDF6E3',
208
- ],
209
- },
210
- {
211
- id: 'github-dark',
212
- name: 'GitHub Dark',
213
- background: '#0D1117',
214
- foreground: '#E6EDF3',
215
- cursor: '#E6EDF3',
216
- selectionBackground: '#264F78',
217
- palette: [
218
- '#484F58',
219
- '#FF7B72',
220
- '#3FB950',
221
- '#D29922',
222
- '#58A6FF',
223
- '#BC8CFF',
224
- '#39C5CF',
225
- '#B1BAC4',
226
- '#6E7681',
227
- '#FFA198',
228
- '#56D364',
229
- '#E3B341',
230
- '#79C0FF',
231
- '#D2A8FF',
232
- '#56D4DD',
233
- '#FFFFFF',
234
- ],
235
- },
236
- {
237
- id: 'rose-pine',
238
- name: 'Rosé Pine',
239
- background: '#191724',
240
- foreground: '#E0DEF4',
241
- cursor: '#E0DEF4',
242
- selectionBackground: '#403D52',
243
- palette: [
244
- '#26233A',
245
- '#EB6F92',
246
- '#31748F',
247
- '#F6C177',
248
- '#9CCFD8',
249
- '#C4A7E7',
250
- '#EBBCBA',
251
- '#E0DEF4',
252
- '#6E6A86',
253
- '#EB6F92',
254
- '#31748F',
255
- '#F6C177',
256
- '#9CCFD8',
257
- '#C4A7E7',
258
- '#EBBCBA',
259
- '#E0DEF4',
260
- ],
261
- },
262
- ];
@@ -1,65 +0,0 @@
1
- import { deleteSession, forkSession, getSessionMessages, listSessions, renameSession, } from '@anthropic-ai/claude-agent-sdk';
2
- import { projects } from './projects.js';
3
- import { runs } from './run.js';
4
- import { readJson, writeJson } from './storage.js';
5
- export async function sessions() {
6
- const marks = readMarks();
7
- const lists = await Promise.all(projects().map(async (project) => (await listSessions({
8
- dir: project.path,
9
- includeWorktrees: false,
10
- includeProgrammatic: false,
11
- })).map((item) => ({
12
- id: item.sessionId,
13
- title: item.summary,
14
- cwd: project.path,
15
- branch: item.gitBranch ?? null,
16
- updatedAt: item.lastModified,
17
- pinned: marks.pinned.includes(item.sessionId),
18
- archived: marks.archived.includes(item.sessionId),
19
- }))));
20
- return lists.flat();
21
- }
22
- export async function updateSession(id, patch) {
23
- if (patch.title !== undefined)
24
- await renameSession(id, patch.title);
25
- const marks = readMarks();
26
- if (patch.pinned !== undefined)
27
- marks.pinned = mark(marks.pinned, id, patch.pinned);
28
- if (patch.archived !== undefined)
29
- marks.archived = mark(marks.archived, id, patch.archived);
30
- writeMarks(marks);
31
- }
32
- export async function removeSession(id) {
33
- const run = runs.get(id);
34
- if (run !== undefined) {
35
- run.stop();
36
- await run.closed;
37
- }
38
- await deleteSession(id);
39
- const marks = readMarks();
40
- writeMarks({
41
- pinned: mark(marks.pinned, id, false),
42
- archived: mark(marks.archived, id, false),
43
- });
44
- }
45
- export async function fork(sessionId, cwd, messageId) {
46
- const disk = await getSessionMessages(sessionId, { dir: cwd });
47
- const index = disk.findIndex((item) => item.uuid === messageId);
48
- if (index < 0)
49
- throw new Error('Cannot fork the session at that point');
50
- const result = await forkSession(sessionId, {
51
- dir: cwd,
52
- upToMessageId: messageId,
53
- });
54
- return { sessionId: result.sessionId };
55
- }
56
- function readMarks() {
57
- return (readJson('sessions.json') ?? { pinned: [], archived: [] });
58
- }
59
- function writeMarks(marks) {
60
- writeJson('sessions.json', marks);
61
- }
62
- function mark(ids, id, on) {
63
- const rest = ids.filter((item) => item !== id);
64
- return on ? [...rest, id] : rest;
65
- }
@@ -1,149 +0,0 @@
1
- import { accounts, addAccount, capabilities, removeAccount, updateAccount, } from './claude.js';
2
- import { configInfo, readConfig, saveConfig } from './config.js';
3
- import { listFiles, saveUpload } from './files.js';
4
- import { commit, createPullRequest, gitStatus, push, suggestCommitMessage, workingDiff, } from './git.js';
5
- import { earlier } from './history.js';
6
- import { clients } from './hub.js';
7
- import { addProject, directories, projects, removeProject, updateProject, } from './projects.js';
8
- import { pushKey, subscribe, unsubscribe } from './push.js';
9
- import { activity, runs } from './run.js';
10
- import { open, rewind, send } from './runs.js';
11
- import { fork, removeSession, sessions, updateSession } from './sessions.js';
12
- import { listShells } from './terminal/process.js';
13
- import { busyTerminal, detachTerminal, savePastedImage, terminalInput, terminalRequest, } from './terminal/terminal.js';
14
- const handlers = {
15
- ping: () => null,
16
- 'config.get': () => configInfo(),
17
- 'config.save': (params) => saveConfig(params),
18
- 'projects.list': () => projects(),
19
- 'projects.add': (params) => addProject(params.path),
20
- 'projects.update': (params) => updateProject(params.path, params.patch),
21
- 'projects.remove': (params) => removeProject(params.path),
22
- 'directories.list': (params) => directories(params.path),
23
- 'sessions.list': () => sessions(),
24
- 'sessions.update': async (params) => {
25
- await updateSession(params.id, params.patch);
26
- return sessions();
27
- },
28
- 'sessions.remove': async (params) => {
29
- await removeSession(params.id);
30
- return sessions();
31
- },
32
- 'sessions.open': async (params, client) => {
33
- await open(client, params.sessionId, params.cwd);
34
- return null;
35
- },
36
- 'sessions.earlier': (params) => earlier(params.sessionId, params.cwd, params.before),
37
- 'sessions.send': async (params, client) => {
38
- await send(client, params);
39
- return null;
40
- },
41
- 'sessions.unqueue': (params) => {
42
- runs.get(params.sessionId)?.unqueue(params.id);
43
- return null;
44
- },
45
- 'sessions.interrupt': async (params) => {
46
- await runs.get(params.sessionId)?.query.interrupt();
47
- return null;
48
- },
49
- 'sessions.configure': async (params) => {
50
- await runs.get(params.sessionId)?.configure(params.settings);
51
- return null;
52
- },
53
- 'sessions.respond': (params) => {
54
- runs
55
- .get(params.sessionId)
56
- ?.respond(params.requestId, params.decision, params.answers);
57
- return null;
58
- },
59
- 'sessions.rewind': (params) => rewind(params),
60
- 'sessions.fork': (params) => fork(params.sessionId, params.cwd, params.messageId),
61
- 'accounts.list': () => accounts(),
62
- 'accounts.add': (params) => {
63
- addAccount(params.name, params.configDir);
64
- return accounts();
65
- },
66
- 'accounts.update': (params) => {
67
- updateAccount(params.id, params.name, params.configDir);
68
- return accounts();
69
- },
70
- 'accounts.remove': (params) => {
71
- removeAccount(params.id);
72
- return accounts();
73
- },
74
- capabilities: (params) => capabilities(params.accountId, params.cwd),
75
- 'files.list': (params) => listFiles(params.cwd),
76
- 'files.upload': (params) => saveUpload(params.name, Buffer.from(params.data, 'base64')),
77
- 'git.status': (params) => gitStatus(params.cwd),
78
- 'git.diff': (params) => workingDiff(params.cwd),
79
- 'git.commit': (params) => commit(params.cwd, params.message),
80
- 'git.push': (params) => push(params.cwd),
81
- 'git.pullRequest': (params) => createPullRequest(params.cwd),
82
- 'git.message': (params) => suggestCommitMessage(params.accountId, params.cwd),
83
- 'push.key': () => pushKey(),
84
- 'push.subscribe': (params) => {
85
- subscribe(params);
86
- return null;
87
- },
88
- 'push.unsubscribe': (params) => {
89
- unsubscribe(params.endpoint);
90
- return null;
91
- },
92
- terminal: async (params, client) => {
93
- await terminalRequest(client, params);
94
- return null;
95
- },
96
- 'terminal.shells': () => listShells(),
97
- 'terminal.busy': (params) => busyTerminal(params.id),
98
- 'terminal.paste': (params) => savePastedImage(params.type, Buffer.from(params.data, 'base64')),
99
- };
100
- export function connectClient(socket) {
101
- const client = {
102
- socket,
103
- heardAt: Date.now(),
104
- opening: null,
105
- sessionId: null,
106
- send: (message) => socket.send(JSON.stringify(message)),
107
- };
108
- clients.add(client);
109
- client.send({ type: 'activity', activity: activity() });
110
- client.send({ type: 'config', config: readConfig() });
111
- client.send({ type: 'projects', projects: projects() });
112
- socket.on('message', (data, isBinary) => {
113
- client.heardAt = Date.now();
114
- if (isBinary) {
115
- terminalInput(client, data);
116
- return;
117
- }
118
- void answer(client, String(data));
119
- });
120
- socket.on('error', (error) => console.warn(`a browser connection failed: ${error}`));
121
- socket.on('close', () => {
122
- clients.delete(client);
123
- detachTerminal(client);
124
- });
125
- }
126
- async function answer(client, text) {
127
- let call;
128
- try {
129
- call = JSON.parse(text);
130
- }
131
- catch (error) {
132
- console.warn(`ignoring a message that is not JSON: ${error}`);
133
- return;
134
- }
135
- try {
136
- if (!Object.hasOwn(handlers, call.method))
137
- throw new Error(`unknown method ${call.method}`);
138
- const handler = handlers[call.method];
139
- const result = await handler(call.params, client);
140
- client.send({ type: 'reply', id: call.id, result });
141
- }
142
- catch (error) {
143
- client.send({
144
- type: 'reply',
145
- id: call.id,
146
- error: error instanceof Error ? error.message : String(error),
147
- });
148
- }
149
- }
@@ -1,22 +0,0 @@
1
- import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
- import path from 'node:path';
3
- import { args } from './args.js';
4
- export const home = args.dir;
5
- export function readJson(name) {
6
- try {
7
- return JSON.parse(readFileSync(path.join(home, name), 'utf8'));
8
- }
9
- catch (error) {
10
- if (error.code === 'ENOENT')
11
- return null;
12
- throw error;
13
- }
14
- }
15
- export function writeJson(name, value) {
16
- const file = path.join(home, name);
17
- mkdirSync(home, { recursive: true });
18
- writeFileSync(`${file}.tmp`, `${JSON.stringify(value, null, 2)}\n`, {
19
- mode: 0o600,
20
- });
21
- renameSync(`${file}.tmp`, file);
22
- }
@@ -1,145 +0,0 @@
1
- export const ALERT_DELAY = 500;
2
- const BELL_GAP = 5000;
3
- const NOTIFICATION_GAP = 1000;
4
- const PAYLOAD_LIMIT = 1024;
5
- const ESC = 0x1b;
6
- const BEL = 0x07;
7
- const CAN = 0x18;
8
- const SUB = 0x1a;
9
- export class Scanner {
10
- title = '';
11
- state = 'ground';
12
- payload = [];
13
- scan(bytes) {
14
- let alert = null;
15
- let index = 0;
16
- while (index < bytes.length) {
17
- if (this.state === 'ground') {
18
- let offset = index;
19
- while (offset < bytes.length &&
20
- bytes[offset] !== ESC &&
21
- bytes[offset] !== BEL)
22
- offset++;
23
- if (offset === bytes.length)
24
- break;
25
- index = offset;
26
- }
27
- const found = this.step(bytes[index]);
28
- index++;
29
- if (found === null)
30
- continue;
31
- if (found.type === 'bell')
32
- alert ??= found;
33
- else
34
- alert = found;
35
- }
36
- return alert;
37
- }
38
- step(byte) {
39
- if (byte === CAN || byte === SUB) {
40
- this.state = 'ground';
41
- return null;
42
- }
43
- switch (this.state) {
44
- case 'ground':
45
- if (byte === ESC)
46
- this.state = 'escape';
47
- if (byte === BEL)
48
- return { type: 'bell' };
49
- return null;
50
- case 'escape':
51
- if (byte === 0x5d) {
52
- this.payload = [];
53
- this.state = 'osc';
54
- }
55
- else if ([0x50, 0x58, 0x5e, 0x5f].includes(byte))
56
- this.state = 'text';
57
- else if (byte !== ESC)
58
- this.state = 'ground';
59
- if (byte === BEL)
60
- return { type: 'bell' };
61
- return null;
62
- case 'osc':
63
- if (byte === BEL) {
64
- this.state = 'ground';
65
- return this.finish();
66
- }
67
- if (byte === ESC)
68
- this.state = 'oscEscape';
69
- else if (this.payload.length < PAYLOAD_LIMIT)
70
- this.payload.push(byte);
71
- return null;
72
- case 'oscEscape':
73
- if (byte === 0x5c) {
74
- this.state = 'ground';
75
- return this.finish();
76
- }
77
- this.state = 'escape';
78
- return this.step(byte);
79
- case 'text':
80
- if (byte === ESC)
81
- this.state = 'textEscape';
82
- return null;
83
- case 'textEscape':
84
- if (byte === 0x5c) {
85
- this.state = 'ground';
86
- return null;
87
- }
88
- this.state = 'escape';
89
- return this.step(byte);
90
- }
91
- }
92
- finish() {
93
- const text = Buffer.from(this.payload).toString('utf8');
94
- if (text.startsWith('0;') || text.startsWith('2;')) {
95
- this.title = text.slice(2);
96
- return null;
97
- }
98
- if (text.startsWith('9;')) {
99
- const body = text.slice(2);
100
- const digits = /^\d*/.exec(body)?.[0].length ?? 0;
101
- if (digits > 0 && (body.length === digits || body[digits] === ';'))
102
- return null;
103
- return { type: 'notification', title: '', body };
104
- }
105
- if (text.startsWith('777;notify;')) {
106
- const rest = text.slice('777;notify;'.length);
107
- const split = rest.indexOf(';');
108
- return split === -1
109
- ? { type: 'notification', title: rest, body: '' }
110
- : {
111
- type: 'notification',
112
- title: rest.slice(0, split),
113
- body: rest.slice(split + 1),
114
- };
115
- }
116
- return null;
117
- }
118
- }
119
- export class Alerts {
120
- pushedAt = null;
121
- bellPending = false;
122
- startBell() {
123
- if (this.bellPending || this.pushedRecently(BELL_GAP))
124
- return false;
125
- this.bellPending = true;
126
- return true;
127
- }
128
- finishBell() {
129
- if (!this.bellPending)
130
- return false;
131
- this.bellPending = false;
132
- this.pushedAt = Date.now();
133
- return true;
134
- }
135
- startNotification() {
136
- this.bellPending = false;
137
- if (this.pushedRecently(NOTIFICATION_GAP))
138
- return false;
139
- this.pushedAt = Date.now();
140
- return true;
141
- }
142
- pushedRecently(gap) {
143
- return this.pushedAt !== null && Date.now() - this.pushedAt < gap;
144
- }
145
- }