@parall/cli 1.31.0 → 1.32.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.
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,aAAa,EAAsB,mBAAmB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgCjH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,QAgBA;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,QAWA;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,QAIvG;AAuBD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,mBAAmB,EAAE,IAAI,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE;;;;;;GAQ5H;AAMD,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEZ,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,cAAc,EAAE,KAAK,CAAC,EAAE,MAAM;CAM/E;AAQD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAc9C;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC,aAAa,CAAC,CASxB;AA4CD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAoIrD"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EACV,aAAa,EAEb,mBAAmB,EACnB,OAAO,EACP,YAAY,EACb,MAAM,aAAa,CAAC;AAmCrB,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,QAqBA;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,QAmBA;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,QAIA;AAuBD,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE;;;;;;GASvD;AAMD,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEZ,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,cAAc,EAAE,KAAK,CAAC,EAAE,MAAM;CAM/E;AAaD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAuB9C;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC,aAAa,CAAC,CASxB;AA6CD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAiJrD"}
@@ -16,7 +16,10 @@ function parseOptionalInt(value, field) {
16
16
  function parsePermissions(value) {
17
17
  if (!value)
18
18
  return undefined;
19
- const permissions = value.split(',').map((v) => v.trim()).filter(Boolean);
19
+ const permissions = value
20
+ .split(',')
21
+ .map((v) => v.trim())
22
+ .filter(Boolean);
20
23
  return permissions.length > 0 ? permissions : undefined;
21
24
  }
22
25
  function parseOptionalSeconds(value, field, fallback) {
@@ -40,13 +43,19 @@ export function validateMachineOptions(opts) {
40
43
  throw new Error('cpu-cores/memory-mb/storage-gb require --machine-label custom');
41
44
  }
42
45
  if (opts.machineType === 'cloud' && opts.machineLabel === 'custom') {
43
- if (opts.cpuCores === undefined || opts.memoryMB === undefined || opts.storageGB === undefined) {
46
+ if (opts.cpuCores === undefined ||
47
+ opts.memoryMB === undefined ||
48
+ opts.storageGB === undefined) {
44
49
  throw new Error('custom machine requires --cpu-cores --memory-mb --storage-gb');
45
50
  }
46
51
  }
47
52
  }
48
53
  export function validateApiKeyOutputOptions(opts) {
49
- const selected = [opts.apiKeyFile !== undefined, opts.showApiKey === true, opts.discardApiKey === true].filter(Boolean).length;
54
+ const selected = [
55
+ opts.apiKeyFile !== undefined,
56
+ opts.showApiKey === true,
57
+ opts.discardApiKey === true,
58
+ ].filter(Boolean).length;
50
59
  if (selected > 1) {
51
60
  throw new Error('--api-key-file, --show-api-key, and --discard-api-key are mutually exclusive');
52
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/commands/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,QAkIxD"}
1
+ {"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/commands/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,QAmIxD"}
@@ -96,8 +96,8 @@ export function registerApprovalCommands(program) {
96
96
  const deadline = Date.now() + timeoutMs;
97
97
  while (true) {
98
98
  const approval = await client.getApproval(id);
99
- const isTerminal = approval.status !== 'pending'
100
- && !(approval.status === 'approved' && !approval.execution_status);
99
+ const isTerminal = approval.status !== 'pending' &&
100
+ !(approval.status === 'approved' && !approval.execution_status);
101
101
  if (isTerminal) {
102
102
  printJson(approval);
103
103
  const ok = approval.status === 'approved' && approval.execution_status === 'succeeded';
@@ -109,7 +109,7 @@ export function registerApprovalCommands(program) {
109
109
  console.error('Timed out waiting for approval decision');
110
110
  process.exit(2);
111
111
  }
112
- await new Promise(r => setTimeout(r, Math.min(pollMs, deadline - now)));
112
+ await new Promise((r) => setTimeout(r, Math.min(pollMs, deadline - now)));
113
113
  }
114
114
  }
115
115
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../src/commands/chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAyIpD"}
1
+ {"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../src/commands/chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAiJpD"}
@@ -82,7 +82,10 @@ export function registerChatCommands(program) {
82
82
  const { client, orgId } = resolveCredentials();
83
83
  const result = await client.createChat(orgId, {
84
84
  type: opts.type,
85
- member_ids: opts.memberIds.split(',').map((s) => stripPrllScheme(s.trim())).filter(Boolean),
85
+ member_ids: opts.memberIds
86
+ .split(',')
87
+ .map((s) => stripPrllScheme(s.trim()))
88
+ .filter(Boolean),
86
89
  name: opts.name,
87
90
  description: opts.description,
88
91
  });
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerClipCommands(program: Command): void;
3
+ //# sourceMappingURL=clip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clip.d.ts","sourceRoot":"","sources":["../../src/commands/clip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8BpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAuJpD"}
@@ -0,0 +1,178 @@
1
+ import { resolveCredentials } from '../lib/client.js';
2
+ import { printJson, printError } from '../lib/output.js';
3
+ /**
4
+ * Derive a CLI-friendly alias from a registry source string.
5
+ * Handles scoped packages ("@scope/name@1.0.0" → "name") and
6
+ * plain packages ("name@1.0.0" → "name").
7
+ */
8
+ function deriveAlias(source) {
9
+ let s = source.trim();
10
+ if (s.startsWith('@')) {
11
+ const slashIdx = s.indexOf('/');
12
+ if (slashIdx > 0) {
13
+ const rest = s.slice(slashIdx + 1);
14
+ const atIdx = rest.indexOf('@');
15
+ s = atIdx > 0 ? rest.slice(0, atIdx) : rest;
16
+ }
17
+ }
18
+ else {
19
+ const atIdx = s.indexOf('@');
20
+ if (atIdx > 0)
21
+ s = s.slice(0, atIdx);
22
+ }
23
+ // Normalize to server's allowed alias charset: ^[a-z0-9][a-z0-9-_]*$
24
+ return s
25
+ .toLowerCase()
26
+ .replace(/[^a-z0-9-_]/g, '-')
27
+ .replace(/^[^a-z0-9]+/, '');
28
+ }
29
+ export function registerClipCommands(program) {
30
+ const clip = program.command('clip').description('Manage clips');
31
+ clip
32
+ .command('list')
33
+ .description('List clips in the organization')
34
+ .action(async () => {
35
+ try {
36
+ const { client, orgId } = resolveCredentials();
37
+ const clips = await client.listClips(orgId);
38
+ // Table display: alias, name, version, status, source_type
39
+ if (clips.length === 0) {
40
+ printJson({ data: [], message: 'No clips found' });
41
+ return;
42
+ }
43
+ const rows = clips.map((c) => ({
44
+ alias: c.alias,
45
+ name: c.name,
46
+ version: c.version ?? '-',
47
+ status: c.status,
48
+ source_type: c.source_type,
49
+ }));
50
+ printJson(rows);
51
+ }
52
+ catch (err) {
53
+ printError(err);
54
+ }
55
+ });
56
+ clip
57
+ .command('install')
58
+ .description('Install a clip from a registry source')
59
+ .argument('<source>', 'Registry source identifier (used as name and alias)')
60
+ .option('--alias <alias>', 'Override the alias (default: derived from source)')
61
+ .action(async (source, opts) => {
62
+ try {
63
+ const { client, orgId } = resolveCredentials();
64
+ // Derive alias: take the last segment, replace non-alphanumeric with dash, lowercase.
65
+ const alias = opts.alias ?? deriveAlias(source);
66
+ const req = {
67
+ alias,
68
+ name: source,
69
+ manifest: {},
70
+ source_type: 'registry',
71
+ source_ref: source,
72
+ };
73
+ const clip = await client.createClip(orgId, req);
74
+ printJson(clip);
75
+ }
76
+ catch (err) {
77
+ printError(err);
78
+ }
79
+ });
80
+ clip
81
+ .command('info')
82
+ .description('Show detailed information about a clip by alias')
83
+ .argument('<alias>', 'Clip alias')
84
+ .action(async (alias) => {
85
+ try {
86
+ const { client, orgId } = resolveCredentials();
87
+ const clips = await client.listClips(orgId);
88
+ const found = clips.find((c) => c.alias === alias);
89
+ if (!found) {
90
+ printError(new Error(`Clip with alias "${alias}" not found`));
91
+ }
92
+ // Display full details including manifest commands
93
+ const info = {
94
+ id: found.id,
95
+ alias: found.alias,
96
+ name: found.name,
97
+ version: found.version,
98
+ description: found.description,
99
+ status: found.status,
100
+ source_type: found.source_type,
101
+ source_ref: found.source_ref,
102
+ manifest: found.manifest,
103
+ created_at: found.created_at,
104
+ updated_at: found.updated_at,
105
+ };
106
+ printJson(info);
107
+ }
108
+ catch (err) {
109
+ printError(err);
110
+ }
111
+ });
112
+ clip
113
+ .command('invoke')
114
+ .description('Invoke a clip command')
115
+ .argument('<alias>', 'Clip alias')
116
+ .argument('<command>', 'Command name to invoke')
117
+ .argument('[input]', 'Input data (JSON string or plain text)')
118
+ .option('--timeout <ms>', 'Timeout in milliseconds', '30000')
119
+ .action(async (alias, command, input, opts) => {
120
+ try {
121
+ const { client, orgId } = resolveCredentials();
122
+ // Parse input: try JSON first, fall back to plain text wrapping.
123
+ let parsedInput = undefined;
124
+ if (input !== undefined) {
125
+ try {
126
+ parsedInput = JSON.parse(input);
127
+ }
128
+ catch {
129
+ // Not valid JSON — send as a plain string.
130
+ parsedInput = input;
131
+ }
132
+ }
133
+ let timeoutMs;
134
+ if (opts?.timeout) {
135
+ timeoutMs = parseInt(opts.timeout, 10);
136
+ if (isNaN(timeoutMs) || timeoutMs <= 0) {
137
+ printError(new Error('--timeout must be a positive integer (milliseconds)'));
138
+ }
139
+ }
140
+ const req = {
141
+ alias,
142
+ command,
143
+ input: parsedInput,
144
+ timeout_ms: timeoutMs,
145
+ };
146
+ const result = await client.invokeClip(orgId, req);
147
+ if (result.error) {
148
+ printError(new Error(result.error));
149
+ }
150
+ else {
151
+ printJson(result.output);
152
+ }
153
+ }
154
+ catch (err) {
155
+ printError(err);
156
+ }
157
+ });
158
+ clip
159
+ .command('remove')
160
+ .description('Remove a clip by alias')
161
+ .argument('<alias>', 'Clip alias')
162
+ .action(async (alias) => {
163
+ try {
164
+ const { client, orgId } = resolveCredentials();
165
+ // Resolve alias to clip ID
166
+ const clips = await client.listClips(orgId);
167
+ const found = clips.find((c) => c.alias === alias);
168
+ if (!found) {
169
+ printError(new Error(`Clip with alias "${alias}" not found`));
170
+ }
171
+ await client.deleteClip(orgId, found.id);
172
+ printJson({ ok: true, removed: alias });
173
+ }
174
+ catch (err) {
175
+ printError(err);
176
+ }
177
+ });
178
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Generic, target-agnostic comment commands over `POST/GET/PATCH/DELETE
4
+ * /comments`. Unlike `parall tasks comments` (task-only) and `parall wiki
5
+ * comment` (wiki page/changeset, builds the URI for you), this group takes a
6
+ * raw `prll://` target URI, so an agent dispatched on a wiki comment can reply
7
+ * by echoing the exact `target_uri` it received.
8
+ */
9
+ export declare function registerCommentCommands(program: Command): void;
10
+ //# sourceMappingURL=comments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/commands/comments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAoGvD"}
@@ -0,0 +1,115 @@
1
+ import { resolveCredentials } from '../lib/client.js';
2
+ import { printError, printJson, printRefHint, stripPrllScheme } from '../lib/output.js';
3
+ function stripUndefined(obj) {
4
+ return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));
5
+ }
6
+ // The unified comment API addresses targets by full `prll://` URI (task,
7
+ // wiki page, wiki changeset, or wiki inline anchor). Accept the URI with or
8
+ // without the scheme so `--target prll://wik_x/Foo.md` and `--target
9
+ // wik_x/Foo.md` both work.
10
+ function normalizeTarget(target) {
11
+ return target.startsWith('prll://') ? target : `prll://${target}`;
12
+ }
13
+ /**
14
+ * Generic, target-agnostic comment commands over `POST/GET/PATCH/DELETE
15
+ * /comments`. Unlike `parall tasks comments` (task-only) and `parall wiki
16
+ * comment` (wiki page/changeset, builds the URI for you), this group takes a
17
+ * raw `prll://` target URI, so an agent dispatched on a wiki comment can reply
18
+ * by echoing the exact `target_uri` it received.
19
+ */
20
+ export function registerCommentCommands(program) {
21
+ const comments = program
22
+ .command('comments')
23
+ .description('Manage comments on any prll:// target (task / wiki page / changeset / inline anchor)');
24
+ comments
25
+ .command('add')
26
+ .description('Add a comment to a prll:// target')
27
+ .requiredOption('--target <uri>', 'Target prll:// URI (task / wiki page / changeset / inline anchor)')
28
+ .requiredOption('--body <text>', 'Comment body')
29
+ .option('--parent <id>', 'Parent comment ID (task comments only — threaded reply)')
30
+ .action(async (opts) => {
31
+ try {
32
+ const { client, orgId } = resolveCredentials();
33
+ const result = await client.createComment(orgId, {
34
+ target_uri: normalizeTarget(opts.target),
35
+ body: opts.body,
36
+ parent_id: opts.parent ? stripPrllScheme(opts.parent) : undefined,
37
+ });
38
+ printJson(result);
39
+ printRefHint(result.id);
40
+ }
41
+ catch (err) {
42
+ printError(err);
43
+ }
44
+ });
45
+ comments
46
+ .command('list')
47
+ .description('List comments on a prll:// target')
48
+ .requiredOption('--target <uri>', 'Target prll:// URI')
49
+ .option('--limit <n>', 'Maximum number of comments to return', '50')
50
+ .option('--cursor <cursor>', 'Pagination cursor')
51
+ .option('--order <order>', 'Sort order (asc or desc)')
52
+ .action(async (opts) => {
53
+ try {
54
+ const { client, orgId } = resolveCredentials();
55
+ const params = stripUndefined({
56
+ limit: Number(opts.limit),
57
+ cursor: opts.cursor,
58
+ order: opts.order,
59
+ });
60
+ const result = await client.getComments(orgId, {
61
+ target_uri: normalizeTarget(opts.target),
62
+ ...params,
63
+ });
64
+ printJson(result);
65
+ }
66
+ catch (err) {
67
+ printError(err);
68
+ }
69
+ });
70
+ comments
71
+ .command('get')
72
+ .description('Get a single comment by ID')
73
+ .argument('<commentId>', 'Comment ID')
74
+ .action(async (commentId) => {
75
+ try {
76
+ const { client, orgId } = resolveCredentials();
77
+ const result = await client.getComment(orgId, stripPrllScheme(commentId));
78
+ printJson(result);
79
+ }
80
+ catch (err) {
81
+ printError(err);
82
+ }
83
+ });
84
+ comments
85
+ .command('update')
86
+ .description('Update a comment (author only)')
87
+ .argument('<commentId>', 'Comment ID')
88
+ .requiredOption('--body <text>', 'New comment body')
89
+ .action(async (commentId, opts) => {
90
+ try {
91
+ const { client, orgId } = resolveCredentials();
92
+ const result = await client.updateComment(orgId, stripPrllScheme(commentId), {
93
+ body: opts.body,
94
+ });
95
+ printJson(result);
96
+ }
97
+ catch (err) {
98
+ printError(err);
99
+ }
100
+ });
101
+ comments
102
+ .command('delete')
103
+ .description('Delete a comment (author only)')
104
+ .argument('<commentId>', 'Comment ID')
105
+ .action(async (commentId) => {
106
+ try {
107
+ const { client, orgId } = resolveCredentials();
108
+ await client.deleteComment(orgId, stripPrllScheme(commentId));
109
+ printJson({ ok: true });
110
+ }
111
+ catch (err) {
112
+ printError(err);
113
+ }
114
+ });
115
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"dm.d.ts","sourceRoot":"","sources":["../../src/commands/dm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,QAmDlD"}
1
+ {"version":3,"file":"dm.d.ts","sourceRoot":"","sources":["../../src/commands/dm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,QAwDlD"}
@@ -1 +1 @@
1
- {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/commands/files.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAoEpD"}
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/commands/files.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAkEpD"}
@@ -43,9 +43,7 @@ export function registerFileCommands(program) {
43
43
  // Sanitize server-provided filename to prevent path traversal
44
44
  const safeName = path.basename(fileInfo.file_name || id);
45
45
  // Determine output path
46
- const outputPath = opts.output
47
- ? path.resolve(opts.output)
48
- : path.resolve(safeName);
46
+ const outputPath = opts.output ? path.resolve(opts.output) : path.resolve(safeName);
49
47
  // If output is a directory, write file inside it
50
48
  let finalPath = outputPath;
51
49
  if (fs.existsSync(outputPath) && fs.statSync(outputPath).isDirectory()) {
@@ -1 +1 @@
1
- {"version":3,"file":"machines.d.ts","sourceRoot":"","sources":["../../src/commands/machines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAoFvD"}
1
+ {"version":3,"file":"machines.d.ts","sourceRoot":"","sources":["../../src/commands/machines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAwFvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QAycnD"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QAulBnD"}
@@ -168,7 +168,9 @@ export function registerMcpCommands(program) {
168
168
  size: result.size,
169
169
  };
170
170
  return {
171
- content: [{ type: 'text', text: result.content || JSON.stringify(structuredContent, null, 2) }],
171
+ content: [
172
+ { type: 'text', text: result.content || JSON.stringify(structuredContent, null, 2) },
173
+ ],
172
174
  structuredContent,
173
175
  };
174
176
  });
@@ -182,9 +184,21 @@ export function registerMcpCommands(program) {
182
184
  wiki: z.string().describe('Wiki slug or ID'),
183
185
  query: z.string().describe('Search query'),
184
186
  ref: z.string().optional().describe('Optional git ref for API-backed search'),
185
- path_prefix: z.string().optional().describe('Restrict search to a file or directory path prefix'),
186
- limit: z.number().int().positive().max(20).optional().describe('Maximum number of results; default 5'),
187
- include_content: z.boolean().optional().describe('Include full matched section content in each result'),
187
+ path_prefix: z
188
+ .string()
189
+ .optional()
190
+ .describe('Restrict search to a file or directory path prefix'),
191
+ limit: z
192
+ .number()
193
+ .int()
194
+ .positive()
195
+ .max(20)
196
+ .optional()
197
+ .describe('Maximum number of results; default 5'),
198
+ include_content: z
199
+ .boolean()
200
+ .optional()
201
+ .describe('Include full matched section content in each result'),
188
202
  },
189
203
  outputSchema: {
190
204
  results: z.array(z.object({
@@ -205,7 +219,7 @@ export function registerMcpCommands(program) {
205
219
  source: z.enum(['local_mount', 'api']),
206
220
  })),
207
221
  },
208
- }, async ({ wiki, query, ref, path_prefix: pathPrefix, limit, include_content: includeContent }) => {
222
+ }, async ({ wiki, query, ref, path_prefix: pathPrefix, limit, include_content: includeContent, }) => {
209
223
  const results = await searchWiki(ctx, wiki, query, {
210
224
  ref,
211
225
  pathPrefix,
@@ -228,9 +242,21 @@ export function registerMcpCommands(program) {
228
242
  wiki: z.string().describe('Wiki slug or ID'),
229
243
  query: z.string().describe('Natural-language query'),
230
244
  ref: z.string().optional().describe('Optional git ref for API-backed queries'),
231
- path_prefix: z.string().optional().describe('Restrict the query to a file or directory path prefix'),
232
- limit: z.number().int().positive().max(20).optional().describe('Maximum number of section results; default 5'),
233
- include_content: z.boolean().optional().describe('Include full matched section content in each result'),
245
+ path_prefix: z
246
+ .string()
247
+ .optional()
248
+ .describe('Restrict the query to a file or directory path prefix'),
249
+ limit: z
250
+ .number()
251
+ .int()
252
+ .positive()
253
+ .max(20)
254
+ .optional()
255
+ .describe('Maximum number of section results; default 5'),
256
+ include_content: z
257
+ .boolean()
258
+ .optional()
259
+ .describe('Include full matched section content in each result'),
234
260
  },
235
261
  outputSchema: {
236
262
  wiki_id: z.string(),
@@ -269,7 +295,7 @@ export function registerMcpCommands(program) {
269
295
  reasoning: z.array(z.string()),
270
296
  })),
271
297
  },
272
- }, async ({ wiki, query, ref, path_prefix: pathPrefix, limit, include_content: includeContent }) => {
298
+ }, async ({ wiki, query, ref, path_prefix: pathPrefix, limit, include_content: includeContent, }) => {
273
299
  const result = await queryWiki(ctx, wiki, query, {
274
300
  ref,
275
301
  pathPrefix,
@@ -290,7 +316,10 @@ export function registerMcpCommands(program) {
290
316
  inputSchema: {
291
317
  wiki: z.string().describe('Wiki slug or ID'),
292
318
  ref: z.string().optional().describe('Optional git ref for API-backed outline'),
293
- path_prefix: z.string().optional().describe('Restrict outline to a file or directory path prefix'),
319
+ path_prefix: z
320
+ .string()
321
+ .optional()
322
+ .describe('Restrict outline to a file or directory path prefix'),
294
323
  },
295
324
  outputSchema: {
296
325
  wiki_id: z.string(),
@@ -331,7 +360,10 @@ export function registerMcpCommands(program) {
331
360
  inputSchema: {
332
361
  wiki: z.string().describe('Wiki slug or ID'),
333
362
  node_id: z.string().describe('Section node ID returned by wiki_search'),
334
- ref: z.string().optional().describe('Optional git ref; when set, reads from the Parall API instead of a local mount'),
363
+ ref: z
364
+ .string()
365
+ .optional()
366
+ .describe('Optional git ref; when set, reads from the Parall API instead of a local mount'),
335
367
  },
336
368
  outputSchema: {
337
369
  wiki_id: z.string(),
@@ -392,11 +424,23 @@ export function registerMcpCommands(program) {
392
424
  inputSchema: {
393
425
  wiki: z.string().describe('Wiki slug or ID'),
394
426
  title: z.string().min(1).describe('Changeset title'),
395
- message: z.string().optional().describe('Changeset commit message (supports prll:// refs)'),
427
+ message: z
428
+ .string()
429
+ .optional()
430
+ .describe('Changeset commit message (supports prll:// refs)'),
396
431
  changeset_id: z.string().optional().describe('Existing changeset ID to update'),
397
- source_chat_id: z.string().optional().describe('Optional source chat ID for approval workflow linkage'),
398
- source_message_id: z.string().optional().describe('Optional source message ID for approval workflow linkage'),
399
- source_run_id: z.string().optional().describe('Optional source run ID for approval workflow linkage'),
432
+ source_chat_id: z
433
+ .string()
434
+ .optional()
435
+ .describe('Optional source chat ID for approval workflow linkage'),
436
+ source_message_id: z
437
+ .string()
438
+ .optional()
439
+ .describe('Optional source message ID for approval workflow linkage'),
440
+ source_run_id: z
441
+ .string()
442
+ .optional()
443
+ .describe('Optional source run ID for approval workflow linkage'),
400
444
  },
401
445
  outputSchema: {
402
446
  wiki_id: z.string(),
@@ -408,12 +452,14 @@ export function registerMcpCommands(program) {
408
452
  auto_merged: z.boolean(),
409
453
  requires_review: z.boolean(),
410
454
  next_action: z.string(),
411
- post_merge_sync: z.object({
455
+ post_merge_sync: z
456
+ .object({
412
457
  applied: z.number(),
413
458
  fastForwarded: z.number(),
414
459
  conflicts: z.array(z.unknown()),
415
460
  failed: z.array(z.unknown()),
416
- }).nullable(),
461
+ })
462
+ .nullable(),
417
463
  post_merge_sync_error: z.string().nullable(),
418
464
  diff_files: z.array(z.object({
419
465
  path: z.string(),
@@ -421,15 +467,17 @@ export function registerMcpCommands(program) {
421
467
  deletions: z.number(),
422
468
  })),
423
469
  source: z.literal('local_mount'),
424
- changeset: z.object({
470
+ changeset: z
471
+ .object({
425
472
  id: z.string(),
426
473
  wiki_id: z.string(),
427
474
  title: z.string(),
428
475
  status: z.string(),
429
476
  changed_paths: z.array(z.string()).optional(),
430
- }).passthrough(),
477
+ })
478
+ .passthrough(),
431
479
  },
432
- }, async ({ wiki, title, message, changeset_id: changesetId, source_chat_id: sourceChatId, source_message_id: sourceMessageId, source_run_id: sourceRunId }) => {
480
+ }, async ({ wiki, title, message, changeset_id: changesetId, source_chat_id: sourceChatId, source_message_id: sourceMessageId, source_run_id: sourceRunId, }) => {
433
481
  const runtime = resolveRuntimeContext();
434
482
  const result = await proposeWikiChangeset(ctx, wiki, {
435
483
  title,
@@ -1,3 +1,3 @@
1
- import { Command } from 'commander';
1
+ import type { Command } from 'commander';
2
2
  export declare function registerMessageCommands(program: Command): void;
3
3
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QA0HvD"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAqJvD"}
@@ -1,5 +1,6 @@
1
+ import { ApiError } from '@parall/sdk';
1
2
  import { resolveCredentials, resolveRuntimeContext } from '../lib/client.js';
2
- import { printJson, printError, printRefHint, stripPrllScheme } from '../lib/output.js';
3
+ import { printError, printJson, printRefHint, stripPrllScheme } from '../lib/output.js';
3
4
  import { uploadFile } from '../lib/upload.js';
4
5
  export function registerMessageCommands(program) {
5
6
  const messages = program.command('messages').description('Manage messages');
@@ -63,6 +64,12 @@ export function registerMessageCommands(program) {
63
64
  printError(new Error('Chat ID required — provide as argument or set PRLL_CHAT_ID'));
64
65
  return;
65
66
  }
67
+ // `messages send` targets a chat. A user id here is an addressing
68
+ // mistake — point at `dm` instead of letting the server reject it.
69
+ if (chatId.startsWith('usr_')) {
70
+ printError(new ApiError(400, `prll://${chatId} is a user, not a chat. To message a user use: parall dm prll://${chatId} --text "..."`, 'INVALID_TARGET'));
71
+ return;
72
+ }
66
73
  if (opts.file && opts.attachment) {
67
74
  printError(new Error('--file and --attachment are mutually exclusive'));
68
75
  return;
@@ -112,7 +119,9 @@ export function registerMessageCommands(program) {
112
119
  .action(async (messageId, opts) => {
113
120
  try {
114
121
  const { client } = resolveCredentials();
115
- const params = { limit: Number(opts.limit) };
122
+ const params = {
123
+ limit: Number(opts.limit),
124
+ };
116
125
  if (opts.before !== undefined)
117
126
  params.before = stripPrllScheme(opts.before);
118
127
  if (opts.after !== undefined)
@@ -1 +1 @@
1
- {"version":3,"file":"schedules.d.ts","sourceRoot":"","sources":["../../src/commands/schedules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,QAmRxD"}
1
+ {"version":3,"file":"schedules.d.ts","sourceRoot":"","sources":["../../src/commands/schedules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,QAgTxD"}