@omercnet/paseo-omp 0.4.0-next.119.1 → 0.4.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/package.json +1 -3
- package/server/package-version.ts +1 -1
- package/server/provider/connection.ts +1 -28
- package/server/provider/omp-rpc.ts +178 -792
- package/server/provider/session-descriptors.ts +18 -52
- package/server/provider/session.ts +1 -12
- package/server/provider/subsessions.ts +6 -28
- package/server/provider/timeline-projector.ts +24 -94
|
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { constants, type Dir } from "node:fs";
|
|
3
3
|
import { type FileHandle, lstat, open, opendir, realpath } from "node:fs/promises";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
|
-
import { basename, isAbsolute, join,
|
|
5
|
+
import { basename, dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
6
6
|
import { ompSessionDir } from "../paths";
|
|
7
7
|
import { isValidImagePayload } from "./image";
|
|
8
8
|
|
|
@@ -510,19 +510,16 @@ interface PersistedTranscriptNode {
|
|
|
510
510
|
message?: unknown;
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
-
function persistedTranscriptMessage(record: Record<string, unknown>, entryId
|
|
513
|
+
function persistedTranscriptMessage(record: Record<string, unknown>, entryId: string): unknown {
|
|
514
514
|
if (record.type === "message") {
|
|
515
515
|
if (!record.message || typeof record.message !== "object" || Array.isArray(record.message))
|
|
516
516
|
return;
|
|
517
|
-
return {
|
|
518
|
-
...(record.message as Record<string, unknown>),
|
|
519
|
-
...(entryId ? { entryId } : {}),
|
|
520
|
-
};
|
|
517
|
+
return { ...(record.message as Record<string, unknown>), entryId };
|
|
521
518
|
}
|
|
522
519
|
if (record.type !== "custom_message") return;
|
|
523
520
|
return {
|
|
524
521
|
role: "custom",
|
|
525
|
-
|
|
522
|
+
entryId,
|
|
526
523
|
customType: record.customType,
|
|
527
524
|
content: record.content,
|
|
528
525
|
display: record.display,
|
|
@@ -683,7 +680,6 @@ export async function readOmpPersistedSubagentTranscript(
|
|
|
683
680
|
childTranscriptId: string,
|
|
684
681
|
cwd: string,
|
|
685
682
|
signal?: AbortSignal,
|
|
686
|
-
childSessionFile?: string,
|
|
687
683
|
): Promise<OmpPersistedSubagentTranscript> {
|
|
688
684
|
signal?.throwIfAborted();
|
|
689
685
|
if (
|
|
@@ -691,12 +687,7 @@ export async function readOmpPersistedSubagentTranscript(
|
|
|
691
687
|
!parentSessionFile.endsWith(".jsonl") ||
|
|
692
688
|
parentSessionFile.includes("\0") ||
|
|
693
689
|
!CHILD_TRANSCRIPT_ID.test(childTranscriptId) ||
|
|
694
|
-
basename(childTranscriptId) !== childTranscriptId
|
|
695
|
-
(childSessionFile !== undefined &&
|
|
696
|
-
(!isAbsolute(childSessionFile) ||
|
|
697
|
-
!childSessionFile.endsWith(".jsonl") ||
|
|
698
|
-
childSessionFile.includes("\0") ||
|
|
699
|
-
basename(childSessionFile) !== `${childTranscriptId}.jsonl`))
|
|
690
|
+
basename(childTranscriptId) !== childTranscriptId
|
|
700
691
|
) {
|
|
701
692
|
throw new Error("Invalid OMP child transcript descriptor");
|
|
702
693
|
}
|
|
@@ -716,53 +707,34 @@ export async function readOmpPersistedSubagentTranscript(
|
|
|
716
707
|
await parentHandle.close().catch(() => undefined);
|
|
717
708
|
}
|
|
718
709
|
const canonicalParent = await realpath(parentSessionFile);
|
|
719
|
-
const
|
|
710
|
+
const parentExtension = extname(canonicalParent);
|
|
711
|
+
const expectedDirectory = canonicalParent.slice(0, -parentExtension.length);
|
|
720
712
|
const canonicalDirectory = await realpath(expectedDirectory).catch(() => undefined);
|
|
721
713
|
if (!canonicalDirectory || canonicalDirectory !== expectedDirectory) {
|
|
722
714
|
throw new Error("OMP child transcript directory is not canonically owned by its parent");
|
|
723
715
|
}
|
|
724
|
-
const
|
|
725
|
-
childSessionFile ?? join(canonicalDirectory, `${childTranscriptId}.jsonl`),
|
|
726
|
-
);
|
|
716
|
+
const sessionFile = join(canonicalDirectory, `${childTranscriptId}.jsonl`);
|
|
727
717
|
let handle: FileHandle;
|
|
728
718
|
try {
|
|
729
719
|
handle = await open(
|
|
730
|
-
|
|
720
|
+
sessionFile,
|
|
731
721
|
constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0),
|
|
732
722
|
);
|
|
733
723
|
} catch {
|
|
734
724
|
throw new Error("OMP child transcript could not be opened");
|
|
735
725
|
}
|
|
736
726
|
try {
|
|
737
|
-
const [stat,
|
|
738
|
-
handle.stat(),
|
|
739
|
-
lstat(requestedFile),
|
|
740
|
-
realpath(requestedFile),
|
|
741
|
-
]);
|
|
727
|
+
const [stat, canonicalChild] = await Promise.all([handle.stat(), realpath(sessionFile)]);
|
|
742
728
|
if (
|
|
743
729
|
!stat.isFile() ||
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
stat.ino !== pathStat.ino ||
|
|
748
|
-
stat.size > MAX_CHILD_TRANSCRIPT_BYTES
|
|
749
|
-
) {
|
|
750
|
-
throw new Error("OMP child transcript failed ownership validation");
|
|
751
|
-
}
|
|
752
|
-
const canonicalRelativeChild = relative(canonicalDirectory, canonicalChild);
|
|
753
|
-
if (
|
|
754
|
-
!canonicalRelativeChild ||
|
|
755
|
-
canonicalRelativeChild.startsWith("..") ||
|
|
756
|
-
isAbsolute(canonicalRelativeChild)
|
|
730
|
+
stat.size > MAX_CHILD_TRANSCRIPT_BYTES ||
|
|
731
|
+
dirname(canonicalChild) !== canonicalDirectory ||
|
|
732
|
+
canonicalChild !== sessionFile
|
|
757
733
|
) {
|
|
758
734
|
throw new Error("OMP child transcript failed ownership validation");
|
|
759
735
|
}
|
|
760
|
-
const bytes = await
|
|
761
|
-
|
|
762
|
-
stat.size,
|
|
763
|
-
signal,
|
|
764
|
-
"OMP child transcript changed while reading",
|
|
765
|
-
);
|
|
736
|
+
const bytes = await handle.readFile();
|
|
737
|
+
signal?.throwIfAborted();
|
|
766
738
|
const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
767
739
|
const messages: unknown[] = [];
|
|
768
740
|
let nativeSessionId: string | undefined;
|
|
@@ -780,21 +752,15 @@ export async function readOmpPersistedSubagentTranscript(
|
|
|
780
752
|
nativeSessionId ??= candidateId;
|
|
781
753
|
if (nativeSessionId !== candidateId)
|
|
782
754
|
throw new Error("OMP child transcript identity changed");
|
|
783
|
-
} else {
|
|
784
|
-
const entryId =
|
|
785
|
-
typeof record.id === "string" && CHILD_TRANSCRIPT_ID.test(record.id)
|
|
786
|
-
? record.id
|
|
787
|
-
: undefined;
|
|
788
|
-
const message = persistedTranscriptMessage(record, entryId);
|
|
789
|
-
if (message === undefined) continue;
|
|
755
|
+
} else if (record.type === "message" && record.message !== undefined) {
|
|
790
756
|
if (messages.length >= MAX_CHILD_TRANSCRIPT_MESSAGES) {
|
|
791
757
|
throw new Error("OMP child transcript exceeds message limits");
|
|
792
758
|
}
|
|
793
|
-
messages.push(message);
|
|
759
|
+
messages.push(record.message);
|
|
794
760
|
}
|
|
795
761
|
}
|
|
796
762
|
if (!nativeSessionId) throw new Error("OMP child transcript is missing session identity");
|
|
797
|
-
return { sessionFile
|
|
763
|
+
return { sessionFile, nativeSessionId, byteLength: bytes.byteLength, messages };
|
|
798
764
|
} catch (error) {
|
|
799
765
|
if (error instanceof Error) throw error;
|
|
800
766
|
throw new Error("OMP child transcript could not be decoded");
|
|
@@ -1685,7 +1685,7 @@ export class OmpProviderSession {
|
|
|
1685
1685
|
});
|
|
1686
1686
|
}
|
|
1687
1687
|
}
|
|
1688
|
-
messages ??= await waitForReplay(this.runtime.getMessages(
|
|
1688
|
+
messages ??= await waitForReplay(this.runtime.getMessages(), replay.signal);
|
|
1689
1689
|
this.quarantineBranchEntries();
|
|
1690
1690
|
for (const message of messages) {
|
|
1691
1691
|
replay.signal.throwIfAborted();
|
|
@@ -3234,17 +3234,6 @@ export class OmpProviderSession {
|
|
|
3234
3234
|
this.handleRuntimeFailure();
|
|
3235
3235
|
return;
|
|
3236
3236
|
}
|
|
3237
|
-
if (
|
|
3238
|
-
event.type === "config_warnings_changed" ||
|
|
3239
|
-
event.type === "advisor_cost_changed" ||
|
|
3240
|
-
event.type === "ttsr_triggered"
|
|
3241
|
-
) {
|
|
3242
|
-
return;
|
|
3243
|
-
}
|
|
3244
|
-
if (event.type === "irc_message") {
|
|
3245
|
-
this.projector.projectPassive(event);
|
|
3246
|
-
return;
|
|
3247
|
-
}
|
|
3248
3237
|
if (
|
|
3249
3238
|
event.type === "notice" ||
|
|
3250
3239
|
event.type === "todo_reminder" ||
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { basename, extname
|
|
2
|
+
import { basename, extname } from "node:path";
|
|
3
3
|
import type { ProviderEvent } from "@getpaseo/plugin/server/provider";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import type {
|
|
@@ -882,32 +882,10 @@ export class OmpSubsessionProjector {
|
|
|
882
882
|
signal.throwIfAborted();
|
|
883
883
|
if (this.sessionIdByNativeId.has(snapshot.id)) continue;
|
|
884
884
|
try {
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
runtime.readPersistedSubagentTranscript({
|
|
890
|
-
parentSessionFile: this.rootSessionFile,
|
|
891
|
-
childTranscriptId: snapshot.id,
|
|
892
|
-
sessionFile: snapshot.sessionFile,
|
|
893
|
-
cwd: this.cwd,
|
|
894
|
-
signal,
|
|
895
|
-
}),
|
|
896
|
-
signal,
|
|
897
|
-
);
|
|
898
|
-
} catch (error) {
|
|
899
|
-
if (signal.aborted) throw error;
|
|
900
|
-
history = await waitForReplay(
|
|
901
|
-
runtimeSession.getSubagentMessages({ subagentId: snapshot.id }),
|
|
902
|
-
signal,
|
|
903
|
-
);
|
|
904
|
-
}
|
|
905
|
-
} else {
|
|
906
|
-
history = await waitForReplay(
|
|
907
|
-
runtimeSession.getSubagentMessages({ subagentId: snapshot.id }),
|
|
908
|
-
signal,
|
|
909
|
-
);
|
|
910
|
-
}
|
|
885
|
+
const history = await waitForReplay(
|
|
886
|
+
runtimeSession.getSubagentMessages({ subagentId: snapshot.id }),
|
|
887
|
+
signal,
|
|
888
|
+
);
|
|
911
889
|
try {
|
|
912
890
|
this.accountReplay(history.messages, budget, signal);
|
|
913
891
|
collected.push({
|
|
@@ -921,7 +899,7 @@ export class OmpSubsessionProjector {
|
|
|
921
899
|
}
|
|
922
900
|
} catch (error) {
|
|
923
901
|
if (signal.aborted) throw error;
|
|
924
|
-
collected.push({ snapshot
|
|
902
|
+
collected.push({ snapshot });
|
|
925
903
|
}
|
|
926
904
|
}
|
|
927
905
|
collected.sort((left, right) => {
|
|
@@ -6,12 +6,7 @@ import type {
|
|
|
6
6
|
} from "@getpaseo/plugin/server/provider";
|
|
7
7
|
import { OMP_MCP_AUTH_TIMELINE_KIND } from "../../shared/mcp";
|
|
8
8
|
import { isOmpImageMimeType, isValidImagePayload, type OmpImageMimeType } from "./image";
|
|
9
|
-
import {
|
|
10
|
-
OMP_MAX_CONTENT_PARTS,
|
|
11
|
-
OMP_MESSAGE_REPLAY_POLICIES,
|
|
12
|
-
type OmpMessage,
|
|
13
|
-
type OmpRpcEvent,
|
|
14
|
-
} from "./omp-rpc";
|
|
9
|
+
import { OMP_MAX_CONTENT_PARTS, type OmpMessage, type OmpRpcEvent } from "./omp-rpc";
|
|
15
10
|
import {
|
|
16
11
|
boundedJsonBytes,
|
|
17
12
|
type JsonValue,
|
|
@@ -139,10 +134,6 @@ function imageBlock(data: string, mimeType: string): StreamBlockSnapshot | undef
|
|
|
139
134
|
}
|
|
140
135
|
|
|
141
136
|
type OmpAssistantMessage = Extract<OmpMessage, { role: "assistant" }>;
|
|
142
|
-
type OmpCustomDisplayMessage = Extract<
|
|
143
|
-
OmpMessage,
|
|
144
|
-
{ role: "bashExecution" | "pythonExecution" | "custom" | "hookMessage" }
|
|
145
|
-
>;
|
|
146
137
|
|
|
147
138
|
function blockText(
|
|
148
139
|
message: OmpAssistantMessage,
|
|
@@ -426,35 +417,16 @@ export class OmpTimelineProjector {
|
|
|
426
417
|
return;
|
|
427
418
|
}
|
|
428
419
|
}
|
|
429
|
-
if (
|
|
430
|
-
(event.type === "message_start" ||
|
|
431
|
-
event.type === "message_update" ||
|
|
432
|
-
event.type === "message_end") &&
|
|
433
|
-
OMP_MESSAGE_REPLAY_POLICIES[event.message.role] === "ignore"
|
|
434
|
-
) {
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
420
|
if (
|
|
438
421
|
event.type === "todo_reminder" ||
|
|
439
422
|
event.type === "todo_auto_clear" ||
|
|
440
|
-
event.type === "goal_updated" ||
|
|
441
|
-
event.type === "auto_retry_start" ||
|
|
442
|
-
event.type === "auto_retry_end" ||
|
|
443
|
-
event.type === "retry_fallback_applied" ||
|
|
444
|
-
event.type === "retry_fallback_succeeded" ||
|
|
445
423
|
event.type === "notice" ||
|
|
446
424
|
event.type === "extension_ui_request" ||
|
|
447
425
|
event.type === "auto_compaction_start" ||
|
|
448
426
|
event.type === "auto_compaction_end" ||
|
|
449
427
|
event.type === "compaction_start" ||
|
|
450
428
|
event.type === "compaction_end" ||
|
|
451
|
-
event.type === "advisor_yielded"
|
|
452
|
-
event.type === "config_warnings_changed" ||
|
|
453
|
-
event.type === "advisor_cost_changed" ||
|
|
454
|
-
event.type === "ttsr_triggered" ||
|
|
455
|
-
event.type === "irc_message" ||
|
|
456
|
-
event.type === "model_changed" ||
|
|
457
|
-
event.type === "thinking_level_changed"
|
|
429
|
+
event.type === "advisor_yielded"
|
|
458
430
|
) {
|
|
459
431
|
this.projectPassive(event);
|
|
460
432
|
return;
|
|
@@ -477,12 +449,7 @@ export class OmpTimelineProjector {
|
|
|
477
449
|
this.scheduleFlush();
|
|
478
450
|
return;
|
|
479
451
|
case "message_end":
|
|
480
|
-
if (
|
|
481
|
-
event.message.role === "custom" ||
|
|
482
|
-
event.message.role === "hookMessage" ||
|
|
483
|
-
event.message.role === "bashExecution" ||
|
|
484
|
-
event.message.role === "pythonExecution"
|
|
485
|
-
) {
|
|
452
|
+
if (event.message.role === "custom" || event.message.role === "bashExecution") {
|
|
486
453
|
this.publishCustomMessage(event.message);
|
|
487
454
|
return;
|
|
488
455
|
}
|
|
@@ -532,13 +499,12 @@ export class OmpTimelineProjector {
|
|
|
532
499
|
if (!snapshot.silent) this.publishTool(snapshot, "running");
|
|
533
500
|
return;
|
|
534
501
|
}
|
|
535
|
-
case "tool_execution_update":
|
|
536
|
-
case "tool_stream_update": {
|
|
502
|
+
case "tool_execution_update": {
|
|
537
503
|
const previous = this.tools.get(event.toolCallId);
|
|
538
504
|
if (!previous) return;
|
|
539
505
|
if (previous.turnId !== turnId || previous.generation !== this.runtimeGeneration) return;
|
|
540
506
|
const output = this.dataFilter.json(
|
|
541
|
-
event.
|
|
507
|
+
event.partialResult,
|
|
542
508
|
MAX_PUBLIC_TOOL_PAYLOAD_BYTES,
|
|
543
509
|
MAX_PUBLIC_TOOL_PAYLOAD_BYTES,
|
|
544
510
|
);
|
|
@@ -634,10 +600,6 @@ export class OmpTimelineProjector {
|
|
|
634
600
|
this.publishRetryFallback(event);
|
|
635
601
|
return;
|
|
636
602
|
}
|
|
637
|
-
if (event.type === "irc_message") {
|
|
638
|
-
this.publishCustomMessage(event.message as OmpCustomDisplayMessage);
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
603
|
if (event.type === "notice") {
|
|
642
604
|
this.noticeSequence += 1;
|
|
643
605
|
this.publish({
|
|
@@ -877,9 +839,8 @@ export class OmpTimelineProjector {
|
|
|
877
839
|
|
|
878
840
|
projectReplayMessage(message: OmpMessage): void {
|
|
879
841
|
if (this.closed) return;
|
|
842
|
+
const nativeIdentity = assistantIdentity(message);
|
|
880
843
|
this.replaySequence += 1;
|
|
881
|
-
if (OMP_MESSAGE_REPLAY_POLICIES[message.role] === "ignore") return;
|
|
882
|
-
|
|
883
844
|
if (message.role === "user") {
|
|
884
845
|
this.replayToolCalls.clear();
|
|
885
846
|
if (this.replayTurnId) this.finishTurn(this.replayTurnId);
|
|
@@ -900,9 +861,7 @@ export class OmpTimelineProjector {
|
|
|
900
861
|
}
|
|
901
862
|
return;
|
|
902
863
|
}
|
|
903
|
-
|
|
904
864
|
if (message.role === "assistant") {
|
|
905
|
-
const nativeIdentity = assistantIdentity(message);
|
|
906
865
|
this.replayTurnId ??= `omp:replay-turn:${this.replaySequence}`;
|
|
907
866
|
this.projectingReplay = true;
|
|
908
867
|
try {
|
|
@@ -921,7 +880,6 @@ export class OmpTimelineProjector {
|
|
|
921
880
|
if (nativeIdentity) this.rememberReplayOccurrence(nativeIdentity, message);
|
|
922
881
|
return;
|
|
923
882
|
}
|
|
924
|
-
|
|
925
883
|
this.replayTurnId ??= `omp:replay-turn:${this.replaySequence}`;
|
|
926
884
|
if (message.role === "toolResult") {
|
|
927
885
|
const replayCall = this.replayToolCalls.get(message.toolCallId);
|
|
@@ -952,18 +910,10 @@ export class OmpTimelineProjector {
|
|
|
952
910
|
);
|
|
953
911
|
return;
|
|
954
912
|
}
|
|
955
|
-
|
|
956
|
-
if (
|
|
957
|
-
message.role === "bashExecution" ||
|
|
958
|
-
message.role === "pythonExecution" ||
|
|
959
|
-
message.role === "custom" ||
|
|
960
|
-
message.role === "hookMessage"
|
|
961
|
-
) {
|
|
913
|
+
if (message.role === "bashExecution") {
|
|
962
914
|
this.publishCustomMessage(message);
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
this.replayTurnId = null;
|
|
966
|
-
}
|
|
915
|
+
this.finishTurn(this.replayTurnId);
|
|
916
|
+
this.replayTurnId = null;
|
|
967
917
|
}
|
|
968
918
|
}
|
|
969
919
|
|
|
@@ -1400,17 +1350,9 @@ export class OmpTimelineProjector {
|
|
|
1400
1350
|
return undefined;
|
|
1401
1351
|
}
|
|
1402
1352
|
|
|
1403
|
-
private publishCustomMessage(message:
|
|
1404
|
-
if (
|
|
1405
|
-
|
|
1406
|
-
message.display === false
|
|
1407
|
-
) {
|
|
1408
|
-
return;
|
|
1409
|
-
}
|
|
1410
|
-
const rawType =
|
|
1411
|
-
message.role === "custom" || message.role === "hookMessage"
|
|
1412
|
-
? (message.customType ?? message.role)
|
|
1413
|
-
: message.role;
|
|
1353
|
+
private publishCustomMessage(message: OmpMessage): void {
|
|
1354
|
+
if (message.display === false) return;
|
|
1355
|
+
const rawType = message.customType ?? message.role;
|
|
1414
1356
|
const publicType = this.dataFilter.text(rawType, 256);
|
|
1415
1357
|
const lowerType = rawType.toLowerCase();
|
|
1416
1358
|
const details = jsonRecord(this.dataFilter.json(message.details ?? null));
|
|
@@ -1419,9 +1361,7 @@ export class OmpTimelineProjector {
|
|
|
1419
1361
|
const id = nativeIdentity
|
|
1420
1362
|
? `omp:custom:${createHash("sha256").update(nativeIdentity).digest("base64url").slice(0, 12)}`
|
|
1421
1363
|
: `omp:custom:${this.customSequence}`;
|
|
1422
|
-
const
|
|
1423
|
-
message.role === "custom" || message.role === "hookMessage" ? message.content : undefined;
|
|
1424
|
-
const contentParts = Array.isArray(messageContent) ? messageContent : [];
|
|
1364
|
+
const contentParts = Array.isArray(message.content) ? message.content : [];
|
|
1425
1365
|
const imageResult = nativeImageResult(
|
|
1426
1366
|
{
|
|
1427
1367
|
content:
|
|
@@ -1433,26 +1373,16 @@ export class OmpTimelineProjector {
|
|
|
1433
1373
|
this.dataFilter,
|
|
1434
1374
|
);
|
|
1435
1375
|
const content =
|
|
1436
|
-
typeof
|
|
1437
|
-
?
|
|
1376
|
+
typeof message.content === "string"
|
|
1377
|
+
? message.content
|
|
1438
1378
|
: contentParts
|
|
1439
1379
|
.flatMap((part) => (part.type === "text" && part.text ? [part.text] : []))
|
|
1440
1380
|
.join("\n\n");
|
|
1441
|
-
|
|
1442
|
-
if (execution || /bash|shell|python/u.test(lowerType)) {
|
|
1443
|
-
const nativeCommand =
|
|
1444
|
-
message.role === "bashExecution"
|
|
1445
|
-
? message.command
|
|
1446
|
-
: message.role === "pythonExecution"
|
|
1447
|
-
? message.code
|
|
1448
|
-
: undefined;
|
|
1381
|
+
if (message.role === "bashExecution" || /bash|shell|python/u.test(lowerType)) {
|
|
1449
1382
|
const command = this.dataFilter.text(
|
|
1450
|
-
|
|
1383
|
+
message.command ?? firstString(details, "command", "input") ?? publicType,
|
|
1451
1384
|
);
|
|
1452
|
-
const output =
|
|
1453
|
-
const exitCode = execution ? message.exitCode : undefined;
|
|
1454
|
-
const cancelled = execution ? message.cancelled : undefined;
|
|
1455
|
-
const truncated = execution ? message.truncated : undefined;
|
|
1385
|
+
const output = message.output ?? content;
|
|
1456
1386
|
this.publish({
|
|
1457
1387
|
type: "tool_call",
|
|
1458
1388
|
id,
|
|
@@ -1463,21 +1393,21 @@ export class OmpTimelineProjector {
|
|
|
1463
1393
|
command,
|
|
1464
1394
|
...(firstString(details, "cwd") ? { cwd: firstString(details, "cwd") } : {}),
|
|
1465
1395
|
...(output ? { output: this.dataFilter.text(output, MAX_STREAM_TEXT_LENGTH) } : {}),
|
|
1466
|
-
...(typeof exitCode === "number" || exitCode === null
|
|
1467
|
-
? { exitCode }
|
|
1396
|
+
...(typeof message.exitCode === "number" || message.exitCode === null
|
|
1397
|
+
? { exitCode: message.exitCode }
|
|
1468
1398
|
: typeof details?.exitCode === "number"
|
|
1469
1399
|
? { exitCode: details.exitCode }
|
|
1470
1400
|
: {}),
|
|
1471
1401
|
},
|
|
1472
|
-
...(cancelled !== undefined || truncated !== undefined
|
|
1402
|
+
...(message.cancelled !== undefined || message.truncated !== undefined
|
|
1473
1403
|
? {
|
|
1474
1404
|
metadata: {
|
|
1475
|
-
...(cancelled !== undefined ? { cancelled } : {}),
|
|
1476
|
-
...(truncated !== undefined ? { truncated } : {}),
|
|
1405
|
+
...(message.cancelled !== undefined ? { cancelled: message.cancelled } : {}),
|
|
1406
|
+
...(message.truncated !== undefined ? { truncated: message.truncated } : {}),
|
|
1477
1407
|
},
|
|
1478
1408
|
}
|
|
1479
1409
|
: {}),
|
|
1480
|
-
status: cancelled ? "canceled" : "completed",
|
|
1410
|
+
status: message.cancelled ? "canceled" : "completed",
|
|
1481
1411
|
error: null,
|
|
1482
1412
|
});
|
|
1483
1413
|
if (imageResult) this.publishImages(id, publicType, imageResult.image);
|