@supanadit/morse-web 0.6.0 → 0.7.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/dist/server.mjs +79 -15
- package/dist/server.mjs.map +4 -4
- package/dist/ui/index.html +1 -1
- package/dist/ui/main-2MJ7PFGM.js +92 -0
- package/dist/ui/webview.manifest.json +3 -3
- package/package.json +1 -1
- package/dist/ui/main-6EMJ4WR3.js +0 -90
package/dist/server.mjs
CHANGED
|
@@ -75,7 +75,7 @@ function hasKnownType(value, allowed) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// ../protocol/dist/version.js
|
|
78
|
-
var PROTOCOL_VERSION =
|
|
78
|
+
var PROTOCOL_VERSION = 18;
|
|
79
79
|
var FRONTEND_MANIFEST_FILE = "webview.manifest.json";
|
|
80
80
|
var DEFAULT_WS_PATH = "/ws";
|
|
81
81
|
|
|
@@ -1108,14 +1108,14 @@ var PiRpcClient = class {
|
|
|
1108
1108
|
throw this.failed ?? new AgentUnavailableError("The pi agent is not running.");
|
|
1109
1109
|
}
|
|
1110
1110
|
const id = `morse-${this.nextId++}`;
|
|
1111
|
-
return new Promise((
|
|
1111
|
+
return new Promise((resolve6, reject) => {
|
|
1112
1112
|
const timer = setTimeout(() => {
|
|
1113
1113
|
this.pending.delete(id);
|
|
1114
1114
|
reject(new AgentProtocolError(`pi did not answer "${command.type}" within ${timeoutMs} ms.`));
|
|
1115
1115
|
}, timeoutMs);
|
|
1116
1116
|
this.pending.set(id, {
|
|
1117
1117
|
command: command.type,
|
|
1118
|
-
resolve: (data) =>
|
|
1118
|
+
resolve: (data) => resolve6(data),
|
|
1119
1119
|
reject,
|
|
1120
1120
|
timer
|
|
1121
1121
|
});
|
|
@@ -1134,14 +1134,14 @@ var PiRpcClient = class {
|
|
|
1134
1134
|
return;
|
|
1135
1135
|
}
|
|
1136
1136
|
let exited = false;
|
|
1137
|
-
await new Promise((
|
|
1137
|
+
await new Promise((resolve6) => {
|
|
1138
1138
|
const finish = () => {
|
|
1139
1139
|
exited = true;
|
|
1140
|
-
|
|
1140
|
+
resolve6();
|
|
1141
1141
|
};
|
|
1142
1142
|
child.once("exit", finish);
|
|
1143
1143
|
child.stdin.end();
|
|
1144
|
-
setTimeout(
|
|
1144
|
+
setTimeout(resolve6, SHUTDOWN_GRACE_MS).unref?.();
|
|
1145
1145
|
});
|
|
1146
1146
|
if (!exited) {
|
|
1147
1147
|
child.kill();
|
|
@@ -2612,6 +2612,7 @@ function noticeMessage(level, text, at) {
|
|
|
2612
2612
|
|
|
2613
2613
|
// ../host-runtime/dist/session-controller.js
|
|
2614
2614
|
var HISTORY_PAGE_SIZE = 50;
|
|
2615
|
+
var UNTITLED_SESSION = "New session";
|
|
2615
2616
|
var HostSessionController = class {
|
|
2616
2617
|
options;
|
|
2617
2618
|
summaries = /* @__PURE__ */ new Map();
|
|
@@ -3322,7 +3323,7 @@ var HostSessionController = class {
|
|
|
3322
3323
|
}
|
|
3323
3324
|
sessions.push({
|
|
3324
3325
|
id: key,
|
|
3325
|
-
title: state?.sessionTitle ?? this.derivedTitle(key) ??
|
|
3326
|
+
title: state?.sessionTitle ?? this.derivedTitle(key) ?? UNTITLED_SESSION,
|
|
3326
3327
|
cwd,
|
|
3327
3328
|
updatedAt: Date.now(),
|
|
3328
3329
|
messageCount: 0
|
|
@@ -3409,7 +3410,12 @@ var HostSessionController = class {
|
|
|
3409
3410
|
};
|
|
3410
3411
|
const state = this.activeKey === void 0 ? void 0 : this.options.services.registry.stateOf(this.activeKey);
|
|
3411
3412
|
if (state) {
|
|
3412
|
-
|
|
3413
|
+
const view = toSessionViewState(state, meta);
|
|
3414
|
+
if (view.sessionTitle === void 0 && this.activeKey !== void 0) {
|
|
3415
|
+
const catalog = this.summaries.get(this.activeKey)?.title;
|
|
3416
|
+
view.sessionTitle = catalog !== void 0 && catalog !== UNTITLED_SESSION ? catalog : this.derivedTitle(this.activeKey);
|
|
3417
|
+
}
|
|
3418
|
+
return view;
|
|
3413
3419
|
}
|
|
3414
3420
|
return draftSessionViewState(this.draftWorkspace ?? this.options.services.registry.defaultWorkspace, meta, this.draftCatalog, this.draftModel, this.draftThinking);
|
|
3415
3421
|
}
|
|
@@ -3798,10 +3804,57 @@ function shortcutRoots(options) {
|
|
|
3798
3804
|
return roots;
|
|
3799
3805
|
}
|
|
3800
3806
|
|
|
3807
|
+
// ../server/src/internal/workspace/file-store.ts
|
|
3808
|
+
import { open as open2, stat as stat4 } from "node:fs/promises";
|
|
3809
|
+
import { isAbsolute as isAbsolute5, relative as relative2, resolve as resolve5 } from "node:path";
|
|
3810
|
+
var MAX_PREVIEW_BYTES = 512 * 1024;
|
|
3811
|
+
var SNIFF_BYTES = 8 * 1024;
|
|
3812
|
+
async function readWorkspaceFile(cwd, requested) {
|
|
3813
|
+
const target = resolveWithin(cwd, requested);
|
|
3814
|
+
const info = await stat4(target).catch(() => void 0);
|
|
3815
|
+
if (info === void 0) {
|
|
3816
|
+
throw new UnsupportedByHostError(`No such file: ${requested}`);
|
|
3817
|
+
}
|
|
3818
|
+
if (info.isDirectory()) {
|
|
3819
|
+
throw new UnsupportedByHostError(`${requested} is a directory, not a file.`);
|
|
3820
|
+
}
|
|
3821
|
+
const handle = await open2(target, "r");
|
|
3822
|
+
try {
|
|
3823
|
+
const length = Math.min(info.size, MAX_PREVIEW_BYTES);
|
|
3824
|
+
const buffer = Buffer.alloc(length);
|
|
3825
|
+
const { bytesRead } = await handle.read(buffer, 0, length, 0);
|
|
3826
|
+
const slice = buffer.subarray(0, bytesRead);
|
|
3827
|
+
const binary = slice.subarray(0, Math.min(bytesRead, SNIFF_BYTES)).includes(0);
|
|
3828
|
+
return {
|
|
3829
|
+
path: toPosix(relative2(cwd, target)),
|
|
3830
|
+
content: binary ? "" : slice.toString("utf8"),
|
|
3831
|
+
size: info.size,
|
|
3832
|
+
truncated: info.size > bytesRead,
|
|
3833
|
+
binary
|
|
3834
|
+
};
|
|
3835
|
+
} finally {
|
|
3836
|
+
await handle.close();
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
function resolveWithin(cwd, requested) {
|
|
3840
|
+
if (isAbsolute5(requested)) {
|
|
3841
|
+
throw new UnsupportedByHostError("A preview only opens files inside the project.");
|
|
3842
|
+
}
|
|
3843
|
+
const target = resolve5(cwd, requested);
|
|
3844
|
+
const rel = relative2(cwd, target);
|
|
3845
|
+
if (rel.length === 0 || rel.startsWith("..") || isAbsolute5(rel)) {
|
|
3846
|
+
throw new UnsupportedByHostError("A preview only opens files inside the project.");
|
|
3847
|
+
}
|
|
3848
|
+
return target;
|
|
3849
|
+
}
|
|
3850
|
+
function toPosix(path) {
|
|
3851
|
+
return path.split("\\").join("/");
|
|
3852
|
+
}
|
|
3853
|
+
|
|
3801
3854
|
// ../server/src/internal/workspace/workspace-index.ts
|
|
3802
3855
|
import { execFile } from "node:child_process";
|
|
3803
3856
|
import { readdir as readdir4 } from "node:fs/promises";
|
|
3804
|
-
import { join as join7, relative as
|
|
3857
|
+
import { join as join7, relative as relative3 } from "node:path";
|
|
3805
3858
|
var SKIPPED_DIRECTORIES2 = /* @__PURE__ */ new Set([
|
|
3806
3859
|
"node_modules",
|
|
3807
3860
|
"dist",
|
|
@@ -3885,12 +3938,12 @@ async function gitFileList(cwd) {
|
|
|
3885
3938
|
}
|
|
3886
3939
|
}
|
|
3887
3940
|
function runGit(args, cwd) {
|
|
3888
|
-
return new Promise((
|
|
3941
|
+
return new Promise((resolve6) => {
|
|
3889
3942
|
execFile(
|
|
3890
3943
|
"git",
|
|
3891
3944
|
args,
|
|
3892
3945
|
{ cwd, timeout: 5e3, maxBuffer: 8 * 1024 * 1024, windowsHide: true },
|
|
3893
|
-
(error, stdout) =>
|
|
3946
|
+
(error, stdout) => resolve6(error ? void 0 : stdout)
|
|
3894
3947
|
);
|
|
3895
3948
|
});
|
|
3896
3949
|
}
|
|
@@ -3921,11 +3974,11 @@ async function walk(root, directory, files) {
|
|
|
3921
3974
|
continue;
|
|
3922
3975
|
}
|
|
3923
3976
|
if (entry.isFile() || entry.isSymbolicLink()) {
|
|
3924
|
-
files.push(
|
|
3977
|
+
files.push(toPosix2(relative3(root, full)));
|
|
3925
3978
|
}
|
|
3926
3979
|
}
|
|
3927
3980
|
}
|
|
3928
|
-
function
|
|
3981
|
+
function toPosix2(path) {
|
|
3929
3982
|
return path.split("\\").join("/");
|
|
3930
3983
|
}
|
|
3931
3984
|
|
|
@@ -3952,6 +4005,9 @@ var MorseSessionFactory = class {
|
|
|
3952
4005
|
// The server can walk the active session's directory, so the composer's
|
|
3953
4006
|
// `@` picker works here too — the same list VS Code offers for a workspace.
|
|
3954
4007
|
filePicker: true,
|
|
4008
|
+
// A browser has no editor of its own, so this host reads files for the
|
|
4009
|
+
// frontend's Explorer and preview tabs. VS Code keeps its native ones.
|
|
4010
|
+
filePreview: true,
|
|
3955
4011
|
// A browser cannot hand a dragged file's path to pi, so the host takes the
|
|
3956
4012
|
// bytes and writes them next to the session; the frontend then `@mentions`
|
|
3957
4013
|
// the path it gets back.
|
|
@@ -4018,6 +4074,14 @@ var MorseSessionFactory = class {
|
|
|
4018
4074
|
const files = await workspaceFiles(cwd, this.logger);
|
|
4019
4075
|
return { files };
|
|
4020
4076
|
}
|
|
4077
|
+
case "readFile": {
|
|
4078
|
+
const cwd = this.requireWritableCwd(context);
|
|
4079
|
+
const path = typeof args?.path === "string" ? args.path : "";
|
|
4080
|
+
if (path.length === 0) {
|
|
4081
|
+
throw new UnsupportedByHostError('readFile needs a "path" argument.');
|
|
4082
|
+
}
|
|
4083
|
+
return readWorkspaceFile(cwd, path);
|
|
4084
|
+
}
|
|
4021
4085
|
case "uploadFile": {
|
|
4022
4086
|
const cwd = this.requireWritableCwd(context);
|
|
4023
4087
|
const saved = await saveUpload(cwd, args ?? {}, this.config.uploadDir);
|
|
@@ -4107,7 +4171,7 @@ MorseGateway = __decorateClass([
|
|
|
4107
4171
|
], MorseGateway);
|
|
4108
4172
|
|
|
4109
4173
|
// ../server/src/app/config.ts
|
|
4110
|
-
import { basename as basename4, dirname as dirname2, isAbsolute as
|
|
4174
|
+
import { basename as basename4, dirname as dirname2, isAbsolute as isAbsolute6, join as join8 } from "node:path";
|
|
4111
4175
|
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
4112
4176
|
import { fileURLToPath } from "node:url";
|
|
4113
4177
|
function loadConfig(env = process.env) {
|
|
@@ -4118,7 +4182,7 @@ function loadConfig(env = process.env) {
|
|
|
4118
4182
|
const monorepoUiDir = join8(moduleDir, "..", "..", "..", "ui-angular", "dist");
|
|
4119
4183
|
const defaultUiDir = existsSync2(join8(bundledUiDir, "index.html")) ? bundledUiDir : monorepoUiDir;
|
|
4120
4184
|
const defaultHost = "127.0.0.1";
|
|
4121
|
-
const uiDir = configuredUiDir ?
|
|
4185
|
+
const uiDir = configuredUiDir ? isAbsolute6(configuredUiDir) ? configuredUiDir : join8(process.cwd(), configuredUiDir) : defaultUiDir;
|
|
4122
4186
|
return {
|
|
4123
4187
|
host: env.MORSE_HOST ?? defaultHost,
|
|
4124
4188
|
port: parsePositiveInt(env.MORSE_PORT, 4399),
|