@dataverse-kit/agent-kit 0.2.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/README.md +166 -0
- package/dist/core.cjs +532 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +278 -0
- package/dist/core.d.ts +278 -0
- package/dist/core.mjs +482 -0
- package/dist/core.mjs.map +1 -0
- package/dist/host.cjs +113 -0
- package/dist/host.cjs.map +1 -0
- package/dist/host.d.cts +3 -0
- package/dist/host.d.ts +3 -0
- package/dist/host.mjs +74 -0
- package/dist/host.mjs.map +1 -0
- package/dist/index-DGN6eYnp.d.cts +103 -0
- package/dist/index-DGN6eYnp.d.ts +103 -0
- package/dist/index.cjs +3145 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +863 -0
- package/dist/index.d.ts +863 -0
- package/dist/index.mjs +3068 -0
- package/dist/index.mjs.map +1 -0
- package/dist/protocol-CZJ1v9Hq.d.cts +270 -0
- package/dist/protocol-CZJ1v9Hq.d.ts +270 -0
- package/dist/services.cjs +333 -0
- package/dist/services.cjs.map +1 -0
- package/dist/services.d.cts +118 -0
- package/dist/services.d.ts +118 -0
- package/dist/services.mjs +300 -0
- package/dist/services.mjs.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
// src/services/scenarios.ts
|
|
2
|
+
var SOURCES = [
|
|
3
|
+
{ id: "src-acct", title: "Contoso Ltd", kind: "dataverse", entityLogicalName: "account", recordId: "11111111-1111-1111-1111-111111111111", snippet: "Annual revenue \xA34.2m, 38 employees." },
|
|
4
|
+
{ id: "src-case", title: "Case 4417 \u2014 invoice mismatch", kind: "dataverse", entityLogicalName: "incident", recordId: "22222222-2222-2222-2222-222222222222", snippet: "Raised 12 Mar, priority High." },
|
|
5
|
+
{ id: "src-kb", title: "KB-208: credit note policy", kind: "knowledge", url: "https://example.invalid/kb/208", snippet: "Credit notes above \xA35,000 require finance approval.", score: 0.82 },
|
|
6
|
+
{ id: "src-doc", title: "Statement-Mar.pdf", kind: "document", snippet: "Page 3 lists the disputed line." },
|
|
7
|
+
{ id: "src-web", title: "Companies House filing", kind: "web", url: "https://example.invalid/ch" }
|
|
8
|
+
];
|
|
9
|
+
var mockScenarios = {
|
|
10
|
+
happy: {
|
|
11
|
+
text: "Contoso has three open cases. The oldest, case 4417, has been waiting eleven days for a credit note.",
|
|
12
|
+
status: "succeeded",
|
|
13
|
+
suggestions: ["Draft a credit note", "Show all three cases", "Who owns case 4417?"]
|
|
14
|
+
},
|
|
15
|
+
// ★ FIVE sources, but the text cites only [3] and [1] — and out of order. The panel must
|
|
16
|
+
// show TWO, renumbered 1 and 2 in first-appearance order. A fixture where every source
|
|
17
|
+
// is cited cannot tell a correct implementation from one that lists everything it was given.
|
|
18
|
+
grounded: {
|
|
19
|
+
text: "Credit notes over \xA35,000 need finance approval [3], and case 4417 is for \xA36,200 [1]. So this one needs sign-off.",
|
|
20
|
+
status: "succeeded",
|
|
21
|
+
sources: SOURCES
|
|
22
|
+
},
|
|
23
|
+
toolApproval: {
|
|
24
|
+
text: "I can raise the credit note for you \u2014 approve the details below and I will submit it.",
|
|
25
|
+
status: "succeeded",
|
|
26
|
+
toolCall: {
|
|
27
|
+
id: "call-1",
|
|
28
|
+
name: "create_credit_note",
|
|
29
|
+
argumentsJson: '{"accountId":"11111111-1111-1111-1111-111111111111","amount":6200,"currency":"GBP","reason":"Invoice mismatch, case 4417"}',
|
|
30
|
+
status: "proposed",
|
|
31
|
+
requiresApproval: true
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
toolAuto: {
|
|
35
|
+
text: "I checked the balance for you.",
|
|
36
|
+
status: "succeeded",
|
|
37
|
+
toolCall: { id: "call-2", name: "get_account_balance", argumentsJson: '{"accountId":"1111"}', status: "running" },
|
|
38
|
+
autoToolResult: '{"balance":6200,"currency":"GBP"}'
|
|
39
|
+
},
|
|
40
|
+
// ★ blocked and refused MUST look different on screen: a content filter fired, versus the
|
|
41
|
+
// model declining. They need different fixes, so they are different states.
|
|
42
|
+
blocked: {
|
|
43
|
+
text: "I can\u2019t help with that request.",
|
|
44
|
+
status: "blocked",
|
|
45
|
+
guarded: true,
|
|
46
|
+
failureMessage: "The response was withheld by the content filter.",
|
|
47
|
+
failureCode: "content_filter",
|
|
48
|
+
recoverable: false
|
|
49
|
+
},
|
|
50
|
+
refused: {
|
|
51
|
+
text: "I don\u2019t have enough information to answer that safely. Could you say which account you mean?",
|
|
52
|
+
status: "refused",
|
|
53
|
+
failureMessage: "The agent declined to answer.",
|
|
54
|
+
recoverable: true
|
|
55
|
+
},
|
|
56
|
+
error: {
|
|
57
|
+
text: "",
|
|
58
|
+
status: "error",
|
|
59
|
+
failureMessage: "The agent is rate limited. Try again shortly.",
|
|
60
|
+
failureCode: "rate_limited",
|
|
61
|
+
recoverable: true,
|
|
62
|
+
retryAfterMs: 4e3
|
|
63
|
+
},
|
|
64
|
+
notProvisioned: {
|
|
65
|
+
text: "",
|
|
66
|
+
status: "notProvisioned",
|
|
67
|
+
failureMessage: "No Foundry project is configured for this environment.",
|
|
68
|
+
failureCode: "not_provisioned",
|
|
69
|
+
recoverable: false,
|
|
70
|
+
unavailable: true
|
|
71
|
+
},
|
|
72
|
+
cancelled: {
|
|
73
|
+
text: "Let me pull the last six months of activity for Contoso and work through it case by case, starting with the oldest\u2026",
|
|
74
|
+
status: "cancelled",
|
|
75
|
+
failureMessage: "Stopped."
|
|
76
|
+
},
|
|
77
|
+
// The fixture the autoscroll and live-region gates run against: enough deltas that
|
|
78
|
+
// "once, not per token" is a meaningful distinction.
|
|
79
|
+
longAnswer: {
|
|
80
|
+
text: Array.from({ length: 200 }, (_, i) => `word${i + 1}`).join(" "),
|
|
81
|
+
status: "succeeded"
|
|
82
|
+
},
|
|
83
|
+
throws: {
|
|
84
|
+
text: "partial\u2026",
|
|
85
|
+
status: "error",
|
|
86
|
+
throwsMidStream: true,
|
|
87
|
+
failureMessage: "never reached \u2014 the iterator throws instead"
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// src/services/MockAgentService.ts
|
|
92
|
+
var realScheduler = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
93
|
+
var immediateScheduler = () => Promise.resolve();
|
|
94
|
+
function mulberry32(seed) {
|
|
95
|
+
let a = seed >>> 0;
|
|
96
|
+
return () => {
|
|
97
|
+
a = a + 1831565813 >>> 0;
|
|
98
|
+
let t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
99
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
100
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
var MockAgentService = class {
|
|
104
|
+
constructor(options = {}) {
|
|
105
|
+
this.name = "mock";
|
|
106
|
+
this.scenarioName = options.scenario ?? "happy";
|
|
107
|
+
this.scenario = mockScenarios[this.scenarioName];
|
|
108
|
+
this.scheduler = options.scheduler ?? realScheduler;
|
|
109
|
+
this.firstTokenMs = options.firstTokenMs ?? 400;
|
|
110
|
+
this.chunkMs = options.chunkMs ?? 28;
|
|
111
|
+
this.rand = mulberry32(options.seed ?? 1);
|
|
112
|
+
this.availabilityOverride = options.availability;
|
|
113
|
+
}
|
|
114
|
+
async isAvailable() {
|
|
115
|
+
if (this.availabilityOverride) return this.availabilityOverride;
|
|
116
|
+
if (this.scenario.unavailable) {
|
|
117
|
+
return {
|
|
118
|
+
available: false,
|
|
119
|
+
status: "notProvisioned",
|
|
120
|
+
reason: this.scenario.failureMessage ?? "Not provisioned."
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
available: true,
|
|
125
|
+
capabilities: { streaming: true, tools: true, citations: true, attachments: true, cancel: true }
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* A prompt can select a scenario (`/blocked`, `/tool`, `/error`), so one story can walk
|
|
130
|
+
* every state without remounting.
|
|
131
|
+
*/
|
|
132
|
+
resolveScenario(promptText) {
|
|
133
|
+
const slash = promptText.trim().match(/^\/(\w+)/)?.[1];
|
|
134
|
+
if (slash && slash in mockScenarios) {
|
|
135
|
+
return { name: slash, scenario: mockScenarios[slash] };
|
|
136
|
+
}
|
|
137
|
+
return { name: this.scenarioName, scenario: this.scenario };
|
|
138
|
+
}
|
|
139
|
+
async *send(turn) {
|
|
140
|
+
const { scenario } = this.resolveScenario(turn.text);
|
|
141
|
+
const messageId = `mock-${Math.floor(this.rand() * 1e9).toString(36)}`;
|
|
142
|
+
const turnId = `turn-${messageId}`;
|
|
143
|
+
const provider = this.name;
|
|
144
|
+
const finish = (result) => ({
|
|
145
|
+
type: "turn_end",
|
|
146
|
+
turnId,
|
|
147
|
+
messageId,
|
|
148
|
+
result: { ...result, provider }
|
|
149
|
+
});
|
|
150
|
+
yield { type: "turn_start", turnId, messageId, provider, model: "mock-1" };
|
|
151
|
+
if (turn.cancelSignal?.aborted) {
|
|
152
|
+
yield finish({ status: "cancelled", text: "", failure: { status: "cancelled", message: "Stopped." } });
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (scenario.status === "notProvisioned" || scenario.status === "error" && !scenario.text) {
|
|
156
|
+
await this.scheduler(this.firstTokenMs);
|
|
157
|
+
yield finish({
|
|
158
|
+
status: scenario.status,
|
|
159
|
+
text: "",
|
|
160
|
+
failure: {
|
|
161
|
+
status: scenario.status,
|
|
162
|
+
message: scenario.failureMessage ?? "Failed.",
|
|
163
|
+
code: scenario.failureCode,
|
|
164
|
+
recoverable: scenario.recoverable,
|
|
165
|
+
retryAfterMs: scenario.retryAfterMs
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (scenario.sources) {
|
|
171
|
+
yield { type: "status", messageId, label: "Searching Dataverse\u2026" };
|
|
172
|
+
await this.scheduler(this.firstTokenMs);
|
|
173
|
+
yield { type: "sources", messageId, sources: scenario.sources };
|
|
174
|
+
}
|
|
175
|
+
if (scenario.thinking) {
|
|
176
|
+
yield { type: "thinking_delta", messageId, text: scenario.thinking };
|
|
177
|
+
}
|
|
178
|
+
if (scenario.toolCall) {
|
|
179
|
+
yield { type: "tool_call", messageId, call: scenario.toolCall };
|
|
180
|
+
if (scenario.autoToolResult !== void 0) {
|
|
181
|
+
await this.scheduler(this.chunkMs);
|
|
182
|
+
yield {
|
|
183
|
+
type: "tool_result",
|
|
184
|
+
messageId,
|
|
185
|
+
callId: scenario.toolCall.id,
|
|
186
|
+
status: "succeeded",
|
|
187
|
+
resultText: scenario.autoToolResult
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const chunks = scenario.chunks ?? scenario.text.split(/(?<=\s)/);
|
|
192
|
+
await this.scheduler(this.firstTokenMs);
|
|
193
|
+
let emitted = "";
|
|
194
|
+
for (const [i, chunk] of chunks.entries()) {
|
|
195
|
+
if (turn.cancelSignal?.aborted) {
|
|
196
|
+
yield finish({
|
|
197
|
+
status: "cancelled",
|
|
198
|
+
text: emitted,
|
|
199
|
+
failure: { status: "cancelled", message: "Stopped." }
|
|
200
|
+
});
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (scenario.throwsMidStream && i === Math.floor(chunks.length / 2)) {
|
|
204
|
+
throw new Error("mock transport exploded mid-stream");
|
|
205
|
+
}
|
|
206
|
+
emitted += chunk;
|
|
207
|
+
yield { type: "text_delta", messageId, text: chunk };
|
|
208
|
+
await this.scheduler(this.chunkMs);
|
|
209
|
+
}
|
|
210
|
+
if (scenario.suggestions) {
|
|
211
|
+
yield { type: "suggestions", messageId, prompts: scenario.suggestions };
|
|
212
|
+
}
|
|
213
|
+
const failed = scenario.status !== "succeeded";
|
|
214
|
+
yield finish({
|
|
215
|
+
status: scenario.status,
|
|
216
|
+
text: emitted,
|
|
217
|
+
guarded: scenario.guarded,
|
|
218
|
+
usage: {
|
|
219
|
+
inputTokens: 128,
|
|
220
|
+
outputTokens: chunks.length,
|
|
221
|
+
costUsd: Number((chunks.length * 2e-6).toFixed(6)),
|
|
222
|
+
durationMs: this.firstTokenMs + chunks.length * this.chunkMs,
|
|
223
|
+
model: "mock-1"
|
|
224
|
+
},
|
|
225
|
+
failure: failed ? {
|
|
226
|
+
status: scenario.status,
|
|
227
|
+
message: scenario.failureMessage ?? "Failed.",
|
|
228
|
+
code: scenario.failureCode,
|
|
229
|
+
recoverable: scenario.recoverable,
|
|
230
|
+
retryAfterMs: scenario.retryAfterMs
|
|
231
|
+
} : void 0
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// src/services/NullAgentService.ts
|
|
237
|
+
var NullAgentService = class {
|
|
238
|
+
constructor() {
|
|
239
|
+
this.name = "none";
|
|
240
|
+
}
|
|
241
|
+
async isAvailable() {
|
|
242
|
+
return {
|
|
243
|
+
available: false,
|
|
244
|
+
status: "notProvisioned",
|
|
245
|
+
reason: "No agent provider is configured for this host."
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
async *send(turn) {
|
|
249
|
+
const messageId = `null-${Date.now()}`;
|
|
250
|
+
const turnId = `turn-${messageId}`;
|
|
251
|
+
void turn;
|
|
252
|
+
yield { type: "turn_start", turnId, messageId, provider: this.name };
|
|
253
|
+
yield {
|
|
254
|
+
type: "turn_end",
|
|
255
|
+
turnId,
|
|
256
|
+
messageId,
|
|
257
|
+
result: {
|
|
258
|
+
status: "notProvisioned",
|
|
259
|
+
text: "",
|
|
260
|
+
provider: this.name,
|
|
261
|
+
failure: {
|
|
262
|
+
status: "notProvisioned",
|
|
263
|
+
message: "No agent provider is configured for this host.",
|
|
264
|
+
code: "not_provisioned",
|
|
265
|
+
recoverable: false
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// src/services/createAgentService.ts
|
|
273
|
+
function decide(config) {
|
|
274
|
+
switch (config.provider) {
|
|
275
|
+
case "custom":
|
|
276
|
+
return config.factory ? { provider: config.factory(), reason: "explicit factory (provider: custom)" } : { provider: new NullAgentService(), reason: "provider: custom but no factory supplied" };
|
|
277
|
+
case "mock":
|
|
278
|
+
return { provider: new MockAgentService(), reason: "provider: mock" };
|
|
279
|
+
case "none":
|
|
280
|
+
return { provider: new NullAgentService(), reason: "provider: none (the default)" };
|
|
281
|
+
default:
|
|
282
|
+
return {
|
|
283
|
+
provider: new NullAgentService(),
|
|
284
|
+
reason: `unrecognised provider ${String(config.provider)} \u2014 falling back to none`
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function createAgentService(config = { provider: "none" }) {
|
|
289
|
+
return decide(config).provider;
|
|
290
|
+
}
|
|
291
|
+
export {
|
|
292
|
+
MockAgentService,
|
|
293
|
+
NullAgentService,
|
|
294
|
+
createAgentService,
|
|
295
|
+
decide,
|
|
296
|
+
immediateScheduler,
|
|
297
|
+
mockScenarios,
|
|
298
|
+
realScheduler
|
|
299
|
+
};
|
|
300
|
+
//# sourceMappingURL=services.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/scenarios.ts","../src/services/MockAgentService.ts","../src/services/NullAgentService.ts","../src/services/createAgentService.ts"],"sourcesContent":["import type { AgentRunStatus, AgentSource, AgentToolCall } from '../core/protocol';\n\n/**\n * What the mock can be driven to do. There is one scenario per terminal state plus the\n * interesting mid-stream shapes, because a Storybook that cannot SHOW a state is a Storybook\n * in which that state is never reviewed — and a test suite that cannot REACH one is a suite\n * in which it is never asserted.\n */\nexport type MockScenarioName =\n | 'happy'\n | 'grounded'\n | 'toolApproval'\n | 'toolAuto'\n | 'blocked'\n | 'refused'\n | 'error'\n | 'notProvisioned'\n | 'cancelled'\n | 'longAnswer'\n | 'throws';\n\nexport interface MockScenario {\n /** The answer, streamed word by word unless `chunks` overrides it. */\n text: string;\n chunks?: string[];\n status: AgentRunStatus;\n guarded?: boolean;\n failureMessage?: string;\n failureCode?: string;\n recoverable?: boolean;\n retryAfterMs?: number;\n sources?: AgentSource[];\n /** Emitted mid-stream, before the terminal event. */\n toolCall?: AgentToolCall;\n /** When set, the tool resolves itself rather than waiting for host approval. */\n autoToolResult?: string;\n suggestions?: string[];\n thinking?: string;\n /** Throw from inside the iterator — the failure channel a Promise-shaped seam does not have. */\n throwsMidStream?: boolean;\n /** Never becomes available; `send()` still yields a well-formed turn. */\n unavailable?: boolean;\n}\n\nconst SOURCES: AgentSource[] = [\n { id: 'src-acct', title: 'Contoso Ltd', kind: 'dataverse', entityLogicalName: 'account', recordId: '11111111-1111-1111-1111-111111111111', snippet: 'Annual revenue £4.2m, 38 employees.' },\n { id: 'src-case', title: 'Case 4417 — invoice mismatch', kind: 'dataverse', entityLogicalName: 'incident', recordId: '22222222-2222-2222-2222-222222222222', snippet: 'Raised 12 Mar, priority High.' },\n { id: 'src-kb', title: 'KB-208: credit note policy', kind: 'knowledge', url: 'https://example.invalid/kb/208', snippet: 'Credit notes above £5,000 require finance approval.', score: 0.82 },\n { id: 'src-doc', title: 'Statement-Mar.pdf', kind: 'document', snippet: 'Page 3 lists the disputed line.' },\n { id: 'src-web', title: 'Companies House filing', kind: 'web', url: 'https://example.invalid/ch' },\n];\n\nexport const mockScenarios: Record<MockScenarioName, MockScenario> = {\n happy: {\n text: 'Contoso has three open cases. The oldest, case 4417, has been waiting eleven days for a credit note.',\n status: 'succeeded',\n suggestions: ['Draft a credit note', 'Show all three cases', 'Who owns case 4417?'],\n },\n\n // ★ FIVE sources, but the text cites only [3] and [1] — and out of order. The panel must\n // show TWO, renumbered 1 and 2 in first-appearance order. A fixture where every source\n // is cited cannot tell a correct implementation from one that lists everything it was given.\n grounded: {\n text: 'Credit notes over £5,000 need finance approval [3], and case 4417 is for £6,200 [1]. So this one needs sign-off.',\n status: 'succeeded',\n sources: SOURCES,\n },\n\n toolApproval: {\n text: 'I can raise the credit note for you — approve the details below and I will submit it.',\n status: 'succeeded',\n toolCall: {\n id: 'call-1',\n name: 'create_credit_note',\n argumentsJson: '{\"accountId\":\"11111111-1111-1111-1111-111111111111\",\"amount\":6200,\"currency\":\"GBP\",\"reason\":\"Invoice mismatch, case 4417\"}',\n status: 'proposed',\n requiresApproval: true,\n },\n },\n\n toolAuto: {\n text: 'I checked the balance for you.',\n status: 'succeeded',\n toolCall: { id: 'call-2', name: 'get_account_balance', argumentsJson: '{\"accountId\":\"1111\"}', status: 'running' },\n autoToolResult: '{\"balance\":6200,\"currency\":\"GBP\"}',\n },\n\n // ★ blocked and refused MUST look different on screen: a content filter fired, versus the\n // model declining. They need different fixes, so they are different states.\n blocked: {\n text: 'I can’t help with that request.',\n status: 'blocked',\n guarded: true,\n failureMessage: 'The response was withheld by the content filter.',\n failureCode: 'content_filter',\n recoverable: false,\n },\n\n refused: {\n text: 'I don’t have enough information to answer that safely. Could you say which account you mean?',\n status: 'refused',\n failureMessage: 'The agent declined to answer.',\n recoverable: true,\n },\n\n error: {\n text: '',\n status: 'error',\n failureMessage: 'The agent is rate limited. Try again shortly.',\n failureCode: 'rate_limited',\n recoverable: true,\n retryAfterMs: 4000,\n },\n\n notProvisioned: {\n text: '',\n status: 'notProvisioned',\n failureMessage: 'No Foundry project is configured for this environment.',\n failureCode: 'not_provisioned',\n recoverable: false,\n unavailable: true,\n },\n\n cancelled: {\n text: 'Let me pull the last six months of activity for Contoso and work through it case by case, starting with the oldest…',\n status: 'cancelled',\n failureMessage: 'Stopped.',\n },\n\n // The fixture the autoscroll and live-region gates run against: enough deltas that\n // \"once, not per token\" is a meaningful distinction.\n longAnswer: {\n text: Array.from({ length: 200 }, (_, i) => `word${i + 1}`).join(' '),\n status: 'succeeded',\n },\n\n throws: {\n text: 'partial…',\n status: 'error',\n throwsMidStream: true,\n failureMessage: 'never reached — the iterator throws instead',\n },\n};\n","import type {\n AgentAvailability,\n AgentEvent,\n AgentTurn,\n AgentTurnResult,\n IAgentService,\n} from '../core/protocol';\nimport { mockScenarios, type MockScenario, type MockScenarioName } from './scenarios';\n\n/** Injectable so tests run at zero delay and Storybook runs at human speed. */\nexport type Scheduler = (ms: number) => Promise<void>;\n\nexport const realScheduler: Scheduler = (ms) =>\n new Promise((resolve) => setTimeout(resolve, ms));\nexport const immediateScheduler: Scheduler = () => Promise.resolve();\n\nexport interface MockAgentServiceOptions {\n scenario?: MockScenarioName;\n scheduler?: Scheduler;\n /** Delay before the first token, so the typing indicator is visible and screenshottable. */\n firstTokenMs?: number;\n chunkMs?: number;\n /**\n * ★ A CONSTRUCTOR ARGUMENT, never module state.\n *\n * tsup runs with `splitting: false`, so every entry gets a self-contained bundle and any\n * module-level `let` is physically duplicated per entry — a story importing from `.` and a\n * test importing from `./services` would get two independent counters. Measured on\n * surface-kit: three copies of the same function body across its entries.\n */\n seed?: number;\n /** Override availability; otherwise derived from the scenario. */\n availability?: AgentAvailability;\n}\n\n/** A tiny deterministic PRNG so Chromatic snapshots do not drift. */\nfunction mulberry32(seed: number): () => number {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * The in-package fake. It is the only \"provider\" agent-kit ships: real transports (Foundry,\n * Copilot Studio, a broker) live in the consuming app, so the kit never holds a credential.\n *\n * ★ It can reach EVERY `AgentRunStatus`. A test asserts that, because a mock that cannot\n * produce a state is a state nothing downstream is ever tested against.\n */\nexport class MockAgentService implements IAgentService {\n readonly name = 'mock';\n\n private readonly scenario: MockScenario;\n private readonly scenarioName: MockScenarioName;\n private readonly scheduler: Scheduler;\n private readonly firstTokenMs: number;\n private readonly chunkMs: number;\n private readonly rand: () => number;\n private readonly availabilityOverride?: AgentAvailability;\n\n constructor(options: MockAgentServiceOptions = {}) {\n this.scenarioName = options.scenario ?? 'happy';\n this.scenario = mockScenarios[this.scenarioName];\n this.scheduler = options.scheduler ?? realScheduler;\n this.firstTokenMs = options.firstTokenMs ?? 400;\n this.chunkMs = options.chunkMs ?? 28;\n this.rand = mulberry32(options.seed ?? 1);\n this.availabilityOverride = options.availability;\n }\n\n async isAvailable(): Promise<AgentAvailability> {\n if (this.availabilityOverride) return this.availabilityOverride;\n if (this.scenario.unavailable) {\n return {\n available: false,\n status: 'notProvisioned',\n reason: this.scenario.failureMessage ?? 'Not provisioned.',\n };\n }\n return {\n available: true,\n capabilities: { streaming: true, tools: true, citations: true, attachments: true, cancel: true },\n };\n }\n\n /**\n * A prompt can select a scenario (`/blocked`, `/tool`, `/error`), so one story can walk\n * every state without remounting.\n */\n private resolveScenario(promptText: string): { name: MockScenarioName; scenario: MockScenario } {\n const slash = promptText.trim().match(/^\\/(\\w+)/)?.[1] as MockScenarioName | undefined;\n if (slash && slash in mockScenarios) {\n return { name: slash, scenario: mockScenarios[slash] };\n }\n return { name: this.scenarioName, scenario: this.scenario };\n }\n\n async *send(turn: AgentTurn): AsyncIterable<AgentEvent> {\n const { scenario } = this.resolveScenario(turn.text);\n const messageId = `mock-${Math.floor(this.rand() * 1e9).toString(36)}`;\n const turnId = `turn-${messageId}`;\n const provider = this.name;\n\n const finish = (result: Omit<AgentTurnResult, 'provider'>): AgentEvent => ({\n type: 'turn_end',\n turnId,\n messageId,\n result: { ...result, provider },\n });\n\n yield { type: 'turn_start', turnId, messageId, provider, model: 'mock-1' };\n\n if (turn.cancelSignal?.aborted) {\n yield finish({ status: 'cancelled', text: '', failure: { status: 'cancelled', message: 'Stopped.' } });\n return;\n }\n\n // Terminal-before-any-text scenarios still emit a well-formed turn.\n if (scenario.status === 'notProvisioned' || (scenario.status === 'error' && !scenario.text)) {\n await this.scheduler(this.firstTokenMs);\n yield finish({\n status: scenario.status,\n text: '',\n failure: {\n status: scenario.status,\n message: scenario.failureMessage ?? 'Failed.',\n code: scenario.failureCode,\n recoverable: scenario.recoverable,\n retryAfterMs: scenario.retryAfterMs,\n },\n });\n return;\n }\n\n if (scenario.sources) {\n yield { type: 'status', messageId, label: 'Searching Dataverse…' };\n await this.scheduler(this.firstTokenMs);\n yield { type: 'sources', messageId, sources: scenario.sources };\n }\n\n if (scenario.thinking) {\n yield { type: 'thinking_delta', messageId, text: scenario.thinking };\n }\n\n if (scenario.toolCall) {\n yield { type: 'tool_call', messageId, call: scenario.toolCall };\n if (scenario.autoToolResult !== undefined) {\n await this.scheduler(this.chunkMs);\n yield {\n type: 'tool_result',\n messageId,\n callId: scenario.toolCall.id,\n status: 'succeeded',\n resultText: scenario.autoToolResult,\n };\n }\n }\n\n const chunks = scenario.chunks ?? scenario.text.split(/(?<=\\s)/);\n await this.scheduler(this.firstTokenMs);\n\n let emitted = '';\n for (const [i, chunk] of chunks.entries()) {\n if (turn.cancelSignal?.aborted) {\n yield finish({\n status: 'cancelled',\n text: emitted,\n failure: { status: 'cancelled', message: 'Stopped.' },\n });\n return;\n }\n if (scenario.throwsMidStream && i === Math.floor(chunks.length / 2)) {\n // The failure channel an AsyncIterable has and a Promise does not. A consumer must\n // surface this as a notice, not by unmounting the tree.\n throw new Error('mock transport exploded mid-stream');\n }\n emitted += chunk;\n yield { type: 'text_delta', messageId, text: chunk };\n await this.scheduler(this.chunkMs);\n }\n\n if (scenario.suggestions) {\n yield { type: 'suggestions', messageId, prompts: scenario.suggestions };\n }\n\n const failed = scenario.status !== 'succeeded';\n yield finish({\n status: scenario.status,\n text: emitted,\n guarded: scenario.guarded,\n usage: {\n inputTokens: 128,\n outputTokens: chunks.length,\n costUsd: Number((chunks.length * 0.000002).toFixed(6)),\n durationMs: this.firstTokenMs + chunks.length * this.chunkMs,\n model: 'mock-1',\n },\n failure: failed\n ? {\n status: scenario.status as Exclude<typeof scenario.status, 'succeeded'>,\n message: scenario.failureMessage ?? 'Failed.',\n code: scenario.failureCode,\n recoverable: scenario.recoverable,\n retryAfterMs: scenario.retryAfterMs,\n }\n : undefined,\n });\n }\n}\n","import type { AgentAvailability, AgentEvent, AgentTurn, IAgentService } from '../core/protocol';\n\n/**\n * The default provider: answers nothing, politely.\n *\n * ★ `none` is the DEFAULT and must stay so. A kit dropped into a host nobody has wired must\n * not silently start talking to a service because someone shipped a new build. Carried\n * from `ILlmService`, where the same rule is load-bearing in a regulated process.\n *\n * ★ It still yields a well-formed turn — `turn_start` then one `turn_end` — rather than\n * throwing or yielding nothing. An unconfigured kit should render \"not configured\", not\n * a spinner that never resolves.\n */\nexport class NullAgentService implements IAgentService {\n readonly name = 'none';\n\n async isAvailable(): Promise<AgentAvailability> {\n return {\n available: false,\n status: 'notProvisioned',\n reason: 'No agent provider is configured for this host.',\n };\n }\n\n async *send(turn: AgentTurn): AsyncIterable<AgentEvent> {\n const messageId = `null-${Date.now()}`;\n const turnId = `turn-${messageId}`;\n void turn;\n yield { type: 'turn_start', turnId, messageId, provider: this.name };\n yield {\n type: 'turn_end',\n turnId,\n messageId,\n result: {\n status: 'notProvisioned',\n text: '',\n provider: this.name,\n failure: {\n status: 'notProvisioned',\n message: 'No agent provider is configured for this host.',\n code: 'not_provisioned',\n recoverable: false,\n },\n },\n };\n }\n}\n","import type { AgentServiceConfig, IAgentService } from '../core/protocol';\nimport { MockAgentService } from './MockAgentService';\nimport { NullAgentService } from './NullAgentService';\n\nexport interface ServiceDecision {\n provider: IAgentService;\n /** Why this one was chosen — surfaced in diagnostics so a misconfiguration is legible. */\n reason: string;\n}\n\n/**\n * Provider selection, as ONE ladder.\n *\n * ★ `decide()` is exported alongside `createAgentService()` and they share a return type, so\n * the factory and any diagnostics view cannot drift — the shape `ServiceFactory.decide()`\n * uses in `@dataverse-kit/api-service` for exactly the same reason.\n *\n * ★ An UNRECOGNISED provider name falls back to `none`, never to a working provider. Carried\n * from `createLlmService`: a typo must produce silence, not an unintended call to a model.\n */\nexport function decide(config: AgentServiceConfig): ServiceDecision {\n switch (config.provider) {\n case 'custom':\n return config.factory\n ? { provider: config.factory(), reason: 'explicit factory (provider: custom)' }\n : { provider: new NullAgentService(), reason: 'provider: custom but no factory supplied' };\n case 'mock':\n return { provider: new MockAgentService(), reason: 'provider: mock' };\n case 'none':\n return { provider: new NullAgentService(), reason: 'provider: none (the default)' };\n default:\n return {\n provider: new NullAgentService(),\n reason: `unrecognised provider ${String(config.provider)} — falling back to none`,\n };\n }\n}\n\nexport function createAgentService(\n config: AgentServiceConfig = { provider: 'none' },\n): IAgentService {\n return decide(config).provider;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dataverse-kit/agent-kit",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Fluent UI v9 conversational and agent surfaces for Dynamics 365 — message thread, composer, streaming, citations, approval cards and a Teams-like app shell, styled as Dynamics CE. Ships one presentational IAgentService seam plus a MockAgentService; real transports (Foundry, Copilot Studio, broker) stay in the consuming app. The pure-TS ./core and ./services subpaths are framework-agnostic.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./core": {
|
|
17
|
+
"types": "./dist/core.d.ts",
|
|
18
|
+
"import": "./dist/core.mjs",
|
|
19
|
+
"require": "./dist/core.cjs"
|
|
20
|
+
},
|
|
21
|
+
"./services": {
|
|
22
|
+
"types": "./dist/services.d.ts",
|
|
23
|
+
"import": "./dist/services.mjs",
|
|
24
|
+
"require": "./dist/services.cjs"
|
|
25
|
+
},
|
|
26
|
+
"./host": {
|
|
27
|
+
"types": "./dist/host.d.ts",
|
|
28
|
+
"import": "./dist/host.mjs",
|
|
29
|
+
"require": "./dist/host.cjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"sideEffects": [
|
|
36
|
+
"**/*.css"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"prepublishOnly": "npm run build",
|
|
40
|
+
"prebuild": "cd ../design-tokens && npm run build && cd ../fluent-theme && npm run build && cd ../surface-kit && npm run build",
|
|
41
|
+
"build": "tsup",
|
|
42
|
+
"dev": "tsup --watch",
|
|
43
|
+
"postbuild": "node scripts/assert-no-react.mjs",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"test:watch": "vitest",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"typecheck:stories": "tsc -p tsconfig.stories.json",
|
|
48
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
49
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
50
|
+
"storybook": "storybook dev -p 6011",
|
|
51
|
+
"build-storybook": "storybook build",
|
|
52
|
+
"clean": "rimraf dist coverage tsconfig.tsbuildinfo storybook-static"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@dataverse-kit/design-tokens": "^0.1.1",
|
|
56
|
+
"@dataverse-kit/fluent-theme": "^0.2.0",
|
|
57
|
+
"@dataverse-kit/surface-kit": "^0.4.1"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"@fluentui/react-components": "^9.46.2",
|
|
61
|
+
"@fluentui/react-icons": "^2.0.239",
|
|
62
|
+
"react": "^18.2.0",
|
|
63
|
+
"react-dom": "^18.2.0"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@fluentui/react-components": "^9.46.2",
|
|
67
|
+
"@fluentui/react-icons": "^2.0.239",
|
|
68
|
+
"@storybook/addon-docs": "^10.4.4",
|
|
69
|
+
"@storybook/react-vite": "^10.4.4",
|
|
70
|
+
"@testing-library/react": "^14.0.0",
|
|
71
|
+
"@testing-library/user-event": "^14.5.1",
|
|
72
|
+
"@types/react": "^18.2.45",
|
|
73
|
+
"@types/react-dom": "^18.2.18",
|
|
74
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
75
|
+
"axe-core": "^4.10.3",
|
|
76
|
+
"jsdom": "^25.0.0",
|
|
77
|
+
"react": "^18.2.0",
|
|
78
|
+
"react-dom": "^18.2.0",
|
|
79
|
+
"rimraf": "^5.0.5",
|
|
80
|
+
"storybook": "^10.4.4",
|
|
81
|
+
"tsup": "^8.0.0",
|
|
82
|
+
"typescript": "^5.3.3",
|
|
83
|
+
"vite": "^7.3.5",
|
|
84
|
+
"vitest": "^1.6.0"
|
|
85
|
+
},
|
|
86
|
+
"publishConfig": {
|
|
87
|
+
"access": "public"
|
|
88
|
+
}
|
|
89
|
+
}
|