@ours.network/cli 0.1.0 → 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.
- package/README.md +49 -6
- package/dist/args.d.ts +1 -1
- package/dist/args.js +1 -1
- package/dist/{chunk-AXXFFER2.js → chunk-6NFATG6P.js} +2 -2
- package/dist/chunk-HNBWRI4O.js +399 -0
- package/dist/chunk-QRNZFPNJ.js +379 -0
- package/dist/chunk-YSHMCQ2B.js +174 -0
- package/dist/commands.d.ts +178 -0
- package/dist/commands.js +14 -0
- package/dist/help.d.ts +4 -0
- package/dist/help.js +15 -0
- package/dist/main.js +72 -97
- package/dist/operations.d.ts +203 -3
- package/dist/operations.js +8 -2
- package/package.json +1 -1
- package/dist/chunk-IUZOQT4D.js +0 -152
package/dist/operations.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import type { OursClient } from '@ours.network/sdk/client';
|
|
2
|
-
type FieldKind = 'string' | 'boolean' | 'integer' | 'string[]' | 'integer[]' | 'cursor';
|
|
3
|
-
interface FieldSpec {
|
|
2
|
+
export type FieldKind = 'string' | 'boolean' | 'integer' | 'string[]' | 'integer[]' | 'cursor';
|
|
3
|
+
export interface FieldSpec {
|
|
4
4
|
kind: FieldKind;
|
|
5
|
+
help: string;
|
|
6
|
+
valueName: string;
|
|
5
7
|
required?: boolean;
|
|
6
8
|
values?: readonly string[];
|
|
7
9
|
positive?: boolean;
|
|
10
|
+
allowEmpty?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface OperationSpec {
|
|
13
|
+
method: keyof OursClient;
|
|
14
|
+
fields: Readonly<Record<string, FieldSpec>>;
|
|
15
|
+
summary: string;
|
|
16
|
+
effects: string;
|
|
17
|
+
exampleInput?: Readonly<Record<string, unknown>>;
|
|
18
|
+
refine?: (input: Record<string, unknown>) => void;
|
|
8
19
|
}
|
|
9
20
|
export declare const OPERATION_SPECS: {
|
|
10
21
|
readonly 'create-identity': {
|
|
@@ -15,6 +26,14 @@ export declare const OPERATION_SPECS: {
|
|
|
15
26
|
readonly exposeLocal: FieldSpec;
|
|
16
27
|
readonly localAutoAccept: FieldSpec;
|
|
17
28
|
};
|
|
29
|
+
readonly summary: "Create a persistent identity and bind this CLI session to it.";
|
|
30
|
+
readonly effects: "Writes identity state. With a Human identity, the new identity becomes its role; otherwise the first persistent identity becomes the Human identity.";
|
|
31
|
+
readonly exampleInput: {
|
|
32
|
+
readonly name: "BuildBot";
|
|
33
|
+
readonly bio: "Build coordinator";
|
|
34
|
+
readonly exposeLocal: true;
|
|
35
|
+
readonly localAutoAccept: true;
|
|
36
|
+
};
|
|
18
37
|
};
|
|
19
38
|
readonly 'create-temporary-identity': {
|
|
20
39
|
readonly method: "createTemporaryIdentity";
|
|
@@ -24,12 +43,25 @@ export declare const OPERATION_SPECS: {
|
|
|
24
43
|
readonly exposeLocal: FieldSpec;
|
|
25
44
|
readonly localAutoAccept: FieldSpec;
|
|
26
45
|
};
|
|
46
|
+
readonly summary: "Create and bind a session-owned temporary identity.";
|
|
47
|
+
readonly effects: "Writes temporary identity state. Session teardown or lease release closes it, sends best-effort remove-me notices, and permanently deletes its local state.";
|
|
48
|
+
readonly exampleInput: {
|
|
49
|
+
readonly name: "ScratchBot";
|
|
50
|
+
readonly bio: "Short-lived test operator";
|
|
51
|
+
readonly exposeLocal: false;
|
|
52
|
+
readonly localAutoAccept: true;
|
|
53
|
+
};
|
|
27
54
|
};
|
|
28
55
|
readonly 'close-temporary-identity': {
|
|
29
56
|
readonly method: "closeTemporaryIdentityOp";
|
|
30
57
|
readonly fields: {
|
|
31
58
|
readonly name: FieldSpec;
|
|
32
59
|
};
|
|
60
|
+
readonly summary: "Close a temporary identity owned by this session, or reclaim one whose owner is stale.";
|
|
61
|
+
readonly effects: "Destructive: queues best-effort remove-me notices and permanently deletes local identity state. A live owner cannot be evicted.";
|
|
62
|
+
readonly exampleInput: {
|
|
63
|
+
readonly name: "ScratchBot";
|
|
64
|
+
};
|
|
33
65
|
};
|
|
34
66
|
readonly 'create-root-identity': {
|
|
35
67
|
readonly method: "createRootIdentity";
|
|
@@ -40,6 +72,15 @@ export declare const OPERATION_SPECS: {
|
|
|
40
72
|
readonly localAutoAccept: FieldSpec;
|
|
41
73
|
readonly skipIfRootExists: FieldSpec;
|
|
42
74
|
};
|
|
75
|
+
readonly summary: "Create the host Human identity and bind this CLI session to it.";
|
|
76
|
+
readonly effects: "Writes identity state and may adopt existing persistent identities as roles. If a Human identity already exists, a non-skipped creation becomes a role under it.";
|
|
77
|
+
readonly exampleInput: {
|
|
78
|
+
readonly name: "Alice@laptop";
|
|
79
|
+
readonly bio: "Alice on laptop";
|
|
80
|
+
readonly exposeLocal: true;
|
|
81
|
+
readonly localAutoAccept: true;
|
|
82
|
+
readonly skipIfRootExists: true;
|
|
83
|
+
};
|
|
43
84
|
};
|
|
44
85
|
readonly 'define-local-identity-file': {
|
|
45
86
|
readonly method: "defineLocalIdentityFile";
|
|
@@ -51,6 +92,16 @@ export declare const OPERATION_SPECS: {
|
|
|
51
92
|
readonly localAutoAccept: FieldSpec;
|
|
52
93
|
readonly overwrite: FieldSpec;
|
|
53
94
|
};
|
|
95
|
+
readonly summary: "Write an advisory .ours-identity workspace pin.";
|
|
96
|
+
readonly effects: "Writes only the workspace pin file. It does not create or bind an identity.";
|
|
97
|
+
readonly exampleInput: {
|
|
98
|
+
readonly name: "BuildBot";
|
|
99
|
+
readonly path: "/srv/project";
|
|
100
|
+
readonly force: false;
|
|
101
|
+
readonly exposeLocal: true;
|
|
102
|
+
readonly localAutoAccept: true;
|
|
103
|
+
readonly overwrite: false;
|
|
104
|
+
};
|
|
54
105
|
};
|
|
55
106
|
readonly 'choose-identity': {
|
|
56
107
|
readonly method: "chooseIdentity";
|
|
@@ -58,24 +109,41 @@ export declare const OPERATION_SPECS: {
|
|
|
58
109
|
readonly name: FieldSpec;
|
|
59
110
|
readonly force: FieldSpec;
|
|
60
111
|
};
|
|
112
|
+
readonly summary: "Bind an existing identity to this CLI lease.";
|
|
113
|
+
readonly effects: "Changes lease ownership. Force can evict another live session; temporary identities still enforce their session owner.";
|
|
114
|
+
readonly exampleInput: {
|
|
115
|
+
readonly name: "BuildBot";
|
|
116
|
+
readonly force: false;
|
|
117
|
+
};
|
|
61
118
|
};
|
|
62
119
|
readonly 'list-identities': {
|
|
63
120
|
readonly method: "listIdentities";
|
|
64
121
|
readonly fields: {};
|
|
122
|
+
readonly summary: "List identities, hierarchy, temporary ownership, and lease state.";
|
|
123
|
+
readonly effects: "Read-only.";
|
|
65
124
|
};
|
|
66
125
|
readonly 'current-identity': {
|
|
67
126
|
readonly method: "currentIdentity";
|
|
68
127
|
readonly fields: {};
|
|
128
|
+
readonly summary: "Show the identity bound to this CLI lease, including its profile and hierarchy.";
|
|
129
|
+
readonly effects: "Read-only.";
|
|
69
130
|
};
|
|
70
131
|
readonly 'remove-identity': {
|
|
71
132
|
readonly method: "removeIdentity";
|
|
72
133
|
readonly fields: {
|
|
73
134
|
readonly name: FieldSpec;
|
|
74
135
|
};
|
|
136
|
+
readonly summary: "Permanently remove an identity.";
|
|
137
|
+
readonly effects: "Destructive: deletes local identity state. A Human identity cannot be removed while it still has roles; temporary identities follow their close lifecycle.";
|
|
138
|
+
readonly exampleInput: {
|
|
139
|
+
readonly name: "OldBot";
|
|
140
|
+
};
|
|
75
141
|
};
|
|
76
142
|
readonly 'release-lease': {
|
|
77
143
|
readonly method: "releaseLease";
|
|
78
144
|
readonly fields: {};
|
|
145
|
+
readonly summary: "Release every identity lease held by this CLI client token.";
|
|
146
|
+
readonly effects: "Changes lease state. Owned temporary identities begin asynchronous permanent closure and best-effort contact notification.";
|
|
79
147
|
};
|
|
80
148
|
readonly 'generate-invite': {
|
|
81
149
|
readonly method: "generateInvite";
|
|
@@ -83,16 +151,29 @@ export declare const OPERATION_SPECS: {
|
|
|
83
151
|
readonly name: FieldSpec;
|
|
84
152
|
readonly mode: FieldSpec;
|
|
85
153
|
};
|
|
154
|
+
readonly summary: "Generate encrypted contact-introduction material for out-of-band sharing.";
|
|
155
|
+
readonly effects: "Creates an outstanding invite. Omitted mode defaults to one_time; public invites cannot pre-assign a name.";
|
|
156
|
+
readonly exampleInput: {
|
|
157
|
+
readonly name: "Peer";
|
|
158
|
+
readonly mode: "one_time";
|
|
159
|
+
};
|
|
86
160
|
};
|
|
87
161
|
readonly 'list-invites': {
|
|
88
162
|
readonly method: "listInvites";
|
|
89
163
|
readonly fields: {};
|
|
164
|
+
readonly summary: "List outstanding one-time and public invites.";
|
|
165
|
+
readonly effects: "Read-only.";
|
|
90
166
|
};
|
|
91
167
|
readonly 'revoke-invite': {
|
|
92
168
|
readonly method: "revokeInvite";
|
|
93
169
|
readonly fields: {
|
|
94
170
|
readonly invite_id: FieldSpec;
|
|
95
171
|
};
|
|
172
|
+
readonly summary: "Revoke an outstanding invite.";
|
|
173
|
+
readonly effects: "Destructive and idempotent. It prevents future redemption but does not remove existing contacts.";
|
|
174
|
+
readonly exampleInput: {
|
|
175
|
+
readonly invite_id: "INVITE_ID";
|
|
176
|
+
};
|
|
96
177
|
};
|
|
97
178
|
readonly 'add-contact': {
|
|
98
179
|
readonly method: "addContact";
|
|
@@ -100,14 +181,24 @@ export declare const OPERATION_SPECS: {
|
|
|
100
181
|
readonly invite: FieldSpec;
|
|
101
182
|
readonly name: FieldSpec;
|
|
102
183
|
};
|
|
184
|
+
readonly summary: "Redeem an invite and begin an encrypted contact handshake.";
|
|
185
|
+
readonly effects: "Sends the first handshake leg. The contact remains pending until the inviter verifies and replies.";
|
|
186
|
+
readonly exampleInput: {
|
|
187
|
+
readonly invite: "<invite-from-peer>";
|
|
188
|
+
readonly name: "Peer";
|
|
189
|
+
};
|
|
103
190
|
};
|
|
104
191
|
readonly 'list-contacts': {
|
|
105
192
|
readonly method: "listContacts";
|
|
106
193
|
readonly fields: {};
|
|
194
|
+
readonly summary: "List established contacts and pending local introductions.";
|
|
195
|
+
readonly effects: "Read-only.";
|
|
107
196
|
};
|
|
108
197
|
readonly 'list-local-contact-book': {
|
|
109
198
|
readonly method: "listLocalContactBook";
|
|
110
199
|
readonly fields: {};
|
|
200
|
+
readonly summary: "List same-host identities published for invite-free introduction.";
|
|
201
|
+
readonly effects: "Read-only.";
|
|
111
202
|
};
|
|
112
203
|
readonly 'set-local-book-policy': {
|
|
113
204
|
readonly method: "setLocalBookPolicy";
|
|
@@ -115,6 +206,12 @@ export declare const OPERATION_SPECS: {
|
|
|
115
206
|
readonly expose: FieldSpec;
|
|
116
207
|
readonly auto_accept: FieldSpec;
|
|
117
208
|
};
|
|
209
|
+
readonly summary: "Change local contact-book exposure and/or introduction approval policy.";
|
|
210
|
+
readonly effects: "Writes identity-local policy. At least one of expose or auto_accept is required.";
|
|
211
|
+
readonly exampleInput: {
|
|
212
|
+
readonly expose: true;
|
|
213
|
+
readonly auto_accept: false;
|
|
214
|
+
};
|
|
118
215
|
readonly refine: (a: Record<string, unknown>) => void;
|
|
119
216
|
};
|
|
120
217
|
readonly 'remove-contact': {
|
|
@@ -122,6 +219,11 @@ export declare const OPERATION_SPECS: {
|
|
|
122
219
|
readonly fields: {
|
|
123
220
|
readonly contact: FieldSpec;
|
|
124
221
|
};
|
|
222
|
+
readonly summary: "Forget a contact locally.";
|
|
223
|
+
readonly effects: "Destructive: removes the local contact and queues one best-effort remove-me notice; remote deletion is not guaranteed.";
|
|
224
|
+
readonly exampleInput: {
|
|
225
|
+
readonly contact: "OldPeer";
|
|
226
|
+
};
|
|
125
227
|
};
|
|
126
228
|
readonly 'rename-contact': {
|
|
127
229
|
readonly method: "renameContact";
|
|
@@ -129,6 +231,12 @@ export declare const OPERATION_SPECS: {
|
|
|
129
231
|
readonly contact: FieldSpec;
|
|
130
232
|
readonly name: FieldSpec;
|
|
131
233
|
};
|
|
234
|
+
readonly summary: "Rename a contact locally without changing keys or the encrypted channel.";
|
|
235
|
+
readonly effects: "Changes only the local display name.";
|
|
236
|
+
readonly exampleInput: {
|
|
237
|
+
readonly contact: "Peer";
|
|
238
|
+
readonly name: "PeerLaptop";
|
|
239
|
+
};
|
|
132
240
|
};
|
|
133
241
|
readonly 'respond-to-introduction': {
|
|
134
242
|
readonly method: "respondToIntroduction";
|
|
@@ -136,18 +244,34 @@ export declare const OPERATION_SPECS: {
|
|
|
136
244
|
readonly contact: FieldSpec;
|
|
137
245
|
readonly action: FieldSpec;
|
|
138
246
|
};
|
|
247
|
+
readonly summary: "Approve or reject a queued local introduction.";
|
|
248
|
+
readonly effects: "Approval establishes the contact and moves queued messages into the inbox; rejection drops the queue.";
|
|
249
|
+
readonly exampleInput: {
|
|
250
|
+
readonly contact: "LocalBot";
|
|
251
|
+
readonly action: "approve";
|
|
252
|
+
};
|
|
139
253
|
};
|
|
140
254
|
readonly 'set-bio': {
|
|
141
255
|
readonly method: "setBio";
|
|
142
256
|
readonly fields: {
|
|
143
257
|
readonly bio: FieldSpec;
|
|
144
258
|
};
|
|
259
|
+
readonly summary: "Replace the bound identity’s public bio.";
|
|
260
|
+
readonly effects: "Writes public profile state. Updating a Human identity also refreshes its profile in role delegation chains.";
|
|
261
|
+
readonly exampleInput: {
|
|
262
|
+
readonly bio: "Build coordinator";
|
|
263
|
+
};
|
|
145
264
|
};
|
|
146
265
|
readonly 'set-persona': {
|
|
147
266
|
readonly method: "setPersona";
|
|
148
267
|
readonly fields: {
|
|
149
268
|
readonly persona: FieldSpec;
|
|
150
269
|
};
|
|
270
|
+
readonly summary: "Replace the bound identity’s local persona.";
|
|
271
|
+
readonly effects: "Writes local profile state. Personas are not shared in invites.";
|
|
272
|
+
readonly exampleInput: {
|
|
273
|
+
readonly persona: "Handle build coordination only.";
|
|
274
|
+
};
|
|
151
275
|
};
|
|
152
276
|
readonly 'send-message': {
|
|
153
277
|
readonly method: "sendMessage";
|
|
@@ -157,6 +281,12 @@ export declare const OPERATION_SPECS: {
|
|
|
157
281
|
readonly reply_to_wire_id: FieldSpec;
|
|
158
282
|
readonly reply_to_sentence: FieldSpec;
|
|
159
283
|
};
|
|
284
|
+
readonly summary: "Send an end-to-end-encrypted text message.";
|
|
285
|
+
readonly effects: "Sends data. A verified same-host identity may be introduced automatically when it is not already a contact.";
|
|
286
|
+
readonly exampleInput: {
|
|
287
|
+
readonly contact: "Peer";
|
|
288
|
+
readonly text: "Build finished.";
|
|
289
|
+
};
|
|
160
290
|
};
|
|
161
291
|
readonly 'send-file': {
|
|
162
292
|
readonly method: "sendFile";
|
|
@@ -169,77 +299,132 @@ export declare const OPERATION_SPECS: {
|
|
|
169
299
|
readonly reply_to_wire_id: FieldSpec;
|
|
170
300
|
readonly reply_to_sentence: FieldSpec;
|
|
171
301
|
};
|
|
302
|
+
readonly summary: "Send an end-to-end-encrypted file from a path or inline base64.";
|
|
303
|
+
readonly effects: "Reads the selected local file when path is used and sends bytes. Exactly one of path or data_base64 is required; data_base64 also requires filename.";
|
|
304
|
+
readonly exampleInput: {
|
|
305
|
+
readonly contact: "Peer";
|
|
306
|
+
readonly path: "/tmp/report.pdf";
|
|
307
|
+
};
|
|
172
308
|
readonly refine: (a: Record<string, unknown>) => void;
|
|
173
309
|
};
|
|
174
310
|
readonly 'list-incoming-messages': {
|
|
175
311
|
readonly method: "listIncomingMessages";
|
|
176
312
|
readonly fields: {};
|
|
313
|
+
readonly summary: "List inbox metadata and status without revealing message bodies.";
|
|
314
|
+
readonly effects: "Read-only; message status is unchanged.";
|
|
177
315
|
};
|
|
178
316
|
readonly 'get-messages': {
|
|
179
317
|
readonly method: "getMessages";
|
|
180
318
|
readonly fields: {};
|
|
319
|
+
readonly summary: "Return every unread message body and mark those messages processed.";
|
|
320
|
+
readonly effects: "Mutates inbox status. This is the only message-body read and is exactly-once unless the returned message IDs are deferred.";
|
|
181
321
|
};
|
|
182
322
|
readonly 'defer-messages': {
|
|
183
323
|
readonly method: "deferMessages";
|
|
184
324
|
readonly fields: {
|
|
185
325
|
readonly msg_ids: FieldSpec;
|
|
186
326
|
};
|
|
327
|
+
readonly summary: "Return processed messages to the unread queue.";
|
|
328
|
+
readonly effects: "Mutates inbox status.";
|
|
329
|
+
readonly exampleInput: {
|
|
330
|
+
readonly msg_ids: readonly [12, 13];
|
|
331
|
+
};
|
|
187
332
|
};
|
|
188
333
|
readonly 'defer-files': {
|
|
189
334
|
readonly method: "deferFiles";
|
|
190
335
|
readonly fields: {
|
|
191
336
|
readonly file_ids: FieldSpec;
|
|
192
337
|
};
|
|
338
|
+
readonly summary: "Return processed files to the unread queue.";
|
|
339
|
+
readonly effects: "Mutates inbox status; already-unread files are left unchanged.";
|
|
340
|
+
readonly exampleInput: {
|
|
341
|
+
readonly file_ids: readonly [4, 5];
|
|
342
|
+
};
|
|
193
343
|
};
|
|
194
344
|
readonly 'get-conversation': {
|
|
195
345
|
readonly method: "getConversation";
|
|
196
346
|
readonly fields: {
|
|
197
347
|
readonly contact: FieldSpec;
|
|
198
348
|
};
|
|
349
|
+
readonly summary: "Show retained conversation history with one contact, oldest first.";
|
|
350
|
+
readonly effects: "Read-only. It is empty when history retention is disabled.";
|
|
351
|
+
readonly exampleInput: {
|
|
352
|
+
readonly contact: "Peer";
|
|
353
|
+
};
|
|
199
354
|
};
|
|
200
355
|
readonly 'get-receipts': {
|
|
201
356
|
readonly method: "getReceipts";
|
|
202
357
|
readonly fields: {
|
|
203
358
|
readonly contact: FieldSpec;
|
|
204
359
|
};
|
|
360
|
+
readonly summary: "Show delivered/read receipts received for sent messages.";
|
|
361
|
+
readonly effects: "Read-only. Receipts are retained only when conversation history is enabled.";
|
|
362
|
+
readonly exampleInput: {
|
|
363
|
+
readonly contact: "Peer";
|
|
364
|
+
};
|
|
205
365
|
};
|
|
206
366
|
readonly 'mark-read': {
|
|
207
367
|
readonly method: "markRead";
|
|
208
368
|
readonly fields: {
|
|
209
369
|
readonly contact: FieldSpec;
|
|
210
370
|
};
|
|
371
|
+
readonly summary: "Mark unread inbound entries in one conversation as read.";
|
|
372
|
+
readonly effects: "Mutates conversation state and sends read receipts for newly marked messages.";
|
|
373
|
+
readonly exampleInput: {
|
|
374
|
+
readonly contact: "Peer";
|
|
375
|
+
};
|
|
211
376
|
};
|
|
212
377
|
readonly 'set-conversation-policy': {
|
|
213
378
|
readonly method: "setConversationPolicy";
|
|
214
379
|
readonly fields: {
|
|
215
380
|
readonly keep_history: FieldSpec;
|
|
216
381
|
};
|
|
382
|
+
readonly summary: "Set conversation-history policy for the bound identity.";
|
|
383
|
+
readonly effects: "Writes identity-local policy. Existing contacts learn newly enabled receipt capability on later outbound traffic.";
|
|
384
|
+
readonly exampleInput: {
|
|
385
|
+
readonly keep_history: true;
|
|
386
|
+
};
|
|
217
387
|
};
|
|
218
388
|
readonly 'list-incoming-files': {
|
|
219
389
|
readonly method: "listIncomingFiles";
|
|
220
390
|
readonly fields: {};
|
|
391
|
+
readonly summary: "List incoming-file metadata for authorization.";
|
|
392
|
+
readonly effects: "Read-only: returns no bytes and does not change file status. Authorize using the authenticated sender ID, not its display name.";
|
|
221
393
|
};
|
|
222
394
|
readonly 'get-files': {
|
|
223
395
|
readonly method: "getFiles";
|
|
224
396
|
readonly fields: {
|
|
225
397
|
readonly wire_ids: FieldSpec;
|
|
226
398
|
};
|
|
399
|
+
readonly summary: "Write approved unread files into the bound identity’s files directory.";
|
|
400
|
+
readonly effects: "Writes received bytes and marks retrieved files processed. An explicit selection must contain 1–32 unique 64-hex wire IDs.";
|
|
401
|
+
readonly exampleInput: {
|
|
402
|
+
readonly wire_ids: readonly ["0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"];
|
|
403
|
+
};
|
|
227
404
|
};
|
|
228
405
|
readonly version: {
|
|
229
406
|
readonly method: "version";
|
|
230
407
|
readonly fields: {};
|
|
408
|
+
readonly summary: "Show the selected daemon’s version and protocol information.";
|
|
409
|
+
readonly effects: "Read-only.";
|
|
231
410
|
};
|
|
232
411
|
readonly 'state-dir': {
|
|
233
412
|
readonly method: "stateDir";
|
|
234
413
|
readonly fields: {};
|
|
414
|
+
readonly summary: "Show the selected daemon’s canonical state directory.";
|
|
415
|
+
readonly effects: "Read-only.";
|
|
235
416
|
};
|
|
236
417
|
readonly identities: {
|
|
237
418
|
readonly method: "identities";
|
|
238
419
|
readonly fields: {};
|
|
420
|
+
readonly summary: "Show the selected daemon’s identity summary.";
|
|
421
|
+
readonly effects: "Read-only.";
|
|
239
422
|
};
|
|
240
423
|
readonly unread: {
|
|
241
424
|
readonly method: "unread";
|
|
242
425
|
readonly fields: {};
|
|
426
|
+
readonly summary: "Show body-free unread counts and sender metadata.";
|
|
427
|
+
readonly effects: "Read-only; it never reveals message bodies or changes inbox status.";
|
|
243
428
|
};
|
|
244
429
|
readonly 'watch-notifications': {
|
|
245
430
|
readonly method: "watchNotifications";
|
|
@@ -247,21 +432,36 @@ export declare const OPERATION_SPECS: {
|
|
|
247
432
|
readonly identity: FieldSpec;
|
|
248
433
|
readonly since: {
|
|
249
434
|
readonly kind: "cursor";
|
|
435
|
+
readonly help: "Byte cursor to resume from, or tip to wait only for new events; omitted defaults to tip.";
|
|
436
|
+
readonly valueName: "N|tip";
|
|
250
437
|
};
|
|
251
438
|
};
|
|
439
|
+
readonly summary: "Stream body-free notification events until interrupted.";
|
|
440
|
+
readonly effects: "Long-running read. It does not reveal message bodies or change inbox status.";
|
|
441
|
+
readonly exampleInput: {
|
|
442
|
+
readonly identity: "BuildBot";
|
|
443
|
+
readonly since: "tip";
|
|
444
|
+
};
|
|
252
445
|
};
|
|
253
446
|
readonly 'fetch-file': {
|
|
254
447
|
readonly method: "fetchFile";
|
|
255
448
|
readonly fields: {
|
|
256
449
|
readonly wire_id: FieldSpec;
|
|
257
450
|
};
|
|
451
|
+
readonly summary: "Return one already-stored received file as base64.";
|
|
452
|
+
readonly effects: "Read-only; file bytes are emitted in the command result, so protect redirected output.";
|
|
453
|
+
readonly exampleInput: {
|
|
454
|
+
readonly wire_id: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
|
455
|
+
};
|
|
258
456
|
};
|
|
259
457
|
};
|
|
260
458
|
export type OperationName = keyof typeof OPERATION_SPECS;
|
|
261
459
|
export declare const operationNames: () => OperationName[];
|
|
262
460
|
export declare const isOperationName: (value: string) => value is OperationName;
|
|
263
461
|
export declare function parseOperationJson(raw: string | undefined, operation: OperationName): Record<string, unknown>;
|
|
462
|
+
export declare const fieldFlag: (name: string) => string;
|
|
463
|
+
export declare function operationSpec(operation: OperationName): OperationSpec;
|
|
264
464
|
export declare function operationValueFlags(operation: OperationName): Set<string>;
|
|
465
|
+
export declare function operationEmptyValueFlags(operation: OperationName): Set<string>;
|
|
265
466
|
export declare function operationInputFromFlags(operation: OperationName, values: Record<string, string>, defaults?: Record<string, unknown>): Record<string, unknown>;
|
|
266
467
|
export declare function invokeOperation(client: OursClient, operation: OperationName, input: Record<string, unknown>): Promise<unknown>;
|
|
267
|
-
export {};
|
package/dist/operations.js
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
OPERATION_SPECS,
|
|
3
|
+
fieldFlag,
|
|
3
4
|
invokeOperation,
|
|
4
5
|
isOperationName,
|
|
6
|
+
operationEmptyValueFlags,
|
|
5
7
|
operationInputFromFlags,
|
|
6
8
|
operationNames,
|
|
9
|
+
operationSpec,
|
|
7
10
|
operationValueFlags,
|
|
8
11
|
parseOperationJson
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-QRNZFPNJ.js";
|
|
13
|
+
import "./chunk-6NFATG6P.js";
|
|
11
14
|
export {
|
|
12
15
|
OPERATION_SPECS,
|
|
16
|
+
fieldFlag,
|
|
13
17
|
invokeOperation,
|
|
14
18
|
isOperationName,
|
|
19
|
+
operationEmptyValueFlags,
|
|
15
20
|
operationInputFromFlags,
|
|
16
21
|
operationNames,
|
|
22
|
+
operationSpec,
|
|
17
23
|
operationValueFlags,
|
|
18
24
|
parseOperationJson
|
|
19
25
|
};
|
package/package.json
CHANGED
package/dist/chunk-IUZOQT4D.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CliUsageError,
|
|
3
|
-
parseBoolean
|
|
4
|
-
} from "./chunk-AXXFFER2.js";
|
|
5
|
-
|
|
6
|
-
// src/operations.ts
|
|
7
|
-
var str = (required = false, values) => ({ kind: "string", required, values });
|
|
8
|
-
var bool = (required = false) => ({ kind: "boolean", required });
|
|
9
|
-
var integer = (required = false, positive = false) => ({ kind: "integer", required, positive });
|
|
10
|
-
var strings = (required = false) => ({ kind: "string[]", required });
|
|
11
|
-
var integers = (required = false) => ({ kind: "integer[]", required });
|
|
12
|
-
var none = {};
|
|
13
|
-
var OPERATION_SPECS = {
|
|
14
|
-
"create-identity": { method: "createIdentity", fields: { name: str(true), bio: str(true), exposeLocal: bool(true), localAutoAccept: bool(true) } },
|
|
15
|
-
"create-temporary-identity": { method: "createTemporaryIdentity", fields: { name: str(), bio: str(true), exposeLocal: bool(true), localAutoAccept: bool(true) } },
|
|
16
|
-
"close-temporary-identity": { method: "closeTemporaryIdentityOp", fields: { name: str() } },
|
|
17
|
-
"create-root-identity": { method: "createRootIdentity", fields: { name: str(true), bio: str(true), exposeLocal: bool(true), localAutoAccept: bool(true), skipIfRootExists: bool(true) } },
|
|
18
|
-
"define-local-identity-file": { method: "defineLocalIdentityFile", fields: { name: str(true), path: str(true), force: bool(true), exposeLocal: bool(true), localAutoAccept: bool(true), overwrite: bool(true) } },
|
|
19
|
-
"choose-identity": { method: "chooseIdentity", fields: { name: str(true), force: bool(true) } },
|
|
20
|
-
"list-identities": { method: "listIdentities", fields: none },
|
|
21
|
-
"current-identity": { method: "currentIdentity", fields: none },
|
|
22
|
-
"remove-identity": { method: "removeIdentity", fields: { name: str(true) } },
|
|
23
|
-
"release-lease": { method: "releaseLease", fields: none },
|
|
24
|
-
"generate-invite": { method: "generateInvite", fields: { name: str(), mode: str(false, ["one_time", "public"]) } },
|
|
25
|
-
"list-invites": { method: "listInvites", fields: none },
|
|
26
|
-
"revoke-invite": { method: "revokeInvite", fields: { invite_id: str(true) } },
|
|
27
|
-
"add-contact": { method: "addContact", fields: { invite: str(true), name: str() } },
|
|
28
|
-
"list-contacts": { method: "listContacts", fields: none },
|
|
29
|
-
"list-local-contact-book": { method: "listLocalContactBook", fields: none },
|
|
30
|
-
"set-local-book-policy": {
|
|
31
|
-
method: "setLocalBookPolicy",
|
|
32
|
-
fields: { expose: bool(), auto_accept: bool() },
|
|
33
|
-
refine: (a) => {
|
|
34
|
-
if (a.expose === void 0 && a.auto_accept === void 0) throw new CliUsageError("set-local-book-policy requires expose and/or auto_accept");
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
"remove-contact": { method: "removeContact", fields: { contact: str(true) } },
|
|
38
|
-
"rename-contact": { method: "renameContact", fields: { contact: str(true), name: str(true) } },
|
|
39
|
-
"respond-to-introduction": { method: "respondToIntroduction", fields: { contact: str(true), action: str(true, ["approve", "reject"]) } },
|
|
40
|
-
"set-bio": { method: "setBio", fields: { bio: str(true) } },
|
|
41
|
-
"set-persona": { method: "setPersona", fields: { persona: str(true) } },
|
|
42
|
-
"send-message": { method: "sendMessage", fields: { contact: str(true), text: str(true), reply_to_wire_id: str(), reply_to_sentence: integer(false, true) } },
|
|
43
|
-
"send-file": {
|
|
44
|
-
method: "sendFile",
|
|
45
|
-
fields: { contact: str(true), path: str(), data_base64: str(), filename: str(), mime: str(), reply_to_wire_id: str(), reply_to_sentence: integer(false, true) },
|
|
46
|
-
refine: (a) => {
|
|
47
|
-
if (a.path === void 0 === (a.data_base64 === void 0)) throw new CliUsageError("send-file requires exactly one of path or data_base64");
|
|
48
|
-
if (a.data_base64 !== void 0 && a.filename === void 0) throw new CliUsageError("send-file requires filename with data_base64");
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
"list-incoming-messages": { method: "listIncomingMessages", fields: none },
|
|
52
|
-
"get-messages": { method: "getMessages", fields: none },
|
|
53
|
-
"defer-messages": { method: "deferMessages", fields: { msg_ids: integers(true) } },
|
|
54
|
-
"defer-files": { method: "deferFiles", fields: { file_ids: integers(true) } },
|
|
55
|
-
"get-conversation": { method: "getConversation", fields: { contact: str(true) } },
|
|
56
|
-
"get-receipts": { method: "getReceipts", fields: { contact: str(true) } },
|
|
57
|
-
"mark-read": { method: "markRead", fields: { contact: str(true) } },
|
|
58
|
-
"set-conversation-policy": { method: "setConversationPolicy", fields: { keep_history: bool(true) } },
|
|
59
|
-
"list-incoming-files": { method: "listIncomingFiles", fields: none },
|
|
60
|
-
"get-files": { method: "getFiles", fields: { wire_ids: strings() } },
|
|
61
|
-
version: { method: "version", fields: none },
|
|
62
|
-
"state-dir": { method: "stateDir", fields: none },
|
|
63
|
-
identities: { method: "identities", fields: none },
|
|
64
|
-
unread: { method: "unread", fields: none },
|
|
65
|
-
"watch-notifications": { method: "watchNotifications", fields: { identity: str(true), since: { kind: "cursor" } } },
|
|
66
|
-
"fetch-file": { method: "fetchFile", fields: { wire_id: str(true) } }
|
|
67
|
-
};
|
|
68
|
-
var operationNames = () => Object.keys(OPERATION_SPECS).sort();
|
|
69
|
-
var isOperationName = (value) => Object.prototype.hasOwnProperty.call(OPERATION_SPECS, value);
|
|
70
|
-
function validateInput(input, operation) {
|
|
71
|
-
const spec = OPERATION_SPECS[operation];
|
|
72
|
-
for (const key of Object.keys(input)) {
|
|
73
|
-
if (!Object.prototype.hasOwnProperty.call(spec.fields, key)) throw new CliUsageError(`${operation}: unknown input field ${JSON.stringify(key)}`);
|
|
74
|
-
}
|
|
75
|
-
for (const [name, field] of Object.entries(spec.fields)) {
|
|
76
|
-
const item = input[name];
|
|
77
|
-
if (item === void 0) {
|
|
78
|
-
if (field.required) throw new CliUsageError(`${operation}: missing required input field ${JSON.stringify(name)}`);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
let valid = false;
|
|
82
|
-
if (field.kind === "string") valid = typeof item === "string" && (field.values === void 0 || field.values.includes(item));
|
|
83
|
-
else if (field.kind === "boolean") valid = typeof item === "boolean";
|
|
84
|
-
else if (field.kind === "integer") valid = Number.isSafeInteger(item) && (!field.positive || Number(item) >= 1);
|
|
85
|
-
else if (field.kind === "string[]") valid = Array.isArray(item) && item.every((v) => typeof v === "string");
|
|
86
|
-
else if (field.kind === "integer[]") valid = Array.isArray(item) && item.every((v) => Number.isSafeInteger(v));
|
|
87
|
-
else valid = item === "tip" || Number.isSafeInteger(item) && Number(item) >= 0;
|
|
88
|
-
if (!valid) {
|
|
89
|
-
const expected = field.values ? field.values.map((value) => JSON.stringify(value)).join(" or ") : field.kind;
|
|
90
|
-
throw new CliUsageError(`${operation}: input field ${JSON.stringify(name)} must be ${expected}`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
spec.refine?.(input);
|
|
94
|
-
return input;
|
|
95
|
-
}
|
|
96
|
-
function parseOperationJson(raw, operation) {
|
|
97
|
-
let value = {};
|
|
98
|
-
if (raw !== void 0) {
|
|
99
|
-
try {
|
|
100
|
-
value = JSON.parse(raw);
|
|
101
|
-
} catch (error) {
|
|
102
|
-
throw new CliUsageError(`--input is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new CliUsageError("--input must be a JSON object");
|
|
106
|
-
return validateInput(value, operation);
|
|
107
|
-
}
|
|
108
|
-
var fieldFlag = (name) => `--${name.replaceAll("_", "-").replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`;
|
|
109
|
-
function operationValueFlags(operation) {
|
|
110
|
-
return new Set(Object.keys(OPERATION_SPECS[operation].fields).map(fieldFlag));
|
|
111
|
-
}
|
|
112
|
-
function operationInputFromFlags(operation, values, defaults = {}) {
|
|
113
|
-
const input = { ...defaults };
|
|
114
|
-
for (const [name, field] of Object.entries(OPERATION_SPECS[operation].fields)) {
|
|
115
|
-
const flag = fieldFlag(name);
|
|
116
|
-
const raw = values[flag];
|
|
117
|
-
if (raw === void 0) continue;
|
|
118
|
-
if (field.kind === "boolean") input[name] = parseBoolean(raw, flag);
|
|
119
|
-
else if (field.kind === "integer") input[name] = parseCliInteger(raw, flag, field.positive === true);
|
|
120
|
-
else if (field.kind === "integer[]") input[name] = raw === "" ? [] : raw.split(",").map((v) => parseCliInteger(v, flag));
|
|
121
|
-
else if (field.kind === "string[]") input[name] = raw === "" ? [] : raw.split(",");
|
|
122
|
-
else if (field.kind === "cursor") input[name] = raw === "tip" ? "tip" : parseCliInteger(raw, flag);
|
|
123
|
-
else input[name] = raw;
|
|
124
|
-
}
|
|
125
|
-
return validateInput(input, operation);
|
|
126
|
-
}
|
|
127
|
-
function parseCliInteger(raw, flag, positive = false) {
|
|
128
|
-
if (!/^[0-9]+$/.test(raw)) throw new CliUsageError(`${flag} must be an integer`);
|
|
129
|
-
const value = Number(raw);
|
|
130
|
-
if (!Number.isSafeInteger(value) || positive && value < 1) throw new CliUsageError(`${flag} is outside the supported integer range`);
|
|
131
|
-
return value;
|
|
132
|
-
}
|
|
133
|
-
async function invokeOperation(client, operation, input) {
|
|
134
|
-
if (operation === "watch-notifications") throw new Error("watch-notifications is a streaming operation");
|
|
135
|
-
if (operation === "fetch-file") {
|
|
136
|
-
const bytes = await client.fetchFile(input.wire_id);
|
|
137
|
-
return { wire_id: input.wire_id, bytes: bytes.byteLength, data_base64: Buffer.from(bytes).toString("base64") };
|
|
138
|
-
}
|
|
139
|
-
const spec = OPERATION_SPECS[operation];
|
|
140
|
-
const fn = client[spec.method];
|
|
141
|
-
return Object.keys(spec.fields).length === 0 ? fn.call(client) : fn.call(client, input);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export {
|
|
145
|
-
OPERATION_SPECS,
|
|
146
|
-
operationNames,
|
|
147
|
-
isOperationName,
|
|
148
|
-
parseOperationJson,
|
|
149
|
-
operationValueFlags,
|
|
150
|
-
operationInputFromFlags,
|
|
151
|
-
invokeOperation
|
|
152
|
-
};
|