@mirrowel/opencode-openshare 0.0.0-stage → 0.1.1

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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +181 -2
  3. package/ci/README.md +56 -0
  4. package/ci/openshare.config.json +10 -0
  5. package/ci/openshare.js +2270 -0
  6. package/dist/commands.d.ts +7 -0
  7. package/dist/commands.js +440 -0
  8. package/dist/config.d.ts +138 -0
  9. package/dist/config.js +524 -0
  10. package/dist/core.d.ts +117 -0
  11. package/dist/core.js +1944 -0
  12. package/dist/dialogs.d.ts +94 -0
  13. package/dist/dialogs.js +725 -0
  14. package/dist/server.d.ts +64 -0
  15. package/dist/server.js +30 -0
  16. package/dist/settings.d.ts +24 -0
  17. package/dist/settings.js +1226 -0
  18. package/dist/share-flow.d.ts +287 -0
  19. package/dist/share-flow.js +516 -0
  20. package/dist/sidebar.d.ts +19 -0
  21. package/dist/sidebar.js +144 -0
  22. package/dist/tui-host.d.ts +158 -0
  23. package/dist/tui-host.js +6 -0
  24. package/dist/tui.d.ts +17 -0
  25. package/dist/tui.js +4719 -0
  26. package/dist/ui-prefs.d.ts +16 -0
  27. package/dist/ui-prefs.js +27 -0
  28. package/dist/v2-server.d.ts +81 -0
  29. package/dist/v2-server.js +402 -0
  30. package/dist/v2-tui.d.ts +24 -0
  31. package/dist/v2-tui.js +313 -0
  32. package/dist/v2-types.d.ts +134 -0
  33. package/dist/v2-types.js +8 -0
  34. package/openshare.config.json +16 -0
  35. package/package.json +98 -4
  36. package/src/banner.txt +25 -0
  37. package/src/commands.ts +452 -0
  38. package/src/config.ts +524 -0
  39. package/src/core.ts +1997 -0
  40. package/src/dialogs.tsx +971 -0
  41. package/src/server.ts +47 -0
  42. package/src/settings.ts +1239 -0
  43. package/src/share-flow.ts +551 -0
  44. package/src/sidebar.tsx +187 -0
  45. package/src/tui-host.ts +134 -0
  46. package/src/tui.tsx +318 -0
  47. package/src/ui-prefs.ts +36 -0
  48. package/src/v2-server.ts +438 -0
  49. package/src/v2-tui.ts +315 -0
  50. package/src/v2-types.ts +102 -0
  51. package/tsconfig.json +18 -0
@@ -0,0 +1,287 @@
1
+ import { saveServerEntry, deleteServerEntry, type ShareConfig, type ServerEntry } from "./config.js";
2
+ import type { ClientApi, SessionInfo, SessionOpts } from "./core.js";
3
+ import type { ShareHostApi } from "./tui-host.js";
4
+ export type SessionBinding = {
5
+ id: string;
6
+ secret: string;
7
+ rev: number;
8
+ url: string;
9
+ enabled?: boolean;
10
+ opts?: SessionOpts;
11
+ };
12
+ export declare const CONSENT_KV_KEY = "openshare_consent";
13
+ export declare function pluginConfigPaths(baseDir?: string): string[];
14
+ export declare function currentConfig(baseDir?: string): ShareConfig;
15
+ /** Writes the config file. Target rule (owner-directed): the global
16
+ * settings home by default, or an explicit existing file chosen in the
17
+ * TUI — NEVER "first existing in the read chain" (that wrote TUI edits
18
+ * into the tracked adjacent template, live-caught). $comment and foreign
19
+ * keys preserved. */
20
+ export declare function saveConfig(cfg: ShareConfig, target?: string, baseDir?: string): {
21
+ path: string;
22
+ } | undefined;
23
+ export declare function isConfigured(cfg: ShareConfig): boolean;
24
+ /** The resolved active server (url + entry), for the TUI server rows. */
25
+ export declare function activeServer(cfg?: ShareConfig): {
26
+ url: string;
27
+ token: string;
28
+ entry: ServerEntry;
29
+ } | undefined;
30
+ export declare function serverEntries(cfg?: ShareConfig): Array<{
31
+ url: string;
32
+ entry: ServerEntry;
33
+ active: boolean;
34
+ }>;
35
+ export { saveServerEntry, deleteServerEntry };
36
+ /** All live per-server bindings from a v2 (or legacy v1) metadata record. */
37
+ export declare function bindingsOf(info: SessionInfo | undefined): Array<SessionBinding & {
38
+ server: string;
39
+ collided?: string;
40
+ }>;
41
+ /** Read every live binding for a session (fan-out aware). */
42
+ export declare function readBindings(client: ClientApi | undefined, sid: string): Promise<Array<SessionBinding & {
43
+ server: string;
44
+ collided?: string;
45
+ }>>;
46
+ export declare function hostOf(url: string): string;
47
+ /** Mutate metadata.openshare.servers[url] through a patcher (TUI per-
48
+ * server actions: opt-out entries, collision resolution). Reads-modifies-
49
+ * writes the whole metadata to keep foreign keys intact. */
50
+ export declare function patchSessionBinding(client: ClientApi | undefined, sid: string, mutator: (servers: Record<string, unknown>, binding: Record<string, unknown>) => void): Promise<boolean>;
51
+ /** The display/primary binding: the active server's entry when bound
52
+ * there, else the first live entry (single-server configs are unchanged). */
53
+ export declare function bindingOf(info: SessionInfo | undefined): SessionBinding | undefined;
54
+ /** Walks parentID up to the root session (the share owns the whole tree). */
55
+ export declare function resolveRoot(client: ClientApi | undefined, sid: string): Promise<string>;
56
+ export declare function readBinding(client: ClientApi | undefined, sid: string): Promise<SessionBinding | undefined>;
57
+ /** Sets metadata.openshare = { ...existing(v2 structure preserved),
58
+ * enabled: true, opts? }. The per-server binding entries are the ENGINE's
59
+ * to manage; the flag just opts the session in. */
60
+ export declare function setShareFlag(client: ClientApi | undefined, sid: string, opts?: SessionOpts): Promise<boolean>;
61
+ export declare function clearShareFlag(client: ClientApi | undefined, sid: string): Promise<boolean>;
62
+ export declare function workerDeleteShare(workerUrl: string, id: string, secret: string): Promise<boolean>;
63
+ /** Health probe for the settings dialog's connection test. */
64
+ export declare function probeWorker(workerUrl: string): Promise<{
65
+ ok: boolean;
66
+ detail: string;
67
+ }>;
68
+ /** Share liveness probe — the "session says shared but the link is dead"
69
+ * case (purged, TTL-expired, or deleted while the binding stayed in
70
+ * session metadata). GET /data answers 404 {status:"gone"} BEFORE the
71
+ * read-auth gate, so this is a credential-free existence check that
72
+ * works identically on the CF worker and the Bun server. Network errors
73
+ * return "unknown" — never auto-disable on unknown. */
74
+ export declare function verifyShare(workerUrl: string, shareId: string): Promise<"live" | "gone" | "unknown">;
75
+ /** Remove the binding entries for shares that no longer exist server-side
76
+ * (the auto-disable half of gone detection). Entries are deleted outright —
77
+ * not optedOut — so a later prompt in the session can create a fresh share. */
78
+ export declare function clearGoneBindingEntries(host: ShareHostApi, root: string, servers: string[]): Promise<boolean>;
79
+ export declare function normServerUrl(url: string): string;
80
+ /** /health probe including the auth mode (public enrolls anyone). */
81
+ export declare function probeAuthMode(workerUrl: string): Promise<{
82
+ ok: boolean;
83
+ mode?: "public" | "private";
84
+ detail: string;
85
+ }>;
86
+ export declare function enrollAtServer(workerUrl: string, code: string): Promise<{
87
+ ok: boolean;
88
+ token?: string;
89
+ userId?: string;
90
+ label?: string;
91
+ error?: string;
92
+ }>;
93
+ export declare function rotateAtServer(workerUrl: string, token: string): Promise<{
94
+ ok: boolean;
95
+ token?: string;
96
+ error?: string;
97
+ }>;
98
+ export declare function disconnectAtServer(workerUrl: string, token: string): Promise<{
99
+ ok: boolean;
100
+ error?: string;
101
+ }>;
102
+ export type AdminUser = {
103
+ id: string;
104
+ label: string;
105
+ createdAt: number;
106
+ frozen: boolean;
107
+ shares: number;
108
+ tokens: number;
109
+ tokensActive: number;
110
+ };
111
+ export type AdminToken = {
112
+ id: string;
113
+ userId: string;
114
+ label: string;
115
+ limits: Record<string, number>;
116
+ createdAt: number;
117
+ lastUsedAt: number;
118
+ expiresAt: number;
119
+ revoked: boolean;
120
+ };
121
+ export type AdminCode = {
122
+ id: string;
123
+ label: string;
124
+ activationsLeft: number;
125
+ used: number;
126
+ createdAt: number;
127
+ expiresAt: number;
128
+ disabled: boolean;
129
+ };
130
+ export type AdminShare = {
131
+ id: string;
132
+ createdAt: number;
133
+ sessionID?: string;
134
+ ownerId?: string | null;
135
+ };
136
+ /** Thin typed client for the worker's /api/admin surface. `token` must be
137
+ * the server's root CREATE_TOKEN (user osk_ tokens get 403). */
138
+ export declare function adminClient(workerUrl: string, token: string): {
139
+ users: () => Promise<{
140
+ ok: boolean;
141
+ status: number;
142
+ data?: {
143
+ users: AdminUser[];
144
+ } | undefined;
145
+ error?: string;
146
+ }>;
147
+ createUser: (label: string) => Promise<{
148
+ ok: boolean;
149
+ status: number;
150
+ data?: {
151
+ userId: string;
152
+ label: string;
153
+ } | undefined;
154
+ error?: string;
155
+ }>;
156
+ freeze: (userId: string) => Promise<{
157
+ ok: boolean;
158
+ status: number;
159
+ data?: {
160
+ frozen: boolean;
161
+ shares: number;
162
+ } | undefined;
163
+ error?: string;
164
+ }>;
165
+ unfreeze: (userId: string) => Promise<{
166
+ ok: boolean;
167
+ status: number;
168
+ data?: {
169
+ frozen: boolean;
170
+ shares: number;
171
+ } | undefined;
172
+ error?: string;
173
+ }>;
174
+ deleteUser: (userId: string, mode: "freeze" | "delete") => Promise<{
175
+ ok: boolean;
176
+ status: number;
177
+ data?: {
178
+ mode: string;
179
+ shares: number;
180
+ } | undefined;
181
+ error?: string;
182
+ }>;
183
+ tokens: () => Promise<{
184
+ ok: boolean;
185
+ status: number;
186
+ data?: {
187
+ tokens: AdminToken[];
188
+ } | undefined;
189
+ error?: string;
190
+ }>;
191
+ mintToken: (userId: string, label?: string, limits?: Record<string, number>) => Promise<{
192
+ ok: boolean;
193
+ status: number;
194
+ data?: {
195
+ token: string;
196
+ id: string;
197
+ } | undefined;
198
+ error?: string;
199
+ }>;
200
+ revokeToken: (tokenId: string) => Promise<{
201
+ ok: boolean;
202
+ status: number;
203
+ data?: unknown;
204
+ error?: string;
205
+ }>;
206
+ codes: () => Promise<{
207
+ ok: boolean;
208
+ status: number;
209
+ data?: {
210
+ codes: AdminCode[];
211
+ } | undefined;
212
+ error?: string;
213
+ }>;
214
+ createCode: (label: string, activations: number) => Promise<{
215
+ ok: boolean;
216
+ status: number;
217
+ data?: {
218
+ code: string;
219
+ id: string;
220
+ activationsLeft: number;
221
+ } | undefined;
222
+ error?: string;
223
+ }>;
224
+ disableCode: (codeId: string) => Promise<{
225
+ ok: boolean;
226
+ status: number;
227
+ data?: unknown;
228
+ error?: string;
229
+ }>;
230
+ shares: () => Promise<{
231
+ ok: boolean;
232
+ status: number;
233
+ data?: {
234
+ shares: AdminShare[];
235
+ } | undefined;
236
+ error?: string;
237
+ }>;
238
+ deleteShare: (shareId: string) => Promise<{
239
+ ok: boolean;
240
+ status: number;
241
+ data?: unknown;
242
+ error?: string;
243
+ }>;
244
+ reassign: (shareId: string, userId: string) => Promise<{
245
+ ok: boolean;
246
+ status: number;
247
+ data?: unknown;
248
+ error?: string;
249
+ }>;
250
+ purge: () => Promise<{
251
+ ok: boolean;
252
+ status: number;
253
+ data?: {
254
+ removed: number;
255
+ } | undefined;
256
+ error?: string;
257
+ }>;
258
+ health: () => Promise<{
259
+ ok: boolean;
260
+ status: number;
261
+ data?: {
262
+ ok: boolean;
263
+ service: string;
264
+ policy: Record<string, unknown>;
265
+ auth: {
266
+ mode: string;
267
+ };
268
+ } | undefined;
269
+ error?: string;
270
+ }>;
271
+ };
272
+ /** Resolve the admin credential for a server: the entry's adminToken, the
273
+ * legacy createToken (when it points at this server), or prompt. */
274
+ export declare function adminTokenFor(url: string, cfg?: ShareConfig): string;
275
+ /** Waits for the server plugin to publish the binding URL (poll; robust on
276
+ * both hosts). Resolves the binding, or undefined on timeout. */
277
+ export declare function waitForBinding(client: ClientApi | undefined, sid: string, timeoutMs?: number): Promise<SessionBinding | undefined>;
278
+ export type FlowResult = {
279
+ ok: boolean;
280
+ message: string;
281
+ url?: string;
282
+ unconfigured?: boolean;
283
+ };
284
+ export declare function runShareFlow(host: ShareHostApi, sessionID: string | undefined): Promise<FlowResult>;
285
+ /** Post-consent share: set the flag, wait for the URL, copy it. */
286
+ export declare function confirmShare(host: ShareHostApi, rootSessionID: string): Promise<FlowResult>;
287
+ export declare function runUnshareFlow(host: ShareHostApi, sessionID: string | undefined): Promise<FlowResult>;