@parall/parel-channel 1.52.1 → 1.52.2

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/dist/fork.d.ts CHANGED
@@ -146,13 +146,17 @@ export declare function handleChildSpawnFailed(ctx: ConnectorContext, event: Chi
146
146
  * this line keeps the child from "finishing" main's visible work).
147
147
  *
148
148
  * Replies are CLI-only on EVERY fork turn (the platform reply contract —
149
- * nothing auto-delivers, parel-reply-contract-alignment.md). The opening
150
- * turn additionally has no envelope (it starts from the spawn input), so it
151
- * gets no per-turn invocation context either the prefix therefore spells
152
- * out the full CLI reply command with the explicit chat target; follow-ups
153
- * arrive as deliverTo envelopes whose invocation context presets
154
- * PRLL_CHAT_ID, so the system prompt's bare `parall messages send` teaching
155
- * covers them.
149
+ * nothing auto-delivers, parel-reply-contract-alignment.md). The opening turn
150
+ * has no envelope of its own (it starts from the spawn input), so its per-turn
151
+ * context rides the effect's `invocationContext` instead; follow-ups arrive as
152
+ * deliverTo envelopes carrying theirs the usual way.
153
+ *
154
+ * The prefix still spells out the full CLI reply command with the explicit chat
155
+ * target rather than relying on the bare `parall messages send` the system
156
+ * prompt teaches. That is deliberate: effects are duck-typed by the host, so a
157
+ * parel deployment predating `invocationContext` silently drops it, and the
158
+ * opening turn would then have no PRLL_CHAT_ID to default to. The explicit
159
+ * target costs nothing and keeps the reply path independent of that skew.
156
160
  */
157
161
  export declare function buildForkScopePrefix(subject: string, threadRootId?: string): string;
158
162
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"fork.d.ts","sourceRoot":"","sources":["../src/fork.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEtE,qEAAqE;AACrE,KAAK,qBAAqB,GAAG,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAAC,CAAC;AA+CjF,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAS1C,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAC9C,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAUhD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,gFAAgF;IAChF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;2CAEuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB;oEACoE;GAClE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAMxC;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAwCvB;AAED;;sEAEsE;AACtE,wBAAsB,WAAW,CAC/B,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,OAAO,CAAC,CASlB;AAED;;;+EAG+E;AAC/E,wBAAsB,aAAa,CAAC,GAAG,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7F;AAED,0EAA0E;AAC1E,wBAAsB,cAAc,CAClC,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,8EAA8E;AAC9E,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,iEAAiE;AACjE,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoB7E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAc/F;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,CA+BhE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC,CA2B3E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAYnF"}
1
+ {"version":3,"file":"fork.d.ts","sourceRoot":"","sources":["../src/fork.ts"],"names":[],"mappings":"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"}
package/dist/fork.js CHANGED
@@ -314,13 +314,17 @@ export async function handleChildSpawnFailed(ctx, event) {
314
314
  * this line keeps the child from "finishing" main's visible work).
315
315
  *
316
316
  * Replies are CLI-only on EVERY fork turn (the platform reply contract —
317
- * nothing auto-delivers, parel-reply-contract-alignment.md). The opening
318
- * turn additionally has no envelope (it starts from the spawn input), so it
319
- * gets no per-turn invocation context either the prefix therefore spells
320
- * out the full CLI reply command with the explicit chat target; follow-ups
321
- * arrive as deliverTo envelopes whose invocation context presets
322
- * PRLL_CHAT_ID, so the system prompt's bare `parall messages send` teaching
323
- * covers them.
317
+ * nothing auto-delivers, parel-reply-contract-alignment.md). The opening turn
318
+ * has no envelope of its own (it starts from the spawn input), so its per-turn
319
+ * context rides the effect's `invocationContext` instead; follow-ups arrive as
320
+ * deliverTo envelopes carrying theirs the usual way.
321
+ *
322
+ * The prefix still spells out the full CLI reply command with the explicit chat
323
+ * target rather than relying on the bare `parall messages send` the system
324
+ * prompt teaches. That is deliberate: effects are duck-typed by the host, so a
325
+ * parel deployment predating `invocationContext` silently drops it, and the
326
+ * opening turn would then have no PRLL_CHAT_ID to default to. The explicit
327
+ * target costs nothing and keeps the reply path independent of that skew.
324
328
  */
325
329
  export function buildForkScopePrefix(subject, threadRootId) {
326
330
  // Quoted-heredoc input form (mirrors agent-core's send hint): plain
@@ -1 +1 @@
1
- {"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACf,MAAM,mBAAmB,CAAC;AA0H3B,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAWrF;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,eAAe,EAAE,CAAC,CAE5B;AAoDD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACtB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,eAAe,EAAE,CAAC,CAE5B;AAsCD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAElF;AAkoBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAE7B"}
1
+ {"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACf,MAAM,mBAAmB,CAAC;AAsI3B,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAWrF;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,eAAe,EAAE,CAAC,CAE5B;AAoDD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACtB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,eAAe,EAAE,CAAC,CAE5B;AAsCD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAElF;AAyoBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAE7B"}
package/dist/inbound.js CHANGED
@@ -473,26 +473,34 @@ async function effectsForDispatch(data, ctx) {
473
473
  ]);
474
474
  if (results.includes('stale'))
475
475
  await invalidateChildSession(ctx, decision.childRef);
476
+ // Same stamp — and same never-stamp-a-stale-ase_ rule — as the
477
+ // deliverTo branch above. Now that the opening turn carries context,
478
+ // its CLI reply links to the child session directly instead of
479
+ // resolving through dispatch provenance alone.
480
+ else
481
+ invocationContext.PRLL_SESSION_ID = childAse;
476
482
  }
477
483
  await recordSpawn(ctx, subject, decision.childRef, { dispatchId, sourceId });
478
484
  await receivedSettled;
479
- // Known gap: SpawnChildSessionEffect (plugin-sdk 0.12) carries no
480
- // invocation context, so the fork's OPENING turn runs without the
481
- // capability env (lark-cli workspace ops would need a follow-up turn)
482
- // AND without PRLL_SESSION_ID (its reply links via dispatch provenance
483
- // instead)deliverTo follow-ups inherit the full context, including
484
- // the session stamp. Channel replies are unaffected: channel_message
485
- // dispatches always ride main. Fix belongs parel-side (context on
486
- // spawnChildSession) tracked as a parel ask.
487
- return [
488
- {
489
- type: 'spawnChildSession',
490
- childRef: decision.childRef,
491
- input: buildForkScopePrefix(chatId, threadRootId) + framedText,
492
- subject,
493
- },
494
- ...timerEffects,
495
- ];
485
+ // The opening turn gets the SAME per-turn context as any deliverTo
486
+ // envelope (parel `spawnChildSession.invocationContext`): PRLL_CHAT_ID,
487
+ // the dispatch-source pair and the session stamp reach the sandbox, and
488
+ // the capability env (lark-cli) is live from turn one. It used to be the
489
+ // single turn of a child's life that ran blind it starts from the spawn
490
+ // input, not an envelope, and the effect had nowhere to carry context.
491
+ //
492
+ // A parel deployment that predates the field ignores it (effects are
493
+ // duck-typed, not schema-validated), which is why buildForkScopePrefix
494
+ // still spells out the explicit chat target: the reply path must not
495
+ // depend on the host having shipped this yet.
496
+ const spawn = {
497
+ type: 'spawnChildSession',
498
+ childRef: decision.childRef,
499
+ input: buildForkScopePrefix(chatId, threadRootId) + framedText,
500
+ subject,
501
+ invocationContext,
502
+ };
503
+ return [spawn, ...timerEffects];
496
504
  }
497
505
  // fall through: black-holed spawn rides main below.
498
506
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/parel-channel",
3
- "version": "1.52.1",
3
+ "version": "1.52.2",
4
4
  "description": "Parall channel plugin for the parel runtime — lets a parel agent treat Parall as a managed_ws channel (receive dispatches, reply via the Parall API)",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/fork.ts CHANGED
@@ -426,13 +426,17 @@ export async function handleChildSpawnFailed(
426
426
  * this line keeps the child from "finishing" main's visible work).
427
427
  *
428
428
  * Replies are CLI-only on EVERY fork turn (the platform reply contract —
429
- * nothing auto-delivers, parel-reply-contract-alignment.md). The opening
430
- * turn additionally has no envelope (it starts from the spawn input), so it
431
- * gets no per-turn invocation context either the prefix therefore spells
432
- * out the full CLI reply command with the explicit chat target; follow-ups
433
- * arrive as deliverTo envelopes whose invocation context presets
434
- * PRLL_CHAT_ID, so the system prompt's bare `parall messages send` teaching
435
- * covers them.
429
+ * nothing auto-delivers, parel-reply-contract-alignment.md). The opening turn
430
+ * has no envelope of its own (it starts from the spawn input), so its per-turn
431
+ * context rides the effect's `invocationContext` instead; follow-ups arrive as
432
+ * deliverTo envelopes carrying theirs the usual way.
433
+ *
434
+ * The prefix still spells out the full CLI reply command with the explicit chat
435
+ * target rather than relying on the bare `parall messages send` the system
436
+ * prompt teaches. That is deliberate: effects are duck-typed by the host, so a
437
+ * parel deployment predating `invocationContext` silently drops it, and the
438
+ * opening turn would then have no PRLL_CHAT_ID to default to. The explicit
439
+ * target costs nothing and keeps the reply path independent of that skew.
436
440
  */
437
441
  export function buildForkScopePrefix(subject: string, threadRootId?: string): string {
438
442
  // Quoted-heredoc input form (mirrors agent-core's send hint): plain
package/src/inbound.ts CHANGED
@@ -97,6 +97,18 @@ import { isTypedEventType, planTypedDispatch } from './typed-dispatch.js';
97
97
  * pending rather than being acked-and-dropped.
98
98
  */
99
99
 
100
+ /**
101
+ * The spawn effect plus parel's `invocationContext`, which carries per-turn
102
+ * context into the child's opening turn. The field is native in
103
+ * `@parel/plugin-sdk` 0.14.0, but this package still resolves `^0.12.0` and a
104
+ * 0.x caret never crosses minors — so the alias stays until that dependency is
105
+ * bumped, then it can go. Effects are duck-typed by the host, so an older parel
106
+ * deployment ignores the field rather than rejecting the spawn.
107
+ */
108
+ type SpawnChildEffect = Extract<ConnectorEffect, { type: 'spawnChildSession' }> & {
109
+ invocationContext?: Record<string, unknown>;
110
+ };
111
+
100
112
  interface DispatchData {
101
113
  id?: unknown;
102
114
  event_type?: unknown;
@@ -614,26 +626,33 @@ async function effectsForDispatch(
614
626
  }),
615
627
  ]);
616
628
  if (results.includes('stale')) await invalidateChildSession(ctx, decision.childRef);
629
+ // Same stamp — and same never-stamp-a-stale-ase_ rule — as the
630
+ // deliverTo branch above. Now that the opening turn carries context,
631
+ // its CLI reply links to the child session directly instead of
632
+ // resolving through dispatch provenance alone.
633
+ else invocationContext.PRLL_SESSION_ID = childAse;
617
634
  }
618
635
  await recordSpawn(ctx, subject, decision.childRef, { dispatchId, sourceId });
619
636
  await receivedSettled;
620
- // Known gap: SpawnChildSessionEffect (plugin-sdk 0.12) carries no
621
- // invocation context, so the fork's OPENING turn runs without the
622
- // capability env (lark-cli workspace ops would need a follow-up turn)
623
- // AND without PRLL_SESSION_ID (its reply links via dispatch provenance
624
- // instead)deliverTo follow-ups inherit the full context, including
625
- // the session stamp. Channel replies are unaffected: channel_message
626
- // dispatches always ride main. Fix belongs parel-side (context on
627
- // spawnChildSession) tracked as a parel ask.
628
- return [
629
- {
630
- type: 'spawnChildSession',
631
- childRef: decision.childRef,
632
- input: buildForkScopePrefix(chatId, threadRootId) + framedText,
633
- subject,
634
- },
635
- ...timerEffects,
636
- ];
637
+ // The opening turn gets the SAME per-turn context as any deliverTo
638
+ // envelope (parel `spawnChildSession.invocationContext`): PRLL_CHAT_ID,
639
+ // the dispatch-source pair and the session stamp reach the sandbox, and
640
+ // the capability env (lark-cli) is live from turn one. It used to be the
641
+ // single turn of a child's life that ran blind it starts from the spawn
642
+ // input, not an envelope, and the effect had nowhere to carry context.
643
+ //
644
+ // A parel deployment that predates the field ignores it (effects are
645
+ // duck-typed, not schema-validated), which is why buildForkScopePrefix
646
+ // still spells out the explicit chat target: the reply path must not
647
+ // depend on the host having shipped this yet.
648
+ const spawn: SpawnChildEffect = {
649
+ type: 'spawnChildSession',
650
+ childRef: decision.childRef,
651
+ input: buildForkScopePrefix(chatId, threadRootId) + framedText,
652
+ subject,
653
+ invocationContext,
654
+ };
655
+ return [spawn, ...timerEffects];
637
656
  }
638
657
  // fall through: black-holed spawn rides main below.
639
658
  }