@parall/parall 1.42.1 → 1.43.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/parall",
3
- "version": "1.42.1",
3
+ "version": "1.43.0",
4
4
  "description": "OpenClaw channel plugin for Parall IM",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,8 +16,8 @@
16
16
  "openclaw.plugin.json"
17
17
  ],
18
18
  "dependencies": {
19
- "@parall/agent-core": "1.42.1",
20
- "@parall/sdk": "1.42.1"
19
+ "@parall/agent-core": "1.43.0",
20
+ "@parall/sdk": "1.43.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^22.0.0",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: parall-platform
3
- description: "Parall platform queries and lightweight agent provisioning: list org members, agents, chats, read message history, check identity, or create another agent. Use when: user asks about org members, who's online, chat history, agent list, creating an agent, or identity/auth questions."
3
+ description: "Parall platform queries and lightweight agent provisioning: list org members, agents, chats, read message history, check identity, create another agent, or walk the prll:// reference graph (resolve URIs, backlinks, multi-hop graph). Use when: user asks about org members, who's online, chat history, agent list, creating an agent, identity/auth questions, or you need to find what an entity is connected to / who references it."
4
4
  ---
5
5
 
6
6
  # Parall Platform
@@ -81,11 +81,11 @@ settled questions or repeat known mistakes. This searches live org data
81
81
  can see.
82
82
 
83
83
  ```bash
84
- # Semantic + keyword search across messages, tasks, and wiki
84
+ # Semantic + keyword search across messages, tasks, wiki, and comments
85
85
  parall search "auth v5 upgrade"
86
86
 
87
- # Restrict entity types (m=message, t=task, w=wiki). --channel narrows the
88
- # MESSAGE hits to one chat (tasks/wiki are unaffected by it).
87
+ # Restrict entity types (m=message, t=task, w=wiki, c=comment). --channel
88
+ # narrows the MESSAGE hits to one chat (tasks/wiki/comments are unaffected).
89
89
  parall search "auth v5 upgrade" --types m,w --channel prll://cht_eng
90
90
 
91
91
  # Time-box to recent activity (RFC3339 or YYYY-MM-DD). Narrows messages + tasks;
@@ -206,6 +206,8 @@ Every entity is addressable with a `prll://` URI. Common prefixes you'll see in
206
206
  | `prll://usr_` | User (human or agent) | parall-platform |
207
207
  | `prll://cht_` | Chat | parall-platform |
208
208
  | `prll://msg_` | Message | parall-platform |
209
+ | `prll://cmt_` | Comment (on tasks, wiki pages, changesets) | by target: task comment → parall-tasks, wiki/changeset comment → parall-wiki |
210
+ | `prll://ase_` | Agent session | parall-platform |
209
211
  | `prll://tsk_` | Task | parall-tasks |
210
212
  | `prll://prj_` | Project | parall-tasks |
211
213
  | `prll://sch_` | Schedule (time trigger) | parall-schedules |
@@ -241,6 +243,23 @@ parall refs graph prll://tsk_xxx --depth 2
241
243
 
242
244
  `refs graph` traverses both directions (inbound + outbound) and returns `nodes`
243
245
  and `edges` with each node's hop `depth`. `truncated: true` means a size cap clipped
244
- the result — narrow it with a smaller `--depth`.
246
+ the result — narrow it with a smaller `--depth`. Edges carry `context` — the
247
+ author's annotation from `[context](prll://...)` — telling you *why* two
248
+ entities are linked, not just that they are.
249
+
250
+ The graph returns bare node URIs (no titles). The usual two-step: `refs graph`
251
+ for topology, then batch-`refs resolve` the node URIs you care about for
252
+ titles/status. If graph rejects your URI with a path/anchor error, strip it to
253
+ the entity root (`prll://wik_xxx/docs/a.md` → `prll://wik_xxx`) and re-query —
254
+ but note this WIDENS the query to the whole entity, not that one file: the
255
+ graph seeds from the wiki id, so a specific file's outbound links may sit
256
+ deeper in the result (or past the size caps). For refs pointing AT one file
257
+ (inbound), `refs backlinks` on the full file URI is precise. There is no
258
+ precise query for one file's OUTBOUND edges today — the widened root graph is
259
+ best-effort for those, or read the file itself for its `prll://` links.
260
+ Wiki-file nodes inside a graph *result* do legitimately carry paths.
261
+
262
+ `refs backlinks` items include a `snippet` of the referencing content — often
263
+ enough to judge relevance without fetching the source entity.
245
264
 
246
265
  CLI success output is JSON. Errors print a JSON line (`{"error","status","code",...}`) and, on a `PERMISSION_DENIED`, may add a plain-text `Request approval:` line — read both.
@@ -1,3 +1,8 @@
1
+ import {
2
+ type AgentCapability,
3
+ extractCapabilities,
4
+ materializeChannelCapabilities,
5
+ } from '@parall/agent-core';
1
6
  import type { ParallClient } from '@parall/sdk';
2
7
  import type { PlatformConfigResponse } from '@parall/sdk';
3
8
  import * as fs from 'node:fs';
@@ -9,6 +14,36 @@ interface CachedPlatformConfig {
9
14
  fetchedAt: string;
10
15
  }
11
16
 
17
+ // Channel-capability snapshot for the OTHER consumers of capability state:
18
+ // the before_prompt_build hook (fragments into the system prompt — evaluated
19
+ // every prompt build, so a refresh reaches the very next turn without any
20
+ // restart) and the gateway's getCapabilityKeys (hint routing). Updated by
21
+ // applyChannelCapabilitySnapshot alongside every config apply, so the shim
22
+ // materialization and the declaration can never diverge within a refresh.
23
+ // Process-global BY THE SAME assumption as runtime.ts's agentIdentity:
24
+ // hosted agents run one-agent-per-pod, so a single snapshot is correct. A
25
+ // future multi-account host would need this keyed per account together with
26
+ // that identity global — do not fix one without the other.
27
+ let currentCapabilities: AgentCapability[] = [];
28
+
29
+ export function getChannelCapabilityFragments(): string[] {
30
+ return currentCapabilities.map((c) => c.fragment);
31
+ }
32
+
33
+ export function getChannelCapabilityKeys(): string[] {
34
+ return currentCapabilities.map((c) => c.key);
35
+ }
36
+
37
+ function applyChannelCapabilitySnapshot(
38
+ stateDir: string,
39
+ config: Record<string, unknown>,
40
+ log?: { info: (msg: string) => void; warn: (msg: string) => void; error: (msg: string) => void },
41
+ ): void {
42
+ const caps = extractCapabilities(config);
43
+ materializeChannelCapabilities(stateDir, caps, log);
44
+ currentCapabilities = caps;
45
+ }
46
+
12
47
  interface ConfigManagerOpts {
13
48
  client: ParallClient;
14
49
  stateDir: string;
@@ -204,6 +239,7 @@ export async function fetchAndApplyPlatformConfig(opts: ConfigManagerOpts): Prom
204
239
  `platform config fetch failed, using cached version ${cached.version}: ${String(err)}`,
205
240
  );
206
241
  applyToOpenClawConfig(configPath, cached.config, credentials);
242
+ applyChannelCapabilitySnapshot(stateDir, cached.config, log);
207
243
  return;
208
244
  }
209
245
  // No cache and fetch fails — degrade gracefully
@@ -216,6 +252,7 @@ export async function fetchAndApplyPlatformConfig(opts: ConfigManagerOpts): Prom
216
252
  log?.info('platform config unchanged (304)');
217
253
  if (cached) {
218
254
  applyToOpenClawConfig(configPath, cached.config, credentials);
255
+ applyChannelCapabilitySnapshot(stateDir, cached.config, log);
219
256
  }
220
257
  return;
221
258
  }
@@ -228,6 +265,7 @@ export async function fetchAndApplyPlatformConfig(opts: ConfigManagerOpts): Prom
228
265
  );
229
266
  if (cached) {
230
267
  applyToOpenClawConfig(configPath, cached.config, credentials);
268
+ applyChannelCapabilitySnapshot(stateDir, cached.config, log);
231
269
  }
232
270
  return;
233
271
  }
@@ -235,5 +273,6 @@ export async function fetchAndApplyPlatformConfig(opts: ConfigManagerOpts): Prom
235
273
  // 5. Newer config received — save cache and apply
236
274
  log?.info(`platform config updated to version ${fresh.version}`);
237
275
  saveCachedConfig(stateDir, fresh);
276
+ applyChannelCapabilitySnapshot(stateDir, fresh.config, log);
238
277
  applyToOpenClawConfig(configPath, fresh.config, credentials);
239
278
  }
package/src/gateway.ts CHANGED
@@ -5,6 +5,7 @@ import type { ChannelPlugin } from 'openclaw/plugin-sdk/core';
5
5
  type ChannelGatewayAdapter<T = unknown> = NonNullable<ChannelPlugin<T>['gateway']>;
6
6
  import {
7
7
  ParallAgentGateway,
8
+ capabilityBinDir,
8
9
  parseShutdownDeadlineMs,
9
10
  parseForkDeadlineMs,
10
11
  parseDispatchDeadlineMs,
@@ -35,7 +36,7 @@ import {
35
36
  } from './runtime.js';
36
37
  import { buildOrchestratorSessionKey } from './session.js';
37
38
  import type { ResolvedParallAccount } from './types.js';
38
- import { fetchAndApplyPlatformConfig } from './config-manager.js';
39
+ import { fetchAndApplyPlatformConfig, getChannelCapabilityKeys } from './config-manager.js';
39
40
  import { startWikiHelper } from './wiki-helper.js';
40
41
  import { SessionManager } from './oc-session.js';
41
42
  import {
@@ -406,6 +407,17 @@ export const parallGateway: ChannelGatewayAdapter<ResolvedParallAccount> = {
406
407
  process.env.OPENCLAW_STATE_DIR || path.join(process.env.HOME || '/data', '.openclaw');
407
408
  const openclawConfigPath = path.join(stateDir, 'openclaw.json');
408
409
 
410
+ // Channel-capability shims resolve ahead of any globally-installed CLI
411
+ // of the same name. The plugin runs INSIDE the openclaw process, whose
412
+ // env every exec-tool child inherits — one idempotent prepend here
413
+ // covers the agent's shell commands for the process lifetime (the
414
+ // DIRECTORY is constant; its content tracks capability grants).
415
+ const shimDir = capabilityBinDir(stateDir);
416
+ const currentPath = process.env.PATH ?? '';
417
+ if (!currentPath.split(path.delimiter).includes(shimDir)) {
418
+ process.env.PATH = currentPath ? `${shimDir}${path.delimiter}${currentPath}` : shimDir;
419
+ }
420
+
409
421
  const configManagerOpts = {
410
422
  client,
411
423
  stateDir,
@@ -471,6 +483,9 @@ export const parallGateway: ChannelGatewayAdapter<ResolvedParallAccount> = {
471
483
  runtimeRef: { hostname: os.hostname(), pid: process.pid },
472
484
  dispatchAdapter,
473
485
  log: otelLog,
486
+ // Live capability view for hint routing: the channel reply hint
487
+ // points at the vendor CLI only while the grant is active.
488
+ getCapabilityKeys: getChannelCapabilityKeys,
474
489
  shutdownDeadlineMs: parseShutdownDeadlineMs(process.env.PRLL_SHUTDOWN_DEADLINE_MS),
475
490
  forkDeadlineMs: parseForkDeadlineMs(process.env.PRLL_FORK_DEADLINE_MS),
476
491
  dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
package/src/hooks.ts CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  recordMessageSend,
10
10
  recordNoReply,
11
11
  } from '@parall/agent-core';
12
+ import { getChannelCapabilityFragments } from './config-manager.js';
12
13
  import { extractAccountIdFromSessionKey } from './session.js';
13
14
  import {
14
15
  clearDispatchGroupKey,
@@ -127,6 +128,12 @@ export function registerParallHooks(api: OpenClawPluginApi) {
127
128
  PRLL_CHANNEL_CONTEXT,
128
129
  PRLL_BEHAVIOR,
129
130
  PRLL_REFERENCE_GUIDE,
131
+ // Channel-capability declarations (platform-config
132
+ // agents.capabilities[]). Evaluated on EVERY prompt build, so a
133
+ // capability grant/revocation reaches the next turn without any
134
+ // restart — the openclaw analogue of the CLI bridges' prompt-file
135
+ // rewrite + respawn.
136
+ ...getChannelCapabilityFragments(),
130
137
  ].join('\n\n'),
131
138
  };
132
139
  });