@parall/parall 1.20.2 → 1.21.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/openclaw.plugin.json +2 -1
- package/package.json +3 -3
- package/skills/parall-platform/SKILL.md +18 -0
- package/skills/parall-schedules/SKILL.md +84 -0
- package/src/hooks.ts +40 -7
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/parall",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.0",
|
|
4
4
|
"description": "OpenClaw channel plugin for Parall IM",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"openclaw.plugin.json"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@parall/agent-core": "1.
|
|
19
|
-
"@parall/sdk": "1.
|
|
18
|
+
"@parall/agent-core": "1.21.0",
|
|
19
|
+
"@parall/sdk": "1.21.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^22.0.0",
|
|
@@ -75,4 +75,22 @@ npx --yes @parall/cli@latest dm "Alice" --file /tmp/report.pdf --text "Report at
|
|
|
75
75
|
|
|
76
76
|
`--file` and `--attachment` are mutually exclusive. `--text` can be combined with either.
|
|
77
77
|
|
|
78
|
+
## Reference URIs
|
|
79
|
+
|
|
80
|
+
Every entity is addressable with a `prll://` URI. Common prefixes you'll see in events, messages, and schedule descriptions:
|
|
81
|
+
|
|
82
|
+
| Prefix | Entity | Skill |
|
|
83
|
+
|--------|--------|-------|
|
|
84
|
+
| `prll://usr_` | User (human or agent) | parall-platform |
|
|
85
|
+
| `prll://cht_` | Chat | parall-platform |
|
|
86
|
+
| `prll://msg_` | Message | parall-platform |
|
|
87
|
+
| `prll://tsk_` | Task | parall-tasks |
|
|
88
|
+
| `prll://prj_` | Project | parall-tasks |
|
|
89
|
+
| `prll://sch_` | Schedule (time trigger) | parall-schedules |
|
|
90
|
+
| `prll://srn_` | Schedule run (single fire audit record; carries fire-time snapshot) | parall-schedules |
|
|
91
|
+
| `prll://wik_` | Wiki | parall-wiki |
|
|
92
|
+
| `prll://att_` | Attachment | parall-platform (files) |
|
|
93
|
+
|
|
94
|
+
When a message or event references `prll://sch_xxx` or `prll://srn_xxx`, or when you receive `[Event: schedule.fired]`, switch to the **parall-schedules** skill for the CLI commands (create / list / pause / resume / cancel / runs).
|
|
95
|
+
|
|
78
96
|
All CLI output is JSON.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: parall-schedules
|
|
3
|
+
description: "Parall schedule operations: create / pause / resume / cancel recurring or one-shot time triggers; respond to schedule fire events. Use when: user asks to set up a recurring reminder, schedule a delayed prompt, run cron-like work, or when the agent receives an `[Event: schedule.fired]` dispatch."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Parall Schedules
|
|
7
|
+
|
|
8
|
+
A **Schedule** is a platform time trigger. At fire time the platform delivers the schedule's `description` to a target — that's it. How you respond is up to you: send a message, create a task, update a wiki page, or do nothing. Use schedules for recurring reminders ("standup every weekday 10am"), delayed prompts ("in 1 hour, check CI"), or fire-and-forget cron work.
|
|
9
|
+
|
|
10
|
+
Three spec types — pick exactly one:
|
|
11
|
+
|
|
12
|
+
- `cron` — 5-field expression (min granularity: 1 minute)
|
|
13
|
+
- `interval` — every N seconds (minimum 60)
|
|
14
|
+
- `one_shot` — fire once at a specific time
|
|
15
|
+
|
|
16
|
+
## Creating schedules
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Recurring cron (weekdays 10am New York)
|
|
20
|
+
npx --yes @parall/cli@latest schedules create \
|
|
21
|
+
--name "Daily standup" \
|
|
22
|
+
--description "Ask the team for their plan today; see prll://wik_xxx for the standup template" \
|
|
23
|
+
--target-id prll://usr_xxx \
|
|
24
|
+
--cron-expr "0 10 * * 1-5" \
|
|
25
|
+
--timezone America/New_York \
|
|
26
|
+
--attached-to-uri prll://cht_xxx
|
|
27
|
+
|
|
28
|
+
# Every 30 minutes
|
|
29
|
+
npx --yes @parall/cli@latest schedules create \
|
|
30
|
+
--name "CI watch" \
|
|
31
|
+
--description "Check the deploy status and flag failures" \
|
|
32
|
+
--target-id prll://usr_xxx \
|
|
33
|
+
--interval-seconds 1800
|
|
34
|
+
|
|
35
|
+
# One-shot at a future RFC3339 time
|
|
36
|
+
npx --yes @parall/cli@latest schedules create \
|
|
37
|
+
--name "Followup" \
|
|
38
|
+
--description "Remind the user about the PR review if still pending" \
|
|
39
|
+
--target-id prll://usr_xxx \
|
|
40
|
+
--run-at 2026-04-19T15:00:00Z
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`--target-id` is who receives the fire (usually yourself when you're self-scheduling; another agent or human when delegating). `--attached-to-uri` optionally anchors the schedule to a task / chat / project / wiki page — when that resource is archived or deleted, the schedule auto-cancels (`cancel_reason=attached_gone`).
|
|
44
|
+
|
|
45
|
+
## Listing / inspecting
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npx --yes @parall/cli@latest schedules list --status active,paused
|
|
49
|
+
npx --yes @parall/cli@latest schedules list --attached-to prll://tsk_xxx
|
|
50
|
+
npx --yes @parall/cli@latest schedules list --target-id prll://usr_xxx
|
|
51
|
+
npx --yes @parall/cli@latest schedules get prll://sch_xxx
|
|
52
|
+
npx --yes @parall/cli@latest schedules runs prll://sch_xxx # fire history
|
|
53
|
+
npx --yes @parall/cli@latest schedules run prll://srn_xxx # single run incl. fire-time snapshot
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Lifecycle
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx --yes @parall/cli@latest schedules update prll://sch_xxx --description "New prompt"
|
|
60
|
+
npx --yes @parall/cli@latest schedules pause prll://sch_xxx # reversible
|
|
61
|
+
npx --yes @parall/cli@latest schedules resume prll://sch_xxx # does NOT catch up missed slots
|
|
62
|
+
npx --yes @parall/cli@latest schedules cancel prll://sch_xxx # terminal; row + runs preserved, prll://sch_ ref stays valid
|
|
63
|
+
npx --yes @parall/cli@latest schedules delete prll://sch_xxx # hard-delete; requires status=cancelled AND run_count=0. Once a schedule has fired, it is permanently undeletable (409 SCHEDULE_HAS_RUNS) — cancel it and leave the audit trail. Delete is for never-fired test/accidental schedules only.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`spec_type` cannot be changed via update — if you need to switch between cron / interval / one_shot, cancel the old one and create a new schedule.
|
|
67
|
+
|
|
68
|
+
## Responding to schedule fires
|
|
69
|
+
|
|
70
|
+
When you receive `[Event: schedule.fired]`, the platform has fired a schedule targeting you.
|
|
71
|
+
|
|
72
|
+
The runtime (agent-core) has already done the heavy lifting: it fetched the schedule run and inlined the fire-time `description` (a frozen snapshot — later edits to the schedule don't change past fires) into your prompt, alongside `[Schedule: prll://sch_xxx]` and `[Run: prll://srn_xxx]` headers. You do **not** need to call `schedules run prll://srn_xxx` yourself — the description is already in the prompt body.
|
|
73
|
+
|
|
74
|
+
Your job is to interpret the description and act:
|
|
75
|
+
|
|
76
|
+
1. Read the description and any `prll://` refs it contains
|
|
77
|
+
2. Do whatever the prompt asks (send a message, create a task, update a wiki, etc.) — there is no canonical response format
|
|
78
|
+
3. Optional: if the fire is genuinely a no-op and you don't want to produce any artifact, use `no-reply` (from `parall-platform` skill) to stay silent for this turn
|
|
79
|
+
|
|
80
|
+
Do not treat schedule fires as "tasks assigned to you" — there's no status to transition, no acknowledgment required. If the work warrants a task (multi-step, needs tracking), create one from within the response.
|
|
81
|
+
|
|
82
|
+
**Fetching the run explicitly** (optional): `schedules run prll://srn_xxx` returns the same snapshot plus `dispatch_event_id` / `inbox_item_id` for audit. If you call it and get 404 (because the schedule was cancelled or its target/attachment changed after the fire), drop the request and continue — don't retry.
|
|
83
|
+
|
|
84
|
+
CLI command results are JSON on stdout; mutation commands may emit auxiliary hints on stderr (for example, `Created: prll://sch_xxx`).
|
package/src/hooks.ts
CHANGED
|
@@ -3,6 +3,18 @@ import { PRLL_BEHAVIOR, PRLL_IDENTITY, PRLL_REFERENCE_GUIDE } from "@parall/agen
|
|
|
3
3
|
import { extractAccountIdFromSessionKey } from "./session.js";
|
|
4
4
|
import { clearDispatchGroupKey, getDispatchGroupKey, getDispatchMessageId, getParallAccountState, getSessionChatId } from "./runtime.js";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Map the session's stored target ID (whatever the current dispatch routed
|
|
8
|
+
* to — chat, task, or schedule) to the `target_type` field on agent_step.
|
|
9
|
+
* Keeps tool_call / tool_result attribution correct across event types.
|
|
10
|
+
*/
|
|
11
|
+
function stepTargetType(targetId: string): string {
|
|
12
|
+
if (targetId.startsWith("cht_")) return "chat";
|
|
13
|
+
if (targetId.startsWith("tsk_")) return "task";
|
|
14
|
+
if (targetId.startsWith("sch_")) return "schedule";
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
|
|
6
18
|
/**
|
|
7
19
|
* Resolve the ParallClient + orgId + sessionId for a hook context.
|
|
8
20
|
* Returns undefined if the account/session is not active.
|
|
@@ -22,13 +34,19 @@ function resolveClientForHook(sessionKey: string | undefined) {
|
|
|
22
34
|
|
|
23
35
|
const PRLL_CHANNEL_CONTEXT = `## Parall Channel — Message Delivery
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
Events from the Parall channel arrive as \`[Event: ...]\` blocks.
|
|
26
38
|
Your text output is **not delivered to the user** — it is discarded silently.
|
|
27
|
-
To
|
|
39
|
+
To respond, you **must** use the Parall CLI via the exec (Bash) tool.
|
|
40
|
+
|
|
41
|
+
### Event types and where to reply
|
|
28
42
|
|
|
29
|
-
|
|
43
|
+
- **\`[Event: message.new]\`** — includes \`[Chat: ... (prll://cht_xxx)]\`. Reply into that chat:
|
|
30
44
|
|
|
31
|
-
|
|
45
|
+
npx --yes @parall/cli@latest messages send prll://cht_xxx --text "Your reply here"
|
|
46
|
+
|
|
47
|
+
- **\`[Event: task.assigned]\` / \`[Event: task.comment.created]\`** — includes \`[Task: ... (prll://tsk_xxx)]\`. Act on the task; use task CLI subcommands (\`tasks update\`, \`tasks comment\`). See the \`parall-tasks\` skill.
|
|
48
|
+
|
|
49
|
+
- **\`[Event: schedule.fired]\`** — includes \`[Schedule: prll://sch_xxx]\` + \`[Run: prll://srn_xxx]\` + optional \`[Attached: prll://...]\`. The body is the fire-time \`description\` verbatim. It is an opaque trigger — decide what to do (reply into an attached chat, create a task, update a wiki file, or do nothing) based on the description. The CLI does not have a "reply to schedule" primitive; any follow-up goes through the appropriate target (chat / task / wiki).
|
|
32
50
|
|
|
33
51
|
Credentials are pre-configured in every Bash command — no setup needed.
|
|
34
52
|
Load the \`parall-platform\` skill for full CLI reference.
|
|
@@ -66,7 +84,7 @@ export function registerParallHooks(api: OpenClawPluginApi) {
|
|
|
66
84
|
try {
|
|
67
85
|
const step = await resolved.client.createAgentStep(resolved.orgId, resolved.agentUserId, resolved.sessionId, {
|
|
68
86
|
step_type: "tool_call",
|
|
69
|
-
target_type:
|
|
87
|
+
target_type: stepTargetType(resolved.chatId),
|
|
70
88
|
target_id: resolved.chatId || undefined,
|
|
71
89
|
content: {
|
|
72
90
|
call_id: event.toolCallId,
|
|
@@ -102,7 +120,22 @@ export function registerParallHooks(api: OpenClawPluginApi) {
|
|
|
102
120
|
injectedEnv.PRLL_AGENT_ID = state.agentUserId;
|
|
103
121
|
if (state.activeSessionId) injectedEnv.PRLL_SESSION_ID = state.activeSessionId;
|
|
104
122
|
if (stepId) injectedEnv.PRLL_STEP_ID = stepId;
|
|
105
|
-
if (chatId)
|
|
123
|
+
if (chatId) {
|
|
124
|
+
if (chatId.startsWith("sch_")) {
|
|
125
|
+
// Schedule-triggered dispatch: expose PRLL_SCHEDULE_ID so the agent
|
|
126
|
+
// can resolve the schedule; deliberately do NOT set PRLL_CHAT_ID,
|
|
127
|
+
// because schedule events have no chat to reply into, and leaving
|
|
128
|
+
// chatId=sch_* would mislead scripts into `messages send
|
|
129
|
+
// prll://sch_*` (a non-existent CLI path). The run snapshot is
|
|
130
|
+
// available via PRLL_TRIGGER_MESSAGE_ID (srn_*) for agents that
|
|
131
|
+
// want to re-fetch fire-time content.
|
|
132
|
+
injectedEnv.PRLL_SCHEDULE_ID = chatId;
|
|
133
|
+
} else {
|
|
134
|
+
// Chat and task dispatches continue to populate PRLL_CHAT_ID for
|
|
135
|
+
// backward compatibility with existing agent scripts.
|
|
136
|
+
injectedEnv.PRLL_CHAT_ID = chatId;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
106
139
|
if (triggerMsgId) injectedEnv.PRLL_TRIGGER_MESSAGE_ID = triggerMsgId;
|
|
107
140
|
if (state.wikiMountRoot) injectedEnv.PRLL_WIKI_MOUNT_ROOT = state.wikiMountRoot;
|
|
108
141
|
|
|
@@ -127,7 +160,7 @@ export function registerParallHooks(api: OpenClawPluginApi) {
|
|
|
127
160
|
try {
|
|
128
161
|
await resolved.client.createAgentStep(resolved.orgId, resolved.agentUserId, resolved.sessionId, {
|
|
129
162
|
step_type: "tool_result",
|
|
130
|
-
target_type:
|
|
163
|
+
target_type: stepTargetType(resolved.chatId),
|
|
131
164
|
target_id: resolved.chatId || undefined,
|
|
132
165
|
content: {
|
|
133
166
|
call_id: event.toolCallId,
|