@omercnet/paseo-omp 0.4.0 → 1.0.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 +8 -8
- package/client/external-url.ts +2 -11
- package/client/omp-config-styles.ts +284 -0
- package/client/omp-config-surface.tsx +16 -286
- package/client/omp-routing-editor.tsx +1 -3
- package/client/provider-launch-settings.tsx +118 -0
- package/index.client.tsx +21 -2
- package/index.server.ts +10 -0
- package/package.json +14 -9
- package/paseo-plugin.json +2 -1
- package/scripts/prepare-dependencies.mjs +44 -11
- package/server/omp-models.ts +2 -6
- package/server/package-version.ts +1 -1
- package/server/protocol-violation-diagnostics.ts +1 -1
- package/server/provider/catalog.ts +2 -1
- package/server/provider/config-normalization.ts +19 -3
- package/server/provider/connection.ts +30 -0
- package/server/provider/host-tools.ts +2 -2
- package/server/provider/mcp-transport.ts +9 -2
- package/server/provider/omp-rpc-environment.ts +368 -0
- package/server/provider/omp-rpc-process.ts +119 -0
- package/server/provider/omp-rpc-protocol.ts +1949 -0
- package/server/provider/omp-rpc-transport.ts +1373 -0
- package/server/provider/omp-rpc-values.ts +31 -0
- package/server/provider/omp-rpc.ts +267 -3311
- package/server/provider/profile-providers.ts +2 -1
- package/server/provider/prompt-payload.ts +253 -0
- package/server/provider/registration.ts +10 -2
- package/server/provider/session-compaction.ts +187 -0
- package/server/provider/session-descriptors.ts +52 -18
- package/server/provider/session-events.ts +42 -0
- package/server/provider/session-permissions.ts +987 -0
- package/server/provider/session-terminal.ts +307 -0
- package/server/provider/session-usage.ts +234 -0
- package/server/provider/session.ts +145 -1853
- package/server/provider/settings.ts +8 -5
- package/server/provider/subsessions.ts +30 -9
- package/server/provider/timeline-projector.ts +140 -29
- package/shared/external-url.ts +0 -9
- package/shared/provider-launch-settings.ts +18 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
environmentNameSchema,
|
|
4
|
+
MAX_INHERITED_ENVIRONMENT_NAMES,
|
|
5
|
+
} from "../../shared/provider-launch-settings";
|
|
2
6
|
|
|
3
7
|
const MAX_COMMAND_PARTS = 64;
|
|
4
|
-
const MAX_ENV_ENTRIES = 256;
|
|
5
|
-
const MAX_TEXT_BYTES = 64 * 1024;
|
|
6
|
-
const MAX_MODEL_SELECTOR_BYTES = 513;
|
|
7
8
|
const MAX_PATH_BYTES = 4_096;
|
|
8
9
|
const MAX_RPC_TIMEOUT_MS = 10 * 60 * 1_000;
|
|
10
|
+
const MAX_TEXT_BYTES = 64 * 1024;
|
|
11
|
+
const MAX_MODEL_SELECTOR_BYTES = 513;
|
|
9
12
|
|
|
10
13
|
function boundedString(maxBytes: number) {
|
|
11
14
|
return z
|
|
@@ -18,7 +21,7 @@ const CommandPartSchema = boundedString(MAX_PATH_BYTES).refine(
|
|
|
18
21
|
(value) => !value.includes("\0") && !/[\r\n]/u.test(value),
|
|
19
22
|
"command arguments cannot contain NUL or line breaks",
|
|
20
23
|
);
|
|
21
|
-
const EnvironmentNameSchema =
|
|
24
|
+
const EnvironmentNameSchema = environmentNameSchema;
|
|
22
25
|
const EnvironmentValueSchema = z
|
|
23
26
|
.string()
|
|
24
27
|
.refine((value) => Buffer.byteLength(value, "utf8") <= MAX_TEXT_BYTES && !value.includes("\0"));
|
|
@@ -63,7 +66,7 @@ export const OmpProviderOptionsSchema = z
|
|
|
63
66
|
.optional(),
|
|
64
67
|
inheritEnv: z
|
|
65
68
|
.array(EnvironmentNameSchema)
|
|
66
|
-
.max(
|
|
69
|
+
.max(MAX_INHERITED_ENVIRONMENT_NAMES)
|
|
67
70
|
.describe("Daemon environment variable names copied at OMP spawn time")
|
|
68
71
|
.optional(),
|
|
69
72
|
outputRedaction: OmpOutputRedactionSchema.describe(
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { basename, extname } from "node:path";
|
|
2
|
+
import { basename, extname, isAbsolute } from "node:path";
|
|
3
3
|
import type { ProviderEvent } from "@getpaseo/plugin/server/provider";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
+
import type { OmpRuntime, OmpRuntimeSession } from "./omp-rpc";
|
|
5
6
|
import type {
|
|
6
7
|
OmpAgentSessionEvent,
|
|
7
8
|
OmpMessage,
|
|
8
|
-
OmpRuntime,
|
|
9
|
-
OmpRuntimeSession,
|
|
10
9
|
OmpSubagentEvent,
|
|
11
10
|
OmpSubagentSnapshot,
|
|
12
|
-
} from "./omp-rpc";
|
|
11
|
+
} from "./omp-rpc-protocol";
|
|
13
12
|
import {
|
|
14
13
|
BoundedStringSet,
|
|
15
14
|
boundedJsonBytes,
|
|
@@ -882,10 +881,32 @@ export class OmpSubsessionProjector {
|
|
|
882
881
|
signal.throwIfAborted();
|
|
883
882
|
if (this.sessionIdByNativeId.has(snapshot.id)) continue;
|
|
884
883
|
try {
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
884
|
+
let history: ReplayHistory;
|
|
885
|
+
if (snapshot.sessionFile && isAbsolute(snapshot.sessionFile) && this.rootSessionFile) {
|
|
886
|
+
try {
|
|
887
|
+
history = await waitForReplay(
|
|
888
|
+
runtime.readPersistedSubagentTranscript({
|
|
889
|
+
parentSessionFile: this.rootSessionFile,
|
|
890
|
+
childTranscriptId: snapshot.id,
|
|
891
|
+
sessionFile: snapshot.sessionFile,
|
|
892
|
+
cwd: this.cwd,
|
|
893
|
+
signal,
|
|
894
|
+
}),
|
|
895
|
+
signal,
|
|
896
|
+
);
|
|
897
|
+
} catch (error) {
|
|
898
|
+
if (signal.aborted) throw error;
|
|
899
|
+
history = await waitForReplay(
|
|
900
|
+
runtimeSession.getSubagentMessages({ subagentId: snapshot.id }),
|
|
901
|
+
signal,
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
} else {
|
|
905
|
+
history = await waitForReplay(
|
|
906
|
+
runtimeSession.getSubagentMessages({ subagentId: snapshot.id }),
|
|
907
|
+
signal,
|
|
908
|
+
);
|
|
909
|
+
}
|
|
889
910
|
try {
|
|
890
911
|
this.accountReplay(history.messages, budget, signal);
|
|
891
912
|
collected.push({
|
|
@@ -899,7 +920,7 @@ export class OmpSubsessionProjector {
|
|
|
899
920
|
}
|
|
900
921
|
} catch (error) {
|
|
901
922
|
if (signal.aborted) throw error;
|
|
902
|
-
collected.push({ snapshot });
|
|
923
|
+
collected.push({ snapshot, sessionFile: snapshot.sessionFile });
|
|
903
924
|
}
|
|
904
925
|
}
|
|
905
926
|
collected.sort((left, right) => {
|
|
@@ -6,7 +6,12 @@ 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 {
|
|
9
|
+
import {
|
|
10
|
+
OMP_MAX_CONTENT_PARTS,
|
|
11
|
+
OMP_MESSAGE_REPLAY_POLICIES,
|
|
12
|
+
type OmpMessage,
|
|
13
|
+
type OmpRpcEvent,
|
|
14
|
+
} from "./omp-rpc-protocol";
|
|
10
15
|
import {
|
|
11
16
|
boundedJsonBytes,
|
|
12
17
|
type JsonValue,
|
|
@@ -75,6 +80,10 @@ type ToolSnapshot = {
|
|
|
75
80
|
specializedRendered: boolean;
|
|
76
81
|
silent: boolean;
|
|
77
82
|
};
|
|
83
|
+
type PendingToolStream = {
|
|
84
|
+
output: JsonValue;
|
|
85
|
+
retainedBytes: number;
|
|
86
|
+
};
|
|
78
87
|
|
|
79
88
|
export interface OmpTimelineScheduler {
|
|
80
89
|
set(callback: () => void | Promise<void>, delayMs: number): unknown;
|
|
@@ -134,6 +143,10 @@ function imageBlock(data: string, mimeType: string): StreamBlockSnapshot | undef
|
|
|
134
143
|
}
|
|
135
144
|
|
|
136
145
|
type OmpAssistantMessage = Extract<OmpMessage, { role: "assistant" }>;
|
|
146
|
+
type OmpCustomDisplayMessage = Extract<
|
|
147
|
+
OmpMessage,
|
|
148
|
+
{ role: "bashExecution" | "pythonExecution" | "custom" | "hookMessage" }
|
|
149
|
+
>;
|
|
137
150
|
|
|
138
151
|
function blockText(
|
|
139
152
|
message: OmpAssistantMessage,
|
|
@@ -345,6 +358,8 @@ type CompactionSlot = {
|
|
|
345
358
|
|
|
346
359
|
export class OmpTimelineProjector {
|
|
347
360
|
private readonly tools = new Map<string, ToolSnapshot>();
|
|
361
|
+
private readonly pendingToolStreams = new Map<string, PendingToolStream>();
|
|
362
|
+
private pendingToolStreamBytes = 0;
|
|
348
363
|
private stream: StreamSnapshot | null = null;
|
|
349
364
|
private flushTimer: unknown;
|
|
350
365
|
private currentTurnId: string | null = null;
|
|
@@ -417,16 +432,35 @@ export class OmpTimelineProjector {
|
|
|
417
432
|
return;
|
|
418
433
|
}
|
|
419
434
|
}
|
|
435
|
+
if (
|
|
436
|
+
(event.type === "message_start" ||
|
|
437
|
+
event.type === "message_update" ||
|
|
438
|
+
event.type === "message_end") &&
|
|
439
|
+
OMP_MESSAGE_REPLAY_POLICIES[event.message.role] === "ignore"
|
|
440
|
+
) {
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
420
443
|
if (
|
|
421
444
|
event.type === "todo_reminder" ||
|
|
422
445
|
event.type === "todo_auto_clear" ||
|
|
446
|
+
event.type === "goal_updated" ||
|
|
447
|
+
event.type === "auto_retry_start" ||
|
|
448
|
+
event.type === "auto_retry_end" ||
|
|
449
|
+
event.type === "retry_fallback_applied" ||
|
|
450
|
+
event.type === "retry_fallback_succeeded" ||
|
|
423
451
|
event.type === "notice" ||
|
|
424
452
|
event.type === "extension_ui_request" ||
|
|
425
453
|
event.type === "auto_compaction_start" ||
|
|
426
454
|
event.type === "auto_compaction_end" ||
|
|
427
455
|
event.type === "compaction_start" ||
|
|
428
456
|
event.type === "compaction_end" ||
|
|
429
|
-
event.type === "advisor_yielded"
|
|
457
|
+
event.type === "advisor_yielded" ||
|
|
458
|
+
event.type === "config_warnings_changed" ||
|
|
459
|
+
event.type === "advisor_cost_changed" ||
|
|
460
|
+
event.type === "ttsr_triggered" ||
|
|
461
|
+
event.type === "irc_message" ||
|
|
462
|
+
event.type === "model_changed" ||
|
|
463
|
+
event.type === "thinking_level_changed"
|
|
430
464
|
) {
|
|
431
465
|
this.projectPassive(event);
|
|
432
466
|
return;
|
|
@@ -449,7 +483,12 @@ export class OmpTimelineProjector {
|
|
|
449
483
|
this.scheduleFlush();
|
|
450
484
|
return;
|
|
451
485
|
case "message_end":
|
|
452
|
-
if (
|
|
486
|
+
if (
|
|
487
|
+
event.message.role === "custom" ||
|
|
488
|
+
event.message.role === "hookMessage" ||
|
|
489
|
+
event.message.role === "bashExecution" ||
|
|
490
|
+
event.message.role === "pythonExecution"
|
|
491
|
+
) {
|
|
453
492
|
this.publishCustomMessage(event.message);
|
|
454
493
|
return;
|
|
455
494
|
}
|
|
@@ -460,6 +499,11 @@ export class OmpTimelineProjector {
|
|
|
460
499
|
return;
|
|
461
500
|
case "tool_execution_start": {
|
|
462
501
|
this.flush(true);
|
|
502
|
+
const pendingStream = this.pendingToolStreams.get(event.toolCallId);
|
|
503
|
+
if (pendingStream) {
|
|
504
|
+
this.pendingToolStreams.delete(event.toolCallId);
|
|
505
|
+
this.pendingToolStreamBytes -= pendingStream.retainedBytes;
|
|
506
|
+
}
|
|
463
507
|
if (this.toolIdentitySaturated || this.retiredToolCallIds.has(event.toolCallId)) return;
|
|
464
508
|
const previous = this.tools.get(event.toolCallId);
|
|
465
509
|
if (!previous && this.tools.size >= MAX_ACTIVE_TOOLS) return;
|
|
@@ -468,7 +512,17 @@ export class OmpTimelineProjector {
|
|
|
468
512
|
MAX_PUBLIC_TOOL_PAYLOAD_BYTES,
|
|
469
513
|
MAX_PUBLIC_TOOL_PAYLOAD_BYTES,
|
|
470
514
|
);
|
|
471
|
-
const
|
|
515
|
+
const inputBytes = boundedJsonBytes(input, MAX_PUBLIC_TOOL_PAYLOAD_BYTES);
|
|
516
|
+
let output = pendingStream?.output ?? null;
|
|
517
|
+
let retainedBytes = inputBytes + (pendingStream?.retainedBytes ?? 0);
|
|
518
|
+
if (
|
|
519
|
+
pendingStream &&
|
|
520
|
+
this.activeToolBytes - (previous?.retainedBytes ?? 0) + retainedBytes >
|
|
521
|
+
MAX_ACTIVE_TOOL_BYTES
|
|
522
|
+
) {
|
|
523
|
+
output = null;
|
|
524
|
+
retainedBytes = inputBytes;
|
|
525
|
+
}
|
|
472
526
|
if (
|
|
473
527
|
this.activeToolBytes - (previous?.retainedBytes ?? 0) + retainedBytes >
|
|
474
528
|
MAX_ACTIVE_TOOL_BYTES
|
|
@@ -487,7 +541,7 @@ export class OmpTimelineProjector {
|
|
|
487
541
|
nativeName: event.toolName,
|
|
488
542
|
name: this.dataFilter.text(displayName, 256),
|
|
489
543
|
input,
|
|
490
|
-
output
|
|
544
|
+
output,
|
|
491
545
|
retainedBytes,
|
|
492
546
|
turnId,
|
|
493
547
|
generation: this.runtimeGeneration,
|
|
@@ -499,16 +553,30 @@ export class OmpTimelineProjector {
|
|
|
499
553
|
if (!snapshot.silent) this.publishTool(snapshot, "running");
|
|
500
554
|
return;
|
|
501
555
|
}
|
|
502
|
-
case "tool_execution_update":
|
|
503
|
-
|
|
504
|
-
if (!previous) return;
|
|
505
|
-
if (previous.turnId !== turnId || previous.generation !== this.runtimeGeneration) return;
|
|
556
|
+
case "tool_execution_update":
|
|
557
|
+
case "tool_stream_update": {
|
|
506
558
|
const output = this.dataFilter.json(
|
|
507
|
-
event.partialResult,
|
|
559
|
+
event.type === "tool_execution_update" ? event.partialResult : event.update,
|
|
508
560
|
MAX_PUBLIC_TOOL_PAYLOAD_BYTES,
|
|
509
561
|
MAX_PUBLIC_TOOL_PAYLOAD_BYTES,
|
|
510
562
|
);
|
|
511
563
|
const outputBytes = boundedJsonBytes(output, MAX_PUBLIC_TOOL_PAYLOAD_BYTES);
|
|
564
|
+
const previous = this.tools.get(event.toolCallId);
|
|
565
|
+
if (!previous) {
|
|
566
|
+
if (event.type !== "tool_stream_update") return;
|
|
567
|
+
const pending = this.pendingToolStreams.get(event.toolCallId);
|
|
568
|
+
if (!pending && this.pendingToolStreams.size >= MAX_ACTIVE_TOOLS) return;
|
|
569
|
+
if (
|
|
570
|
+
this.pendingToolStreamBytes - (pending?.retainedBytes ?? 0) + outputBytes >
|
|
571
|
+
MAX_ACTIVE_TOOL_BYTES
|
|
572
|
+
) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
this.pendingToolStreamBytes += outputBytes - (pending?.retainedBytes ?? 0);
|
|
576
|
+
this.pendingToolStreams.set(event.toolCallId, { output, retainedBytes: outputBytes });
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (previous.turnId !== turnId || previous.generation !== this.runtimeGeneration) return;
|
|
512
580
|
const inputBytes = boundedJsonBytes(previous.input, MAX_PUBLIC_TOOL_PAYLOAD_BYTES);
|
|
513
581
|
const retainedBytes = inputBytes + outputBytes;
|
|
514
582
|
if (this.activeToolBytes - previous.retainedBytes + retainedBytes > MAX_ACTIVE_TOOL_BYTES)
|
|
@@ -600,6 +668,10 @@ export class OmpTimelineProjector {
|
|
|
600
668
|
this.publishRetryFallback(event);
|
|
601
669
|
return;
|
|
602
670
|
}
|
|
671
|
+
if (event.type === "irc_message") {
|
|
672
|
+
this.publishCustomMessage(event.message as OmpCustomDisplayMessage);
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
603
675
|
if (event.type === "notice") {
|
|
604
676
|
this.noticeSequence += 1;
|
|
605
677
|
this.publish({
|
|
@@ -831,6 +903,7 @@ export class OmpTimelineProjector {
|
|
|
831
903
|
this.activeToolBytes = 0;
|
|
832
904
|
this.replayToolCalls.clear();
|
|
833
905
|
this.tools.clear();
|
|
906
|
+
this.clearPendingToolStreams();
|
|
834
907
|
this.commandText = "";
|
|
835
908
|
this.commandPublishedText = "";
|
|
836
909
|
this.revertEntryByToken.clear();
|
|
@@ -839,8 +912,9 @@ export class OmpTimelineProjector {
|
|
|
839
912
|
|
|
840
913
|
projectReplayMessage(message: OmpMessage): void {
|
|
841
914
|
if (this.closed) return;
|
|
842
|
-
const nativeIdentity = assistantIdentity(message);
|
|
843
915
|
this.replaySequence += 1;
|
|
916
|
+
if (OMP_MESSAGE_REPLAY_POLICIES[message.role] === "ignore") return;
|
|
917
|
+
|
|
844
918
|
if (message.role === "user") {
|
|
845
919
|
this.replayToolCalls.clear();
|
|
846
920
|
if (this.replayTurnId) this.finishTurn(this.replayTurnId);
|
|
@@ -861,7 +935,9 @@ export class OmpTimelineProjector {
|
|
|
861
935
|
}
|
|
862
936
|
return;
|
|
863
937
|
}
|
|
938
|
+
|
|
864
939
|
if (message.role === "assistant") {
|
|
940
|
+
const nativeIdentity = assistantIdentity(message);
|
|
865
941
|
this.replayTurnId ??= `omp:replay-turn:${this.replaySequence}`;
|
|
866
942
|
this.projectingReplay = true;
|
|
867
943
|
try {
|
|
@@ -880,6 +956,7 @@ export class OmpTimelineProjector {
|
|
|
880
956
|
if (nativeIdentity) this.rememberReplayOccurrence(nativeIdentity, message);
|
|
881
957
|
return;
|
|
882
958
|
}
|
|
959
|
+
|
|
883
960
|
this.replayTurnId ??= `omp:replay-turn:${this.replaySequence}`;
|
|
884
961
|
if (message.role === "toolResult") {
|
|
885
962
|
const replayCall = this.replayToolCalls.get(message.toolCallId);
|
|
@@ -910,10 +987,18 @@ export class OmpTimelineProjector {
|
|
|
910
987
|
);
|
|
911
988
|
return;
|
|
912
989
|
}
|
|
913
|
-
|
|
990
|
+
|
|
991
|
+
if (
|
|
992
|
+
message.role === "bashExecution" ||
|
|
993
|
+
message.role === "pythonExecution" ||
|
|
994
|
+
message.role === "custom" ||
|
|
995
|
+
message.role === "hookMessage"
|
|
996
|
+
) {
|
|
914
997
|
this.publishCustomMessage(message);
|
|
915
|
-
|
|
916
|
-
|
|
998
|
+
if (message.role === "bashExecution" || message.role === "pythonExecution") {
|
|
999
|
+
this.finishTurn(this.replayTurnId);
|
|
1000
|
+
this.replayTurnId = null;
|
|
1001
|
+
}
|
|
917
1002
|
}
|
|
918
1003
|
}
|
|
919
1004
|
|
|
@@ -1086,6 +1171,7 @@ export class OmpTimelineProjector {
|
|
|
1086
1171
|
this.clearFlushTimer();
|
|
1087
1172
|
this.stream = null;
|
|
1088
1173
|
this.tools.clear();
|
|
1174
|
+
this.clearPendingToolStreams();
|
|
1089
1175
|
this.replayToolCalls.clear();
|
|
1090
1176
|
this.activeToolBytes = 0;
|
|
1091
1177
|
this.replayCandidates.clear();
|
|
@@ -1126,6 +1212,11 @@ export class OmpTimelineProjector {
|
|
|
1126
1212
|
}
|
|
1127
1213
|
this.activeToolBytes = 0;
|
|
1128
1214
|
this.tools.clear();
|
|
1215
|
+
this.clearPendingToolStreams();
|
|
1216
|
+
}
|
|
1217
|
+
private clearPendingToolStreams(): void {
|
|
1218
|
+
this.pendingToolStreams.clear();
|
|
1219
|
+
this.pendingToolStreamBytes = 0;
|
|
1129
1220
|
}
|
|
1130
1221
|
private ensureTurn(turnId: string): void {
|
|
1131
1222
|
if (this.currentTurnId === turnId) return;
|
|
@@ -1350,9 +1441,17 @@ export class OmpTimelineProjector {
|
|
|
1350
1441
|
return undefined;
|
|
1351
1442
|
}
|
|
1352
1443
|
|
|
1353
|
-
private publishCustomMessage(message:
|
|
1354
|
-
if (
|
|
1355
|
-
|
|
1444
|
+
private publishCustomMessage(message: OmpCustomDisplayMessage): void {
|
|
1445
|
+
if (
|
|
1446
|
+
(message.role === "custom" || message.role === "hookMessage") &&
|
|
1447
|
+
message.display === false
|
|
1448
|
+
) {
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
const rawType =
|
|
1452
|
+
message.role === "custom" || message.role === "hookMessage"
|
|
1453
|
+
? (message.customType ?? message.role)
|
|
1454
|
+
: message.role;
|
|
1356
1455
|
const publicType = this.dataFilter.text(rawType, 256);
|
|
1357
1456
|
const lowerType = rawType.toLowerCase();
|
|
1358
1457
|
const details = jsonRecord(this.dataFilter.json(message.details ?? null));
|
|
@@ -1361,7 +1460,9 @@ export class OmpTimelineProjector {
|
|
|
1361
1460
|
const id = nativeIdentity
|
|
1362
1461
|
? `omp:custom:${createHash("sha256").update(nativeIdentity).digest("base64url").slice(0, 12)}`
|
|
1363
1462
|
: `omp:custom:${this.customSequence}`;
|
|
1364
|
-
const
|
|
1463
|
+
const messageContent =
|
|
1464
|
+
message.role === "custom" || message.role === "hookMessage" ? message.content : undefined;
|
|
1465
|
+
const contentParts = Array.isArray(messageContent) ? messageContent : [];
|
|
1365
1466
|
const imageResult = nativeImageResult(
|
|
1366
1467
|
{
|
|
1367
1468
|
content:
|
|
@@ -1373,16 +1474,26 @@ export class OmpTimelineProjector {
|
|
|
1373
1474
|
this.dataFilter,
|
|
1374
1475
|
);
|
|
1375
1476
|
const content =
|
|
1376
|
-
typeof
|
|
1377
|
-
?
|
|
1477
|
+
typeof messageContent === "string"
|
|
1478
|
+
? messageContent
|
|
1378
1479
|
: contentParts
|
|
1379
1480
|
.flatMap((part) => (part.type === "text" && part.text ? [part.text] : []))
|
|
1380
1481
|
.join("\n\n");
|
|
1381
|
-
|
|
1482
|
+
const execution = message.role === "bashExecution" || message.role === "pythonExecution";
|
|
1483
|
+
if (execution || /bash|shell|python/u.test(lowerType)) {
|
|
1484
|
+
const nativeCommand =
|
|
1485
|
+
message.role === "bashExecution"
|
|
1486
|
+
? message.command
|
|
1487
|
+
: message.role === "pythonExecution"
|
|
1488
|
+
? message.code
|
|
1489
|
+
: undefined;
|
|
1382
1490
|
const command = this.dataFilter.text(
|
|
1383
|
-
|
|
1491
|
+
nativeCommand ?? firstString(details, "command", "input") ?? publicType,
|
|
1384
1492
|
);
|
|
1385
|
-
const output = message.output ?? content;
|
|
1493
|
+
const output = execution ? (message.output ?? content) : content;
|
|
1494
|
+
const exitCode = execution ? message.exitCode : undefined;
|
|
1495
|
+
const cancelled = execution ? message.cancelled : undefined;
|
|
1496
|
+
const truncated = execution ? message.truncated : undefined;
|
|
1386
1497
|
this.publish({
|
|
1387
1498
|
type: "tool_call",
|
|
1388
1499
|
id,
|
|
@@ -1393,21 +1504,21 @@ export class OmpTimelineProjector {
|
|
|
1393
1504
|
command,
|
|
1394
1505
|
...(firstString(details, "cwd") ? { cwd: firstString(details, "cwd") } : {}),
|
|
1395
1506
|
...(output ? { output: this.dataFilter.text(output, MAX_STREAM_TEXT_LENGTH) } : {}),
|
|
1396
|
-
...(typeof
|
|
1397
|
-
? { exitCode
|
|
1507
|
+
...(typeof exitCode === "number" || exitCode === null
|
|
1508
|
+
? { exitCode }
|
|
1398
1509
|
: typeof details?.exitCode === "number"
|
|
1399
1510
|
? { exitCode: details.exitCode }
|
|
1400
1511
|
: {}),
|
|
1401
1512
|
},
|
|
1402
|
-
...(
|
|
1513
|
+
...(cancelled !== undefined || truncated !== undefined
|
|
1403
1514
|
? {
|
|
1404
1515
|
metadata: {
|
|
1405
|
-
...(
|
|
1406
|
-
...(
|
|
1516
|
+
...(cancelled !== undefined ? { cancelled } : {}),
|
|
1517
|
+
...(truncated !== undefined ? { truncated } : {}),
|
|
1407
1518
|
},
|
|
1408
1519
|
}
|
|
1409
1520
|
: {}),
|
|
1410
|
-
status:
|
|
1521
|
+
status: cancelled ? "canceled" : "completed",
|
|
1411
1522
|
error: null,
|
|
1412
1523
|
});
|
|
1413
1524
|
if (imageResult) this.publishImages(id, publicType, imageResult.image);
|
package/shared/external-url.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
export type ExternalUrlOpener = (url: string) => Promise<void>;
|
|
2
|
-
|
|
3
|
-
export function selectExternalUrlOpener(
|
|
4
|
-
paseoOpener: ExternalUrlOpener | undefined,
|
|
5
|
-
fallback: ExternalUrlOpener,
|
|
6
|
-
): ExternalUrlOpener {
|
|
7
|
-
return paseoOpener ?? fallback;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
1
|
export function validatedHttpUrl(value: string): string {
|
|
11
2
|
let url: URL;
|
|
12
3
|
try {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineSettings } from "@getpaseo/plugin";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
export const MAX_INHERITED_ENVIRONMENT_NAMES = 256;
|
|
5
|
+
export const environmentNameSchema = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/u);
|
|
6
|
+
|
|
7
|
+
export const providerLaunchSettingsSchema = z.object({
|
|
8
|
+
inheritEnv: z.array(environmentNameSchema).max(MAX_INHERITED_ENVIRONMENT_NAMES).default([]),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export type ProviderLaunchSettings = z.infer<typeof providerLaunchSettingsSchema>;
|
|
12
|
+
|
|
13
|
+
export const providerLaunchSettings = defineSettings({
|
|
14
|
+
id: "provider-launch",
|
|
15
|
+
scope: "host",
|
|
16
|
+
version: 1,
|
|
17
|
+
schema: providerLaunchSettingsSchema,
|
|
18
|
+
});
|