@dxos/assistant 0.8.0 → 0.8.1-main.a06ad20
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/lib/browser/index.mjs +976 -536
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +2 -2
- package/dist/lib/browser/testing/index.mjs.map +1 -1
- package/dist/lib/node/index.cjs +1172 -735
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +22 -22
- package/dist/lib/node/testing/index.cjs.map +2 -2
- package/dist/lib/node-esm/index.mjs +976 -536
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +2 -2
- package/dist/lib/node-esm/testing/index.mjs.map +1 -1
- package/dist/types/src/ai-service/edge-client.d.ts +19 -0
- package/dist/types/src/ai-service/edge-client.d.ts.map +1 -0
- package/dist/types/src/ai-service/index.d.ts +4 -1
- package/dist/types/src/ai-service/index.d.ts.map +1 -1
- package/dist/types/src/ai-service/message-collector.d.ts +88 -0
- package/dist/types/src/ai-service/message-collector.d.ts.map +1 -0
- package/dist/types/src/ai-service/ollama-client.d.ts +43 -0
- package/dist/types/src/ai-service/ollama-client.d.ts.map +1 -0
- package/dist/types/src/ai-service/parser.d.ts +3 -1
- package/dist/types/src/ai-service/parser.d.ts.map +1 -1
- package/dist/types/src/ai-service/service.d.ts +9 -0
- package/dist/types/src/ai-service/service.d.ts.map +1 -0
- package/dist/types/src/ai-service/stream.d.ts +2 -1
- package/dist/types/src/ai-service/stream.d.ts.map +1 -1
- package/dist/types/src/ai-service/testing/mock.d.ts +2 -2
- package/dist/types/src/ai-service/testing/mock.d.ts.map +1 -1
- package/dist/types/src/ai-service/types.d.ts +3 -3
- package/dist/types/src/ai-service/types.d.ts.map +1 -1
- package/dist/types/src/conversation/conversation.d.ts +3 -1
- package/dist/types/src/conversation/conversation.d.ts.map +1 -1
- package/dist/types/src/conversation/types.d.ts +1 -1
- package/dist/types/src/conversation/types.d.ts.map +1 -1
- package/dist/types/src/testing/query-promts.d.ts +1 -1
- package/dist/types/src/testing/query-promts.d.ts.map +1 -1
- package/dist/types/src/testing/test-data.d.ts +1 -1
- package/dist/types/src/testing/test-data.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +1 -1
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/package.json +17 -14
- package/src/ai-service/client.test.ts +94 -7
- package/src/ai-service/{client.ts → edge-client.ts} +15 -24
- package/src/ai-service/index.ts +4 -1
- package/src/ai-service/message-collector.ts +84 -0
- package/src/ai-service/ollama-client.ts +473 -0
- package/src/ai-service/parser.ts +7 -2
- package/src/ai-service/service.ts +15 -0
- package/src/ai-service/stream.ts +5 -3
- package/src/ai-service/testing/mock.ts +7 -2
- package/src/ai-service/types.ts +1 -1
- package/src/bin/chat.ts +2 -2
- package/src/conversation/conversation.test.ts +3 -3
- package/src/conversation/conversation.ts +3 -2
- package/src/conversation/types.ts +1 -1
- package/src/testing/artifacts.test.ts +2 -2
- package/src/testing/query-promts.ts +1 -1
- package/src/testing/query.test.ts +2 -2
- package/src/testing/test-data.ts +1 -1
- package/src/testing/test-schema.ts +1 -1
- package/dist/types/src/ai-service/client.d.ts +0 -25
- package/dist/types/src/ai-service/client.d.ts.map +0 -1
package/dist/lib/node/index.cjs
CHANGED
|
@@ -28,18 +28,21 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
var node_exports = {};
|
|
30
30
|
__export(node_exports, {
|
|
31
|
-
|
|
31
|
+
AIServiceEdgeClient: () => AIServiceEdgeClient,
|
|
32
32
|
DEFAULT_LLM_MODEL: () => DEFAULT_LLM_MODEL,
|
|
33
33
|
DEFAULT_LLM_MODELS: () => DEFAULT_LLM_MODELS,
|
|
34
34
|
EchoDataSource: () => import_chunk_QPHGQINW.EchoDataSource,
|
|
35
35
|
GenerateRequest: () => GenerateRequest,
|
|
36
|
-
|
|
36
|
+
GenerationStreamImpl: () => GenerationStreamImpl,
|
|
37
37
|
LLMModel: () => LLMModel,
|
|
38
|
+
MessageCollector: () => MessageCollector,
|
|
38
39
|
MixedStreamParser: () => MixedStreamParser,
|
|
40
|
+
OllamaClient: () => OllamaClient,
|
|
39
41
|
StreamTransform: () => StreamTransform,
|
|
40
42
|
ToolTypes: () => ToolTypes,
|
|
41
43
|
createArtifactElement: () => createArtifactElement,
|
|
42
44
|
createGenerationStream: () => createGenerationStream,
|
|
45
|
+
emitMessageAsEvents: () => emitMessageAsEvents,
|
|
43
46
|
executeQuery: () => import_chunk_QPHGQINW.executeQuery,
|
|
44
47
|
executeQueryPlan: () => import_chunk_QPHGQINW.executeQueryPlan,
|
|
45
48
|
formatInferredRelationshipLabel: () => import_chunk_QPHGQINW.formatInferredRelationshipLabel,
|
|
@@ -54,26 +57,45 @@ __export(node_exports, {
|
|
|
54
57
|
});
|
|
55
58
|
module.exports = __toCommonJS(node_exports);
|
|
56
59
|
var import_chunk_QPHGQINW = require("./chunk-QPHGQINW.cjs");
|
|
57
|
-
var
|
|
60
|
+
var import_effect = require("effect");
|
|
58
61
|
var import_artifact = require("@dxos/artifact");
|
|
59
62
|
var import_invariant = require("@dxos/invariant");
|
|
60
63
|
var import_log = require("@dxos/log");
|
|
61
64
|
var import_async = require("@dxos/async");
|
|
62
65
|
var import_log2 = require("@dxos/log");
|
|
63
66
|
var import_artifact2 = require("@dxos/artifact");
|
|
64
|
-
var import_async2 = require("@dxos/async");
|
|
65
67
|
var import_echo_schema = require("@dxos/echo-schema");
|
|
66
68
|
var import_invariant2 = require("@dxos/invariant");
|
|
67
69
|
var import_log3 = require("@dxos/log");
|
|
68
|
-
var
|
|
69
|
-
var P = __toESM(require("parsimmon"));
|
|
70
|
-
var import_schema2 = require("@effect/schema");
|
|
70
|
+
var import_effect2 = require("effect");
|
|
71
71
|
var import_artifact3 = require("@dxos/artifact");
|
|
72
72
|
var import_echo_schema2 = require("@dxos/echo-schema");
|
|
73
73
|
var import_artifact4 = require("@dxos/artifact");
|
|
74
74
|
var import_echo_schema3 = require("@dxos/echo-schema");
|
|
75
75
|
var import_invariant3 = require("@dxos/invariant");
|
|
76
76
|
var import_log4 = require("@dxos/log");
|
|
77
|
+
var import_artifact5 = require("@dxos/artifact");
|
|
78
|
+
var import_async2 = require("@dxos/async");
|
|
79
|
+
var import_echo_schema4 = require("@dxos/echo-schema");
|
|
80
|
+
var import_invariant4 = require("@dxos/invariant");
|
|
81
|
+
var import_log5 = require("@dxos/log");
|
|
82
|
+
var import_util = require("@dxos/util");
|
|
83
|
+
var P = __toESM(require("parsimmon"));
|
|
84
|
+
var DEFAULT_LLM_MODEL = "@anthropic/claude-3-5-sonnet-20241022";
|
|
85
|
+
var DEFAULT_LLM_MODELS = [
|
|
86
|
+
// AI Gateway.
|
|
87
|
+
// https://developers.cloudflare.com/ai-gateway
|
|
88
|
+
"@anthropic/claude-3-5-haiku-20241022",
|
|
89
|
+
"@anthropic/claude-3-5-sonnet-20241022",
|
|
90
|
+
"@anthropic/claude-3-7-sonnet-20250219",
|
|
91
|
+
// Workers AI.
|
|
92
|
+
// https://developers.cloudflare.com/workers-ai/models
|
|
93
|
+
"@cf/deepseek-ai/deepseek-r1-distill-qwen-32b",
|
|
94
|
+
"@hf/nousresearch/hermes-2-pro-mistral-7b",
|
|
95
|
+
"@ollama/llama-3-1-nemotron-70b-instruct",
|
|
96
|
+
"@ollama/llama-3-1-nemotron-mini-4b-instruct",
|
|
97
|
+
"@ollama/llama-3-2-3b"
|
|
98
|
+
];
|
|
77
99
|
async function* iterSSEMessages(response, controller) {
|
|
78
100
|
if (!response.body) {
|
|
79
101
|
controller.abort();
|
|
@@ -321,7 +343,7 @@ var createGenerationStream = (response, controller = new AbortController()) => {
|
|
|
321
343
|
raw: sse.raw
|
|
322
344
|
}, {
|
|
323
345
|
F: __dxlog_file,
|
|
324
|
-
L:
|
|
346
|
+
L: 22,
|
|
325
347
|
S: this,
|
|
326
348
|
C: (f, a) => f(...a)
|
|
327
349
|
});
|
|
@@ -337,7 +359,7 @@ var createGenerationStream = (response, controller = new AbortController()) => {
|
|
|
337
359
|
raw: sse.raw
|
|
338
360
|
}, {
|
|
339
361
|
F: __dxlog_file,
|
|
340
|
-
L:
|
|
362
|
+
L: 38,
|
|
341
363
|
S: this,
|
|
342
364
|
C: (f, a) => f(...a)
|
|
343
365
|
});
|
|
@@ -352,9 +374,9 @@ var createGenerationStream = (response, controller = new AbortController()) => {
|
|
|
352
374
|
}
|
|
353
375
|
}
|
|
354
376
|
};
|
|
355
|
-
return new
|
|
377
|
+
return new GenerationStreamImpl(controller, iterator);
|
|
356
378
|
};
|
|
357
|
-
var
|
|
379
|
+
var GenerationStreamImpl = class {
|
|
358
380
|
constructor(_controller, _getIterator) {
|
|
359
381
|
this._controller = _controller;
|
|
360
382
|
this._getIterator = _getIterator;
|
|
@@ -393,18 +415,19 @@ var GenerationStream = class {
|
|
|
393
415
|
this._done.wake();
|
|
394
416
|
} catch (err) {
|
|
395
417
|
this._done.throw(err);
|
|
418
|
+
throw err;
|
|
396
419
|
}
|
|
397
420
|
};
|
|
398
421
|
return generator.call(this);
|
|
399
422
|
})();
|
|
400
423
|
}
|
|
401
424
|
};
|
|
402
|
-
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/experimental/assistant/src/ai-service/client.ts";
|
|
403
|
-
var
|
|
425
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/experimental/assistant/src/ai-service/edge-client.ts";
|
|
426
|
+
var AIServiceEdgeClient = class {
|
|
404
427
|
constructor({ endpoint }) {
|
|
405
428
|
(0, import_invariant.invariant)(endpoint, "endpoint is required", {
|
|
406
429
|
F: __dxlog_file2,
|
|
407
|
-
L:
|
|
430
|
+
L: 23,
|
|
408
431
|
S: this,
|
|
409
432
|
A: [
|
|
410
433
|
"endpoint",
|
|
@@ -413,6 +436,10 @@ var AIServiceClientImpl = class {
|
|
|
413
436
|
});
|
|
414
437
|
this._endpoint = endpoint;
|
|
415
438
|
}
|
|
439
|
+
/**
|
|
440
|
+
* @deprecated
|
|
441
|
+
*/
|
|
442
|
+
// TODO(burdon): Remove.
|
|
416
443
|
async appendMessages(messages) {
|
|
417
444
|
const url = `${this._endpoint}/message`;
|
|
418
445
|
const res = await fetch(url, {
|
|
@@ -421,7 +448,7 @@ var AIServiceClientImpl = class {
|
|
|
421
448
|
"Content-Type": "application/json"
|
|
422
449
|
},
|
|
423
450
|
body: JSON.stringify({
|
|
424
|
-
messages: await
|
|
451
|
+
messages: await import_effect.Schema.encodePromise(import_effect.Schema.Array(import_artifact.Message))(messages)
|
|
425
452
|
})
|
|
426
453
|
});
|
|
427
454
|
if (!res.ok) {
|
|
@@ -432,15 +459,11 @@ var AIServiceClientImpl = class {
|
|
|
432
459
|
* Process request and open message stream.
|
|
433
460
|
*/
|
|
434
461
|
async exec(request) {
|
|
435
|
-
request = {
|
|
436
|
-
tools: request.tools ?? [],
|
|
437
|
-
...request
|
|
438
|
-
};
|
|
439
462
|
import_log.log.info("requesting", {
|
|
440
463
|
endpoint: this._endpoint
|
|
441
464
|
}, {
|
|
442
465
|
F: __dxlog_file2,
|
|
443
|
-
L:
|
|
466
|
+
L: 50,
|
|
444
467
|
S: this,
|
|
445
468
|
C: (f, a) => f(...a)
|
|
446
469
|
});
|
|
@@ -451,11 +474,15 @@ var AIServiceClientImpl = class {
|
|
|
451
474
|
headers: {
|
|
452
475
|
"Content-Type": "application/json"
|
|
453
476
|
},
|
|
454
|
-
body: JSON.stringify(
|
|
477
|
+
body: JSON.stringify({
|
|
478
|
+
// TODO(dmaretskyi): Errors if tools are not provided.
|
|
479
|
+
tools: request.tools ?? [],
|
|
480
|
+
...request
|
|
481
|
+
})
|
|
455
482
|
});
|
|
456
483
|
(0, import_invariant.invariant)(response.body instanceof ReadableStream, void 0, {
|
|
457
484
|
F: __dxlog_file2,
|
|
458
|
-
L:
|
|
485
|
+
L: 63,
|
|
459
486
|
S: this,
|
|
460
487
|
A: [
|
|
461
488
|
"response.body instanceof ReadableStream",
|
|
@@ -465,807 +492,1217 @@ var AIServiceClientImpl = class {
|
|
|
465
492
|
return createGenerationStream(response, controller);
|
|
466
493
|
}
|
|
467
494
|
};
|
|
468
|
-
var
|
|
469
|
-
var DEFAULT_LLM_MODELS = [
|
|
470
|
-
// AI Gateway.
|
|
471
|
-
// https://developers.cloudflare.com/ai-gateway
|
|
472
|
-
"@anthropic/claude-3-5-haiku-20241022",
|
|
473
|
-
"@anthropic/claude-3-5-sonnet-20241022",
|
|
474
|
-
"@anthropic/claude-3-7-sonnet-20250219",
|
|
475
|
-
// Workers AI.
|
|
476
|
-
// https://developers.cloudflare.com/workers-ai/models
|
|
477
|
-
"@cf/deepseek-ai/deepseek-r1-distill-qwen-32b",
|
|
478
|
-
"@hf/nousresearch/hermes-2-pro-mistral-7b",
|
|
479
|
-
"@ollama/llama-3-1-nemotron-70b-instruct",
|
|
480
|
-
"@ollama/llama-3-1-nemotron-mini-4b-instruct",
|
|
481
|
-
"@ollama/llama-3-2-3b"
|
|
482
|
-
];
|
|
483
|
-
var textChunk = P.regexp(/[^<]+/).map((content) => ({
|
|
484
|
-
type: "text",
|
|
485
|
-
content
|
|
486
|
-
}));
|
|
487
|
-
var attribute = P.seq(P.regexp(/[a-zA-Z_][a-zA-Z0-9_-]*/), P.string("=").trim(P.optWhitespace), P.alt(P.regexp(/"[^"]*"/).map((s) => s.slice(1, -1)), P.regexp(/'[^']*'/).map((s) => s.slice(1, -1)))).map(([name, _, value]) => [
|
|
488
|
-
name,
|
|
489
|
-
value
|
|
490
|
-
]);
|
|
491
|
-
var tagName = P.regexp(/[a-zA-Z_][a-zA-Z0-9_-]*/);
|
|
492
|
-
var selfClosingTag = P.seqMap(
|
|
493
|
-
//
|
|
494
|
-
P.string("<"),
|
|
495
|
-
tagName,
|
|
496
|
-
P.optWhitespace.then(attribute).many(),
|
|
497
|
-
P.optWhitespace.then(P.string("/>")),
|
|
498
|
-
P.optWhitespace,
|
|
499
|
-
(_, tag, attributes, __) => ({
|
|
500
|
-
type: "tag",
|
|
501
|
-
tag,
|
|
502
|
-
attributes: Object.fromEntries(attributes),
|
|
503
|
-
content: [],
|
|
504
|
-
selfClosing: true
|
|
505
|
-
})
|
|
506
|
-
);
|
|
507
|
-
var openTag = P.seqMap(
|
|
508
|
-
//
|
|
509
|
-
P.string("<"),
|
|
510
|
-
tagName,
|
|
511
|
-
P.optWhitespace.then(attribute).many(),
|
|
512
|
-
P.string(">"),
|
|
513
|
-
P.regexp(/[^<]*/),
|
|
514
|
-
(_, tag, attributes, __, content) => ({
|
|
515
|
-
type: "tag",
|
|
516
|
-
tag,
|
|
517
|
-
attributes: Object.fromEntries(attributes),
|
|
518
|
-
content: content.length ? [
|
|
519
|
-
{
|
|
520
|
-
type: "text",
|
|
521
|
-
content
|
|
522
|
-
}
|
|
523
|
-
] : []
|
|
524
|
-
})
|
|
525
|
-
);
|
|
526
|
-
var closeTag = P.seqMap(
|
|
527
|
-
//
|
|
528
|
-
P.string("</"),
|
|
529
|
-
tagName,
|
|
530
|
-
P.string(">"),
|
|
531
|
-
P.optWhitespace,
|
|
532
|
-
(_, tag) => ({
|
|
533
|
-
type: "tag",
|
|
534
|
-
tag,
|
|
535
|
-
content: [],
|
|
536
|
-
closing: true
|
|
537
|
-
})
|
|
538
|
-
);
|
|
539
|
-
var mixedChunk = P.alt(selfClosingTag, openTag, closeTag, textChunk);
|
|
540
|
-
var StreamTransform = class {
|
|
495
|
+
var MessageCollector = class {
|
|
541
496
|
constructor() {
|
|
542
|
-
this.
|
|
497
|
+
this._messages = [];
|
|
498
|
+
this._pendingMessage = void 0;
|
|
543
499
|
}
|
|
544
|
-
|
|
545
|
-
this.
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
500
|
+
get messages() {
|
|
501
|
+
return this._messages;
|
|
502
|
+
}
|
|
503
|
+
get pendingMessage() {
|
|
504
|
+
return this._pendingMessage;
|
|
505
|
+
}
|
|
506
|
+
push(event) {
|
|
507
|
+
switch (event.type) {
|
|
508
|
+
case "message_start":
|
|
509
|
+
this._pendingMessage = event.message;
|
|
510
|
+
break;
|
|
511
|
+
case "message_stop":
|
|
512
|
+
if (this._pendingMessage) {
|
|
513
|
+
this._messages.push(this._pendingMessage);
|
|
514
|
+
this._pendingMessage = void 0;
|
|
515
|
+
}
|
|
516
|
+
break;
|
|
517
|
+
case "content_block_start":
|
|
518
|
+
if (this._pendingMessage) {
|
|
519
|
+
this._pendingMessage.content = this._pendingMessage.content || [];
|
|
520
|
+
this._pendingMessage.content[event.index] = event.content;
|
|
521
|
+
}
|
|
522
|
+
break;
|
|
523
|
+
case "content_block_delta":
|
|
524
|
+
if (this._pendingMessage && this._pendingMessage.content) {
|
|
525
|
+
const block = this._pendingMessage.content[event.index];
|
|
526
|
+
if (block && event.delta.type === "text_delta" && block.type === "text") {
|
|
527
|
+
block.text = (block.text || "") + event.delta.text;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
break;
|
|
531
|
+
case "content_block_stop":
|
|
532
|
+
if (this._pendingMessage && this._pendingMessage.content) {
|
|
533
|
+
const block = this._pendingMessage.content[event.index];
|
|
534
|
+
if (block) {
|
|
535
|
+
block.pending = false;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
break;
|
|
539
|
+
case "message_delta":
|
|
540
|
+
if (this._pendingMessage && event.delta) {
|
|
541
|
+
Object.assign(this._pendingMessage, event.delta);
|
|
542
|
+
}
|
|
543
|
+
break;
|
|
554
544
|
}
|
|
555
|
-
return results;
|
|
556
545
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
const remaining = this._buffer;
|
|
560
|
-
this._buffer = "";
|
|
561
|
-
return remaining.length > 0 ? [
|
|
562
|
-
{
|
|
563
|
-
type: "text",
|
|
564
|
-
content: remaining
|
|
565
|
-
}
|
|
566
|
-
] : [];
|
|
546
|
+
pushMessage(message) {
|
|
547
|
+
this._messages.push(message);
|
|
567
548
|
}
|
|
568
549
|
};
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
550
|
+
function* emitMessageAsEvents(message) {
|
|
551
|
+
yield {
|
|
552
|
+
type: "message_start",
|
|
553
|
+
message
|
|
554
|
+
};
|
|
555
|
+
yield {
|
|
556
|
+
type: "message_stop"
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
var createArtifactElement = (id) => `<artifact id=${id} />`;
|
|
560
|
+
var LLMModel = import_effect2.Schema.Literal(...DEFAULT_LLM_MODELS);
|
|
561
|
+
var ToolTypes = Object.freeze({
|
|
562
|
+
// TODO(dmaretskyi): Not implemented yet.
|
|
563
|
+
// DatabaseQuery: 'database_query',
|
|
564
|
+
TextToImage: "text_to_image"
|
|
565
|
+
});
|
|
566
|
+
var GenerateRequest = import_effect2.Schema.Struct({
|
|
567
|
+
spaceId: import_effect2.Schema.optional(import_artifact3.SpaceIdSchema),
|
|
568
|
+
threadId: import_effect2.Schema.optional(import_echo_schema2.ObjectId),
|
|
569
|
+
/**
|
|
570
|
+
* Preferred model or system default.
|
|
571
|
+
*/
|
|
572
|
+
model: import_effect2.Schema.optional(LLMModel),
|
|
573
|
+
/**
|
|
574
|
+
* Tools available for the LLM.
|
|
575
|
+
*/
|
|
576
|
+
tools: import_effect2.Schema.optional(import_effect2.Schema.Array(import_artifact3.Tool).pipe(import_effect2.Schema.mutable)),
|
|
577
|
+
/**
|
|
578
|
+
* System instructions to the LLM.
|
|
579
|
+
*/
|
|
580
|
+
systemPrompt: import_effect2.Schema.optional(import_effect2.Schema.String),
|
|
581
|
+
/**
|
|
582
|
+
* History of messages to include in the context window.
|
|
583
|
+
*/
|
|
584
|
+
// TODO(burdon): Rename messages.
|
|
585
|
+
history: import_effect2.Schema.optional(import_effect2.Schema.Array(import_artifact3.Message)),
|
|
586
|
+
/**
|
|
587
|
+
* Current request.
|
|
588
|
+
*/
|
|
589
|
+
prompt: import_effect2.Schema.optional(import_artifact3.Message)
|
|
590
|
+
});
|
|
591
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/experimental/assistant/src/conversation/conversation.ts";
|
|
592
|
+
var runLLM = async (params) => {
|
|
593
|
+
let conversationResult = null;
|
|
594
|
+
const history = params.history ?? [];
|
|
595
|
+
const generate = async () => {
|
|
596
|
+
(0, import_log4.log)("llm generate", {
|
|
597
|
+
tools: params.tools
|
|
598
|
+
}, {
|
|
599
|
+
F: __dxlog_file3,
|
|
600
|
+
L: 44,
|
|
601
|
+
S: void 0,
|
|
602
|
+
C: (f, a) => f(...a)
|
|
603
|
+
});
|
|
604
|
+
const beginTs = Date.now();
|
|
605
|
+
const stream = await params.client.exec({
|
|
606
|
+
model: params.model,
|
|
607
|
+
spaceId: params.spaceId,
|
|
608
|
+
threadId: params.threadId,
|
|
609
|
+
history,
|
|
610
|
+
systemPrompt: params.system,
|
|
611
|
+
tools: params.tools
|
|
612
|
+
});
|
|
613
|
+
for await (const event of stream) {
|
|
614
|
+
params.logger?.(event);
|
|
615
|
+
}
|
|
616
|
+
await stream.complete();
|
|
617
|
+
const messages = [];
|
|
618
|
+
const message = messages.at(-1);
|
|
619
|
+
(0, import_invariant3.invariant)(message, void 0, {
|
|
620
|
+
F: __dxlog_file3,
|
|
621
|
+
L: 63,
|
|
622
|
+
S: void 0,
|
|
623
|
+
A: [
|
|
624
|
+
"message",
|
|
625
|
+
""
|
|
626
|
+
]
|
|
627
|
+
});
|
|
628
|
+
(0, import_log4.log)("llm result", {
|
|
629
|
+
time: Date.now() - beginTs,
|
|
630
|
+
message
|
|
631
|
+
}, {
|
|
632
|
+
F: __dxlog_file3,
|
|
633
|
+
L: 65,
|
|
634
|
+
S: void 0,
|
|
635
|
+
C: (f, a) => f(...a)
|
|
636
|
+
});
|
|
637
|
+
(0, import_invariant3.invariant)(message, void 0, {
|
|
638
|
+
F: __dxlog_file3,
|
|
639
|
+
L: 66,
|
|
640
|
+
S: void 0,
|
|
641
|
+
A: [
|
|
642
|
+
"message",
|
|
643
|
+
""
|
|
644
|
+
]
|
|
645
|
+
});
|
|
646
|
+
params.logger?.({
|
|
647
|
+
type: "message",
|
|
648
|
+
message
|
|
649
|
+
});
|
|
650
|
+
history.push(...messages.map((message2) => ({
|
|
651
|
+
...message2,
|
|
652
|
+
content: message2.content.filter((block) => block.type !== "image")
|
|
653
|
+
})));
|
|
654
|
+
const isToolUse2 = message.content.at(-1)?.type === "tool_use";
|
|
655
|
+
if (isToolUse2) {
|
|
656
|
+
const toolCalls = message.content.filter((block) => block.type === "tool_use");
|
|
657
|
+
(0, import_invariant3.invariant)(toolCalls.length === 1, void 0, {
|
|
658
|
+
F: __dxlog_file3,
|
|
659
|
+
L: 77,
|
|
660
|
+
S: void 0,
|
|
661
|
+
A: [
|
|
662
|
+
"toolCalls.length === 1",
|
|
663
|
+
""
|
|
664
|
+
]
|
|
665
|
+
});
|
|
666
|
+
const toolCall = toolCalls[0];
|
|
667
|
+
const tool = params.tools.find((tool2) => tool2.name === toolCall.name);
|
|
668
|
+
if (!tool) {
|
|
669
|
+
throw new Error(`Tool not found: ${toolCall.name}`);
|
|
581
670
|
}
|
|
582
|
-
(0,
|
|
671
|
+
(0, import_invariant3.invariant)(tool.execute, void 0, {
|
|
583
672
|
F: __dxlog_file3,
|
|
584
|
-
L:
|
|
585
|
-
S:
|
|
673
|
+
L: 84,
|
|
674
|
+
S: void 0,
|
|
586
675
|
A: [
|
|
587
|
-
"
|
|
676
|
+
"tool.execute",
|
|
588
677
|
""
|
|
589
678
|
]
|
|
590
679
|
});
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* Parse stream until end.
|
|
604
|
-
*/
|
|
605
|
-
async parse(stream) {
|
|
606
|
-
const transformer = new StreamTransform();
|
|
607
|
-
let contentBlock;
|
|
608
|
-
let streamBlock;
|
|
609
|
-
const stack = [];
|
|
610
|
-
const messagesCollected = [];
|
|
611
|
-
for await (const event of stream) {
|
|
612
|
-
switch (event.type) {
|
|
613
|
-
//
|
|
614
|
-
// Messages.
|
|
615
|
-
//
|
|
616
|
-
case "message_start": {
|
|
617
|
-
if (this._message) {
|
|
618
|
-
import_log3.log.warn("unexpected message_start", void 0, {
|
|
619
|
-
F: __dxlog_file3,
|
|
620
|
-
L: 88,
|
|
621
|
-
S: this,
|
|
622
|
-
C: (f, a) => f(...a)
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
|
-
this._message = (0, import_echo_schema.createStatic)(import_artifact2.Message, {
|
|
626
|
-
role: "assistant",
|
|
627
|
-
content: []
|
|
680
|
+
const toolResult = await tool.execute(toolCall.input);
|
|
681
|
+
switch (toolResult.kind) {
|
|
682
|
+
case "error": {
|
|
683
|
+
import_log4.log.warn("tool error", {
|
|
684
|
+
message: toolResult.message
|
|
685
|
+
}, {
|
|
686
|
+
F: __dxlog_file3,
|
|
687
|
+
L: 88,
|
|
688
|
+
S: void 0,
|
|
689
|
+
C: (f, a) => f(...a)
|
|
628
690
|
});
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
}
|
|
641
|
-
break;
|
|
642
|
-
}
|
|
643
|
-
case "message_stop": {
|
|
644
|
-
if (!this._message) {
|
|
645
|
-
import_log3.log.warn("unexpected message_stop", void 0, {
|
|
646
|
-
F: __dxlog_file3,
|
|
647
|
-
L: 106,
|
|
648
|
-
S: this,
|
|
649
|
-
C: (f, a) => f(...a)
|
|
650
|
-
});
|
|
651
|
-
} else {
|
|
652
|
-
messagesCollected.push(this._message);
|
|
653
|
-
this._message = void 0;
|
|
654
|
-
}
|
|
655
|
-
break;
|
|
656
|
-
}
|
|
657
|
-
//
|
|
658
|
-
// Content blocks.
|
|
659
|
-
//
|
|
660
|
-
case "content_block_start": {
|
|
661
|
-
if (contentBlock) {
|
|
662
|
-
import_log3.log.warn("unexpected content_block_start", {
|
|
663
|
-
content: contentBlock
|
|
664
|
-
}, {
|
|
665
|
-
F: __dxlog_file3,
|
|
666
|
-
L: 120,
|
|
667
|
-
S: this,
|
|
668
|
-
C: (f, a) => f(...a)
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
contentBlock = event.content;
|
|
672
|
-
break;
|
|
673
|
-
}
|
|
674
|
-
case "content_block_delta": {
|
|
675
|
-
if (!contentBlock) {
|
|
676
|
-
import_log3.log.warn("unexpected content_block_delta", void 0, {
|
|
677
|
-
F: __dxlog_file3,
|
|
678
|
-
L: 130,
|
|
679
|
-
S: this,
|
|
680
|
-
C: (f, a) => f(...a)
|
|
681
|
-
});
|
|
682
|
-
break;
|
|
683
|
-
}
|
|
684
|
-
switch (event.delta.type) {
|
|
685
|
-
//
|
|
686
|
-
// Text
|
|
687
|
-
//
|
|
688
|
-
case "text_delta": {
|
|
689
|
-
const chunks = transformer.transform(event.delta.text);
|
|
690
|
-
for (const chunk of chunks) {
|
|
691
|
-
switch (streamBlock?.type) {
|
|
692
|
-
//
|
|
693
|
-
// XML Fragment.
|
|
694
|
-
//
|
|
695
|
-
case "tag": {
|
|
696
|
-
if (chunk.type === "tag") {
|
|
697
|
-
if (chunk.selfClosing) {
|
|
698
|
-
streamBlock.content.push(chunk);
|
|
699
|
-
} else if (chunk.closing) {
|
|
700
|
-
if (stack.length > 0) {
|
|
701
|
-
const top = stack.pop();
|
|
702
|
-
(0, import_invariant2.invariant)(top && top.type === "tag", void 0, {
|
|
703
|
-
F: __dxlog_file3,
|
|
704
|
-
L: 154,
|
|
705
|
-
S: this,
|
|
706
|
-
A: [
|
|
707
|
-
"top && top.type === 'tag'",
|
|
708
|
-
""
|
|
709
|
-
]
|
|
710
|
-
});
|
|
711
|
-
top.content.push(streamBlock);
|
|
712
|
-
streamBlock = top;
|
|
713
|
-
} else {
|
|
714
|
-
this._emitBlock(contentBlock, streamBlock);
|
|
715
|
-
streamBlock = void 0;
|
|
716
|
-
}
|
|
717
|
-
} else {
|
|
718
|
-
stack.push(streamBlock);
|
|
719
|
-
streamBlock = chunk;
|
|
720
|
-
}
|
|
721
|
-
} else {
|
|
722
|
-
if (streamBlock.content.length === 0) {
|
|
723
|
-
streamBlock.content.push(chunk);
|
|
724
|
-
} else {
|
|
725
|
-
const last = streamBlock.content.at(-1);
|
|
726
|
-
(0, import_invariant2.invariant)(last, void 0, {
|
|
727
|
-
F: __dxlog_file3,
|
|
728
|
-
L: 171,
|
|
729
|
-
S: this,
|
|
730
|
-
A: [
|
|
731
|
-
"last",
|
|
732
|
-
""
|
|
733
|
-
]
|
|
734
|
-
});
|
|
735
|
-
if (last.type === "text") {
|
|
736
|
-
last.content += chunk.content;
|
|
737
|
-
} else {
|
|
738
|
-
streamBlock.content.push(chunk);
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
break;
|
|
743
|
-
}
|
|
744
|
-
//
|
|
745
|
-
// Text Fragment.
|
|
746
|
-
//
|
|
747
|
-
case "text": {
|
|
748
|
-
if (chunk.type === "tag") {
|
|
749
|
-
this._emitBlock(contentBlock, streamBlock);
|
|
750
|
-
if (chunk.selfClosing) {
|
|
751
|
-
this._emitBlock(contentBlock, chunk);
|
|
752
|
-
streamBlock = void 0;
|
|
753
|
-
} else {
|
|
754
|
-
streamBlock = chunk;
|
|
755
|
-
}
|
|
756
|
-
} else {
|
|
757
|
-
streamBlock.content += chunk.content;
|
|
758
|
-
}
|
|
759
|
-
break;
|
|
760
|
-
}
|
|
761
|
-
//
|
|
762
|
-
// No current chunk.
|
|
763
|
-
//
|
|
764
|
-
default: {
|
|
765
|
-
if (chunk.type === "tag" && chunk.selfClosing) {
|
|
766
|
-
this._emitBlock(contentBlock, chunk);
|
|
767
|
-
} else {
|
|
768
|
-
streamBlock = chunk;
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
break;
|
|
774
|
-
}
|
|
775
|
-
//
|
|
776
|
-
// JSON
|
|
777
|
-
//
|
|
778
|
-
case "input_json_delta": {
|
|
779
|
-
if (!contentBlock) {
|
|
780
|
-
import_log3.log.warn("unexpected input_json_delta", {
|
|
781
|
-
contentBlock
|
|
782
|
-
}, {
|
|
783
|
-
F: __dxlog_file3,
|
|
784
|
-
L: 221,
|
|
785
|
-
S: this,
|
|
786
|
-
C: (f, a) => f(...a)
|
|
787
|
-
});
|
|
788
|
-
break;
|
|
691
|
+
const resultMessage = {
|
|
692
|
+
id: import_echo_schema3.ObjectId.random(),
|
|
693
|
+
spaceId: params.spaceId,
|
|
694
|
+
threadId: params.threadId,
|
|
695
|
+
role: "user",
|
|
696
|
+
content: [
|
|
697
|
+
{
|
|
698
|
+
type: "tool_result",
|
|
699
|
+
toolUseId: toolCall.id,
|
|
700
|
+
content: toolResult.message,
|
|
701
|
+
isError: true
|
|
789
702
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
703
|
+
]
|
|
704
|
+
};
|
|
705
|
+
params.logger?.({
|
|
706
|
+
type: "message",
|
|
707
|
+
message: resultMessage
|
|
708
|
+
});
|
|
709
|
+
history.push(resultMessage);
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
case "success": {
|
|
713
|
+
(0, import_log4.log)("tool success", {
|
|
714
|
+
result: toolResult.result
|
|
715
|
+
}, {
|
|
716
|
+
F: __dxlog_file3,
|
|
717
|
+
L: 110,
|
|
718
|
+
S: void 0,
|
|
719
|
+
C: (f, a) => f(...a)
|
|
720
|
+
});
|
|
721
|
+
const resultMessage = {
|
|
722
|
+
id: import_echo_schema3.ObjectId.random(),
|
|
723
|
+
spaceId: params.spaceId,
|
|
724
|
+
threadId: params.threadId,
|
|
725
|
+
role: "user",
|
|
726
|
+
content: [
|
|
727
|
+
{
|
|
728
|
+
type: "tool_result",
|
|
729
|
+
toolUseId: toolCall.id,
|
|
730
|
+
content: JSON.stringify(toolResult.result)
|
|
797
731
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
732
|
+
]
|
|
733
|
+
};
|
|
734
|
+
params.logger?.({
|
|
735
|
+
type: "message",
|
|
736
|
+
message: resultMessage
|
|
737
|
+
});
|
|
738
|
+
history.push(resultMessage);
|
|
739
|
+
return true;
|
|
802
740
|
}
|
|
803
|
-
case "
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
contentBlock = void 0;
|
|
815
|
-
streamBlock = void 0;
|
|
816
|
-
break;
|
|
741
|
+
case "break": {
|
|
742
|
+
(0, import_log4.log)("tool break", {
|
|
743
|
+
result: toolResult.result
|
|
744
|
+
}, {
|
|
745
|
+
F: __dxlog_file3,
|
|
746
|
+
L: 131,
|
|
747
|
+
S: void 0,
|
|
748
|
+
C: (f, a) => f(...a)
|
|
749
|
+
});
|
|
750
|
+
conversationResult = toolResult.result;
|
|
751
|
+
return false;
|
|
817
752
|
}
|
|
818
753
|
}
|
|
819
|
-
if (contentBlock && streamBlock) {
|
|
820
|
-
this._emitUpdate(contentBlock, streamBlock);
|
|
821
|
-
}
|
|
822
754
|
}
|
|
823
|
-
return
|
|
755
|
+
return false;
|
|
756
|
+
};
|
|
757
|
+
while (await generate()) {
|
|
824
758
|
}
|
|
759
|
+
return {
|
|
760
|
+
result: conversationResult,
|
|
761
|
+
history
|
|
762
|
+
};
|
|
825
763
|
};
|
|
826
|
-
var
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
streamBlock
|
|
830
|
-
}, {
|
|
764
|
+
var isToolUse = (message, { onlyToolNames } = {}) => {
|
|
765
|
+
const block = message.content.at(-1);
|
|
766
|
+
(0, import_invariant3.invariant)(block, void 0, {
|
|
831
767
|
F: __dxlog_file3,
|
|
832
|
-
L:
|
|
768
|
+
L: 152,
|
|
833
769
|
S: void 0,
|
|
834
|
-
|
|
770
|
+
A: [
|
|
771
|
+
"block",
|
|
772
|
+
""
|
|
773
|
+
]
|
|
835
774
|
});
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
775
|
+
return block.type === "tool_use" && (!onlyToolNames || onlyToolNames.includes(block.name));
|
|
776
|
+
};
|
|
777
|
+
var runTools = async ({ message, tools, extensions }) => {
|
|
778
|
+
const toolCalls = message.content.filter((block) => block.type === "tool_use");
|
|
779
|
+
(0, import_invariant3.invariant)(toolCalls.length === 1, void 0, {
|
|
780
|
+
F: __dxlog_file3,
|
|
781
|
+
L: 174,
|
|
782
|
+
S: void 0,
|
|
783
|
+
A: [
|
|
784
|
+
"toolCalls.length === 1",
|
|
785
|
+
""
|
|
786
|
+
]
|
|
787
|
+
});
|
|
788
|
+
const toolCall = toolCalls[0];
|
|
789
|
+
const tool = tools.find((tool2) => tool2.name === toolCall.name);
|
|
790
|
+
if (!tool) {
|
|
791
|
+
throw new Error(`Tool not found: ${toolCall.name}`);
|
|
792
|
+
}
|
|
793
|
+
let toolResult;
|
|
794
|
+
try {
|
|
795
|
+
(0, import_invariant3.invariant)(tool.execute, void 0, {
|
|
796
|
+
F: __dxlog_file3,
|
|
797
|
+
L: 183,
|
|
798
|
+
S: void 0,
|
|
799
|
+
A: [
|
|
800
|
+
"tool.execute",
|
|
801
|
+
""
|
|
802
|
+
]
|
|
803
|
+
});
|
|
804
|
+
toolResult = await tool.execute(toolCall.input, {
|
|
805
|
+
extensions
|
|
806
|
+
});
|
|
807
|
+
} catch (error) {
|
|
808
|
+
(0, import_log4.log)("tool error", {
|
|
809
|
+
error
|
|
810
|
+
}, {
|
|
811
|
+
F: __dxlog_file3,
|
|
812
|
+
L: 186,
|
|
813
|
+
S: void 0,
|
|
814
|
+
C: (f, a) => f(...a)
|
|
815
|
+
});
|
|
816
|
+
toolResult = import_artifact4.ToolResult.Error(error.message);
|
|
817
|
+
}
|
|
818
|
+
switch (toolResult.kind) {
|
|
819
|
+
case "error": {
|
|
820
|
+
(0, import_log4.log)("tool error", {
|
|
821
|
+
message: toolResult.message
|
|
822
|
+
}, {
|
|
823
|
+
F: __dxlog_file3,
|
|
824
|
+
L: 192,
|
|
825
|
+
S: void 0,
|
|
826
|
+
C: (f, a) => f(...a)
|
|
827
|
+
});
|
|
828
|
+
const resultMessage = (0, import_echo_schema3.createStatic)(import_artifact4.Message, {
|
|
829
|
+
role: "user",
|
|
830
|
+
content: [
|
|
831
|
+
{
|
|
832
|
+
type: "tool_result",
|
|
833
|
+
toolUseId: toolCall.id,
|
|
834
|
+
content: toolResult.message,
|
|
835
|
+
isError: true
|
|
836
|
+
}
|
|
837
|
+
]
|
|
838
|
+
});
|
|
841
839
|
return {
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
text: streamBlock.content
|
|
840
|
+
type: "continue",
|
|
841
|
+
message: resultMessage
|
|
845
842
|
};
|
|
846
843
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
type: "json",
|
|
872
|
-
disposition: "artifact",
|
|
873
|
-
json: JSON.stringify(attributes)
|
|
874
|
-
};
|
|
875
|
-
}
|
|
876
|
-
case "suggest": {
|
|
877
|
-
if (streamBlock.content.length === 1 && streamBlock.content[0].type === "text") {
|
|
878
|
-
return {
|
|
879
|
-
type: "json",
|
|
880
|
-
disposition: "suggest",
|
|
881
|
-
json: JSON.stringify({
|
|
882
|
-
text: streamBlock.content[0].content
|
|
883
|
-
})
|
|
884
|
-
};
|
|
885
|
-
}
|
|
886
|
-
break;
|
|
887
|
-
}
|
|
888
|
-
case "select": {
|
|
889
|
-
return {
|
|
890
|
-
type: "json",
|
|
891
|
-
disposition: "select",
|
|
892
|
-
json: JSON.stringify({
|
|
893
|
-
options: streamBlock.content.flatMap((content) => content.type === "tag" && content.content.length === 1 && content.content[0].type === "text" ? [
|
|
894
|
-
content.content[0].content
|
|
895
|
-
] : [])
|
|
896
|
-
})
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
|
-
case "tool-list": {
|
|
900
|
-
return {
|
|
901
|
-
type: "json",
|
|
902
|
-
disposition: "tool_list",
|
|
903
|
-
json: JSON.stringify({})
|
|
904
|
-
};
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
break;
|
|
844
|
+
case "success": {
|
|
845
|
+
(0, import_log4.log)("tool success", {
|
|
846
|
+
result: toolResult.result
|
|
847
|
+
}, {
|
|
848
|
+
F: __dxlog_file3,
|
|
849
|
+
L: 213,
|
|
850
|
+
S: void 0,
|
|
851
|
+
C: (f, a) => f(...a)
|
|
852
|
+
});
|
|
853
|
+
const resultMessage = (0, import_echo_schema3.createStatic)(import_artifact4.Message, {
|
|
854
|
+
role: "user",
|
|
855
|
+
content: [
|
|
856
|
+
{
|
|
857
|
+
type: "tool_result",
|
|
858
|
+
toolUseId: toolCall.id,
|
|
859
|
+
content: typeof toolResult.result === "string" ? toolResult.result : JSON.stringify(toolResult.result) ?? ""
|
|
860
|
+
},
|
|
861
|
+
...toolResult.extractContentBlocks ?? []
|
|
862
|
+
]
|
|
863
|
+
});
|
|
864
|
+
return {
|
|
865
|
+
type: "continue",
|
|
866
|
+
message: resultMessage
|
|
867
|
+
};
|
|
908
868
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
}
|
|
869
|
+
case "break": {
|
|
870
|
+
(0, import_log4.log)("tool break", {
|
|
871
|
+
result: toolResult.result
|
|
872
|
+
}, {
|
|
873
|
+
F: __dxlog_file3,
|
|
874
|
+
L: 234,
|
|
875
|
+
S: void 0,
|
|
876
|
+
C: (f, a) => f(...a)
|
|
877
|
+
});
|
|
921
878
|
return {
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
disposition: "artifact",
|
|
925
|
-
json: streamBlock.content
|
|
879
|
+
type: "break",
|
|
880
|
+
result: toolResult.result
|
|
926
881
|
};
|
|
927
882
|
}
|
|
928
883
|
}
|
|
929
884
|
};
|
|
930
|
-
var
|
|
931
|
-
var
|
|
932
|
-
var
|
|
933
|
-
|
|
934
|
-
// DatabaseQuery: 'database_query',
|
|
935
|
-
TextToImage: "text_to_image"
|
|
936
|
-
});
|
|
937
|
-
var GenerateRequest = import_schema2.Schema.Struct({
|
|
938
|
-
spaceId: import_schema2.Schema.optional(import_artifact3.SpaceIdSchema),
|
|
939
|
-
threadId: import_schema2.Schema.optional(import_echo_schema2.ObjectId),
|
|
940
|
-
/**
|
|
941
|
-
* Preferred model or system default.
|
|
942
|
-
*/
|
|
943
|
-
model: import_schema2.Schema.optional(LLMModel),
|
|
944
|
-
/**
|
|
945
|
-
* Tools available for the LLM.
|
|
946
|
-
*/
|
|
947
|
-
tools: import_schema2.Schema.optional(import_schema2.Schema.Array(import_artifact3.Tool).pipe(import_schema2.Schema.mutable)),
|
|
885
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/experimental/assistant/src/ai-service/ollama-client.ts";
|
|
886
|
+
var DEFAULT_OLLAMA_URL = "http://localhost:11434";
|
|
887
|
+
var DEFAULT_OLLAMA_MODEL = "llama3.2:1b";
|
|
888
|
+
var OllamaClient = class _OllamaClient {
|
|
948
889
|
/**
|
|
949
|
-
*
|
|
950
|
-
*/
|
|
951
|
-
systemPrompt: import_schema2.Schema.optional(import_schema2.Schema.String),
|
|
952
|
-
/**
|
|
953
|
-
* History of messages to include in the context window.
|
|
890
|
+
* Create a test client with small local model and no temperature for predictable results.
|
|
954
891
|
*/
|
|
955
|
-
|
|
956
|
-
|
|
892
|
+
static createClient(options) {
|
|
893
|
+
return new _OllamaClient({
|
|
894
|
+
tools: options?.tools,
|
|
895
|
+
overrides: {
|
|
896
|
+
model: DEFAULT_OLLAMA_MODEL,
|
|
897
|
+
temperature: 0
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
}
|
|
957
901
|
/**
|
|
958
|
-
*
|
|
902
|
+
* Check if Ollama server is running and accessible.
|
|
903
|
+
* @returns Promise that resolves to true if Ollama is running, false otherwise.
|
|
959
904
|
*/
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
S: void 0,
|
|
973
|
-
C: (f, a) => f(...a)
|
|
974
|
-
});
|
|
975
|
-
const beginTs = Date.now();
|
|
976
|
-
const stream = await params.client.exec({
|
|
977
|
-
model: params.model,
|
|
978
|
-
spaceId: params.spaceId,
|
|
979
|
-
threadId: params.threadId,
|
|
980
|
-
history,
|
|
981
|
-
systemPrompt: params.system,
|
|
982
|
-
tools: params.tools
|
|
983
|
-
});
|
|
984
|
-
for await (const event of stream) {
|
|
985
|
-
params.logger?.(event);
|
|
905
|
+
static async isRunning() {
|
|
906
|
+
try {
|
|
907
|
+
const response = await fetch(`${DEFAULT_OLLAMA_URL}/api/version`, {
|
|
908
|
+
method: "GET",
|
|
909
|
+
headers: {
|
|
910
|
+
"Content-Type": "application/json"
|
|
911
|
+
},
|
|
912
|
+
signal: AbortSignal.timeout(100)
|
|
913
|
+
});
|
|
914
|
+
return response.ok;
|
|
915
|
+
} catch (error) {
|
|
916
|
+
return false;
|
|
986
917
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
918
|
+
}
|
|
919
|
+
constructor({ endpoint, tools, overrides, maxToolInvocations }) {
|
|
920
|
+
this._endpoint = endpoint ?? DEFAULT_OLLAMA_URL;
|
|
921
|
+
this._tools = tools ?? [];
|
|
922
|
+
this._modelOverride = overrides?.model;
|
|
923
|
+
this._temperatureOverride = overrides?.temperature;
|
|
924
|
+
this._maxToolInvocations = maxToolInvocations ?? 3;
|
|
925
|
+
}
|
|
926
|
+
_getEmbededTools(clientTools) {
|
|
927
|
+
return [
|
|
928
|
+
...this._tools,
|
|
929
|
+
...clientTools.filter((tool) => tool.type !== void 0 && WELL_KNOWN_TOOLS[tool.type]).map((tool) => WELL_KNOWN_TOOLS[tool.type])
|
|
930
|
+
];
|
|
931
|
+
}
|
|
932
|
+
async *_generateStream(request, signal) {
|
|
933
|
+
(0, import_invariant2.invariant)(request.prompt === void 0, "Prompt must be in history", {
|
|
991
934
|
F: __dxlog_file4,
|
|
992
|
-
L:
|
|
993
|
-
S:
|
|
935
|
+
L: 99,
|
|
936
|
+
S: this,
|
|
994
937
|
A: [
|
|
995
|
-
"
|
|
996
|
-
""
|
|
938
|
+
"request.prompt === undefined",
|
|
939
|
+
"'Prompt must be in history'"
|
|
997
940
|
]
|
|
998
941
|
});
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
942
|
+
const ollamaRequest = {
|
|
943
|
+
model: this._modelOverride ?? request.model ?? "llama3",
|
|
944
|
+
messages: [],
|
|
945
|
+
stream: true,
|
|
946
|
+
options: {
|
|
947
|
+
temperature: this._temperatureOverride ?? 0.7
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
if (request.systemPrompt) {
|
|
951
|
+
ollamaRequest.messages.push({
|
|
952
|
+
role: "system",
|
|
953
|
+
content: request.systemPrompt
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
if (request.history?.length) {
|
|
957
|
+
for (const message of request.history) {
|
|
958
|
+
const role = message.role === "assistant" ? "assistant" : "user";
|
|
959
|
+
if (message.content.length === 0) {
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
for (const content of message.content) {
|
|
963
|
+
switch (content.type) {
|
|
964
|
+
case "text": {
|
|
965
|
+
ollamaRequest.messages.push({
|
|
966
|
+
role,
|
|
967
|
+
content: content.text
|
|
968
|
+
});
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
case "tool_use": {
|
|
972
|
+
ollamaRequest.messages.push({
|
|
973
|
+
role: "assistant",
|
|
974
|
+
content: "",
|
|
975
|
+
tool_calls: [
|
|
976
|
+
{
|
|
977
|
+
function: {
|
|
978
|
+
name: content.name,
|
|
979
|
+
arguments: content.input
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
]
|
|
983
|
+
});
|
|
984
|
+
break;
|
|
985
|
+
}
|
|
986
|
+
case "tool_result": {
|
|
987
|
+
ollamaRequest.messages.push({
|
|
988
|
+
role: "tool",
|
|
989
|
+
content: JSON.stringify({
|
|
990
|
+
type: "tool_result",
|
|
991
|
+
toolUseId: content.toolUseId,
|
|
992
|
+
content: content.content
|
|
993
|
+
})
|
|
994
|
+
});
|
|
995
|
+
break;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
if (request.tools?.length || this._tools.length) {
|
|
1002
|
+
const allTools = [
|
|
1003
|
+
...request.tools ?? [],
|
|
1004
|
+
...this._tools
|
|
1005
|
+
];
|
|
1006
|
+
const withWellKnownTools = allTools.map((tool) => tool.type !== void 0 && WELL_KNOWN_TOOLS[tool.type] ? WELL_KNOWN_TOOLS[tool.type] : tool);
|
|
1007
|
+
if (withWellKnownTools.length > 0) {
|
|
1008
|
+
ollamaRequest.tools = withWellKnownTools.map((tool) => ({
|
|
1009
|
+
type: "function",
|
|
1010
|
+
function: {
|
|
1011
|
+
name: tool.name,
|
|
1012
|
+
description: tool.description,
|
|
1013
|
+
parameters: {
|
|
1014
|
+
type: "object",
|
|
1015
|
+
properties: tool.parameters?.properties,
|
|
1016
|
+
required: tool.parameters?.required
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}));
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
import_log3.log.info("generate request", {
|
|
1023
|
+
history: request.history,
|
|
1024
|
+
prompt: request.prompt,
|
|
1025
|
+
ollamaRequest
|
|
1002
1026
|
}, {
|
|
1003
1027
|
F: __dxlog_file4,
|
|
1004
|
-
L:
|
|
1005
|
-
S:
|
|
1028
|
+
L: 193,
|
|
1029
|
+
S: this,
|
|
1006
1030
|
C: (f, a) => f(...a)
|
|
1007
1031
|
});
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
]
|
|
1032
|
+
const response = await fetch(`${this._endpoint}/api/chat`, {
|
|
1033
|
+
method: "POST",
|
|
1034
|
+
headers: {
|
|
1035
|
+
"Content-Type": "application/json"
|
|
1036
|
+
},
|
|
1037
|
+
body: JSON.stringify(ollamaRequest),
|
|
1038
|
+
signal
|
|
1016
1039
|
});
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1040
|
+
if (!response.ok) {
|
|
1041
|
+
throw new Error(`Ollama API error: ${response.status} ${response.statusText}`);
|
|
1042
|
+
}
|
|
1043
|
+
if (!response.body) {
|
|
1044
|
+
throw new Error("Ollama API returned no response body");
|
|
1045
|
+
}
|
|
1046
|
+
const reader = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new OllamaDecoderStream()).getReader();
|
|
1047
|
+
try {
|
|
1048
|
+
const messageId = import_echo_schema.ObjectId.random();
|
|
1049
|
+
yield {
|
|
1050
|
+
type: "message_start",
|
|
1051
|
+
message: {
|
|
1052
|
+
id: messageId,
|
|
1053
|
+
role: "assistant",
|
|
1054
|
+
content: []
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
const textBlock = {
|
|
1058
|
+
type: "text",
|
|
1059
|
+
text: ""
|
|
1060
|
+
};
|
|
1061
|
+
let currentBlockIndex = 0;
|
|
1062
|
+
yield {
|
|
1063
|
+
type: "content_block_start",
|
|
1064
|
+
index: currentBlockIndex,
|
|
1065
|
+
content: textBlock
|
|
1066
|
+
};
|
|
1067
|
+
while (true) {
|
|
1068
|
+
const { done, value: data } = await reader.read();
|
|
1069
|
+
if (done) {
|
|
1070
|
+
break;
|
|
1071
|
+
}
|
|
1072
|
+
import_log3.log.info("ollama data", {
|
|
1073
|
+
data
|
|
1074
|
+
}, {
|
|
1075
|
+
F: __dxlog_file4,
|
|
1076
|
+
L: 256,
|
|
1077
|
+
S: this,
|
|
1078
|
+
C: (f, a) => f(...a)
|
|
1079
|
+
});
|
|
1080
|
+
if (data.message?.content) {
|
|
1081
|
+
yield {
|
|
1082
|
+
type: "content_block_delta",
|
|
1083
|
+
index: 0,
|
|
1084
|
+
delta: {
|
|
1085
|
+
type: "text_delta",
|
|
1086
|
+
text: data.message.content
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
if (data.message?.tool_calls && data.message?.tool_calls?.length > 0) {
|
|
1091
|
+
if (data.message.tool_calls.length > 1) {
|
|
1092
|
+
import_log3.log.warn("Ollama returned multiple tool calls. Only the first one will be used.", void 0, {
|
|
1093
|
+
F: __dxlog_file4,
|
|
1094
|
+
L: 273,
|
|
1095
|
+
S: this,
|
|
1096
|
+
C: (f, a) => f(...a)
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
yield {
|
|
1100
|
+
type: "content_block_stop",
|
|
1101
|
+
index: currentBlockIndex++
|
|
1102
|
+
};
|
|
1103
|
+
yield {
|
|
1104
|
+
type: "content_block_start",
|
|
1105
|
+
index: currentBlockIndex,
|
|
1106
|
+
content: {
|
|
1107
|
+
type: "tool_use",
|
|
1108
|
+
id: import_echo_schema.ObjectId.random(),
|
|
1109
|
+
name: data.message.tool_calls[0].function.name,
|
|
1110
|
+
input: sanitizeToolArguments(data.message.tool_calls[0].function.arguments)
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
yield {
|
|
1114
|
+
type: "message_delta",
|
|
1115
|
+
delta: {
|
|
1116
|
+
stopReason: "tool_use"
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
yield {
|
|
1122
|
+
type: "content_block_stop",
|
|
1123
|
+
index: currentBlockIndex
|
|
1124
|
+
};
|
|
1125
|
+
yield {
|
|
1126
|
+
type: "message_stop"
|
|
1127
|
+
};
|
|
1128
|
+
} finally {
|
|
1129
|
+
reader.releaseLock();
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
async exec(request) {
|
|
1133
|
+
const controller = new AbortController();
|
|
1134
|
+
try {
|
|
1135
|
+
return new GenerationStreamImpl(controller, async function* () {
|
|
1136
|
+
const collector = new MessageCollector();
|
|
1137
|
+
let toolInvocations = 0;
|
|
1138
|
+
while (true) {
|
|
1139
|
+
for await (const event of this._generateStream({
|
|
1140
|
+
...request,
|
|
1141
|
+
history: [
|
|
1142
|
+
...request.history ?? [],
|
|
1143
|
+
...request.prompt ? [
|
|
1144
|
+
request.prompt
|
|
1145
|
+
] : [],
|
|
1146
|
+
...collector.messages
|
|
1147
|
+
],
|
|
1148
|
+
prompt: void 0
|
|
1149
|
+
}, controller.signal)) {
|
|
1150
|
+
collector.push(event);
|
|
1151
|
+
yield event;
|
|
1152
|
+
}
|
|
1153
|
+
if (collector.messages.length > 0 && !isToolUse(collector.messages.at(-1), {
|
|
1154
|
+
onlyToolNames: this._getEmbededTools(request.tools ?? []).map((tool) => tool.name)
|
|
1155
|
+
})) {
|
|
1156
|
+
break;
|
|
1157
|
+
}
|
|
1158
|
+
if (++toolInvocations > this._maxToolInvocations) {
|
|
1159
|
+
throw new Error("Maximum number of tool invocations reached");
|
|
1160
|
+
}
|
|
1161
|
+
const result = await runTools({
|
|
1162
|
+
message: collector.messages.at(-1),
|
|
1163
|
+
tools: this._getEmbededTools(request.tools ?? [])
|
|
1164
|
+
});
|
|
1165
|
+
switch (result.type) {
|
|
1166
|
+
case "continue": {
|
|
1167
|
+
collector.pushMessage(result.message);
|
|
1168
|
+
yield* emitMessageAsEvents(result.message);
|
|
1169
|
+
break;
|
|
1170
|
+
}
|
|
1171
|
+
case "break": {
|
|
1172
|
+
throw new Error("Tool use breaks not allowed");
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}.bind(this));
|
|
1177
|
+
} catch (error) {
|
|
1178
|
+
controller.abort();
|
|
1179
|
+
throw error;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
var sanitizeToolArguments = (args) => {
|
|
1184
|
+
if (args.type === "object" && typeof args.properties === "object" && Array.isArray(args.required)) {
|
|
1185
|
+
return args.properties;
|
|
1186
|
+
}
|
|
1187
|
+
return args;
|
|
1188
|
+
};
|
|
1189
|
+
var SAMPLE_IMAGE_URL = "https://images.nightcafe.studio/jobs/BNmcRhHCM1JRKoUtqSei/BNmcRhHCM1JRKoUtqSei--1--5b9rv.jpg";
|
|
1190
|
+
var WELL_KNOWN_TOOLS = {
|
|
1191
|
+
[ToolTypes.TextToImage]: (0, import_artifact2.defineTool)("system", {
|
|
1192
|
+
name: "text-to-image",
|
|
1193
|
+
description: "Generate an image from a text prompt",
|
|
1194
|
+
schema: import_echo_schema.S.Struct({
|
|
1195
|
+
prompt: import_echo_schema.S.String.annotations({
|
|
1196
|
+
description: "The text prompt describing the image to generate"
|
|
1197
|
+
})
|
|
1198
|
+
}),
|
|
1199
|
+
execute: async ({ prompt }) => {
|
|
1200
|
+
const image = await fetch(SAMPLE_IMAGE_URL).then(async (res) => Buffer.from(await res.arrayBuffer()));
|
|
1201
|
+
const imageBase64 = image.toString("base64");
|
|
1202
|
+
const id = import_echo_schema.ObjectId.random();
|
|
1203
|
+
return import_artifact2.ToolResult.Success(`The generation was successful. Image ID: ${id} Prompt: ${prompt}`, [
|
|
1204
|
+
{
|
|
1205
|
+
type: "image",
|
|
1206
|
+
id,
|
|
1207
|
+
source: {
|
|
1208
|
+
type: "base64",
|
|
1209
|
+
mediaType: "image/jpeg",
|
|
1210
|
+
data: imageBase64
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
]);
|
|
1214
|
+
}
|
|
1215
|
+
})
|
|
1216
|
+
};
|
|
1217
|
+
var OllamaDecoderStream = class extends TransformStream {
|
|
1218
|
+
constructor() {
|
|
1219
|
+
super({
|
|
1220
|
+
transform: (chunk, controller) => {
|
|
1221
|
+
this._buffer += chunk;
|
|
1222
|
+
const lines = this._buffer.split("\n");
|
|
1223
|
+
this._buffer = lines.pop() || "";
|
|
1224
|
+
for (const line of lines) {
|
|
1225
|
+
controller.enqueue(JSON.parse(line.trim()));
|
|
1226
|
+
}
|
|
1227
|
+
},
|
|
1228
|
+
flush: (controller) => {
|
|
1229
|
+
this._buffer = this._buffer.trim();
|
|
1230
|
+
if (this._buffer.length > 0) {
|
|
1231
|
+
controller.enqueue(JSON.parse(this._buffer));
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1020
1234
|
});
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1235
|
+
this._buffer = "";
|
|
1236
|
+
}
|
|
1237
|
+
};
|
|
1238
|
+
var textChunk = P.regexp(/[^<]+/).map((content) => ({
|
|
1239
|
+
type: "text",
|
|
1240
|
+
content
|
|
1241
|
+
}));
|
|
1242
|
+
var attribute = P.seq(P.regexp(/[a-zA-Z_][a-zA-Z0-9_-]*/), P.string("=").trim(P.optWhitespace), P.alt(P.regexp(/"[^"]*"/).map((s) => s.slice(1, -1)), P.regexp(/'[^']*'/).map((s) => s.slice(1, -1)))).map(([name, _, value]) => [
|
|
1243
|
+
name,
|
|
1244
|
+
value
|
|
1245
|
+
]);
|
|
1246
|
+
var tagName = P.regexp(/[a-zA-Z_][a-zA-Z0-9_-]*/);
|
|
1247
|
+
var selfClosingTag = P.seqMap(
|
|
1248
|
+
//
|
|
1249
|
+
P.string("<"),
|
|
1250
|
+
tagName,
|
|
1251
|
+
P.optWhitespace.then(attribute).many(),
|
|
1252
|
+
P.optWhitespace.then(P.string("/>")),
|
|
1253
|
+
P.optWhitespace,
|
|
1254
|
+
(_, tag, attributes, __) => ({
|
|
1255
|
+
type: "tag",
|
|
1256
|
+
tag,
|
|
1257
|
+
attributes: Object.fromEntries(attributes),
|
|
1258
|
+
content: [],
|
|
1259
|
+
selfClosing: true
|
|
1260
|
+
})
|
|
1261
|
+
);
|
|
1262
|
+
var openTag = P.seqMap(
|
|
1263
|
+
//
|
|
1264
|
+
P.string("<"),
|
|
1265
|
+
tagName,
|
|
1266
|
+
P.optWhitespace.then(attribute).many(),
|
|
1267
|
+
P.string(">"),
|
|
1268
|
+
P.regexp(/[^<]*/),
|
|
1269
|
+
(_, tag, attributes, __, content) => ({
|
|
1270
|
+
type: "tag",
|
|
1271
|
+
tag,
|
|
1272
|
+
attributes: Object.fromEntries(attributes),
|
|
1273
|
+
content: content.length ? [
|
|
1274
|
+
{
|
|
1275
|
+
type: "text",
|
|
1276
|
+
content
|
|
1277
|
+
}
|
|
1278
|
+
] : []
|
|
1279
|
+
})
|
|
1280
|
+
);
|
|
1281
|
+
var closeTag = P.seqMap(
|
|
1282
|
+
//
|
|
1283
|
+
P.string("</"),
|
|
1284
|
+
tagName,
|
|
1285
|
+
P.string(">"),
|
|
1286
|
+
P.optWhitespace,
|
|
1287
|
+
(_, tag) => ({
|
|
1288
|
+
type: "tag",
|
|
1289
|
+
tag,
|
|
1290
|
+
content: [],
|
|
1291
|
+
closing: true
|
|
1292
|
+
})
|
|
1293
|
+
);
|
|
1294
|
+
var mixedChunk = P.alt(selfClosingTag, openTag, closeTag, textChunk);
|
|
1295
|
+
var StreamTransform = class {
|
|
1296
|
+
constructor() {
|
|
1297
|
+
this._buffer = "";
|
|
1298
|
+
}
|
|
1299
|
+
transform(chunk) {
|
|
1300
|
+
this._buffer += chunk;
|
|
1301
|
+
const results = [];
|
|
1302
|
+
const parser = mixedChunk.many().skip(P.optWhitespace);
|
|
1303
|
+
const result = parser.parse(this._buffer);
|
|
1304
|
+
if (result.status) {
|
|
1305
|
+
for (const chunk2 of result.value) {
|
|
1306
|
+
results.push(chunk2);
|
|
1041
1307
|
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1308
|
+
this._buffer = "";
|
|
1309
|
+
}
|
|
1310
|
+
return results;
|
|
1311
|
+
}
|
|
1312
|
+
// TODO(burdon): Process remaining buffer?
|
|
1313
|
+
flush() {
|
|
1314
|
+
const remaining = this._buffer;
|
|
1315
|
+
this._buffer = "";
|
|
1316
|
+
return remaining.length > 0 ? [
|
|
1317
|
+
{
|
|
1318
|
+
type: "text",
|
|
1319
|
+
content: remaining
|
|
1320
|
+
}
|
|
1321
|
+
] : [];
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/experimental/assistant/src/ai-service/parser.ts";
|
|
1325
|
+
var MixedStreamParser = class {
|
|
1326
|
+
constructor() {
|
|
1327
|
+
this.message = new import_async2.Event();
|
|
1328
|
+
this.block = new import_async2.Event();
|
|
1329
|
+
this.update = new import_async2.Event();
|
|
1330
|
+
this.streamEvent = new import_async2.Event();
|
|
1331
|
+
}
|
|
1332
|
+
_emitBlock(contentBlock, streamBlock) {
|
|
1333
|
+
const messageBlock = streamBlock ? mergeMessageBlock(contentBlock, streamBlock) : contentBlock;
|
|
1334
|
+
if (messageBlock) {
|
|
1335
|
+
if (messageBlock.type === "text" && messageBlock.text.length === 0) {
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
(0, import_invariant4.invariant)(this._message, void 0, {
|
|
1339
|
+
F: __dxlog_file5,
|
|
1340
|
+
L: 49,
|
|
1341
|
+
S: this,
|
|
1046
1342
|
A: [
|
|
1047
|
-
"
|
|
1343
|
+
"this._message",
|
|
1048
1344
|
""
|
|
1049
1345
|
]
|
|
1050
1346
|
});
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1347
|
+
this._message.content.push(messageBlock);
|
|
1348
|
+
this.block.emit(messageBlock);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
_emitUpdate(contentBlock, streamBlock) {
|
|
1352
|
+
const messageBlock = mergeMessageBlock(contentBlock, streamBlock);
|
|
1353
|
+
if (messageBlock) {
|
|
1354
|
+
messageBlock.pending = true;
|
|
1355
|
+
this.update.emit(messageBlock);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Parse stream until end.
|
|
1360
|
+
*/
|
|
1361
|
+
async parse(stream) {
|
|
1362
|
+
const transformer = new StreamTransform();
|
|
1363
|
+
let contentBlock;
|
|
1364
|
+
let streamBlock;
|
|
1365
|
+
const stack = [];
|
|
1366
|
+
const messagesCollected = [];
|
|
1367
|
+
for await (const event of stream) {
|
|
1368
|
+
this.streamEvent.emit(event);
|
|
1369
|
+
switch (event.type) {
|
|
1370
|
+
//
|
|
1371
|
+
// Messages.
|
|
1372
|
+
//
|
|
1373
|
+
case "message_start": {
|
|
1374
|
+
if (this._message) {
|
|
1375
|
+
import_log5.log.warn("unexpected message_start", void 0, {
|
|
1376
|
+
F: __dxlog_file5,
|
|
1377
|
+
L: 93,
|
|
1378
|
+
S: this,
|
|
1379
|
+
C: (f, a) => f(...a)
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
this._message = (0, import_echo_schema4.createStatic)(import_artifact5.Message, {
|
|
1383
|
+
role: event.message.role,
|
|
1067
1384
|
content: [
|
|
1068
|
-
|
|
1069
|
-
type: "tool_result",
|
|
1070
|
-
toolUseId: toolCall.id,
|
|
1071
|
-
content: toolResult.message,
|
|
1072
|
-
isError: true
|
|
1073
|
-
}
|
|
1385
|
+
...event.message.content
|
|
1074
1386
|
]
|
|
1075
|
-
};
|
|
1076
|
-
params.logger?.({
|
|
1077
|
-
type: "message",
|
|
1078
|
-
message: resultMessage
|
|
1079
1387
|
});
|
|
1080
|
-
|
|
1081
|
-
|
|
1388
|
+
this.message.emit(this._message);
|
|
1389
|
+
break;
|
|
1082
1390
|
}
|
|
1083
|
-
case "
|
|
1084
|
-
(
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1391
|
+
case "message_delta": {
|
|
1392
|
+
if (!this._message) {
|
|
1393
|
+
import_log5.log.warn("unexpected message_delta", void 0, {
|
|
1394
|
+
F: __dxlog_file5,
|
|
1395
|
+
L: 103,
|
|
1396
|
+
S: this,
|
|
1397
|
+
C: (f, a) => f(...a)
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
break;
|
|
1401
|
+
}
|
|
1402
|
+
case "message_stop": {
|
|
1403
|
+
if (!this._message) {
|
|
1404
|
+
import_log5.log.warn("unexpected message_stop", void 0, {
|
|
1405
|
+
F: __dxlog_file5,
|
|
1406
|
+
L: 111,
|
|
1407
|
+
S: this,
|
|
1408
|
+
C: (f, a) => f(...a)
|
|
1409
|
+
});
|
|
1410
|
+
} else {
|
|
1411
|
+
messagesCollected.push(this._message);
|
|
1412
|
+
this._message = void 0;
|
|
1413
|
+
}
|
|
1414
|
+
break;
|
|
1415
|
+
}
|
|
1416
|
+
//
|
|
1417
|
+
// Content blocks.
|
|
1418
|
+
//
|
|
1419
|
+
case "content_block_start": {
|
|
1420
|
+
if (contentBlock) {
|
|
1421
|
+
import_log5.log.warn("unexpected content_block_start", {
|
|
1422
|
+
content: contentBlock
|
|
1423
|
+
}, {
|
|
1424
|
+
F: __dxlog_file5,
|
|
1425
|
+
L: 125,
|
|
1426
|
+
S: this,
|
|
1427
|
+
C: (f, a) => f(...a)
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
contentBlock = event.content;
|
|
1431
|
+
break;
|
|
1432
|
+
}
|
|
1433
|
+
case "content_block_delta": {
|
|
1434
|
+
if (!contentBlock) {
|
|
1435
|
+
import_log5.log.warn("unexpected content_block_delta", void 0, {
|
|
1436
|
+
F: __dxlog_file5,
|
|
1437
|
+
L: 135,
|
|
1438
|
+
S: this,
|
|
1439
|
+
C: (f, a) => f(...a)
|
|
1440
|
+
});
|
|
1441
|
+
break;
|
|
1442
|
+
}
|
|
1443
|
+
switch (event.delta.type) {
|
|
1444
|
+
//
|
|
1445
|
+
// Text
|
|
1446
|
+
//
|
|
1447
|
+
case "text_delta": {
|
|
1448
|
+
const chunks = transformer.transform(event.delta.text);
|
|
1449
|
+
for (const chunk of chunks) {
|
|
1450
|
+
switch (streamBlock?.type) {
|
|
1451
|
+
//
|
|
1452
|
+
// XML Fragment.
|
|
1453
|
+
//
|
|
1454
|
+
case "tag": {
|
|
1455
|
+
if (chunk.type === "tag") {
|
|
1456
|
+
if (chunk.selfClosing) {
|
|
1457
|
+
streamBlock.content.push(chunk);
|
|
1458
|
+
} else if (chunk.closing) {
|
|
1459
|
+
if (stack.length > 0) {
|
|
1460
|
+
const top = stack.pop();
|
|
1461
|
+
(0, import_invariant4.invariant)(top && top.type === "tag", void 0, {
|
|
1462
|
+
F: __dxlog_file5,
|
|
1463
|
+
L: 159,
|
|
1464
|
+
S: this,
|
|
1465
|
+
A: [
|
|
1466
|
+
"top && top.type === 'tag'",
|
|
1467
|
+
""
|
|
1468
|
+
]
|
|
1469
|
+
});
|
|
1470
|
+
top.content.push(streamBlock);
|
|
1471
|
+
streamBlock = top;
|
|
1472
|
+
} else {
|
|
1473
|
+
this._emitBlock(contentBlock, streamBlock);
|
|
1474
|
+
streamBlock = void 0;
|
|
1475
|
+
}
|
|
1476
|
+
} else {
|
|
1477
|
+
stack.push(streamBlock);
|
|
1478
|
+
streamBlock = chunk;
|
|
1479
|
+
}
|
|
1480
|
+
} else {
|
|
1481
|
+
if (streamBlock.content.length === 0) {
|
|
1482
|
+
streamBlock.content.push(chunk);
|
|
1483
|
+
} else {
|
|
1484
|
+
const last = streamBlock.content.at(-1);
|
|
1485
|
+
(0, import_invariant4.invariant)(last, void 0, {
|
|
1486
|
+
F: __dxlog_file5,
|
|
1487
|
+
L: 176,
|
|
1488
|
+
S: this,
|
|
1489
|
+
A: [
|
|
1490
|
+
"last",
|
|
1491
|
+
""
|
|
1492
|
+
]
|
|
1493
|
+
});
|
|
1494
|
+
if (last.type === "text") {
|
|
1495
|
+
last.content += chunk.content;
|
|
1496
|
+
} else {
|
|
1497
|
+
streamBlock.content.push(chunk);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
break;
|
|
1502
|
+
}
|
|
1503
|
+
//
|
|
1504
|
+
// Text Fragment.
|
|
1505
|
+
//
|
|
1506
|
+
case "text": {
|
|
1507
|
+
if (chunk.type === "tag") {
|
|
1508
|
+
this._emitBlock(contentBlock, streamBlock);
|
|
1509
|
+
if (chunk.selfClosing) {
|
|
1510
|
+
this._emitBlock(contentBlock, chunk);
|
|
1511
|
+
streamBlock = void 0;
|
|
1512
|
+
} else {
|
|
1513
|
+
streamBlock = chunk;
|
|
1514
|
+
}
|
|
1515
|
+
} else {
|
|
1516
|
+
streamBlock.content += chunk.content;
|
|
1517
|
+
}
|
|
1518
|
+
break;
|
|
1519
|
+
}
|
|
1520
|
+
//
|
|
1521
|
+
// No current chunk.
|
|
1522
|
+
//
|
|
1523
|
+
default: {
|
|
1524
|
+
if (chunk.type === "tag" && chunk.selfClosing) {
|
|
1525
|
+
this._emitBlock(contentBlock, chunk);
|
|
1526
|
+
} else {
|
|
1527
|
+
streamBlock = chunk;
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1102
1531
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1532
|
+
break;
|
|
1533
|
+
}
|
|
1534
|
+
//
|
|
1535
|
+
// JSON
|
|
1536
|
+
//
|
|
1537
|
+
case "input_json_delta": {
|
|
1538
|
+
if (!contentBlock) {
|
|
1539
|
+
import_log5.log.warn("unexpected input_json_delta", {
|
|
1540
|
+
contentBlock
|
|
1541
|
+
}, {
|
|
1542
|
+
F: __dxlog_file5,
|
|
1543
|
+
L: 226,
|
|
1544
|
+
S: this,
|
|
1545
|
+
C: (f, a) => f(...a)
|
|
1546
|
+
});
|
|
1547
|
+
break;
|
|
1548
|
+
}
|
|
1549
|
+
if (streamBlock?.type === "json") {
|
|
1550
|
+
streamBlock.content += event.delta.partial_json;
|
|
1551
|
+
} else {
|
|
1552
|
+
streamBlock = {
|
|
1553
|
+
type: "json",
|
|
1554
|
+
content: event.delta.partial_json
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
break;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
break;
|
|
1111
1561
|
}
|
|
1112
|
-
case "
|
|
1113
|
-
(
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1562
|
+
case "content_block_stop": {
|
|
1563
|
+
if (!contentBlock) {
|
|
1564
|
+
import_log5.log.warn("unexpected content_block_stop", void 0, {
|
|
1565
|
+
F: __dxlog_file5,
|
|
1566
|
+
L: 243,
|
|
1567
|
+
S: this,
|
|
1568
|
+
C: (f, a) => f(...a)
|
|
1569
|
+
});
|
|
1570
|
+
break;
|
|
1571
|
+
}
|
|
1572
|
+
this._emitBlock(contentBlock, streamBlock);
|
|
1573
|
+
contentBlock = void 0;
|
|
1574
|
+
streamBlock = void 0;
|
|
1575
|
+
break;
|
|
1123
1576
|
}
|
|
1124
1577
|
}
|
|
1578
|
+
if (contentBlock && streamBlock) {
|
|
1579
|
+
this._emitUpdate(contentBlock, streamBlock);
|
|
1580
|
+
}
|
|
1125
1581
|
}
|
|
1126
|
-
return
|
|
1127
|
-
};
|
|
1128
|
-
while (await generate()) {
|
|
1582
|
+
return messagesCollected;
|
|
1129
1583
|
}
|
|
1130
|
-
return {
|
|
1131
|
-
result: conversationResult,
|
|
1132
|
-
history
|
|
1133
|
-
};
|
|
1134
|
-
};
|
|
1135
|
-
var isToolUse = (message) => {
|
|
1136
|
-
const block = message.content.at(-1);
|
|
1137
|
-
(0, import_invariant3.invariant)(block, void 0, {
|
|
1138
|
-
F: __dxlog_file4,
|
|
1139
|
-
L: 152,
|
|
1140
|
-
S: void 0,
|
|
1141
|
-
A: [
|
|
1142
|
-
"block",
|
|
1143
|
-
""
|
|
1144
|
-
]
|
|
1145
|
-
});
|
|
1146
|
-
return block.type === "tool_use";
|
|
1147
1584
|
};
|
|
1148
|
-
var
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1585
|
+
var mergeMessageBlock = (contentBlock, streamBlock) => {
|
|
1586
|
+
(0, import_log5.log)("mergeMessageBlock", {
|
|
1587
|
+
contentBlock,
|
|
1588
|
+
streamBlock
|
|
1589
|
+
}, {
|
|
1590
|
+
F: __dxlog_file5,
|
|
1591
|
+
L: 270,
|
|
1153
1592
|
S: void 0,
|
|
1154
|
-
|
|
1155
|
-
"toolCalls.length === 1",
|
|
1156
|
-
""
|
|
1157
|
-
]
|
|
1593
|
+
C: (f, a) => f(...a)
|
|
1158
1594
|
});
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
let toolResult;
|
|
1165
|
-
try {
|
|
1166
|
-
(0, import_invariant3.invariant)(tool.execute, void 0, {
|
|
1167
|
-
F: __dxlog_file4,
|
|
1168
|
-
L: 183,
|
|
1169
|
-
S: void 0,
|
|
1170
|
-
A: [
|
|
1171
|
-
"tool.execute",
|
|
1172
|
-
""
|
|
1173
|
-
]
|
|
1174
|
-
});
|
|
1175
|
-
toolResult = await tool.execute(toolCall.input, {
|
|
1176
|
-
extensions
|
|
1177
|
-
});
|
|
1178
|
-
} catch (error) {
|
|
1179
|
-
(0, import_log4.log)("tool error", {
|
|
1180
|
-
error
|
|
1181
|
-
}, {
|
|
1182
|
-
F: __dxlog_file4,
|
|
1183
|
-
L: 186,
|
|
1184
|
-
S: void 0,
|
|
1185
|
-
C: (f, a) => f(...a)
|
|
1186
|
-
});
|
|
1187
|
-
toolResult = import_artifact4.ToolResult.Error(error.message);
|
|
1188
|
-
}
|
|
1189
|
-
switch (toolResult.kind) {
|
|
1190
|
-
case "error": {
|
|
1191
|
-
(0, import_log4.log)("tool error", {
|
|
1192
|
-
message: toolResult.message
|
|
1193
|
-
}, {
|
|
1194
|
-
F: __dxlog_file4,
|
|
1195
|
-
L: 192,
|
|
1196
|
-
S: void 0,
|
|
1197
|
-
C: (f, a) => f(...a)
|
|
1198
|
-
});
|
|
1199
|
-
const resultMessage = (0, import_echo_schema3.createStatic)(import_artifact4.Message, {
|
|
1200
|
-
role: "user",
|
|
1201
|
-
content: [
|
|
1202
|
-
{
|
|
1203
|
-
type: "tool_result",
|
|
1204
|
-
toolUseId: toolCall.id,
|
|
1205
|
-
content: toolResult.message,
|
|
1206
|
-
isError: true
|
|
1207
|
-
}
|
|
1208
|
-
]
|
|
1209
|
-
});
|
|
1595
|
+
switch (streamBlock.type) {
|
|
1596
|
+
//
|
|
1597
|
+
// Text
|
|
1598
|
+
//
|
|
1599
|
+
case "text": {
|
|
1210
1600
|
return {
|
|
1211
|
-
|
|
1212
|
-
|
|
1601
|
+
...contentBlock,
|
|
1602
|
+
type: "text",
|
|
1603
|
+
text: streamBlock.content
|
|
1213
1604
|
};
|
|
1214
1605
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1606
|
+
//
|
|
1607
|
+
// XML
|
|
1608
|
+
//
|
|
1609
|
+
case "tag": {
|
|
1610
|
+
switch (streamBlock.tag) {
|
|
1611
|
+
case "cot": {
|
|
1612
|
+
const content = streamBlock.content.map((block) => {
|
|
1613
|
+
switch (block.type) {
|
|
1614
|
+
case "text":
|
|
1615
|
+
return block.content;
|
|
1616
|
+
default:
|
|
1617
|
+
return null;
|
|
1618
|
+
}
|
|
1619
|
+
}).filter(import_util.isNotFalsy).join("\n");
|
|
1620
|
+
return {
|
|
1621
|
+
...contentBlock,
|
|
1622
|
+
type: "text",
|
|
1623
|
+
disposition: "cot",
|
|
1624
|
+
text: content
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
case "artifact": {
|
|
1628
|
+
const { attributes } = streamBlock;
|
|
1629
|
+
return {
|
|
1630
|
+
type: "json",
|
|
1631
|
+
disposition: "artifact",
|
|
1632
|
+
json: JSON.stringify(attributes)
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
case "suggest": {
|
|
1636
|
+
if (streamBlock.content.length === 1 && streamBlock.content[0].type === "text") {
|
|
1637
|
+
return {
|
|
1638
|
+
type: "json",
|
|
1639
|
+
disposition: "suggest",
|
|
1640
|
+
json: JSON.stringify({
|
|
1641
|
+
text: streamBlock.content[0].content
|
|
1642
|
+
})
|
|
1643
|
+
};
|
|
1231
1644
|
}
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1645
|
+
break;
|
|
1646
|
+
}
|
|
1647
|
+
case "select": {
|
|
1648
|
+
return {
|
|
1649
|
+
type: "json",
|
|
1650
|
+
disposition: "select",
|
|
1651
|
+
json: JSON.stringify({
|
|
1652
|
+
options: streamBlock.content.flatMap((content) => content.type === "tag" && content.content.length === 1 && content.content[0].type === "text" ? [
|
|
1653
|
+
content.content[0].content
|
|
1654
|
+
] : [])
|
|
1655
|
+
})
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
case "tool-list": {
|
|
1659
|
+
return {
|
|
1660
|
+
type: "json",
|
|
1661
|
+
disposition: "tool_list",
|
|
1662
|
+
json: JSON.stringify({})
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
break;
|
|
1238
1667
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1668
|
+
//
|
|
1669
|
+
// JSON
|
|
1670
|
+
//
|
|
1671
|
+
case "json": {
|
|
1672
|
+
switch (contentBlock.type) {
|
|
1673
|
+
case "tool_use": {
|
|
1674
|
+
return {
|
|
1675
|
+
...contentBlock,
|
|
1676
|
+
input: (0, import_util.safeParseJson)(streamBlock.content) ?? {}
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1248
1680
|
return {
|
|
1249
|
-
|
|
1250
|
-
|
|
1681
|
+
...contentBlock,
|
|
1682
|
+
type: "json",
|
|
1683
|
+
disposition: "artifact",
|
|
1684
|
+
json: streamBlock.content
|
|
1251
1685
|
};
|
|
1252
1686
|
}
|
|
1253
1687
|
}
|
|
1254
1688
|
};
|
|
1255
1689
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1256
1690
|
0 && (module.exports = {
|
|
1257
|
-
|
|
1691
|
+
AIServiceEdgeClient,
|
|
1258
1692
|
DEFAULT_LLM_MODEL,
|
|
1259
1693
|
DEFAULT_LLM_MODELS,
|
|
1260
1694
|
EchoDataSource,
|
|
1261
1695
|
GenerateRequest,
|
|
1262
|
-
|
|
1696
|
+
GenerationStreamImpl,
|
|
1263
1697
|
LLMModel,
|
|
1698
|
+
MessageCollector,
|
|
1264
1699
|
MixedStreamParser,
|
|
1700
|
+
OllamaClient,
|
|
1265
1701
|
StreamTransform,
|
|
1266
1702
|
ToolTypes,
|
|
1267
1703
|
createArtifactElement,
|
|
1268
1704
|
createGenerationStream,
|
|
1705
|
+
emitMessageAsEvents,
|
|
1269
1706
|
executeQuery,
|
|
1270
1707
|
executeQueryPlan,
|
|
1271
1708
|
formatInferredRelationshipLabel,
|