@phyzess/pappra 0.1.0-beta.18 → 0.1.0-beta.19

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.
@@ -0,0 +1,293 @@
1
+ import { parseArgs } from 'node:util';
2
+ export function parseOptions(args) {
3
+ const { values, positionals } = parseArgs({
4
+ args: [...args],
5
+ options: {
6
+ help: { type: 'boolean', short: 'h' },
7
+ version: { type: 'boolean', short: 'v' },
8
+ json: { type: 'boolean' },
9
+ live: { type: 'boolean' },
10
+ config: { type: 'string' },
11
+ apply: { type: 'boolean' },
12
+ watch: { type: 'boolean' },
13
+ yes: { type: 'boolean', short: 'y' },
14
+ 'no-runtime': { type: 'boolean' },
15
+ 'allow-workspace-writes': { type: 'boolean' },
16
+ reconfigure: { type: 'boolean' },
17
+ hosts: { type: 'string' },
18
+ 'apply-host': { type: 'boolean' },
19
+ 'dry-run': { type: 'boolean' },
20
+ 'print-handoff': { type: 'boolean' },
21
+ 'auto-resume': { type: 'boolean' },
22
+ from: { type: 'string' },
23
+ tarball: { type: 'string' },
24
+ out: { type: 'string' },
25
+ 'bootstrap-config': { type: 'string' },
26
+ 'recovery-config': { type: 'string' },
27
+ 'transition-extension': { type: 'boolean' },
28
+ mode: { type: 'string' },
29
+ marketplace: { type: 'boolean' },
30
+ scope: { type: 'string' },
31
+ bind: { type: 'boolean' },
32
+ force: { type: 'boolean' },
33
+ 'no-interactive': { type: 'boolean' },
34
+ 'print-choices': { type: 'boolean' },
35
+ 'install-runtime': { type: 'boolean' },
36
+ 'runtime-tarball': { type: 'string' },
37
+ 'runtime-version': { type: 'string' },
38
+ root: { type: 'string' },
39
+ 'task-id': { type: 'string' },
40
+ record: { type: 'string' },
41
+ roots: { type: 'string' },
42
+ 'include-private': { type: 'boolean' },
43
+ 'include-archived': { type: 'boolean' },
44
+ task: { type: 'string' },
45
+ objective: { type: 'string' },
46
+ acceptance: { type: 'string', multiple: true },
47
+ constraint: { type: 'string', multiple: true },
48
+ decision: { type: 'string', multiple: true },
49
+ attempted: { type: 'string', multiple: true },
50
+ 'next-action': { type: 'string', multiple: true },
51
+ limitation: { type: 'string', multiple: true },
52
+ artifact: { type: 'string', multiple: true },
53
+ 'collaboration-record': { type: 'string' },
54
+ 'context-completeness': { type: 'string' },
55
+ 'author-session': { type: 'string' },
56
+ 'native-harness': { type: 'string' },
57
+ 'native-session': { type: 'string' },
58
+ session: { type: 'string' },
59
+ repo: { type: 'string' },
60
+ kind: { type: 'string' },
61
+ query: { type: 'string' },
62
+ limit: { type: 'string' },
63
+ 'max-bytes': { type: 'string' },
64
+ rebuild: { type: 'boolean' },
65
+ host: { type: 'string' },
66
+ 'host-root': { type: 'string' },
67
+ 'host-version': { type: 'string' },
68
+ goal: { type: 'string' },
69
+ prepared: { type: 'string' },
70
+ capabilities: { type: 'string' },
71
+ controller: { type: 'string' },
72
+ 'rpc-request-timeout-ms': { type: 'string' },
73
+ 'rpc-operation-timeout-ms': { type: 'string' },
74
+ 'domain-root': { type: 'string' },
75
+ 'task-root': { type: 'string' },
76
+ message: { type: 'string' },
77
+ 'message-id': { type: 'string' },
78
+ binding: { type: 'string' },
79
+ retry: { type: 'boolean' },
80
+ 'caller-pane': { type: 'string' },
81
+ assignment: { type: 'string' },
82
+ 'max-age-minutes': { type: 'string' },
83
+ harness: { type: 'string' },
84
+ template: { type: 'string' },
85
+ execution: { type: 'string' },
86
+ events: { type: 'string' },
87
+ request: { type: 'string' },
88
+ 'owner-epoch': { type: 'string' },
89
+ 'subtask-id': { type: 'string' },
90
+ attempt: { type: 'string' },
91
+ },
92
+ allowPositionals: true,
93
+ strict: true,
94
+ });
95
+ if (values.help && values.version) {
96
+ throw new Error('Use either --help or --version, not both.');
97
+ }
98
+ const command = positionals[0] ?? null;
99
+ if (command === 'task') {
100
+ if (positionals.length > 3) {
101
+ throw new Error('task accepts one action and an optional task id.');
102
+ }
103
+ return {
104
+ values,
105
+ command,
106
+ docsAction: null,
107
+ docsArgument: null,
108
+ codeAction: null,
109
+ hostAction: null,
110
+ hostSubAction: null,
111
+ collaborationAction: null,
112
+ resumeTaskId: null,
113
+ runtimeAction: null,
114
+ taskAction: positionals[1] ?? null,
115
+ taskArgument: positionals[2] ?? null,
116
+ };
117
+ }
118
+ if (command === 'docs') {
119
+ if (positionals.length > (positionals[1] === 'relocate' ? 4 : 3)) {
120
+ throw new Error('Unknown command; docs accepts one action and one argument.');
121
+ }
122
+ return {
123
+ values,
124
+ codeAction: null,
125
+ command,
126
+ docsAction: positionals[1] ?? null,
127
+ docsArgument: positionals[2] ?? null,
128
+ docsTarget: positionals[3] ?? null,
129
+ hostAction: null,
130
+ hostSubAction: null,
131
+ collaborationAction: null,
132
+ resumeTaskId: null,
133
+ runtimeAction: null,
134
+ taskAction: null,
135
+ taskArgument: null,
136
+ };
137
+ }
138
+ if (command === 'resume') {
139
+ if (positionals.length > 2) {
140
+ throw new Error('resume accepts exactly one task id.');
141
+ }
142
+ return {
143
+ values,
144
+ command,
145
+ docsAction: null,
146
+ docsArgument: null,
147
+ codeAction: null,
148
+ hostAction: null,
149
+ hostSubAction: null,
150
+ collaborationAction: null,
151
+ resumeTaskId: positionals[1] ?? null,
152
+ runtimeAction: null,
153
+ taskAction: null,
154
+ taskArgument: null,
155
+ };
156
+ }
157
+ if (command === 'code') {
158
+ if (positionals.length > 2) {
159
+ throw new Error('code accepts one action: status, prepare, or query.');
160
+ }
161
+ return {
162
+ values,
163
+ command,
164
+ docsAction: null,
165
+ docsArgument: null,
166
+ codeAction: positionals[1] ?? null,
167
+ hostAction: null,
168
+ hostSubAction: null,
169
+ collaborationAction: null,
170
+ resumeTaskId: null,
171
+ runtimeAction: null,
172
+ taskAction: null,
173
+ taskArgument: null,
174
+ };
175
+ }
176
+ if (command === 'host') {
177
+ if (positionals.length > 3) {
178
+ throw new Error('host accepts one action and an optional mcp sub-action.');
179
+ }
180
+ return {
181
+ values,
182
+ command,
183
+ docsAction: null,
184
+ docsArgument: null,
185
+ codeAction: null,
186
+ hostAction: positionals[1] ?? null,
187
+ hostSubAction: positionals[2] ?? null,
188
+ collaborationAction: null,
189
+ resumeTaskId: null,
190
+ runtimeAction: null,
191
+ taskAction: null,
192
+ taskArgument: null,
193
+ };
194
+ }
195
+ if (command === 'runtime') {
196
+ if (positionals.length > 2) {
197
+ throw new Error('runtime accepts one action: install, status, verify, or remove.');
198
+ }
199
+ return {
200
+ values,
201
+ command,
202
+ docsAction: null,
203
+ docsArgument: null,
204
+ codeAction: null,
205
+ hostAction: null,
206
+ hostSubAction: null,
207
+ collaborationAction: null,
208
+ resumeTaskId: null,
209
+ runtimeAction: positionals[1] ?? null,
210
+ taskAction: null,
211
+ taskArgument: null,
212
+ };
213
+ }
214
+ if (command === 'collab') {
215
+ // `collab message <action>` is the only two-level form; the action string carries
216
+ // both segments so callers keep one parsed field.
217
+ if (positionals.length > 3 ||
218
+ (positionals.length === 3 &&
219
+ positionals[1] !== 'transition' &&
220
+ positionals[1] !== 'bootstrap' &&
221
+ positionals[1] !== 'plan' &&
222
+ positionals[1] !== 'role-plan' &&
223
+ positionals[1] !== 'message' &&
224
+ !(positionals[1] === 'capabilities' && positionals[2] === 'derive') &&
225
+ !((positionals[1] === 'state' ||
226
+ positionals[1] === 'resource' ||
227
+ positionals[1] === 'handoff' ||
228
+ positionals[1] === 'recovery' ||
229
+ positionals[1] === 'binding' ||
230
+ positionals[1] === 'rollover') &&
231
+ positionals[2] !== undefined))) {
232
+ throw new Error('collab accepts prepare, run, work-run, query, preflight, plan, bootstrap, rollover <inspect|plan>, transition <plan|apply>, message <send|list|read|notify>, capabilities derive, state <show|doctor|epoch-check>, resource <list|claim|release>, handoff <inventory|begin|stopped|rebind|transfer|confirm|complete|abort|release-dispatch>, recovery <inspect|reconcile|lock-break>, recovery-run, or binding <list|resolve|bind|unbind>.');
233
+ }
234
+ return {
235
+ values,
236
+ command,
237
+ docsAction: null,
238
+ docsArgument: null,
239
+ codeAction: null,
240
+ hostAction: null,
241
+ hostSubAction: null,
242
+ collaborationAction: positionals[1] === undefined ? null : positionals.slice(1).join(':'),
243
+ resumeTaskId: null,
244
+ runtimeAction: null,
245
+ taskAction: null,
246
+ taskArgument: null,
247
+ };
248
+ }
249
+ if (positionals.length > 1) {
250
+ throw new Error('Only one command may be specified.');
251
+ }
252
+ return {
253
+ values,
254
+ command,
255
+ docsAction: null,
256
+ docsArgument: null,
257
+ codeAction: null,
258
+ hostAction: null,
259
+ collaborationAction: null,
260
+ resumeTaskId: null,
261
+ runtimeAction: null,
262
+ };
263
+ }
264
+ export function failure(output, json, code, error) {
265
+ const message = typeof error === 'string'
266
+ ? error
267
+ : error instanceof Error
268
+ ? error.message
269
+ : 'Operation failed.';
270
+ if (json) {
271
+ output.stdout(`${JSON.stringify({ ok: false, code, message })}\n`);
272
+ }
273
+ else {
274
+ output.stderr(`pappra: ${message}\n`);
275
+ }
276
+ }
277
+ export function hasContinuityOptions(values, includeSession = true) {
278
+ return (values.task !== undefined ||
279
+ values.objective !== undefined ||
280
+ values.acceptance !== undefined ||
281
+ values.constraint !== undefined ||
282
+ values.decision !== undefined ||
283
+ values.attempted !== undefined ||
284
+ values['next-action'] !== undefined ||
285
+ values.limitation !== undefined ||
286
+ values.artifact !== undefined ||
287
+ values['collaboration-record'] !== undefined ||
288
+ values['context-completeness'] !== undefined ||
289
+ values['author-session'] !== undefined ||
290
+ values['native-harness'] !== undefined ||
291
+ values['native-session'] !== undefined ||
292
+ (includeSession && values.session !== undefined));
293
+ }