sootsim 0.0.1 → 0.0.2
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 +12 -0
- package/dist-cli/bin.js +16 -10
- package/dist-cli/chunks/agent-3T4BJEZM.js +61 -0
- package/dist-cli/chunks/agent-wrapper-WCYNLWHZ.js +15 -0
- package/dist-cli/chunks/assert-FPFJEFF3.js +47 -0
- package/dist-cli/chunks/auto-bootstrap-HDW6N77H.js +2 -0
- package/dist-cli/chunks/chunk-3HBBSRLE.js +2 -0
- package/dist-cli/chunks/chunk-4372UQHZ.js +308 -0
- package/dist-cli/chunks/chunk-4GWEO5CL.js +1 -0
- package/dist-cli/chunks/{chunk-G5MR66EB.js → chunk-5C5I5OFM.js} +2 -2
- package/dist-cli/chunks/chunk-6IPY24VM.js +11 -0
- package/dist-cli/chunks/chunk-AS4V7TZU.js +2 -0
- package/dist-cli/chunks/chunk-B5R4K2DG.js +5 -0
- package/dist-cli/chunks/chunk-CXTA5VGA.js +4 -0
- package/dist-cli/chunks/chunk-CZZB4DWG.js +3 -0
- package/dist-cli/chunks/chunk-DW54UPRZ.js +119 -0
- package/dist-cli/chunks/chunk-EIZCWDRE.js +1 -0
- package/dist-cli/chunks/{chunk-KSACMDXK.js → chunk-ET3NNZAR.js} +2 -2
- package/dist-cli/chunks/chunk-EWEKADK4.js +5 -0
- package/dist-cli/chunks/{chunk-JSF5LPNT.js → chunk-EWMYTXM2.js} +5 -5
- package/dist-cli/chunks/chunk-FUQ4XA6I.js +16 -0
- package/dist-cli/chunks/chunk-GQUOQNTP.js +27 -0
- package/dist-cli/chunks/chunk-HBNVKYSC.js +2 -0
- package/dist-cli/chunks/{chunk-64TOMNZX.js → chunk-HORCHQT7.js} +2 -2
- package/dist-cli/chunks/{chunk-YCETS3B3.js → chunk-ISAMAM3I.js} +2 -2
- package/dist-cli/chunks/{chunk-GPVPHE2B.js → chunk-K6YUSCAC.js} +2 -2
- package/dist-cli/chunks/{chunk-E522F5JW.js → chunk-K7LDP7JL.js} +1 -1
- package/dist-cli/chunks/chunk-KZ2LIDW6.js +2 -0
- package/dist-cli/chunks/{chunk-J2S3OCWA.js → chunk-LOV766MI.js} +1 -1
- package/dist-cli/chunks/{chunk-OROM7DZI.js → chunk-LXCFGKL2.js} +1 -1
- package/dist-cli/chunks/{chunk-PWXPA745.js → chunk-NE62JSI6.js} +1 -1
- package/dist-cli/chunks/chunk-NHA3G6A3.js +22 -0
- package/dist-cli/chunks/chunk-NXWCDGWS.js +2 -0
- package/dist-cli/chunks/{chunk-QOBRRY5X.js → chunk-RJUBGX5M.js} +1 -1
- package/dist-cli/chunks/chunk-SLCVEGTW.js +4 -0
- package/dist-cli/chunks/chunk-TGDP3D3V.js +34 -0
- package/dist-cli/chunks/chunk-TSZBQS6W.js +62 -0
- package/dist-cli/chunks/chunk-XKDQEYTE.js +1 -0
- package/dist-cli/chunks/chunk-XXUAOYYT.js +4 -0
- package/dist-cli/chunks/{chunk-7X6OPSRD.js → chunk-YVSZHVLU.js} +2 -2
- package/dist-cli/chunks/{compat-MRN2ORY5.js → compat-3HMKLGXL.js} +4 -4
- package/dist-cli/chunks/{config-CO5IYWUY.js → config-IJQ3KANN.js} +5 -5
- package/dist-cli/chunks/control-3RAFI4AW.js +2 -0
- package/dist-cli/chunks/{daemon-G4XVRFHM.js → daemon-BBEQJLRY.js} +2 -2
- package/dist-cli/chunks/{debug-ZNSZTWT6.js → debug-SGZ5ZFQI.js} +4 -4
- package/dist-cli/chunks/demo-app-registry-NCYP3WA6.js +2 -0
- package/dist-cli/chunks/{detox-JEGYNTYV.js → detox-PK74V2Y7.js} +2 -2
- package/dist-cli/chunks/{device-BS34FAFM.js → device-MWNFX54L.js} +2 -2
- package/dist-cli/chunks/drivers-EXUREU4B.js +2 -0
- package/dist-cli/chunks/electron-3NIHSU2K.js +15 -0
- package/dist-cli/chunks/flow-6Y3E6E5P.js +2 -0
- package/dist-cli/chunks/{hints-7Z656W4H.js → hints-XZJLBIXW.js} +2 -2
- package/dist-cli/chunks/home-paths-BNRMUBJA.js +2 -0
- package/dist-cli/chunks/{inspect-NAHXP2M5.js → inspect-FGTUAK4C.js} +153 -165
- package/dist-cli/chunks/install-LCXALH26.js +65 -0
- package/dist-cli/chunks/{install-desktop-PYIZIH67.js → install-desktop-U3RQ6XUX.js} +8 -4
- package/dist-cli/chunks/install-dev-desktop-BLKRFI42.js +100 -0
- package/dist-cli/chunks/keys-N5LBDSD5.js +19 -0
- package/dist-cli/chunks/launch-NIMSJH5I.js +16 -0
- package/dist-cli/chunks/{login-Z5Z54HUJ.js → login-CQV2XBRM.js} +5 -5
- package/dist-cli/chunks/{logout-T2QDYGCB.js → logout-R56NWAWQ.js} +2 -2
- package/dist-cli/chunks/{maestro-4AXTS7OE.js → maestro-ZYUVTM7H.js} +2 -2
- package/dist-cli/chunks/{preview-NMGWHWMX.js → preview-AOAWAYEQ.js} +2 -2
- package/dist-cli/chunks/{profile-6RGJA4FR.js → profile-DDADDPRW.js} +3 -3
- package/dist-cli/chunks/record-3OIOTHP6.js +37 -0
- package/dist-cli/chunks/runtime-JTLZYEXK.js +25 -0
- package/dist-cli/chunks/{screenshot-R3GCCSCI.js → screenshot-Q6N2V5LL.js} +3 -3
- package/dist-cli/chunks/screenshot-mode-WWLWJWQD.js +17 -0
- package/dist-cli/chunks/{screenshots-4UQJE4NC.js → screenshots-2JEPJGZO.js} +2 -2
- package/dist-cli/chunks/server-VH34RVAX.js +29 -0
- package/dist-cli/chunks/{skills-2PPKPL4B.js → skills-PU4627FY.js} +2 -2
- package/dist-cli/chunks/store-U2VDD2S4.js +2 -0
- package/dist-cli/chunks/{test-5LFKOQ4M.js → test-AECE56E7.js} +3 -3
- package/dist-cli/chunks/upload-KPP7KG6E.js +2 -0
- package/dist-cli/chunks/{whoami-H6FW34JS.js → whoami-NCGRRR7X.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +414 -0
- package/dist-lib/agent-events.cjs +48 -0
- package/dist-lib/agent-sessions.cjs +692 -0
- package/dist-lib/attached-projects.cjs +448 -0
- package/dist-lib/auth/shared-session.cjs +174 -0
- package/dist-lib/backend-origin.cjs +70 -0
- package/dist-lib/bridge-constants.cjs +32 -0
- package/dist-lib/cli-constants.cjs +32 -0
- package/dist-lib/config.cjs +88 -0
- package/dist-lib/dev-bundle-resolution.cjs +236 -0
- package/dist-lib/home-paths.cjs +234 -0
- package/dist-lib/host/bridge-host.cjs +3458 -0
- package/dist-lib/index.cjs +361 -0
- package/dist-lib/metro.cjs +215 -0
- package/dist-lib/render-mode.cjs +54 -0
- package/dist-lib/vite-base.cjs +4217 -0
- package/dist-lib/vite.cjs +178 -0
- package/package.json +80 -13
- package/scripts/postinstall.cjs +70 -0
- package/dist-cli/chunks/bridge-host-2EY7Z4AO.js +0 -2
- package/dist-cli/chunks/chunk-3C3ZH7PP.js +0 -4
- package/dist-cli/chunks/chunk-3R4ZZESY.js +0 -119
- package/dist-cli/chunks/chunk-74XPLOV4.js +0 -2
- package/dist-cli/chunks/chunk-7LMDCMSI.js +0 -8
- package/dist-cli/chunks/chunk-A2CZQIWO.js +0 -1
- package/dist-cli/chunks/chunk-CKZ376AY.js +0 -322
- package/dist-cli/chunks/chunk-E5UBZEYR.js +0 -2
- package/dist-cli/chunks/chunk-HOIHCO7S.js +0 -3
- package/dist-cli/chunks/chunk-KQWZZ56P.js +0 -2
- package/dist-cli/chunks/chunk-KSB6MSZ4.js +0 -34
- package/dist-cli/chunks/chunk-KXYKAYYB.js +0 -51
- package/dist-cli/chunks/chunk-MBFP2LVH.js +0 -3
- package/dist-cli/chunks/chunk-MPSZ5EWF.js +0 -16
- package/dist-cli/chunks/chunk-X2U72K7X.js +0 -1
- package/dist-cli/chunks/control-Y7TKKB6D.js +0 -2
- package/dist-cli/chunks/dev-ZUKCZQEX.js +0 -25
- package/dist-cli/chunks/dev-checkout-IEZVVTCN.js +0 -2
- package/dist-cli/chunks/drivers-46PFFIDF.js +0 -2
- package/dist-cli/chunks/electron-P2KOPX2S.js +0 -15
- package/dist-cli/chunks/flow-VVOF6UNC.js +0 -2
- package/dist-cli/chunks/install-EPUJX4AT.js +0 -67
- package/dist-cli/chunks/record-IE27Z2GA.js +0 -37
- package/dist-cli/chunks/screenshot-mode-SZQDNGYE.js +0 -17
- package/dist-cli/chunks/server-AN2G5KO4.js +0 -21
- package/dist-cli/chunks/store-PU5ES4YQ.js +0 -2
- package/dist-cli/chunks/upload-BYNPC54C.js +0 -2
- package/dist-cli/chunks/vite-plugin-5AEUUBKP.js +0 -9
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
/*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
|
+
"use strict";
|
|
4
|
+
var __create = Object.create;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
30
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
31
|
+
|
|
32
|
+
// src/attached-projects.ts
|
|
33
|
+
var attached_projects_exports = {};
|
|
34
|
+
__export(attached_projects_exports, {
|
|
35
|
+
__setUserDataDirForTests: () => __setUserDataDirForTests,
|
|
36
|
+
costThisWeek: () => costThisWeek,
|
|
37
|
+
deletePreviewAttachment: () => deletePreviewAttachment,
|
|
38
|
+
deleteProject: () => deleteProject,
|
|
39
|
+
deleteSession: () => deleteSession,
|
|
40
|
+
findProjectByBundleUrl: () => findProjectByBundleUrl,
|
|
41
|
+
findProjectByCwd: () => findProjectByCwd,
|
|
42
|
+
findProjectById: () => findProjectById,
|
|
43
|
+
findSessionById: () => findSessionById,
|
|
44
|
+
getUserDataDir: () => getUserDataDir,
|
|
45
|
+
listPreviewAttachments: () => listPreviewAttachments,
|
|
46
|
+
listProjects: () => listProjects,
|
|
47
|
+
listSessions: () => listSessions,
|
|
48
|
+
loadStore: () => loadStore,
|
|
49
|
+
mutateStore: () => mutateStore,
|
|
50
|
+
projectIdForCwd: () => projectIdForCwd,
|
|
51
|
+
recordTurnTelemetry: () => recordTurnTelemetry,
|
|
52
|
+
seedFromDemoAppRegistry: () => seedFromDemoAppRegistry,
|
|
53
|
+
setUserDataDir: () => setUserDataDir,
|
|
54
|
+
updateSessionStatus: () => updateSessionStatus,
|
|
55
|
+
upsertPreviewAttachment: () => upsertPreviewAttachment,
|
|
56
|
+
upsertProject: () => upsertProject,
|
|
57
|
+
upsertSession: () => upsertSession
|
|
58
|
+
});
|
|
59
|
+
module.exports = __toCommonJS(attached_projects_exports);
|
|
60
|
+
var import_node_crypto = require("node:crypto");
|
|
61
|
+
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
62
|
+
var import_node_os = __toESM(require("node:os"), 1);
|
|
63
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
64
|
+
var overrideDir = null;
|
|
65
|
+
function setUserDataDir(dir) {
|
|
66
|
+
overrideDir = dir;
|
|
67
|
+
}
|
|
68
|
+
var __setUserDataDirForTests = setUserDataDir;
|
|
69
|
+
function userDataDir() {
|
|
70
|
+
if (overrideDir) return overrideDir;
|
|
71
|
+
const fromEnv = process.env.SOOTSIM_USER_DATA_DIR;
|
|
72
|
+
if (fromEnv) return fromEnv;
|
|
73
|
+
try {
|
|
74
|
+
const electron = require("electron");
|
|
75
|
+
if (electron.app?.getPath) return electron.app.getPath("userData");
|
|
76
|
+
} catch {
|
|
77
|
+
}
|
|
78
|
+
return platformDefaultUserDataDir();
|
|
79
|
+
}
|
|
80
|
+
function platformDefaultUserDataDir() {
|
|
81
|
+
const home = import_node_os.default.homedir();
|
|
82
|
+
if (process.platform === "darwin") {
|
|
83
|
+
return import_node_path.default.join(home, "Library", "Application Support", "sootsim");
|
|
84
|
+
}
|
|
85
|
+
if (process.platform === "win32") {
|
|
86
|
+
return import_node_path.default.join(process.env.APPDATA || home, "sootsim");
|
|
87
|
+
}
|
|
88
|
+
const xdg = process.env.XDG_CONFIG_HOME || import_node_path.default.join(home, ".config");
|
|
89
|
+
return import_node_path.default.join(xdg, "sootsim");
|
|
90
|
+
}
|
|
91
|
+
function getUserDataDir() {
|
|
92
|
+
return userDataDir();
|
|
93
|
+
}
|
|
94
|
+
function storeFile() {
|
|
95
|
+
return import_node_path.default.join(userDataDir(), "attached-projects.json");
|
|
96
|
+
}
|
|
97
|
+
function cloneEmpty() {
|
|
98
|
+
return {
|
|
99
|
+
version: 1,
|
|
100
|
+
attachedProjects: [],
|
|
101
|
+
previewAttachments: [],
|
|
102
|
+
agentSessions: []
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function loadStore() {
|
|
106
|
+
const file = storeFile();
|
|
107
|
+
let raw;
|
|
108
|
+
try {
|
|
109
|
+
raw = import_node_fs.default.readFileSync(file, "utf8");
|
|
110
|
+
} catch (err) {
|
|
111
|
+
if (err.code === "ENOENT") return cloneEmpty();
|
|
112
|
+
throw err;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const parsed = JSON.parse(raw);
|
|
116
|
+
if (!parsed || typeof parsed !== "object") throw new Error("not an object");
|
|
117
|
+
return {
|
|
118
|
+
version: 1,
|
|
119
|
+
attachedProjects: Array.isArray(parsed.attachedProjects) ? parsed.attachedProjects : [],
|
|
120
|
+
previewAttachments: Array.isArray(parsed.previewAttachments) ? parsed.previewAttachments : [],
|
|
121
|
+
agentSessions: Array.isArray(parsed.agentSessions) ? parsed.agentSessions : []
|
|
122
|
+
};
|
|
123
|
+
} catch (err) {
|
|
124
|
+
const quarantine = `${file}.corrupt-${Date.now()}`;
|
|
125
|
+
try {
|
|
126
|
+
import_node_fs.default.renameSync(file, quarantine);
|
|
127
|
+
console.warn(
|
|
128
|
+
`[sootsim] attached-projects.json was unparseable; quarantined to ${quarantine}. original error: ${err.message}`
|
|
129
|
+
);
|
|
130
|
+
} catch {
|
|
131
|
+
}
|
|
132
|
+
return cloneEmpty();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function writeStore(store) {
|
|
136
|
+
const file = storeFile();
|
|
137
|
+
import_node_fs.default.mkdirSync(import_node_path.default.dirname(file), { recursive: true });
|
|
138
|
+
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
139
|
+
const fd = import_node_fs.default.openSync(tmp, "w", 384);
|
|
140
|
+
try {
|
|
141
|
+
import_node_fs.default.writeFileSync(fd, JSON.stringify(store, null, 2));
|
|
142
|
+
import_node_fs.default.fsyncSync(fd);
|
|
143
|
+
} finally {
|
|
144
|
+
import_node_fs.default.closeSync(fd);
|
|
145
|
+
}
|
|
146
|
+
import_node_fs.default.renameSync(tmp, file);
|
|
147
|
+
}
|
|
148
|
+
function mutateStore(fn) {
|
|
149
|
+
const store = loadStore();
|
|
150
|
+
fn(store);
|
|
151
|
+
writeStore(store);
|
|
152
|
+
return store;
|
|
153
|
+
}
|
|
154
|
+
function projectIdForCwd(cwd) {
|
|
155
|
+
return (0, import_node_crypto.createHash)("sha256").update(import_node_path.default.resolve(cwd)).digest("hex").slice(0, 16);
|
|
156
|
+
}
|
|
157
|
+
function newSessionId() {
|
|
158
|
+
return `s_${(0, import_node_crypto.randomBytes)(10).toString("hex")}`;
|
|
159
|
+
}
|
|
160
|
+
function newPreviewId() {
|
|
161
|
+
return `pa_${(0, import_node_crypto.randomBytes)(10).toString("hex")}`;
|
|
162
|
+
}
|
|
163
|
+
function upsertProject(input) {
|
|
164
|
+
const cwd = import_node_path.default.resolve(input.cwd);
|
|
165
|
+
const id = projectIdForCwd(cwd);
|
|
166
|
+
let result;
|
|
167
|
+
mutateStore((store) => {
|
|
168
|
+
const existing = store.attachedProjects.find((p) => p.id === id);
|
|
169
|
+
if (existing) {
|
|
170
|
+
const merged = {
|
|
171
|
+
...existing,
|
|
172
|
+
...input,
|
|
173
|
+
id,
|
|
174
|
+
cwd,
|
|
175
|
+
sourceRoots: input.sourceRoots ?? existing.sourceRoots,
|
|
176
|
+
knownBundleUrls: input.knownBundleUrls ?? existing.knownBundleUrls,
|
|
177
|
+
pinnedSourceResolutions: input.pinnedSourceResolutions ?? existing.pinnedSourceResolutions,
|
|
178
|
+
telemetry: input.telemetry ?? existing.telemetry,
|
|
179
|
+
updatedAt: Date.now(),
|
|
180
|
+
createdAt: existing.createdAt
|
|
181
|
+
};
|
|
182
|
+
const idx = store.attachedProjects.indexOf(existing);
|
|
183
|
+
store.attachedProjects[idx] = merged;
|
|
184
|
+
result = merged;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const now = Date.now();
|
|
188
|
+
const created = {
|
|
189
|
+
id,
|
|
190
|
+
name: input.name ?? import_node_path.default.basename(cwd),
|
|
191
|
+
cwd,
|
|
192
|
+
repoRoot: input.repoRoot,
|
|
193
|
+
sourceRoots: input.sourceRoots ?? [cwd],
|
|
194
|
+
framework: input.framework ?? "unknown",
|
|
195
|
+
bundleId: input.bundleId,
|
|
196
|
+
knownBundleUrls: input.knownBundleUrls ?? [],
|
|
197
|
+
preferredProvider: input.preferredProvider ?? "codex",
|
|
198
|
+
preferredTransport: input.preferredTransport ?? "tmux",
|
|
199
|
+
editorOpenCommand: input.editorOpenCommand,
|
|
200
|
+
moshiWebhookToken: input.moshiWebhookToken,
|
|
201
|
+
pinnedSourceResolutions: input.pinnedSourceResolutions ?? {},
|
|
202
|
+
isolateDiscovery: input.isolateDiscovery,
|
|
203
|
+
git: input.git,
|
|
204
|
+
telemetry: input.telemetry ?? { lastOpened: 0, runsCompleted: 0 },
|
|
205
|
+
createdAt: now,
|
|
206
|
+
updatedAt: now
|
|
207
|
+
};
|
|
208
|
+
store.attachedProjects.push(created);
|
|
209
|
+
result = created;
|
|
210
|
+
});
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
function findProjectById(id) {
|
|
214
|
+
return loadStore().attachedProjects.find((p) => p.id === id) ?? null;
|
|
215
|
+
}
|
|
216
|
+
function findProjectByCwd(cwd) {
|
|
217
|
+
const resolved = import_node_path.default.resolve(cwd);
|
|
218
|
+
return loadStore().attachedProjects.find((p) => p.cwd === resolved) ?? null;
|
|
219
|
+
}
|
|
220
|
+
function findProjectByBundleUrl(bundleUrl) {
|
|
221
|
+
const store = loadStore();
|
|
222
|
+
const exact = store.attachedProjects.find((p) => p.knownBundleUrls.includes(bundleUrl));
|
|
223
|
+
if (exact) return exact;
|
|
224
|
+
const base = stripQuery(bundleUrl);
|
|
225
|
+
return store.attachedProjects.find(
|
|
226
|
+
(p) => p.knownBundleUrls.some((u) => stripQuery(u) === base)
|
|
227
|
+
) ?? null;
|
|
228
|
+
}
|
|
229
|
+
function stripQuery(url) {
|
|
230
|
+
const q = url.indexOf("?");
|
|
231
|
+
return q >= 0 ? url.slice(0, q) : url;
|
|
232
|
+
}
|
|
233
|
+
function listProjects() {
|
|
234
|
+
return loadStore().attachedProjects;
|
|
235
|
+
}
|
|
236
|
+
var COST_HISTORY_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
237
|
+
function recordTurnTelemetry(projectId, input = {}) {
|
|
238
|
+
mutateStore((store) => {
|
|
239
|
+
const project = store.attachedProjects.find((p) => p.id === projectId);
|
|
240
|
+
if (!project) return;
|
|
241
|
+
const ts = input.ts ?? Date.now();
|
|
242
|
+
project.telemetry.runsCompleted = (project.telemetry.runsCompleted ?? 0) + 1;
|
|
243
|
+
if (typeof input.usd === "number" && Number.isFinite(input.usd) && input.usd >= 0) {
|
|
244
|
+
const history = project.telemetry.costHistory ?? [];
|
|
245
|
+
const cutoff = ts - COST_HISTORY_MAX_AGE_MS;
|
|
246
|
+
const trimmed = history.filter((e) => e.ts >= cutoff);
|
|
247
|
+
trimmed.push({ ts, usd: input.usd });
|
|
248
|
+
project.telemetry.costHistory = trimmed;
|
|
249
|
+
}
|
|
250
|
+
project.updatedAt = ts;
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
function costThisWeek(project, now = Date.now()) {
|
|
254
|
+
const cutoff = now - 7 * 24 * 60 * 60 * 1e3;
|
|
255
|
+
const history = project.telemetry.costHistory ?? [];
|
|
256
|
+
let total = 0;
|
|
257
|
+
for (const e of history) {
|
|
258
|
+
if (e.ts >= cutoff) total += e.usd;
|
|
259
|
+
}
|
|
260
|
+
return total;
|
|
261
|
+
}
|
|
262
|
+
function deleteProject(id) {
|
|
263
|
+
mutateStore((store) => {
|
|
264
|
+
store.attachedProjects = store.attachedProjects.filter((p) => p.id !== id);
|
|
265
|
+
store.agentSessions = store.agentSessions.filter((s) => s.projectId !== id);
|
|
266
|
+
store.previewAttachments = store.previewAttachments.filter(
|
|
267
|
+
(pa) => pa.projectId !== id
|
|
268
|
+
);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
function upsertSession(input) {
|
|
272
|
+
let result;
|
|
273
|
+
mutateStore((store) => {
|
|
274
|
+
if (input.id) {
|
|
275
|
+
const existing = store.agentSessions.find((s) => s.id === input.id);
|
|
276
|
+
if (existing) {
|
|
277
|
+
const merged = {
|
|
278
|
+
...existing,
|
|
279
|
+
...input,
|
|
280
|
+
lastSeenAt: Date.now()
|
|
281
|
+
};
|
|
282
|
+
const idx = store.agentSessions.indexOf(existing);
|
|
283
|
+
store.agentSessions[idx] = merged;
|
|
284
|
+
result = merged;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const project = store.attachedProjects.find((p) => p.id === input.projectId);
|
|
289
|
+
if (!project) {
|
|
290
|
+
throw new Error(`upsertSession: no AttachedProject with id=${input.projectId}`);
|
|
291
|
+
}
|
|
292
|
+
const now = Date.now();
|
|
293
|
+
const created = {
|
|
294
|
+
id: input.id ?? newSessionId(),
|
|
295
|
+
projectId: input.projectId,
|
|
296
|
+
provider: input.provider,
|
|
297
|
+
transport: input.transport ?? project.preferredTransport,
|
|
298
|
+
cwd: input.cwd ?? project.cwd,
|
|
299
|
+
claudeSessionUuid: input.claudeSessionUuid,
|
|
300
|
+
tmuxSessionName: input.tmuxSessionName,
|
|
301
|
+
wrapperPid: input.wrapperPid,
|
|
302
|
+
status: input.status ?? "idle",
|
|
303
|
+
needsAttention: input.needsAttention ?? false,
|
|
304
|
+
lastPrompt: input.lastPrompt,
|
|
305
|
+
lastSummary: input.lastSummary,
|
|
306
|
+
lastTurnFiles: input.lastTurnFiles,
|
|
307
|
+
currentlyEditing: input.currentlyEditing,
|
|
308
|
+
lastSeenAt: now,
|
|
309
|
+
createdAt: now
|
|
310
|
+
};
|
|
311
|
+
store.agentSessions.push(created);
|
|
312
|
+
result = created;
|
|
313
|
+
});
|
|
314
|
+
return result;
|
|
315
|
+
}
|
|
316
|
+
function findSessionById(id) {
|
|
317
|
+
return loadStore().agentSessions.find((s) => s.id === id) ?? null;
|
|
318
|
+
}
|
|
319
|
+
function listSessions(projectId) {
|
|
320
|
+
const all = loadStore().agentSessions;
|
|
321
|
+
return projectId ? all.filter((s) => s.projectId === projectId) : all;
|
|
322
|
+
}
|
|
323
|
+
function updateSessionStatus(id, patch) {
|
|
324
|
+
mutateStore((store) => {
|
|
325
|
+
const existing = store.agentSessions.find((s) => s.id === id);
|
|
326
|
+
if (!existing) return;
|
|
327
|
+
const idx = store.agentSessions.indexOf(existing);
|
|
328
|
+
store.agentSessions[idx] = {
|
|
329
|
+
...existing,
|
|
330
|
+
...patch,
|
|
331
|
+
id: existing.id,
|
|
332
|
+
projectId: existing.projectId,
|
|
333
|
+
createdAt: existing.createdAt,
|
|
334
|
+
lastSeenAt: Date.now()
|
|
335
|
+
};
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
function deleteSession(id) {
|
|
339
|
+
mutateStore((store) => {
|
|
340
|
+
store.agentSessions = store.agentSessions.filter((s) => s.id !== id);
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
function upsertPreviewAttachment(input) {
|
|
344
|
+
let result;
|
|
345
|
+
mutateStore((store) => {
|
|
346
|
+
const existing = store.previewAttachments.find(
|
|
347
|
+
(pa) => pa.bundleUrl === input.bundleUrl && pa.browserId === input.browserId
|
|
348
|
+
);
|
|
349
|
+
if (existing) {
|
|
350
|
+
const merged = {
|
|
351
|
+
...existing,
|
|
352
|
+
...input,
|
|
353
|
+
lastSeenAt: Date.now()
|
|
354
|
+
};
|
|
355
|
+
const idx = store.previewAttachments.indexOf(existing);
|
|
356
|
+
store.previewAttachments[idx] = merged;
|
|
357
|
+
result = merged;
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
const created = {
|
|
361
|
+
id: input.id ?? newPreviewId(),
|
|
362
|
+
projectId: input.projectId ?? null,
|
|
363
|
+
bundleUrl: input.bundleUrl,
|
|
364
|
+
browserId: input.browserId,
|
|
365
|
+
deviceModel: input.deviceModel ?? "unknown",
|
|
366
|
+
status: input.status ?? "connecting",
|
|
367
|
+
lastSeenAt: Date.now()
|
|
368
|
+
};
|
|
369
|
+
store.previewAttachments.push(created);
|
|
370
|
+
result = created;
|
|
371
|
+
});
|
|
372
|
+
return result;
|
|
373
|
+
}
|
|
374
|
+
function listPreviewAttachments(projectId) {
|
|
375
|
+
const all = loadStore().previewAttachments;
|
|
376
|
+
return projectId ? all.filter((pa) => pa.projectId === projectId) : all;
|
|
377
|
+
}
|
|
378
|
+
function deletePreviewAttachment(id) {
|
|
379
|
+
mutateStore((store) => {
|
|
380
|
+
store.previewAttachments = store.previewAttachments.filter((pa) => pa.id !== id);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
async function seedFromDemoAppRegistry() {
|
|
384
|
+
const existing = loadStore().attachedProjects;
|
|
385
|
+
if (existing.length > 0) return;
|
|
386
|
+
let APPS;
|
|
387
|
+
try {
|
|
388
|
+
const mod = await import("sootsim/scripts/demo-app-registry");
|
|
389
|
+
APPS = mod.APPS;
|
|
390
|
+
} catch (err) {
|
|
391
|
+
console.warn(
|
|
392
|
+
"[sootsim] seedFromDemoAppRegistry: could not load demo registry:",
|
|
393
|
+
err.message
|
|
394
|
+
);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (!Array.isArray(APPS)) return;
|
|
398
|
+
const apps = APPS;
|
|
399
|
+
mutateStore((store) => {
|
|
400
|
+
for (const app of apps) {
|
|
401
|
+
if (!import_node_fs.default.existsSync(app.dir)) continue;
|
|
402
|
+
const cwd = import_node_path.default.resolve(app.dir);
|
|
403
|
+
const id = projectIdForCwd(cwd);
|
|
404
|
+
if (store.attachedProjects.some((p) => p.id === id)) continue;
|
|
405
|
+
const now = Date.now();
|
|
406
|
+
store.attachedProjects.push({
|
|
407
|
+
id,
|
|
408
|
+
name: app.label,
|
|
409
|
+
cwd,
|
|
410
|
+
sourceRoots: [cwd],
|
|
411
|
+
framework: app.framework,
|
|
412
|
+
knownBundleUrls: [`http://localhost:${app.preferredPort}/index.bundle`],
|
|
413
|
+
preferredProvider: "codex",
|
|
414
|
+
preferredTransport: "tmux",
|
|
415
|
+
pinnedSourceResolutions: {},
|
|
416
|
+
telemetry: { lastOpened: 0, runsCompleted: 0 },
|
|
417
|
+
createdAt: now,
|
|
418
|
+
updatedAt: now
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
424
|
+
0 && (module.exports = {
|
|
425
|
+
__setUserDataDirForTests,
|
|
426
|
+
costThisWeek,
|
|
427
|
+
deletePreviewAttachment,
|
|
428
|
+
deleteProject,
|
|
429
|
+
deleteSession,
|
|
430
|
+
findProjectByBundleUrl,
|
|
431
|
+
findProjectByCwd,
|
|
432
|
+
findProjectById,
|
|
433
|
+
findSessionById,
|
|
434
|
+
getUserDataDir,
|
|
435
|
+
listPreviewAttachments,
|
|
436
|
+
listProjects,
|
|
437
|
+
listSessions,
|
|
438
|
+
loadStore,
|
|
439
|
+
mutateStore,
|
|
440
|
+
projectIdForCwd,
|
|
441
|
+
recordTurnTelemetry,
|
|
442
|
+
seedFromDemoAppRegistry,
|
|
443
|
+
setUserDataDir,
|
|
444
|
+
updateSessionStatus,
|
|
445
|
+
upsertPreviewAttachment,
|
|
446
|
+
upsertProject,
|
|
447
|
+
upsertSession
|
|
448
|
+
});
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
|
+
"use strict";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/auth/shared-session.ts
|
|
23
|
+
var shared_session_exports = {};
|
|
24
|
+
__export(shared_session_exports, {
|
|
25
|
+
clearSharedDesktopAuthSession: () => clearSharedDesktopAuthSession,
|
|
26
|
+
getSharedDesktopAuthFilePath: () => getSharedDesktopAuthFilePath,
|
|
27
|
+
readSharedDesktopAuthSession: () => readSharedDesktopAuthSession,
|
|
28
|
+
refreshSharedDesktopAuthSession: () => refreshSharedDesktopAuthSession,
|
|
29
|
+
writeSharedDesktopAuthSession: () => writeSharedDesktopAuthSession
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(shared_session_exports);
|
|
32
|
+
var import_node_fs = require("node:fs");
|
|
33
|
+
var import_node_os = require("node:os");
|
|
34
|
+
var import_node_path = require("node:path");
|
|
35
|
+
var SESSION_VERSION = 1;
|
|
36
|
+
var SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
|
|
37
|
+
var DEFAULT_ORIGIN = "https://sootbean.com";
|
|
38
|
+
function getBaseDir() {
|
|
39
|
+
const explicit = process.env[SESSION_FILE_ENV];
|
|
40
|
+
if (explicit?.trim()) {
|
|
41
|
+
return (0, import_node_path.dirname)((0, import_node_path.resolve)(explicit));
|
|
42
|
+
}
|
|
43
|
+
const home = (0, import_node_os.homedir)();
|
|
44
|
+
if (!home) {
|
|
45
|
+
throw new Error("could not determine home directory for sootsim auth storage");
|
|
46
|
+
}
|
|
47
|
+
switch ((0, import_node_os.platform)()) {
|
|
48
|
+
case "darwin":
|
|
49
|
+
return (0, import_node_path.join)(home, "Library", "Application Support", "sootsim");
|
|
50
|
+
case "win32":
|
|
51
|
+
return (0, import_node_path.join)(process.env.APPDATA || (0, import_node_path.join)(home, "AppData", "Roaming"), "sootsim");
|
|
52
|
+
case "aix":
|
|
53
|
+
case "android":
|
|
54
|
+
case "cygwin":
|
|
55
|
+
case "freebsd":
|
|
56
|
+
case "haiku":
|
|
57
|
+
case "linux":
|
|
58
|
+
case "netbsd":
|
|
59
|
+
case "openbsd":
|
|
60
|
+
case "sunos":
|
|
61
|
+
default:
|
|
62
|
+
return (0, import_node_path.join)(process.env.XDG_CONFIG_HOME || (0, import_node_path.join)(home, ".config"), "sootsim");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function getSharedDesktopAuthFilePath() {
|
|
66
|
+
const explicit = process.env[SESSION_FILE_ENV];
|
|
67
|
+
if (explicit?.trim()) return (0, import_node_path.resolve)(explicit);
|
|
68
|
+
return (0, import_node_path.join)(getBaseDir(), "desktop-auth.json");
|
|
69
|
+
}
|
|
70
|
+
function normalizeUser(input) {
|
|
71
|
+
if (!input || typeof input !== "object") return null;
|
|
72
|
+
const value = input;
|
|
73
|
+
if (typeof value.id !== "string" || !value.id.trim()) return null;
|
|
74
|
+
return {
|
|
75
|
+
id: value.id.trim(),
|
|
76
|
+
name: typeof value.name === "string" ? value.name : void 0,
|
|
77
|
+
email: typeof value.email === "string" ? value.email : void 0,
|
|
78
|
+
image: typeof value.image === "string" ? value.image : void 0
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function normalizeSession(input) {
|
|
82
|
+
if (!input || typeof input !== "object") return null;
|
|
83
|
+
const value = input;
|
|
84
|
+
if (value.version !== SESSION_VERSION) return null;
|
|
85
|
+
if (typeof value.token !== "string" || !value.token.trim()) return null;
|
|
86
|
+
const origin = typeof value.origin === "string" && value.origin.trim() ? value.origin.trim() : DEFAULT_ORIGIN;
|
|
87
|
+
const source = value.source === "cli" || value.source === "electron" || value.source === "browser" || value.source === "unknown" ? value.source : "unknown";
|
|
88
|
+
const updatedAt = typeof value.updatedAt === "string" && value.updatedAt ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
89
|
+
const validatedAt = typeof value.validatedAt === "string" && value.validatedAt ? value.validatedAt : void 0;
|
|
90
|
+
return {
|
|
91
|
+
version: SESSION_VERSION,
|
|
92
|
+
token: value.token.trim(),
|
|
93
|
+
user: normalizeUser(value.user),
|
|
94
|
+
origin,
|
|
95
|
+
source,
|
|
96
|
+
updatedAt,
|
|
97
|
+
validatedAt
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function readSharedDesktopAuthSession() {
|
|
101
|
+
const filepath = getSharedDesktopAuthFilePath();
|
|
102
|
+
if (!(0, import_node_fs.existsSync)(filepath)) return null;
|
|
103
|
+
try {
|
|
104
|
+
const parsed = JSON.parse((0, import_node_fs.readFileSync)(filepath, "utf8"));
|
|
105
|
+
const normalized = normalizeSession(parsed);
|
|
106
|
+
if (!normalized) {
|
|
107
|
+
(0, import_node_fs.rmSync)(filepath, { force: true });
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return normalized;
|
|
111
|
+
} catch {
|
|
112
|
+
(0, import_node_fs.rmSync)(filepath, { force: true });
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function writeSharedDesktopAuthSession(session) {
|
|
117
|
+
const filepath = getSharedDesktopAuthFilePath();
|
|
118
|
+
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(filepath), { recursive: true });
|
|
119
|
+
const normalized = {
|
|
120
|
+
version: SESSION_VERSION,
|
|
121
|
+
token: session.token.trim(),
|
|
122
|
+
user: session.user ? normalizeUser(session.user) : null,
|
|
123
|
+
origin: session.origin?.trim() || DEFAULT_ORIGIN,
|
|
124
|
+
source: session.source,
|
|
125
|
+
updatedAt: session.updatedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
126
|
+
validatedAt: session.validatedAt
|
|
127
|
+
};
|
|
128
|
+
(0, import_node_fs.writeFileSync)(filepath, JSON.stringify(normalized, null, 2) + "\n");
|
|
129
|
+
try {
|
|
130
|
+
(0, import_node_fs.chmodSync)(filepath, 384);
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
return normalized;
|
|
134
|
+
}
|
|
135
|
+
function clearSharedDesktopAuthSession() {
|
|
136
|
+
(0, import_node_fs.rmSync)(getSharedDesktopAuthFilePath(), { force: true });
|
|
137
|
+
}
|
|
138
|
+
async function refreshSharedDesktopAuthSession(originOverride) {
|
|
139
|
+
const current = readSharedDesktopAuthSession();
|
|
140
|
+
if (!current?.token) return null;
|
|
141
|
+
const origin = originOverride || current.origin || DEFAULT_ORIGIN;
|
|
142
|
+
try {
|
|
143
|
+
const res = await fetch(`${origin.replace(/\/$/, "")}/api/auth/me`, {
|
|
144
|
+
headers: { authorization: `Bearer ${current.token}` }
|
|
145
|
+
});
|
|
146
|
+
if (res.status === 401) {
|
|
147
|
+
clearSharedDesktopAuthSession();
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
if (!res.ok) return current;
|
|
151
|
+
const data = await res.json();
|
|
152
|
+
if (!data.user?.id) {
|
|
153
|
+
clearSharedDesktopAuthSession();
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
return writeSharedDesktopAuthSession({
|
|
157
|
+
token: current.token,
|
|
158
|
+
user: data.user,
|
|
159
|
+
origin,
|
|
160
|
+
source: current.source,
|
|
161
|
+
validatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
162
|
+
});
|
|
163
|
+
} catch {
|
|
164
|
+
return current;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
168
|
+
0 && (module.exports = {
|
|
169
|
+
clearSharedDesktopAuthSession,
|
|
170
|
+
getSharedDesktopAuthFilePath,
|
|
171
|
+
readSharedDesktopAuthSession,
|
|
172
|
+
refreshSharedDesktopAuthSession,
|
|
173
|
+
writeSharedDesktopAuthSession
|
|
174
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
|
+
"use strict";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/backend-origin.ts
|
|
23
|
+
var backend_origin_exports = {};
|
|
24
|
+
__export(backend_origin_exports, {
|
|
25
|
+
DEFAULT_SOOT_BACKEND_ORIGIN: () => DEFAULT_SOOT_BACKEND_ORIGIN,
|
|
26
|
+
isLoopbackHost: () => isLoopbackHost,
|
|
27
|
+
isSootBackendHost: () => isSootBackendHost,
|
|
28
|
+
isSootBackendOrigin: () => isSootBackendOrigin,
|
|
29
|
+
resolveSootBackendOrigin: () => resolveSootBackendOrigin
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(backend_origin_exports);
|
|
32
|
+
var DEFAULT_SOOT_BACKEND_ORIGIN = "https://sootbean.com";
|
|
33
|
+
function normalizeHostname(hostname) {
|
|
34
|
+
return hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
function isLoopbackHost(hostname) {
|
|
37
|
+
const normalized = normalizeHostname(hostname);
|
|
38
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
39
|
+
}
|
|
40
|
+
function isSootBackendHost(hostname) {
|
|
41
|
+
const normalized = normalizeHostname(hostname);
|
|
42
|
+
return isLoopbackHost(normalized) || normalized === "sootbean.com" || normalized.endsWith(".sootbean.com");
|
|
43
|
+
}
|
|
44
|
+
function isSootBackendOrigin(origin) {
|
|
45
|
+
try {
|
|
46
|
+
return isSootBackendHost(new URL(origin).hostname);
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function resolveSootBackendOrigin(currentOrigin) {
|
|
52
|
+
const origin = currentOrigin?.trim();
|
|
53
|
+
if (!origin) return DEFAULT_SOOT_BACKEND_ORIGIN;
|
|
54
|
+
try {
|
|
55
|
+
const parsed = new URL(origin);
|
|
56
|
+
if (isLoopbackHost(parsed.hostname) || isSootBackendHost(parsed.hostname)) {
|
|
57
|
+
return parsed.origin;
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
return DEFAULT_SOOT_BACKEND_ORIGIN;
|
|
62
|
+
}
|
|
63
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
+
0 && (module.exports = {
|
|
65
|
+
DEFAULT_SOOT_BACKEND_ORIGIN,
|
|
66
|
+
isLoopbackHost,
|
|
67
|
+
isSootBackendHost,
|
|
68
|
+
isSootBackendOrigin,
|
|
69
|
+
resolveSootBackendOrigin
|
|
70
|
+
});
|