@parall/cli 1.32.0 → 1.33.0

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":"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"}
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,QA+IpD"}
@@ -116,11 +116,14 @@ export function registerChatCommands(program) {
116
116
  .description('Add a member to a chat')
117
117
  .argument('<chatId>', 'Chat ID')
118
118
  .requiredOption('--user-id <userId>', 'User ID to add')
119
- .option('--role <role>', 'Member role: owner, admin, or member', 'member')
119
+ .option('--role <role>', 'Deprecated. Only "member" is supported')
120
120
  .action(async (chatId, opts) => {
121
121
  try {
122
+ if (opts.role !== undefined && opts.role !== 'member') {
123
+ throw new Error('--role only supports "member"; update the role after adding the member');
124
+ }
122
125
  const { client, orgId } = resolveCredentials();
123
- await client.addChatMember(orgId, stripPrllScheme(chatId), stripPrllScheme(opts.userId), opts.role);
126
+ await client.addChatMember(orgId, stripPrllScheme(chatId), stripPrllScheme(opts.userId));
124
127
  printJson({ ok: true });
125
128
  }
126
129
  catch (err) {
@@ -58,6 +58,7 @@ export function registerClipCommands(program) {
58
58
  .description('Install a clip from a registry source')
59
59
  .argument('<source>', 'Registry source identifier (used as name and alias)')
60
60
  .option('--alias <alias>', 'Override the alias (default: derived from source)')
61
+ .requiredOption('-m, --machine-id <machineId>', 'Machine ID that runs this clip')
61
62
  .action(async (source, opts) => {
62
63
  try {
63
64
  const { client, orgId } = resolveCredentials();
@@ -65,10 +66,9 @@ export function registerClipCommands(program) {
65
66
  const alias = opts.alias ?? deriveAlias(source);
66
67
  const req = {
67
68
  alias,
68
- name: source,
69
- manifest: {},
70
69
  source_type: 'registry',
71
70
  source_ref: source,
71
+ machine_id: opts.machineId,
72
72
  };
73
73
  const clip = await client.createClip(orgId, req);
74
74
  printJson(clip);
@@ -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,QAyIvD"}
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;
@@ -1 +1 @@
1
- {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE7C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAY,GAAG,IAAI,CAEvE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAmC9C"}
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE7C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAY,GAAG,IAAI,CAEvE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAwC9C"}
@@ -17,36 +17,41 @@ export function stripPrllScheme(idOrUri) {
17
17
  return idOrUri.startsWith('prll://') ? idOrUri.slice(7) : idOrUri;
18
18
  }
19
19
  export function printError(err) {
20
- let msg;
21
20
  if (err instanceof ApiError) {
22
- msg = { error: err.message, status: err.status, ...(err.code ? { code: err.code } : {}) };
23
- console.error(JSON.stringify(msg));
24
- if (err.code === 'PERMISSION_DENIED' && err.extras) {
25
- const { action, resource_uri } = err.extras;
26
- // Subset of authz.Service.RegisteredActions() only actions agents commonly encounter.
27
- // Verify the full list via GET /approvals/actions.
28
- const approvable = new Set([
29
- 'chat.delete',
30
- 'chat.archive',
31
- 'chat.restore',
32
- 'task.delete',
33
- 'task.archive',
34
- 'task.restore',
35
- ]);
36
- if (typeof action === 'string' &&
37
- typeof resource_uri === 'string' &&
38
- approvable.has(action)) {
39
- console.error(`Tip: parall approvals request --action ${action} --resource ${resource_uri} --chat <chat_id> --title "..." --reason "..."`);
21
+ // Faithful, parseable line: the server's real message + machine anchors.
22
+ console.error(JSON.stringify({
23
+ error: err.message,
24
+ status: err.status,
25
+ ...(err.code ? { code: err.code } : {}),
26
+ ...(err.action ? { action: err.action } : {}),
27
+ ...(err.resourceUri ? { resource_uri: err.resourceUri } : {}),
28
+ ...(err.approvable !== undefined ? { approvable: err.approvable } : {}),
29
+ ...(err.extras ? { extras: err.extras } : {}),
30
+ }));
31
+ // Authorization denial: tell the agent how to escalate, driven entirely by
32
+ // the server's `approvable` flag (no hardcoded allowlist that can drift).
33
+ // See docs/engineering-design/error-contract-design.md
34
+ if (err.code === 'PERMISSION_DENIED' && err.action) {
35
+ // Only an explicit `false` means "not approvable". A missing flag (older
36
+ // server, or a service that doesn't emit it) is unknown — offer the
37
+ // approval path rather than suppressing a possibly-valid request.
38
+ if (err.approvable === false) {
39
+ console.error('This action is not approvable. Ask a human with permission to perform it.');
40
+ }
41
+ else {
42
+ const lead = err.approvable === true
43
+ ? 'This action can be approved.'
44
+ : 'This action may be approvable.';
45
+ const chat = err.resourceUri?.startsWith('prll://cht_') ? err.resourceUri : '<chat_id>';
46
+ console.error(`${lead} Request approval:\n parall approvals request --action ${err.action} --resource ${err.resourceUri ?? '<resource>'} --chat ${chat} --title "..." --reason "..."`);
40
47
  }
41
48
  }
42
49
  }
43
50
  else if (err instanceof Error) {
44
- msg = { error: err.message };
45
- console.error(JSON.stringify(msg));
51
+ console.error(JSON.stringify({ error: err.message }));
46
52
  }
47
53
  else {
48
- msg = { error: String(err) };
49
- console.error(JSON.stringify(msg));
54
+ console.error(JSON.stringify({ error: String(err) }));
50
55
  }
51
56
  return process.exit(1);
52
57
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/cli",
3
- "version": "1.32.0",
3
+ "version": "1.33.0",
4
4
  "description": "CLI client for Parall — universal agent & human access to Parall API",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,7 +30,7 @@
30
30
  "@modelcontextprotocol/sdk": "1.27.1",
31
31
  "commander": "^13.0.0",
32
32
  "zod": "^4.3.6",
33
- "@parall/sdk": "1.32.0"
33
+ "@parall/sdk": "1.33.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^22.0.0",