@moxt-ai/mobius 0.0.27 → 0.0.28
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/acp/activity.d.ts +1 -0
- package/dist/acp/activity.d.ts.map +1 -1
- package/dist/acp/activity.js +14 -1
- package/dist/acp/activity.js.map +1 -1
- package/dist/acp/session-history.d.ts.map +1 -1
- package/dist/acp/session-history.js +10 -16
- package/dist/acp/session-history.js.map +1 -1
- package/dist/acp/session-manager.d.ts +7 -0
- package/dist/acp/session-manager.d.ts.map +1 -1
- package/dist/acp/session-manager.js +65 -11
- package/dist/acp/session-manager.js.map +1 -1
- package/dist/artifacts/runtime-artifact-uploader.d.ts +12 -0
- package/dist/artifacts/runtime-artifact-uploader.d.ts.map +1 -0
- package/dist/artifacts/runtime-artifact-uploader.js +157 -0
- package/dist/artifacts/runtime-artifact-uploader.js.map +1 -0
- package/dist/authorization/local-raster.d.ts +10 -0
- package/dist/authorization/local-raster.d.ts.map +1 -0
- package/dist/authorization/local-raster.js +134 -0
- package/dist/authorization/local-raster.js.map +1 -0
- package/dist/cli.js +826 -113
- package/dist/cli.js.map +4 -4
- package/dist/index.js +849 -137
- package/dist/index.js.map +4 -4
- package/dist/native-sessions/codex-history.d.ts.map +1 -1
- package/dist/native-sessions/codex-history.js +11 -11
- package/dist/native-sessions/codex-history.js.map +1 -1
- package/dist/native-sessions/history-images.d.ts +3 -0
- package/dist/native-sessions/history-images.d.ts.map +1 -0
- package/dist/native-sessions/history-images.js +74 -0
- package/dist/native-sessions/history-images.js.map +1 -0
- package/dist/run-daemon.d.ts.map +1 -1
- package/dist/run-daemon.js +30 -7
- package/dist/run-daemon.js.map +1 -1
- package/dist/runtime.js +845 -133
- package/dist/runtime.js.map +4 -4
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { mkdir as mkdir5 } from "node:fs/promises";
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@moxt-ai/mobius",
|
|
14
|
-
version: "0.0.
|
|
14
|
+
version: "0.0.28",
|
|
15
15
|
description: "Mobius CLI for pairing and running local AI agent services.",
|
|
16
16
|
type: "module",
|
|
17
17
|
bin: {
|
|
@@ -55,6 +55,7 @@ var package_default = {
|
|
|
55
55
|
},
|
|
56
56
|
devDependencies: {
|
|
57
57
|
"@moxt-ai/mobius-protocol": "workspace:*",
|
|
58
|
+
"@moxt-ai/mobius-sdk": "workspace:*",
|
|
58
59
|
"@types/node": "^24.13.3",
|
|
59
60
|
esbuild: "0.28.2"
|
|
60
61
|
},
|
|
@@ -18841,8 +18842,8 @@ function rewriteKeyNames(ctx) {
|
|
|
18841
18842
|
bySchema.set(entry.schema, entry);
|
|
18842
18843
|
}
|
|
18843
18844
|
const rewrites = /* @__PURE__ */ new Map();
|
|
18844
|
-
for (const
|
|
18845
|
-
const seen = ctx.seen.get(
|
|
18845
|
+
for (const record3 of pendingRecords.get(ctx) ?? []) {
|
|
18846
|
+
const seen = ctx.seen.get(record3);
|
|
18846
18847
|
const names = (seen?.def ?? seen?.schema)?.propertyNames;
|
|
18847
18848
|
if (!names || names === true || rewrites.has(names))
|
|
18848
18849
|
continue;
|
|
@@ -21799,6 +21800,7 @@ var elicitationFieldSchema = external_exports.strictObject({
|
|
|
21799
21800
|
type: external_exports.enum(["boolean", "integer", "multiselect", "number", "select", "string"])
|
|
21800
21801
|
}).readonly();
|
|
21801
21802
|
var displayContentSchema = external_exports.strictObject({
|
|
21803
|
+
artifactId: external_exports.string().max(128).default(""),
|
|
21802
21804
|
data: external_exports.string().max(4e6),
|
|
21803
21805
|
mimeType: external_exports.string().max(255),
|
|
21804
21806
|
name: external_exports.string().max(500),
|
|
@@ -21811,6 +21813,7 @@ var displayContentSchema = external_exports.strictObject({
|
|
|
21811
21813
|
uri: external_exports.string().max(4096)
|
|
21812
21814
|
}).readonly();
|
|
21813
21815
|
var recordedDisplayContentSchema = external_exports.strictObject({
|
|
21816
|
+
artifactId: external_exports.string().max(128).default(""),
|
|
21814
21817
|
data: external_exports.string().max(4e6),
|
|
21815
21818
|
mimeType: external_exports.string().max(255),
|
|
21816
21819
|
name: external_exports.string().max(500),
|
|
@@ -23681,7 +23684,7 @@ var AuditStore = class {
|
|
|
23681
23684
|
this.database.exec("ALTER TABLE audit_events ADD COLUMN details_json TEXT NOT NULL DEFAULT '{}'");
|
|
23682
23685
|
}
|
|
23683
23686
|
}
|
|
23684
|
-
record(
|
|
23687
|
+
record(record3) {
|
|
23685
23688
|
this.database.prepare(
|
|
23686
23689
|
`
|
|
23687
23690
|
INSERT INTO audit_events (
|
|
@@ -23694,10 +23697,10 @@ var AuditStore = class {
|
|
|
23694
23697
|
`
|
|
23695
23698
|
).run(
|
|
23696
23699
|
(/* @__PURE__ */ new Date()).toISOString(),
|
|
23697
|
-
|
|
23698
|
-
|
|
23699
|
-
|
|
23700
|
-
JSON.stringify(
|
|
23700
|
+
record3.event,
|
|
23701
|
+
record3.commandId,
|
|
23702
|
+
record3.sessionId,
|
|
23703
|
+
JSON.stringify(record3.details ?? {})
|
|
23701
23704
|
);
|
|
23702
23705
|
}
|
|
23703
23706
|
close() {
|
|
@@ -23707,9 +23710,9 @@ var AuditStore = class {
|
|
|
23707
23710
|
|
|
23708
23711
|
// src/run-daemon.ts
|
|
23709
23712
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
23710
|
-
import { basename as
|
|
23713
|
+
import { basename as basename5, join as join16 } from "node:path";
|
|
23711
23714
|
import { styleText } from "node:util";
|
|
23712
|
-
import { fetch as
|
|
23715
|
+
import { fetch as fetch7, WebSocket as WebSocket2 } from "undici";
|
|
23713
23716
|
|
|
23714
23717
|
// src/acp/session-manager.ts
|
|
23715
23718
|
import { spawn as spawn3 } from "node:child_process";
|
|
@@ -23720,6 +23723,212 @@ import {
|
|
|
23720
23723
|
RequestError as RequestError2
|
|
23721
23724
|
} from "@agentclientprotocol/sdk";
|
|
23722
23725
|
|
|
23726
|
+
// src/authorization/local-raster.ts
|
|
23727
|
+
import { readFile, realpath as realpath7, stat as stat6 } from "node:fs/promises";
|
|
23728
|
+
import { basename as basename2, isAbsolute as isAbsolute7, normalize as normalize2, relative as relative4, sep as sep4 } from "node:path";
|
|
23729
|
+
import { fileURLToPath } from "node:url";
|
|
23730
|
+
var MAX_LOCAL_RASTER_BYTES = 3e6;
|
|
23731
|
+
var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71);
|
|
23732
|
+
var JPEG_SIGNATURE = Uint8Array.of(255, 216, 255);
|
|
23733
|
+
var GIF87_SIGNATURE = new TextEncoder().encode("GIF87a");
|
|
23734
|
+
var GIF89_SIGNATURE = new TextEncoder().encode("GIF89a");
|
|
23735
|
+
var RIFF_SIGNATURE = new TextEncoder().encode("RIFF");
|
|
23736
|
+
var WEBP_SIGNATURE = new TextEncoder().encode("WEBP");
|
|
23737
|
+
var LocalRasterImage = class {
|
|
23738
|
+
bytes;
|
|
23739
|
+
mimeType;
|
|
23740
|
+
name;
|
|
23741
|
+
constructor(name, mimeType, bytes) {
|
|
23742
|
+
this.bytes = bytes;
|
|
23743
|
+
this.mimeType = mimeType;
|
|
23744
|
+
this.name = name;
|
|
23745
|
+
}
|
|
23746
|
+
base64 = () => Buffer.from(this.bytes).toString("base64");
|
|
23747
|
+
};
|
|
23748
|
+
function startsWith(bytes, signature, offset = 0) {
|
|
23749
|
+
if (bytes.byteLength < offset + signature.byteLength) {
|
|
23750
|
+
return false;
|
|
23751
|
+
}
|
|
23752
|
+
return signature.every((value, index) => bytes[offset + index] === value);
|
|
23753
|
+
}
|
|
23754
|
+
function sniffRasterMime(bytes) {
|
|
23755
|
+
if (startsWith(bytes, PNG_SIGNATURE)) {
|
|
23756
|
+
return "image/png";
|
|
23757
|
+
}
|
|
23758
|
+
if (startsWith(bytes, JPEG_SIGNATURE)) {
|
|
23759
|
+
return "image/jpeg";
|
|
23760
|
+
}
|
|
23761
|
+
if (startsWith(bytes, GIF87_SIGNATURE) || startsWith(bytes, GIF89_SIGNATURE)) {
|
|
23762
|
+
return "image/gif";
|
|
23763
|
+
}
|
|
23764
|
+
if (startsWith(bytes, RIFF_SIGNATURE) && startsWith(bytes, WEBP_SIGNATURE, 8)) {
|
|
23765
|
+
return "image/webp";
|
|
23766
|
+
}
|
|
23767
|
+
return null;
|
|
23768
|
+
}
|
|
23769
|
+
function isInsideRoot(root, target) {
|
|
23770
|
+
const relation = relative4(root, target);
|
|
23771
|
+
return relation !== ".." && !relation.startsWith(`..${sep4}`) && !isAbsolute7(relation);
|
|
23772
|
+
}
|
|
23773
|
+
async function resolveCanonicalPath(requested, signal) {
|
|
23774
|
+
signal.throwIfAborted();
|
|
23775
|
+
if (!isAbsolute7(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
|
|
23776
|
+
return null;
|
|
23777
|
+
}
|
|
23778
|
+
try {
|
|
23779
|
+
const target = await realpath7(requested);
|
|
23780
|
+
signal.throwIfAborted();
|
|
23781
|
+
if (!isAbsolute7(target) || normalize2(target) !== target) {
|
|
23782
|
+
return null;
|
|
23783
|
+
}
|
|
23784
|
+
return target;
|
|
23785
|
+
} catch (cause) {
|
|
23786
|
+
signal.throwIfAborted();
|
|
23787
|
+
if (cause instanceof Error && cause.name === "AbortError") {
|
|
23788
|
+
throw cause;
|
|
23789
|
+
}
|
|
23790
|
+
return null;
|
|
23791
|
+
}
|
|
23792
|
+
}
|
|
23793
|
+
function parseLocalImageUri(uri) {
|
|
23794
|
+
const trimmed = uri.trim();
|
|
23795
|
+
if (trimmed.length === 0 || trimmed.length > 2048 || trimmed.includes("\0")) {
|
|
23796
|
+
return null;
|
|
23797
|
+
}
|
|
23798
|
+
if (trimmed.startsWith("data:")) {
|
|
23799
|
+
return null;
|
|
23800
|
+
}
|
|
23801
|
+
if (trimmed.startsWith("file:")) {
|
|
23802
|
+
try {
|
|
23803
|
+
const url2 = new URL(trimmed);
|
|
23804
|
+
if (url2.protocol !== "file:" || url2.host.length > 0) {
|
|
23805
|
+
return null;
|
|
23806
|
+
}
|
|
23807
|
+
return fileURLToPath(url2);
|
|
23808
|
+
} catch {
|
|
23809
|
+
return null;
|
|
23810
|
+
}
|
|
23811
|
+
}
|
|
23812
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
|
|
23813
|
+
return null;
|
|
23814
|
+
}
|
|
23815
|
+
return trimmed;
|
|
23816
|
+
}
|
|
23817
|
+
async function readAuthorizedRaster(uri, roots, signal) {
|
|
23818
|
+
signal.throwIfAborted();
|
|
23819
|
+
const requested = parseLocalImageUri(uri);
|
|
23820
|
+
if (requested === null) {
|
|
23821
|
+
return null;
|
|
23822
|
+
}
|
|
23823
|
+
const target = await resolveCanonicalPath(requested, signal);
|
|
23824
|
+
if (target === null) {
|
|
23825
|
+
return null;
|
|
23826
|
+
}
|
|
23827
|
+
const targetMetadata = await stat6(target);
|
|
23828
|
+
signal.throwIfAborted();
|
|
23829
|
+
if (!targetMetadata.isFile() || targetMetadata.size < 1 || targetMetadata.size > MAX_LOCAL_RASTER_BYTES) {
|
|
23830
|
+
return null;
|
|
23831
|
+
}
|
|
23832
|
+
const authorizedRoots = [];
|
|
23833
|
+
for (const root of roots) {
|
|
23834
|
+
const directory = await resolveCanonicalPath(root, signal);
|
|
23835
|
+
if (directory === null) {
|
|
23836
|
+
continue;
|
|
23837
|
+
}
|
|
23838
|
+
const metadata = await stat6(directory);
|
|
23839
|
+
signal.throwIfAborted();
|
|
23840
|
+
if (metadata.isDirectory()) {
|
|
23841
|
+
authorizedRoots.push(directory);
|
|
23842
|
+
}
|
|
23843
|
+
}
|
|
23844
|
+
if (!authorizedRoots.some((root) => isInsideRoot(root, target))) {
|
|
23845
|
+
return null;
|
|
23846
|
+
}
|
|
23847
|
+
const bytes = new Uint8Array(await readFile(target));
|
|
23848
|
+
signal.throwIfAborted();
|
|
23849
|
+
if (bytes.byteLength < 1 || bytes.byteLength > MAX_LOCAL_RASTER_BYTES) {
|
|
23850
|
+
return null;
|
|
23851
|
+
}
|
|
23852
|
+
const mimeType = sniffRasterMime(bytes);
|
|
23853
|
+
if (mimeType === null) {
|
|
23854
|
+
return null;
|
|
23855
|
+
}
|
|
23856
|
+
return new LocalRasterImage(basename2(target) || "Image", mimeType, bytes);
|
|
23857
|
+
}
|
|
23858
|
+
|
|
23859
|
+
// src/native-sessions/history-images.ts
|
|
23860
|
+
var IMAGE_MARKER = /\[@image\]\(([^)\r\n]*)(?:\)|$)/g;
|
|
23861
|
+
async function embedLocalHistoryImages(history, roots, signal) {
|
|
23862
|
+
if (history.status !== "available") {
|
|
23863
|
+
return history;
|
|
23864
|
+
}
|
|
23865
|
+
const messages = [];
|
|
23866
|
+
let imageCharacters = 0;
|
|
23867
|
+
for (const message of history.messages) {
|
|
23868
|
+
signal.throwIfAborted();
|
|
23869
|
+
const resolved = await resolveMessageImages(message, roots, imageCharacters, signal);
|
|
23870
|
+
imageCharacters += (resolved.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
23871
|
+
messages.push(resolved);
|
|
23872
|
+
}
|
|
23873
|
+
return {
|
|
23874
|
+
...history,
|
|
23875
|
+
messages
|
|
23876
|
+
};
|
|
23877
|
+
}
|
|
23878
|
+
async function resolveMessageImages(message, roots, usedCharacters, signal) {
|
|
23879
|
+
const images = [...message.images ?? []];
|
|
23880
|
+
let imageCharacters = images.reduce((size, image) => size + image.data.length, 0);
|
|
23881
|
+
const text = await replaceImageMarkers(message.text, async (uri) => {
|
|
23882
|
+
if (images.length >= 8 || usedCharacters + imageCharacters >= SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
23883
|
+
return "[Image unavailable]";
|
|
23884
|
+
}
|
|
23885
|
+
const embedded = parseNativeHistoryText(`[@image](${uri})`).images[0];
|
|
23886
|
+
if (embedded !== void 0) {
|
|
23887
|
+
if (usedCharacters + imageCharacters + embedded.data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
23888
|
+
return "[Image unavailable]";
|
|
23889
|
+
}
|
|
23890
|
+
images.push(embedded);
|
|
23891
|
+
imageCharacters += embedded.data.length;
|
|
23892
|
+
return "";
|
|
23893
|
+
}
|
|
23894
|
+
const local = await readAuthorizedRaster(uri, roots, signal);
|
|
23895
|
+
if (local === null) {
|
|
23896
|
+
return "[Image unavailable]";
|
|
23897
|
+
}
|
|
23898
|
+
const data = local.base64();
|
|
23899
|
+
if (usedCharacters + imageCharacters + data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
23900
|
+
return "[Image unavailable]";
|
|
23901
|
+
}
|
|
23902
|
+
images.push({
|
|
23903
|
+
data,
|
|
23904
|
+
mimeType: local.mimeType,
|
|
23905
|
+
name: local.name
|
|
23906
|
+
});
|
|
23907
|
+
imageCharacters += data.length;
|
|
23908
|
+
return "";
|
|
23909
|
+
});
|
|
23910
|
+
return {
|
|
23911
|
+
...message,
|
|
23912
|
+
text,
|
|
23913
|
+
...images.length > 0 ? { images } : {}
|
|
23914
|
+
};
|
|
23915
|
+
}
|
|
23916
|
+
async function replaceImageMarkers(text, replace) {
|
|
23917
|
+
const matches = [...text.matchAll(IMAGE_MARKER)];
|
|
23918
|
+
if (matches.length === 0) {
|
|
23919
|
+
return text;
|
|
23920
|
+
}
|
|
23921
|
+
let cursor = 0;
|
|
23922
|
+
let rewritten = "";
|
|
23923
|
+
for (const match of matches) {
|
|
23924
|
+
const index = match.index ?? 0;
|
|
23925
|
+
rewritten += text.slice(cursor, index);
|
|
23926
|
+
rewritten += await replace(match[1] ?? "");
|
|
23927
|
+
cursor = index + match[0].length;
|
|
23928
|
+
}
|
|
23929
|
+
return `${rewritten}${text.slice(cursor)}`;
|
|
23930
|
+
}
|
|
23931
|
+
|
|
23723
23932
|
// src/acp/activity.ts
|
|
23724
23933
|
var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
|
|
23725
23934
|
function isRecord8(value) {
|
|
@@ -23817,6 +24026,7 @@ function readContentOutputDetail(content) {
|
|
|
23817
24026
|
function summarizeDisplayContent(content) {
|
|
23818
24027
|
return {
|
|
23819
24028
|
...content,
|
|
24029
|
+
artifactId: truncate(content.artifactId, 128),
|
|
23820
24030
|
data: truncate(content.data, AGENT_ACTIVITY_DETAIL_LIMIT),
|
|
23821
24031
|
mimeType: truncate(content.mimeType, 255),
|
|
23822
24032
|
name: truncate(content.name, 500),
|
|
@@ -23829,7 +24039,7 @@ function summarizeDisplayContent(content) {
|
|
|
23829
24039
|
};
|
|
23830
24040
|
}
|
|
23831
24041
|
function contentFitsRecordingEnvelope(content) {
|
|
23832
|
-
return content.data.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.mimeType.length <= 255 && content.name.length <= 500 && content.newText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.oldText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.path.length <= 2048 && content.terminalId.length <= 255 && content.text.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.uri.length <= 4096;
|
|
24042
|
+
return content.artifactId.length <= 128 && content.data.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.mimeType.length <= 255 && content.name.length <= 500 && content.newText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.oldText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.path.length <= 2048 && content.terminalId.length <= 255 && content.text.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.uri.length <= 4096;
|
|
23833
24043
|
}
|
|
23834
24044
|
function encodedByteLength(value) {
|
|
23835
24045
|
return new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
@@ -23855,6 +24065,7 @@ function recordedDetail(activity) {
|
|
|
23855
24065
|
}
|
|
23856
24066
|
function emptyDisplayContent(type) {
|
|
23857
24067
|
return {
|
|
24068
|
+
artifactId: "",
|
|
23858
24069
|
data: "",
|
|
23859
24070
|
mimeType: "",
|
|
23860
24071
|
name: "",
|
|
@@ -23867,6 +24078,16 @@ function emptyDisplayContent(type) {
|
|
|
23867
24078
|
uri: ""
|
|
23868
24079
|
};
|
|
23869
24080
|
}
|
|
24081
|
+
function imageDisplayContent(mimeType, name, data, artifactId = "", uri = "") {
|
|
24082
|
+
return {
|
|
24083
|
+
...emptyDisplayContent("image"),
|
|
24084
|
+
artifactId,
|
|
24085
|
+
data,
|
|
24086
|
+
mimeType,
|
|
24087
|
+
name,
|
|
24088
|
+
uri
|
|
24089
|
+
};
|
|
24090
|
+
}
|
|
23870
24091
|
function normalizeContentBlock(content) {
|
|
23871
24092
|
if (content.type === "text") {
|
|
23872
24093
|
return { ...emptyDisplayContent("text"), text: content.text };
|
|
@@ -24658,7 +24879,6 @@ var AcpHistoryReplay = class {
|
|
|
24658
24879
|
#messages = [];
|
|
24659
24880
|
#lastMessageId = null;
|
|
24660
24881
|
#characters = 0;
|
|
24661
|
-
#imageCharacters = 0;
|
|
24662
24882
|
#truncated = false;
|
|
24663
24883
|
record = (update) => {
|
|
24664
24884
|
if (update.sessionUpdate !== "user_message_chunk" && update.sessionUpdate !== "agent_message_chunk") {
|
|
@@ -24669,40 +24889,30 @@ var AcpHistoryReplay = class {
|
|
|
24669
24889
|
}
|
|
24670
24890
|
const role = update.sessionUpdate === "user_message_chunk" ? "user" : "assistant";
|
|
24671
24891
|
const content = update.content;
|
|
24672
|
-
const
|
|
24673
|
-
|
|
24674
|
-
);
|
|
24675
|
-
const text = parsed.text;
|
|
24676
|
-
if (text.length === 0 && parsed.images.length === 0) {
|
|
24892
|
+
const text = content.type === "text" ? content.text : content.type === "image" ? content.data.length > 0 ? `[@image](data:${content.mimeType};base64,${content.data})` : content.uri != null && content.uri.length > 0 ? `[@image](${content.uri})` : "[image attachment]" : `[${content.type} attachment]`;
|
|
24893
|
+
if (text.length === 0) {
|
|
24677
24894
|
return;
|
|
24678
24895
|
}
|
|
24679
24896
|
const previous = this.#messages.at(-1);
|
|
24680
24897
|
const id = update.messageId ?? null;
|
|
24681
24898
|
const continuation = previous?.role === role && id === this.#lastMessageId;
|
|
24682
24899
|
const combined = continuation ? `${previous.text}${text}` : text;
|
|
24683
|
-
const allImages = continuation ? [...previous.images ?? [], ...parsed.images] : parsed.images;
|
|
24684
|
-
const images = allImages.slice(0, 8);
|
|
24685
|
-
this.#truncated ||= images.length < allImages.length;
|
|
24686
24900
|
if (continuation) {
|
|
24687
24901
|
this.#messages.pop();
|
|
24688
24902
|
this.#characters -= previous.text.length;
|
|
24689
|
-
this.#imageCharacters -= (previous.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
24690
24903
|
}
|
|
24691
24904
|
const bounded = combined.slice(-SESSION_HISTORY_CHARACTER_LIMIT);
|
|
24692
24905
|
this.#truncated ||= bounded.length < combined.length;
|
|
24693
24906
|
this.#messages.push({
|
|
24694
24907
|
role,
|
|
24695
|
-
text: bounded
|
|
24696
|
-
...images.length > 0 ? { images } : {}
|
|
24908
|
+
text: bounded
|
|
24697
24909
|
});
|
|
24698
24910
|
this.#characters += bounded.length;
|
|
24699
|
-
this.#imageCharacters += images.reduce((size, image) => size + image.data.length, 0);
|
|
24700
24911
|
this.#lastMessageId = id;
|
|
24701
|
-
while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT
|
|
24912
|
+
while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT) {
|
|
24702
24913
|
const removed = this.#messages.shift();
|
|
24703
24914
|
if (removed !== void 0) {
|
|
24704
24915
|
this.#characters -= removed.text.length;
|
|
24705
|
-
this.#imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
24706
24916
|
}
|
|
24707
24917
|
this.#truncated = true;
|
|
24708
24918
|
}
|
|
@@ -24925,6 +25135,10 @@ var MAX_PRE_SESSION_UPDATES = 100;
|
|
|
24925
25135
|
var MAX_PRE_SESSION_UPDATE_BYTES = 1024 * 1024;
|
|
24926
25136
|
var SESSION_CONTROL_COMMAND_ID = "session-control";
|
|
24927
25137
|
var NullAcpSessionObserver = class {
|
|
25138
|
+
importLocalImage = (_sessionId, _image, signal) => {
|
|
25139
|
+
signal.throwIfAborted();
|
|
25140
|
+
return Promise.resolve("");
|
|
25141
|
+
};
|
|
24928
25142
|
onCommands = () => Promise.resolve();
|
|
24929
25143
|
onConfig = () => Promise.resolve();
|
|
24930
25144
|
onContent = () => Promise.resolve();
|
|
@@ -25547,11 +25761,75 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
25547
25761
|
);
|
|
25548
25762
|
await this.#updateTail;
|
|
25549
25763
|
signal.throwIfAborted();
|
|
25550
|
-
return
|
|
25764
|
+
return await embedLocalHistoryImages(
|
|
25765
|
+
history.snapshot(),
|
|
25766
|
+
[this.#cwd, ...this.#additionalDirectories],
|
|
25767
|
+
signal
|
|
25768
|
+
);
|
|
25551
25769
|
} finally {
|
|
25552
25770
|
this.#replay = { kind: "idle" };
|
|
25553
25771
|
}
|
|
25554
25772
|
};
|
|
25773
|
+
imageRoots = () => [this.#cwd, ...this.#additionalDirectories];
|
|
25774
|
+
emitAgentText = async (text, messageId) => {
|
|
25775
|
+
const signal = AbortSignal.timeout(2e4);
|
|
25776
|
+
const parts = text.split(/(\[@image\]\([^)\r\n]*(?:\)|$))/);
|
|
25777
|
+
let leftover = "";
|
|
25778
|
+
for (const part of parts) {
|
|
25779
|
+
const marker = /^\[@image\]\(([^)\r\n]*)(?:\)|$)/.exec(part);
|
|
25780
|
+
if (marker === null) {
|
|
25781
|
+
leftover += part;
|
|
25782
|
+
continue;
|
|
25783
|
+
}
|
|
25784
|
+
if (leftover.length > 0) {
|
|
25785
|
+
await this.#turn.onText(leftover, messageId);
|
|
25786
|
+
leftover = "";
|
|
25787
|
+
}
|
|
25788
|
+
const raster = await readAuthorizedRaster(marker[1] ?? "", this.imageRoots(), signal);
|
|
25789
|
+
if (raster === null) {
|
|
25790
|
+
leftover += "[Image unavailable]";
|
|
25791
|
+
continue;
|
|
25792
|
+
}
|
|
25793
|
+
await this.emitRaster(raster, messageId, signal);
|
|
25794
|
+
}
|
|
25795
|
+
if (leftover.length > 0) {
|
|
25796
|
+
await this.#turn.onText(leftover, messageId);
|
|
25797
|
+
}
|
|
25798
|
+
};
|
|
25799
|
+
emitAgentContent = async (content, messageId) => {
|
|
25800
|
+
if (content.type === "image" && content.data.length === 0 && content.uri.length > 0) {
|
|
25801
|
+
const signal = AbortSignal.timeout(2e4);
|
|
25802
|
+
const raster = await readAuthorizedRaster(content.uri, this.imageRoots(), signal);
|
|
25803
|
+
if (raster !== null) {
|
|
25804
|
+
await this.emitRaster(raster, messageId, signal);
|
|
25805
|
+
return;
|
|
25806
|
+
}
|
|
25807
|
+
}
|
|
25808
|
+
await this.#getObserver().onContent({
|
|
25809
|
+
commandId: this.#turn.commandId,
|
|
25810
|
+
content,
|
|
25811
|
+
contentId: `content-${crypto.randomUUID()}`,
|
|
25812
|
+
kind: AGENT_CONTENT_KIND,
|
|
25813
|
+
messageId,
|
|
25814
|
+
sessionId: this.#mobiusSessionId
|
|
25815
|
+
});
|
|
25816
|
+
};
|
|
25817
|
+
emitRaster = async (raster, messageId, signal) => {
|
|
25818
|
+
const artifactId = await this.#getObserver().importLocalImage(this.#mobiusSessionId, raster, signal);
|
|
25819
|
+
await this.#getObserver().onContent({
|
|
25820
|
+
commandId: this.#turn.commandId,
|
|
25821
|
+
content: imageDisplayContent(
|
|
25822
|
+
raster.mimeType,
|
|
25823
|
+
raster.name,
|
|
25824
|
+
artifactId.length > 0 ? "" : raster.base64(),
|
|
25825
|
+
artifactId
|
|
25826
|
+
),
|
|
25827
|
+
contentId: `content-${crypto.randomUUID()}`,
|
|
25828
|
+
kind: AGENT_CONTENT_KIND,
|
|
25829
|
+
messageId,
|
|
25830
|
+
sessionId: this.#mobiusSessionId
|
|
25831
|
+
});
|
|
25832
|
+
};
|
|
25555
25833
|
async #initializeAgent(signal) {
|
|
25556
25834
|
const initialized = await this.race(
|
|
25557
25835
|
this.#connection.agent.request(
|
|
@@ -26254,18 +26532,14 @@ var AcpProcessSession = class _AcpProcessSession {
|
|
|
26254
26532
|
);
|
|
26255
26533
|
} else {
|
|
26256
26534
|
await this.#turn.activities.finishNarrative();
|
|
26257
|
-
await this
|
|
26535
|
+
await this.emitAgentText(update.content.text, truncate3(update.messageId ?? "", 255));
|
|
26258
26536
|
}
|
|
26259
26537
|
} else {
|
|
26260
26538
|
await this.#turn.activities.finishNarrative();
|
|
26261
|
-
await this
|
|
26262
|
-
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
kind: AGENT_CONTENT_KIND,
|
|
26266
|
-
messageId: truncate3(update.messageId ?? "", 255),
|
|
26267
|
-
sessionId: this.#mobiusSessionId
|
|
26268
|
-
});
|
|
26539
|
+
await this.emitAgentContent(
|
|
26540
|
+
normalizeContentBlock(update.content),
|
|
26541
|
+
truncate3(update.messageId ?? "", 255)
|
|
26542
|
+
);
|
|
26269
26543
|
}
|
|
26270
26544
|
return;
|
|
26271
26545
|
}
|
|
@@ -27626,6 +27900,402 @@ var FixedInstallationExecutor = class {
|
|
|
27626
27900
|
};
|
|
27627
27901
|
};
|
|
27628
27902
|
|
|
27903
|
+
// src/artifacts/runtime-artifact-uploader.ts
|
|
27904
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
27905
|
+
|
|
27906
|
+
// ../mobius-sdk/src/errors.ts
|
|
27907
|
+
var MobiusError = class extends Error {
|
|
27908
|
+
code;
|
|
27909
|
+
constructor(code, message, options = {}) {
|
|
27910
|
+
super(message, options);
|
|
27911
|
+
this.code = code;
|
|
27912
|
+
this.name = "MobiusError";
|
|
27913
|
+
}
|
|
27914
|
+
};
|
|
27915
|
+
var MobiusProtocolError = class extends MobiusError {
|
|
27916
|
+
constructor(message, options = {}) {
|
|
27917
|
+
super("invalid_service_response", message, options);
|
|
27918
|
+
this.name = "MobiusProtocolError";
|
|
27919
|
+
}
|
|
27920
|
+
};
|
|
27921
|
+
var MobiusValidationError = class extends MobiusError {
|
|
27922
|
+
constructor(message, options = {}) {
|
|
27923
|
+
super("invalid_request", message, options);
|
|
27924
|
+
this.name = "MobiusValidationError";
|
|
27925
|
+
}
|
|
27926
|
+
};
|
|
27927
|
+
|
|
27928
|
+
// ../mobius-sdk/src/resources.ts
|
|
27929
|
+
var IDENTIFIER_PATTERN6 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
27930
|
+
function invalidResponse(message) {
|
|
27931
|
+
return new MobiusProtocolError(message);
|
|
27932
|
+
}
|
|
27933
|
+
function isRecord11(value) {
|
|
27934
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27935
|
+
}
|
|
27936
|
+
function record2(value, name) {
|
|
27937
|
+
if (!isRecord11(value)) {
|
|
27938
|
+
throw invalidResponse(`The service returned an invalid ${name}`);
|
|
27939
|
+
}
|
|
27940
|
+
return value;
|
|
27941
|
+
}
|
|
27942
|
+
function stringField(value, field, maximumLength = 85e5) {
|
|
27943
|
+
const candidate = value[field];
|
|
27944
|
+
if (typeof candidate !== "string" || candidate.length > maximumLength) {
|
|
27945
|
+
throw invalidResponse(`The service returned an invalid ${field}`);
|
|
27946
|
+
}
|
|
27947
|
+
return candidate;
|
|
27948
|
+
}
|
|
27949
|
+
function identifierField(value, field) {
|
|
27950
|
+
const candidate = stringField(value, field, 128);
|
|
27951
|
+
if (!IDENTIFIER_PATTERN6.test(candidate)) {
|
|
27952
|
+
throw invalidResponse(`The service returned an invalid ${field}`);
|
|
27953
|
+
}
|
|
27954
|
+
return candidate;
|
|
27955
|
+
}
|
|
27956
|
+
function integerField(value, field) {
|
|
27957
|
+
const candidate = value[field];
|
|
27958
|
+
if (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0) {
|
|
27959
|
+
throw invalidResponse(`The service returned an invalid ${field}`);
|
|
27960
|
+
}
|
|
27961
|
+
return candidate;
|
|
27962
|
+
}
|
|
27963
|
+
function validateTimestamp(value, field) {
|
|
27964
|
+
if (Number.isNaN(Date.parse(value))) {
|
|
27965
|
+
throw invalidResponse(`The service returned an invalid ${field}`);
|
|
27966
|
+
}
|
|
27967
|
+
return value;
|
|
27968
|
+
}
|
|
27969
|
+
var MobiusArtifactUploadRequest = class {
|
|
27970
|
+
byteLength;
|
|
27971
|
+
mediaType;
|
|
27972
|
+
name;
|
|
27973
|
+
sha256;
|
|
27974
|
+
constructor(name, mediaType, byteLength, sha256) {
|
|
27975
|
+
if (name.length < 1 || name.length > 500 || name.includes("\0") || mediaType.length < 1 || mediaType.length > 255 || mediaType.includes("\r") || mediaType.includes("\n") || !Number.isSafeInteger(byteLength) || byteLength < 1 || !/^[a-f0-9]{64}$/.test(sha256)) {
|
|
27976
|
+
throw new MobiusValidationError("The artifact upload request is invalid");
|
|
27977
|
+
}
|
|
27978
|
+
this.byteLength = byteLength;
|
|
27979
|
+
this.mediaType = mediaType;
|
|
27980
|
+
this.name = name;
|
|
27981
|
+
this.sha256 = sha256;
|
|
27982
|
+
}
|
|
27983
|
+
};
|
|
27984
|
+
var MobiusArtifact = class {
|
|
27985
|
+
artifactId;
|
|
27986
|
+
byteLength;
|
|
27987
|
+
createdAt;
|
|
27988
|
+
mediaType;
|
|
27989
|
+
name;
|
|
27990
|
+
sessionId;
|
|
27991
|
+
sha256;
|
|
27992
|
+
constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt) {
|
|
27993
|
+
this.artifactId = artifactId;
|
|
27994
|
+
this.byteLength = byteLength;
|
|
27995
|
+
this.createdAt = createdAt;
|
|
27996
|
+
this.mediaType = mediaType;
|
|
27997
|
+
this.name = name;
|
|
27998
|
+
this.sessionId = sessionId;
|
|
27999
|
+
this.sha256 = sha256;
|
|
28000
|
+
}
|
|
28001
|
+
};
|
|
28002
|
+
var MobiusUploadingArtifact = class extends MobiusArtifact {
|
|
28003
|
+
expiresAt;
|
|
28004
|
+
state = "uploading";
|
|
28005
|
+
constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiresAt) {
|
|
28006
|
+
super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
|
|
28007
|
+
this.expiresAt = expiresAt;
|
|
28008
|
+
}
|
|
28009
|
+
};
|
|
28010
|
+
var MobiusArtifactUpload = class extends MobiusUploadingArtifact {
|
|
28011
|
+
uploadToken;
|
|
28012
|
+
constructor(artifact, uploadToken) {
|
|
28013
|
+
super(
|
|
28014
|
+
artifact.sessionId,
|
|
28015
|
+
artifact.artifactId,
|
|
28016
|
+
artifact.name,
|
|
28017
|
+
artifact.mediaType,
|
|
28018
|
+
artifact.byteLength,
|
|
28019
|
+
artifact.sha256,
|
|
28020
|
+
artifact.createdAt,
|
|
28021
|
+
artifact.expiresAt
|
|
28022
|
+
);
|
|
28023
|
+
this.uploadToken = uploadToken;
|
|
28024
|
+
}
|
|
28025
|
+
};
|
|
28026
|
+
var MobiusAvailableArtifact = class extends MobiusArtifact {
|
|
28027
|
+
availableAt;
|
|
28028
|
+
state = "available";
|
|
28029
|
+
constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, availableAt) {
|
|
28030
|
+
super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
|
|
28031
|
+
this.availableAt = availableAt;
|
|
28032
|
+
}
|
|
28033
|
+
};
|
|
28034
|
+
var MobiusExpiredArtifact = class extends MobiusArtifact {
|
|
28035
|
+
expiredAt;
|
|
28036
|
+
state = "expired";
|
|
28037
|
+
constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiredAt) {
|
|
28038
|
+
super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
|
|
28039
|
+
this.expiredAt = expiredAt;
|
|
28040
|
+
}
|
|
28041
|
+
};
|
|
28042
|
+
function artifactFields(value) {
|
|
28043
|
+
const sha256 = stringField(value, "sha256", 64);
|
|
28044
|
+
if (!/^[a-f0-9]{64}$/.test(sha256)) {
|
|
28045
|
+
throw invalidResponse("The service returned an invalid artifact digest");
|
|
28046
|
+
}
|
|
28047
|
+
return {
|
|
28048
|
+
artifactId: identifierField(value, "artifactId"),
|
|
28049
|
+
byteLength: integerField(value, "byteLength"),
|
|
28050
|
+
createdAt: validateTimestamp(stringField(value, "createdAt", 128), "createdAt"),
|
|
28051
|
+
mediaType: stringField(value, "mediaType", 255),
|
|
28052
|
+
name: stringField(value, "name", 500),
|
|
28053
|
+
sessionId: identifierField(value, "sessionId"),
|
|
28054
|
+
sha256
|
|
28055
|
+
};
|
|
28056
|
+
}
|
|
28057
|
+
function uploadingArtifact(value) {
|
|
28058
|
+
const fields = artifactFields(value);
|
|
28059
|
+
return new MobiusUploadingArtifact(
|
|
28060
|
+
fields.sessionId,
|
|
28061
|
+
fields.artifactId,
|
|
28062
|
+
fields.name,
|
|
28063
|
+
fields.mediaType,
|
|
28064
|
+
fields.byteLength,
|
|
28065
|
+
fields.sha256,
|
|
28066
|
+
fields.createdAt,
|
|
28067
|
+
validateTimestamp(stringField(value, "expiresAt", 128), "expiresAt")
|
|
28068
|
+
);
|
|
28069
|
+
}
|
|
28070
|
+
function decodeMobiusArtifactUpload(value) {
|
|
28071
|
+
const artifact = record2(value, "artifact upload authorization");
|
|
28072
|
+
return new MobiusArtifactUpload(uploadingArtifact(artifact), stringField(artifact, "uploadToken", 256));
|
|
28073
|
+
}
|
|
28074
|
+
function decodeMobiusArtifact(value) {
|
|
28075
|
+
const artifact = record2(value, "artifact");
|
|
28076
|
+
const state = stringField(artifact, "state", 32);
|
|
28077
|
+
if (state === "uploading") {
|
|
28078
|
+
return uploadingArtifact(artifact);
|
|
28079
|
+
}
|
|
28080
|
+
const fields = artifactFields(artifact);
|
|
28081
|
+
if (state === "available") {
|
|
28082
|
+
return new MobiusAvailableArtifact(
|
|
28083
|
+
fields.sessionId,
|
|
28084
|
+
fields.artifactId,
|
|
28085
|
+
fields.name,
|
|
28086
|
+
fields.mediaType,
|
|
28087
|
+
fields.byteLength,
|
|
28088
|
+
fields.sha256,
|
|
28089
|
+
fields.createdAt,
|
|
28090
|
+
validateTimestamp(stringField(artifact, "availableAt", 128), "availableAt")
|
|
28091
|
+
);
|
|
28092
|
+
}
|
|
28093
|
+
if (state === "expired") {
|
|
28094
|
+
return new MobiusExpiredArtifact(
|
|
28095
|
+
fields.sessionId,
|
|
28096
|
+
fields.artifactId,
|
|
28097
|
+
fields.name,
|
|
28098
|
+
fields.mediaType,
|
|
28099
|
+
fields.byteLength,
|
|
28100
|
+
fields.sha256,
|
|
28101
|
+
fields.createdAt,
|
|
28102
|
+
validateTimestamp(stringField(artifact, "expiredAt", 128), "expiredAt")
|
|
28103
|
+
);
|
|
28104
|
+
}
|
|
28105
|
+
throw invalidResponse("The service returned an invalid artifact state");
|
|
28106
|
+
}
|
|
28107
|
+
function decodeMobiusAvailableArtifact(value) {
|
|
28108
|
+
const artifact = decodeMobiusArtifact(value);
|
|
28109
|
+
if (!(artifact instanceof MobiusAvailableArtifact)) {
|
|
28110
|
+
throw invalidResponse("The service did not make the artifact available");
|
|
28111
|
+
}
|
|
28112
|
+
return artifact;
|
|
28113
|
+
}
|
|
28114
|
+
var MobiusRuntimePairingLifecycle = Object.freeze({
|
|
28115
|
+
Expired: "expired",
|
|
28116
|
+
Paired: "paired",
|
|
28117
|
+
Pending: "pending",
|
|
28118
|
+
Revoked: "revoked"
|
|
28119
|
+
});
|
|
28120
|
+
|
|
28121
|
+
// src/artifacts/runtime-artifact-uploader.ts
|
|
28122
|
+
import { fetch as fetch4 } from "undici";
|
|
28123
|
+
var UPLOAD_TIMEOUT_MILLISECONDS = 2e4;
|
|
28124
|
+
var RuntimeArtifactUploadError = class extends Error {
|
|
28125
|
+
code;
|
|
28126
|
+
constructor(code, message, options = {}) {
|
|
28127
|
+
super(message, options);
|
|
28128
|
+
this.code = code;
|
|
28129
|
+
this.name = "RuntimeArtifactUploadError";
|
|
28130
|
+
}
|
|
28131
|
+
};
|
|
28132
|
+
var UploadedRuntimeArtifact = class {
|
|
28133
|
+
artifactId;
|
|
28134
|
+
byteLength;
|
|
28135
|
+
mimeType;
|
|
28136
|
+
name;
|
|
28137
|
+
sha256;
|
|
28138
|
+
constructor(artifactId, name, mimeType, byteLength, sha256) {
|
|
28139
|
+
this.artifactId = artifactId;
|
|
28140
|
+
this.byteLength = byteLength;
|
|
28141
|
+
this.mimeType = mimeType;
|
|
28142
|
+
this.name = name;
|
|
28143
|
+
this.sha256 = sha256;
|
|
28144
|
+
}
|
|
28145
|
+
};
|
|
28146
|
+
function daemonToken(config2) {
|
|
28147
|
+
const token = config2.relayUrl.searchParams.get("token");
|
|
28148
|
+
if (token === null || token.length < 32) {
|
|
28149
|
+
throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay daemon token is missing");
|
|
28150
|
+
}
|
|
28151
|
+
return token;
|
|
28152
|
+
}
|
|
28153
|
+
function channelOrigin(config2) {
|
|
28154
|
+
const url2 = new URL(config2.relayUrl);
|
|
28155
|
+
url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
|
|
28156
|
+
let channelPath = "";
|
|
28157
|
+
if (url2.pathname.endsWith("/daemon")) {
|
|
28158
|
+
channelPath = url2.pathname.slice(0, -"/daemon".length);
|
|
28159
|
+
} else {
|
|
28160
|
+
const runtimePath = `${MOBIUS_API_PREFIX}/v1/runtimes/connect`;
|
|
28161
|
+
if (!url2.pathname.endsWith("/v1/runtimes/connect") && !url2.pathname.endsWith(runtimePath)) {
|
|
28162
|
+
throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay artifact endpoint is invalid");
|
|
28163
|
+
}
|
|
28164
|
+
channelPath = `${url2.pathname.replace(/\/v1\/runtimes\/connect$/, "")}/channels/${encodeURIComponent(config2.channelId)}`;
|
|
28165
|
+
}
|
|
28166
|
+
url2.pathname = channelPath;
|
|
28167
|
+
url2.search = "";
|
|
28168
|
+
url2.hash = "";
|
|
28169
|
+
return url2;
|
|
28170
|
+
}
|
|
28171
|
+
function uploadError(code, message, cause) {
|
|
28172
|
+
return new RuntimeArtifactUploadError(code, message, cause === void 0 ? {} : { cause });
|
|
28173
|
+
}
|
|
28174
|
+
function translateSdkError(cause) {
|
|
28175
|
+
if (cause instanceof MobiusValidationError) {
|
|
28176
|
+
throw uploadError("artifact_upload_failed", cause.message, cause);
|
|
28177
|
+
}
|
|
28178
|
+
if (cause instanceof MobiusProtocolError) {
|
|
28179
|
+
throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
|
|
28180
|
+
}
|
|
28181
|
+
throw cause;
|
|
28182
|
+
}
|
|
28183
|
+
async function readJson(response) {
|
|
28184
|
+
try {
|
|
28185
|
+
return await response.json();
|
|
28186
|
+
} catch (cause) {
|
|
28187
|
+
throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
|
|
28188
|
+
}
|
|
28189
|
+
}
|
|
28190
|
+
async function readAuthorization(response) {
|
|
28191
|
+
try {
|
|
28192
|
+
return decodeMobiusArtifactUpload(await readJson(response));
|
|
28193
|
+
} catch (cause) {
|
|
28194
|
+
translateSdkError(cause);
|
|
28195
|
+
}
|
|
28196
|
+
}
|
|
28197
|
+
function sessionArtifactUrl(origin, sessionId, resourcePath, token) {
|
|
28198
|
+
const url2 = new URL(`${origin.pathname}/sessions/${encodeURIComponent(sessionId)}/${resourcePath}`, origin);
|
|
28199
|
+
url2.searchParams.set("token", token);
|
|
28200
|
+
return url2;
|
|
28201
|
+
}
|
|
28202
|
+
async function postLease(url2, request, signal) {
|
|
28203
|
+
return await fetch4(url2, {
|
|
28204
|
+
dispatcher: environmentProxyDispatcher,
|
|
28205
|
+
headers: { "content-type": "application/json" },
|
|
28206
|
+
method: "POST",
|
|
28207
|
+
body: JSON.stringify(request),
|
|
28208
|
+
signal
|
|
28209
|
+
});
|
|
28210
|
+
}
|
|
28211
|
+
async function putContent(url2, authorization, bytes, signal) {
|
|
28212
|
+
return await fetch4(url2, {
|
|
28213
|
+
dispatcher: environmentProxyDispatcher,
|
|
28214
|
+
headers: {
|
|
28215
|
+
"content-type": authorization.mediaType,
|
|
28216
|
+
"x-mobius-upload-token": authorization.uploadToken
|
|
28217
|
+
},
|
|
28218
|
+
method: "PUT",
|
|
28219
|
+
body: bytes,
|
|
28220
|
+
signal
|
|
28221
|
+
});
|
|
28222
|
+
}
|
|
28223
|
+
async function uploadRuntimeArtifact(config2, sessionId, image, signal) {
|
|
28224
|
+
signal.throwIfAborted();
|
|
28225
|
+
let request;
|
|
28226
|
+
try {
|
|
28227
|
+
request = new MobiusArtifactUploadRequest(
|
|
28228
|
+
image.name,
|
|
28229
|
+
image.mimeType,
|
|
28230
|
+
image.bytes.byteLength,
|
|
28231
|
+
createHash2("sha256").update(image.bytes).digest("hex")
|
|
28232
|
+
);
|
|
28233
|
+
} catch (cause) {
|
|
28234
|
+
translateSdkError(cause);
|
|
28235
|
+
}
|
|
28236
|
+
const timeoutSignal = AbortSignal.timeout(UPLOAD_TIMEOUT_MILLISECONDS);
|
|
28237
|
+
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
28238
|
+
const origin = channelOrigin(config2);
|
|
28239
|
+
const token = daemonToken(config2);
|
|
28240
|
+
let created;
|
|
28241
|
+
try {
|
|
28242
|
+
created = await postLease(
|
|
28243
|
+
sessionArtifactUrl(origin, sessionId, "artifacts/uploads", token),
|
|
28244
|
+
request,
|
|
28245
|
+
requestSignal
|
|
28246
|
+
);
|
|
28247
|
+
} catch (cause) {
|
|
28248
|
+
signal.throwIfAborted();
|
|
28249
|
+
throw uploadError(
|
|
28250
|
+
timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
|
|
28251
|
+
timeoutSignal.aborted ? "The artifact upload authorization timed out" : "The artifact upload could not start",
|
|
28252
|
+
cause
|
|
28253
|
+
);
|
|
28254
|
+
}
|
|
28255
|
+
if (!created.ok) {
|
|
28256
|
+
await created.body?.cancel();
|
|
28257
|
+
throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact upload");
|
|
28258
|
+
}
|
|
28259
|
+
const authorization = await readAuthorization(created);
|
|
28260
|
+
let uploaded;
|
|
28261
|
+
try {
|
|
28262
|
+
uploaded = await putContent(
|
|
28263
|
+
sessionArtifactUrl(
|
|
28264
|
+
origin,
|
|
28265
|
+
sessionId,
|
|
28266
|
+
`artifacts/${encodeURIComponent(authorization.artifactId)}/content`,
|
|
28267
|
+
token
|
|
28268
|
+
),
|
|
28269
|
+
authorization,
|
|
28270
|
+
image.bytes,
|
|
28271
|
+
requestSignal
|
|
28272
|
+
);
|
|
28273
|
+
} catch (cause) {
|
|
28274
|
+
signal.throwIfAborted();
|
|
28275
|
+
throw uploadError(
|
|
28276
|
+
timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
|
|
28277
|
+
timeoutSignal.aborted ? "The artifact upload timed out" : "The artifact content could not be uploaded",
|
|
28278
|
+
cause
|
|
28279
|
+
);
|
|
28280
|
+
}
|
|
28281
|
+
if (!uploaded.ok) {
|
|
28282
|
+
await uploaded.body?.cancel();
|
|
28283
|
+
throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact content");
|
|
28284
|
+
}
|
|
28285
|
+
try {
|
|
28286
|
+
const available = decodeMobiusAvailableArtifact(await readJson(uploaded));
|
|
28287
|
+
return new UploadedRuntimeArtifact(
|
|
28288
|
+
available.artifactId,
|
|
28289
|
+
available.name,
|
|
28290
|
+
available.mediaType,
|
|
28291
|
+
available.byteLength,
|
|
28292
|
+
available.sha256
|
|
28293
|
+
);
|
|
28294
|
+
} catch (cause) {
|
|
28295
|
+
translateSdkError(cause);
|
|
28296
|
+
}
|
|
28297
|
+
}
|
|
28298
|
+
|
|
27629
28299
|
// src/authorization/local-authorization-error.ts
|
|
27630
28300
|
var LocalAuthorizationError = class extends Error {
|
|
27631
28301
|
code = "local_authorization_failed";
|
|
@@ -27636,9 +28306,9 @@ var LocalAuthorizationError = class extends Error {
|
|
|
27636
28306
|
};
|
|
27637
28307
|
|
|
27638
28308
|
// src/authorization/workspace-directory.ts
|
|
27639
|
-
import { readdir, realpath as
|
|
28309
|
+
import { readdir, realpath as realpath8, stat as stat7 } from "node:fs/promises";
|
|
27640
28310
|
import { homedir as homedir2 } from "node:os";
|
|
27641
|
-
import { basename as
|
|
28311
|
+
import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute8, join as join15, normalize as normalize3, relative as relative5 } from "node:path";
|
|
27642
28312
|
var WorkspaceDirectoryListing = class {
|
|
27643
28313
|
directoryId;
|
|
27644
28314
|
directoryLabel;
|
|
@@ -27664,7 +28334,7 @@ function decodePath(value, prefix) {
|
|
|
27664
28334
|
throw new LocalAuthorizationError("The directory identifier is invalid");
|
|
27665
28335
|
}
|
|
27666
28336
|
const decoded = Buffer.from(encoded, "base64url").toString("utf8");
|
|
27667
|
-
if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") ||
|
|
28337
|
+
if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize3(decoded) !== decoded) {
|
|
27668
28338
|
throw new LocalAuthorizationError("The directory identifier is invalid");
|
|
27669
28339
|
}
|
|
27670
28340
|
return decoded;
|
|
@@ -27690,7 +28360,7 @@ var WorkspaceDirectoryService = class {
|
|
|
27690
28360
|
}
|
|
27691
28361
|
if (id.startsWith("path-")) {
|
|
27692
28362
|
const path2 = decodePath(id, "path-");
|
|
27693
|
-
if (
|
|
28363
|
+
if (isAbsolute8(path2)) {
|
|
27694
28364
|
return path2;
|
|
27695
28365
|
}
|
|
27696
28366
|
}
|
|
@@ -27698,15 +28368,15 @@ var WorkspaceDirectoryService = class {
|
|
|
27698
28368
|
};
|
|
27699
28369
|
resolvePath = async (requested, signal) => {
|
|
27700
28370
|
signal.throwIfAborted();
|
|
27701
|
-
if (!
|
|
28371
|
+
if (!isAbsolute8(requested) || requested.includes("\0") || normalize3(requested) !== requested) {
|
|
27702
28372
|
throw new LocalAuthorizationError("The local directory path is invalid");
|
|
27703
28373
|
}
|
|
27704
28374
|
try {
|
|
27705
|
-
const target = await
|
|
28375
|
+
const target = await realpath8(requested);
|
|
27706
28376
|
signal.throwIfAborted();
|
|
27707
|
-
const metadata = await
|
|
28377
|
+
const metadata = await stat7(target);
|
|
27708
28378
|
signal.throwIfAborted();
|
|
27709
|
-
if (!
|
|
28379
|
+
if (!isAbsolute8(target) || normalize3(target) !== target || !metadata.isDirectory()) {
|
|
27710
28380
|
throw new LocalAuthorizationError("The selected location is not a directory");
|
|
27711
28381
|
}
|
|
27712
28382
|
return target;
|
|
@@ -27721,8 +28391,8 @@ var WorkspaceDirectoryService = class {
|
|
|
27721
28391
|
}
|
|
27722
28392
|
};
|
|
27723
28393
|
label = (path2) => {
|
|
27724
|
-
const suffix =
|
|
27725
|
-
return suffix === "" ? "~" : !
|
|
28394
|
+
const suffix = relative5(homedir2(), path2);
|
|
28395
|
+
return suffix === "" ? "~" : !isAbsolute8(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
|
|
27726
28396
|
};
|
|
27727
28397
|
identify = async (bindingId, requestedPath, signal) => {
|
|
27728
28398
|
this.authorizeMachine(bindingId);
|
|
@@ -27730,7 +28400,7 @@ var WorkspaceDirectoryService = class {
|
|
|
27730
28400
|
return {
|
|
27731
28401
|
path: path2,
|
|
27732
28402
|
directoryId: encodePath(path2),
|
|
27733
|
-
name:
|
|
28403
|
+
name: basename3(path2) || path2,
|
|
27734
28404
|
label: this.label(path2)
|
|
27735
28405
|
};
|
|
27736
28406
|
};
|
|
@@ -27787,8 +28457,8 @@ var WorkspaceDirectoryService = class {
|
|
|
27787
28457
|
};
|
|
27788
28458
|
|
|
27789
28459
|
// src/bots/local-bot-grant-store.ts
|
|
27790
|
-
import { createHash as
|
|
27791
|
-
import { stat as
|
|
28460
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
|
|
28461
|
+
import { stat as stat8 } from "node:fs/promises";
|
|
27792
28462
|
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
27793
28463
|
var LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS = 90 * 24 * 60 * 60 * 1e3;
|
|
27794
28464
|
var LocalBotAuthorizationError = class extends Error {
|
|
@@ -27832,7 +28502,7 @@ var LocalBotGrant = class {
|
|
|
27832
28502
|
}
|
|
27833
28503
|
};
|
|
27834
28504
|
function digest(value) {
|
|
27835
|
-
return
|
|
28505
|
+
return createHash3("sha256").update(value, "utf8").digest("hex");
|
|
27836
28506
|
}
|
|
27837
28507
|
function agentDigest(agent) {
|
|
27838
28508
|
return digest(
|
|
@@ -27846,7 +28516,7 @@ function agentDigest(agent) {
|
|
|
27846
28516
|
);
|
|
27847
28517
|
}
|
|
27848
28518
|
async function workspaceDigest(path2) {
|
|
27849
|
-
const metadata = await
|
|
28519
|
+
const metadata = await stat8(path2);
|
|
27850
28520
|
if (!metadata.isDirectory()) {
|
|
27851
28521
|
throw new LocalBotAuthorizationError("binding_incompatible", "The Bot workspace is not a directory");
|
|
27852
28522
|
}
|
|
@@ -28263,12 +28933,12 @@ var BotExecutionContextRegistry = class {
|
|
|
28263
28933
|
// src/bots/bot-outbound-ipc.ts
|
|
28264
28934
|
import { chmod as chmod2, mkdir as mkdir4, unlink } from "node:fs/promises";
|
|
28265
28935
|
import { createServer } from "node:net";
|
|
28266
|
-
import { dirname as dirname6, isAbsolute as
|
|
28267
|
-
import { fetch as
|
|
28936
|
+
import { dirname as dirname6, isAbsolute as isAbsolute9 } from "node:path";
|
|
28937
|
+
import { fetch as fetch5 } from "undici";
|
|
28268
28938
|
var BOT_IPC_REQUEST_LIMIT = 32 * 1024;
|
|
28269
28939
|
var BOT_IPC_TIMEOUT_MILLISECONDS2 = 2e4;
|
|
28270
28940
|
var BOT_RELAY_TIMEOUT_MILLISECONDS = 2e4;
|
|
28271
|
-
var
|
|
28941
|
+
var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
28272
28942
|
var WINDOWS_NAMED_PIPE_PREFIX = "\\\\.\\pipe\\";
|
|
28273
28943
|
var BotOutboundIpcRequest = class {
|
|
28274
28944
|
contextHandle;
|
|
@@ -28282,7 +28952,7 @@ var BotOutboundIpcRequest = class {
|
|
|
28282
28952
|
this.text = text;
|
|
28283
28953
|
}
|
|
28284
28954
|
};
|
|
28285
|
-
function
|
|
28955
|
+
function isRecord12(value) {
|
|
28286
28956
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28287
28957
|
}
|
|
28288
28958
|
function decodeRequest(encoded) {
|
|
@@ -28292,7 +28962,7 @@ function decodeRequest(encoded) {
|
|
|
28292
28962
|
} catch (cause) {
|
|
28293
28963
|
throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid", { cause });
|
|
28294
28964
|
}
|
|
28295
|
-
if (!
|
|
28965
|
+
if (!isRecord12(value)) {
|
|
28296
28966
|
throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
|
|
28297
28967
|
}
|
|
28298
28968
|
const keys = Object.keys(value);
|
|
@@ -28303,7 +28973,7 @@ function decodeRequest(encoded) {
|
|
|
28303
28973
|
const idempotencyKey = value["idempotencyKey"];
|
|
28304
28974
|
const target = value["target"];
|
|
28305
28975
|
const text = value["text"];
|
|
28306
|
-
if (typeof contextHandle !== "string" || !/^ctx_[a-zA-Z0-9_-]{43}$/.test(contextHandle) || typeof idempotencyKey !== "string" || !
|
|
28976
|
+
if (typeof contextHandle !== "string" || !/^ctx_[a-zA-Z0-9_-]{43}$/.test(contextHandle) || typeof idempotencyKey !== "string" || !IDENTIFIER_PATTERN7.test(idempotencyKey) || typeof target !== "string" || !IDENTIFIER_PATTERN7.test(target) || typeof text !== "string" || text.trim().length === 0 || text.length > 1e4) {
|
|
28307
28977
|
throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
|
|
28308
28978
|
}
|
|
28309
28979
|
return new BotOutboundIpcRequest(contextHandle, idempotencyKey, target, text);
|
|
@@ -28325,7 +28995,7 @@ function relayEndpoint(relayUrl, context, target) {
|
|
|
28325
28995
|
endpoint.pathname = `${MOBIUS_API_PREFIX}/v1/bot-executions/${execution}/delivery-targets/${encodeURIComponent(deliveryTargetId)}/messages`;
|
|
28326
28996
|
return endpoint;
|
|
28327
28997
|
}
|
|
28328
|
-
function
|
|
28998
|
+
function daemonToken2(relayUrl) {
|
|
28329
28999
|
const token = relayUrl.searchParams.get("token") ?? "";
|
|
28330
29000
|
if (!/^[a-zA-Z0-9_-]{32,256}$/.test(token)) {
|
|
28331
29001
|
throw new LocalBotAuthorizationError("bot_service_unavailable", "The Runtime credential is unavailable");
|
|
@@ -28342,10 +29012,10 @@ async function decodeRelayResponse(response) {
|
|
|
28342
29012
|
cause
|
|
28343
29013
|
});
|
|
28344
29014
|
}
|
|
28345
|
-
if (response.status === 202 &&
|
|
29015
|
+
if (response.status === 202 && isRecord12(value) && typeof value["outboundMessageId"] === "string") {
|
|
28346
29016
|
return value["outboundMessageId"];
|
|
28347
29017
|
}
|
|
28348
|
-
if (
|
|
29018
|
+
if (isRecord12(value) && isRecord12(value["error"])) {
|
|
28349
29019
|
const error61 = value["error"];
|
|
28350
29020
|
if (typeof error61["code"] === "string" && typeof error61["message"] === "string") {
|
|
28351
29021
|
throw new LocalBotAuthorizationError(error61["code"], error61["message"]);
|
|
@@ -28361,7 +29031,7 @@ var BotOutboundIpcServer = class {
|
|
|
28361
29031
|
#usesFilesystemSocket;
|
|
28362
29032
|
constructor(socketPath, relayUrl, registry2) {
|
|
28363
29033
|
const usesFilesystemSocket = !socketPath.startsWith(WINDOWS_NAMED_PIPE_PREFIX);
|
|
28364
|
-
if (usesFilesystemSocket && !
|
|
29034
|
+
if (usesFilesystemSocket && !isAbsolute9(socketPath)) {
|
|
28365
29035
|
throw new Error("The Bot IPC path must be absolute");
|
|
28366
29036
|
}
|
|
28367
29037
|
this.#registry = registry2;
|
|
@@ -28378,7 +29048,7 @@ var BotOutboundIpcServer = class {
|
|
|
28378
29048
|
if (this.#usesFilesystemSocket) {
|
|
28379
29049
|
await mkdir4(dirname6(this.#socketPath), { mode: 448, recursive: true });
|
|
28380
29050
|
await unlink(this.#socketPath).catch((error61) => {
|
|
28381
|
-
if (!
|
|
29051
|
+
if (!isRecord12(error61) || error61["code"] !== "ENOENT") {
|
|
28382
29052
|
throw error61;
|
|
28383
29053
|
}
|
|
28384
29054
|
});
|
|
@@ -28413,7 +29083,7 @@ var BotOutboundIpcServer = class {
|
|
|
28413
29083
|
}
|
|
28414
29084
|
if (this.#usesFilesystemSocket) {
|
|
28415
29085
|
await unlink(this.#socketPath).catch((error61) => {
|
|
28416
|
-
if (!
|
|
29086
|
+
if (!isRecord12(error61) || error61["code"] !== "ENOENT") {
|
|
28417
29087
|
throw error61;
|
|
28418
29088
|
}
|
|
28419
29089
|
});
|
|
@@ -28477,10 +29147,10 @@ var BotOutboundIpcServer = class {
|
|
|
28477
29147
|
const requestSignal = AbortSignal.any([signal, timeout]);
|
|
28478
29148
|
let response;
|
|
28479
29149
|
try {
|
|
28480
|
-
response = await
|
|
29150
|
+
response = await fetch5(relayEndpoint(this.#relayUrl, context, request.target), {
|
|
28481
29151
|
body: JSON.stringify({ idempotencyKey: request.idempotencyKey, text: request.text }),
|
|
28482
29152
|
headers: {
|
|
28483
|
-
authorization: `Bearer ${
|
|
29153
|
+
authorization: `Bearer ${daemonToken2(this.#relayUrl)}`,
|
|
28484
29154
|
"content-type": "application/json",
|
|
28485
29155
|
"x-mobius-bot-execution-capability": context.command.executionCapabilitySecret
|
|
28486
29156
|
},
|
|
@@ -28501,7 +29171,7 @@ var BotOutboundIpcServer = class {
|
|
|
28501
29171
|
|
|
28502
29172
|
// src/native-sessions/service.ts
|
|
28503
29173
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
28504
|
-
import { basename as
|
|
29174
|
+
import { basename as basename4 } from "node:path";
|
|
28505
29175
|
|
|
28506
29176
|
// src/native-sessions/codex-history.ts
|
|
28507
29177
|
import { spawn as spawn4 } from "node:child_process";
|
|
@@ -28534,7 +29204,6 @@ function decodeHistory(thread, value) {
|
|
|
28534
29204
|
const page = turnsSchema.parse(value);
|
|
28535
29205
|
const messages = [];
|
|
28536
29206
|
let characters = 0;
|
|
28537
|
-
let imageCharacters = 0;
|
|
28538
29207
|
let truncated = page.nextCursor != null;
|
|
28539
29208
|
for (const turn of page.data.toReversed()) {
|
|
28540
29209
|
for (const item of turn.items) {
|
|
@@ -28542,22 +29211,19 @@ function decodeHistory(thread, value) {
|
|
|
28542
29211
|
let message;
|
|
28543
29212
|
if (type === "userMessage") {
|
|
28544
29213
|
const { content } = userMessageSchema.parse(item);
|
|
28545
|
-
const
|
|
28546
|
-
|
|
28547
|
-
|
|
28548
|
-
|
|
28549
|
-
|
|
28550
|
-
|
|
28551
|
-
|
|
28552
|
-
|
|
28553
|
-
|
|
28554
|
-
|
|
28555
|
-
}).join("")
|
|
28556
|
-
);
|
|
29214
|
+
const text2 = content.map((block) => {
|
|
29215
|
+
const { type: type2 } = itemTypeSchema.parse(block);
|
|
29216
|
+
if (type2 === "text") {
|
|
29217
|
+
return textSchema.parse(block).text;
|
|
29218
|
+
}
|
|
29219
|
+
if (type2 === "image") {
|
|
29220
|
+
return `[@image](${imageSchema.parse(block).url})`;
|
|
29221
|
+
}
|
|
29222
|
+
return "[Attachment]";
|
|
29223
|
+
}).join("");
|
|
28557
29224
|
message = {
|
|
28558
29225
|
role: "user",
|
|
28559
|
-
text:
|
|
28560
|
-
...parsed.images.length > 0 ? { images: parsed.images } : {}
|
|
29226
|
+
text: text2
|
|
28561
29227
|
};
|
|
28562
29228
|
} else if (type === "agentMessage") {
|
|
28563
29229
|
const agent = agentMessageSchema.parse(item);
|
|
@@ -28575,12 +29241,10 @@ function decodeHistory(thread, value) {
|
|
|
28575
29241
|
truncated ||= text.length < message.text.length;
|
|
28576
29242
|
messages.push({ ...message, text });
|
|
28577
29243
|
characters += text.length;
|
|
28578
|
-
|
|
28579
|
-
while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT || imageCharacters > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
|
|
29244
|
+
while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT) {
|
|
28580
29245
|
const removed = messages.shift();
|
|
28581
29246
|
if (removed !== void 0) {
|
|
28582
29247
|
characters -= removed.text.length;
|
|
28583
|
-
imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
|
|
28584
29248
|
}
|
|
28585
29249
|
truncated = true;
|
|
28586
29250
|
}
|
|
@@ -28738,7 +29402,11 @@ async function readCodexHistory(agent, cwd, nativeSessionId, signal) {
|
|
|
28738
29402
|
params: { clientInfo: { name: "mobius_history", version: "1.0.0" } }
|
|
28739
29403
|
});
|
|
28740
29404
|
}
|
|
28741
|
-
|
|
29405
|
+
const snapshot = await response.promise;
|
|
29406
|
+
return {
|
|
29407
|
+
...snapshot,
|
|
29408
|
+
history: await embedLocalHistoryImages(snapshot.history, [cwd, snapshot.cwd], signal)
|
|
29409
|
+
};
|
|
28742
29410
|
} finally {
|
|
28743
29411
|
clearTimeout(timeout);
|
|
28744
29412
|
signal.removeEventListener("abort", abort);
|
|
@@ -28992,7 +29660,7 @@ var NativeSessionService = class {
|
|
|
28992
29660
|
}
|
|
28993
29661
|
resolvedPaths.add(path2);
|
|
28994
29662
|
additionalDirectories.push(path2);
|
|
28995
|
-
additionalEntries.push({ directoryId: directoryId2, name:
|
|
29663
|
+
additionalEntries.push({ directoryId: directoryId2, name: basename4(path2) });
|
|
28996
29664
|
}
|
|
28997
29665
|
const listing = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
|
|
28998
29666
|
const opened = await this.#sessions.forkSessionAtTurn(
|
|
@@ -29131,13 +29799,13 @@ var NativeSessionService = class {
|
|
|
29131
29799
|
};
|
|
29132
29800
|
|
|
29133
29801
|
// src/prompt-artifact-resolver.ts
|
|
29134
|
-
import { createHash as
|
|
29135
|
-
import { fetch as
|
|
29802
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
29803
|
+
import { fetch as fetch6 } from "undici";
|
|
29136
29804
|
var ARTIFACT_SCHEME = "mobius-artifact:";
|
|
29137
29805
|
var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
|
|
29138
29806
|
var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
|
|
29139
29807
|
var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
|
|
29140
|
-
var
|
|
29808
|
+
var IDENTIFIER_PATTERN8 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
29141
29809
|
var PromptArtifactError = class extends Error {
|
|
29142
29810
|
code;
|
|
29143
29811
|
constructor(code, message, options = {}) {
|
|
@@ -29180,7 +29848,7 @@ function parseReference(resource) {
|
|
|
29180
29848
|
const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
|
|
29181
29849
|
const sha256 = url2.searchParams.get("sha256") ?? "";
|
|
29182
29850
|
const byteLength = Number(encodedByteLength2);
|
|
29183
|
-
if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !
|
|
29851
|
+
if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !IDENTIFIER_PATTERN8.test(artifactId) || keys.length !== 2 || keys[0] !== "byteLength" || keys[1] !== "sha256" || !/^[1-9][0-9]*$/.test(encodedByteLength2) || !Number.isSafeInteger(byteLength) || !/^[a-f0-9]{64}$/.test(sha256)) {
|
|
29184
29852
|
throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
|
|
29185
29853
|
}
|
|
29186
29854
|
return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
|
|
@@ -29246,7 +29914,7 @@ async function download(config2, command, reference, signal) {
|
|
|
29246
29914
|
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
29247
29915
|
let response;
|
|
29248
29916
|
try {
|
|
29249
|
-
response = await
|
|
29917
|
+
response = await fetch6(downloadUrl(config2, command, reference), {
|
|
29250
29918
|
dispatcher: environmentProxyDispatcher,
|
|
29251
29919
|
headers: {
|
|
29252
29920
|
accept: reference.resource.mimeType,
|
|
@@ -29270,7 +29938,7 @@ async function download(config2, command, reference, signal) {
|
|
|
29270
29938
|
);
|
|
29271
29939
|
}
|
|
29272
29940
|
const bytes = await responseBytes(response, reference.byteLength, requestSignal);
|
|
29273
|
-
if (
|
|
29941
|
+
if (createHash4("sha256").update(bytes).digest("hex") !== reference.sha256) {
|
|
29274
29942
|
throw new PromptArtifactError(
|
|
29275
29943
|
"artifact_integrity_failed",
|
|
29276
29944
|
"The prompt artifact failed integrity validation"
|
|
@@ -30306,10 +30974,23 @@ function botIpcSocketPath() {
|
|
|
30306
30974
|
return join16("/tmp", `mobius-bot-${randomUUID6()}.sock`);
|
|
30307
30975
|
}
|
|
30308
30976
|
var DaemonAcpObserver = class {
|
|
30977
|
+
#config;
|
|
30309
30978
|
#record;
|
|
30310
|
-
constructor(
|
|
30311
|
-
this.#
|
|
30979
|
+
constructor(config2, record3) {
|
|
30980
|
+
this.#config = config2;
|
|
30981
|
+
this.#record = record3;
|
|
30312
30982
|
}
|
|
30983
|
+
importLocalImage = async (sessionId, image, signal) => {
|
|
30984
|
+
try {
|
|
30985
|
+
return (await uploadRuntimeArtifact(this.#config, sessionId, image, signal)).artifactId;
|
|
30986
|
+
} catch (cause) {
|
|
30987
|
+
signal.throwIfAborted();
|
|
30988
|
+
if (cause instanceof Error && cause.name === "AbortError") {
|
|
30989
|
+
throw cause;
|
|
30990
|
+
}
|
|
30991
|
+
return "";
|
|
30992
|
+
}
|
|
30993
|
+
};
|
|
30313
30994
|
onCommands = (event) => {
|
|
30314
30995
|
this.#record(event.sessionId, encodeSessionCommandsUpdatedEvent(event));
|
|
30315
30996
|
return Promise.resolve();
|
|
@@ -30519,7 +31200,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
|
|
|
30519
31200
|
const requestSignal = AbortSignal.any([signal, timeoutSignal]);
|
|
30520
31201
|
let response;
|
|
30521
31202
|
try {
|
|
30522
|
-
response = await
|
|
31203
|
+
response = await fetch7(activeTurnReconciliationEndpoint(config2, turn), {
|
|
30523
31204
|
body: JSON.stringify({ outcome: { kind: "running" } }),
|
|
30524
31205
|
dispatcher: environmentProxyDispatcher,
|
|
30525
31206
|
headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
|
|
@@ -30835,7 +31516,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
|
|
|
30835
31516
|
additionalDirectories.push(directory);
|
|
30836
31517
|
additionalDirectoryEntries.push({
|
|
30837
31518
|
directoryId: additionalDirectoryId,
|
|
30838
|
-
name:
|
|
31519
|
+
name: basename5(directory)
|
|
30839
31520
|
});
|
|
30840
31521
|
}
|
|
30841
31522
|
return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
|
|
@@ -31346,8 +32027,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31346
32027
|
rejectConnection(failure);
|
|
31347
32028
|
};
|
|
31348
32029
|
const processingDeliveryIds = /* @__PURE__ */ new Set();
|
|
31349
|
-
const processDeliveredPrompt = async (delivery) => {
|
|
31350
|
-
const command = decodeSessionPromptCommand(delivery.payload);
|
|
32030
|
+
const processDeliveredPrompt = async (delivery, command, trackActiveAttempt, execute) => {
|
|
31351
32031
|
if (command.sessionId !== delivery.sessionId) {
|
|
31352
32032
|
throw new Error("Runtime delivery Session identity does not match its payload");
|
|
31353
32033
|
}
|
|
@@ -31375,22 +32055,11 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31375
32055
|
}
|
|
31376
32056
|
const turn = new ActiveDaemonTurn(command, receipt.attemptId);
|
|
31377
32057
|
activeTurns.set(command.commandId, turn);
|
|
31378
|
-
if (
|
|
32058
|
+
if (trackActiveAttempt) {
|
|
31379
32059
|
activeAttemptIds.set(command.sessionId, receipt.attemptId);
|
|
31380
32060
|
}
|
|
31381
32061
|
try {
|
|
31382
|
-
await
|
|
31383
|
-
outbox,
|
|
31384
|
-
publisher,
|
|
31385
|
-
command,
|
|
31386
|
-
config2,
|
|
31387
|
-
directories,
|
|
31388
|
-
audit,
|
|
31389
|
-
sessions,
|
|
31390
|
-
receipt.attemptId,
|
|
31391
|
-
timer,
|
|
31392
|
-
turn.signal
|
|
31393
|
-
);
|
|
32062
|
+
await execute(receipt.attemptId, turn.signal);
|
|
31394
32063
|
} finally {
|
|
31395
32064
|
activeTurns.delete(command.commandId);
|
|
31396
32065
|
if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
|
|
@@ -31469,8 +32138,50 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31469
32138
|
}
|
|
31470
32139
|
return;
|
|
31471
32140
|
}
|
|
32141
|
+
if (kind === BOT_SESSION_PROMPT_KIND) {
|
|
32142
|
+
const command = decodeBotSessionPromptCommand(delivery.payload);
|
|
32143
|
+
await processDeliveredPrompt(
|
|
32144
|
+
delivery,
|
|
32145
|
+
command,
|
|
32146
|
+
true,
|
|
32147
|
+
(attemptId, executionSignal) => executeBotPrompt(
|
|
32148
|
+
outbox,
|
|
32149
|
+
publisher,
|
|
32150
|
+
command,
|
|
32151
|
+
config2,
|
|
32152
|
+
directories,
|
|
32153
|
+
audit,
|
|
32154
|
+
sessions,
|
|
32155
|
+
grants,
|
|
32156
|
+
contexts,
|
|
32157
|
+
applicator,
|
|
32158
|
+
ipc,
|
|
32159
|
+
attemptId,
|
|
32160
|
+
timer,
|
|
32161
|
+
executionSignal
|
|
32162
|
+
)
|
|
32163
|
+
);
|
|
32164
|
+
return;
|
|
32165
|
+
}
|
|
31472
32166
|
if (kind === SESSION_PROMPT_KIND) {
|
|
31473
|
-
|
|
32167
|
+
const command = decodeSessionPromptCommand(delivery.payload);
|
|
32168
|
+
await processDeliveredPrompt(
|
|
32169
|
+
delivery,
|
|
32170
|
+
command,
|
|
32171
|
+
command.disposition !== SessionPromptDisposition.Steer,
|
|
32172
|
+
(attemptId, executionSignal) => executePrompt(
|
|
32173
|
+
outbox,
|
|
32174
|
+
publisher,
|
|
32175
|
+
command,
|
|
32176
|
+
config2,
|
|
32177
|
+
directories,
|
|
32178
|
+
audit,
|
|
32179
|
+
sessions,
|
|
32180
|
+
attemptId,
|
|
32181
|
+
timer,
|
|
32182
|
+
executionSignal
|
|
32183
|
+
)
|
|
32184
|
+
);
|
|
31474
32185
|
return;
|
|
31475
32186
|
}
|
|
31476
32187
|
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
@@ -31508,6 +32219,8 @@ async function runRelayConnection(config2, directories, audit, sessions, install
|
|
|
31508
32219
|
payloadSessionId = decodeSessionElicitationRespondCommand(delivery.payload).sessionId;
|
|
31509
32220
|
} else if (payloadKind === SESSION_PROMPT_KIND) {
|
|
31510
32221
|
payloadSessionId = decodeSessionPromptCommand(delivery.payload).sessionId;
|
|
32222
|
+
} else if (payloadKind === BOT_SESSION_PROMPT_KIND) {
|
|
32223
|
+
payloadSessionId = decodeBotSessionPromptCommand(delivery.payload).sessionId;
|
|
31511
32224
|
} else {
|
|
31512
32225
|
throw new Error("Runtime delivery contains an unsupported protocol message");
|
|
31513
32226
|
}
|
|
@@ -32105,7 +32818,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
|
|
|
32105
32818
|
}
|
|
32106
32819
|
publisher.recordAttempt(sessionId, payload, attemptId);
|
|
32107
32820
|
};
|
|
32108
|
-
const sessions = new AcpSessionManager(new DaemonAcpObserver(recordSessionEvent), sessionStore);
|
|
32821
|
+
const sessions = new AcpSessionManager(new DaemonAcpObserver(config2, recordSessionEvent), sessionStore);
|
|
32109
32822
|
const directories = new WorkspaceDirectoryService(config2.bindingId, config2.defaultWorkspace);
|
|
32110
32823
|
const installationObserver = new DaemonInstallationObserver();
|
|
32111
32824
|
const diagnostics = new RelayConnectionDiagnostics(audit, config2.channelId, config2.relayUrl);
|