@kuralle-agents/engagement 0.8.0 → 0.8.5
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/README.md +2 -0
- package/dist/escalation.d.ts +38 -0
- package/dist/escalation.js +20 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/scheduler.d.ts +10 -25
- package/dist/scheduler.js +1 -36
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -96,6 +96,8 @@ import { whatsappPolicy, webPolicy, instagramPolicy } from '@kuralle-agents/enga
|
|
|
96
96
|
- **`sessionConsentStore` / `consentGate`** — opt-in/opt-out and STOP handling (customer-keyed).
|
|
97
97
|
- **`sessionOwnershipStore` / `ownershipGate`** — bot vs human thread ownership; human-owned inbound does not run flows.
|
|
98
98
|
- **`createBroadcasts` / `createDrip`** — campaign ledger idempotency and drip schedules (see exports in `src/index.ts`).
|
|
99
|
+
- **`createOwnershipEscalationHandler` / `resolveEscalation`** — the channel side of `HarnessConfig.escalation`: claim the thread for the human + notify on escalation; release + resume the bot (with the resolution in context) when the human is done.
|
|
100
|
+
- The `Scheduler` contract is owned by `@kuralle-agents/core` (re-exported here) — drips, broadcasts, and runtime wake turns (`RunOptions.wake`) share backends: in-process timers in dev, Cloudflare DO alarms via `@kuralle-agents/cf-agent`.
|
|
99
101
|
|
|
100
102
|
## Example
|
|
101
103
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { EscalationHandler, EscalationOutcome, EscalationRequest } from '@kuralle-agents/core';
|
|
2
|
+
import type { OwnershipStore } from '@kuralle-agents/messaging';
|
|
3
|
+
/**
|
|
4
|
+
* Channel-side escalation bridge: when the runtime escalates, claim thread
|
|
5
|
+
* ownership for the human (so `ownershipGate` suppresses bot sends) and
|
|
6
|
+
* notify the human channel; when the human is done, `resolveEscalation`
|
|
7
|
+
* releases ownership and hands the conversation back to the bot with the
|
|
8
|
+
* resolution in context.
|
|
9
|
+
*/
|
|
10
|
+
export interface EscalationBridgeOptions {
|
|
11
|
+
ownership: OwnershipStore;
|
|
12
|
+
/** Map the escalation to the channel threadId to claim. Default: `request.sessionId`. */
|
|
13
|
+
threadIdFor?: (request: EscalationRequest) => string;
|
|
14
|
+
/**
|
|
15
|
+
* Notify the human side (inbox, Slack, pager). The returned outcome is
|
|
16
|
+
* surfaced to the runtime; returning nothing defaults to
|
|
17
|
+
* `{ status: 'queued', queueId: sessionId }`.
|
|
18
|
+
*/
|
|
19
|
+
notify?: (request: EscalationRequest) => Promise<EscalationOutcome | void>;
|
|
20
|
+
}
|
|
21
|
+
export declare function createOwnershipEscalationHandler(options: EscalationBridgeOptions): EscalationHandler;
|
|
22
|
+
/** The runtime surface `resolveEscalation` needs (satisfied by `Runtime`). */
|
|
23
|
+
export interface EscalationResumable {
|
|
24
|
+
resumeFromEscalation(sessionId: string, opts?: {
|
|
25
|
+
resolutionSummary?: string;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export interface ResolveEscalationOptions {
|
|
29
|
+
runtime: EscalationResumable;
|
|
30
|
+
ownership: OwnershipStore;
|
|
31
|
+
sessionId: string;
|
|
32
|
+
/** Channel threadId that was claimed. Default: `sessionId`. */
|
|
33
|
+
threadId?: string;
|
|
34
|
+
/** What the human did — appended to the conversation so the bot resumes with context. */
|
|
35
|
+
resolutionSummary?: string;
|
|
36
|
+
}
|
|
37
|
+
/** Human is done: release the thread back to the bot and resume the run with context. */
|
|
38
|
+
export declare function resolveEscalation(options: ResolveEscalationOptions): Promise<void>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function createOwnershipEscalationHandler(options) {
|
|
2
|
+
return async (request) => {
|
|
3
|
+
const threadId = options.threadIdFor?.(request) ?? request.sessionId;
|
|
4
|
+
await options.ownership.claim(threadId, 'human');
|
|
5
|
+
if (options.notify) {
|
|
6
|
+
const outcome = await options.notify(request);
|
|
7
|
+
if (outcome) {
|
|
8
|
+
return outcome;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return { status: 'queued', queueId: request.sessionId };
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/** Human is done: release the thread back to the bot and resume the run with context. */
|
|
15
|
+
export async function resolveEscalation(options) {
|
|
16
|
+
await options.ownership.release(options.threadId ?? options.sessionId);
|
|
17
|
+
await options.runtime.resumeFromEscalation(options.sessionId, {
|
|
18
|
+
resolutionSummary: options.resolutionSummary,
|
|
19
|
+
});
|
|
20
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export { aiTemplateSelector } from './selector.js';
|
|
|
16
16
|
export type { OutboundTemplateComponent } from '@kuralle-agents/messaging';
|
|
17
17
|
export { webPolicy } from './policies/web.js';
|
|
18
18
|
export { sessionOwnershipStore, ownershipGate, OWNERSHIP_WM_KEY, } from './ownership.js';
|
|
19
|
+
export { createOwnershipEscalationHandler, resolveEscalation, type EscalationBridgeOptions, type EscalationResumable, type ResolveEscalationOptions, } from './escalation.js';
|
|
19
20
|
export { sessionConsentStore, consentGate, CONSENT_WM_KEY } from './consent.js';
|
|
20
21
|
export { createInProcessScheduler, type Scheduler, type SendJob, } from './scheduler.js';
|
|
21
22
|
export { createInMemoryBroadcastLedger, createRedisBroadcastLedger, type BroadcastLedger, } from './broadcast-ledger.js';
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export { whatsappTemplateCatalog, mapTemplateInfoToDescriptor, isApprovedNonPaus
|
|
|
15
15
|
export { aiTemplateSelector } from './selector.js';
|
|
16
16
|
export { webPolicy } from './policies/web.js';
|
|
17
17
|
export { sessionOwnershipStore, ownershipGate, OWNERSHIP_WM_KEY, } from './ownership.js';
|
|
18
|
+
export { createOwnershipEscalationHandler, resolveEscalation, } from './escalation.js';
|
|
18
19
|
export { sessionConsentStore, consentGate, CONSENT_WM_KEY } from './consent.js';
|
|
19
20
|
export { createInProcessScheduler, } from './scheduler.js';
|
|
20
21
|
export { createInMemoryBroadcastLedger, createRedisBroadcastLedger, } from './broadcast-ledger.js';
|
package/dist/scheduler.d.ts
CHANGED
|
@@ -1,27 +1,12 @@
|
|
|
1
|
-
/** A unit of deferred work (broadcast step / drip step). Shape is engagement-internal. */
|
|
2
|
-
export interface SendJob {
|
|
3
|
-
kind: string;
|
|
4
|
-
payload: Record<string, unknown>;
|
|
5
|
-
}
|
|
6
|
-
export interface Scheduler {
|
|
7
|
-
enqueue(job: SendJob, opts?: {
|
|
8
|
-
delayMs?: number;
|
|
9
|
-
}): Promise<string>;
|
|
10
|
-
cancel(jobId: string): Promise<void>;
|
|
11
|
-
}
|
|
12
|
-
export type InjectableTimer = {
|
|
13
|
-
set(fn: () => void, ms: number): unknown;
|
|
14
|
-
clear(handle: unknown): void;
|
|
15
|
-
};
|
|
16
1
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* Inject a durable adapter for multi-process / serverless.
|
|
2
|
+
* The scheduler contract is owned by `@kuralle-agents/core` — one interface
|
|
3
|
+
* for engagement send-jobs and runtime wake turns (broadcasts, drips, and
|
|
4
|
+
* proactive agent-initiated messages share backends: in-process timers in
|
|
5
|
+
* dev, DO alarms on Cloudflare, any queue in between). Re-exported here so
|
|
6
|
+
* existing engagement consumers keep their import path.
|
|
23
7
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
8
|
+
import type { ScheduledJob } from '@kuralle-agents/core';
|
|
9
|
+
export { createInProcessScheduler } from '@kuralle-agents/core';
|
|
10
|
+
export type { Scheduler, InjectableTimer } from '@kuralle-agents/core';
|
|
11
|
+
/** A unit of deferred engagement work (broadcast step / drip step). */
|
|
12
|
+
export type SendJob = ScheduledJob;
|
package/dist/scheduler.js
CHANGED
|
@@ -1,36 +1 @@
|
|
|
1
|
-
|
|
2
|
-
set: (fn, ms) => setTimeout(fn, ms),
|
|
3
|
-
clear: (handle) => clearTimeout(handle),
|
|
4
|
-
};
|
|
5
|
-
/**
|
|
6
|
-
* Default in-process scheduler (timer-based). For single-process/dev.
|
|
7
|
-
* Production adapters (interface-compatible, not implemented here):
|
|
8
|
-
* - BullMQ (Redis-backed queue)
|
|
9
|
-
* - Google Cloud Tasks
|
|
10
|
-
* - cron / system scheduler
|
|
11
|
-
* Inject a durable adapter for multi-process / serverless.
|
|
12
|
-
*/
|
|
13
|
-
export function createInProcessScheduler(opts) {
|
|
14
|
-
const timer = opts.timer ?? defaultTimer;
|
|
15
|
-
let nextJobId = 0;
|
|
16
|
-
const handles = new Map();
|
|
17
|
-
return {
|
|
18
|
-
async enqueue(job, options) {
|
|
19
|
-
const jobId = String(++nextJobId);
|
|
20
|
-
const delayMs = options?.delayMs ?? 0;
|
|
21
|
-
const handle = timer.set(() => {
|
|
22
|
-
handles.delete(jobId);
|
|
23
|
-
void opts.run(job);
|
|
24
|
-
}, delayMs);
|
|
25
|
-
handles.set(jobId, handle);
|
|
26
|
-
return jobId;
|
|
27
|
-
},
|
|
28
|
-
async cancel(jobId) {
|
|
29
|
-
const handle = handles.get(jobId);
|
|
30
|
-
if (handle === undefined)
|
|
31
|
-
return;
|
|
32
|
-
timer.clear(handle);
|
|
33
|
-
handles.delete(jobId);
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
}
|
|
1
|
+
export { createInProcessScheduler } from '@kuralle-agents/core';
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "git+https://github.com/kuralle/kuralle-agents.git",
|
|
7
7
|
"directory": "packages/kuralle-engagement"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.8.
|
|
9
|
+
"version": "0.8.5",
|
|
10
10
|
"description": "Channel-agnostic engagement layer for Kuralle agents (window-safe outbound, smart-send, interactive fidelity, handoff, consent, proactive).",
|
|
11
11
|
"type": "module",
|
|
12
12
|
"main": "dist/index.js",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"ai": "^6.0.0",
|
|
29
29
|
"zod": "^4.0.0",
|
|
30
|
-
"@kuralle-agents/core": "0.8.
|
|
31
|
-
"@kuralle-agents/messaging": "0.8.
|
|
32
|
-
"@kuralle-agents/messaging
|
|
30
|
+
"@kuralle-agents/core": "0.8.5",
|
|
31
|
+
"@kuralle-agents/messaging-meta": "0.8.5",
|
|
32
|
+
"@kuralle-agents/messaging": "0.8.5"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"typescript": "^5.8.2",
|