@keemakr/agent-sdk 0.19.0-dev-20261014201650 → 0.19.0-dev-20261014211203
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/channel-testkit.d.ts +1 -0
- package/dist/channel-testkit.js +11 -2
- package/dist/channel.d.ts +53 -0
- package/dist/channel.js +14 -0
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/channel-testkit.js
CHANGED
|
@@ -192,11 +192,19 @@ export async function startFakeCore(options = {}) {
|
|
|
192
192
|
req.on('end', () => {
|
|
193
193
|
const action = JSON.parse(raw || '{}');
|
|
194
194
|
// Checked as core checks it: a reach ref counts only if THIS turn was served it.
|
|
195
|
-
const
|
|
195
|
+
const effects = action.effects;
|
|
196
|
+
const cited = action.action === 'turn'
|
|
197
|
+
? (effects?.replies?.flatMap((r) => r.groundedOn ?? []) ?? [])
|
|
198
|
+
: Array.isArray(action.grounded_on)
|
|
199
|
+
? action.grounded_on
|
|
200
|
+
: [];
|
|
196
201
|
unverified.set(String(action.delivery_id), cited.filter((g) => typeof g === 'string' &&
|
|
197
202
|
(!(served.get(trace)?.has(/^(record|op|hold|kb|workflow):/.test(g) ? g : `kb:${g}`) ??
|
|
198
203
|
false) ||
|
|
199
|
-
(g.startsWith('workflow:') &&
|
|
204
|
+
(g.startsWith('workflow:') &&
|
|
205
|
+
(action.action === 'turn'
|
|
206
|
+
? (effects?.replies?.some((r) => r.groundedOn?.includes(g) && workflowText.get(`${trace}:${g}`) !== r.text) ?? false)
|
|
207
|
+
: workflowText.get(`${trace}:${g}`) !== action.text)))));
|
|
200
208
|
const resolve = waiting.get(String(action.delivery_id));
|
|
201
209
|
if (resolve) {
|
|
202
210
|
waiting.delete(String(action.delivery_id));
|
|
@@ -276,6 +284,7 @@ export async function startFakeCore(options = {}) {
|
|
|
276
284
|
...(input.language ? { language: input.language } : {}),
|
|
277
285
|
...(input.channel ? { channel: input.channel } : {}),
|
|
278
286
|
...(input.setup ? { setup: input.setup } : {}),
|
|
287
|
+
...(input.continuity ? { continuity: input.continuity } : {}),
|
|
279
288
|
}),
|
|
280
289
|
});
|
|
281
290
|
const action = (await answered);
|
package/dist/channel.d.ts
CHANGED
|
@@ -14,8 +14,53 @@ export interface ChannelPresentation {
|
|
|
14
14
|
format: 'chat' | 'email' | 'sms';
|
|
15
15
|
maxTextChars?: number;
|
|
16
16
|
}
|
|
17
|
+
export interface ChannelQuestion {
|
|
18
|
+
id: string;
|
|
19
|
+
revision: number;
|
|
20
|
+
text: string;
|
|
21
|
+
sourcePosition: number;
|
|
22
|
+
state: 'open' | 'partitioned' | 'answered' | 'cancelled';
|
|
23
|
+
attempts: number;
|
|
24
|
+
}
|
|
25
|
+
export interface QuestionRef {
|
|
26
|
+
id: string;
|
|
27
|
+
revision: number;
|
|
28
|
+
}
|
|
29
|
+
export interface ChannelTurnEffects {
|
|
30
|
+
protocol: 'scoped-v1';
|
|
31
|
+
withdrawals?: Array<{
|
|
32
|
+
question: QuestionRef;
|
|
33
|
+
request: QuestionRef;
|
|
34
|
+
}>;
|
|
35
|
+
partitions?: Array<{
|
|
36
|
+
question: QuestionRef;
|
|
37
|
+
parts: Array<{
|
|
38
|
+
key: string;
|
|
39
|
+
text: string;
|
|
40
|
+
}>;
|
|
41
|
+
}>;
|
|
42
|
+
replies: Array<{
|
|
43
|
+
key: string;
|
|
44
|
+
text: string;
|
|
45
|
+
kind: 'answer' | 'conversation' | 'workflow';
|
|
46
|
+
confidence?: number;
|
|
47
|
+
coverage: 'answered' | 'clarification' | 'limitation';
|
|
48
|
+
groundedOn: string[];
|
|
49
|
+
questions: QuestionRef[];
|
|
50
|
+
}>;
|
|
51
|
+
assistance: Array<{
|
|
52
|
+
key: string;
|
|
53
|
+
questions: QuestionRef[];
|
|
54
|
+
reason: 'customer_requested' | 'clinical' | 'repeated_gap' | 'urgent' | 'operation_uncertain';
|
|
55
|
+
stopAgent?: boolean;
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
17
58
|
/** The envelope core POSTs. Loose by rule — core adds fields without asking packs first. */
|
|
18
59
|
export interface ChannelDelivery {
|
|
60
|
+
continuity?: {
|
|
61
|
+
protocol: 'scoped-v1';
|
|
62
|
+
questions: ChannelQuestion[];
|
|
63
|
+
};
|
|
19
64
|
event: string;
|
|
20
65
|
delivery_id: string;
|
|
21
66
|
conversation: {
|
|
@@ -46,6 +91,10 @@ export interface ChannelDelivery {
|
|
|
46
91
|
}
|
|
47
92
|
/** What a pack proposes. Core decides what happens to it. */
|
|
48
93
|
export type ChannelAction = {
|
|
94
|
+
action: 'turn';
|
|
95
|
+
effects: ChannelTurnEffects;
|
|
96
|
+
usage: Usage;
|
|
97
|
+
} | {
|
|
49
98
|
action: 'reply';
|
|
50
99
|
text: string;
|
|
51
100
|
confidence?: number;
|
|
@@ -208,6 +257,10 @@ export declare class ChannelReplyNotDeliverable extends Error {
|
|
|
208
257
|
constructor();
|
|
209
258
|
}
|
|
210
259
|
export interface ChannelContext {
|
|
260
|
+
continuity?: ChannelDelivery['continuity'];
|
|
261
|
+
turn(effects: ChannelTurnEffects, opts?: {
|
|
262
|
+
usage?: Usage;
|
|
263
|
+
}): ChannelAction;
|
|
211
264
|
tenantId: string;
|
|
212
265
|
conversationId: string;
|
|
213
266
|
deliveryId: string;
|
package/dist/channel.js
CHANGED
|
@@ -224,6 +224,8 @@ export function createChannelAgent(options) {
|
|
|
224
224
|
// A CONTRACT THIS SDK DOES NOT SPEAK IS A REFUSAL, NOT A GUESS. Absent means a core
|
|
225
225
|
// that predates the field. Anything else means core has changed the envelope's SHAPE,
|
|
226
226
|
// and answering it with v1 assumptions is how a pack confidently misreads a customer.
|
|
227
|
+
if (body.continuity && body.continuity.protocol !== 'scoped-v1')
|
|
228
|
+
return refuse(400, 'turn_effects_unsupported');
|
|
227
229
|
if (body.contract !== undefined && body.contract !== SUPPORTED_CONTRACT) {
|
|
228
230
|
return refuse(400, 'contract_unsupported');
|
|
229
231
|
}
|
|
@@ -310,6 +312,7 @@ export function createChannelAgent(options) {
|
|
|
310
312
|
contact: body.contact,
|
|
311
313
|
channel: body.channel,
|
|
312
314
|
setup: body.setup,
|
|
315
|
+
continuity: body.continuity,
|
|
313
316
|
booking: {
|
|
314
317
|
async requestVerification(appointmentId) {
|
|
315
318
|
return (await readOrRefuse(await authed('/api/capability/booking/verification/request', {
|
|
@@ -521,6 +524,15 @@ export function createChannelAgent(options) {
|
|
|
521
524
|
// PURE BUILDERS. They return an action and touch nothing — so a pack's `answer` can
|
|
522
525
|
// be tested by calling it and inspecting what came back, with no core, no fake and no
|
|
523
526
|
// network.
|
|
527
|
+
turn(effects, opts) {
|
|
528
|
+
if (body.continuity?.protocol !== 'scoped-v1' || effects.protocol !== 'scoped-v1')
|
|
529
|
+
throw new Error('turn_effects_not_negotiated');
|
|
530
|
+
return {
|
|
531
|
+
action: 'turn',
|
|
532
|
+
effects,
|
|
533
|
+
usage: opts?.usage ?? { input_tokens: 0, output_tokens: 0 },
|
|
534
|
+
};
|
|
535
|
+
},
|
|
524
536
|
reply(text, opts) {
|
|
525
537
|
const run = body.unanswered_messages ?? [];
|
|
526
538
|
if (run.length > 0 && run.every((m) => m.email && !m.email.replyable)) {
|
|
@@ -598,6 +610,8 @@ export function createChannelAgent(options) {
|
|
|
598
610
|
// ANSWERED on the preview path — so the owner is shown, under v1 assumptions, something
|
|
599
611
|
// no customer of theirs would ever receive. A preview that lies is worse than no
|
|
600
612
|
// preview, because it is trusted.
|
|
613
|
+
if (body.continuity && body.continuity.protocol !== 'scoped-v1')
|
|
614
|
+
return refuse(400, 'turn_effects_unsupported');
|
|
601
615
|
if (body.contract !== undefined && body.contract !== SUPPORTED_CONTRACT) {
|
|
602
616
|
return refuse(400, 'contract_unsupported');
|
|
603
617
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export { useKee, MemoryConflictError, RecordConflictError, RecordValidationError
|
|
|
6
6
|
export { keemakrToolDirectory } from './tool-directory.js';
|
|
7
7
|
export { refreshGrant, REFRESH_THRESHOLD_SECONDS } from './refresh.js';
|
|
8
8
|
export { audioCanvas, imageCanvas, type AudioCanvas, type Canvas, type ImageCanvas, type ReportCanvas, } from './canvases.js';
|
|
9
|
-
export { createChannelAgent, assertTrustworthyCore, ChannelReachError, ChannelReplyNotDeliverable, isApprovalRequired, isHoldSettled, isOutcomeUnknown, isWriteDone, type ChannelWriteDone, type ChannelWriteResult, type ChannelWriteOptions, type ChannelApprovalRequired, type ChannelHoldSettled, type ChannelOutcomeUnknown, type HeldActionStatus, type ChannelReach, type ChannelRecord, type ChannelAction, type ChannelAgent, type ChannelAgentOptions, type ChannelContext, type ChannelDelivery, type ChannelEmail, type ChannelMessage, type HandoffReason, type Usage, } from './channel.js';
|
|
9
|
+
export { createChannelAgent, assertTrustworthyCore, ChannelReachError, ChannelReplyNotDeliverable, isApprovalRequired, isHoldSettled, isOutcomeUnknown, isWriteDone, type ChannelWriteDone, type ChannelWriteResult, type ChannelWriteOptions, type ChannelApprovalRequired, type ChannelHoldSettled, type ChannelOutcomeUnknown, type HeldActionStatus, type ChannelReach, type ChannelRecord, type ChannelAction, type ChannelAgent, type ChannelAgentOptions, type ChannelContext, type ChannelDelivery, type ChannelTurnEffects, type ChannelQuestion, type QuestionRef, type ChannelEmail, type ChannelMessage, type HandoffReason, type Usage, } from './channel.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keemakr/agent-sdk",
|
|
3
|
-
"version": "0.19.0-dev-
|
|
3
|
+
"version": "0.19.0-dev-20261014211203",
|
|
4
4
|
"description": "The floor for keemakr marketplace agents: verify the capability grant and reach tenant connections, memory, and shared platform tools through keemakr-core — without holding raw secrets or resolving the tenant yourself.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|