atlarix 15.2.0 → 15.4.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.
|
@@ -81,11 +81,19 @@ function getRegisteredHandler(channel) {
|
|
|
81
81
|
return handlers.get(channel);
|
|
82
82
|
}
|
|
83
83
|
function attachCliWindow(send) {
|
|
84
|
+
cliSenders.add(send);
|
|
85
|
+
const detach = () => {
|
|
86
|
+
cliSenders.delete(send);
|
|
87
|
+
if (cliSenders.size === 0) cliWindow = null;
|
|
88
|
+
};
|
|
89
|
+
if (cliWindow) return detach;
|
|
84
90
|
const webContents = {
|
|
85
91
|
id: 1,
|
|
86
92
|
isDestroyed: () => false,
|
|
87
93
|
isCrashed: () => false,
|
|
88
|
-
send
|
|
94
|
+
send: (channel, payload) => {
|
|
95
|
+
for (const s3 of [...cliSenders]) s3(channel, payload);
|
|
96
|
+
}
|
|
89
97
|
};
|
|
90
98
|
cliWindow = {
|
|
91
99
|
id: 1,
|
|
@@ -97,11 +105,12 @@ function attachCliWindow(send) {
|
|
|
97
105
|
focus: noop,
|
|
98
106
|
show: noop
|
|
99
107
|
};
|
|
108
|
+
return detach;
|
|
100
109
|
}
|
|
101
110
|
function setSafeStorageImpl(impl) {
|
|
102
111
|
safeStorageImpl = impl;
|
|
103
112
|
}
|
|
104
|
-
var handlers, ipcMain, userDataBase, noop, app, BrowserWindow, cliWindow, safeStorageImpl, safeStorage, dialog, shell, clipboard, nativeTheme, powerMonitor, powerSaveBlocker, session, Menu, Notification, contextBridge, ipcRenderer, webFrame, WebContentsView, electron_stub_default;
|
|
113
|
+
var handlers, ipcMain, userDataBase, noop, app, BrowserWindow, cliWindow, cliSenders, safeStorageImpl, safeStorage, dialog, shell, clipboard, nativeTheme, powerMonitor, powerSaveBlocker, session, Menu, Notification, contextBridge, ipcRenderer, webFrame, WebContentsView, electron_stub_default;
|
|
105
114
|
var init_electron_stub = __esm({
|
|
106
115
|
"src/headless/electron-stub.ts"() {
|
|
107
116
|
handlers = /* @__PURE__ */ new Map();
|
|
@@ -140,6 +149,7 @@ var init_electron_stub = __esm({
|
|
|
140
149
|
fromId: () => null
|
|
141
150
|
};
|
|
142
151
|
cliWindow = null;
|
|
152
|
+
cliSenders = /* @__PURE__ */ new Set();
|
|
143
153
|
safeStorageImpl = {
|
|
144
154
|
isEncryptionAvailable: () => false,
|
|
145
155
|
encryptString: (s3) => Buffer.from(s3, "utf8"),
|
|
@@ -27345,6 +27355,8 @@ var init_schemas3 = __esm({
|
|
|
27345
27355
|
voiceTranscriptionProvider: external_exports.string().optional(),
|
|
27346
27356
|
/** Messages from the user's other Atlarix sessions: delivered, or refused. Unset = accept. */
|
|
27347
27357
|
peerMessages: external_exports.enum(["accept", "refuse"]).optional(),
|
|
27358
|
+
/** A one-line recap when the user comes back to a session after a few minutes away. Unset = on. */
|
|
27359
|
+
sessionRecap: external_exports.boolean().optional(),
|
|
27348
27360
|
// `voiceInputMode` REMOVED. Its "live" value streamed a re-transcription of a
|
|
27349
27361
|
// growing buffer every 1.5s, which was only viable against the local WebGPU
|
|
27350
27362
|
// pipeline; against a metered API it would bill every 1.5s for the same audio.
|
|
@@ -67729,7 +67741,7 @@ var require_cross_spawn = __commonJS({
|
|
|
67729
67741
|
var cp = __require("child_process");
|
|
67730
67742
|
var parse4 = require_parse();
|
|
67731
67743
|
var enoent = require_enoent();
|
|
67732
|
-
function
|
|
67744
|
+
function spawn6(command, args2, options) {
|
|
67733
67745
|
const parsed = parse4(command, args2, options);
|
|
67734
67746
|
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
|
67735
67747
|
enoent.hookChildProcess(spawned, parsed);
|
|
@@ -67741,8 +67753,8 @@ var require_cross_spawn = __commonJS({
|
|
|
67741
67753
|
result2.error = result2.error || enoent.verifyENOENTSync(result2.status, parsed);
|
|
67742
67754
|
return result2;
|
|
67743
67755
|
}
|
|
67744
|
-
module2.exports =
|
|
67745
|
-
module2.exports.spawn =
|
|
67756
|
+
module2.exports = spawn6;
|
|
67757
|
+
module2.exports.spawn = spawn6;
|
|
67746
67758
|
module2.exports.sync = spawnSync3;
|
|
67747
67759
|
module2.exports._parse = parse4;
|
|
67748
67760
|
module2.exports._enoent = enoent;
|
|
@@ -147390,12 +147402,12 @@ var require_oauth2client = __commonJS({
|
|
|
147390
147402
|
throw new Error("Expiration time too far in future: " + JSON.stringify(payload));
|
|
147391
147403
|
}
|
|
147392
147404
|
const earliest = iat - _OAuth2Client.CLOCK_SKEW_SECS_;
|
|
147393
|
-
const
|
|
147405
|
+
const latest2 = exp + _OAuth2Client.CLOCK_SKEW_SECS_;
|
|
147394
147406
|
if (now2 < earliest) {
|
|
147395
147407
|
throw new Error("Token used too early, " + now2 + " < " + earliest + ": " + JSON.stringify(payload));
|
|
147396
147408
|
}
|
|
147397
|
-
if (now2 >
|
|
147398
|
-
throw new Error("Token used too late, " + now2 + " > " +
|
|
147409
|
+
if (now2 > latest2) {
|
|
147410
|
+
throw new Error("Token used too late, " + now2 + " > " + latest2 + ": " + JSON.stringify(payload));
|
|
147399
147411
|
}
|
|
147400
147412
|
if (issuers && issuers.indexOf(payload.iss) < 0) {
|
|
147401
147413
|
throw new Error("Invalid issuer, expected one of [" + issuers + "], but got " + payload.iss);
|
|
@@ -192238,6 +192250,7 @@ function autoStatusFromHeaders(headers) {
|
|
|
192238
192250
|
function broadcastAutoStatus(headers) {
|
|
192239
192251
|
const status = autoStatusFromHeaders(headers);
|
|
192240
192252
|
if (!status) return;
|
|
192253
|
+
latest = status;
|
|
192241
192254
|
void noteAutoBilling(status.billing);
|
|
192242
192255
|
import_electron_log17.default.scope("atlarix-auto").info(
|
|
192243
192256
|
`Auto reply: billing=${status.billing ?? "?"} model=${status.servedModel ?? "?"}`
|
|
@@ -192246,13 +192259,14 @@ function broadcastAutoStatus(headers) {
|
|
|
192246
192259
|
if (!win.isDestroyed()) safeSend(win.webContents, "core:auto-status", status);
|
|
192247
192260
|
}
|
|
192248
192261
|
}
|
|
192249
|
-
var import_electron_log17;
|
|
192262
|
+
var import_electron_log17, latest;
|
|
192250
192263
|
var init_auto_status = __esm({
|
|
192251
192264
|
"src/main/auto-status.ts"() {
|
|
192252
192265
|
init_electron_stub();
|
|
192253
192266
|
import_electron_log17 = __toESM(require_src());
|
|
192254
192267
|
init_safe_sender();
|
|
192255
192268
|
init_auto_context_window();
|
|
192269
|
+
latest = null;
|
|
192256
192270
|
}
|
|
192257
192271
|
});
|
|
192258
192272
|
|
|
@@ -212134,7 +212148,7 @@ function getPostHog() {
|
|
|
212134
212148
|
if (client) return client;
|
|
212135
212149
|
const apiKey = process.env.POSTHOG_API_KEY;
|
|
212136
212150
|
if (!apiKey) return null;
|
|
212137
|
-
client = new PostHog(apiKey, { host: POSTHOG_HOST });
|
|
212151
|
+
client = new PostHog(apiKey, { host: POSTHOG_HOST, disableGeoip: false });
|
|
212138
212152
|
return client;
|
|
212139
212153
|
}
|
|
212140
212154
|
function resolveDistinctId() {
|
|
@@ -237597,7 +237611,7 @@ function isOnlyToolDebris(content) {
|
|
|
237597
237611
|
stripToolJsonLinesFromMarkdown(stripOrphanToolTagFragments(content))
|
|
237598
237612
|
).trim();
|
|
237599
237613
|
if (!stripped) return true;
|
|
237600
|
-
if (/^[\s\]},":\d._-]+$/.test(stripped)) return true;
|
|
237614
|
+
if (/^[\s\]},":\d._-]+$/.test(stripped) && /[\]}"]/.test(stripped)) return true;
|
|
237601
237615
|
if (/^"?,?\s*"message"\s*:/.test(stripped)) return true;
|
|
237602
237616
|
if (/^\{\s*"success"\s*:/.test(stripped)) return true;
|
|
237603
237617
|
const lines = stripped.split("\n").filter((l3) => l3.trim());
|
|
@@ -238276,7 +238290,7 @@ var init_framing = __esm({
|
|
|
238276
238290
|
|
|
238277
238291
|
// src/lib/peers/peer-message.ts
|
|
238278
238292
|
function peerSurfaceLabel(surface2) {
|
|
238279
|
-
return surface2 === "cli" ? "CLI" : surface2 === "chrome" ? "browser" : "app";
|
|
238293
|
+
return surface2 === "cli" ? "CLI" : surface2 === "chrome" ? "browser" : surface2 === "editor" ? "editor" : "app";
|
|
238280
238294
|
}
|
|
238281
238295
|
var init_peer_message = __esm({
|
|
238282
238296
|
"src/lib/peers/peer-message.ts"() {
|
|
@@ -238373,7 +238387,7 @@ function publish() {
|
|
|
238373
238387
|
host,
|
|
238374
238388
|
peerSocketPath(),
|
|
238375
238389
|
token,
|
|
238376
|
-
surface === "app" ? "Atlarix app" : "Atlarix CLI",
|
|
238390
|
+
surface === "app" ? "Atlarix app" : surface === "editor" ? "Atlarix in an editor" : "Atlarix CLI",
|
|
238377
238391
|
"",
|
|
238378
238392
|
surface,
|
|
238379
238393
|
0,
|
|
@@ -238409,6 +238423,11 @@ function noteLiveSession(s3) {
|
|
|
238409
238423
|
local.set(s3.sessionId, s3);
|
|
238410
238424
|
if (!prev || prev.name !== s3.name || prev.chatId !== s3.chatId) publish();
|
|
238411
238425
|
}
|
|
238426
|
+
function sessionsHeldElsewhere() {
|
|
238427
|
+
return new Set(
|
|
238428
|
+
liveRows().filter((r3) => r3.pid !== process.pid && !r3.session_id.startsWith(PROCESS_ROW_PREFIX)).map((r3) => r3.session_id)
|
|
238429
|
+
);
|
|
238430
|
+
}
|
|
238412
238431
|
function forgetLiveSession(sessionId) {
|
|
238413
238432
|
if (local.delete(sessionId)) publish();
|
|
238414
238433
|
}
|
|
@@ -238454,7 +238473,7 @@ function listPeerSessions(exclude) {
|
|
|
238454
238473
|
sessionId: r3.session_id,
|
|
238455
238474
|
name: r3.name,
|
|
238456
238475
|
workspace: r3.workspace,
|
|
238457
|
-
surface: r3.surface === "cli"
|
|
238476
|
+
surface: r3.surface === "cli" || r3.surface === "chrome" || r3.surface === "editor" ? r3.surface : "app",
|
|
238458
238477
|
busy: r3.busy === 1,
|
|
238459
238478
|
pid: r3.pid
|
|
238460
238479
|
});
|
|
@@ -238735,7 +238754,7 @@ async function noteSessionOpen(sessionId, chatId) {
|
|
|
238735
238754
|
noteLiveSession({
|
|
238736
238755
|
sessionId,
|
|
238737
238756
|
chatId,
|
|
238738
|
-
name: (session2.title?.trim() && !isPlaceholderTitle(session2.title) ? session2.title.trim() : "") || `New ${process.env.ATLARIX_SURFACE === "cli" ? "CLI " : ""}session (${(app2?.path ?? "").split(/[\\/]/).pop() || "no folder"})`,
|
|
238757
|
+
name: (session2.title?.trim() && !isPlaceholderTitle(session2.title) ? session2.title.trim() : "") || `New ${process.env.ATLARIX_PEER_SURFACE === "editor" ? "editor " : process.env.ATLARIX_SURFACE === "cli" ? "CLI " : ""}session (${(app2?.path ?? "").split(/[\\/]/).pop() || "no folder"})`,
|
|
238739
238758
|
workspace: app2?.path ?? ""
|
|
238740
238759
|
});
|
|
238741
238760
|
} catch (e3) {
|
|
@@ -238880,6 +238899,65 @@ var init_continue_in_terminal = __esm({
|
|
|
238880
238899
|
}
|
|
238881
238900
|
});
|
|
238882
238901
|
|
|
238902
|
+
// src/lib/peers/open-in-editor.ts
|
|
238903
|
+
var open_in_editor_exports = {};
|
|
238904
|
+
__export(open_in_editor_exports, {
|
|
238905
|
+
EDITORS: () => EDITORS,
|
|
238906
|
+
editorLink: () => editorLink,
|
|
238907
|
+
guessEditor: () => guessEditor,
|
|
238908
|
+
openCommand: () => openCommand,
|
|
238909
|
+
openInEditor: () => openInEditor
|
|
238910
|
+
});
|
|
238911
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
238912
|
+
function editorLink(scheme, sessionId, folder) {
|
|
238913
|
+
const q3 = new URLSearchParams({ session: sessionId, folder });
|
|
238914
|
+
return `${scheme}://${EXTENSION}/open?${q3.toString()}`;
|
|
238915
|
+
}
|
|
238916
|
+
function guessEditor(env3 = process.env) {
|
|
238917
|
+
const hint = `${env3.VSCODE_GIT_ASKPASS_NODE ?? ""} ${env3.__CFBundleIdentifier ?? ""} ${env3.TERM_PROGRAM ?? ""}`.toLowerCase();
|
|
238918
|
+
for (const key of ["cursor", "kiro", "windsurf", "vscodium", "insiders"]) {
|
|
238919
|
+
if (hint.includes(key)) return key;
|
|
238920
|
+
}
|
|
238921
|
+
return "vscode";
|
|
238922
|
+
}
|
|
238923
|
+
function openCommand(platform, url2) {
|
|
238924
|
+
if (platform === "darwin") return { file: "open", args: [url2] };
|
|
238925
|
+
if (platform === "win32") return { file: "cmd.exe", args: ["/c", "start", "", url2.replace(/&/g, "^&")] };
|
|
238926
|
+
return { file: "xdg-open", args: [url2] };
|
|
238927
|
+
}
|
|
238928
|
+
async function openInEditor(sessionId, folder, editor) {
|
|
238929
|
+
const key = (editor || guessEditor()).toLowerCase();
|
|
238930
|
+
const target = EDITORS[key];
|
|
238931
|
+
if (!target) {
|
|
238932
|
+
return { ok: false, editor: key, error: `Unknown editor "${editor}". Try: ${Object.keys(EDITORS).filter((k2) => k2 !== "code").join(", ")}.` };
|
|
238933
|
+
}
|
|
238934
|
+
if (!/^[\w-]+$/.test(sessionId)) return { ok: false, editor: target.name, error: "This session has no id yet." };
|
|
238935
|
+
const { file: file2, args: args2 } = openCommand(process.platform, editorLink(target.scheme, sessionId, folder));
|
|
238936
|
+
return new Promise((resolve14) => {
|
|
238937
|
+
const child = spawn3(file2, args2, { detached: true, stdio: "ignore", windowsHide: true });
|
|
238938
|
+
child.once("error", (e3) => resolve14({ ok: false, editor: target.name, error: `Couldn't open ${target.name}: ${e3.message}` }));
|
|
238939
|
+
child.once("spawn", () => {
|
|
238940
|
+
child.unref();
|
|
238941
|
+
resolve14({ ok: true, editor: target.name });
|
|
238942
|
+
});
|
|
238943
|
+
});
|
|
238944
|
+
}
|
|
238945
|
+
var EDITORS, EXTENSION;
|
|
238946
|
+
var init_open_in_editor = __esm({
|
|
238947
|
+
"src/lib/peers/open-in-editor.ts"() {
|
|
238948
|
+
EDITORS = {
|
|
238949
|
+
vscode: { scheme: "vscode", name: "VS Code" },
|
|
238950
|
+
code: { scheme: "vscode", name: "VS Code" },
|
|
238951
|
+
insiders: { scheme: "vscode-insiders", name: "VS Code Insiders" },
|
|
238952
|
+
cursor: { scheme: "cursor", name: "Cursor" },
|
|
238953
|
+
kiro: { scheme: "kiro", name: "Kiro" },
|
|
238954
|
+
windsurf: { scheme: "windsurf", name: "Windsurf" },
|
|
238955
|
+
vscodium: { scheme: "vscodium", name: "VSCodium" }
|
|
238956
|
+
};
|
|
238957
|
+
EXTENSION = "atlarix.atlarix";
|
|
238958
|
+
}
|
|
238959
|
+
});
|
|
238960
|
+
|
|
238883
238961
|
// src/ipc/handlers/workspace_session_handlers.ts
|
|
238884
238962
|
var workspace_session_handlers_exports = {};
|
|
238885
238963
|
__export(workspace_session_handlers_exports, {
|
|
@@ -239054,18 +239132,18 @@ async function resolveOrBindWorkspaceSessionForStream(input) {
|
|
|
239054
239132
|
"workspaceSessionId is required for workspace chat streams"
|
|
239055
239133
|
);
|
|
239056
239134
|
}
|
|
239057
|
-
const
|
|
239135
|
+
const latest2 = await db.query.chatSessions.findFirst({
|
|
239058
239136
|
where: eq(chatSessions.workspaceId, appId),
|
|
239059
239137
|
orderBy: [desc(chatSessions.updatedAt)]
|
|
239060
239138
|
});
|
|
239061
|
-
if (
|
|
239062
|
-
const stored =
|
|
239139
|
+
if (latest2) {
|
|
239140
|
+
const stored = latest2.streamChatId;
|
|
239063
239141
|
if (stored == null || isStreamTransportId(stored) && !getStreamTransport(stored)) {
|
|
239064
|
-
await persistSessionStreamChatId(
|
|
239142
|
+
await persistSessionStreamChatId(latest2.id, input.chatId);
|
|
239065
239143
|
logger30.warn(
|
|
239066
|
-
`Bound transport chat ${input.chatId} to session ${
|
|
239144
|
+
`Bound transport chat ${input.chatId} to session ${latest2.id} (workspace ${appId})`
|
|
239067
239145
|
);
|
|
239068
|
-
return
|
|
239146
|
+
return latest2.id;
|
|
239069
239147
|
}
|
|
239070
239148
|
}
|
|
239071
239149
|
const session2 = await insertWorkspaceSession(appId);
|
|
@@ -239160,10 +239238,13 @@ async function verifyTrulyEmptySession(sessionId, purpose) {
|
|
|
239160
239238
|
}
|
|
239161
239239
|
return { row, empty: true, reason: "empty" };
|
|
239162
239240
|
}
|
|
239163
|
-
async function startWorkspaceSession(workspaceId) {
|
|
239241
|
+
async function startWorkspaceSession(workspaceId, opts = {}) {
|
|
239164
239242
|
let session2 = null;
|
|
239165
239243
|
try {
|
|
239166
|
-
const
|
|
239244
|
+
const held = sessionsHeldElsewhere();
|
|
239245
|
+
const rows = (await listSessionsWithMessageCounts(workspaceId)).filter(
|
|
239246
|
+
(r3) => !held.has(r3.id) && !claimedSessions.has(r3.id)
|
|
239247
|
+
);
|
|
239167
239248
|
const { reuseId, pruneIds } = pickSessionReuse(rows);
|
|
239168
239249
|
if (rows.length > 0) {
|
|
239169
239250
|
logger30.log(
|
|
@@ -239207,6 +239288,7 @@ async function startWorkspaceSession(workspaceId) {
|
|
|
239207
239288
|
if (!session2) {
|
|
239208
239289
|
session2 = await insertWorkspaceSession(workspaceId);
|
|
239209
239290
|
}
|
|
239291
|
+
if (opts.claim) claimedSessions.add(session2.id);
|
|
239210
239292
|
const chatId = createStreamTransport(workspaceId);
|
|
239211
239293
|
await persistSessionStreamChatId(session2.id, chatId);
|
|
239212
239294
|
return { sessionId: session2.id, chatId, session: session2 };
|
|
@@ -239345,9 +239427,9 @@ function registerWorkspaceSessionHandlers() {
|
|
|
239345
239427
|
return out;
|
|
239346
239428
|
}
|
|
239347
239429
|
);
|
|
239348
|
-
handle("sessions:start", async (_event, workspaceId) => {
|
|
239430
|
+
handle("sessions:start", async (_event, workspaceId, opts) => {
|
|
239349
239431
|
await requireAuthSession();
|
|
239350
|
-
const started = await startWorkspaceSession(workspaceId);
|
|
239432
|
+
const started = await startWorkspaceSession(workspaceId, { claim: opts?.claim === true });
|
|
239351
239433
|
logger30.info(
|
|
239352
239434
|
`sessions:start workspace=${workspaceId} session=${started.sessionId} transport=${started.chatId}`
|
|
239353
239435
|
);
|
|
@@ -239378,6 +239460,15 @@ function registerWorkspaceSessionHandlers() {
|
|
|
239378
239460
|
const { continueInTerminal: continueInTerminal2 } = await Promise.resolve().then(() => (init_continue_in_terminal(), continue_in_terminal_exports));
|
|
239379
239461
|
return continueInTerminal2(sessionId, workspace?.path ?? "");
|
|
239380
239462
|
});
|
|
239463
|
+
handle("sessions:open-in-editor", async (_event, sessionId, editor) => {
|
|
239464
|
+
const session2 = await db.query.chatSessions.findFirst({
|
|
239465
|
+
where: eq(chatSessions.id, sessionId)
|
|
239466
|
+
});
|
|
239467
|
+
if (!session2) return { ok: false, error: "Session not found" };
|
|
239468
|
+
const workspace = session2.workspaceId ? await db.query.apps.findFirst({ where: eq(apps.id, session2.workspaceId) }) : void 0;
|
|
239469
|
+
const { openInEditor: openInEditor2 } = await Promise.resolve().then(() => (init_open_in_editor(), open_in_editor_exports));
|
|
239470
|
+
return openInEditor2(sessionId, workspace?.path ?? "", editor);
|
|
239471
|
+
});
|
|
239381
239472
|
handle("sessions:create", async (_event, workspaceId) => {
|
|
239382
239473
|
await requireAuthSession();
|
|
239383
239474
|
return insertWorkspaceSession(workspaceId);
|
|
@@ -239525,7 +239616,7 @@ function registerWorkspaceSessionHandlers() {
|
|
|
239525
239616
|
return { title: currentTitle };
|
|
239526
239617
|
});
|
|
239527
239618
|
}
|
|
239528
|
-
var import_electron_log32, DEFAULT_SESSION_TITLES, logger30, handle;
|
|
239619
|
+
var import_electron_log32, DEFAULT_SESSION_TITLES, logger30, handle, claimedSessions;
|
|
239529
239620
|
var init_workspace_session_handlers = __esm({
|
|
239530
239621
|
"src/ipc/handlers/workspace_session_handlers.ts"() {
|
|
239531
239622
|
import_electron_log32 = __toESM(require_src());
|
|
@@ -239549,6 +239640,7 @@ var init_workspace_session_handlers = __esm({
|
|
|
239549
239640
|
DEFAULT_SESSION_TITLES = /* @__PURE__ */ new Set(["Untitled", "New session", "New chat"]);
|
|
239550
239641
|
logger30 = import_electron_log32.default.scope("workspace_session_handlers");
|
|
239551
239642
|
handle = createLoggedHandler(logger30);
|
|
239643
|
+
claimedSessions = /* @__PURE__ */ new Set();
|
|
239552
239644
|
}
|
|
239553
239645
|
});
|
|
239554
239646
|
|
|
@@ -250381,14 +250473,14 @@ var init_mcp_manager = __esm({
|
|
|
250381
250473
|
};
|
|
250382
250474
|
const envForTransport = Object.keys(env3).length > 0 ? env3 : void 0;
|
|
250383
250475
|
if (!s3.command) throw new Error("MCP server command is required");
|
|
250384
|
-
const
|
|
250476
|
+
const spawn6 = await wrapStdioSpawnForFirejail(
|
|
250385
250477
|
s3.command,
|
|
250386
250478
|
args2,
|
|
250387
250479
|
readSettings()
|
|
250388
250480
|
);
|
|
250389
250481
|
transport = new StdioClientTransport({
|
|
250390
|
-
command:
|
|
250391
|
-
args:
|
|
250482
|
+
command: spawn6.command,
|
|
250483
|
+
args: spawn6.args,
|
|
250392
250484
|
env: envForTransport
|
|
250393
250485
|
});
|
|
250394
250486
|
} else if (s3.transport === "http") {
|
|
@@ -294799,15 +294891,15 @@ var require_generators = __commonJS({
|
|
|
294799
294891
|
var stack = new Error().stack;
|
|
294800
294892
|
return function() {
|
|
294801
294893
|
var generator = generatorFunction.apply(this, arguments);
|
|
294802
|
-
var
|
|
294894
|
+
var spawn6 = new PromiseSpawn$(
|
|
294803
294895
|
void 0,
|
|
294804
294896
|
void 0,
|
|
294805
294897
|
yieldHandler,
|
|
294806
294898
|
stack
|
|
294807
294899
|
);
|
|
294808
|
-
var ret2 =
|
|
294809
|
-
|
|
294810
|
-
|
|
294900
|
+
var ret2 = spawn6.promise();
|
|
294901
|
+
spawn6._generator = generator;
|
|
294902
|
+
spawn6._promiseFulfilled(void 0);
|
|
294811
294903
|
return ret2;
|
|
294812
294904
|
};
|
|
294813
294905
|
};
|
|
@@ -294822,9 +294914,9 @@ var require_generators = __commonJS({
|
|
|
294822
294914
|
if (typeof generatorFunction !== "function") {
|
|
294823
294915
|
return apiRejection("generatorFunction must be a function\n\n See http://goo.gl/MqrFmX\n");
|
|
294824
294916
|
}
|
|
294825
|
-
var
|
|
294826
|
-
var ret2 =
|
|
294827
|
-
|
|
294917
|
+
var spawn6 = new PromiseSpawn(generatorFunction, this);
|
|
294918
|
+
var ret2 = spawn6.promise();
|
|
294919
|
+
spawn6._run(Promise2.spawn);
|
|
294828
294920
|
return ret2;
|
|
294829
294921
|
};
|
|
294830
294922
|
};
|
|
@@ -320114,12 +320206,12 @@ async function readPlan(args2) {
|
|
|
320114
320206
|
const row = await getLatestPlanArtifact(sessionId, filter4);
|
|
320115
320207
|
if (!row) {
|
|
320116
320208
|
if (filter4) {
|
|
320117
|
-
const
|
|
320118
|
-
if (
|
|
320209
|
+
const latest2 = await getLatestPlanArtifact(sessionId);
|
|
320210
|
+
if (latest2) {
|
|
320119
320211
|
return {
|
|
320120
320212
|
success: true,
|
|
320121
320213
|
content: null,
|
|
320122
|
-
message: `No plan with status "${filter4}" \u2014 this session's plan is "${
|
|
320214
|
+
message: `No plan with status "${filter4}" \u2014 this session's plan is "${latest2.planStatus}" (planId: ${latest2.id}). Call plan({operation:"read"}) without a status to read it.`
|
|
320123
320215
|
};
|
|
320124
320216
|
}
|
|
320125
320217
|
}
|
|
@@ -324644,11 +324736,11 @@ async function persistCursor(automationId, cursor) {
|
|
|
324644
324736
|
await db.update(automations).set({ cursor: JSON.stringify(cursor), updatedAt: /* @__PURE__ */ new Date() }).where(eq(automations.id, automationId));
|
|
324645
324737
|
}
|
|
324646
324738
|
async function recordPollError(automationId, message) {
|
|
324647
|
-
const
|
|
324739
|
+
const latest2 = await db.query.automationRuns.findFirst({
|
|
324648
324740
|
where: eq(automationRuns.automationId, automationId),
|
|
324649
324741
|
orderBy: (runs, { desc: desc2 }) => [desc2(runs.startedAt)]
|
|
324650
324742
|
});
|
|
324651
|
-
if (
|
|
324743
|
+
if (latest2?.status === "error" && latest2.error === message) return;
|
|
324652
324744
|
const { randomUUID: randomUUID13 } = await import("node:crypto");
|
|
324653
324745
|
const now2 = /* @__PURE__ */ new Date();
|
|
324654
324746
|
await db.insert(automationRuns).values({
|
|
@@ -328295,7 +328387,7 @@ var init_prompt_budget = __esm({
|
|
|
328295
328387
|
});
|
|
328296
328388
|
|
|
328297
328389
|
// src/ipc/utils/system_git_exec.ts
|
|
328298
|
-
import { execFile as execFile8, spawn as
|
|
328390
|
+
import { execFile as execFile8, spawn as spawn5 } from "node:child_process";
|
|
328299
328391
|
import path54 from "node:path";
|
|
328300
328392
|
function gitInstallHint() {
|
|
328301
328393
|
switch (process.platform) {
|
|
@@ -331867,7 +331959,7 @@ function attachEmptyOutputSafeRejectHandlers(streamResult, logWarn, scope) {
|
|
|
331867
331959
|
attach("finishReason");
|
|
331868
331960
|
attach("response");
|
|
331869
331961
|
}
|
|
331870
|
-
var MODEL_EMPTY_RESPONSE_USER_MESSAGE, EmptyModelOutputAfterRetryError;
|
|
331962
|
+
var MODEL_EMPTY_RESPONSE_USER_MESSAGE, EmptyModelOutputAfterRetryError, ProviderRefusedRequestError;
|
|
331871
331963
|
var init_no_usable_model_output = __esm({
|
|
331872
331964
|
"src/ipc/utils/no_usable_model_output.ts"() {
|
|
331873
331965
|
init_dist21();
|
|
@@ -331878,6 +331970,14 @@ var init_no_usable_model_output = __esm({
|
|
|
331878
331970
|
this.name = "EmptyModelOutputAfterRetryError";
|
|
331879
331971
|
}
|
|
331880
331972
|
};
|
|
331973
|
+
ProviderRefusedRequestError = class extends Error {
|
|
331974
|
+
constructor(refusal) {
|
|
331975
|
+
super("ProviderRefusedRequest");
|
|
331976
|
+
this.refusal = refusal;
|
|
331977
|
+
this.name = "ProviderRefusedRequestError";
|
|
331978
|
+
}
|
|
331979
|
+
refusal;
|
|
331980
|
+
};
|
|
331881
331981
|
}
|
|
331882
331982
|
});
|
|
331883
331983
|
|
|
@@ -332583,6 +332683,10 @@ async function runStreamRoundWithEmptyOutputRetry(ctx, deps, params) {
|
|
|
332583
332683
|
"[stream] The SDK reported 'no output generated' for a transport failure \u2014 retrying as a network error instead"
|
|
332584
332684
|
);
|
|
332585
332685
|
}
|
|
332686
|
+
const refusal = bundle?.getRecordedRefusal?.();
|
|
332687
|
+
if (refusal != null && isEmptyOutputStreamError(err2)) {
|
|
332688
|
+
throw new ProviderRefusedRequestError(refusal);
|
|
332689
|
+
}
|
|
332586
332690
|
if (isForcedToolChoiceRejection(err2) && !ctx.forcedToolChoiceRejected) {
|
|
332587
332691
|
ctx.forcedToolChoiceRejected = true;
|
|
332588
332692
|
logger81.warn(
|
|
@@ -333162,6 +333266,7 @@ async function simpleStreamText(ctx, deps, {
|
|
|
333162
333266
|
if (msgs && msgs.length) completedStepMessages.push(...msgs);
|
|
333163
333267
|
};
|
|
333164
333268
|
let recordedNetworkError = null;
|
|
333269
|
+
let recordedRefusal = null;
|
|
333165
333270
|
const turnBuckets = {
|
|
333166
333271
|
filesRead: 0,
|
|
333167
333272
|
searchResults: 0,
|
|
@@ -333474,6 +333579,7 @@ async function simpleStreamText(ctx, deps, {
|
|
|
333474
333579
|
} else {
|
|
333475
333580
|
message = byokLimitUserMessage(message, modelClient.builtinProviderId) ?? modelFailureUserMessage(message);
|
|
333476
333581
|
}
|
|
333582
|
+
if (isProviderRefusal(error51)) recordedRefusal = error51;
|
|
333477
333583
|
logger84.error(
|
|
333478
333584
|
`AI stream text error for request: errorMessage=${errorMessage} error=`,
|
|
333479
333585
|
error51
|
|
@@ -333528,9 +333634,16 @@ async function simpleStreamText(ctx, deps, {
|
|
|
333528
333634
|
* SDK's substitute error arrives, so the network branch can arm — see
|
|
333529
333635
|
* `recordedNetworkError` above for why the substitution happens at all.
|
|
333530
333636
|
*/
|
|
333531
|
-
getRecordedNetworkError: () => recordedNetworkError
|
|
333637
|
+
getRecordedNetworkError: () => recordedNetworkError,
|
|
333638
|
+
/** A refusal `onError` already reported; see `recordedRefusal`. */
|
|
333639
|
+
getRecordedRefusal: () => recordedRefusal
|
|
333532
333640
|
};
|
|
333533
333641
|
}
|
|
333642
|
+
function isProviderRefusal(error51) {
|
|
333643
|
+
const e3 = error51;
|
|
333644
|
+
const status = [e3?.statusCode, e3?.status, e3?.error?.statusCode, e3?.error?.status].find((x4) => typeof x4 === "number");
|
|
333645
|
+
return status != null && status >= 400 && status < 500 && status !== 408 && status !== 409 && status !== 429;
|
|
333646
|
+
}
|
|
333534
333647
|
var import_electron_log87, logger84;
|
|
333535
333648
|
var init_simple_stream_text = __esm({
|
|
333536
333649
|
"src/ipc/handlers/chat_stream/turn-runner/simple-stream-text.ts"() {
|
|
@@ -339469,6 +339582,18 @@ async function handleTurnError(error51, ctx, deps) {
|
|
|
339469
339582
|
FileUploadsState.getInstance().clear(req.chatId);
|
|
339470
339583
|
return;
|
|
339471
339584
|
}
|
|
339585
|
+
if (error51 instanceof ProviderRefusedRequestError) {
|
|
339586
|
+
safeSend(event.sender, "chat:response:end", {
|
|
339587
|
+
chatId: req.chatId,
|
|
339588
|
+
streamId,
|
|
339589
|
+
updatedFiles: false,
|
|
339590
|
+
hadToolCallsOrPermissions: false
|
|
339591
|
+
});
|
|
339592
|
+
if (activeStreamId.get(req.chatId) === streamId)
|
|
339593
|
+
activeStreams.delete(req.chatId);
|
|
339594
|
+
FileUploadsState.getInstance().clear(req.chatId);
|
|
339595
|
+
return;
|
|
339596
|
+
}
|
|
339472
339597
|
if (error51 instanceof EmptyModelOutputAfterRetryError) {
|
|
339473
339598
|
safeSend(event.sender, "chat:response:error", {
|
|
339474
339599
|
chatId: req.chatId,
|
|
@@ -342965,7 +343090,7 @@ ${err2.stack}` : "";
|
|
|
342965
343090
|
}
|
|
342966
343091
|
|
|
342967
343092
|
// src/headless/atlarix-headless.mts
|
|
342968
|
-
var VERSION15 = false ? "dev" : "15.
|
|
343093
|
+
var VERSION15 = false ? "dev" : "15.4.0";
|
|
342969
343094
|
if (process.argv[2] === "run") process.argv.splice(2, 1);
|
|
342970
343095
|
function arg(name29) {
|
|
342971
343096
|
const i4 = process.argv.indexOf(`--${name29}`);
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atlarix",
|
|
3
|
-
"version": "15.
|
|
3
|
+
"version": "15.4.0",
|
|
4
4
|
"description": "Atlarix CLI: an AI coding agent in your terminal. Works with any model (Atlarix Auto, your own API key, or a local model) and runs unattended with `atlarix run` for CI.",
|
|
5
5
|
"license": "PROPRIETARY",
|
|
6
6
|
"author": {
|
|
@@ -65,12 +65,12 @@
|
|
|
65
65
|
"provenance": false
|
|
66
66
|
},
|
|
67
67
|
"optionalDependencies": {
|
|
68
|
-
"atlarix-darwin-arm64": "15.
|
|
69
|
-
"atlarix-darwin-x64": "15.
|
|
70
|
-
"atlarix-linux-x64": "15.
|
|
71
|
-
"atlarix-linux-arm64": "15.
|
|
72
|
-
"atlarix-linux-x64-musl": "15.
|
|
73
|
-
"atlarix-linux-arm64-musl": "15.
|
|
74
|
-
"atlarix-windows-x64": "15.
|
|
68
|
+
"atlarix-darwin-arm64": "15.4.0",
|
|
69
|
+
"atlarix-darwin-x64": "15.4.0",
|
|
70
|
+
"atlarix-linux-x64": "15.4.0",
|
|
71
|
+
"atlarix-linux-arm64": "15.4.0",
|
|
72
|
+
"atlarix-linux-x64-musl": "15.4.0",
|
|
73
|
+
"atlarix-linux-arm64-musl": "15.4.0",
|
|
74
|
+
"atlarix-windows-x64": "15.4.0"
|
|
75
75
|
}
|
|
76
76
|
}
|