offsite 0.0.3 → 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-ji4UO7hp.js → angular-html-prQpjz7s.js} +1 -1
  5. package/apps/web/dist/assets/{angular-ts-CkobLhDa.js → angular-ts-BE4HJ5Uh.js} +1 -1
  6. package/apps/web/dist/assets/{apl-DAjPJTs4.js → apl-CJ-NIQ-7.js} +1 -1
  7. package/apps/web/dist/assets/{astro-DlwA-zmc.js → astro-CVkyXRVY.js} +1 -1
  8. package/apps/web/dist/assets/{blade-wTlHdbgB.js → blade-CQFMHse_.js} +1 -1
  9. package/apps/web/dist/assets/{c-HyCIpwKL.js → c-gqNWYRL8.js} +1 -1
  10. package/apps/web/dist/assets/{chapel-SOYLpFSa.js → chapel-CQ9_BV4j.js} +1 -1
  11. package/apps/web/dist/assets/{cobol-DlvLD04V.js → cobol-D-9v184m.js} +1 -1
  12. package/apps/web/dist/assets/{coffee-CGp5oJTY.js → coffee-BE0tIOLL.js} +1 -1
  13. package/apps/web/dist/assets/{cpp-CzmH13Nm.js → cpp-CzOLC-NF.js} +1 -1
  14. package/apps/web/dist/assets/{crystal-zS14MbR_.js → crystal-f1GcBNi_.js} +1 -1
  15. package/apps/web/dist/assets/{css-DQEQn59R.js → css-DlqRAumc.js} +1 -1
  16. package/apps/web/dist/assets/{edge-Bkv0KzZU.js → edge-DQkkPJaW.js} +1 -1
  17. package/apps/web/dist/assets/{elixir-B8tse0js.js → elixir-ClG78o74.js} +1 -1
  18. package/apps/web/dist/assets/{elm-F2InAxd7.js → elm-DZDmCmuw.js} +1 -1
  19. package/apps/web/dist/assets/{erb-CAIamwOm.js → erb-B1mu0-DN.js} +1 -1
  20. package/apps/web/dist/assets/{git-rebase-U0z47rUi.js → git-rebase-x1gs-rK2.js} +1 -1
  21. package/apps/web/dist/assets/{glimmer-js-Bg_zPoN-.js → glimmer-js-Cjos1igW.js} +1 -1
  22. package/apps/web/dist/assets/{glimmer-ts-v3suqAPH.js → glimmer-ts-CrR-PFvn.js} +1 -1
  23. package/apps/web/dist/assets/{glsl-8io-Pcmd.js → glsl-DR0G8e99.js} +1 -1
  24. package/apps/web/dist/assets/{graphql-B_q9cV-C.js → graphql-DKmrBZt7.js} +1 -1
  25. package/apps/web/dist/assets/{hack-DosfNWDX.js → hack-Brs_j9Xv.js} +1 -1
  26. package/apps/web/dist/assets/{haml-DcBtkGn5.js → haml-8Lc-lF96.js} +1 -1
  27. package/apps/web/dist/assets/{handlebars-2F0KxPFu.js → handlebars-Ds8WdPdv.js} +1 -1
  28. package/apps/web/dist/assets/{html-DrWZZyp3.js → html-C0gvYDho.js} +1 -1
  29. package/apps/web/dist/assets/{html-derivative-BaV8vDp-.js → html-derivative-CU9dkErg.js} +1 -1
  30. package/apps/web/dist/assets/{http-Dwo7FxJA.js → http-BE0w0Fty.js} +1 -1
  31. package/apps/web/dist/assets/{hurl-9r6SjmMP.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-CAkt7S2h.js → java-PSSQ0YmM.js} +1 -1
  35. package/apps/web/dist/assets/{javascript-CMo8GEjU.js → javascript-Ci3r4rzs.js} +1 -1
  36. package/apps/web/dist/assets/{jinja-XhRt7Tzv.js → jinja-lLTko9Wl.js} +1 -1
  37. package/apps/web/dist/assets/{jison-BXZQEb4C.js → jison-1BpHD5UK.js} +1 -1
  38. package/apps/web/dist/assets/{json-SyJDQmRp.js → json-BAUn76M4.js} +1 -1
  39. package/apps/web/dist/assets/{jsx-B76-zKzH.js → jsx-B8sFp1vz.js} +1 -1
  40. package/apps/web/dist/assets/{julia-Ca5lbuMA.js → julia-C4TZ4EL9.js} +1 -1
  41. package/apps/web/dist/assets/{just-CDt2RojJ.js → just-D5qIrqkp.js} +1 -1
  42. package/apps/web/dist/assets/{latex-D9bybvWo.js → latex-BL7XYxFg.js} +1 -1
  43. package/apps/web/dist/assets/{liquid-DMp-tByG.js → liquid-DBx9Hq7B.js} +1 -1
  44. package/apps/web/dist/assets/{lua-zNnfh_4o.js → lua-BqjicQyd.js} +1 -1
  45. package/apps/web/dist/assets/{marko-Ce5B11L0.js → marko-CHgy7yaY.js} +1 -1
  46. package/apps/web/dist/assets/{mdc-Btapt9E8.js → mdc-DOloBwb8.js} +1 -1
  47. package/apps/web/dist/assets/{nginx-Bzjverzh.js → nginx-g7I1HPwV.js} +1 -1
  48. package/apps/web/dist/assets/{nim-D6zpNhUX.js → nim-O6zJV1LD.js} +1 -1
  49. package/apps/web/dist/assets/{org-DTy-FvFD.js → org-HLg4-757.js} +1 -1
  50. package/apps/web/dist/assets/{perl-BV8Dxusy.js → perl-B3cDKTai.js} +1 -1
  51. package/apps/web/dist/assets/{php-BjkIa26S.js → php-2eDApoU3.js} +1 -1
  52. package/apps/web/dist/assets/{pug-DdfmTHk6.js → pug-itzGn-nK.js} +1 -1
  53. package/apps/web/dist/assets/{qml-BWLYImhB.js → qml-sU0VtUmf.js} +1 -1
  54. package/apps/web/dist/assets/{r-CKc9klse.js → r-C6mhPqgr.js} +1 -1
  55. package/apps/web/dist/assets/{razor-YcF2a59Y.js → razor-CSzRtbW7.js} +1 -1
  56. package/apps/web/dist/assets/{regexp-D3esVJ1X.js → regexp-BmdBJRV9.js} +1 -1
  57. package/apps/web/dist/assets/{rst-DVaj4AQD.js → rst-BRxUd6sp.js} +1 -1
  58. package/apps/web/dist/assets/{ruby-DBJQEVev.js → ruby-CQHHOfmX.js} +1 -1
  59. package/apps/web/dist/assets/{sas-NSuLkGD1.js → sas-DlaL8b25.js} +1 -1
  60. package/apps/web/dist/assets/{scss-TMy8m-so.js → scss-Cc71ABWp.js} +1 -1
  61. package/apps/web/dist/assets/{shellscript-BVuIsFkY.js → shellscript-CzA_LIIm.js} +1 -1
  62. package/apps/web/dist/assets/{shellsession-CV7MHIu6.js → shellsession-DESJlgp3.js} +1 -1
  63. package/apps/web/dist/assets/{soy-DDY0EoKE.js → soy-Nkvq88YN.js} +1 -1
  64. package/apps/web/dist/assets/{sql-CoZqqtiv.js → sql-CtPxrO7T.js} +1 -1
  65. package/apps/web/dist/assets/{stata-B8C1noIb.js → stata-BacEfVTr.js} +1 -1
  66. package/apps/web/dist/assets/{surrealql-BYiUJt-V.js → surrealql-CYW10JNe.js} +1 -1
  67. package/apps/web/dist/assets/{svelte-DGeZ8dPs.js → svelte-D3_tCKGs.js} +1 -1
  68. package/apps/web/dist/assets/{templ-Dn21SE_C.js → templ-BGKIfY_b.js} +1 -1
  69. package/apps/web/dist/assets/{tex-Da9GBCsM.js → tex-BkkYOaXX.js} +1 -1
  70. package/apps/web/dist/assets/{ts-tags-BuL1T6K3.js → ts-tags-B02tnbpZ.js} +1 -1
  71. package/apps/web/dist/assets/{tsx-DiLCnfgl.js → tsx-D3MB1IUf.js} +1 -1
  72. package/apps/web/dist/assets/{twig-Cx1peiH-.js → twig-CPhw2wGK.js} +1 -1
  73. package/apps/web/dist/assets/{typescript-pVxvHJ4R.js → typescript-B7U4faGm.js} +1 -1
  74. package/apps/web/dist/assets/{typst-CJQbitzj.js → typst-CN9EZswy.js} +1 -1
  75. package/apps/web/dist/assets/{vue-CXKyVnbB.js → vue-YH8dfjo_.js} +1 -1
  76. package/apps/web/dist/assets/{vue-html-AQjnBMTh.js → vue-html-NwX2xzgp.js} +1 -1
  77. package/apps/web/dist/assets/{vue-vine-DYxt9AbK.js → vue-vine-DoRmnjLj.js} +1 -1
  78. package/apps/web/dist/assets/{xml-CEJ01uJ1.js → xml-DgfgLpPc.js} +1 -1
  79. package/apps/web/dist/assets/{xsl-CULFBy6v.js → xsl-CEwQRUK_.js} +1 -1
  80. package/apps/web/dist/assets/{yaml-BNf68xM_.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 +5 -1
  86. package/apps/server/dist/args.js +0 -11
  87. package/apps/server/dist/claude.js +0 -245
  88. package/apps/server/dist/config.js +0 -191
  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 -70
  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 -99
  103. package/apps/server/dist/socket.js +0 -193
  104. package/apps/server/dist/storage.js +0 -71
  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-CIBt6t2M.css +0 -2
  111. package/apps/web/dist/assets/index-CPpMMYyZ.js +0 -902
  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,99 +0,0 @@
1
- import { watch } from 'node:fs';
2
- import path from 'node:path';
3
- import { deleteSession, forkSession, getSessionMessages, listSessions, renameSession, } from '@anthropic-ai/claude-agent-sdk';
4
- import { readConfig } from './config.js';
5
- import { broadcast } from './hub.js';
6
- import { projects } from './projects.js';
7
- import { runs } from './run.js';
8
- import { readJson, writeJson } from './storage.js';
9
- let watcher = null;
10
- let timer;
11
- export async function sessions() {
12
- const marks = readMarks();
13
- const lists = await Promise.all(projects().map(async (project) => (await listSessions({
14
- dir: project.path,
15
- includeWorktrees: false,
16
- includeProgrammatic: false,
17
- })).map((item) => ({
18
- id: item.sessionId,
19
- title: item.summary,
20
- cwd: project.path,
21
- branch: item.gitBranch ?? null,
22
- updatedAt: item.lastModified,
23
- pinned: marks.pinned.includes(item.sessionId),
24
- archived: marks.archived.includes(item.sessionId),
25
- }))));
26
- return lists.flat();
27
- }
28
- export async function publishSessions() {
29
- try {
30
- broadcast({ type: 'sessions', sessions: await sessions() });
31
- }
32
- catch (error) {
33
- console.warn(`could not list threads: ${error}`);
34
- }
35
- }
36
- export function watchSessions() {
37
- watcher?.close();
38
- watcher = null;
39
- const dir = path.join(readConfig().claudeBaseDir, 'projects');
40
- try {
41
- watcher = watch(dir, { recursive: true }, () => {
42
- timer ??= setTimeout(() => {
43
- timer = undefined;
44
- void publishSessions();
45
- }, 1000);
46
- });
47
- }
48
- catch (error) {
49
- if (error.code !== 'ENOENT')
50
- throw error;
51
- console.warn(`${dir} does not exist; threads changed outside offsite will not show`);
52
- return;
53
- }
54
- watcher.on('error', (error) => console.warn(`stopped watching ${dir}: ${error}`));
55
- }
56
- export async function updateSession(id, patch) {
57
- if (patch.title !== undefined)
58
- await renameSession(id, patch.title);
59
- const marks = readMarks();
60
- if (patch.pinned !== undefined)
61
- marks.pinned = mark(marks.pinned, id, patch.pinned);
62
- if (patch.archived !== undefined)
63
- marks.archived = mark(marks.archived, id, patch.archived);
64
- writeMarks(marks);
65
- }
66
- export async function removeSession(id) {
67
- const run = runs.get(id);
68
- if (run !== undefined) {
69
- run.stop();
70
- await run.closed;
71
- }
72
- await deleteSession(id);
73
- const marks = readMarks();
74
- writeMarks({
75
- pinned: mark(marks.pinned, id, false),
76
- archived: mark(marks.archived, id, false),
77
- });
78
- }
79
- export async function fork(sessionId, cwd, messageId) {
80
- const disk = await getSessionMessages(sessionId, { dir: cwd });
81
- const index = disk.findIndex((item) => item.uuid === messageId);
82
- if (index < 0)
83
- throw new Error('Cannot fork the session at that point');
84
- const result = await forkSession(sessionId, {
85
- dir: cwd,
86
- upToMessageId: messageId,
87
- });
88
- return { sessionId: result.sessionId };
89
- }
90
- function readMarks() {
91
- return (readJson('sessions.json') ?? { pinned: [], archived: [] });
92
- }
93
- function writeMarks(marks) {
94
- writeJson('sessions.json', marks);
95
- }
96
- function mark(ids, id, on) {
97
- const rest = ids.filter((item) => item !== id);
98
- return on ? [...rest, id] : rest;
99
- }
@@ -1,193 +0,0 @@
1
- import { accounts, addAccount, capabilities, linkAccount, publishAccounts, 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, publishSessions, removeSession, sessions, updateSession, watchSessions, } 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
- sync: async () => ({
17
- ...configInfo(),
18
- projects: projects(),
19
- sessions: await sessions(),
20
- activity: activity(),
21
- }),
22
- 'config.get': () => configInfo(),
23
- 'config.save': (params) => {
24
- const before = readConfig().claudeBaseDir;
25
- const saved = saveConfig(params);
26
- if (saved.claudeBaseDir === before)
27
- return saved;
28
- watchSessions();
29
- void publishSessions();
30
- void publishAccounts();
31
- return saved;
32
- },
33
- 'projects.add': async (params) => {
34
- const project = await addProject(params.path);
35
- void publishSessions();
36
- return project;
37
- },
38
- 'projects.update': (params) => updateProject(params.path, params.patch),
39
- 'projects.remove': (params) => {
40
- removeProject(params.path);
41
- void publishSessions();
42
- return null;
43
- },
44
- 'directories.list': (params) => directories(params.path),
45
- 'sessions.update': async (params) => {
46
- try {
47
- await updateSession(params.id, params.patch);
48
- }
49
- finally {
50
- void publishSessions();
51
- }
52
- return null;
53
- },
54
- 'sessions.remove': async (params) => {
55
- try {
56
- await removeSession(params.id);
57
- }
58
- finally {
59
- void publishSessions();
60
- }
61
- return null;
62
- },
63
- 'sessions.open': async (params, client) => {
64
- await open(client, params.sessionId, params.cwd);
65
- return null;
66
- },
67
- 'sessions.earlier': (params) => earlier(params.sessionId, params.cwd, params.before),
68
- 'sessions.send': async (params, client) => {
69
- await send(client, params);
70
- return null;
71
- },
72
- 'sessions.unqueue': (params) => {
73
- runs.get(params.sessionId)?.unqueue(params.id);
74
- return null;
75
- },
76
- 'sessions.interrupt': async (params) => {
77
- await runs.get(params.sessionId)?.query.interrupt();
78
- return null;
79
- },
80
- 'sessions.configure': async (params) => {
81
- await runs.get(params.sessionId)?.configure(params.settings);
82
- return null;
83
- },
84
- 'sessions.respond': (params) => {
85
- runs
86
- .get(params.sessionId)
87
- ?.respond(params.requestId, params.decision, params.answers);
88
- return null;
89
- },
90
- 'sessions.rewind': (params) => rewind(params),
91
- 'sessions.fork': async (params) => {
92
- const result = await fork(params.sessionId, params.cwd, params.messageId);
93
- void publishSessions();
94
- return result;
95
- },
96
- 'accounts.list': () => accounts(),
97
- 'accounts.add': (params) => {
98
- addAccount(params.name, params.configDir);
99
- void publishAccounts();
100
- return null;
101
- },
102
- 'accounts.update': (params) => {
103
- updateAccount(params.id, params.name, params.configDir);
104
- void publishAccounts();
105
- return null;
106
- },
107
- 'accounts.remove': (params) => {
108
- removeAccount(params.id);
109
- void publishAccounts();
110
- return null;
111
- },
112
- 'accounts.link': async (params) => {
113
- await linkAccount(params.id);
114
- void publishAccounts();
115
- return null;
116
- },
117
- capabilities: (params) => capabilities(params.accountId, params.cwd),
118
- 'files.list': (params) => listFiles(params.cwd),
119
- 'files.upload': (params) => saveUpload(params.name, Buffer.from(params.data, 'base64')),
120
- 'git.status': (params) => gitStatus(params.cwd),
121
- 'git.diff': (params) => workingDiff(params.cwd),
122
- 'git.commit': (params) => commit(params.cwd, params.message),
123
- 'git.push': (params) => push(params.cwd),
124
- 'git.pullRequest': (params) => createPullRequest(params.cwd),
125
- 'git.message': (params) => suggestCommitMessage(params.accountId, params.cwd),
126
- 'push.key': () => pushKey(),
127
- 'push.subscribe': (params) => {
128
- subscribe(params);
129
- return null;
130
- },
131
- 'push.unsubscribe': (params) => {
132
- unsubscribe(params.endpoint);
133
- return null;
134
- },
135
- terminal: async (params, client) => {
136
- await terminalRequest(client, params);
137
- return null;
138
- },
139
- 'terminal.shells': () => listShells(),
140
- 'terminal.busy': (params) => busyTerminal(params.id),
141
- 'terminal.paste': (params) => savePastedImage(params.type, Buffer.from(params.data, 'base64')),
142
- debug: (params) => {
143
- console.log(`[paste-debug] ${params.line}`);
144
- return null;
145
- },
146
- };
147
- export function connectClient(socket) {
148
- const client = {
149
- socket,
150
- heardAt: Date.now(),
151
- opening: null,
152
- sessionId: null,
153
- send: (message) => socket.send(JSON.stringify(message)),
154
- };
155
- clients.add(client);
156
- socket.on('message', (data, isBinary) => {
157
- client.heardAt = Date.now();
158
- if (isBinary) {
159
- terminalInput(client, data);
160
- return;
161
- }
162
- void answer(client, String(data));
163
- });
164
- socket.on('error', (error) => console.warn(`a browser connection failed: ${error}`));
165
- socket.on('close', () => {
166
- clients.delete(client);
167
- detachTerminal(client);
168
- });
169
- }
170
- async function answer(client, text) {
171
- let call;
172
- try {
173
- call = JSON.parse(text);
174
- }
175
- catch (error) {
176
- console.warn(`ignoring a message that is not JSON: ${error}`);
177
- return;
178
- }
179
- try {
180
- if (!Object.hasOwn(handlers, call.method))
181
- throw new Error(`unknown method ${call.method}`);
182
- const handler = handlers[call.method];
183
- const result = await handler(call.params, client);
184
- client.send({ type: 'reply', id: call.id, result });
185
- }
186
- catch (error) {
187
- client.send({
188
- type: 'reply',
189
- id: call.id,
190
- error: error instanceof Error ? error.message : String(error),
191
- });
192
- }
193
- }
@@ -1,71 +0,0 @@
1
- import { mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from 'node:fs';
2
- import path from 'node:path';
3
- import { consola } from 'consola';
4
- import { args } from './args.js';
5
- export const home = args.dir;
6
- const lockFile = path.join(home, 'server.pid');
7
- mkdirSync(home, { recursive: true });
8
- lock();
9
- process.on('exit', () => unlinkSync(lockFile));
10
- function lock() {
11
- try {
12
- writeFileSync(lockFile, `${process.pid}\n`, { flag: 'wx' });
13
- return;
14
- }
15
- catch (error) {
16
- if (!hasCode(error, 'EEXIST'))
17
- throw error;
18
- }
19
- let content;
20
- try {
21
- content = readFileSync(lockFile, 'utf8');
22
- }
23
- catch (error) {
24
- if (hasCode(error, 'ENOENT'))
25
- return lock();
26
- throw error;
27
- }
28
- const pid = Number(content);
29
- if (!Number.isInteger(pid) || pid < 1)
30
- throw new Error(`invalid pid ${JSON.stringify(content)} in ${lockFile}`);
31
- if (pid !== process.pid && isRunning(pid)) {
32
- consola.error(`offsite is already running for ${home} (pid ${pid})`);
33
- process.exit(1);
34
- }
35
- unlinkSync(lockFile);
36
- lock();
37
- }
38
- function isRunning(pid) {
39
- try {
40
- process.kill(pid, 0);
41
- return true;
42
- }
43
- catch (error) {
44
- if (hasCode(error, 'ESRCH'))
45
- return false;
46
- if (hasCode(error, 'EPERM'))
47
- return true;
48
- throw error;
49
- }
50
- }
51
- function hasCode(error, code) {
52
- return error instanceof Error && 'code' in error && error.code === code;
53
- }
54
- export function readJson(name) {
55
- try {
56
- return JSON.parse(readFileSync(path.join(home, name), 'utf8'));
57
- }
58
- catch (error) {
59
- if (error.code === 'ENOENT')
60
- return null;
61
- throw error;
62
- }
63
- }
64
- export function writeJson(name, value) {
65
- const file = path.join(home, name);
66
- mkdirSync(home, { recursive: true });
67
- writeFileSync(`${file}.tmp`, `${JSON.stringify(value, null, 2)}\n`, {
68
- mode: 0o600,
69
- });
70
- renameSync(`${file}.tmp`, file);
71
- }