cortad 0.4.4 → 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/cli.mjs +2 -2
- package/lib/proxy.mjs +3 -1
- package/local.mjs +8 -3
- package/package.json +1 -1
package/lib/cli.mjs
CHANGED
|
@@ -105,9 +105,9 @@ const RELEASE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
|
105
105
|
// The first cortad that holds a run to a number of conversations. An older one takes the number,
|
|
106
106
|
// plays every conversation the run chose and spends the person's whole key on it, so a run it cannot
|
|
107
107
|
// hold is refused here rather than handed to it (lib/verbs.mjs run).
|
|
108
|
-
const CAP_FROM = "0.4.
|
|
108
|
+
const CAP_FROM = "0.4.5";
|
|
109
109
|
// In release order on the numbers, with a prerelease counting below the release it leads to: a
|
|
110
|
-
// 0.4.
|
|
110
|
+
// 0.4.5 build from before this is not 0.4.5. A version this cannot read counts as older, never as
|
|
111
111
|
// new enough.
|
|
112
112
|
const olderThan = (version, floor) => {
|
|
113
113
|
const parts = (v) => { const m = /^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/.exec(v); return m ? [+m[1], +m[2], +m[3], m[4] ? 0 : 1] : null; };
|
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