@charzhu/openjaw-agent 0.2.0 → 0.2.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 +1 -1
- package/dist/main.js +458 -87
- package/dist/main.js.map +3 -3
- package/package.json +2 -2
package/dist/main.js
CHANGED
|
@@ -3540,6 +3540,13 @@ var init_tool_exposure = __esm({
|
|
|
3540
3540
|
|
|
3541
3541
|
// src/copilot-auth.ts
|
|
3542
3542
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
3543
|
+
function isOAuthAbortError(err) {
|
|
3544
|
+
if (!err || typeof err !== "object") return false;
|
|
3545
|
+
const anyErr = err;
|
|
3546
|
+
if (anyErr.name === "AbortError") return true;
|
|
3547
|
+
if (anyErr.code === "ABORT_ERR") return true;
|
|
3548
|
+
return false;
|
|
3549
|
+
}
|
|
3543
3550
|
function oauthDomain(enterpriseUrl) {
|
|
3544
3551
|
return enterpriseUrl ? normalizeCopilotEnterpriseDomain(enterpriseUrl) : "github.com";
|
|
3545
3552
|
}
|
|
@@ -3578,11 +3585,14 @@ async function startCopilotDeviceFlow(clientId, enterpriseUrl) {
|
|
|
3578
3585
|
enterpriseUrl: normalizedEnterpriseUrl
|
|
3579
3586
|
};
|
|
3580
3587
|
}
|
|
3581
|
-
async function completeCopilotDeviceFlow(flow) {
|
|
3588
|
+
async function completeCopilotDeviceFlow(flow, signal) {
|
|
3582
3589
|
const domain = oauthDomain(flow.enterpriseUrl);
|
|
3583
3590
|
let intervalMs = flow.intervalSeconds * 1e3;
|
|
3584
3591
|
while (true) {
|
|
3585
|
-
|
|
3592
|
+
if (signal?.aborted) {
|
|
3593
|
+
throw signal.reason instanceof Error ? signal.reason : new DOMException("Aborted", "AbortError");
|
|
3594
|
+
}
|
|
3595
|
+
await sleep(intervalMs + OAUTH_POLLING_SAFETY_MARGIN_MS, void 0, { signal });
|
|
3586
3596
|
const res = await fetch(`https://${domain}/login/oauth/access_token`, {
|
|
3587
3597
|
method: "POST",
|
|
3588
3598
|
headers: {
|
|
@@ -3594,7 +3604,8 @@ async function completeCopilotDeviceFlow(flow) {
|
|
|
3594
3604
|
client_id: flow.clientId,
|
|
3595
3605
|
device_code: flow.deviceCode,
|
|
3596
3606
|
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
3597
|
-
})
|
|
3607
|
+
}),
|
|
3608
|
+
signal
|
|
3598
3609
|
});
|
|
3599
3610
|
if (!res.ok) {
|
|
3600
3611
|
throw new Error(`GitHub device login failed: ${res.status}`);
|
|
@@ -3633,6 +3644,7 @@ var init_copilot_auth = __esm({
|
|
|
3633
3644
|
init_provider_auth();
|
|
3634
3645
|
init_copilot();
|
|
3635
3646
|
OAUTH_POLLING_SAFETY_MARGIN_MS = 3e3;
|
|
3647
|
+
__name(isOAuthAbortError, "isOAuthAbortError");
|
|
3636
3648
|
__name(oauthDomain, "oauthDomain");
|
|
3637
3649
|
__name(startCopilotDeviceFlow, "startCopilotDeviceFlow");
|
|
3638
3650
|
__name(completeCopilotDeviceFlow, "completeCopilotDeviceFlow");
|
|
@@ -3648,7 +3660,8 @@ __export(connect_exports, {
|
|
|
3648
3660
|
disconnectContext: () => disconnectContext,
|
|
3649
3661
|
handleConnectCommand: () => handleConnectCommand,
|
|
3650
3662
|
listDisconnectChoices: () => listDisconnectChoices,
|
|
3651
|
-
maestroConfig: () => maestroConfig
|
|
3663
|
+
maestroConfig: () => maestroConfig,
|
|
3664
|
+
resolveCopilotClientId: () => resolveCopilotClientId
|
|
3652
3665
|
});
|
|
3653
3666
|
function maestroConfig(flavor = "anthropic") {
|
|
3654
3667
|
return {
|
|
@@ -8978,6 +8991,19 @@ import { DatabaseSync } from "node:sqlite";
|
|
|
8978
8991
|
import { join as join12 } from "node:path";
|
|
8979
8992
|
import { homedir as homedir9 } from "node:os";
|
|
8980
8993
|
import { mkdirSync as mkdirSync8, existsSync as existsSync10 } from "node:fs";
|
|
8994
|
+
function hasFts5() {
|
|
8995
|
+
return _hasFts5;
|
|
8996
|
+
}
|
|
8997
|
+
function detectFts5(database) {
|
|
8998
|
+
const probe = `__fts5_probe_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
8999
|
+
try {
|
|
9000
|
+
database.exec(`CREATE VIRTUAL TABLE temp.${probe} USING fts5(x)`);
|
|
9001
|
+
database.exec(`DROP TABLE temp.${probe}`);
|
|
9002
|
+
return true;
|
|
9003
|
+
} catch {
|
|
9004
|
+
return false;
|
|
9005
|
+
}
|
|
9006
|
+
}
|
|
8981
9007
|
function getMemoryDb() {
|
|
8982
9008
|
if (!db) {
|
|
8983
9009
|
if (!existsSync10(DB_DIR)) {
|
|
@@ -8987,12 +9013,12 @@ function getMemoryDb() {
|
|
|
8987
9013
|
db.exec("PRAGMA journal_mode=WAL");
|
|
8988
9014
|
db.exec("PRAGMA busy_timeout=5000");
|
|
8989
9015
|
ensureSchema(db);
|
|
8990
|
-
logger_default.debug("Memory database opened", { path: DB_PATH });
|
|
9016
|
+
logger_default.debug("Memory database opened", { path: DB_PATH, hasFts5: _hasFts5 });
|
|
8991
9017
|
}
|
|
8992
9018
|
return db;
|
|
8993
9019
|
}
|
|
8994
|
-
function ensureSchema(
|
|
8995
|
-
|
|
9020
|
+
function ensureSchema(database) {
|
|
9021
|
+
database.exec(`
|
|
8996
9022
|
CREATE TABLE IF NOT EXISTS memories (
|
|
8997
9023
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
8998
9024
|
content TEXT NOT NULL,
|
|
@@ -9002,36 +9028,49 @@ function ensureSchema(db2) {
|
|
|
9002
9028
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
9003
9029
|
)
|
|
9004
9030
|
`);
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9031
|
+
_hasFts5 = detectFts5(database);
|
|
9032
|
+
if (_hasFts5) {
|
|
9033
|
+
database.exec(`
|
|
9034
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
9035
|
+
content,
|
|
9036
|
+
content='memories',
|
|
9037
|
+
content_rowid='id',
|
|
9038
|
+
tokenize='unicode61'
|
|
9039
|
+
)
|
|
9040
|
+
`);
|
|
9041
|
+
database.exec(`
|
|
9042
|
+
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
9043
|
+
INSERT INTO memories_fts(rowid, content) VALUES (new.id, new.content);
|
|
9044
|
+
END
|
|
9045
|
+
`);
|
|
9046
|
+
database.exec(`
|
|
9047
|
+
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
9048
|
+
INSERT INTO memories_fts(memories_fts, rowid, content) VALUES ('delete', old.id, old.content);
|
|
9049
|
+
END
|
|
9050
|
+
`);
|
|
9051
|
+
database.exec(`
|
|
9052
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
9053
|
+
INSERT INTO memories_fts(memories_fts, rowid, content) VALUES ('delete', old.id, old.content);
|
|
9054
|
+
INSERT INTO memories_fts(rowid, content) VALUES (new.id, new.content);
|
|
9055
|
+
END
|
|
9056
|
+
`);
|
|
9057
|
+
try {
|
|
9058
|
+
database.exec(`INSERT INTO memories_fts(memories_fts) VALUES('rebuild')`);
|
|
9059
|
+
} catch (err) {
|
|
9060
|
+
logger_default.warn("FTS5 rebuild failed (non-fatal)", { error: String(err) });
|
|
9061
|
+
}
|
|
9062
|
+
} else {
|
|
9063
|
+
database.exec(`DROP TRIGGER IF EXISTS memories_ai`);
|
|
9064
|
+
database.exec(`DROP TRIGGER IF EXISTS memories_ad`);
|
|
9065
|
+
database.exec(`DROP TRIGGER IF EXISTS memories_au`);
|
|
9066
|
+
logger_default.warn("FTS5 not available in this SQLite build \u2014 memory search will use LIKE-based fallback. For best performance, upgrade to Node 23.5+ (bundled SQLite includes FTS5 by default).");
|
|
9067
|
+
}
|
|
9029
9068
|
try {
|
|
9030
|
-
|
|
9069
|
+
database.exec("ALTER TABLE memories ADD COLUMN hrr_vector BLOB");
|
|
9031
9070
|
} catch {
|
|
9032
9071
|
}
|
|
9033
9072
|
}
|
|
9034
|
-
var DB_DIR, DB_PATH, db;
|
|
9073
|
+
var DB_DIR, DB_PATH, db, _hasFts5;
|
|
9035
9074
|
var init_db = __esm({
|
|
9036
9075
|
"../openjaw-mcp/dist/memory/db.js"() {
|
|
9037
9076
|
"use strict";
|
|
@@ -9039,6 +9078,9 @@ var init_db = __esm({
|
|
|
9039
9078
|
DB_DIR = join12(homedir9(), ".openjaw");
|
|
9040
9079
|
DB_PATH = join12(DB_DIR, "memory.db");
|
|
9041
9080
|
db = null;
|
|
9081
|
+
_hasFts5 = false;
|
|
9082
|
+
__name(hasFts5, "hasFts5");
|
|
9083
|
+
__name(detectFts5, "detectFts5");
|
|
9042
9084
|
__name(getMemoryDb, "getMemoryDb");
|
|
9043
9085
|
__name(ensureSchema, "ensureSchema");
|
|
9044
9086
|
}
|
|
@@ -9135,11 +9177,15 @@ var init_hrr = __esm({
|
|
|
9135
9177
|
});
|
|
9136
9178
|
|
|
9137
9179
|
// ../openjaw-mcp/dist/memory/retrieval.js
|
|
9138
|
-
|
|
9180
|
+
function escapeLike(token) {
|
|
9181
|
+
return `%${token.replace(/[\\%_]/g, "\\$&")}%`;
|
|
9182
|
+
}
|
|
9183
|
+
var STOPWORDS, MAX_LIKE_TERMS, DEFAULT_WEIGHTS_FTS, DEFAULT_WEIGHTS_NO_FTS, HybridRetriever;
|
|
9139
9184
|
var init_retrieval = __esm({
|
|
9140
9185
|
"../openjaw-mcp/dist/memory/retrieval.js"() {
|
|
9141
9186
|
"use strict";
|
|
9142
9187
|
init_hrr();
|
|
9188
|
+
init_db();
|
|
9143
9189
|
init_logger();
|
|
9144
9190
|
STOPWORDS = /* @__PURE__ */ new Set([
|
|
9145
9191
|
"a",
|
|
@@ -9201,23 +9247,30 @@ var init_retrieval = __esm({
|
|
|
9201
9247
|
"should",
|
|
9202
9248
|
"could"
|
|
9203
9249
|
]);
|
|
9204
|
-
|
|
9250
|
+
MAX_LIKE_TERMS = 16;
|
|
9251
|
+
__name(escapeLike, "escapeLike");
|
|
9252
|
+
DEFAULT_WEIGHTS_FTS = {
|
|
9205
9253
|
fts: 0.4,
|
|
9206
9254
|
jaccard: 0.3,
|
|
9207
9255
|
hrr: 0.3
|
|
9208
9256
|
};
|
|
9257
|
+
DEFAULT_WEIGHTS_NO_FTS = {
|
|
9258
|
+
fts: 0,
|
|
9259
|
+
jaccard: 0.5,
|
|
9260
|
+
hrr: 0.5
|
|
9261
|
+
};
|
|
9209
9262
|
HybridRetriever = class {
|
|
9210
9263
|
static {
|
|
9211
9264
|
__name(this, "HybridRetriever");
|
|
9212
9265
|
}
|
|
9213
9266
|
db;
|
|
9214
9267
|
weights;
|
|
9215
|
-
constructor(db2, weights
|
|
9268
|
+
constructor(db2, weights) {
|
|
9216
9269
|
this.db = db2;
|
|
9217
|
-
this.weights = weights;
|
|
9270
|
+
this.weights = weights ?? (hasFts5() ? DEFAULT_WEIGHTS_FTS : DEFAULT_WEIGHTS_NO_FTS);
|
|
9218
9271
|
}
|
|
9219
9272
|
/**
|
|
9220
|
-
* Hybrid search: FTS5 candidate retrieval → Jaccard + HRR re-ranking.
|
|
9273
|
+
* Hybrid search: FTS5 (or LIKE fallback) candidate retrieval → Jaccard + HRR re-ranking.
|
|
9221
9274
|
*/
|
|
9222
9275
|
search(query, limit = 10) {
|
|
9223
9276
|
const queryTokens = query.toLowerCase().match(/[\w]+/g);
|
|
@@ -9228,27 +9281,47 @@ var init_retrieval = __esm({
|
|
|
9228
9281
|
return [];
|
|
9229
9282
|
const queryTokenSet = new Set(filtered);
|
|
9230
9283
|
const candidateLimit = Math.max(limit * 5, 50);
|
|
9231
|
-
const ftsQuery = filtered.join(" OR ");
|
|
9232
9284
|
let hasHrrColumn = true;
|
|
9233
9285
|
try {
|
|
9234
9286
|
this.db.prepare("SELECT hrr_vector FROM memories LIMIT 0").all();
|
|
9235
9287
|
} catch {
|
|
9236
9288
|
hasHrrColumn = false;
|
|
9237
9289
|
}
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9290
|
+
let candidates = [];
|
|
9291
|
+
if (hasFts5()) {
|
|
9292
|
+
const selectCols = hasHrrColumn ? "m.id, m.content, m.source, m.created_at, m.hrr_vector, fts.rank" : "m.id, m.content, m.source, m.created_at, fts.rank";
|
|
9293
|
+
const ftsQuery = filtered.join(" OR ");
|
|
9294
|
+
try {
|
|
9295
|
+
candidates = this.db.prepare(`
|
|
9296
|
+
SELECT ${selectCols}
|
|
9297
|
+
FROM memories_fts fts
|
|
9298
|
+
JOIN memories m ON m.id = fts.rowid
|
|
9299
|
+
WHERE memories_fts MATCH ?
|
|
9300
|
+
ORDER BY fts.rank
|
|
9301
|
+
LIMIT ?
|
|
9302
|
+
`).all(ftsQuery, candidateLimit);
|
|
9303
|
+
} catch (err) {
|
|
9304
|
+
logger_default.warn("FTS5 search failed in hybrid retriever", { query: ftsQuery, error: String(err) });
|
|
9305
|
+
return [];
|
|
9306
|
+
}
|
|
9307
|
+
} else {
|
|
9308
|
+
const terms = Array.from(new Set(filtered)).slice(0, MAX_LIKE_TERMS);
|
|
9309
|
+
const selectCols = hasHrrColumn ? "m.id, m.content, m.source, m.created_at, m.hrr_vector, 0 AS rank" : "m.id, m.content, m.source, m.created_at, 0 AS rank";
|
|
9310
|
+
const wheres = terms.map(() => `m.content LIKE ? ESCAPE '\\'`).join(" OR ");
|
|
9311
|
+
const params = terms.map(escapeLike);
|
|
9312
|
+
params.push(candidateLimit);
|
|
9313
|
+
try {
|
|
9314
|
+
candidates = this.db.prepare(`
|
|
9315
|
+
SELECT ${selectCols}
|
|
9316
|
+
FROM memories m
|
|
9317
|
+
WHERE ${wheres}
|
|
9318
|
+
ORDER BY m.created_at DESC, m.id DESC
|
|
9319
|
+
LIMIT ?
|
|
9320
|
+
`).all(...params);
|
|
9321
|
+
} catch (err) {
|
|
9322
|
+
logger_default.warn("LIKE-fallback search failed in hybrid retriever", { error: String(err) });
|
|
9323
|
+
return [];
|
|
9324
|
+
}
|
|
9252
9325
|
}
|
|
9253
9326
|
if (candidates.length === 0)
|
|
9254
9327
|
return [];
|
|
@@ -19380,6 +19453,9 @@ import { homedir as homedir11 } from "node:os";
|
|
|
19380
19453
|
function setMemoryPrefetchQuery(query) {
|
|
19381
19454
|
currentQuery = query;
|
|
19382
19455
|
}
|
|
19456
|
+
function escapeLike2(token) {
|
|
19457
|
+
return `%${token.replace(/[\\%_]/g, "\\$&")}%`;
|
|
19458
|
+
}
|
|
19383
19459
|
function getMemorySection() {
|
|
19384
19460
|
if (!currentQuery) return null;
|
|
19385
19461
|
try {
|
|
@@ -19396,15 +19472,34 @@ function getMemorySection() {
|
|
|
19396
19472
|
if (!tokens || tokens.length === 0) return null;
|
|
19397
19473
|
const filtered = tokens.filter((t) => !STOPWORDS2.has(t));
|
|
19398
19474
|
if (filtered.length === 0) return null;
|
|
19399
|
-
|
|
19400
|
-
const
|
|
19401
|
-
|
|
19402
|
-
|
|
19403
|
-
|
|
19404
|
-
|
|
19405
|
-
|
|
19406
|
-
|
|
19407
|
-
|
|
19475
|
+
let rows = [];
|
|
19476
|
+
const ftsQuery = filtered.join(" OR ");
|
|
19477
|
+
try {
|
|
19478
|
+
rows = db2.prepare(`
|
|
19479
|
+
SELECT m.content, m.source, m.created_at
|
|
19480
|
+
FROM memories_fts fts
|
|
19481
|
+
JOIN memories m ON m.id = fts.rowid
|
|
19482
|
+
WHERE memories_fts MATCH ?
|
|
19483
|
+
ORDER BY fts.rank
|
|
19484
|
+
LIMIT ?
|
|
19485
|
+
`).all(ftsQuery, MAX_PREFETCH_RESULTS);
|
|
19486
|
+
} catch {
|
|
19487
|
+
const terms = Array.from(new Set(filtered)).slice(0, MAX_LIKE_TERMS2);
|
|
19488
|
+
const wheres = terms.map(() => `content LIKE ? ESCAPE '\\'`).join(" OR ");
|
|
19489
|
+
const params = terms.map(escapeLike2);
|
|
19490
|
+
params.push(MAX_PREFETCH_RESULTS);
|
|
19491
|
+
try {
|
|
19492
|
+
rows = db2.prepare(`
|
|
19493
|
+
SELECT content, source, created_at
|
|
19494
|
+
FROM memories
|
|
19495
|
+
WHERE ${wheres}
|
|
19496
|
+
ORDER BY created_at DESC, id DESC
|
|
19497
|
+
LIMIT ?
|
|
19498
|
+
`).all(...params);
|
|
19499
|
+
} catch {
|
|
19500
|
+
return null;
|
|
19501
|
+
}
|
|
19502
|
+
}
|
|
19408
19503
|
if (rows.length === 0) return null;
|
|
19409
19504
|
let result = "# Relevant Memories\n\nRecalled from your memory database based on your current query:\n\n";
|
|
19410
19505
|
for (const row of rows) {
|
|
@@ -19421,12 +19516,13 @@ function getMemorySection() {
|
|
|
19421
19516
|
return null;
|
|
19422
19517
|
}
|
|
19423
19518
|
}
|
|
19424
|
-
var MAX_PREFETCH_RESULTS, MAX_PREFETCH_CHARS, STOPWORDS2, currentQuery;
|
|
19519
|
+
var MAX_PREFETCH_RESULTS, MAX_PREFETCH_CHARS, MAX_LIKE_TERMS2, STOPWORDS2, currentQuery;
|
|
19425
19520
|
var init_memory2 = __esm({
|
|
19426
19521
|
"src/prompts/memory.ts"() {
|
|
19427
19522
|
"use strict";
|
|
19428
19523
|
MAX_PREFETCH_RESULTS = 10;
|
|
19429
19524
|
MAX_PREFETCH_CHARS = 4e3;
|
|
19525
|
+
MAX_LIKE_TERMS2 = 16;
|
|
19430
19526
|
STOPWORDS2 = /* @__PURE__ */ new Set([
|
|
19431
19527
|
"a",
|
|
19432
19528
|
"an",
|
|
@@ -19489,6 +19585,7 @@ var init_memory2 = __esm({
|
|
|
19489
19585
|
]);
|
|
19490
19586
|
currentQuery = null;
|
|
19491
19587
|
__name(setMemoryPrefetchQuery, "setMemoryPrefetchQuery");
|
|
19588
|
+
__name(escapeLike2, "escapeLike");
|
|
19492
19589
|
__name(getMemorySection, "getMemorySection");
|
|
19493
19590
|
}
|
|
19494
19591
|
});
|
|
@@ -47225,6 +47322,19 @@ function registerRpcHandlers(options) {
|
|
|
47225
47322
|
let currentRun = null;
|
|
47226
47323
|
const pendingResponders = /* @__PURE__ */ new Map();
|
|
47227
47324
|
const promptCollector = createPromptCollector(bus, () => agentLoop.sessionId);
|
|
47325
|
+
const OAUTH_FLOW_TTL_MS = 15 * 60 * 1e3;
|
|
47326
|
+
const oauthFlows = /* @__PURE__ */ new Map();
|
|
47327
|
+
const cleanupOAuthFlow = /* @__PURE__ */ __name((flowId, abort) => {
|
|
47328
|
+
const entry = oauthFlows.get(flowId);
|
|
47329
|
+
if (!entry) {
|
|
47330
|
+
return;
|
|
47331
|
+
}
|
|
47332
|
+
clearTimeout(entry.timer);
|
|
47333
|
+
if (abort && !entry.controller.signal.aborted) {
|
|
47334
|
+
entry.controller.abort();
|
|
47335
|
+
}
|
|
47336
|
+
oauthFlows.delete(flowId);
|
|
47337
|
+
}, "cleanupOAuthFlow");
|
|
47228
47338
|
const onBridgeEvent = /* @__PURE__ */ __name((rawEvent) => {
|
|
47229
47339
|
const source = inferBridgeSource(rawEvent);
|
|
47230
47340
|
const user = bridgeUser(rawEvent, source);
|
|
@@ -47771,6 +47881,77 @@ ${helpMessage}` : field.label;
|
|
|
47771
47881
|
}
|
|
47772
47882
|
return { disconnected: true, slug };
|
|
47773
47883
|
});
|
|
47884
|
+
bus.registerRpc("model.oauth_start", async (params) => {
|
|
47885
|
+
const slug = String(params.slug ?? "").trim();
|
|
47886
|
+
if (!PROVIDERS2.includes(slug)) {
|
|
47887
|
+
throw new Error(`unknown provider: ${slug}`);
|
|
47888
|
+
}
|
|
47889
|
+
const auth = PROVIDER_AUTH[slug];
|
|
47890
|
+
if (auth.auth_type !== "oauth") {
|
|
47891
|
+
throw new Error(`${PROVIDER_LABELS[slug]} does not use OAuth (auth_type=${auth.auth_type})`);
|
|
47892
|
+
}
|
|
47893
|
+
const clientId = resolveCopilotClientId();
|
|
47894
|
+
if (!clientId) {
|
|
47895
|
+
throw new Error(
|
|
47896
|
+
"GitHub Copilot login needs a GitHub OAuth App client ID. Set GITHUB_COPILOT_CLIENT_ID or llm.copilot_oauth_client_id in ~/.openjaw-agent/config.yaml."
|
|
47897
|
+
);
|
|
47898
|
+
}
|
|
47899
|
+
const enterpriseUrl = (() => {
|
|
47900
|
+
const raw = params["enterprise_url"];
|
|
47901
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
47902
|
+
return raw.trim();
|
|
47903
|
+
}
|
|
47904
|
+
return agentConfig.llm.copilot_enterprise_url;
|
|
47905
|
+
})();
|
|
47906
|
+
const flow = await startCopilotDeviceFlow(clientId, enterpriseUrl);
|
|
47907
|
+
const flowId = randomUUID13();
|
|
47908
|
+
const controller = new AbortController();
|
|
47909
|
+
const timer = setTimeout(() => {
|
|
47910
|
+
cleanupOAuthFlow(flowId, true);
|
|
47911
|
+
}, OAUTH_FLOW_TTL_MS);
|
|
47912
|
+
if (typeof timer.unref === "function") {
|
|
47913
|
+
timer.unref();
|
|
47914
|
+
}
|
|
47915
|
+
oauthFlows.set(flowId, { controller, flow, slug, timer });
|
|
47916
|
+
return {
|
|
47917
|
+
flow_id: flowId,
|
|
47918
|
+
interval_seconds: flow.intervalSeconds,
|
|
47919
|
+
user_code: flow.userCode,
|
|
47920
|
+
verification_uri: flow.verificationUri
|
|
47921
|
+
};
|
|
47922
|
+
});
|
|
47923
|
+
bus.registerRpc("model.oauth_complete", async (params) => {
|
|
47924
|
+
const flowId = String(params["flow_id"] ?? "").trim();
|
|
47925
|
+
const entry = oauthFlows.get(flowId);
|
|
47926
|
+
if (!entry) {
|
|
47927
|
+
throw new Error("OAuth flow not found or already completed/expired");
|
|
47928
|
+
}
|
|
47929
|
+
try {
|
|
47930
|
+
await completeCopilotDeviceFlow(entry.flow, entry.controller.signal);
|
|
47931
|
+
} catch (err) {
|
|
47932
|
+
cleanupOAuthFlow(flowId, false);
|
|
47933
|
+
if (isOAuthAbortError(err) || entry.controller.signal.aborted) {
|
|
47934
|
+
return { aborted: true, slug: entry.slug };
|
|
47935
|
+
}
|
|
47936
|
+
throw err;
|
|
47937
|
+
}
|
|
47938
|
+
cleanupOAuthFlow(flowId, false);
|
|
47939
|
+
reconnectProviderContext(entry.slug);
|
|
47940
|
+
const live = await fetchLiveModels(entry.slug, agentConfig, agentLoop.model);
|
|
47941
|
+
return {
|
|
47942
|
+
provider: buildProviderOption(entry.slug, agentLoop.providerName, agentLoop.model, live.models, live.error),
|
|
47943
|
+
slug: entry.slug
|
|
47944
|
+
};
|
|
47945
|
+
});
|
|
47946
|
+
bus.registerRpc("model.oauth_cancel", (params) => {
|
|
47947
|
+
const flowId = String(params["flow_id"] ?? "").trim();
|
|
47948
|
+
const entry = oauthFlows.get(flowId);
|
|
47949
|
+
if (!entry) {
|
|
47950
|
+
return { cancelled: false, reason: "flow not found" };
|
|
47951
|
+
}
|
|
47952
|
+
cleanupOAuthFlow(flowId, true);
|
|
47953
|
+
return { cancelled: true, slug: entry.slug };
|
|
47954
|
+
});
|
|
47774
47955
|
bus.registerRpc("commands.catalog", () => {
|
|
47775
47956
|
const skillCount = toolRegistry.listTools().filter((t) => /^skill[:_-]/i.test(t.name)).length;
|
|
47776
47957
|
return buildCommandsCatalog({ skillCount });
|
|
@@ -48394,6 +48575,9 @@ ${helpMessage}` : field.label;
|
|
|
48394
48575
|
bridgeEmitter?.off("bridgeEvent", onBridgeEvent);
|
|
48395
48576
|
mcpManager.off("tools-changed", onToolsChanged);
|
|
48396
48577
|
pendingResponders.clear();
|
|
48578
|
+
for (const id of Array.from(oauthFlows.keys())) {
|
|
48579
|
+
cleanupOAuthFlow(id, true);
|
|
48580
|
+
}
|
|
48397
48581
|
};
|
|
48398
48582
|
}
|
|
48399
48583
|
var PROVIDERS2, PROVIDER_LABELS, PROVIDER_AUTH, isProviderAuthenticated, buildProviderOption, fetchLiveModels, BRIDGE_SOURCES, isBridgeSource, inferBridgeSource, bridgeLabels, bridgeEventLabels, stripBridgeGlyph, firstLogLine, bridgeUser, formatBridgeText, runProcess, contentToText, sessionMessageToMarkdown, usageSnapshot, sessionInfoSnapshot;
|
|
@@ -48402,6 +48586,7 @@ var init_rpcHandlers = __esm({
|
|
|
48402
48586
|
"use strict";
|
|
48403
48587
|
init_connect();
|
|
48404
48588
|
init_config();
|
|
48589
|
+
init_copilot_auth();
|
|
48405
48590
|
init_context_manager();
|
|
48406
48591
|
init_eventBridge();
|
|
48407
48592
|
init_fork();
|
|
@@ -56261,8 +56446,8 @@ var init_providers2 = __esm({
|
|
|
56261
56446
|
});
|
|
56262
56447
|
|
|
56263
56448
|
// src/components/modelPicker.tsx
|
|
56264
|
-
import { useEffect as useEffect17, useMemo as useMemo12, useState as useState19 } from "react";
|
|
56265
|
-
import { jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
56449
|
+
import { useEffect as useEffect17, useMemo as useMemo12, useRef as useRef17, useState as useState19 } from "react";
|
|
56450
|
+
import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
56266
56451
|
function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t }) {
|
|
56267
56452
|
const [providers, setProviders] = useState19([]);
|
|
56268
56453
|
const [currentModel, setCurrentModel] = useState19("");
|
|
@@ -56275,10 +56460,19 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56275
56460
|
const [keyInput, setKeyInput] = useState19("");
|
|
56276
56461
|
const [keySaving, setKeySaving] = useState19(false);
|
|
56277
56462
|
const [keyError, setKeyError] = useState19("");
|
|
56463
|
+
const [oauthStatus, setOauthStatus] = useState19("starting");
|
|
56464
|
+
const [oauthVerificationUri, setOauthVerificationUri] = useState19("");
|
|
56465
|
+
const [oauthUserCode, setOauthUserCode] = useState19("");
|
|
56466
|
+
const [oauthError, setOauthError] = useState19("");
|
|
56467
|
+
const oauthFlowIdRef = useRef17(null);
|
|
56468
|
+
const oauthProviderSlugRef = useRef17(null);
|
|
56469
|
+
const oauthAttemptRef = useRef17(0);
|
|
56470
|
+
const mountedRef = useRef17(true);
|
|
56278
56471
|
const { stdout } = useStdout();
|
|
56279
56472
|
const width = Math.max(MIN_WIDTH2, Math.min(MAX_WIDTH2, (stdout?.columns ?? 80) - 6));
|
|
56280
56473
|
useEffect17(() => {
|
|
56281
56474
|
gw.request("model.options", sessionId ? { session_id: sessionId } : {}).then((raw) => {
|
|
56475
|
+
if (!mountedRef.current) return;
|
|
56282
56476
|
const r = asRpcResult(raw);
|
|
56283
56477
|
if (!r) {
|
|
56284
56478
|
setErr("invalid response: model.options");
|
|
@@ -56299,6 +56493,7 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56299
56493
|
setErr("");
|
|
56300
56494
|
setLoading(false);
|
|
56301
56495
|
}).catch((e) => {
|
|
56496
|
+
if (!mountedRef.current) return;
|
|
56302
56497
|
setErr(rpcErrorMessage(e));
|
|
56303
56498
|
setLoading(false);
|
|
56304
56499
|
});
|
|
@@ -56306,7 +56501,121 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56306
56501
|
const provider = providers[providerIdx];
|
|
56307
56502
|
const models = provider?.models ?? [];
|
|
56308
56503
|
const names = useMemo12(() => providerDisplayNames(providers), [providers]);
|
|
56504
|
+
useEffect17(() => {
|
|
56505
|
+
mountedRef.current = true;
|
|
56506
|
+
return () => {
|
|
56507
|
+
mountedRef.current = false;
|
|
56508
|
+
const flowId = oauthFlowIdRef.current;
|
|
56509
|
+
if (flowId) {
|
|
56510
|
+
gw.request("model.oauth_cancel", { flow_id: flowId }).catch(() => {
|
|
56511
|
+
});
|
|
56512
|
+
oauthFlowIdRef.current = null;
|
|
56513
|
+
}
|
|
56514
|
+
};
|
|
56515
|
+
}, [gw]);
|
|
56516
|
+
const refreshProviders = /* @__PURE__ */ __name(() => gw.request("model.options", sessionId ? { session_id: sessionId } : {}).then((raw) => {
|
|
56517
|
+
if (!mountedRef.current) return;
|
|
56518
|
+
const r = asRpcResult(raw);
|
|
56519
|
+
if (!r) {
|
|
56520
|
+
return;
|
|
56521
|
+
}
|
|
56522
|
+
setProviders(r.providers ?? []);
|
|
56523
|
+
setCurrentModel(String(r.model ?? ""));
|
|
56524
|
+
}).catch(() => {
|
|
56525
|
+
}), "refreshProviders");
|
|
56526
|
+
const cancelActiveOAuth = /* @__PURE__ */ __name(() => {
|
|
56527
|
+
oauthAttemptRef.current += 1;
|
|
56528
|
+
const flowId = oauthFlowIdRef.current;
|
|
56529
|
+
if (!flowId) {
|
|
56530
|
+
return;
|
|
56531
|
+
}
|
|
56532
|
+
oauthFlowIdRef.current = null;
|
|
56533
|
+
gw.request("model.oauth_cancel", { flow_id: flowId }).catch(() => {
|
|
56534
|
+
});
|
|
56535
|
+
}, "cancelActiveOAuth");
|
|
56536
|
+
const startOAuthFlow = /* @__PURE__ */ __name((slug) => {
|
|
56537
|
+
cancelActiveOAuth();
|
|
56538
|
+
const attempt = ++oauthAttemptRef.current;
|
|
56539
|
+
oauthProviderSlugRef.current = slug;
|
|
56540
|
+
setStage("oauth");
|
|
56541
|
+
setOauthStatus("starting");
|
|
56542
|
+
setOauthVerificationUri("");
|
|
56543
|
+
setOauthUserCode("");
|
|
56544
|
+
setOauthError("");
|
|
56545
|
+
const isCurrent = /* @__PURE__ */ __name(() => mountedRef.current && oauthAttemptRef.current === attempt, "isCurrent");
|
|
56546
|
+
gw.request("model.oauth_start", {
|
|
56547
|
+
slug,
|
|
56548
|
+
...sessionId ? { session_id: sessionId } : {}
|
|
56549
|
+
}).then((raw) => {
|
|
56550
|
+
const r = asRpcResult(raw);
|
|
56551
|
+
if (!isCurrent()) {
|
|
56552
|
+
if (r?.flow_id) {
|
|
56553
|
+
gw.request("model.oauth_cancel", { flow_id: r.flow_id }).catch(() => {
|
|
56554
|
+
});
|
|
56555
|
+
}
|
|
56556
|
+
return;
|
|
56557
|
+
}
|
|
56558
|
+
if (!r?.flow_id) {
|
|
56559
|
+
setOauthStatus("error");
|
|
56560
|
+
setOauthError("invalid response from model.oauth_start");
|
|
56561
|
+
return;
|
|
56562
|
+
}
|
|
56563
|
+
oauthFlowIdRef.current = r.flow_id;
|
|
56564
|
+
setOauthVerificationUri(r.verification_uri);
|
|
56565
|
+
setOauthUserCode(r.user_code);
|
|
56566
|
+
setOauthStatus("waiting");
|
|
56567
|
+
gw.request("model.oauth_complete", {
|
|
56568
|
+
flow_id: r.flow_id,
|
|
56569
|
+
...sessionId ? { session_id: sessionId } : {}
|
|
56570
|
+
}).then((rawComplete) => {
|
|
56571
|
+
if (!isCurrent()) return;
|
|
56572
|
+
if (oauthFlowIdRef.current !== r.flow_id) return;
|
|
56573
|
+
oauthFlowIdRef.current = null;
|
|
56574
|
+
const rc = asRpcResult(rawComplete);
|
|
56575
|
+
if (!rc) {
|
|
56576
|
+
setOauthStatus("error");
|
|
56577
|
+
setOauthError("invalid response from model.oauth_complete");
|
|
56578
|
+
return;
|
|
56579
|
+
}
|
|
56580
|
+
if (rc.aborted) {
|
|
56581
|
+
setStage("provider");
|
|
56582
|
+
return;
|
|
56583
|
+
}
|
|
56584
|
+
if (rc.provider) {
|
|
56585
|
+
setProviders(
|
|
56586
|
+
(prev) => prev.map((p) => p.slug === rc.provider.slug ? rc.provider : p)
|
|
56587
|
+
);
|
|
56588
|
+
} else {
|
|
56589
|
+
refreshProviders();
|
|
56590
|
+
}
|
|
56591
|
+
if (mode === "connect") {
|
|
56592
|
+
onCancel();
|
|
56593
|
+
return;
|
|
56594
|
+
}
|
|
56595
|
+
setStage("model");
|
|
56596
|
+
setModelIdx(0);
|
|
56597
|
+
}).catch((e) => {
|
|
56598
|
+
if (!isCurrent()) return;
|
|
56599
|
+
if (oauthFlowIdRef.current !== r.flow_id) return;
|
|
56600
|
+
oauthFlowIdRef.current = null;
|
|
56601
|
+
setOauthStatus("error");
|
|
56602
|
+
setOauthError(rpcErrorMessage(e));
|
|
56603
|
+
});
|
|
56604
|
+
}).catch((e) => {
|
|
56605
|
+
if (!isCurrent()) return;
|
|
56606
|
+
setOauthStatus("error");
|
|
56607
|
+
setOauthError(rpcErrorMessage(e));
|
|
56608
|
+
});
|
|
56609
|
+
}, "startOAuthFlow");
|
|
56309
56610
|
const back = /* @__PURE__ */ __name(() => {
|
|
56611
|
+
if (stage === "oauth") {
|
|
56612
|
+
cancelActiveOAuth();
|
|
56613
|
+
setStage("provider");
|
|
56614
|
+
setOauthVerificationUri("");
|
|
56615
|
+
setOauthUserCode("");
|
|
56616
|
+
setOauthError("");
|
|
56617
|
+
return;
|
|
56618
|
+
}
|
|
56310
56619
|
if (stage === "model" || stage === "key" || stage === "disconnect") {
|
|
56311
56620
|
setStage("provider");
|
|
56312
56621
|
setModelIdx(0);
|
|
@@ -56317,8 +56626,30 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56317
56626
|
}
|
|
56318
56627
|
onCancel();
|
|
56319
56628
|
}, "back");
|
|
56320
|
-
|
|
56629
|
+
const close = /* @__PURE__ */ __name(() => {
|
|
56630
|
+
if (stage === "oauth") {
|
|
56631
|
+
cancelActiveOAuth();
|
|
56632
|
+
}
|
|
56633
|
+
onCancel();
|
|
56634
|
+
}, "close");
|
|
56635
|
+
useOverlayKeys({ onBack: back, onClose: close });
|
|
56321
56636
|
use_input_default((ch, key) => {
|
|
56637
|
+
if (stage === "oauth") {
|
|
56638
|
+
if (key.escape) {
|
|
56639
|
+
back();
|
|
56640
|
+
return;
|
|
56641
|
+
}
|
|
56642
|
+
if (key.return && oauthStatus === "error") {
|
|
56643
|
+
const slug = oauthProviderSlugRef.current;
|
|
56644
|
+
if (slug) {
|
|
56645
|
+
startOAuthFlow(slug);
|
|
56646
|
+
} else {
|
|
56647
|
+
back();
|
|
56648
|
+
}
|
|
56649
|
+
return;
|
|
56650
|
+
}
|
|
56651
|
+
return;
|
|
56652
|
+
}
|
|
56322
56653
|
if (stage === "key") {
|
|
56323
56654
|
if (keySaving) {
|
|
56324
56655
|
return;
|
|
@@ -56424,6 +56755,11 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56424
56755
|
setStage("key");
|
|
56425
56756
|
setKeyInput("");
|
|
56426
56757
|
setKeyError("");
|
|
56758
|
+
return;
|
|
56759
|
+
}
|
|
56760
|
+
if (provider.auth_type === "oauth") {
|
|
56761
|
+
startOAuthFlow(provider.slug);
|
|
56762
|
+
return;
|
|
56427
56763
|
}
|
|
56428
56764
|
return;
|
|
56429
56765
|
}
|
|
@@ -56470,6 +56806,41 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56470
56806
|
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Esc/q cancel" })
|
|
56471
56807
|
] });
|
|
56472
56808
|
}
|
|
56809
|
+
if (stage === "oauth") {
|
|
56810
|
+
const slug = oauthProviderSlugRef.current;
|
|
56811
|
+
const providerName = providers.find((p) => p.slug === slug)?.name ?? "GitHub Copilot";
|
|
56812
|
+
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
56813
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56814
|
+
"Sign in to ",
|
|
56815
|
+
providerName
|
|
56816
|
+
] }),
|
|
56817
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56818
|
+
oauthStatus === "starting" ? /* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "requesting device code\u2026" }) : oauthStatus === "error" ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
56819
|
+
/* @__PURE__ */ jsxs13(Text9, { color: t.color.label, wrap: "truncate-end", children: [
|
|
56820
|
+
"error: ",
|
|
56821
|
+
oauthError || "failed to start GitHub sign-in"
|
|
56822
|
+
] }),
|
|
56823
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56824
|
+
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Enter retry \xB7 Esc back" })
|
|
56825
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
56826
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "1. Open this URL in your browser:" }),
|
|
56827
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56828
|
+
" ",
|
|
56829
|
+
oauthVerificationUri
|
|
56830
|
+
] }),
|
|
56831
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56832
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "2. Enter this code on the GitHub page:" }),
|
|
56833
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
56834
|
+
" ",
|
|
56835
|
+
oauthUserCode
|
|
56836
|
+
] }),
|
|
56837
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56838
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "waiting for authorization\u2026" }),
|
|
56839
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }),
|
|
56840
|
+
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "Esc cancel" })
|
|
56841
|
+
] })
|
|
56842
|
+
] });
|
|
56843
|
+
}
|
|
56473
56844
|
if (stage === "key" && provider) {
|
|
56474
56845
|
const masked = keyInput ? "\u2022".repeat(Math.min(keyInput.length, 40)) : "";
|
|
56475
56846
|
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
@@ -57423,7 +57794,7 @@ var init_appOverlays = __esm({
|
|
|
57423
57794
|
|
|
57424
57795
|
// src/components/branding.tsx
|
|
57425
57796
|
import { useEffect as useEffect20, useState as useState24 } from "react";
|
|
57426
|
-
import { Fragment as
|
|
57797
|
+
import { Fragment as Fragment6, jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
57427
57798
|
function useColumns() {
|
|
57428
57799
|
const { stdout } = useStdout();
|
|
57429
57800
|
const [cols, setCols] = useState24(stdout?.columns ?? 80);
|
|
@@ -58864,7 +59235,7 @@ var init_syntax = __esm({
|
|
|
58864
59235
|
});
|
|
58865
59236
|
|
|
58866
59237
|
// src/components/markdown.tsx
|
|
58867
|
-
import { Fragment as
|
|
59238
|
+
import { Fragment as Fragment7, memo, useMemo as useMemo14 } from "react";
|
|
58868
59239
|
import { jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
58869
59240
|
function ResolvedLink({ fallbackLabel, t, url }) {
|
|
58870
59241
|
const fetched = useLinkTitle(url);
|
|
@@ -59396,7 +59767,7 @@ var init_markdown = __esm({
|
|
|
59396
59767
|
const cellWidth = /* @__PURE__ */ __name((raw) => stringWidth(stripInlineMarkup(raw)), "cellWidth");
|
|
59397
59768
|
const widths = rows[0].map((_, ci) => Math.max(...rows.map((r) => cellWidth(r[ci] ?? ""))));
|
|
59398
59769
|
const sep2 = widths.map((w) => "\u2500".repeat(Math.max(1, w))).join(" ");
|
|
59399
|
-
return /* @__PURE__ */ jsx34(Box_default, { flexDirection: "column", paddingLeft: 2, children: rows.map((row, ri) => /* @__PURE__ */ jsxs21(
|
|
59770
|
+
return /* @__PURE__ */ jsx34(Box_default, { flexDirection: "column", paddingLeft: 2, children: rows.map((row, ri) => /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
59400
59771
|
/* @__PURE__ */ jsx34(Box_default, { children: widths.map((w, ci) => /* @__PURE__ */ jsxs21(Text9, { bold: ri === 0, color: ri === 0 ? t.color.accent : void 0, children: [
|
|
59401
59772
|
/* @__PURE__ */ jsx34(MdInline, { t, text: row[ci] ?? "" }),
|
|
59402
59773
|
" ".repeat(Math.max(0, w - cellWidth(row[ci] ?? ""))),
|
|
@@ -59437,7 +59808,7 @@ var init_markdown = __esm({
|
|
|
59437
59808
|
});
|
|
59438
59809
|
|
|
59439
59810
|
// src/components/streamingMarkdown.tsx
|
|
59440
|
-
import { memo as memo2, useRef as
|
|
59811
|
+
import { memo as memo2, useRef as useRef18 } from "react";
|
|
59441
59812
|
import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
59442
59813
|
var fenceOpenAt, findStableBoundary, StreamingMd;
|
|
59443
59814
|
var init_streamingMarkdown = __esm({
|
|
@@ -59500,7 +59871,7 @@ var init_streamingMarkdown = __esm({
|
|
|
59500
59871
|
return -1;
|
|
59501
59872
|
}, "findStableBoundary");
|
|
59502
59873
|
StreamingMd = memo2(/* @__PURE__ */ __name(function StreamingMd2({ compact, t, text }) {
|
|
59503
|
-
const stablePrefixRef =
|
|
59874
|
+
const stablePrefixRef = useRef18("");
|
|
59504
59875
|
if (!text.startsWith(stablePrefixRef.current)) {
|
|
59505
59876
|
stablePrefixRef.current = "";
|
|
59506
59877
|
}
|
|
@@ -59527,7 +59898,7 @@ var init_streamingMarkdown = __esm({
|
|
|
59527
59898
|
// src/components/thinking.tsx
|
|
59528
59899
|
import { memo as memo3, useEffect as useEffect23, useMemo as useMemo15, useState as useState26 } from "react";
|
|
59529
59900
|
import spinners from "unicode-animations";
|
|
59530
|
-
import { Fragment as
|
|
59901
|
+
import { Fragment as Fragment8, jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
59531
59902
|
import { createElement } from "react";
|
|
59532
59903
|
function TreeRow({
|
|
59533
59904
|
branch,
|
|
@@ -59786,7 +60157,7 @@ function SubagentAccordion({
|
|
|
59786
60157
|
{
|
|
59787
60158
|
branch: index === item.tools.length - 1 ? "last" : "mid",
|
|
59788
60159
|
color: t.color.text,
|
|
59789
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60160
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
59790
60161
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u25CF " }),
|
|
59791
60162
|
line
|
|
59792
60163
|
] }),
|
|
@@ -60059,7 +60430,7 @@ var init_thinking = __esm({
|
|
|
60059
60430
|
color: t.color.muted,
|
|
60060
60431
|
dimColor: true,
|
|
60061
60432
|
key: `tr-${i}`,
|
|
60062
|
-
content: groups.length ? /* @__PURE__ */ jsxs23(
|
|
60433
|
+
content: groups.length ? /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60063
60434
|
/* @__PURE__ */ jsx36(Spinner3, { color: t.color.accent, variant: "think" }),
|
|
60064
60435
|
" ",
|
|
60065
60436
|
line
|
|
@@ -60076,7 +60447,7 @@ var init_thinking = __esm({
|
|
|
60076
60447
|
key: tool.id,
|
|
60077
60448
|
label,
|
|
60078
60449
|
details: [],
|
|
60079
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60450
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60080
60451
|
/* @__PURE__ */ jsx36(Spinner3, { color: t.color.accent, variant: "tool" }),
|
|
60081
60452
|
" ",
|
|
60082
60453
|
label,
|
|
@@ -60104,7 +60475,7 @@ var init_thinking = __esm({
|
|
|
60104
60475
|
const inlineDelegateKey = hasSubagents && delegateGroups.length === 1 ? delegateGroups[0].key : null;
|
|
60105
60476
|
const toolLabel = /* @__PURE__ */ __name((group) => {
|
|
60106
60477
|
const { duration, label } = splitToolDuration(String(group.content));
|
|
60107
|
-
return duration ? /* @__PURE__ */ jsxs23(
|
|
60478
|
+
return duration ? /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60108
60479
|
label,
|
|
60109
60480
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.statusFg, dim: true, children: duration })
|
|
60110
60481
|
] }) : group.content;
|
|
@@ -60216,7 +60587,7 @@ var init_thinking = __esm({
|
|
|
60216
60587
|
{
|
|
60217
60588
|
branch,
|
|
60218
60589
|
color: group.color,
|
|
60219
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60590
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60220
60591
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u25CF " }),
|
|
60221
60592
|
toolLabel(group)
|
|
60222
60593
|
] }),
|
|
@@ -60319,7 +60690,7 @@ var init_thinking = __esm({
|
|
|
60319
60690
|
{
|
|
60320
60691
|
branch: "last",
|
|
60321
60692
|
color: t.color.statusFg,
|
|
60322
|
-
content: /* @__PURE__ */ jsxs23(
|
|
60693
|
+
content: /* @__PURE__ */ jsxs23(Fragment8, { children: [
|
|
60323
60694
|
/* @__PURE__ */ jsx36(Text9, { color: t.color.accent, children: "\u03A3 " }),
|
|
60324
60695
|
totalTokensLabel
|
|
60325
60696
|
] }),
|
|
@@ -60622,7 +60993,7 @@ var init_queuedMessages = __esm({
|
|
|
60622
60993
|
// src/components/streamingAssistant.tsx
|
|
60623
60994
|
import { useStore as useStore8 } from "@nanostores/react";
|
|
60624
60995
|
import { memo as memo6 } from "react";
|
|
60625
|
-
import { Fragment as
|
|
60996
|
+
import { Fragment as Fragment9, jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
60626
60997
|
var groupedSegments, StreamingAssistant, LiveTodoPanel;
|
|
60627
60998
|
var init_streamingAssistant = __esm({
|
|
60628
60999
|
"src/components/streamingAssistant.tsx"() {
|
|
@@ -60650,7 +61021,7 @@ var init_streamingAssistant = __esm({
|
|
|
60650
61021
|
if (!progress.showProgressArea && !showStreamingArea && !activeTools.length) {
|
|
60651
61022
|
return null;
|
|
60652
61023
|
}
|
|
60653
|
-
return /* @__PURE__ */ jsxs27(
|
|
61024
|
+
return /* @__PURE__ */ jsxs27(Fragment9, { children: [
|
|
60654
61025
|
groupedSegments(streamSegments).map((msg, i) => /* @__PURE__ */ jsx40(
|
|
60655
61026
|
MessageLine,
|
|
60656
61027
|
{
|
|
@@ -60719,8 +61090,8 @@ var init_streamingAssistant = __esm({
|
|
|
60719
61090
|
|
|
60720
61091
|
// src/components/appLayout.tsx
|
|
60721
61092
|
import { useStore as useStore9 } from "@nanostores/react";
|
|
60722
|
-
import { Fragment as
|
|
60723
|
-
import { Fragment as
|
|
61093
|
+
import { Fragment as Fragment10, memo as memo7, useMemo as useMemo16, useRef as useRef19 } from "react";
|
|
61094
|
+
import { Fragment as Fragment11, jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
60724
61095
|
var PromptPrefix, TranscriptPane, ComposerPane, AgentsOverlayPane, StatusRulePane, AppLayout;
|
|
60725
61096
|
var init_appLayout = __esm({
|
|
60726
61097
|
"src/components/appLayout.tsx"() {
|
|
@@ -60776,7 +61147,7 @@ var init_appLayout = __esm({
|
|
|
60776
61147
|
() => transcript.historyItems.findIndex((m) => m.role === "user"),
|
|
60777
61148
|
[transcript.historyItems]
|
|
60778
61149
|
);
|
|
60779
|
-
return /* @__PURE__ */ jsxs28(
|
|
61150
|
+
return /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
60780
61151
|
/* @__PURE__ */ jsx41(
|
|
60781
61152
|
ScrollBox_default,
|
|
60782
61153
|
{
|
|
@@ -60850,7 +61221,7 @@ var init_appLayout = __esm({
|
|
|
60850
61221
|
const promptBlank = " ".repeat(promptWidth);
|
|
60851
61222
|
const inputColumns = stableComposerColumns(composer.cols, promptWidth);
|
|
60852
61223
|
const inputHeight = inputVisualHeight(composer.input, inputColumns);
|
|
60853
|
-
const inputMouseRef =
|
|
61224
|
+
const inputMouseRef = useRef19(null);
|
|
60854
61225
|
const captureInputDrag = /* @__PURE__ */ __name((e) => {
|
|
60855
61226
|
if (e.button !== 0) {
|
|
60856
61227
|
return;
|
|
@@ -60920,7 +61291,7 @@ var init_appLayout = __esm({
|
|
|
60920
61291
|
}
|
|
60921
61292
|
),
|
|
60922
61293
|
composer.input === "?" && !composer.inputBuf.length && /* @__PURE__ */ jsx41(HelpHint, { t: ui.theme }),
|
|
60923
|
-
!isBlocked && /* @__PURE__ */ jsxs28(
|
|
61294
|
+
!isBlocked && /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
60924
61295
|
composer.inputBuf.map((line, i) => /* @__PURE__ */ jsxs28(Box_default, { children: [
|
|
60925
61296
|
/* @__PURE__ */ jsx41(Box_default, { width: promptWidth, children: i === 0 ? /* @__PURE__ */ jsx41(PromptPrefix, { color: ui.theme.color.muted, promptText, width: promptWidth }) : /* @__PURE__ */ jsx41(Text9, { color: ui.theme.color.muted, children: promptBlank }) }),
|
|
60926
61297
|
/* @__PURE__ */ jsx41(Text9, { color: ui.theme.color.composeText, children: line || " " })
|
|
@@ -61026,11 +61397,11 @@ var init_appLayout = __esm({
|
|
|
61026
61397
|
}) {
|
|
61027
61398
|
const overlay = useStore9($overlayState);
|
|
61028
61399
|
const ui = useStore9($uiState);
|
|
61029
|
-
const Shell = INLINE_MODE ?
|
|
61400
|
+
const Shell = INLINE_MODE ? Fragment10 : AlternateScreen;
|
|
61030
61401
|
const shellProps = INLINE_MODE ? {} : { mouseTracking };
|
|
61031
61402
|
return /* @__PURE__ */ jsx41(Shell, { ...shellProps, children: /* @__PURE__ */ jsxs28(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
61032
61403
|
/* @__PURE__ */ jsx41(Box_default, { flexDirection: "row", flexGrow: 1, children: overlay.agents ? /* @__PURE__ */ jsx41(PerfPane, { id: "agents", children: /* @__PURE__ */ jsx41(AgentsOverlayPane, {}) }) : /* @__PURE__ */ jsx41(PerfPane, { id: "transcript", children: /* @__PURE__ */ jsx41(TranscriptPane, { actions, composer, progress, transcript }) }) }),
|
|
61033
|
-
!overlay.agents && /* @__PURE__ */ jsxs28(
|
|
61404
|
+
!overlay.agents && /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
61034
61405
|
/* @__PURE__ */ jsx41(PerfPane, { id: "prompt", children: /* @__PURE__ */ jsx41(
|
|
61035
61406
|
PromptZone,
|
|
61036
61407
|
{
|