cortad 0.4.5 → 0.4.6
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/lib/proxy.mjs +3 -1
- package/local.mjs +8 -3
- package/package.json +1 -1
package/lib/proxy.mjs
CHANGED
|
@@ -19,7 +19,9 @@ const { MAX, REPLY_MAX, MODEL_HOST, scrubbed, turnOf, decoded, cookieNames, make
|
|
|
19
19
|
// Where each SDK sends its calls when the app's settings name nowhere else.
|
|
20
20
|
const DEFAULTS = { OPENAI_BASE_URL: "https://api.openai.com/v1", ANTHROPIC_BASE_URL: "https://api.anthropic.com", GOOGLE_GEMINI_BASE_URL: "https://generativelanguage.googleapis.com" };
|
|
21
21
|
// Another setting of the app's that addresses a model: a URL on a model host, or a base URL named for one.
|
|
22
|
-
|
|
22
|
+
// `MODEL`: an app that names its own provider rather than an SDK's calls the setting
|
|
23
|
+
// MODEL_ENDPOINT or MODEL_URL (Helix Foundry does), and that address is the one to take over.
|
|
24
|
+
const MODEL_SETTING = /OPENAI|ANTHROPIC|GEMINI|LLM|OLLAMA|LITELLM|VLLM|MODEL/i;
|
|
23
25
|
const ADDRESS_SETTING = /BASE|URL|ENDPOINT|HOST/i;
|
|
24
26
|
const SECRET_SETTING = /KEY|TOKEN|SECRET|PASSWORD/i;
|
|
25
27
|
// Said by one connection, never passed on. A provider's reply is passed on decoded, so its encoding goes too.
|
package/local.mjs
CHANGED
|
@@ -730,12 +730,13 @@ async function startProxied(up, waitMs) {
|
|
|
730
730
|
|
|
731
731
|
async function start(waitMs) {
|
|
732
732
|
const { cmd, lifted } = launched;
|
|
733
|
+
const cmdText = commandText(cmd, appDir);
|
|
733
734
|
// The record of what the app writes opens with the app: the first run starts itself on the
|
|
734
735
|
// server's side, with no verb here to mark it, and a restart mid-run keeps the record open.
|
|
735
736
|
try { markRun(writesDirOf(homeOf(projectOf(root))), "session", { keep: true }); } catch { /* the app's writes go unrecorded */ }
|
|
736
737
|
toolsAtStart = toolsNow();
|
|
737
738
|
// Taken before the app reads a file: a save after this moment is a change it has not loaded.
|
|
738
|
-
const note = { own: true, at: Date.now(), reloads: RELOADER.test(
|
|
739
|
+
const note = { own: true, at: Date.now(), reloads: RELOADER.test(cmdText), answered: false };
|
|
739
740
|
note.files = sourceOf(root, files);
|
|
740
741
|
loaded = note;
|
|
741
742
|
// The app gets this terminal's environment, as a start by hand would, its own request limits raised
|
|
@@ -779,8 +780,12 @@ async function start(waitMs) {
|
|
|
779
780
|
const ports = await listening(mine.pid);
|
|
780
781
|
// The socket can open before the server answers; the log line is the tiebreak among several.
|
|
781
782
|
const plain = withoutStores(seen.replace(/\x1b\[[0-9;]*m/g, ""));
|
|
782
|
-
const said = [...plain.matchAll(/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1?\]):(\d{2,5})\b|\bport\s*[:=]?\s*(\d{4,5})\b/gi)].map((m) => Number(m[1] || m[2]));
|
|
783
|
-
|
|
783
|
+
const said = [...plain.matchAll(/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1?\]):(\d{2,5})\b|\bport\s*[:=]?\s*(\d{4,5})\b/gi)].map((m) => Number(m[1] || m[2])).reverse();
|
|
784
|
+
// A container publishes its port through the daemon, so nothing in this command's own process
|
|
785
|
+
// family listens on it and `ports` stays empty however long the wait runs. What the container
|
|
786
|
+
// said is then the only evidence there is, and `answers` still has to agree before it is used.
|
|
787
|
+
const alsoSaid = IN_CONTAINER.test(cmdText) ? said : [];
|
|
788
|
+
for (const port of [...new Set([...(wantedPort ? [wantedPort] : []), ...said.filter((p) => ports.includes(p)), ...ports, ...alsoSaid])]) {
|
|
784
789
|
if (await answers(port)) {
|
|
785
790
|
note.answered = true;
|
|
786
791
|
if (loaded === note) noteApp();
|
package/package.json
CHANGED