@anhlp/alp-paseo 0.0.0-beta.2 → 0.0.1-beta.3
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 +16 -4
- package/client/library.tsx +22 -6
- package/package.json +14 -14
- package/paseo-plugin.json +1 -1
- package/server/dist/THIRD-PARTY-NOTICES.txt +2 -2
- package/server/dist/alpd.js +705 -326
- package/server/dist/index.js +686 -273
- package/server/dist/library.js +65 -9
- package/server/dist/main.js +284 -102
- package/server/dist/mapping.js +4 -2
- package/server/dist/panel/library.js +65 -9
- package/server/dist/panel/mapping.js +4 -2
- package/server/dist/panel/tasks.js +1 -1
- package/server/dist/panel/usage.js +3 -3
- package/server/dist/paseo/agents.js +62 -18
- package/server/dist/paseo/index.js +166 -68
- package/server/dist/paseo/plugins.js +84 -28
- package/server/dist/paseo/providers.js +44 -3
- package/server/dist/provider-core.js +14 -0
- package/server/dist/provider.js +574 -209
- package/server/dist/remote/index.js +34 -5
- package/server/dist/remote/link.js +1 -1
- package/server/dist/remote/panels.js +20 -5
- package/server/dist/remote/provider.js +15 -1
- package/server/dist/session-usage.js +15 -0
- package/server/dist/tasks.js +1 -1
- package/server/dist/usage.js +3 -3
- package/server/dist/web.js +1 -1
- package/shared/library.ts +2 -0
package/server/dist/main.js
CHANGED
|
@@ -178,7 +178,7 @@ var init_wire = __esm({
|
|
|
178
178
|
};
|
|
179
179
|
ERROR = Object.freeze({ failed: 1e3, notFound: 1001, forbidden: 1003, conflict: 1004, unavailable: 1005, protocol: 1006 });
|
|
180
180
|
RPC_ERROR = Object.freeze({ parseError: -32700, invalidRequest: -32600, methodNotFound: -32601, invalidParams: -32602 });
|
|
181
|
-
CAPABILITY = Object.freeze({ attachAfter: "attach.after", promptReceipts: "prompt.receipts", extensionMethods: "extension.methods", team: "team", task: "task", library: "library", settingsLanguage: "settings.language", sessionListPage: "session.list.page", questionWatch: "question.watch", questionWatchTurns: "question.watch.turns", workspaceFiles: "workspace.files", workspaceFilesRead: "workspace.files.read", promptImages: "prompt.images" });
|
|
181
|
+
CAPABILITY = Object.freeze({ attachAfter: "attach.after", promptReceipts: "prompt.receipts", extensionMethods: "extension.methods", team: "team", task: "task", library: "library", libraryProjectWrite: "library.project.write", settingsLanguage: "settings.language", sessionListPage: "session.list.page", questionWatch: "question.watch", questionWatchTurns: "question.watch.turns", workspaceFiles: "workspace.files", workspaceFilesRead: "workspace.files.read", promptImages: "prompt.images" });
|
|
182
182
|
PROMPT_IMAGES = Object.freeze({ mimeTypes: Object.freeze(["image/png", "image/jpeg", "image/gif", "image/webp"]), maxCount: 8, maxBytes: 5 * 1024 * 1024, maxTotalBytes: 11 * 1024 * 1024 });
|
|
183
183
|
RPC_METHODS = Object.freeze(["assignment.recall", "board.list", "catalog.get", "daemon.hello", "daemon.pause", "daemon.pauses", "daemon.resume", "daemon.shutdown", "daemon.status", "daemon.usage", "extension.register", "extension.unregister", "library.delete", "library.duplicate", "library.get", "library.list", "library.models", "library.rename", "library.save", "library.skills.set", "question.answer", "question.list", "question.watch", "session.archive", "session.attach", "session.close", "session.configure", "session.create", "session.get", "session.interrupt", "session.list", "session.log", "session.message", "session.preview", "session.prompt", "session.release", "session.rename", "session.status", "settings.language.get", "settings.language.set", "task.create", "task.gate.resolve", "task.list", "task.update", "team.list", "workspace.files.list", "workspace.files.read", "workspace.files.search"]);
|
|
184
184
|
WORKSPACE_FILES = Object.freeze({ maxReadBytes: 1024 * 1024, maxListEntries: 1e3, maxPathLength: 4096 });
|
|
@@ -1138,17 +1138,19 @@ __export(src_exports, {
|
|
|
1138
1138
|
hello: () => hello,
|
|
1139
1139
|
isAlpClientError: () => isAlpClientError,
|
|
1140
1140
|
lockAlive: () => lockAlive,
|
|
1141
|
+
readDaemonLifecycle: () => readDaemonLifecycle,
|
|
1141
1142
|
readLock: () => readLock,
|
|
1142
1143
|
redactUrl: () => redactUrl,
|
|
1143
1144
|
releaseDaemonLock: () => releaseDaemonLock,
|
|
1144
1145
|
retryable: () => retryable,
|
|
1145
1146
|
startIntegration: () => startIntegration,
|
|
1146
1147
|
timerDelay: () => timerDelay,
|
|
1147
|
-
utf8Length: () => utf8Length
|
|
1148
|
+
utf8Length: () => utf8Length,
|
|
1149
|
+
withDaemonLifecycle: () => withDaemonLifecycle
|
|
1148
1150
|
});
|
|
1149
1151
|
import { spawn } from "node:child_process";
|
|
1150
|
-
import { createHash } from "node:crypto";
|
|
1151
|
-
import { open, readFile, realpath, stat, lstat, mkdir, readlink, unlink } from "node:fs/promises";
|
|
1152
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
1153
|
+
import { open, readFile, writeFile, realpath, stat, lstat, mkdir, readlink, unlink, readdir, rename, rmdir, link } from "node:fs/promises";
|
|
1152
1154
|
import net from "node:net";
|
|
1153
1155
|
import os from "node:os";
|
|
1154
1156
|
import path from "node:path";
|
|
@@ -1324,10 +1326,86 @@ async function tail(file2, lines = 30) {
|
|
|
1324
1326
|
return "";
|
|
1325
1327
|
}
|
|
1326
1328
|
}
|
|
1329
|
+
async function lifecycleOwners(home2) {
|
|
1330
|
+
const directory = path.join(home2, "state", "alpd.starting");
|
|
1331
|
+
const names = await readdir(directory).catch((error51) => {
|
|
1332
|
+
if (error51.code === "ENOENT") return [];
|
|
1333
|
+
throw error51;
|
|
1334
|
+
});
|
|
1335
|
+
return names.map((token) => {
|
|
1336
|
+
const match = /^owner-(\d+)-(\d+)-(start|stop)-[a-f0-9-]+$/.exec(token);
|
|
1337
|
+
if (!match) throw new Error("Invalid alpd startup admission owner");
|
|
1338
|
+
return { token, pid: Number(match[1]), bootTime: Number(match[2]), action: match[3] };
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
async function readDaemonLifecycle(home2) {
|
|
1342
|
+
return (await lifecycleOwners(home2)).find((owner) => lockAlive(owner));
|
|
1343
|
+
}
|
|
1344
|
+
async function withDaemonLifecycle(home2, action, run3, { joinStart = false } = {}) {
|
|
1345
|
+
try {
|
|
1346
|
+
await assertPrivateDirectory(home2, { create: true });
|
|
1347
|
+
} catch (cause) {
|
|
1348
|
+
throw Object.assign(new Error(`ALP_HOME_UNUSABLE, alpd failed to start while preparing its home: ${cause.message}`, { cause }), { code: "ALP_HOME_UNUSABLE" });
|
|
1349
|
+
}
|
|
1350
|
+
const state = path.join(home2, "state");
|
|
1351
|
+
await assertPrivateDirectory(state, { create: true });
|
|
1352
|
+
const directory = path.join(state, "alpd.starting");
|
|
1353
|
+
const token = `owner-${process.pid}-${bootTime()}-${action}-${randomUUID()}`;
|
|
1354
|
+
const candidate = path.join(state, `alpd.starting-${token}`);
|
|
1355
|
+
await mkdir(candidate, { mode: 448 });
|
|
1356
|
+
await writeFile(path.join(candidate, token), JSON.stringify({ pid: process.pid, bootTime: bootTime(), action }), { mode: 384 });
|
|
1357
|
+
try {
|
|
1358
|
+
let joined = false;
|
|
1359
|
+
if (joinStart) {
|
|
1360
|
+
const owner = await readDaemonLifecycle(home2);
|
|
1361
|
+
if (owner?.action === "start") {
|
|
1362
|
+
try {
|
|
1363
|
+
await link(path.join(directory, owner.token), path.join(directory, token));
|
|
1364
|
+
joined = true;
|
|
1365
|
+
} catch (error51) {
|
|
1366
|
+
if (error51.code !== "ENOENT") throw error51;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
while (!joined) {
|
|
1371
|
+
try {
|
|
1372
|
+
await rename(candidate, directory);
|
|
1373
|
+
break;
|
|
1374
|
+
} catch (error51) {
|
|
1375
|
+
if (!["EEXIST", "ENOTEMPTY", "EPERM", "EACCES"].includes(error51.code)) throw error51;
|
|
1376
|
+
for (const owner of await lifecycleOwners(home2)) {
|
|
1377
|
+
if (!lockAlive(owner)) await unlink(path.join(directory, owner.token)).catch((error52) => {
|
|
1378
|
+
if (error52.code !== "ENOENT") throw error52;
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
await rmdir(directory).catch((error52) => {
|
|
1382
|
+
if (!["ENOENT", "ENOTEMPTY", "EEXIST"].includes(error52.code)) throw error52;
|
|
1383
|
+
});
|
|
1384
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
try {
|
|
1388
|
+
return await run3();
|
|
1389
|
+
} finally {
|
|
1390
|
+
await unlink(path.join(directory, token));
|
|
1391
|
+
await rmdir(directory).catch((error51) => {
|
|
1392
|
+
if (!["ENOENT", "ENOTEMPTY", "EEXIST"].includes(error51.code)) throw error51;
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
} finally {
|
|
1396
|
+
await unlink(path.join(candidate, token)).catch((error51) => {
|
|
1397
|
+
if (error51.code !== "ENOENT") throw error51;
|
|
1398
|
+
});
|
|
1399
|
+
await rmdir(candidate).catch((error51) => {
|
|
1400
|
+
if (error51.code !== "ENOENT") throw error51;
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1327
1404
|
async function ensureDaemon({ home: home2 = alpHome(), entry = (
|
|
1328
1405
|
/** @type {string | undefined} */
|
|
1329
1406
|
void 0
|
|
1330
|
-
), env = process.env, execPath = process.execPath, timeoutMs = 15e3 } = {}) {
|
|
1407
|
+
), env = process.env, execPath = process.execPath, timeoutMs = 15e3, lifecycleLocked = false } = {}) {
|
|
1408
|
+
if (!lifecycleLocked) return withDaemonLifecycle(home2, "start", () => ensureDaemon({ home: home2, entry, env, execPath, timeoutMs, lifecycleLocked: true }));
|
|
1331
1409
|
const ready = async () => {
|
|
1332
1410
|
const lock = await readLock(home2);
|
|
1333
1411
|
return lockAlive(lock) && lock.ready ? lock.socket : void 0;
|
|
@@ -1340,7 +1418,7 @@ async function ensureDaemon({ home: home2 = alpHome(), entry = (
|
|
|
1340
1418
|
entry ??= await findDaemonEntry({ home: home2, env });
|
|
1341
1419
|
if (!entry) throw new Error("ALP daemon is not running and alpd.js was not found. Install the ALP CLI and run `alp daemon start`, or set ALP_DAEMON_ENTRY to alpd.js");
|
|
1342
1420
|
await new Promise((resolve, reject) => {
|
|
1343
|
-
const launcher = spawn(execPath, [entry, "--detach"], {
|
|
1421
|
+
const launcher = spawn(execPath, [entry, "--detach", `--startup-timeout=${timeoutMs}`], {
|
|
1344
1422
|
env: { ...env, ALP_HOME: home2, ELECTRON_RUN_AS_NODE: "1" },
|
|
1345
1423
|
stdio: ["ignore", "ignore", "pipe"],
|
|
1346
1424
|
windowsHide: true
|
|
@@ -15323,7 +15401,7 @@ var require_base64_js = __commonJS({
|
|
|
15323
15401
|
|
|
15324
15402
|
// integrations/paseo/server/main.ts
|
|
15325
15403
|
init_src2();
|
|
15326
|
-
import { mkdir as mkdir12, open as open3, readFile as readFile13, rename as
|
|
15404
|
+
import { mkdir as mkdir12, open as open3, readFile as readFile13, rename as rename8, stat as stat10, unlink as unlink4, writeFile as writeFile13 } from "node:fs/promises";
|
|
15327
15405
|
import { mkdirSync } from "node:fs";
|
|
15328
15406
|
import { openSync, writeSync } from "node:fs";
|
|
15329
15407
|
import path24 from "node:path";
|
|
@@ -15331,12 +15409,12 @@ import { fileURLToPath } from "node:url";
|
|
|
15331
15409
|
|
|
15332
15410
|
// packages/client/src/supervise.js
|
|
15333
15411
|
init_src2();
|
|
15334
|
-
import { mkdir as mkdir3, unlink as unlink3, writeFile as
|
|
15412
|
+
import { mkdir as mkdir3, unlink as unlink3, writeFile as writeFile3, stat as stat2 } from "node:fs/promises";
|
|
15335
15413
|
import path3 from "node:path";
|
|
15336
15414
|
|
|
15337
15415
|
// packages/client/src/service.js
|
|
15338
15416
|
import { createHash as createHash2 } from "node:crypto";
|
|
15339
|
-
import { mkdir as mkdir2, readFile as readFile2, unlink as unlink2, writeFile } from "node:fs/promises";
|
|
15417
|
+
import { mkdir as mkdir2, readFile as readFile2, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
|
|
15340
15418
|
import os2 from "node:os";
|
|
15341
15419
|
import path2 from "node:path";
|
|
15342
15420
|
|
|
@@ -15445,16 +15523,20 @@ async function whenReady(home2, timeoutMs) {
|
|
|
15445
15523
|
}
|
|
15446
15524
|
throw new Error(`alpd did not become ready within ${timeoutMs / 1e3} s; see ${path3.join(home2, "logs")}`);
|
|
15447
15525
|
}
|
|
15448
|
-
async function startDaemon({ home: home2, entry, env = process.env, timeoutMs = 15e3 }) {
|
|
15449
|
-
|
|
15450
|
-
|
|
15451
|
-
|
|
15452
|
-
|
|
15453
|
-
|
|
15454
|
-
|
|
15455
|
-
|
|
15456
|
-
|
|
15457
|
-
|
|
15526
|
+
async function startDaemon({ home: home2, entry, env = process.env, timeoutMs = 15e3, automatic = false }) {
|
|
15527
|
+
return withDaemonLifecycle(home2, "start", async () => {
|
|
15528
|
+
if (automatic) {
|
|
15529
|
+
if (await daemonHeld(home2)) return;
|
|
15530
|
+
} else await releaseHold(home2);
|
|
15531
|
+
const lock = await readLock(home2);
|
|
15532
|
+
if (lockAlive(lock)) return lock.ready ? lock.socket : whenReady(home2, timeoutMs);
|
|
15533
|
+
const service = serviceFor({ home: home2, env });
|
|
15534
|
+
if (service && await installedProgram(service)) {
|
|
15535
|
+
await startService(service);
|
|
15536
|
+
return whenReady(home2, timeoutMs);
|
|
15537
|
+
}
|
|
15538
|
+
return ensureDaemon({ home: home2, entry, env, timeoutMs, lifecycleLocked: true });
|
|
15539
|
+
});
|
|
15458
15540
|
}
|
|
15459
15541
|
function superviseDaemon({ home: home2, entry, env = process.env, intervalMs = 5e3, misses = 2, log: log3 = () => {
|
|
15460
15542
|
} }) {
|
|
@@ -15462,7 +15544,9 @@ function superviseDaemon({ home: home2, entry, env = process.env, intervalMs = 5
|
|
|
15462
15544
|
let missed = 0;
|
|
15463
15545
|
let starting;
|
|
15464
15546
|
const start = (reason) => {
|
|
15465
|
-
starting ??= startDaemon({ home: home2, entry: typeof entry === "function" ? entry() : entry, env
|
|
15547
|
+
starting ??= startDaemon({ home: home2, entry: typeof entry === "function" ? entry() : entry, env, automatic: reason !== "started with Paseo" }).then((socket) => {
|
|
15548
|
+
if (socket) log3(`alpd ${reason}`);
|
|
15549
|
+
}, (error51) => log3(`could not start alpd: ${error51?.message ?? error51}`)).finally(() => {
|
|
15466
15550
|
starting = void 0;
|
|
15467
15551
|
missed = 0;
|
|
15468
15552
|
});
|
|
@@ -15549,11 +15633,11 @@ var MODELS = [
|
|
|
15549
15633
|
].map(([runtime, id2, label, description, efforts, effort]) => ({ runtime, id: id2, label, description, efforts, ...effort ? { effort } : {} }));
|
|
15550
15634
|
|
|
15551
15635
|
// packages/core/src/atomic.js
|
|
15552
|
-
import { rename, rm, writeFile as
|
|
15636
|
+
import { rename as rename2, rm, writeFile as writeFile4 } from "node:fs/promises";
|
|
15553
15637
|
async function moveFile(from, to) {
|
|
15554
15638
|
for (let attempt = 0; ; attempt++) {
|
|
15555
15639
|
try {
|
|
15556
|
-
return await
|
|
15640
|
+
return await rename2(from, to);
|
|
15557
15641
|
} catch (error51) {
|
|
15558
15642
|
if (process.platform !== "win32" || attempt >= 20 || !["EPERM", "EACCES", "EBUSY"].includes(error51?.code)) throw error51;
|
|
15559
15643
|
await new Promise((resolve) => setTimeout(resolve, 10 + attempt * 10));
|
|
@@ -15923,7 +16007,7 @@ init_log();
|
|
|
15923
16007
|
// integrations/paseo/server/web.ts
|
|
15924
16008
|
import { randomBytes } from "node:crypto";
|
|
15925
16009
|
import { createReadStream } from "node:fs";
|
|
15926
|
-
import { mkdir as mkdir4, readFile as readFile3, rename as
|
|
16010
|
+
import { mkdir as mkdir4, readFile as readFile3, rename as rename3, stat as stat3, writeFile as writeFile5 } from "node:fs/promises";
|
|
15927
16011
|
import http from "node:http";
|
|
15928
16012
|
import path5 from "node:path";
|
|
15929
16013
|
|
|
@@ -16112,8 +16196,8 @@ function createWebServer({ app, home: home2, port = DEFAULT_WEB_PORT, log: log3
|
|
|
16112
16196
|
bound = server.address().port;
|
|
16113
16197
|
const info = { port: bound, token, url: `http://127.0.0.1:${bound}/`, pid: process.pid, serverId };
|
|
16114
16198
|
await mkdir4(home2, { recursive: true, mode: 448 });
|
|
16115
|
-
await
|
|
16116
|
-
await
|
|
16199
|
+
await writeFile5(`${webFile(home2)}.tmp`, JSON.stringify(info), { mode: 384 });
|
|
16200
|
+
await rename3(`${webFile(home2)}.tmp`, webFile(home2));
|
|
16117
16201
|
return info;
|
|
16118
16202
|
},
|
|
16119
16203
|
async close() {
|
|
@@ -16129,8 +16213,8 @@ import { existsSync as existsSync3 } from "node:fs";
|
|
|
16129
16213
|
import path23 from "node:path";
|
|
16130
16214
|
|
|
16131
16215
|
// packages/core/src/user-settings.js
|
|
16132
|
-
import { mkdir as mkdir5, readFile as readFile4, writeFile as
|
|
16133
|
-
import { randomUUID } from "node:crypto";
|
|
16216
|
+
import { mkdir as mkdir5, readFile as readFile4, writeFile as writeFile6 } from "node:fs/promises";
|
|
16217
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
16134
16218
|
import path6 from "node:path";
|
|
16135
16219
|
var DEFAULT_LANGUAGE = "Vietnamese";
|
|
16136
16220
|
var LANGUAGE_CHARS = 40;
|
|
@@ -16174,8 +16258,8 @@ async function setLanguage(home2, language) {
|
|
|
16174
16258
|
else next.language = language.trim();
|
|
16175
16259
|
validateUserSettings(next, file2);
|
|
16176
16260
|
await mkdir5(home2, { recursive: true, mode: 448 });
|
|
16177
|
-
const temporary = `${file2}.${
|
|
16178
|
-
await
|
|
16261
|
+
const temporary = `${file2}.${randomUUID2().slice(0, 8)}.tmp`;
|
|
16262
|
+
await writeFile6(temporary, JSON.stringify(next, null, 2) + "\n");
|
|
16179
16263
|
await moveFile(temporary, file2);
|
|
16180
16264
|
return languageSetting(home2);
|
|
16181
16265
|
}
|
|
@@ -16184,8 +16268,8 @@ async function setWebRelay(home2, patch) {
|
|
|
16184
16268
|
const next = { ...settings, web: { ...settings.web, relay: { ...settings.web?.relay, ...patch } } };
|
|
16185
16269
|
validateUserSettings(next, file2);
|
|
16186
16270
|
await mkdir5(home2, { recursive: true, mode: 448 });
|
|
16187
|
-
const temporary = `${file2}.${
|
|
16188
|
-
await
|
|
16271
|
+
const temporary = `${file2}.${randomUUID2().slice(0, 8)}.tmp`;
|
|
16272
|
+
await writeFile6(temporary, JSON.stringify(next, null, 2) + "\n");
|
|
16189
16273
|
await moveFile(temporary, file2);
|
|
16190
16274
|
return next.web.relay;
|
|
16191
16275
|
}
|
|
@@ -16254,11 +16338,11 @@ var CHOICES = {
|
|
|
16254
16338
|
};
|
|
16255
16339
|
|
|
16256
16340
|
// integrations/paseo/server/paseo/agents.ts
|
|
16257
|
-
import { randomUUID as
|
|
16341
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
16258
16342
|
import path15 from "node:path";
|
|
16259
16343
|
|
|
16260
16344
|
// packages/core/src/teams.js
|
|
16261
|
-
import { readdir as
|
|
16345
|
+
import { readdir as readdir4 } from "node:fs/promises";
|
|
16262
16346
|
import path9 from "node:path";
|
|
16263
16347
|
|
|
16264
16348
|
// packages/core/src/template-path.js
|
|
@@ -16270,12 +16354,12 @@ function shippedTemplateRoot() {
|
|
|
16270
16354
|
}
|
|
16271
16355
|
|
|
16272
16356
|
// packages/core/src/resolver.js
|
|
16273
|
-
import { readFile as readFile6, readdir as
|
|
16357
|
+
import { readFile as readFile6, readdir as readdir3, stat as stat4 } from "node:fs/promises";
|
|
16274
16358
|
import path8 from "node:path";
|
|
16275
16359
|
|
|
16276
16360
|
// packages/core/src/library.js
|
|
16277
|
-
import { mkdir as mkdir6, readFile as readFile5, readdir, writeFile as
|
|
16278
|
-
import { createHash as createHash3, randomUUID as
|
|
16361
|
+
import { mkdir as mkdir6, readFile as readFile5, readdir as readdir2, writeFile as writeFile7 } from "node:fs/promises";
|
|
16362
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
|
|
16279
16363
|
import path7 from "node:path";
|
|
16280
16364
|
var MANIFEST = "library.json";
|
|
16281
16365
|
var sha = (text) => createHash3("sha256").update(text.replaceAll("\r\n", "\n")).digest("hex");
|
|
@@ -16292,7 +16376,7 @@ async function shippedFiles({ templateRoot: templateRoot2, templates: templates2
|
|
|
16292
16376
|
const root = templateRoot2 ?? shippedTemplateRoot();
|
|
16293
16377
|
const files = { "role-skills.json": await readFile5(new URL("role-skills.json", root), "utf8") };
|
|
16294
16378
|
async function walk(relative) {
|
|
16295
|
-
for (const entry of await
|
|
16379
|
+
for (const entry of await readdir2(new URL(`${relative}/`, root), { withFileTypes: true })) {
|
|
16296
16380
|
if (entry.isDirectory()) await walk(`${relative}/${entry.name}`);
|
|
16297
16381
|
else if (entry.isFile()) files[`${relative}/${entry.name}`] = await readFile5(new URL(`${relative}/${entry.name}`, root), "utf8");
|
|
16298
16382
|
}
|
|
@@ -16316,21 +16400,21 @@ async function seedLibrary(home2, options2 = {}) {
|
|
|
16316
16400
|
if (seeded === void 0) {
|
|
16317
16401
|
if (current !== void 0) continue;
|
|
16318
16402
|
await mkdir6(path7.dirname(target), { recursive: true });
|
|
16319
|
-
await
|
|
16403
|
+
await writeFile7(target, content, { flag: "wx" }).catch((error51) => {
|
|
16320
16404
|
if (error51.code !== "EEXIST") throw error51;
|
|
16321
16405
|
});
|
|
16322
16406
|
manifest.files[name] = sha(content);
|
|
16323
16407
|
created.push(name);
|
|
16324
16408
|
} else if (current !== void 0 && sha(current) === seeded && seeded !== sha(content)) {
|
|
16325
|
-
await
|
|
16409
|
+
await writeFile7(target, content);
|
|
16326
16410
|
manifest.files[name] = sha(content);
|
|
16327
16411
|
updated.push(name);
|
|
16328
16412
|
}
|
|
16329
16413
|
}
|
|
16330
16414
|
if (created.length || updated.length || manifestText === void 0) {
|
|
16331
16415
|
await mkdir6(home2, { recursive: true });
|
|
16332
|
-
const temporary = `${manifestPath}.${
|
|
16333
|
-
await
|
|
16416
|
+
const temporary = `${manifestPath}.${randomUUID3().slice(0, 8)}.tmp`;
|
|
16417
|
+
await writeFile7(temporary, JSON.stringify(manifest, null, 2) + "\n");
|
|
16334
16418
|
await moveFile(temporary, manifestPath);
|
|
16335
16419
|
}
|
|
16336
16420
|
return { created, updated };
|
|
@@ -16370,7 +16454,7 @@ async function jsonObject(file2, code) {
|
|
|
16370
16454
|
}
|
|
16371
16455
|
async function entries(directory) {
|
|
16372
16456
|
try {
|
|
16373
|
-
return (await
|
|
16457
|
+
return (await readdir3(directory, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
|
|
16374
16458
|
} catch (error51) {
|
|
16375
16459
|
if (error51.code === "ENOENT") return [];
|
|
16376
16460
|
throw error51;
|
|
@@ -16546,7 +16630,7 @@ function validateTeam(config2, source) {
|
|
|
16546
16630
|
}
|
|
16547
16631
|
async function directories(directory) {
|
|
16548
16632
|
try {
|
|
16549
|
-
return (await
|
|
16633
|
+
return (await readdir4(directory, { withFileTypes: true })).filter((entry) => entry.isDirectory() && validName2(entry.name)).map((entry) => entry.name).sort();
|
|
16550
16634
|
} catch (error51) {
|
|
16551
16635
|
if (error51.code === "ENOENT") return [];
|
|
16552
16636
|
throw error51;
|
|
@@ -16624,8 +16708,8 @@ init_src();
|
|
|
16624
16708
|
var PIN_KINDS = ["claim", "decision", "finding"];
|
|
16625
16709
|
|
|
16626
16710
|
// packages/core/src/tasks.js
|
|
16627
|
-
import { mkdir as mkdir7, readFile as readFile7, readdir as
|
|
16628
|
-
import { createHash as createHash4, randomUUID as
|
|
16711
|
+
import { mkdir as mkdir7, readFile as readFile7, readdir as readdir5, rmdir as rmdir2, stat as stat5, writeFile as writeFile8 } from "node:fs/promises";
|
|
16712
|
+
import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
|
|
16629
16713
|
import path11 from "node:path";
|
|
16630
16714
|
|
|
16631
16715
|
// packages/core/src/safe-path.js
|
|
@@ -16681,7 +16765,7 @@ async function taskNames(projectRoot) {
|
|
|
16681
16765
|
await assertNoSymlinks(scope, "tasks");
|
|
16682
16766
|
let names;
|
|
16683
16767
|
try {
|
|
16684
|
-
names = await
|
|
16768
|
+
names = await readdir5(tasksDir(projectRoot));
|
|
16685
16769
|
} catch (error51) {
|
|
16686
16770
|
if (error51.code === "ENOENT") return [];
|
|
16687
16771
|
throw error51;
|
|
@@ -16851,7 +16935,7 @@ async function locked(projectRoot, work) {
|
|
|
16851
16935
|
if (error51.code !== "EEXIST") throw error51;
|
|
16852
16936
|
const age = await stat5(lock).then((info) => Date.now() - info.mtimeMs, () => 0);
|
|
16853
16937
|
if (age > LOCK_STALE_MS) {
|
|
16854
|
-
await
|
|
16938
|
+
await rmdir2(lock).catch(() => {
|
|
16855
16939
|
});
|
|
16856
16940
|
continue;
|
|
16857
16941
|
}
|
|
@@ -16862,7 +16946,7 @@ async function locked(projectRoot, work) {
|
|
|
16862
16946
|
try {
|
|
16863
16947
|
return await work();
|
|
16864
16948
|
} finally {
|
|
16865
|
-
await
|
|
16949
|
+
await rmdir2(lock).catch(() => {
|
|
16866
16950
|
});
|
|
16867
16951
|
}
|
|
16868
16952
|
});
|
|
@@ -16871,15 +16955,15 @@ async function locked(projectRoot, work) {
|
|
|
16871
16955
|
}
|
|
16872
16956
|
async function prepare(dir) {
|
|
16873
16957
|
await mkdir7(dir, { recursive: true });
|
|
16874
|
-
await
|
|
16958
|
+
await writeFile8(path11.join(dir, ".gitignore"), GITIGNORE, { flag: "wx" }).catch((error51) => {
|
|
16875
16959
|
if (error51.code !== "EEXIST") throw error51;
|
|
16876
16960
|
});
|
|
16877
16961
|
}
|
|
16878
16962
|
async function save(projectRoot, task) {
|
|
16879
16963
|
const file2 = taskFile(projectRoot, task.id);
|
|
16880
16964
|
await assertNoSymlinks(path11.join(path11.resolve(projectRoot), ".alp"), path11.join("tasks", `${task.id}.json`));
|
|
16881
|
-
const temporary = `${file2}.${
|
|
16882
|
-
await
|
|
16965
|
+
const temporary = `${file2}.${randomUUID4().slice(0, 8)}.tmp`;
|
|
16966
|
+
await writeFile8(temporary, JSON.stringify(task, null, 2) + "\n");
|
|
16883
16967
|
await moveFile(temporary, file2);
|
|
16884
16968
|
return task;
|
|
16885
16969
|
}
|
|
@@ -16890,7 +16974,7 @@ function newId(tasks, title, parent) {
|
|
|
16890
16974
|
const used = tasks.filter((task) => task.id.startsWith(prefix) && !task.id.slice(prefix.length).includes(".")).map((task) => Number(task.id.slice(prefix.length)));
|
|
16891
16975
|
return `${prefix}${Math.max(0, ...used) + 1}`;
|
|
16892
16976
|
}
|
|
16893
|
-
const hash2 = createHash4("sha256").update(`${title}\0${now()}\0${
|
|
16977
|
+
const hash2 = createHash4("sha256").update(`${title}\0${now()}\0${randomUUID4()}`).digest("hex");
|
|
16894
16978
|
for (let length = 4; length <= 12; length++) if (!taken.has(`t-${hash2.slice(0, length)}`)) return `t-${hash2.slice(0, length)}`;
|
|
16895
16979
|
return fail3("INVALID_TASK", "Could not choose a free task id");
|
|
16896
16980
|
}
|
|
@@ -31612,12 +31696,14 @@ var toolShapes = {
|
|
|
31612
31696
|
body: external_exports.string().min(1).max(2e4),
|
|
31613
31697
|
roles: external_exports.array(external_exports.string().min(1)).min(1).max(10),
|
|
31614
31698
|
lessons: external_exports.array(external_exports.string().min(1).max(600)).max(50).optional(),
|
|
31615
|
-
replace: external_exports.boolean().optional()
|
|
31699
|
+
replace: external_exports.boolean().optional(),
|
|
31700
|
+
requestId: external_exports.string().min(1).max(100).optional()
|
|
31616
31701
|
},
|
|
31617
31702
|
alp_issue: {
|
|
31618
31703
|
action: external_exports.enum(["search", "create", "comment"]),
|
|
31619
31704
|
target: external_exports.enum(["project", "alp"]),
|
|
31620
31705
|
query: external_exports.string().min(1).max(200).optional(),
|
|
31706
|
+
requestId: external_exports.string().min(1).max(100).optional(),
|
|
31621
31707
|
title: external_exports.string().min(1).max(200).optional(),
|
|
31622
31708
|
body: external_exports.string().min(1).max(2e4).optional(),
|
|
31623
31709
|
issue: external_exports.number().int().positive().optional(),
|
|
@@ -31705,7 +31791,7 @@ var toolShapes = {
|
|
|
31705
31791
|
|
|
31706
31792
|
// packages/core/src/providers.js
|
|
31707
31793
|
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
31708
|
-
import { readdir as
|
|
31794
|
+
import { readdir as readdir6, readFile as readFile8 } from "node:fs/promises";
|
|
31709
31795
|
import path12 from "node:path";
|
|
31710
31796
|
var PROVIDER_SETTINGS = ["$schema", "kind", "label", "description", "command", "args", "env", "models", "additionalModels", "enabled", "params", "readOnlyMode"];
|
|
31711
31797
|
var BUILTIN_RUNTIMES = ["codex", "claude", "acp", "antigravity"];
|
|
@@ -31761,7 +31847,7 @@ async function listProviders(library) {
|
|
|
31761
31847
|
if (!library) return [];
|
|
31762
31848
|
let names = [];
|
|
31763
31849
|
try {
|
|
31764
|
-
names = await
|
|
31850
|
+
names = await readdir6(path12.join(library, "providers"));
|
|
31765
31851
|
} catch (error51) {
|
|
31766
31852
|
if (error51.code !== "ENOENT") throw error51;
|
|
31767
31853
|
}
|
|
@@ -33643,9 +33729,9 @@ async function syncTemplateProfiles(settings, options2 = {}) {
|
|
|
33643
33729
|
}
|
|
33644
33730
|
|
|
33645
33731
|
// packages/core/src/init.js
|
|
33646
|
-
import { mkdir as mkdir8, writeFile as
|
|
33732
|
+
import { mkdir as mkdir8, writeFile as writeFile9, lstat as lstat3, readFile as readFile9, rename as rename4, rm as rm2 } from "node:fs/promises";
|
|
33647
33733
|
import path14 from "node:path";
|
|
33648
|
-
import { randomUUID as
|
|
33734
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
33649
33735
|
async function syncProjectSettings(projectRoot, { library, templates: templates2, teamIds, replaceModels = false } = {}) {
|
|
33650
33736
|
const root = path14.resolve(projectRoot);
|
|
33651
33737
|
const file2 = path14.join(root, ".alp/settings.json");
|
|
@@ -33660,11 +33746,11 @@ async function syncProjectSettings(projectRoot, { library, templates: templates2
|
|
|
33660
33746
|
const next = await syncTemplateProfiles(settings, { root, library, templates: templates2, teamIds, replaceModels });
|
|
33661
33747
|
validateSettings(next, file2);
|
|
33662
33748
|
if (JSON.stringify(settings) === JSON.stringify(next)) return false;
|
|
33663
|
-
const temporary = `${file2}.${
|
|
33749
|
+
const temporary = `${file2}.${randomUUID5()}.tmp`;
|
|
33664
33750
|
try {
|
|
33665
|
-
await
|
|
33751
|
+
await writeFile9(temporary, JSON.stringify(next, null, 2) + "\n", { flag: "wx", mode: info.mode });
|
|
33666
33752
|
if (await readFile9(file2, "utf8") !== before) throw new Error(`Settings changed while saving the template: ${file2}`);
|
|
33667
|
-
await
|
|
33753
|
+
await rename4(temporary, file2);
|
|
33668
33754
|
} finally {
|
|
33669
33755
|
await rm2(temporary, { force: true });
|
|
33670
33756
|
}
|
|
@@ -33908,7 +33994,7 @@ var TimelineDeltas = class {
|
|
|
33908
33994
|
};
|
|
33909
33995
|
|
|
33910
33996
|
// integrations/paseo/server/paseo/timeline-store.ts
|
|
33911
|
-
import { randomUUID as
|
|
33997
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
33912
33998
|
|
|
33913
33999
|
// node_modules/@getpaseo/protocol/dist/timeline-identity.js
|
|
33914
34000
|
function timelineItemIdentity(item) {
|
|
@@ -34313,7 +34399,7 @@ var InMemoryAgentTimelineStore = class {
|
|
|
34313
34399
|
const projection = new TimelineProjection();
|
|
34314
34400
|
for (const row of rows) projection.append(row);
|
|
34315
34401
|
this.states.set(agentId, {
|
|
34316
|
-
epoch: options2?.epoch ??
|
|
34402
|
+
epoch: options2?.epoch ?? randomUUID6(),
|
|
34317
34403
|
projection,
|
|
34318
34404
|
minSeq: projection.getRows()[0]?.seqStart ?? 0,
|
|
34319
34405
|
nextSeq
|
|
@@ -34416,6 +34502,17 @@ var InMemoryAgentTimelineStore = class {
|
|
|
34416
34502
|
}
|
|
34417
34503
|
};
|
|
34418
34504
|
|
|
34505
|
+
// integrations/paseo/server/session-usage.ts
|
|
34506
|
+
var USAGE_FIELDS = ["inputTokens", "cachedInputTokens", "outputTokens", "totalCostUsd", "contextWindowMaxTokens", "contextWindowUsedTokens"];
|
|
34507
|
+
function agentUsage(usage) {
|
|
34508
|
+
const out = {};
|
|
34509
|
+
for (const key of USAGE_FIELDS) {
|
|
34510
|
+
const value = usage?.[key];
|
|
34511
|
+
if (typeof value === "number" && Number.isFinite(value)) out[key] = value;
|
|
34512
|
+
}
|
|
34513
|
+
return out;
|
|
34514
|
+
}
|
|
34515
|
+
|
|
34419
34516
|
// integrations/paseo/server/paseo/agents.ts
|
|
34420
34517
|
var PROVIDER = "alp";
|
|
34421
34518
|
var POLL_MS = 2e3;
|
|
@@ -34541,6 +34638,8 @@ function createAgents({ clientFactory, home: home2, broadcast, directory, log: l
|
|
|
34541
34638
|
pendingPermissions: [...questions.values()].filter((question) => question.rootId === session.id).map(permissionOf),
|
|
34542
34639
|
persistence: session.persistent ? { provider: PROVIDER, sessionId: session.id } : null,
|
|
34543
34640
|
runtimeInfo: { provider: PROVIDER, sessionId: session.id, model: `${session.runtime}:${session.model}`, modeId: session.mode },
|
|
34641
|
+
// Paseo's context meter reads the agent's last usage.
|
|
34642
|
+
...session.usage ? { lastUsage: agentUsage(session.usage) } : {},
|
|
34544
34643
|
...session.lastError ? { lastError: session.lastError.message } : {},
|
|
34545
34644
|
title: session.title ?? null,
|
|
34546
34645
|
labels: {},
|
|
@@ -34603,8 +34702,7 @@ function createAgents({ clientFactory, home: home2, broadcast, directory, log: l
|
|
|
34603
34702
|
});
|
|
34604
34703
|
}
|
|
34605
34704
|
for (const id2 of [...roots.keys()]) if (!seen.has(id2)) {
|
|
34606
|
-
|
|
34607
|
-
epochs.delete(id2);
|
|
34705
|
+
forget(id2);
|
|
34608
34706
|
broadcast({ type: "agent_update", payload: { kind: "remove", agentId: id2 } });
|
|
34609
34707
|
directory.changed();
|
|
34610
34708
|
}
|
|
@@ -34719,8 +34817,10 @@ function createAgents({ clientFactory, home: home2, broadcast, directory, log: l
|
|
|
34719
34817
|
break;
|
|
34720
34818
|
case "turn.ended": {
|
|
34721
34819
|
turns.delete(root);
|
|
34722
|
-
if (event.state === "completed")
|
|
34723
|
-
|
|
34820
|
+
if (event.state === "completed") {
|
|
34821
|
+
const usage = roots.get(root)?.usage;
|
|
34822
|
+
stream(root, { type: "turn_completed", provider: PROVIDER, turnId: event.turnId, ...usage ? { usage: agentUsage(usage) } : {} }, envelope.ts);
|
|
34823
|
+
} else if (event.state === "canceled") stream(root, { type: "turn_canceled", provider: PROVIDER, turnId: event.turnId, reason: event.error?.message ?? "Stopped" }, envelope.ts);
|
|
34724
34824
|
else stream(root, { type: "turn_failed", provider: PROVIDER, turnId: event.turnId, error: event.error?.message ?? "The turn failed" }, envelope.ts);
|
|
34725
34825
|
if (!replaying.has(root) && event.state !== "canceled") {
|
|
34726
34826
|
const reason = event.state === "completed" ? "finished" : "error";
|
|
@@ -34729,6 +34829,13 @@ function createAgents({ clientFactory, home: home2, broadcast, directory, log: l
|
|
|
34729
34829
|
}
|
|
34730
34830
|
break;
|
|
34731
34831
|
}
|
|
34832
|
+
case "usage": {
|
|
34833
|
+
if (replaying.has(root) || !session) return;
|
|
34834
|
+
const next = { ...session, usage: event.usage };
|
|
34835
|
+
roots.set(root, next);
|
|
34836
|
+
upsert(next);
|
|
34837
|
+
return;
|
|
34838
|
+
}
|
|
34732
34839
|
case "session.opened":
|
|
34733
34840
|
case "session.updated":
|
|
34734
34841
|
case "session.closed":
|
|
@@ -34744,19 +34851,24 @@ function createAgents({ clientFactory, home: home2, broadcast, directory, log: l
|
|
|
34744
34851
|
if (timelines.has(root)) return Promise.resolve();
|
|
34745
34852
|
let pending = attaching.get(root);
|
|
34746
34853
|
if (!pending) {
|
|
34854
|
+
const connection = alp;
|
|
34855
|
+
if (!connection) return Promise.reject(new Error("ALP daemon is not connected"));
|
|
34747
34856
|
pending = (async () => {
|
|
34748
34857
|
timelines.initialize(root);
|
|
34749
34858
|
deltas.set(root, new TimelineDeltas());
|
|
34750
34859
|
epochs.delete(root);
|
|
34751
34860
|
replaying.add(root);
|
|
34861
|
+
const current = () => attaching.get(root) === pending;
|
|
34752
34862
|
try {
|
|
34753
|
-
await
|
|
34863
|
+
await connection.request("session.attach", { sessionId: root, replay: true });
|
|
34754
34864
|
} catch (error51) {
|
|
34755
|
-
timelines.delete(root);
|
|
34865
|
+
if (current()) timelines.delete(root);
|
|
34756
34866
|
throw error51;
|
|
34757
34867
|
} finally {
|
|
34758
|
-
|
|
34759
|
-
|
|
34868
|
+
if (current()) {
|
|
34869
|
+
replaying.delete(root);
|
|
34870
|
+
attaching.delete(root);
|
|
34871
|
+
}
|
|
34760
34872
|
}
|
|
34761
34873
|
})();
|
|
34762
34874
|
attaching.set(root, pending);
|
|
@@ -34777,6 +34889,22 @@ function createAgents({ clientFactory, home: home2, broadcast, directory, log: l
|
|
|
34777
34889
|
}
|
|
34778
34890
|
void ensureTimeline(root).catch((error51) => log3(`agents reattach failed: ${error51?.message ?? error51}`));
|
|
34779
34891
|
}
|
|
34892
|
+
function forget(root) {
|
|
34893
|
+
roots.delete(root);
|
|
34894
|
+
timelines.delete(root);
|
|
34895
|
+
deltas.delete(root);
|
|
34896
|
+
attaching.delete(root);
|
|
34897
|
+
replaying.delete(root);
|
|
34898
|
+
epochs.delete(root);
|
|
34899
|
+
turns.delete(root);
|
|
34900
|
+
attention.delete(root);
|
|
34901
|
+
for (const child of [...children2.values()]) {
|
|
34902
|
+
if (child.root !== root) continue;
|
|
34903
|
+
children2.delete(child.id);
|
|
34904
|
+
childTimelines.delete(child.id);
|
|
34905
|
+
childDeltas.delete(child.id);
|
|
34906
|
+
}
|
|
34907
|
+
}
|
|
34780
34908
|
function known(agentId) {
|
|
34781
34909
|
const session = roots.get(agentId);
|
|
34782
34910
|
if (!session) throw Object.assign(new Error(`No agent ${agentId}`), { code: "agent_not_found" });
|
|
@@ -34794,14 +34922,14 @@ function createAgents({ clientFactory, home: home2, broadcast, directory, log: l
|
|
|
34794
34922
|
async function create(input) {
|
|
34795
34923
|
const { config: config2 } = input;
|
|
34796
34924
|
if (config2.provider !== PROVIDER) throw new Error(`ALP runs its own teams; ${config2.provider} is not one of them`);
|
|
34797
|
-
const sessionId = `web-${
|
|
34925
|
+
const sessionId = `web-${randomUUID7()}`;
|
|
34798
34926
|
if (input.workspaceId) directory.assign(sessionId, input.workspaceId);
|
|
34799
34927
|
await alp.request("session.create", { sessionId, spec: { cwd: config2.cwd, persist: true, ...config2.model ? { workflow: config2.model } : {}, ...config2.modeId ? { mode: config2.modeId } : {} } });
|
|
34800
34928
|
if (config2.title) await alp.request("session.rename", { sessionId, title: config2.title });
|
|
34801
34929
|
await refresh();
|
|
34802
34930
|
await ensureTimeline(sessionId);
|
|
34803
34931
|
const prompt = input.initialPrompt?.trim();
|
|
34804
|
-
if (prompt) await alp.request("session.prompt", { sessionId, clientMessageId: input.clientMessageId ??
|
|
34932
|
+
if (prompt) await alp.request("session.prompt", { sessionId, clientMessageId: input.clientMessageId ?? randomUUID7(), content: [{ type: "text", text: prompt }] });
|
|
34805
34933
|
return agentOf(known(sessionId));
|
|
34806
34934
|
}
|
|
34807
34935
|
const view = {
|
|
@@ -34983,7 +35111,7 @@ function createAgents({ clientFactory, home: home2, broadcast, directory, log: l
|
|
|
34983
35111
|
if (running && message.activeTurnBehavior === "interrupt") await alp.request("session.interrupt", { sessionId: session.id });
|
|
34984
35112
|
await alp.request("session.prompt", {
|
|
34985
35113
|
sessionId: session.id,
|
|
34986
|
-
clientMessageId: message.messageId ??
|
|
35114
|
+
clientMessageId: message.messageId ?? randomUUID7(),
|
|
34987
35115
|
delivery: running && message.activeTurnBehavior !== "interrupt" ? "steer" : "auto",
|
|
34988
35116
|
content: [{ type: "text", text: message.text }]
|
|
34989
35117
|
});
|
|
@@ -35564,14 +35692,14 @@ function createCheckouts({ broadcast, log: log3 = () => {
|
|
|
35564
35692
|
}
|
|
35565
35693
|
|
|
35566
35694
|
// integrations/paseo/server/paseo/files.ts
|
|
35567
|
-
import { readFile as readFile10, readdir as
|
|
35695
|
+
import { readFile as readFile10, readdir as readdir7, realpath as realpath2, stat as stat7 } from "node:fs/promises";
|
|
35568
35696
|
import os5 from "node:os";
|
|
35569
35697
|
import path17 from "node:path";
|
|
35570
35698
|
var SKIPPED = /* @__PURE__ */ new Set(["node_modules", "Library", ".git", "dist", "build", ".cache", "target", ".venv", "venv", "__pycache__"]);
|
|
35571
35699
|
var HOME_SCAN_LIMIT = 5e3;
|
|
35572
35700
|
var HOME_DEPTH = 4;
|
|
35573
35701
|
var WORKSPACE_SCAN_LIMIT = 2e4;
|
|
35574
|
-
var children = (directory) =>
|
|
35702
|
+
var children = (directory) => readdir7(directory, { withFileTypes: true }).catch(() => []);
|
|
35575
35703
|
var expand = (query) => query === "~" ? os5.homedir() : query.startsWith("~/") ? path17.join(os5.homedir(), query.slice(2)) : query;
|
|
35576
35704
|
function rank2(candidate, query) {
|
|
35577
35705
|
const name = candidate.toLowerCase();
|
|
@@ -35696,7 +35824,7 @@ async function fileExplorer(message) {
|
|
|
35696
35824
|
const relative = posixRelative(realRoot, real);
|
|
35697
35825
|
if (message.mode === "list") {
|
|
35698
35826
|
const entries2 = [];
|
|
35699
|
-
for (const entry of await
|
|
35827
|
+
for (const entry of await readdir7(real, { withFileTypes: true })) {
|
|
35700
35828
|
const child = path17.join(real, entry.name);
|
|
35701
35829
|
const resolved = entry.isSymbolicLink() ? await inside(realRoot, path17.relative(realRoot, child)).then((found) => found.real, () => void 0) : child;
|
|
35702
35830
|
if (!resolved) continue;
|
|
@@ -35726,11 +35854,11 @@ async function fileExplorer(message) {
|
|
|
35726
35854
|
import { createHash as createHash7 } from "node:crypto";
|
|
35727
35855
|
|
|
35728
35856
|
// alp-plugin-client:plugin-client
|
|
35729
|
-
var plugin_client_default = { "id": "alp-provider", "requirements": { "paseo": ">=0.11.1 <0.12.0" }, "factory": '(function(require){const module={exports:{}};const exports=module.exports;var __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === "object" || typeof from === "function") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { value: from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);\nvar __async = (__this, __arguments, generator) => {\n return new Promise((resolve, reject) => {\n var fulfilled = (value) => {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n };\n var rejected = (value) => {\n try {\n step(generator.throw(value));\n } catch (e) {\n reject(e);\n }\n };\n var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);\n step((generator = generator.apply(__this, __arguments)).next());\n });\n};\n\n// integrations/paseo/index.client.tsx\nvar index_client_exports = {};\n__export(index_client_exports, {\n default: () => contribute\n});\nmodule.exports = __toCommonJS(index_client_exports);\n\n// integrations/paseo/client/tasks-panel.tsx\nvar import_client = require("@getpaseo/plugin/client");\nvar import_react_native = require("@getpaseo/plugin/client/react-native");\nvar import_react = require("react");\nvar import_react_native2 = require("react-native");\n\n// integrations/paseo/shared/tasks.ts\nvar import_plugin = require("@getpaseo/plugin");\nvar import_zod = require("zod");\nvar TaskRowSchema = import_zod.z.object({\n id: import_zod.z.string(),\n title: import_zod.z.string(),\n type: import_zod.z.string(),\n priority: import_zod.z.number(),\n status: import_zod.z.enum(["open", "in_progress", "review", "closed"]),\n parent: import_zod.z.string().optional(),\n assignee: import_zod.z.string().optional(),\n ready: import_zod.z.boolean(),\n /** Open tasks that must close first, including those of ancestors. */\n blockedBy: import_zod.z.array(import_zod.z.string()).optional(),\n /** Open gates, as labels. */\n waits: import_zod.z.array(import_zod.z.string()).optional(),\n /** Open human gates of this task: the user approves them here. */\n approvals: import_zod.z.array(import_zod.z.object({ gate: import_zod.z.string(), note: import_zod.z.string() })).optional(),\n handoff: import_zod.z.object({ outcome: import_zod.z.string(), summary: import_zod.z.string(), agent: import_zod.z.string().optional() }).optional(),\n closed: import_zod.z.object({ reason: import_zod.z.string(), summary: import_zod.z.string().optional(), at: import_zod.z.string() }).optional(),\n /** What the task is about, for its detail view; at most 4000 characters. */\n description: import_zod.z.string().optional(),\n labels: import_zod.z.array(import_zod.z.string()).optional(),\n paths: import_zod.z.array(import_zod.z.string()).optional(),\n /** An epic or parent task: how many of its children are closed. */\n progress: import_zod.z.object({ done: import_zod.z.number(), total: import_zod.z.number() }).optional(),\n createdAt: import_zod.z.string().optional(),\n updatedAt: import_zod.z.string()\n});\nvar Directory = import_zod.z.string().min(1);\nvar tasksList = (0, import_plugin.defineRpc)({\n name: "alp.tasks.list",\n input: import_zod.z.object({ directory: Directory }),\n output: import_zod.z.object({\n /** The ALP project containing the directory, or null when there is none. */\n projectRoot: import_zod.z.string().nullable(),\n tasks: import_zod.z.array(TaskRowSchema),\n unreadable: import_zod.z.array(import_zod.z.object({ file: import_zod.z.string(), error: import_zod.z.string() })),\n /** By provider session id: the tasks that session\'s tree worked on (ALPD \xA755). */\n sessions: import_zod.z.record(import_zod.z.string(), import_zod.z.array(import_zod.z.string())).optional()\n })\n});\nvar tasksAdd = (0, import_plugin.defineRpc)({\n name: "alp.tasks.add",\n input: import_zod.z.object({ directory: Directory, title: import_zod.z.string().trim().min(1).max(200), priority: import_zod.z.number().int().min(0).max(4).optional() }),\n output: import_zod.z.object({ id: import_zod.z.string() })\n});\nvar tasksChange = (0, import_plugin.defineRpc)({\n name: "alp.tasks.change",\n input: import_zod.z.object({\n directory: Directory,\n id: import_zod.z.string().min(1),\n action: import_zod.z.enum(["close", "reopen", "approve"]),\n /** For approve: the human gate. */\n gate: import_zod.z.string().optional(),\n note: import_zod.z.string().max(2e3).optional()\n }),\n /** landed: the first line of the report when the close landed an epic. */\n output: import_zod.z.object({ id: import_zod.z.string(), status: import_zod.z.string(), landed: import_zod.z.string().optional() })\n});\nvar rank = (a, b) => a.priority - b.priority || a.id.localeCompare(b.id);\nfunction boardSections(tasks, closedLimit = 20) {\n const open = tasks.filter((task) => task.status !== "closed");\n const sections = [\n { key: "approve", title: "Waiting for your approval", tasks: open.filter((task) => task.approvals?.length).sort(rank) },\n { key: "review", title: "In review", tasks: open.filter((task) => task.status === "review").sort(rank) },\n { key: "progress", title: "In progress", tasks: open.filter((task) => task.status === "in_progress").sort(rank) },\n { key: "ready", title: "Ready", tasks: open.filter((task) => task.ready).sort(rank) },\n { key: "waiting", title: "Blocked or waiting", tasks: open.filter((task) => task.status === "open" && !task.ready && !task.approvals?.length && task.type !== "epic").sort(rank) },\n { key: "epics", title: "Epics", tasks: open.filter((task) => task.type === "epic" && !task.approvals?.length).sort(rank) },\n { key: "closed", title: "Closed", tasks: tasks.filter((task) => task.status === "closed").sort((a, b) => (b.closed?.at ?? b.updatedAt).localeCompare(a.closed?.at ?? a.updatedAt)).slice(0, closedLimit) }\n ];\n return sections.filter((section) => section.tasks.length);\n}\n\n// integrations/paseo/client/tasks-panel.tsx\nvar import_jsx_runtime = require("react/jsx-runtime");\nvar POLL_MS = 5e3;\nvar SPLIT_FROM = 820;\nfunction TasksPanel({ theme, layout, workspaceId }) {\n const directory = (0, import_client.useWorkspace)(workspaceId, (workspace) => workspace.directory || workspace.projectRootPath);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskBoard, { theme, compact: layout.compact, directory, ...useTasks(directory) });\n}\nfunction TasksScreen({ theme, layout, params }) {\n const directory = params.directory || null;\n const tasks = useTasks(directory);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n TaskBoard,\n {\n theme,\n compact: layout.compact,\n directory,\n ...tasks,\n initial: params.taskId ? { selected: params.taskId } : void 0\n },\n params.taskId ?? ""\n );\n}\nfunction useTasks(directory) {\n const list = (0, import_client.useRpc)(tasksList);\n const add = (0, import_client.useRpc)(tasksAdd);\n const change = (0, import_client.useRpc)(tasksChange);\n const toast = (0, import_react_native.useToast)();\n const [data, setData] = (0, import_react.useState)(null);\n const [error, setError] = (0, import_react.useState)(null);\n const [tick, setTick] = (0, import_react.useState)(0);\n const refresh = (0, import_react.useCallback)(() => setTick((value) => value + 1), []);\n (0, import_react.useEffect)(() => {\n if (!directory) return;\n let live = true;\n const load = () => list({ directory }).then((result) => {\n if (live) {\n setData(result);\n setError(null);\n }\n }).catch((cause) => {\n if (live) setError(cause instanceof Error ? cause.message : String(cause));\n });\n void load();\n const timer = setInterval(load, POLL_MS);\n return () => {\n live = false;\n clearInterval(timer);\n };\n }, [directory, list, tick]);\n const onAdd = (0, import_react.useCallback)((title, priority) => __async(null, null, function* () {\n if (!directory) return false;\n try {\n const { id } = yield add({ directory, title, priority });\n toast.show(`Added ${id}`, { variant: "success" });\n refresh();\n return true;\n } catch (cause) {\n toast.error(cause instanceof Error ? cause.message : String(cause));\n return false;\n }\n }), [add, directory, refresh, toast]);\n const onAction = (0, import_react.useCallback)((_0) => __async(null, [_0], function* ({ id, action, gate }) {\n if (!directory) return;\n try {\n const { landed } = yield change({ directory, id, action, ...gate ? { gate } : {} });\n toast.show(landed ?? (action === "approve" ? `Approved ${id}` : action === "close" ? `Closed ${id}` : `Reopened ${id}`), { variant: "success" });\n refresh();\n } catch (cause) {\n toast.error(cause instanceof Error ? cause.message : String(cause));\n }\n }), [change, directory, refresh, toast]);\n return { projectRoot: data?.projectRoot ?? null, tasks: data?.tasks ?? null, unreadable: data?.unreadable.length ?? 0, error, onAdd, onAction, onRefresh: refresh };\n}\nvar PRIORITIES = [0, 1, 2, 3, 4];\nvar TYPE_ICONS = { bug: "Bug", feature: "Sparkles", task: "SquareCheck", chore: "Wrench", epic: "Target" };\nvar hovered = (state) => !!state.hovered;\nfunction age(iso, now = Date.now()) {\n if (!iso) return "";\n const minutes = Math.max(0, Math.floor((now - Date.parse(iso)) / 6e4));\n if (minutes < 60) return `${minutes}m`;\n if (minutes < 60 * 24) return `${Math.floor(minutes / 60)}h`;\n if (minutes < 60 * 24 * 14) return `${Math.floor(minutes / 1440)}d`;\n return `${Math.floor(minutes / 10080)}w`;\n}\nfunction stateOf(task) {\n if (task.status === "closed") return "closed";\n if (task.approvals?.length) return "approve";\n if (task.status === "review") return "review";\n if (task.status === "in_progress") return "progress";\n if (task.type === "epic") return task.progress?.done ? "progress" : "ready";\n return task.ready ? "ready" : "blocked";\n}\nvar STATE_LABELS = { approve: "Needs approval", review: "In review", progress: "In progress", ready: "Ready", blocked: "Blocked", closed: "Closed" };\nfunction filterTasks(tasks, filter, query) {\n const words = query.trim().toLowerCase().split(/\\s+/).filter(Boolean);\n return tasks.filter((task) => {\n if (filter === "open" && task.status === "closed") return false;\n if (filter === "ready" && !(task.ready && task.status !== "closed")) return false;\n if (filter === "closed" && task.status !== "closed") return false;\n const text = [task.id, task.title, task.type, task.assignee ?? "", ...task.labels ?? []].join(" ").toLowerCase();\n return words.every((word) => text.includes(word));\n });\n}\nfunction TaskBoard({ theme, compact, directory, projectRoot, tasks, unreadable, error, onAdd, onAction, onRefresh, initial }) {\n const styles = (0, import_react.useMemo)(() => makeStyles(theme, compact), [theme, compact]);\n const [view, setView] = (0, import_react.useState)(initial?.view ?? "list");\n const [filter, setFilter] = (0, import_react.useState)(initial?.filter ?? "open");\n const [query, setQuery] = (0, import_react.useState)("");\n const [selected, setSelected] = (0, import_react.useState)(initial?.selected ?? null);\n const [composing, setComposing] = (0, import_react.useState)(false);\n const [width, setWidth] = (0, import_react.useState)(initial?.width ?? 0);\n const shown = (0, import_react.useMemo)(() => tasks ? filterTasks(tasks, filter, query) : [], [tasks, filter, query]);\n const task = selected ? tasks?.find((candidate) => candidate.id === selected) ?? null : null;\n const split = !!task && width >= SPLIT_FROM;\n const counts = (0, import_react.useMemo)(() => ({\n open: (tasks ?? []).filter((entry) => entry.status !== "closed").length,\n ready: (tasks ?? []).filter((entry) => entry.ready && entry.status !== "closed").length,\n closed: (tasks ?? []).filter((entry) => entry.status === "closed").length,\n all: (tasks ?? []).length\n }), [tasks]);\n if (!directory) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.screen, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.muted, children: "This view needs a workspace." }) });\n const open = (id) => setSelected(id);\n const detail = task ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskDetail, { theme, styles, task, tasks: tasks ?? [], onBack: () => setSelected(null), onOpen: open, onAction }) : null;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.screen, onLayout: (event) => setWidth(event.nativeEvent.layout.width), children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.toolbar, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.toolbarRow, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.title, children: "Tasks" }),\n tasks ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.count, children: [\n counts.open,\n " open"\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: { flex: 1 } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n Segmented,\n {\n theme,\n styles,\n value: view,\n onChange: (value) => {\n setView(value);\n setSelected(null);\n },\n options: [{ key: "list", label: "List", icon: "List" }, { key: "board", label: "Board", icon: "Columns3" }, { key: "epics", label: "Epics", icon: "Target" }]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconButton, { theme, icon: "RefreshCw", label: "Refresh", onPress: onRefresh }),\n projectRoot ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconButton, { theme, icon: "Plus", label: "New task", onPress: () => setComposing(!composing), primary: true }) : null\n ] }),\n projectRoot ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.toolbarRow, children: [\n ["open", "ready", "closed", "all"].map((key) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Show ${key}`, accessibilityState: { selected: filter === key }, onPress: () => setFilter(key), style: [styles.filter, filter === key ? styles.filterOn : null], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: filter === key ? styles.filterTextOn : styles.filterText, children: [\n key[0].toUpperCase() + key.slice(1),\n " ",\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.filterCount, children: counts[key] })\n ] }) }, key)),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.search, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: "Search", size: 14, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TextInput, { style: styles.searchInput, value: query, onChangeText: setQuery, placeholder: "Filter by id, title, label, agent", placeholderTextColor: theme.colors.foregroundMuted, accessibilityLabel: "Filter tasks" })\n ] })\n ] }) : null,\n composing && projectRoot ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Composer, { theme, styles, onAdd: (title, priority) => __async(null, null, function* () {\n const added = yield onAdd(title, priority);\n if (added) setComposing(false);\n return added;\n }) }) : null\n ] }),\n error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.danger, styles.pad], children: error }) : null,\n tasks === null && !error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.muted, styles.pad], children: "Loading tasks\\u2026" }) : null,\n tasks !== null && projectRoot === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: [styles.muted, styles.pad], children: [\n directory,\n " is not an ALP project. Run alp init to start one."\n ] }) : null,\n projectRoot && tasks ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.body, children: [\n !task || split ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [styles.pane, split ? styles.paneList : null], children: [\n unreadable ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: [styles.warning, styles.pad], children: [\n unreadable,\n " unreadable task ",\n unreadable === 1 ? "file" : "files",\n " in ",\n projectRoot,\n "/.alp/tasks"\n ] }) : null,\n !tasks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, { styles, text: "No tasks yet. Add one here, with alp task add, or ask main to plan the work." }) : null,\n tasks.length && !shown.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, { styles, text: "No tasks match." }) : null,\n shown.length && view === "list" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListView, { theme, styles, tasks: shown, selected, onOpen: open, onAction }) : null,\n shown.length && view === "board" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BoardView, { theme, styles, tasks: shown, onOpen: open }) : null,\n view === "epics" && tasks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EpicsView, { theme, styles, tasks, shown, onOpen: open }) : null\n ] }) : null,\n detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [styles.pane, split ? styles.paneDetail : null], children: detail }) : null\n ] }) : null\n ] });\n}\nfunction Segmented({ theme, styles, value, options, onChange }) {\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.segmented, children: options.map((option) => {\n const on = option.key === value;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "tab", accessibilityLabel: option.label, accessibilityState: { selected: on }, onPress: () => onChange(option.key), style: [styles.segment, on ? styles.segmentOn : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: option.icon, size: 13, color: on ? theme.colors.foreground : theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: on ? styles.segmentTextOn : styles.segmentText, children: option.label })\n ] }, option.key);\n }) });\n}\nfunction IconButton({ theme, icon, label, onPress, primary }) {\n const { colors } = theme;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_react_native2.Pressable,\n {\n accessibilityRole: "button",\n accessibilityLabel: label,\n onPress,\n style: (state) => ({ padding: 7, borderRadius: 8, backgroundColor: primary ? colors.accent : hovered(state) ? colors.surface2 : "transparent" }),\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: icon, size: 15, color: primary ? colors.accentForeground : colors.foregroundMuted })\n }\n );\n}\nfunction Composer({ theme, styles, onAdd }) {\n const [title, setTitle] = (0, import_react.useState)("");\n const [priority, setPriority] = (0, import_react.useState)(2);\n const submit = () => __async(null, null, function* () {\n const text = title.trim();\n if (text && (yield onAdd(text, priority))) setTitle("");\n });\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.composer, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TextInput, { style: styles.input, value: title, onChangeText: setTitle, onSubmitEditing: submit, placeholder: "Add a task for main", placeholderTextColor: theme.colors.foregroundMuted, accessibilityLabel: "New task title", autoFocus: true }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.priorities, children: PRIORITIES.map((value) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Priority ${value}`, onPress: () => setPriority(value), style: [styles.chip, value === priority ? styles.chipOn : null], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: value === priority ? styles.chipTextOn : styles.chipText, children: [\n "P",\n value\n ] }) }, value)) }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "button", onPress: submit, style: styles.button, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.buttonText, children: "Add" }) })\n ] });\n}\nfunction Empty({ styles, text }) {\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.empty, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.muted, children: text }) });\n}\nfunction Priority({ theme, value }) {\n const { colors } = theme;\n const color = value === 0 ? colors.statusDanger : value === 1 ? colors.statusWarning : colors.foregroundMuted;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: { alignSelf: "flex-start", borderRadius: 4, borderWidth: 1, borderColor: value <= 1 ? color : colors.border, paddingHorizontal: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: { color, fontSize: 10.5, fontWeight: "600", fontVariant: ["tabular-nums"] }, children: [\n "P",\n value\n ] }) });\n}\nfunction StateDot({ theme, task }) {\n const { colors } = theme;\n const state = stateOf(task);\n const color = state === "approve" ? colors.statusWarning : state === "review" ? colors.accent : state === "progress" ? colors.statusWarning : state === "ready" ? colors.statusSuccess : state === "blocked" ? colors.statusDanger : colors.border;\n const ring = state === "progress" || state === "closed";\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { accessibilityLabel: STATE_LABELS[state], style: { width: 9, height: 9, borderRadius: 5, borderWidth: ring ? 2 : 0, borderColor: color, backgroundColor: ring ? "transparent" : color } });\n}\nfunction TaskLine({ theme, styles, task, selected, onOpen }) {\n const meta = [\n task.blockedBy?.length ? `after ${task.blockedBy.join(", ")}` : "",\n // Gates waiting for the user show with their Approve instead.\n task.waits?.length && !task.approvals?.length ? `waits on ${task.waits.join("; ")}` : "",\n task.parent ? `in ${task.parent}` : ""\n ].filter(Boolean).join(" \\xB7 ");\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Open ${task.id}`, onPress: () => onOpen(task.id), style: (state) => [styles.line, selected ? styles.lineOn : hovered(state) ? styles.lineHover : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.lineTop, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateDot, { theme, task }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: TYPE_ICONS[task.type] ?? "SquareCheck", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Priority, { theme, value: task.priority }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.id, children: task.id }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.lineTitle, numberOfLines: 1, children: task.title }),\n task.assignee ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.assignee, numberOfLines: 1, children: [\n "@",\n task.assignee\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.age, children: age(task.status === "closed" ? task.closed?.at : task.updatedAt) })\n ] }),\n meta || task.labels?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.lineMeta, children: [\n meta ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.small, numberOfLines: 1, children: meta }) : null,\n (task.labels ?? []).map((label) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.label, children: [\n "#",\n label\n ] }, label))\n ] }) : null\n ] });\n}\nvar SECTION_ICONS = { approve: "Hand", review: "Eye", progress: "LoaderCircle", ready: "CircleCheck", waiting: "CircleSlash", epics: "Target", closed: "CircleDashed" };\nfunction ListView({ theme, styles, tasks, selected, onOpen, onAction }) {\n const sections = (0, import_react.useMemo)(() => boardSections(tasks), [tasks]);\n const [hidden, setHidden] = (0, import_react.useState)({});\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { contentContainerStyle: styles.listContent, children: sections.map((section) => {\n const collapsed = hidden[section.key] ?? false;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.group, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `${collapsed ? "Show" : "Hide"} ${section.title}`, onPress: () => setHidden((current) => ({ ...current, [section.key]: !collapsed })), style: styles.groupHeader, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: collapsed ? "ChevronRight" : "ChevronDown", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: SECTION_ICONS[section.key] ?? "Circle", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.groupTitle, children: section.title }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.groupCount, children: section.tasks.length })\n ] }),\n !collapsed ? section.tasks.map((task) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskLine, { theme, styles, task, selected: task.id === selected, onOpen }),\n section.key === "approve" ? task.approvals.map((approval) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.inlineAction, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.small, numberOfLines: 2, children: approval.note || "Waiting for your approval" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, label: "Approve", primary: true, onPress: () => onAction({ id: task.id, action: "approve", gate: approval.gate }) })\n ] }, approval.gate)) : null\n ] }, `${section.key}-${task.id}`)) : null\n ] }, section.key);\n }) });\n}\nvar COLUMNS = [\n { key: "approve", title: "Needs approval" },\n { key: "blocked", title: "Blocked" },\n { key: "ready", title: "Ready" },\n { key: "progress", title: "In progress" },\n { key: "review", title: "In review" },\n { key: "closed", title: "Closed" }\n];\nfunction BoardView({ theme, styles, tasks, onOpen }) {\n const columns = COLUMNS.map((column) => ({ ...column, tasks: tasks.filter((task) => task.type !== "epic" && stateOf(task) === column.key) })).filter((column) => column.tasks.length || ["blocked", "ready", "progress"].includes(column.key));\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { horizontal: true, contentContainerStyle: styles.board, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.column, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.columnHeader, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateDot, { theme, task: { status: column.key === "closed" ? "closed" : column.key === "review" ? "review" : column.key === "progress" ? "in_progress" : "open", ready: column.key === "ready", approvals: column.key === "approve" ? [{ gate: "", note: "" }] : void 0 } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.columnTitle, children: column.title }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.groupCount, children: column.tasks.length })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.ScrollView, { contentContainerStyle: styles.columnBody, children: [\n column.tasks.map((task) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Open ${task.id}`, onPress: () => onOpen(task.id), style: (state) => [styles.card, hovered(state) ? styles.cardHover : null, column.key === "blocked" ? styles.cardBlocked : column.key === "ready" ? styles.cardReady : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.lineTop, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: TYPE_ICONS[task.type] ?? "SquareCheck", size: 12, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Priority, { theme, value: task.priority }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.id, children: task.id }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: { flex: 1 } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.age, children: age(task.updatedAt) })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.cardTitle, numberOfLines: 3, children: task.title }),\n task.assignee ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.assignee, numberOfLines: 1, children: [\n "@",\n task.assignee\n ] }) : null,\n task.blockedBy?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.blocked, numberOfLines: 1, children: [\n "after ",\n task.blockedBy.join(", ")\n ] }) : null,\n task.labels?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.cardLabels, children: task.labels.map((label) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.label, children: [\n "#",\n label\n ] }, label)) }) : null\n ] }, task.id)),\n !column.tasks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.small, styles.pad], children: "Nothing here" }) : null\n ] })\n ] }, column.key)) });\n}\nfunction EpicsView({ theme, styles, tasks, shown, onOpen }) {\n const epics = shown.filter((task) => task.type === "epic" || task.progress);\n const [opened, setOpened] = (0, import_react.useState)({});\n if (!epics.length) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, { styles, text: "No epics here. An epic is a task other tasks name as their parent." });\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { contentContainerStyle: styles.listContent, children: epics.map((epic) => {\n const children = tasks.filter((task) => task.parent === epic.id);\n const done = epic.progress?.done ?? 0;\n const total = epic.progress?.total ?? 0;\n const expanded = opened[epic.id] ?? epic.status !== "closed";\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.epic, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Open ${epic.id}`, onPress: () => onOpen(epic.id), style: styles.lineTop, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateDot, { theme, task: epic }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: "Target", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Priority, { theme, value: epic.priority }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.id, children: epic.id }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.lineTitle, numberOfLines: 1, children: epic.title }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.progressText, children: [\n done,\n "/",\n total\n ] })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.progressTrack, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [styles.progressFill, { width: `${total ? Math.round(done / total * 100) : 0}%` }] }) }),\n children.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `${expanded ? "Hide" : "Show"} the tasks of ${epic.id}`, onPress: () => setOpened((current) => ({ ...current, [epic.id]: !expanded })), style: styles.treeToggle, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: expanded ? "ChevronDown" : "ChevronRight", size: 12, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.small, children: [\n children.length,\n " ",\n children.length === 1 ? "task" : "tasks"\n ] })\n ] }) : null,\n expanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.tree, children: children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskLine, { theme, styles, task: child, selected: false, onOpen }, child.id)) }) : null\n ] }, epic.id);\n }) });\n}\nfunction SmallButton({ styles, label, onPress, primary, danger }) {\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "button", onPress, style: [styles.smallButton, primary ? styles.smallButtonPrimary : null, danger ? styles.smallButtonDanger : null], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: primary ? styles.smallButtonTextPrimary : danger ? styles.smallButtonTextDanger : styles.smallButtonText, children: label }) });\n}\nfunction TaskDetail({ theme, styles, task, tasks, onBack, onOpen, onAction }) {\n const state = stateOf(task);\n const children = tasks.filter((entry) => entry.parent === task.id);\n const blocks = tasks.filter((entry) => entry.blockedBy?.includes(task.id) && entry.status !== "closed");\n const field = (label, value) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.field, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.fieldLabel, children: label }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.fieldValue, children: typeof value === "string" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: value }) : value })\n ] });\n const link = (id) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "link", accessibilityLabel: `Open ${id}`, onPress: () => onOpen(id), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.link, children: id }) }, id);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.ScrollView, { contentContainerStyle: styles.detail, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.detailHeader, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconButton, { theme, icon: "ArrowLeft", label: "Back to the list", onPress: onBack }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.id, children: task.id }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.statePill, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateDot, { theme, task }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.small, children: STATE_LABELS[state] })\n ] })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.detailTitle, children: task.title }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.fields, children: [\n field("Type", /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.inline, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: TYPE_ICONS[task.type] ?? "SquareCheck", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: task.type })\n ] })),\n field("Priority", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Priority, { theme, value: task.priority })),\n task.assignee ? field("Assignee", `@${task.assignee}`) : null,\n task.parent ? field("Parent", link(task.parent)) : null,\n task.blockedBy?.length ? field("Blocked by", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.inline, children: task.blockedBy.map(link) })) : null,\n blocks.length ? field("Blocks", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.inline, children: blocks.map((entry) => link(entry.id)) })) : null,\n task.waits?.length ? field("Waits on", task.waits.join("; ")) : null,\n task.labels?.length ? field("Labels", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.inline, children: task.labels.map((label) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.label, children: [\n "#",\n label\n ] }, label)) })) : null,\n task.paths?.length ? field("Paths", task.paths.join(", ")) : null,\n task.progress ? field("Progress", `${task.progress.done} of ${task.progress.total} closed`) : null,\n task.createdAt ? field("Created", `${age(task.createdAt)} ago`) : null,\n field("Updated", `${age(task.updatedAt)} ago`)\n ] }),\n task.description ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.box, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.boxTitle, children: "Description" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: task.description })\n ] }) : null,\n task.handoff ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.box, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.boxTitle, children: [\n "Handoff \\xB7 ",\n task.handoff.outcome,\n task.handoff.agent ? ` from ${task.handoff.agent}` : ""\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: task.handoff.summary })\n ] }) : null,\n task.closed ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.box, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.boxTitle, children: [\n "Closed \\xB7 ",\n task.closed.reason\n ] }),\n task.closed.summary ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: task.closed.summary }) : null\n ] }) : null,\n children.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.box, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.boxTitle, children: [\n "Tasks \\xB7 ",\n children.filter((child) => child.status === "closed").length,\n "/",\n children.length,\n " closed"\n ] }),\n children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskLine, { theme, styles, task: child, selected: false, onOpen }, child.id))\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.detailActions, children: [\n (task.approvals ?? []).map((approval) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, primary: true, label: `Approve${approval.note ? `: ${approval.note.slice(0, 40)}` : ""}`, onPress: () => onAction({ id: task.id, action: "approve", gate: approval.gate }) }, approval.gate)),\n state === "review" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, primary: true, label: "Accept and close", onPress: () => onAction({ id: task.id, action: "close" }) }) : null,\n task.status !== "closed" && state !== "review" && task.type !== "epic" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, label: "Close", onPress: () => onAction({ id: task.id, action: "close" }) }) : null,\n task.status === "closed" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, label: "Reopen", onPress: () => onAction({ id: task.id, action: "reopen" }) }) : null\n ] })\n ] });\n}\nfunction makeStyles(theme, compact) {\n const { colors } = theme;\n const mono = { fontFamily: "monospace", fontVariant: ["tabular-nums"] };\n return {\n screen: { flex: 1, backgroundColor: colors.surface0 },\n pad: { paddingHorizontal: compact ? 12 : 16, paddingVertical: 8 },\n toolbar: { paddingHorizontal: compact ? 12 : 16, paddingTop: 12, paddingBottom: 10, gap: 10, borderBottomWidth: 1, borderBottomColor: colors.border },\n toolbarRow: { flexDirection: "row", alignItems: "center", gap: 6, flexWrap: "wrap" },\n title: { color: colors.foreground, fontSize: 15, fontWeight: "600" },\n count: { color: colors.foregroundMuted, fontSize: 12, marginLeft: 4 },\n segmented: { flexDirection: "row", backgroundColor: colors.surface1, borderRadius: 8, borderWidth: 1, borderColor: colors.border, padding: 2 },\n segment: { flexDirection: "row", alignItems: "center", gap: 5, paddingHorizontal: 8, paddingVertical: 4, borderRadius: 6 },\n segmentOn: { backgroundColor: colors.surface0, shadowColor: "#000", shadowOpacity: 0.08, shadowRadius: 2 },\n segmentText: { color: colors.foregroundMuted, fontSize: 12 },\n segmentTextOn: { color: colors.foreground, fontSize: 12, fontWeight: "600" },\n filter: { paddingHorizontal: 9, paddingVertical: 4, borderRadius: 999, borderWidth: 1, borderColor: colors.border },\n filterOn: { backgroundColor: colors.foreground, borderColor: colors.foreground },\n filterText: { color: colors.foreground, fontSize: 12 },\n filterTextOn: { color: colors.surface0, fontSize: 12, fontWeight: "600" },\n filterCount: { opacity: 0.6, fontSize: 11 },\n search: { flex: 1, minWidth: 160, flexDirection: "row", alignItems: "center", gap: 6, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 8, backgroundColor: colors.surface1 },\n searchInput: { flex: 1, minWidth: 0, color: colors.foreground, fontSize: 12.5, paddingVertical: 6 },\n composer: { flexDirection: compact ? "column" : "row", gap: 8, alignItems: compact ? "stretch" : "center" },\n input: { flex: compact ? void 0 : 1, minWidth: 0, color: colors.foreground, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 10, paddingVertical: 7, backgroundColor: colors.surface1 },\n priorities: { flexDirection: "row", gap: 4 },\n chip: { paddingHorizontal: 7, paddingVertical: 5, borderRadius: 6, borderWidth: 1, borderColor: colors.border },\n chipOn: { backgroundColor: colors.accent, borderColor: colors.accent },\n chipText: { color: colors.foregroundMuted, fontSize: 12 },\n chipTextOn: { color: colors.accentForeground, fontSize: 12 },\n button: { paddingHorizontal: 12, paddingVertical: 7, borderRadius: 8, backgroundColor: colors.accent },\n buttonText: { color: colors.accentForeground, fontWeight: "600" },\n body: { flex: 1, flexDirection: "row" },\n pane: { flex: 1, minWidth: 0 },\n paneList: { flex: 2, borderRightWidth: 1, borderRightColor: colors.border },\n paneDetail: { flex: 3 },\n empty: { margin: 16, borderWidth: 1, borderStyle: "dashed", borderColor: colors.border, borderRadius: 10, padding: 24, alignItems: "center" },\n listContent: { paddingVertical: 6 },\n group: { marginBottom: 4 },\n groupHeader: { flexDirection: "row", alignItems: "center", gap: 6, paddingHorizontal: compact ? 10 : 14, paddingVertical: 7 },\n groupTitle: { color: colors.foregroundMuted, fontSize: 11.5, fontWeight: "600", textTransform: "uppercase", letterSpacing: 0.4 },\n groupCount: { color: colors.foregroundMuted, fontSize: 11, opacity: 0.8 },\n line: { paddingHorizontal: compact ? 10 : 14, paddingVertical: 7, gap: 3, borderLeftWidth: 2, borderLeftColor: "transparent" },\n lineOn: { backgroundColor: colors.surface2, borderLeftColor: colors.accent },\n lineHover: { backgroundColor: colors.surface1 },\n lineTop: { flexDirection: "row", alignItems: "center", gap: 7 },\n lineTitle: { flex: 1, minWidth: 0, color: colors.foreground, fontSize: 13 },\n lineMeta: { flexDirection: "row", flexWrap: "wrap", gap: 6, paddingLeft: 16 },\n id: { color: colors.foregroundMuted, fontSize: 11.5, ...mono },\n age: { color: colors.foregroundMuted, fontSize: 11, ...mono },\n assignee: { color: colors.accent, fontSize: 11.5, maxWidth: 110 },\n label: { color: colors.foregroundMuted, fontSize: 11, backgroundColor: colors.surface2, borderRadius: 4, paddingHorizontal: 5, paddingVertical: 1 },\n inlineAction: { flexDirection: "row", alignItems: "center", gap: 10, paddingLeft: compact ? 26 : 30, paddingRight: 14, paddingBottom: 8 },\n board: { padding: 12, gap: 10, alignItems: "flex-start" },\n column: { width: 248, backgroundColor: colors.surface1, borderRadius: 10, borderWidth: 1, borderColor: colors.border, maxHeight: 640 },\n columnHeader: { flexDirection: "row", alignItems: "center", gap: 7, paddingHorizontal: 12, paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: colors.border },\n columnTitle: { flex: 1, color: colors.foreground, fontSize: 12.5, fontWeight: "600" },\n columnBody: { padding: 8, gap: 8 },\n card: { backgroundColor: colors.surface0, borderRadius: 8, borderWidth: 1, borderColor: colors.border, borderLeftWidth: 3, padding: 10, gap: 5 },\n cardHover: { borderColor: colors.foregroundMuted },\n cardBlocked: { borderLeftColor: colors.statusDanger },\n cardReady: { borderLeftColor: colors.statusSuccess },\n cardLabels: { flexDirection: "row", flexWrap: "wrap", gap: 6 },\n blocked: { color: colors.statusDanger, fontSize: 11.5 },\n cardTitle: { color: colors.foreground, fontSize: 13, lineHeight: 18 },\n epic: { marginHorizontal: compact ? 10 : 14, marginVertical: 6, padding: 12, borderRadius: 10, borderWidth: 1, borderColor: colors.border, backgroundColor: colors.surface1, gap: 8 },\n progressTrack: { height: 6, borderRadius: 3, backgroundColor: colors.surface2, overflow: "hidden" },\n progressFill: { height: 6, borderRadius: 3, backgroundColor: colors.statusSuccess },\n progressText: { color: colors.foregroundMuted, fontSize: 11.5, ...mono },\n treeToggle: { flexDirection: "row", alignItems: "center", gap: 4 },\n tree: { marginLeft: 6, borderLeftWidth: 1, borderLeftColor: colors.border, backgroundColor: colors.surface0, borderRadius: 6 },\n detail: { padding: compact ? 12 : 18, gap: 14 },\n detailHeader: { flexDirection: "row", alignItems: "center", gap: 8 },\n statePill: { flexDirection: "row", alignItems: "center", gap: 6, borderWidth: 1, borderColor: colors.border, borderRadius: 999, paddingHorizontal: 8, paddingVertical: 2 },\n detailTitle: { color: colors.foreground, fontSize: 17, fontWeight: "600", lineHeight: 23 },\n fields: { borderWidth: 1, borderColor: colors.border, borderRadius: 10, overflow: "hidden" },\n field: { flexDirection: "row", alignItems: "center", gap: 12, paddingHorizontal: 12, paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: colors.border },\n fieldLabel: { width: 84, color: colors.foregroundMuted, fontSize: 12 },\n fieldValue: { flex: 1, minWidth: 0 },\n inline: { flexDirection: "row", alignItems: "center", gap: 6, flexWrap: "wrap" },\n box: { borderRadius: 10, backgroundColor: colors.surface1, borderWidth: 1, borderColor: colors.border, padding: 12, gap: 6 },\n boxTitle: { color: colors.foregroundMuted, fontSize: 11.5, fontWeight: "600", textTransform: "uppercase", letterSpacing: 0.4 },\n detailActions: { flexDirection: "row", gap: 8, flexWrap: "wrap" },\n smallButton: { paddingHorizontal: 10, paddingVertical: 6, borderRadius: 7, borderWidth: 1, borderColor: colors.border, backgroundColor: colors.surface1 },\n smallButtonPrimary: { backgroundColor: colors.accent, borderColor: colors.accent },\n smallButtonDanger: { borderColor: colors.statusDanger },\n smallButtonText: { color: colors.foreground, fontSize: 12.5, fontWeight: "500" },\n smallButtonTextPrimary: { color: colors.accentForeground, fontSize: 12.5, fontWeight: "600" },\n smallButtonTextDanger: { color: colors.statusDanger, fontSize: 12.5 },\n text: { color: colors.foreground, fontSize: 13, lineHeight: 19 },\n small: { color: colors.foregroundMuted, fontSize: 12 },\n muted: { color: colors.foregroundMuted, fontSize: 13 },\n danger: { color: colors.statusDanger, fontSize: 13 },\n warning: { color: colors.statusWarning, fontSize: 12 },\n link: { color: colors.accent, fontSize: 13, ...mono }\n };\n}\n\n// integrations/paseo/client/task-pills.ts\nvar TASKS_SCREEN = "alp-tasks";\nvar POLL_MS2 = 2e4;\nvar MENU_LIMIT = 8;\nvar PAGE = 200;\nfunction tasksScreen(workspaceId, directory, taskId) {\n return { screenId: TASKS_SCREEN, params: { workspaceId, directory, ...taskId ? { taskId } : {} } };\n}\nvar ORDER = ["approve", "review", "progress", "ready", "blocked"];\nvar STATES = {\n approve: { label: "Approve", icon: "Hand" },\n review: { label: "Review", icon: "Eye" },\n progress: { label: "In progress", icon: "LoaderCircle" },\n ready: { label: "Ready", icon: "CircleCheck" },\n blocked: { label: "Blocked", icon: "CircleSlash" },\n closed: { label: "Done", icon: "CheckCheck" }\n};\nfunction sessionWork(board, sessions = []) {\n const ids = sessions.map((id) => board?.sessions?.[id]).find(Boolean) ?? [];\n const index = new Map((board?.tasks ?? []).map((task) => [task.id, task]));\n return ids.flatMap((id) => index.has(id) ? [{ task: index.get(id), state: stateOf(index.get(id)) }] : []);\n}\nfunction menuTasks(tasks) {\n return tasks.filter((task) => task.status !== "closed" && task.type !== "epic").map((task) => ({ task, state: stateOf(task) })).sort((a, b) => ORDER.indexOf(a.state) - ORDER.indexOf(b.state) || a.task.priority - b.task.priority || a.task.id.localeCompare(b.task.id));\n}\nfunction taskButton(board, open, sessions = []) {\n const listed = board ? menuTasks(board.tasks) : [];\n const worked = sessionWork(board, sessions);\n const done = worked.filter((entry2) => entry2.state === "closed").length;\n const mine = new Set(worked.map((entry2) => entry2.task.id));\n const shown = [...worked, ...listed.filter((entry2) => !mine.has(entry2.task.id))];\n const entry = ({ task, state }, index) => ({\n kind: "item",\n id: `task-${index}`,\n title: `${STATES[state].label} \\xB7 ${task.title}`,\n icon: STATES[state].icon,\n behavior: { kind: "action", onPress: () => open(task.id) }\n });\n const items = shown.slice(0, MENU_LIMIT).map(entry);\n if (worked.length && items.length > worked.length) items.splice(worked.length, 0, { kind: "separator", id: "session-end" });\n if (items.length) items.push({ kind: "separator", id: "tasks-end" });\n const more = shown.length - MENU_LIMIT;\n items.push({ kind: "item", id: "all-tasks", title: more > 0 ? `All tasks (${more} more)` : "All tasks", icon: "ListTodo", behavior: { kind: "action", onPress: () => open() } });\n return {\n title: worked.length ? `ALP tasks: ${done} of ${worked.length} done in this session, ${listed.length} open` : listed.length ? `ALP tasks: ${listed.length} open` : "ALP tasks",\n icon: "ListTodo",\n label: worked.length ? `Tasks \\xB7 ${done}/${worked.length}` : listed.length ? `Tasks \\xB7 ${listed.length}` : "Tasks",\n visible: board?.projectRoot !== null,\n behavior: { kind: "menu", items }\n };\n}\nfunction signature(board, sessions) {\n return JSON.stringify(board && [board.projectRoot !== null, [...sessionWork(board, sessions), ...menuTasks(board.tasks)].map(({ task, state }) => [task.id, state, task.title])]);\n}\nfunction addTaskPills(client) {\n const agents = /* @__PURE__ */ new Map();\n const directories = /* @__PURE__ */ new Map();\n const boards = /* @__PURE__ */ new Map();\n const pills = /* @__PURE__ */ new Map();\n let subscription = null;\n let stopped = false;\n let retry;\n let polling = false;\n let again = false;\n const opener = (agent, directory) => (taskId) => client.openScreen(tasksScreen(agent.workspaceId, directory, taskId));\n const directoryOf = (agent) => {\n let found = directories.get(agent.workspaceId);\n if (!found) {\n found = client.paseo.workspaces.ref(agent.workspaceId).refresh().then((workspace) => workspace?.workspaceDirectory || workspace?.projectRootPath || agent.cwd).catch(() => {\n directories.delete(agent.workspaceId);\n return agent.cwd;\n });\n directories.set(agent.workspaceId, found);\n }\n return found;\n };\n const show = (agent) => __async(null, null, function* () {\n const directory = yield directoryOf(agent);\n if (stopped || pills.has(agent.id) || agents.get(agent.id) !== agent) return;\n const board = boards.get(directory) ?? null;\n try {\n const registration = client.addComposerPill({ id: "alp-tasks", workspaceId: agent.workspaceId, agentId: agent.id, button: taskButton(board, opener(agent, directory), agent.sessions) });\n pills.set(agent.id, { agent, directory, registration, signature: signature(board, agent.sessions) });\n } catch {\n return;\n }\n if (!board) void poll();\n });\n const hide = (id) => {\n agents.delete(id);\n pills.get(id)?.registration.remove();\n pills.delete(id);\n };\n const accept = (snapshot) => {\n const known = agents.get(snapshot.id);\n if (snapshot.provider !== "alp" || !snapshot.workspaceId || snapshot.archivedAt) {\n if (known) hide(snapshot.id);\n return;\n }\n const sessions = [snapshot.persistence?.sessionId, snapshot.id].filter((id) => Boolean(id));\n if (known?.workspaceId === snapshot.workspaceId && known.sessions.join() === sessions.join()) return;\n if (known) hide(snapshot.id);\n const agent = { id: snapshot.id, workspaceId: snapshot.workspaceId, cwd: snapshot.cwd, sessions };\n agents.set(agent.id, agent);\n void show(agent);\n };\n const load = (page) => __async(null, null, function* () {\n const seen = /* @__PURE__ */ new Set();\n for (let current = page; ; ) {\n for (const { agent } of current.entries) {\n seen.add(agent.id);\n accept(agent);\n }\n const cursor = current.pageInfo.nextCursor;\n if (!current.pageInfo.hasMore || !cursor || stopped) break;\n current = yield client.paseo.agents.list({ scope: "active", page: { limit: PAGE, cursor } });\n }\n for (const id of [...agents.keys()]) if (!seen.has(id)) hide(id);\n });\n const watch = () => __async(null, null, function* () {\n try {\n const first = yield client.paseo.agents.list({ scope: "active", page: { limit: PAGE }, subscribe: {} });\n if (stopped) {\n void first.subscription.release().catch(() => {\n });\n return;\n }\n subscription = first.subscription;\n first.subscription.subscribe({\n snapshot: (snapshot) => {\n void load(snapshot).catch(() => {\n });\n },\n update: (message2) => {\n if (message2.type !== "agent_update") return;\n if (message2.payload.kind === "remove") hide(message2.payload.agentId);\n else accept(message2.payload.agent);\n }\n });\n } catch {\n if (!stopped) retry = setTimeout(() => void watch(), POLL_MS2);\n }\n });\n const poll = () => __async(null, null, function* () {\n if (polling) {\n again = true;\n return;\n }\n polling = true;\n try {\n const shown = new Set([...pills.values()].map((pill) => pill.directory));\n for (const directory of shown) {\n if (stopped) return;\n try {\n boards.set(directory, yield client.rpc(tasksList, { directory }));\n } catch {\n continue;\n }\n for (const pill of pills.values()) if (pill.directory === directory) render(pill);\n }\n for (const directory of [...boards.keys()]) if (!shown.has(directory)) boards.delete(directory);\n } finally {\n polling = false;\n if (again && !stopped) {\n again = false;\n void poll();\n }\n }\n });\n const render = (pill) => {\n const board = boards.get(pill.directory) ?? null;\n const next = signature(board, pill.agent.sessions);\n if (next === pill.signature) return;\n pill.signature = next;\n pill.registration.update(taskButton(board, opener(pill.agent, pill.directory), pill.agent.sessions));\n };\n const timer = setInterval(() => void poll(), POLL_MS2);\n void watch();\n return () => {\n stopped = true;\n clearInterval(timer);\n if (retry !== void 0) clearTimeout(retry);\n for (const id of [...pills.keys()]) hide(id);\n void subscription?.release().catch(() => {\n });\n };\n}\n\n// integrations/paseo/client/team-model-settings.tsx\nvar import_react3 = require("react");\nvar import_react_native5 = require("react-native");\nvar import_client2 = require("@getpaseo/plugin/client");\nvar import_ui = require("@getpaseo/plugin/client/ui");\n\n// integrations/paseo/shared/library.ts\nvar import_plugin2 = require("@getpaseo/plugin");\nvar import_zod2 = require("zod");\nvar Directory2 = import_zod2.z.string().min(1).optional();\nvar KindSchema = import_zod2.z.enum(["agents", "skills", "mcp", "hooks", "teams", "providers"]);\nvar ScopeSchema = import_zod2.z.enum(["library", "project"]);\nvar Name = import_zod2.z.string().regex(/^[\\w.-]+$/).refine((name) => name !== "." && name !== "..");\nvar Source = import_zod2.z.enum(["builtin", "library", "project"]);\nvar EntryRowSchema = import_zod2.z.object({\n name: import_zod2.z.string(),\n source: Source,\n overrides: Source.optional(),\n path: import_zod2.z.string().optional(),\n description: import_zod2.z.string().optional(),\n usedBy: import_zod2.z.array(import_zod2.z.string()).optional()\n});\nvar libraryList = (0, import_plugin2.defineRpc)({\n name: "alp.library.list",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema }),\n output: import_zod2.z.object({\n projectRoot: import_zod2.z.string().nullable(),\n library: import_zod2.z.string(),\n entries: import_zod2.z.array(EntryRowSchema),\n /**\n * Set when the library can only be looked at from here (ALP remote mode): why, and where to\n * change it. `unlisted` says why there are no entries at all (no granted workspace open).\n */\n readOnly: import_zod2.z.object({ reason: import_zod2.z.string(), unlisted: import_zod2.z.string().optional() }).optional()\n })\n});\nvar libraryGet = (0, import_plugin2.defineRpc)({\n name: "alp.library.get",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema, name: Name, scope: ScopeSchema.optional() }),\n output: import_zod2.z.object({\n kind: KindSchema,\n name: import_zod2.z.string(),\n source: Source,\n overrides: Source.optional(),\n content: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()),\n /** Pass back with a save or delete; a different current revision refuses it. */\n revision: import_zod2.z.string().nullable(),\n usedBy: import_zod2.z.array(import_zod2.z.string()),\n /** Agents: the skills the library gives it by name (role-skills.json). */\n librarySkills: import_zod2.z.array(import_zod2.z.string()).optional()\n })\n});\nvar librarySkills = (0, import_plugin2.defineRpc)({\n name: "alp.library.skills",\n input: import_zod2.z.object({ agent: Name, skills: import_zod2.z.array(Name) }),\n output: import_zod2.z.object({ skills: import_zod2.z.array(import_zod2.z.string()) })\n});\nvar librarySave = (0, import_plugin2.defineRpc)({\n name: "alp.library.save",\n input: import_zod2.z.object({\n directory: Directory2,\n kind: KindSchema,\n name: Name,\n scope: ScopeSchema,\n content: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()),\n /** null creates; a string replaces that revision; omitted overwrites. */\n revision: import_zod2.z.string().nullable().optional()\n }),\n output: import_zod2.z.object({ revision: import_zod2.z.string().nullable(), syncedProjects: import_zod2.z.number().int().nonnegative().optional(), syncErrors: import_zod2.z.array(import_zod2.z.string()).optional() })\n});\nvar libraryDelete = (0, import_plugin2.defineRpc)({\n name: "alp.library.delete",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema, name: Name, scope: ScopeSchema, revision: import_zod2.z.string().optional() }),\n /** now: the layer that applies again after removing an override. */\n output: import_zod2.z.object({ removed: import_zod2.z.boolean(), now: Source.optional() })\n});\nvar libraryDuplicate = (0, import_plugin2.defineRpc)({\n name: "alp.library.duplicate",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema, from: Name, to: Name, scope: ScopeSchema }),\n output: import_zod2.z.object({ revision: import_zod2.z.string().nullable() })\n});\nvar libraryRename = (0, import_plugin2.defineRpc)({\n name: "alp.library.rename",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema, from: Name, to: Name, scope: ScopeSchema }),\n output: import_zod2.z.object({ revision: import_zod2.z.string().nullable() })\n});\nvar libraryTest = (0, import_plugin2.defineRpc)({\n name: "alp.library.test",\n input: import_zod2.z.object({ directory: Directory2, kind: import_zod2.z.enum(["mcp", "hooks", "providers"]), name: Name, scope: ScopeSchema.optional() }),\n output: import_zod2.z.object({\n ok: import_zod2.z.boolean(),\n /** MCP: the server and its tools. */\n server: import_zod2.z.object({ name: import_zod2.z.string().optional(), version: import_zod2.z.string().optional() }).optional(),\n tools: import_zod2.z.array(import_zod2.z.object({ name: import_zod2.z.string(), description: import_zod2.z.string().optional() })).optional(),\n /** Hooks: how the sample run went. */\n exitCode: import_zod2.z.number().nullable().optional(),\n signal: import_zod2.z.string().nullable().optional(),\n timedOut: import_zod2.z.boolean().optional(),\n wouldBlock: import_zod2.z.boolean().optional(),\n stdout: import_zod2.z.string().optional(),\n stderr: import_zod2.z.string().optional(),\n durationMs: import_zod2.z.number().optional(),\n /** Providers: who the ACP agent says it is, and what it supports. */\n protocolVersion: import_zod2.z.number().optional(),\n agent: import_zod2.z.object({ name: import_zod2.z.string().optional(), title: import_zod2.z.string().optional(), version: import_zod2.z.string().optional() }).optional(),\n loadSession: import_zod2.z.boolean().optional(),\n mcpHttp: import_zod2.z.boolean().optional(),\n authMethods: import_zod2.z.array(import_zod2.z.string()).optional()\n })\n});\nvar LanguageSettingSchema = import_zod2.z.object({\n language: import_zod2.z.string().nullable(),\n applies: import_zod2.z.string(),\n default: import_zod2.z.string(),\n /** Why it cannot be changed from here (ALP remote mode). */\n readOnly: import_zod2.z.string().optional()\n});\nvar languageGet = (0, import_plugin2.defineRpc)({\n name: "alp.settings.language.get",\n input: import_zod2.z.object({}),\n output: LanguageSettingSchema\n});\nvar languageSet = (0, import_plugin2.defineRpc)({\n name: "alp.settings.language.set",\n input: import_zod2.z.object({ language: import_zod2.z.string().trim().min(1).max(40).nullable() }),\n output: LanguageSettingSchema\n});\nvar libraryModels = (0, import_plugin2.defineRpc)({\n name: "alp.library.models",\n input: import_zod2.z.object({}),\n output: import_zod2.z.object({ models: import_zod2.z.array(import_zod2.z.object({ id: import_zod2.z.string(), label: import_zod2.z.string(), efforts: import_zod2.z.array(import_zod2.z.string()), effort: import_zod2.z.string().optional() })) })\n});\n\n// integrations/paseo/shared/team-models.ts\nvar MODEL_PRESETS = [\n { label: "Claude only", value: "claude" },\n { label: "Codex only", value: "codex" },\n { label: "OpenCode only", value: "opencode" },\n { label: "Antigravity only", value: "antigravity" },\n { label: "Mix \\xB7 Claude + Codex", value: "mix" }\n];\nfunction presetTeamModels(team, preset, models) {\n const next = JSON.parse(JSON.stringify(team));\n const find = (provider) => models.find((model) => provider === "opencode" ? model.id === "acp:opencode" || model.id.startsWith("acp:opencode/") : model.id.startsWith(`${provider}:`));\n const primary = find(preset === "mix" ? "claude" : preset);\n const secondary = preset === "mix" ? find("codex") : primary;\n if (!primary || !secondary) throw new Error("No models available for this preset. Configure the provider in Settings first.");\n const assign = (target, model) => {\n target.model = model.id;\n if (model.effort) target.thinking = model.effort;\n else delete target.thinking;\n };\n for (const [name, member] of Object.entries(next.members ?? {})) {\n if (name !== "oracle") assign(member, name === next.main ? primary : secondary);\n }\n if (next.supervisor) assign(next.supervisor, secondary);\n if (next.members?.oracle) {\n next.oracleModels = [.../* @__PURE__ */ new Set([primary.id, secondary.id])];\n next.oracleThinking = Object.fromEntries([primary, secondary].filter((model) => model.effort).map((model) => [model.id, model.effort]));\n }\n next.modelSetup = { mode: "default", preset };\n return next;\n}\nfunction modelSetupFor(team, models) {\n if (team.modelSetup) return team.modelSetup;\n for (const { value } of MODEL_PRESETS) {\n let expected;\n try {\n expected = presetTeamModels(team, value, models);\n } catch {\n continue;\n }\n const same = (a, b) => a.model === b.model && a.thinking === b.thinking;\n if (!Object.entries(team.members ?? {}).filter(([name]) => name !== "oracle").every(([name, member]) => same(member, expected.members[name]))) continue;\n if (team.supervisor && !same(team.supervisor, expected.supervisor)) continue;\n if (team.members?.oracle && (JSON.stringify(team.oracleModels) !== JSON.stringify(expected.oracleModels) || expected.oracleModels.some((id) => (team.oracleThinking?.[id] ?? team.oracleThinking?.[id.split(":")[0]]) !== expected.oracleThinking?.[id]))) continue;\n return { mode: "default", preset: value };\n }\n return { mode: "custom" };\n}\n\n// integrations/paseo/client/side-nav.tsx\nvar import_react_native3 = require("@getpaseo/plugin/client/react-native");\nvar import_react2 = require("react");\nvar import_react_native4 = require("react-native");\nvar import_jsx_runtime2 = require("react/jsx-runtime");\nvar hovered2 = (state) => !!state.hovered;\nvar COLLAPSE_BELOW = 640;\nvar EXPANDED = 216;\nvar COLLAPSED = 52;\nfunction SideNavLayout(props) {\n const { theme, compact, groups, active, onSelect } = props;\n const styles = (0, import_react2.useMemo)(() => layoutStyles(theme), [theme]);\n const [width, setWidth] = (0, import_react2.useState)(0);\n const [choice, setChoice] = (0, import_react2.useState)(props.initialCollapsed);\n const [open, setOpen] = (0, import_react2.useState)(false);\n const collapsed = choice ?? (width > 0 && width < COLLAPSE_BELOW);\n const select = (item, child) => {\n onSelect(item, child);\n setOpen(false);\n };\n const aside = (mode) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(\n Aside,\n {\n styles,\n theme,\n title: props.title,\n subtitle: props.subtitle,\n groups,\n active,\n onSelect: select,\n collapsed: mode === "fixed" && collapsed,\n onToggle: mode === "fixed" ? () => setChoice(!collapsed) : () => setOpen(false),\n overlay: mode === "overlay"\n }\n );\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: props.embedded ? { width: "100%" } : styles.root, onLayout: (event) => setWidth(event.nativeEvent.layout.width), children: [\n !props.embedded && !compact ? aside("fixed") : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: props.embedded ? { minWidth: 0 } : styles.main, children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: [styles.header, props.embedded ? { paddingHorizontal: 0, paddingTop: 0 } : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.headerRow, children: [\n compact && !props.embedded ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "button", accessibilityLabel: "Open navigation", onPress: () => setOpen(true), style: styles.iconButton, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: "Menu", size: 18, color: theme.colors.foreground }) }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.crumbs, children: [\n props.breadcrumb.map((part, index) => [\n index ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.crumbSeparator, children: "/" }, `separator-${index}`) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: index === props.breadcrumb.length - 1 ? styles.crumbCurrent : styles.crumb, numberOfLines: 1, children: part }, `${index}-${part}`)\n ]),\n props.badges\n ] }),\n props.actions ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: styles.actions, children: props.actions }) : null\n ] }),\n props.tabs?.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, contentContainerStyle: styles.tabs, children: props.tabs.map((tab) => {\n const on = tab.key === props.tab;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "tab", accessibilityLabel: tab.label, accessibilityState: { selected: on }, onPress: () => props.onTab?.(tab.key), style: [styles.tab, on ? styles.tabOn : null], children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.Text, { style: on ? styles.tabTextOn : styles.tabText, children: [\n tab.label,\n tab.count !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.tabCount, children: ` ${tab.count}` }) : null\n ] }) }, tab.key);\n }) }) : null\n ] }),\n props.embedded ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: [styles.bodyContent, { paddingHorizontal: 0 }], children: props.children }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.ScrollView, { style: styles.body, contentContainerStyle: styles.bodyContent, children: props.children }),\n props.footer ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: [styles.footer, props.embedded ? { paddingHorizontal: 0 } : null], children: props.footer }) : null\n ] }),\n !props.embedded && compact && open ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.overlay, children: [\n aside("overlay"),\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "button", accessibilityLabel: "Close navigation", onPress: () => setOpen(false), style: styles.scrim })\n ] }) : null\n ] });\n}\nfunction Aside({ styles, theme, title, subtitle, groups, active, onSelect, collapsed, onToggle, overlay }) {\n const { colors } = theme;\n const [opened, setOpened] = (0, import_react2.useState)({});\n const tone = (value) => value === "accent" ? colors.accent : value === "warning" ? colors.statusWarning : colors.border;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: [styles.aside, { width: collapsed ? COLLAPSED : EXPANDED }, overlay ? styles.asideOverlay : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: [styles.asideHeader, collapsed ? styles.asideHeaderCollapsed : null], children: [\n !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.asideTitleBox, children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.asideTitle, numberOfLines: 1, children: title }),\n subtitle ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.asideSubtitle, numberOfLines: 1, children: subtitle }) : null\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "button", accessibilityLabel: overlay ? "Close navigation" : collapsed ? "Expand navigation" : "Collapse navigation", onPress: onToggle, style: styles.iconButton, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: overlay ? "X" : collapsed ? "PanelLeftOpen" : "PanelLeftClose", size: 16, color: colors.foregroundMuted }) })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.ScrollView, { contentContainerStyle: styles.asideList, children: groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.group, children: [\n !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.groupLabel, children: group.label }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: styles.groupRule }),\n group.items.map((item) => {\n const selected = active.item === item.key;\n const expanded = !collapsed && (opened[item.key] ?? selected) && !!item.children?.length;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(\n import_react_native4.Pressable,\n {\n accessibilityRole: "button",\n accessibilityLabel: item.label,\n accessibilityState: { selected: selected && !active.child },\n onPress: () => {\n onSelect(item.key);\n setOpened((current) => ({ ...current, [item.key]: true }));\n },\n style: (state) => [styles.item, collapsed ? styles.itemCollapsed : null, selected ? styles.itemOn : hovered2(state) ? styles.itemHover : null],\n children: [\n selected ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: styles.itemBar }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: item.icon, size: 16, color: selected ? colors.accent : colors.foregroundMuted }),\n !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: [styles.itemLabel, selected ? styles.itemLabelOn : null], numberOfLines: 1, children: item.label }) : null,\n !collapsed && item.count !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.count, children: item.count }) : null,\n !collapsed && item.children?.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "button", accessibilityLabel: `${expanded ? "Hide" : "Show"} ${item.label}`, hitSlop: 8, onPress: () => setOpened((current) => ({ ...current, [item.key]: !expanded })), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: expanded ? "ChevronDown" : "ChevronRight", size: 14, color: colors.foregroundMuted }) }) : null\n ]\n }\n ),\n expanded ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: styles.children, children: item.children.map((child) => {\n const on = selected && active.child === child.key;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(\n import_react_native4.Pressable,\n {\n accessibilityRole: "button",\n accessibilityLabel: `${item.label} ${child.label}`,\n accessibilityState: { selected: on },\n onPress: () => onSelect(item.key, child.key),\n style: (state) => [styles.child, on ? styles.childOn : hovered2(state) ? styles.itemHover : null],\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: [styles.dot, { backgroundColor: tone(child.tone) }] }),\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: [styles.childLabel, on ? styles.itemLabelOn : null], numberOfLines: 1, children: child.label }),\n child.hint ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.childHint, numberOfLines: 1, children: child.hint }) : null\n ]\n },\n child.key\n );\n }) }) : null\n ] }, item.key);\n })\n ] }, group.key)) })\n ] });\n}\nfunction Pill({ theme, label, tone = "muted" }) {\n const { colors } = theme;\n const color = tone === "accent" ? colors.accent : tone === "success" ? colors.statusSuccess : tone === "warning" ? colors.statusWarning : tone === "danger" ? colors.statusDanger : colors.foregroundMuted;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: { borderRadius: 999, borderWidth: 1, borderColor: tone === "muted" ? colors.border : color, paddingHorizontal: 7, paddingVertical: 1, alignSelf: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: { color, fontSize: 11, fontWeight: "500" }, children: label }) });\n}\nfunction Button({ theme, label, onPress, kind = "plain", icon, disabled, accessibilityLabel }) {\n const { colors } = theme;\n const color = kind === "primary" ? colors.accentForeground : kind === "danger" ? colors.statusDanger : colors.foreground;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(\n import_react_native4.Pressable,\n {\n accessibilityRole: "button",\n accessibilityLabel: accessibilityLabel ?? label,\n disabled,\n onPress,\n style: (state) => ({\n flexDirection: "row",\n alignItems: "center",\n gap: 6,\n borderRadius: 8,\n paddingHorizontal: 12,\n paddingVertical: 7,\n opacity: disabled ? 0.5 : 1,\n backgroundColor: kind === "primary" ? colors.accent : hovered2(state) ? colors.surface2 : colors.surface1,\n borderWidth: kind === "primary" ? 0 : 1,\n borderColor: kind === "danger" ? colors.statusDanger : colors.border\n }),\n children: [\n icon ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: icon, size: 14, color }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: { color, fontSize: 13, fontWeight: kind === "primary" ? "600" : "500" }, children: label })\n ]\n }\n );\n}\nfunction layoutStyles(theme) {\n const { colors } = theme;\n return {\n root: { flex: 1, flexDirection: "row", backgroundColor: colors.surface0, minHeight: 560, borderWidth: 1, borderColor: colors.border, borderRadius: 12, overflow: "hidden" },\n aside: { backgroundColor: colors.surface1, borderRightWidth: 1, borderRightColor: colors.border },\n asideOverlay: { height: "100%", shadowColor: "#000", shadowOpacity: 0.2, shadowRadius: 16 },\n asideHeader: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 12, paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: colors.border, gap: 8 },\n asideHeaderCollapsed: { justifyContent: "center", paddingHorizontal: 0 },\n asideTitleBox: { flex: 1, minWidth: 0 },\n asideTitle: { color: colors.foreground, fontSize: 14, fontWeight: "600" },\n asideSubtitle: { color: colors.foregroundMuted, fontSize: 11, marginTop: 1 },\n asideList: { paddingVertical: 8, gap: 10 },\n group: { gap: 1 },\n groupLabel: { color: colors.foregroundMuted, fontSize: 11, fontWeight: "600", letterSpacing: 0.4, textTransform: "uppercase", paddingHorizontal: 14, paddingBottom: 4 },\n groupRule: { height: 1, backgroundColor: colors.border, marginHorizontal: 12, marginBottom: 4 },\n item: { flexDirection: "row", alignItems: "center", gap: 10, marginHorizontal: 6, paddingHorizontal: 8, paddingVertical: 7, borderRadius: 7 },\n itemCollapsed: { justifyContent: "center", paddingHorizontal: 0 },\n itemOn: { backgroundColor: colors.surface2 },\n itemHover: { backgroundColor: colors.surface2 },\n itemBar: { position: "absolute", left: -6, top: 6, bottom: 6, width: 3, borderRadius: 2, backgroundColor: colors.accent },\n itemLabel: { flex: 1, color: colors.foreground, fontSize: 13 },\n itemLabelOn: { color: colors.foreground, fontWeight: "600" },\n count: { color: colors.foregroundMuted, fontSize: 11, fontVariant: ["tabular-nums"] },\n children: { marginLeft: 22, borderLeftWidth: 1, borderLeftColor: colors.border, marginVertical: 2, paddingLeft: 4 },\n child: { flexDirection: "row", alignItems: "center", gap: 8, marginRight: 6, paddingHorizontal: 8, paddingVertical: 5, borderRadius: 6 },\n childOn: { backgroundColor: colors.surface2 },\n childLabel: { flex: 1, color: colors.foreground, fontSize: 12.5 },\n childHint: { color: colors.foregroundMuted, fontSize: 11 },\n dot: { width: 6, height: 6, borderRadius: 3 },\n main: { flex: 1, minWidth: 0 },\n header: { borderBottomWidth: 1, borderBottomColor: colors.border, paddingHorizontal: 20, paddingTop: 14, gap: 10 },\n headerRow: { flexDirection: "row", alignItems: "center", gap: 10, minHeight: 32 },\n crumbs: { flex: 1, minWidth: 0, flexDirection: "row", alignItems: "center", gap: 8, flexWrap: "wrap" },\n crumb: { color: colors.foregroundMuted, fontSize: 13 },\n crumbSeparator: { color: colors.foregroundMuted, fontSize: 13, opacity: 0.6 },\n crumbCurrent: { color: colors.foreground, fontSize: 16, fontWeight: "600" },\n actions: { flexDirection: "row", gap: 8, alignItems: "center" },\n tabs: { flexDirection: "row", gap: 4 },\n tab: { paddingHorizontal: 10, paddingVertical: 8, borderBottomWidth: 2, borderBottomColor: "transparent" },\n tabOn: { borderBottomColor: colors.accent },\n tabText: { color: colors.foregroundMuted, fontSize: 13 },\n tabTextOn: { color: colors.foreground, fontSize: 13, fontWeight: "600" },\n tabCount: { color: colors.foregroundMuted, fontSize: 11 },\n body: { flex: 1 },\n bodyContent: { padding: 20, gap: 16 },\n footer: { flexDirection: "row", alignItems: "center", gap: 10, paddingHorizontal: 20, paddingVertical: 12, borderTopWidth: 1, borderTopColor: colors.border, backgroundColor: colors.surface1 },\n iconButton: { padding: 6, borderRadius: 6 },\n overlay: { position: "absolute", left: 0, top: 0, right: 0, bottom: 0, flexDirection: "row" },\n scrim: { flex: 1, backgroundColor: "rgba(0,0,0,0.25)" }\n };\n}\n\n// integrations/paseo/client/team-model-settings.tsx\nvar import_jsx_runtime3 = require("react/jsx-runtime");\nvar clone = (team) => JSON.parse(JSON.stringify(team));\nfunction TeamModelSettings({ team, theme, onChange }) {\n const readModels = (0, import_client2.useRpc)(libraryModels);\n const [models, setModels] = (0, import_react3.useState)([]);\n const [error, setError] = (0, import_react3.useState)("");\n const [customFields, setCustomFields] = (0, import_react3.useState)({});\n const setup = modelSetupFor(team, models);\n const mode = setup.mode;\n const preset = setup.preset ?? "mix";\n (0, import_react3.useEffect)(() => {\n let live = true;\n readModels({}).then((result) => {\n if (live) {\n setModels(result.models);\n setError("");\n }\n }).catch((cause) => {\n if (live) setError(String(cause.message ?? cause));\n });\n return () => {\n live = false;\n };\n }, [readModels]);\n const edit = (work) => {\n const next = clone(team);\n next.modelSetup = { mode: "custom" };\n work(next);\n onChange(next);\n setError("");\n };\n const selectPreset = (value) => {\n try {\n onChange(presetTeamModels(team, value, models));\n setCustomFields({});\n setError("");\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n }\n };\n const chooseModel = (label, value, set) => {\n const known = models.find((model) => model.id === value);\n const options = [...label.startsWith("oracle-") ? [] : [{ label: "Inherit", value: "" }], ...models.map((model) => ({ value: model.id, label: model.label }))];\n if (value && !known) options.push({ label: value, value });\n options.push({ label: "Custom model ID", value: "__custom" });\n return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSelect, { label: "Model", value: customFields[label] ? "__custom" : value, options, onValueChange: (id) => {\n setCustomFields((previous) => ({ ...previous, [label]: id === "__custom" }));\n if (id !== "__custom") edit((next) => set(next, id, models.find((model) => model.id === id)?.effort));\n } }),\n customFields[label] || value && !known ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsInput, { label: "Custom model ID", hint: "claude:model, codex:model, antigravity:model or acp:provider/model", initialValue: value, onChangeText: (id) => edit((next) => set(next, id.trim())) }, `${label}-custom`) : null\n ] });\n };\n const effort = (model, value, set) => {\n const known = models.find((choice) => choice.id === model);\n const values = known ? known.efforts : ["none", "off", "low", "medium", "high", "xhigh", "max", "ultra", "ultracode"];\n const options = [{ label: "Inherit", value: "" }, ...[.../* @__PURE__ */ new Set([...values, ...value ? [value] : []])].map((value2) => ({ label: value2, value: value2 }))];\n return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSelect, { label: "Effort", value, options, onValueChange: (value2) => edit((next) => set(next, value2)) });\n };\n const assign = (target, id, thinking) => {\n if (id) target.model = id;\n else delete target.model;\n if (thinking) target.thinking = thinking;\n else delete target.thinking;\n };\n const setEffort = (target, value) => {\n if (value) target.thinking = value;\n else delete target.thinking;\n };\n const lenses = team.oracleModels ?? ["claude:claude-fable-5-1", "codex:gpt-6-astra"];\n return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: "Model setup", children: [\n /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSelect, { label: "Mode", value: mode, options: [{ label: "Default presets", value: "default" }, { label: "Custom", value: "custom" }], onValueChange: (value) => value === "default" ? selectPreset(preset) : edit(() => {\n }) }),\n mode === "default" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSelect, { label: "Preset", value: preset, options: MODEL_PRESETS, onValueChange: selectPreset }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: "Save with template", hint: "Save writes these model choices into settings.json for this team immediately. Project template overrides still apply to Host templates." }),\n error ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native5.Text, { accessibilityRole: "alert", style: { color: theme?.colors.statusDanger }, children: error }) : null\n ] }),\n mode === "default" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: "Preset models", children: [\n Object.entries(team.members ?? {}).filter(([name]) => name !== "oracle").map(([name, member]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: name, hint: member.model }, name)),\n team.supervisor ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: "Supervisor", hint: team.supervisor.model }) : null,\n team.members?.oracle ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: "Oracle", hint: lenses.join(", ") }) : null\n ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react3.Fragment, { children: [\n Object.entries(team.members ?? {}).filter(([name]) => name !== "oracle").map(([name, member]) => {\n const config = member;\n return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: name === team.main ? `${name} \\xB7 main` : name, children: [\n chooseModel(name, config.model ?? "", (next, id, effort2) => assign(next.members[name], id, effort2)),\n effort(config.model ?? team.members[team.main]?.model ?? "", config.thinking ?? "", (next, value) => setEffort(next.members[name], value))\n ] }, name);\n }),\n team.supervisor ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: "Supervisor", children: [\n chooseModel("supervisor", team.supervisor.model ?? "", (next, id, effort2) => assign(next.supervisor, id, effort2)),\n effort(team.supervisor.model ?? "", team.supervisor.thinking ?? "", (next, value) => setEffort(next.supervisor, value))\n ] }) : null,\n team.members?.oracle ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [\n lenses.map((id, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: `Oracle ${index + 1}`, children: [\n chooseModel(`oracle-${index}`, id, (next, value, effort2) => {\n next.oracleModels = [...lenses];\n next.oracleModels[index] = value;\n next.oracleThinking ?? (next.oracleThinking = {});\n delete next.oracleThinking[id];\n if (effort2) next.oracleThinking[value] = effort2;\n }),\n effort(id, team.oracleThinking?.[id] ?? team.oracleThinking?.[id.split(":")[0]] ?? "", (next, value) => {\n next.oracleThinking ?? (next.oracleThinking = {});\n delete next.oracleThinking[id.split(":")[0]];\n if (value) next.oracleThinking[id] = value;\n else delete next.oracleThinking[id];\n }),\n theme && lenses.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { theme, label: "Remove model", onPress: () => edit((next) => {\n next.oracleModels = lenses.filter((_, i) => i !== index);\n }) }) : null\n ] }, index)),\n theme ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { theme, label: "Add oracle model", onPress: () => edit((next) => {\n next.oracleModels = [...lenses, ""];\n setCustomFields((previous) => ({ ...previous, [`oracle-${lenses.length}`]: true }));\n }) }) : null\n ] }) : null\n ] }, "custom-models"),\n JSON.stringify(team).includes("antigravity:") ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSection, { title: "Antigravity", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: "Advisory roles", hint: \'Reviewer, Oracle and Supervisor require readOnlyMode: "instructions" in the Antigravity provider. Review copies and custom permission rules are unsupported.\' }) }) : null\n ] });\n}\n\n// integrations/paseo/client/library.tsx\nvar import_client3 = require("@getpaseo/plugin/client");\nvar import_react_native6 = require("@getpaseo/plugin/client/react-native");\nvar import_ui2 = require("@getpaseo/plugin/client/ui");\nvar import_react4 = require("react");\nvar import_react_native7 = require("react-native");\nvar import_jsx_runtime4 = require("react/jsx-runtime");\nvar KINDS = [\n { kind: "teams", title: "Teams", one: "team", icon: "Users", group: "Organisation" },\n { kind: "agents", title: "Agents", one: "agent", icon: "Bot", group: "Organisation" },\n { kind: "skills", title: "Skills", one: "skill", icon: "BookOpen", group: "Capabilities" },\n { kind: "mcp", title: "MCP servers", one: "MCP server", icon: "Plug", group: "Capabilities" },\n { kind: "hooks", title: "Hooks", one: "hook", icon: "Webhook", group: "Capabilities" },\n // ACP agents (ALPD \xA746): in the library only, so the project panel leaves them out.\n { kind: "providers", title: "Providers", one: "provider", icon: "Cpu", group: "Runtimes" }\n];\nvar shownIn = (scope) => KINDS.filter((item) => scope === "library" || item.kind !== "providers");\nvar kindOf = (kind) => KINDS.find((item) => item.kind === kind);\nvar HOOK_EVENTS = ["session.start", "turn.end", "assignment.start", "assignment.end", "handoff", "task.close", "merge"];\nvar BLOCKING_EVENTS = ["handoff", "task.close", "merge"];\nvar ROLES = ["lead", "peer", "advisor", "reviewer"];\nvar MODES = ["", "read-only", "workspace-write", "full-access"];\nvar NAME = /^[\\w.-]+$/;\nvar clone2 = (value) => JSON.parse(JSON.stringify(value));\nvar message = (cause) => cause instanceof Error ? cause.message : String(cause);\nvar sourceLabel = (source) => source === "builtin" ? "built-in" : source;\nvar sourceTone = (source) => source === "project" ? "warning" : source === "library" ? "accent" : "muted";\nvar LANGUAGES = [\n { label: "Ti\\u1EBFng Vi\\u1EC7t", value: "Vietnamese" },\n { label: "English", value: "English" },\n { label: "\\u65E5\\u672C\\u8A9E", value: "Japanese" },\n { label: "\\uD55C\\uAD6D\\uC5B4", value: "Korean" },\n { label: "\\u4E2D\\u6587", value: "Chinese" },\n { label: "Fran\\xE7ais", value: "French" },\n { label: "Deutsch", value: "German" },\n { label: "Espa\\xF1ol", value: "Spanish" }\n];\nfunction LibrarySettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library" });\n}\nfunction TeamsSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "teams", embedded: true });\n}\nfunction AgentsSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "agents", embedded: true });\n}\nfunction SkillsSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "skills", embedded: true });\n}\nfunction HooksSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "hooks", embedded: true });\n}\nfunction McpSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "mcp", embedded: true });\n}\nfunction ProjectLibraryPanel({ theme, layout, workspaceId }) {\n const directory = (0, import_client3.useWorkspace)(workspaceId, (workspace) => workspace.directory || workspace.projectRootPath);\n if (!directory) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: { padding: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: { color: theme.colors.foregroundMuted }, children: "This panel needs a workspace." }) });\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "project", directory });\n}\nfunction LibraryManager({ theme, compact, scope, directory, embedded = false, initialKind = "teams" }) {\n const list = (0, import_client3.useRpc)(libraryList);\n const get = (0, import_client3.useRpc)(libraryGet);\n const save = (0, import_client3.useRpc)(librarySave);\n const remove = (0, import_client3.useRpc)(libraryDelete);\n const duplicate = (0, import_client3.useRpc)(libraryDuplicate);\n const probe = (0, import_client3.useRpc)(libraryTest);\n const give = (0, import_client3.useRpc)(librarySkills);\n const readLanguage = (0, import_client3.useRpc)(languageGet);\n const writeLanguage = (0, import_client3.useRpc)(languageSet);\n const toast = (0, import_react_native6.useToast)();\n const [language, setLanguageState] = (0, import_react4.useState)(null);\n const [lists, setLists] = (0, import_react4.useState)({});\n const [where, setWhere] = (0, import_react4.useState)(null);\n const [error, setError] = (0, import_react4.useState)(null);\n const [selection, setSelection] = (0, import_react4.useState)({ kind: initialKind });\n const [entry, setEntry] = (0, import_react4.useState)(null);\n const [tick, setTick] = (0, import_react4.useState)(0);\n const refresh = (0, import_react4.useCallback)(() => setTick((value) => value + 1), []);\n const base = directory ? { directory } : {};\n (0, import_react4.useEffect)(() => {\n let live = true;\n Promise.all(KINDS.map(({ kind }) => list({ ...base, kind }).then((result) => [kind, result]))).then((results) => {\n if (!live) return;\n setLists(Object.fromEntries(results.map(([kind, result]) => [kind, result.entries])));\n setWhere({ projectRoot: results[0][1].projectRoot, library: results[0][1].library, ...results[0][1].readOnly ? { readOnly: results[0][1].readOnly } : {} });\n setError(null);\n }).catch((cause) => {\n if (live) setError(message(cause));\n });\n return () => {\n live = false;\n };\n }, [list, directory, tick]);\n (0, import_react4.useEffect)(() => {\n if (scope !== "library") return;\n let live = true;\n readLanguage({}).then((result) => {\n if (live) setLanguageState(result);\n }).catch((cause) => {\n if (live) setError(message(cause));\n });\n return () => {\n live = false;\n };\n }, [readLanguage, scope, tick]);\n (0, import_react4.useEffect)(() => {\n if (!selection.name || selection.creating) {\n setEntry(null);\n return;\n }\n let live = true;\n get({ ...base, kind: selection.kind, name: selection.name }).then((result) => {\n if (live) setEntry(result);\n }).catch((cause) => {\n if (live) {\n toast.error(message(cause));\n setSelection({ kind: selection.kind });\n }\n });\n return () => {\n live = false;\n };\n }, [selection, get, directory, tick]);\n const run = (0, import_react4.useCallback)((work, done) => __async(null, null, function* () {\n try {\n yield work();\n toast.show(done, { variant: "success" });\n refresh();\n return true;\n } catch (cause) {\n toast.error(message(cause));\n return false;\n }\n }), [toast, refresh]);\n const actions = {\n select: (next) => setSelection(next),\n duplicate: (kind, from, to) => run(() => duplicate({ ...base, kind, from, to, scope }), `Copied ${from} to ${to}`),\n // In the project panel: copy what applies into .alp/, or drop the project\'s copy.\n override: (kind, name) => run(() => duplicate({ ...base, kind, from: name, to: name, scope: "project" }), `${name} is now overridden in this project`),\n useLibrary: (kind, name) => run(() => remove({ ...base, kind, name, scope: "project" }), `${name} follows the library again`),\n save: (kind, name, content, revision, creating) => __async(null, null, function* () {\n try {\n const result = yield save({ ...base, kind, name, scope, content, revision });\n const synced = result.syncedProjects ?? 0;\n toast.show(`Saved ${name}${synced ? ` \\xB7 Updated settings in ${synced} project${synced === 1 ? "" : "s"}` : ""}`, { variant: "success" });\n if (result.syncErrors?.length) toast.error(`Template saved, but some project settings could not be updated: ${result.syncErrors.join("; ")}`);\n refresh();\n if (creating) setSelection({ kind, name });\n return true;\n } catch (cause) {\n toast.error(message(cause));\n return false;\n }\n }),\n giveSkills: (agent, skills) => run(() => give({ agent, skills }), `Saved the skills of ${agent}`),\n setLanguage: (next) => run(() => writeLanguage({ language: next }), next ? `Agents now write to you in ${next}` : "Agents write to you in the default language again"),\n remove: (kind, name, revision) => __async(null, null, function* () {\n const removed = yield run(() => remove({ ...base, kind, name, scope, ...revision ? { revision } : {} }), `Removed ${name}`);\n if (removed) setSelection({ kind });\n return removed;\n }),\n test: (kind, name) => __async(null, null, function* () {\n try {\n return yield probe({ ...base, kind, name });\n } catch (cause) {\n toast.error(message(cause));\n return null;\n }\n })\n };\n const shown = selection.name && !selection.creating && entry?.name !== selection.name ? { kind: selection.kind } : selection;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryWorkspace, { theme, compact, scope, where, lists, error, selection: shown, entry: shown.name ? entry : null, actions, language, embedded });\n}\nfunction navGroups(scope, lists, readOnly = false) {\n const groups = scope === "library" ? [{ key: "General", label: "General", items: [{ key: "language", label: "Language", icon: "Languages" }] }] : [];\n for (const item of shownIn(scope)) {\n let group = groups.find((candidate) => candidate.label === item.group);\n if (!group) groups.push(group = { key: item.group, label: item.group, items: [] });\n const rows = lists[item.kind];\n group.items.push({\n key: item.kind,\n label: item.title,\n icon: item.icon,\n ...rows ? { count: rows.length } : {},\n // A read-only library\'s entries cannot be opened, so the aside lists kinds only.\n children: readOnly ? [] : (rows ?? []).map((row) => ({ key: row.name, label: row.name, tone: sourceTone(row.source) }))\n });\n }\n return groups;\n}\nfunction LibraryWorkspace({ theme, compact, scope, where, lists, error, selection, entry, actions, initialCollapsed, language, embedded }) {\n const styles = (0, import_react4.useMemo)(() => makeStyles2(theme, compact), [theme, compact]);\n const title = scope === "library" ? "ALP library" : "ALP project";\n const subtitle = scope === "library" ? where?.library : where?.projectRoot ?? void 0;\n const groups = navGroups(scope, lists, !!where?.readOnly);\n const onSelect = (kind2, name) => actions.select(kind2 === "language" ? { kind: kind2 } : { kind: kind2, ...name ? { name } : {} });\n if (scope === "project" && where?.readOnly?.unlisted) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.screen, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: where.readOnly.unlisted }) });\n }\n if (scope === "project" && where && !where.projectRoot) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.screen, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "This workspace is not an ALP project. Run alp init to start one." }) });\n }\n if (selection.kind === "language") {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LanguageSettings, { theme, compact, language: language ?? null, error, actions, layout: { title, subtitle, groups, onSelect, initialCollapsed, embedded }, styles });\n }\n const kind = kindOf(selection.kind);\n if (selection.name || selection.creating) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(\n EntryEditor,\n {\n theme,\n compact,\n scope,\n kind: selection.kind,\n entry: selection.creating ? null : entry,\n lists,\n actions,\n layout: { title, subtitle, groups, onSelect, initialCollapsed, embedded }\n },\n `${selection.kind}/${selection.name ?? "new"}/${entry?.revision ?? "new"}/${(entry?.librarySkills ?? []).join(",")}`\n );\n }\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(KindOverview, { theme, compact, scope, kind: kind.kind, rows: lists[kind.kind], error, where, actions, layout: { title, subtitle, groups, onSelect, initialCollapsed, embedded }, styles });\n}\nvar OTHER = "other";\nfunction LanguageSettings({ theme, compact, language, error, actions, layout, styles }) {\n const named = language && LANGUAGES.some((option) => option.value === language.applies);\n const [choice, setChoice] = (0, import_react4.useState)(null);\n const [typed, setTyped] = (0, import_react4.useState)("");\n const shown = choice ?? (language ? named ? language.applies : OTHER : "");\n const typedValid = typed.trim().length > 0 && typed.trim().length <= 40;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(\n SideNavLayout,\n {\n theme,\n compact,\n title: layout.title,\n subtitle: layout.subtitle,\n groups: layout.groups,\n active: { item: "language" },\n onSelect: layout.onSelect,\n initialCollapsed: layout.initialCollapsed,\n embedded: layout.embedded,\n breadcrumb: ["Library", "Language"],\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "The language you read. Main writes its replies, questions, approval requests and task titles in it, other agents put their questions to you in it, and ALP asks for approvals and writes its notices in it. Agents may talk among themselves in any language." }),\n error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.danger, children: error }) : null,\n !language && !error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "Loading\\u2026" }) : null,\n language?.readOnly ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Language", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.name, children: [\n language.applies,\n language.language ? "" : " (default)"\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: language.readOnly })\n ] }) : !language ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Language", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(\n import_ui2.SettingsSelect,\n {\n label: "Language",\n hint: language.language ? `Set in your settings.json` : `Not set: ${language.default} applies`,\n value: shown,\n options: [...LANGUAGES, { label: named || !language.language ? "Other\\u2026" : `${language.applies} (other)`, value: OTHER }],\n onValueChange: (value) => __async(null, null, function* () {\n setChoice(value);\n if (value !== OTHER && (yield actions.setLanguage(value))) setChoice(null);\n })\n }\n ),\n shown === OTHER ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Other language", hint: "Its name in English, such as Thai or Indonesian", initialValue: named ? "" : language.language ?? "", placeholder: "Thai", onChangeText: setTyped }) : null,\n shown === OTHER ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsAction, { label: "Use this language", actionLabel: "Save", disabled: !typedValid, onPress: () => __async(null, null, function* () {\n if (typedValid && (yield actions.setLanguage(typed.trim()))) setChoice(null);\n }) }) : null,\n language.language ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsAction, { label: `Use the default (${language.default})`, hint: "Removes the setting", actionLabel: "Reset", onPress: () => __async(null, null, function* () {\n if (yield actions.setLanguage(null)) setChoice(null);\n }) }) : null\n ] })\n ]\n }\n );\n}\nvar SOURCES = [{ key: "all", label: "All" }, { key: "builtin", label: "Built-in" }, { key: "library", label: "Library" }, { key: "project", label: "Project" }];\nfunction KindOverview({ theme, compact, scope, kind, rows, error, where, actions, layout, styles }) {\n const { title, one } = kindOf(kind);\n const [filter, setFilter] = (0, import_react4.useState)("all");\n const [copying, setCopying] = (0, import_react4.useState)(null);\n const [copyName, setCopyName] = (0, import_react4.useState)("");\n const tabs = SOURCES.map((source) => ({ ...source, count: (rows ?? []).filter((row) => source.key === "all" || row.source === source.key).length })).filter((tab) => tab.key === "all" || tab.count);\n const shown = (rows ?? []).filter((row) => filter === "all" || row.source === filter);\n const readOnly = where?.readOnly;\n const intro = readOnly ? `The ${title.toLowerCase()} ${scope === "project" ? "this project uses on the ALP host" : "of the ALP host"}, by name.` : kind === "providers" ? "Agents that speak the Agent Client Protocol. They live in your library only." : scope === "library" ? "Every project uses your library. Built-ins follow ALP updates; saving one makes your own copy of that name." : "What this project overrides. Override an entry to change it here only; Use library drops the project\'s copy.";\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(\n SideNavLayout,\n {\n theme,\n compact,\n title: layout.title,\n subtitle: layout.subtitle,\n groups: layout.groups,\n active: { item: kind },\n onSelect: layout.onSelect,\n initialCollapsed: layout.initialCollapsed,\n embedded: layout.embedded,\n breadcrumb: layout.embedded ? [] : [scope === "library" ? "Library" : "Project", title],\n tabs,\n tab: filter,\n onTab: setFilter,\n actions: readOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, kind: "primary", icon: "Plus", label: `New ${one}`, onPress: () => actions.select({ kind, creating: true }) }),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: intro }),\n readOnly ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: readOnly.reason }) : null,\n error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.danger, children: error }) : null,\n !rows && !error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "Loading\\u2026" }) : null,\n readOnly?.unlisted ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.empty, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: readOnly.unlisted }) }) : rows && !shown.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.empty, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.muted, children: [\n "No ",\n title.toLowerCase(),\n " ",\n filter === "all" ? "yet" : `from the ${sourceLabel(filter)}`,\n "."\n ] }) }) : null,\n shown.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.table, children: shown.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: [styles.tableRow, index ? styles.tableRowRule : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Pressable, { accessibilityRole: readOnly ? void 0 : "button", accessibilityLabel: `${readOnly ? "" : "Open "}${one} ${row.name}`, disabled: !!readOnly, onPress: () => actions.select({ kind, name: row.name }), style: styles.rowMain, children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: styles.rowTitle, children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.name, children: row.name }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: sourceLabel(row.source), tone: sourceTone(row.source) }),\n row.overrides ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: `overrides ${sourceLabel(row.overrides)}` }) : null\n ] }),\n row.description ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, numberOfLines: 2, children: row.description }) : null,\n row.usedBy?.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.small, numberOfLines: 1, children: [\n "Used by ",\n row.usedBy.join(", ")\n ] }) : null\n ] }),\n readOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: [styles.rowActions, compact ? styles.rowActionsCompact : null], children: [\n scope === "project" && row.source === "project" && row.overrides ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, label: "Use library", onPress: () => actions.useLibrary(kind, row.name) }) : null,\n scope === "project" && row.source !== "project" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, label: "Override in this project", onPress: () => actions.override(kind, row.name) }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, icon: "Copy", label: "Duplicate", accessibilityLabel: `Duplicate ${one} ${row.name}`, onPress: () => {\n setCopying(row.name);\n setCopyName(`${row.name}-copy`);\n } })\n ] }),\n copying === row.name ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: styles.copyRow, children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.TextInput, { style: styles.input, value: copyName, onChangeText: setCopyName, accessibilityLabel: "Name of the copy", placeholder: "Name of the copy", placeholderTextColor: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, kind: "primary", label: "Copy", onPress: () => __async(null, null, function* () {\n if (NAME.test(copyName) && (yield actions.duplicate(kind, row.name, copyName))) setCopying(null);\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, label: "Cancel", onPress: () => setCopying(null) })\n ] }) : null\n ] }, row.name)) }) : null\n ]\n }\n );\n}\nfunction blank(kind, name = "new") {\n if (kind === "agents") return { instructions: `# ${name}\n\nDescribe what this agent does, and how.\n`, config: {} };\n if (kind === "skills") return { body: `---\nname: ${name}\ndescription: When to use this skill.\n---\n\n# ${name}\n\nSteps and checks.\n` };\n if (kind === "mcp") return { server: { command: "" } };\n if (kind === "hooks") return { hook: { event: "handoff", command: "", blocking: false } };\n if (kind === "providers") return { provider: { kind: "acp", label: name, command: "" } };\n return { team: { label: name, main: "main", members: { main: {} }, delegation: {}, supervisor: false }, houseRules: "" };\n}\nfunction entryTabs(kind, saved) {\n const tabs = {\n agents: [["general", "General"], ["instructions", "Instructions"], ["capabilities", "Skills, MCP & hooks"]],\n teams: [["models", "Models & effort"], ["general", "General"], ["members", "Members"], ["delegation", "Delegation"], ["supervisor", "Supervisor"], ["rules", "House rules"]],\n skills: [["body", "SKILL.md"]],\n mcp: [["server", "Server"], ["test", "Test"]],\n hooks: [["hook", "Hook"], ["test", "Test"]],\n providers: [["agent", "ACP agent"], ["test", "Test"]]\n };\n return tabs[kind].filter(([key]) => key !== "test" || saved).map(([key, label]) => ({ key, label }));\n}\nfunction EntryEditor({ theme, compact, scope, kind, entry, lists, actions, layout, initialTab }) {\n const styles = (0, import_react4.useMemo)(() => makeStyles2(theme, compact), [theme, compact]);\n const { one, title } = kindOf(kind);\n const tabs = entryTabs(kind, !!entry);\n const [tab, setTab] = (0, import_react4.useState)(initialTab && tabs.some((candidate) => candidate.key === initialTab) ? initialTab : tabs[0].key);\n const [name, setName] = (0, import_react4.useState)(entry?.name ?? "");\n const original = (0, import_react4.useMemo)(() => clone2(entry?.content ?? blank(kind)), [entry, kind]);\n const [content, setContent] = (0, import_react4.useState)(() => clone2(original));\n const [result, setResult] = (0, import_react4.useState)(null);\n const own = entry?.source === scope;\n const update = (change) => setContent((current) => {\n const draft = clone2(current);\n change(draft);\n return draft;\n });\n const valid = NAME.test(name);\n const changed = !entry || JSON.stringify(content) !== JSON.stringify(original);\n const givenOriginal = (0, import_react4.useMemo)(() => entry?.librarySkills ?? [], [entry]);\n const [given, setGiven] = (0, import_react4.useState)(givenOriginal);\n const givesSkills = kind === "agents" && scope === "library";\n const givenChanged = givesSkills && [...given].sort().join() !== [...givenOriginal].sort().join();\n const dirty = changed || givenChanged;\n const onSave = () => __async(null, null, function* () {\n if (!valid) return;\n if (changed && !(yield actions.save(kind, name, content, own ? entry.revision : null, !entry))) return;\n if (givenChanged) yield actions.giveSkills(name, given);\n });\n const note = entry ? entry.source === "builtin" ? `Built into ALP. Saving makes ${scope === "library" ? "your library\'s" : "this project\'s"} own ${entry.name}, which overrides it.` : own ? `In ${scope === "library" ? "your library" : "this project"}${entry.overrides ? `; overrides the ${sourceLabel(entry.overrides)} one` : ""}.` : `From the ${sourceLabel(entry.source)}. Saving makes this project\'s own copy.` : null;\n const form = { content, update, lists, styles, theme };\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(\n SideNavLayout,\n {\n theme,\n compact,\n title: layout.title,\n subtitle: layout.subtitle,\n groups: layout.groups,\n active: { item: kind, ...entry ? { child: entry.name } : {} },\n onSelect: layout.onSelect,\n initialCollapsed: layout.initialCollapsed,\n embedded: layout.embedded,\n breadcrumb: [title, entry ? entry.name : `New ${one}`],\n badges: entry ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: sourceLabel(entry.source), tone: sourceTone(entry.source) }),\n entry.overrides ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: `overrides ${sourceLabel(entry.overrides)}` }) : null\n ] }) : null,\n actions: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, icon: "ArrowLeft", label: `All ${title.toLowerCase()}`, onPress: () => actions.select({ kind }) }),\n tabs,\n tab,\n onTab: setTab,\n footer: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, kind: "primary", label: entry && entry.source === "builtin" && (changed || !givenChanged) ? "Save as my own" : "Save", disabled: !valid || !dirty, onPress: () => {\n void onSave();\n } }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.small, children: !valid ? "Name the entry first" : dirty ? "Unsaved changes" : own ? "Saved" : "No changes" }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: { flex: 1 } }),\n entry && own ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, kind: "danger", label: entry.overrides ? `Remove (the ${sourceLabel(entry.overrides)} one applies again)` : "Remove", onPress: () => actions.remove(kind, entry.name, entry.revision) }) : null\n ] }),\n children: [\n note || entry?.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: styles.banner, children: [\n note ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.bannerText, children: note }) : null,\n entry?.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.small, children: [\n "Used by ",\n entry.usedBy.join(", "),\n "."\n ] }) : null\n ] }) : null,\n !entry && tab === tabs[0].key ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSection, { title: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Name", hint: "Letters, digits, \'.\', \'_\' or \'-\'", error: name && !valid ? "Not a valid name" : null, initialValue: name, onChangeText: setName }) }) : null,\n kind === "agents" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AgentForm, { ...form, tab, given: entry?.librarySkills ?? [], ...givesSkills ? { draftGiven: given, setGiven } : {} }) : null,\n kind === "teams" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TeamForm, { ...form, tab }) : null,\n kind === "skills" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Multiline, { value: content.body ?? "", onChange: (text) => update((draft) => {\n draft.body = text;\n }), styles, theme, label: "SKILL.md", tall: true }) : null,\n kind === "mcp" && tab === "server" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(McpForm, { content, update }) : null,\n kind === "hooks" && tab === "hook" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HookForm, { content, update, lists }) : null,\n kind === "providers" && tab === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ProviderForm, { content, update }) : null,\n tab === "test" && entry ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Test", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsAction, { label: kind === "mcp" ? "Start the server and list its tools" : kind === "providers" ? "Start the agent and ask what it supports" : "Run once with a sample event", hint: "The test runs what is saved.", actionLabel: "Test", onPress: () => __async(null, null, function* () {\n return setResult(yield actions.test(kind, entry.name));\n }) }),\n result ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TestResult, { kind, result, styles }) : null\n ] }) : null\n ]\n }\n );\n}\nvar names = (lists, kind) => (lists[kind] ?? []).map((row) => row.name);\nvar toggle = (list, name, on) => {\n const set = new Set(list ?? []);\n if (on) set.add(name);\n else set.delete(name);\n return [...set];\n};\nvar setOrDelete = (target, key, value) => {\n if (value === "" || value === void 0 || Array.isArray(value) && !value.length) delete target[key];\n else target[key] = value;\n};\nvar CONTEXT_SIZES = [2e5, 4e5, 6e5, 1e6];\nvar contextOptions = (current) => [\n { label: "Auto (the model\'s)", value: "" },\n ...[.../* @__PURE__ */ new Set([...CONTEXT_SIZES, ...typeof current === "number" ? [current] : []])].sort((a, b) => a - b).map((tokens) => ({ label: tokens >= 1e6 ? `${tokens / 1e6}M tokens` : `${Math.round(tokens / 1e3)}k tokens`, value: String(tokens) }))\n];\nfunction AgentForm({ content, update, lists, styles, theme, tab, given = [], draftGiven, setGiven }) {\n const config = content.config ?? {};\n const field = (key) => (text) => update((draft) => {\n draft.config ?? (draft.config = {});\n setOrDelete(draft.config, key, text.trim());\n });\n const show = (key) => !tab || tab === key;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n show("general") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Agent", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Description", initialValue: config.description ?? "", onChangeText: field("description") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Provider", hint: "The team or project settings may choose another", value: config.provider ?? "", options: [{ label: "Default", value: "" }, { label: "Codex", value: "codex" }, { label: "Claude Code", value: "claude" }, ...names(lists, "providers").map((provider) => ({ label: `${provider} (ACP)`, value: provider }))], onValueChange: field("provider") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Model", hint: "Such as claude:claude-sonnet-5-5, codex:gpt-6-sol or acp:gemini", initialValue: config.model ?? "", onChangeText: field("model") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Thinking", hint: "Effort, such as low, medium or high", initialValue: config.thinking ?? "", onChangeText: field("thinking") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(\n import_ui2.SettingsSelect,\n {\n label: "Context",\n hint: "How much context it works with before the runtime compacts it",\n value: typeof config.context === "number" ? String(config.context) : "",\n options: contextOptions(config.context),\n onValueChange: (value) => update((draft) => {\n draft.config ?? (draft.config = {});\n setOrDelete(draft.config, "context", value ? Number(value) : "");\n })\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Default mode", value: config.mode ?? "", options: MODES.map((mode) => ({ label: mode || "As its requester chooses", value: mode })), onValueChange: field("mode") })\n ] }) : null,\n show("instructions") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Multiline, { value: content.instructions ?? "", onChange: (text) => update((draft) => {\n draft.instructions = text;\n }), styles, theme, label: "AGENT.md", tall: true }) : null,\n show("capabilities") ? ["skills", "mcp", "hooks"].map((kind) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: kindOf(kind).title, children: [\n !names(lists, kind).length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsRow, { label: `No ${kindOf(kind).title.toLowerCase()} to choose from yet` }) : null,\n names(lists, kind).map((name) => {\n const own = (config[kind] ?? []).includes(name);\n const configToggle = (on) => update((draft) => {\n draft.config ?? (draft.config = {});\n setOrDelete(draft.config, kind, toggle(draft.config[kind], name, on));\n });\n if (kind !== "skills") return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: name, value: own, onValueChange: configToggle }, name);\n if (setGiven) {\n const library = (draftGiven ?? given).includes(name);\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(\n import_ui2.SettingsSwitch,\n {\n label: name,\n hint: given.includes(name) ? "Default for this agent" : void 0,\n value: library || own,\n onValueChange: (on) => {\n setGiven(toggle(draftGiven ?? given, name, on));\n if (!on && own) configToggle(false);\n }\n },\n name\n );\n }\n if (given.includes(name)) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: name, hint: "Given by your library; change it in Settings \\u2192 ALP", value: true, disabled: true, onValueChange: () => {\n } }, name);\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: name, value: own, onValueChange: configToggle }, name);\n })\n ] }, kind)) : null\n ] });\n}\nfunction withMember(team, agent, on) {\n const next = clone2(team);\n next.members ?? (next.members = {});\n next.delegation ?? (next.delegation = {});\n if (on) {\n next.members[agent] = { role: "peer" };\n return next;\n }\n delete next.members[agent];\n delete next.delegation[agent];\n for (const owner of Object.keys(next.delegation)) {\n next.delegation[owner] = next.delegation[owner].filter((target) => target !== agent);\n if (!next.delegation[owner].length) delete next.delegation[owner];\n }\n return next;\n}\nfunction withDelegation(team, owner, target, on) {\n const next = clone2(team);\n next.delegation ?? (next.delegation = {});\n const targets = toggle(next.delegation[owner], target, on);\n if (targets.length) next.delegation[owner] = targets;\n else delete next.delegation[owner];\n return next;\n}\nvar EFFORTS = ["", "none", "low", "medium", "high", "xhigh", "max"];\nvar effortOptions = EFFORTS.map((value) => ({ label: value || "Inherit", value }));\nfunction TeamModels({ content, update, theme }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TeamModelSettings, { team: content.team ?? {}, theme, onChange: (next) => update((draft) => {\n draft.team = next;\n }) });\n}\nfunction TeamForm({ content, update, lists, styles, theme, tab }) {\n const show = (key) => !tab || tab === key;\n const team = content.team ?? {};\n const agents = names(lists, "agents");\n const members = Object.keys(team.members ?? {});\n const others = members.filter((member) => member !== team.main);\n const cycle = delegationCycle(team.delegation ?? {});\n const text = (key) => (value) => update((draft) => {\n setOrDelete(draft.team, key, value.trim());\n });\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n show("models") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TeamModels, { content, update, lists, styles, theme }) : null,\n show("general") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Team", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Label", hint: "Shown in the model picker", initialValue: team.label ?? "", onChangeText: text("label") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Description", initialValue: team.description ?? "", onChangeText: text("description") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Most peers at once", initialValue: team.maxPeers === void 0 ? "" : String(team.maxPeers), onChangeText: (value) => update((draft) => {\n setOrDelete(draft.team, "maxPeers", value.trim() ? Number(value) : "");\n }) })\n ] }) : null,\n show("members") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: [team.main, ...agents.filter((agent) => agent !== team.main && agent !== team.supervisor?.agent)].filter(Boolean).map((agent) => {\n const member = team.members?.[agent];\n const main = agent === team.main;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: main ? `${agent} \\xB7 main` : agent, info: main ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.small, children: "The agent you talk with." }) : void 0, children: [\n !main ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: "In this team", value: !!member, onValueChange: (on) => update((draft) => {\n draft.team = withMember(draft.team, agent, on);\n }) }) : null,\n member && !main ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Role", value: member.role ?? "peer", options: ROLES.map((role) => ({ label: role, value: role })), onValueChange: (role) => update((draft) => {\n draft.team.members[agent].role = role;\n }) }) : null\n ] }, agent);\n }) }) : null,\n show("delegation") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n cycle ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.danger, children: [\n "Cycle at ",\n cycle,\n ": ALP refuses it"\n ] }) : null,\n members.map((owner) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: `${owner} may delegate to`, info: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.small, children: (team.delegation?.[owner] ?? []).join(", ") || "no one" }), children: [\n others.filter((target) => target !== owner).map((target) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: target, value: (team.delegation?.[owner] ?? []).includes(target), onValueChange: (on) => update((draft) => {\n draft.team = withDelegation(draft.team, owner, target, on);\n }) }, `${owner}-${target}`)),\n !others.filter((target) => target !== owner).length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsRow, { label: "No other members" }) : null\n ] }, owner))\n ] }) : null,\n show("supervisor") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Supervisor", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: "Review main\'s process after each turn", value: !!team.supervisor, onValueChange: (on) => update((draft) => {\n draft.team.supervisor = on ? { agent: "supervisor" } : false;\n }) }),\n team.supervisor ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Supervisor agent", value: team.supervisor.agent, options: agents.filter((agent) => !members.includes(agent)).map((agent) => ({ label: agent, value: agent })), onValueChange: (agent) => update((draft) => {\n draft.team.supervisor.agent = agent;\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsRow, { label: "Model & effort", hint: "Configure in Models & effort" })\n ] }) : null\n ] }) : null,\n show("rules") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Multiline, { value: content.houseRules ?? "", onChange: (value) => update((draft) => {\n draft.houseRules = value;\n }), styles, theme, label: "House rules", placeholder: "The team\'s rules and process, which every member reads (HOUSE_RULES.md)", tall: true }) : null\n ] });\n}\nfunction delegationCycle(graph) {\n const visiting = /* @__PURE__ */ new Set();\n const done = /* @__PURE__ */ new Set();\n const visit = (owner) => {\n if (visiting.has(owner)) return owner;\n if (done.has(owner)) return null;\n visiting.add(owner);\n for (const target of graph[owner] ?? []) {\n const found = visit(target);\n if (found) return found;\n }\n visiting.delete(owner);\n done.add(owner);\n return null;\n };\n for (const owner of Object.keys(graph)) {\n const found = visit(owner);\n if (found) return found;\n }\n return null;\n}\nvar lines = (text) => text.split("\\n").map((line) => line.trim()).filter(Boolean);\nvar pairs = (text) => Object.fromEntries(lines(text).filter((line) => line.includes("=")).map((line) => [line.slice(0, line.indexOf("=")).trim(), line.slice(line.indexOf("=") + 1).trim()]));\nvar unpairs = (map) => Object.entries(map ?? {}).map(([key, value]) => `${key}=${value}`).join("\\n");\nfunction McpForm({ content, update }) {\n const server = content.server ?? {};\n const http = server.url !== void 0;\n const set = (key, value) => update((draft) => {\n setOrDelete(draft.server, key, value);\n });\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Server", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Transport", value: http ? "http" : "stdio", options: [{ label: "Command (stdio)", value: "stdio" }, { label: "URL (HTTP)", value: "http" }], onValueChange: (kind) => update((draft) => {\n draft.server = kind === "http" ? { url: "" } : { command: "" };\n }) }),\n http ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "URL", initialValue: server.url ?? "", onChangeText: (value) => update((draft) => {\n draft.server.url = value.trim();\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Headers", hint: "Name=value, separated by \';\'", initialValue: unpairs(server.headers).replaceAll("\\n", "; "), onChangeText: (value) => set("headers", Object.keys(pairs(value.replaceAll(";", "\\n"))).length ? pairs(value.replaceAll(";", "\\n")) : void 0) })\n ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Command", initialValue: server.command ?? "", onChangeText: (value) => update((draft) => {\n draft.server.command = value.trim();\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Arguments", hint: "Separated by spaces", initialValue: (server.args ?? []).join(" "), onChangeText: (value) => set("args", value.split(/\\s+/).filter(Boolean)) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Environment", hint: "NAME=value, separated by \';\'", initialValue: unpairs(server.env).replaceAll("\\n", "; "), onChangeText: (value) => set("env", Object.keys(pairs(value.replaceAll(";", "\\n"))).length ? pairs(value.replaceAll(";", "\\n")) : void 0) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Working directory", hint: "Relative to the mcp directory", initialValue: server.cwd ?? "", onChangeText: (value) => set("cwd", value.trim()) })\n ] })\n ] });\n}\nfunction ProviderForm({ content, update }) {\n const provider = content.provider ?? {};\n const set = (key, value) => update((draft) => {\n draft.provider ?? (draft.provider = { kind: "acp" });\n setOrDelete(draft.provider, key, value);\n });\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "ACP agent", info: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { children: "Any agent that speaks the Agent Client Protocol on stdio. ALP answers its permission requests by the session\'s mode; it cannot steer it mid-turn or sandbox its commands." }), children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Label", initialValue: provider.label ?? "", onChangeText: (value) => set("label", value.trim()) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Description", initialValue: provider.description ?? "", onChangeText: (value) => set("description", value.trim()) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Command", hint: "Such as gemini, or an absolute path", initialValue: provider.command ?? "", onChangeText: (value) => update((draft) => {\n draft.provider.command = value.trim();\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Arguments", hint: "Separated by spaces, such as --experimental-acp", initialValue: (provider.args ?? []).join(" "), onChangeText: (value) => set("args", value.split(/\\s+/).filter(Boolean)) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Environment", hint: "NAME=value, separated by \';\'", initialValue: unpairs(provider.env).replaceAll("\\n", "; "), onChangeText: (value) => set("env", Object.keys(pairs(value.replaceAll(";", "\\n"))).length ? pairs(value.replaceAll(";", "\\n")) : void 0) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Models", hint: "Ids the agent offers, separated by \',\'; empty lets any through", initialValue: (provider.models ?? []).map((model) => model.id).join(", "), onChangeText: (value) => set("models", value.split(",").map((id) => id.trim()).filter(Boolean).map((id) => (provider.models ?? []).find((model) => model.id === id) ?? { id })) })\n ] });\n}\nfunction HookForm({ content, update, lists }) {\n const hook = content.hook ?? {};\n const set = (key, value) => update((draft) => {\n setOrDelete(draft.hook, key, value);\n });\n const blocking = BLOCKING_EVENTS.includes(hook.event);\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Hook", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Event", value: hook.event ?? "handoff", options: HOOK_EVENTS.map((event) => ({ label: event, value: event })), onValueChange: (event) => update((draft) => {\n draft.hook.event = event;\n if (!BLOCKING_EVENTS.includes(event)) delete draft.hook.blocking;\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Command", hint: "Runs in the session\'s directory; the event arrives as JSON on stdin", initialValue: hook.command ?? "", onChangeText: (value) => update((draft) => {\n draft.hook.command = value;\n }) }),\n blocking ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: "Block the action when it fails", hint: "Its stderr becomes the reason the agent reads", value: !!hook.blocking, onValueChange: (on) => set("blocking", on || void 0) }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Timeout (seconds)", initialValue: hook.timeoutSec === void 0 ? "" : String(hook.timeoutSec), onChangeText: (value) => set("timeoutSec", value.trim() ? Number(value) : "") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Only for agent", value: hook.match?.agent ?? "", options: [{ label: "Every agent", value: "" }, ...names(lists, "agents").map((agent) => ({ label: agent, value: agent }))], onValueChange: (agent) => update((draft) => {\n var _a;\n (_a = draft.hook).match ?? (_a.match = {});\n setOrDelete(draft.hook.match, "agent", agent);\n if (!Object.keys(draft.hook.match).length) delete draft.hook.match;\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Only for tasks labeled", initialValue: hook.match?.label ?? "", onChangeText: (label) => update((draft) => {\n var _a;\n (_a = draft.hook).match ?? (_a.match = {});\n setOrDelete(draft.hook.match, "label", label.trim());\n if (!Object.keys(draft.hook.match).length) delete draft.hook.match;\n }) })\n ] });\n}\nfunction TestResult({ kind, result, styles }) {\n if (kind === "providers") {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.success, children: [\n result.agent?.title ?? result.agent?.name ?? "The agent",\n result.agent?.version ? ` ${result.agent.version}` : "",\n " speaks ACP ",\n result.protocolVersion\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.muted, children: [\n result.loadSession ? "Resumes sessions" : "Cannot resume sessions",\n result.mcpHttp ? "; takes HTTP MCP servers" : "; takes stdio MCP servers only",\n result.authMethods?.length ? `; signs in with ${result.authMethods.join(", ")}` : ""\n ] })\n ] });\n }\n if (kind === "mcp") {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.success, children: [\n result.server?.name ?? "The server",\n result.server?.version ? ` ${result.server.version}` : "",\n " offers ",\n result.tools?.length ?? 0,\n " tools"\n ] }),\n (result.tools ?? []).map((tool) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.muted, children: [\n tool.name,\n tool.description ? ` \\u2014 ${tool.description.split("\\n")[0]}` : ""\n ] }, tool.name))\n ] });\n }\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: result.ok ? styles.success : styles.danger, children: [\n result.timedOut ? "Timed out" : `Exit ${result.exitCode ?? result.signal}`,\n " in ",\n result.durationMs,\n " ms",\n result.wouldBlock ? "; as a blocking hook it would refuse the action" : ""\n ] }),\n result.stdout ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.code, children: result.stdout }) : null,\n result.stderr ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.code, children: result.stderr }) : null\n ] });\n}\nfunction Multiline({ value, onChange, styles, theme, label, placeholder, tall }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.TextInput, { style: [styles.multiline, tall ? styles.tall : null], value, onChangeText: onChange, multiline: true, accessibilityLabel: label, placeholder: placeholder ?? label, placeholderTextColor: theme.colors.foregroundMuted });\n}\nfunction makeStyles2(theme, compact) {\n const { colors } = theme;\n return {\n screen: { flex: 1, backgroundColor: colors.surface0, padding: compact ? 12 : 20 },\n muted: { color: colors.foregroundMuted, fontSize: 13, lineHeight: 19 },\n small: { color: colors.foregroundMuted, fontSize: 12 },\n danger: { color: colors.statusDanger, fontSize: 13 },\n success: { color: colors.statusSuccess, fontSize: 13 },\n name: { color: colors.foreground, fontSize: 14, fontWeight: "600" },\n empty: { borderWidth: 1, borderStyle: "dashed", borderColor: colors.border, borderRadius: 10, padding: 24, alignItems: "center" },\n table: { borderWidth: 1, borderColor: colors.border, borderRadius: 10, backgroundColor: colors.surface1, overflow: "hidden" },\n tableRow: { flexDirection: compact ? "column" : "row", flexWrap: "wrap", alignItems: compact ? "stretch" : "center", gap: 10, paddingHorizontal: 14, paddingVertical: 12 },\n tableRowRule: { borderTopWidth: 1, borderTopColor: colors.border },\n rowMain: { flex: 1, minWidth: 0, gap: 3 },\n rowTitle: { flexDirection: "row", alignItems: "center", gap: 8, flexWrap: "wrap" },\n rowActions: { flexDirection: "row", gap: 8, alignItems: "center" },\n rowActionsCompact: { flexWrap: "wrap" },\n copyRow: { flexBasis: "100%", flexDirection: "row", gap: 8, alignItems: "center" },\n input: { flex: 1, color: colors.foreground, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 10, paddingVertical: 7, backgroundColor: colors.surface0 },\n banner: { borderRadius: 10, backgroundColor: colors.surface1, borderWidth: 1, borderColor: colors.border, paddingHorizontal: 14, paddingVertical: 10, gap: 4 },\n bannerText: { color: colors.foreground, fontSize: 13 },\n multiline: { minHeight: 160, color: colors.foreground, borderWidth: 1, borderColor: colors.border, borderRadius: 10, padding: 12, fontFamily: "monospace", fontSize: 13, lineHeight: 19, backgroundColor: colors.surface1, textAlignVertical: "top" },\n tall: { minHeight: 420 },\n code: { color: colors.foreground, fontFamily: "monospace", fontSize: 12 }\n };\n}\n\n// integrations/paseo/client/usage.tsx\nvar import_client4 = require("@getpaseo/plugin/client");\nvar import_react_native8 = require("@getpaseo/plugin/client/react-native");\nvar import_react5 = require("react");\nvar import_react_native9 = require("react-native");\n\n// integrations/paseo/shared/usage.ts\nvar import_plugin3 = require("@getpaseo/plugin");\nvar import_zod3 = require("zod");\nvar Pause = import_zod3.z.object({ reason: import_zod3.z.string(), since: import_zod3.z.string(), resetsAt: import_zod3.z.string().optional() });\nvar usageGet = (0, import_plugin3.defineRpc)({\n name: "alp.usage.get",\n input: import_zod3.z.object({ refresh: import_zod3.z.boolean().optional() }),\n output: import_zod3.z.object({\n providers: import_zod3.z.array(import_zod3.z.object({\n runtime: import_zod3.z.enum(["codex", "claude"]),\n available: import_zod3.z.boolean(),\n checkedAt: import_zod3.z.string(),\n plan: import_zod3.z.string().nullable(),\n limited: import_zod3.z.boolean(),\n windows: import_zod3.z.array(import_zod3.z.object({ name: import_zod3.z.string(), usedPercent: import_zod3.z.number().nullable(), resetsAt: import_zod3.z.string().nullable() })),\n pause: Pause.nullable(),\n parked: import_zod3.z.number()\n }))\n })\n});\n\n// integrations/paseo/client/usage.tsx\nvar import_jsx_runtime5 = require("react/jsx-runtime");\nfunction UsageScreen({ theme, layout }) {\n const read = (0, import_client4.useRpc)(usageGet);\n const [data, setData] = (0, import_react5.useState)(null);\n const [error, setError] = (0, import_react5.useState)(null);\n const [loading, setLoading] = (0, import_react5.useState)(true);\n const [tick, setTick] = (0, import_react5.useState)(0);\n const forceRefresh = (0, import_react5.useRef)(false);\n (0, import_react5.useEffect)(() => {\n let live = true;\n setLoading(true);\n const refresh = forceRefresh.current;\n forceRefresh.current = false;\n read({ refresh }).then((result) => {\n if (live) {\n setData(result);\n setError(null);\n }\n }).catch((cause) => {\n if (live) setError(cause instanceof Error ? cause.message : String(cause));\n }).finally(() => {\n if (live) setLoading(false);\n });\n return () => {\n live = false;\n };\n }, [read, tick]);\n (0, import_react5.useEffect)(() => {\n const timer = setInterval(() => setTick((value) => value + 1), 6e4);\n return () => clearInterval(timer);\n }, []);\n return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UsageView, { theme, compact: layout.compact, data, loading, error, onRefresh: () => {\n forceRefresh.current = true;\n setTick((value) => value + 1);\n } });\n}\nfunction dateLabel(value) {\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" }) : "Unknown";\n}\nfunction resetLabel(value, now) {\n if (!value) return "Reset time unavailable";\n const minutes = Math.ceil((Date.parse(value) - now) / 6e4);\n if (minutes <= 0) return "Reset time passed \\xB7 awaiting provider update";\n const duration = minutes >= 1440 ? `${Math.floor(minutes / 1440)}d ${Math.floor(minutes % 1440 / 60)}h` : minutes >= 60 ? `${Math.floor(minutes / 60)}h ${minutes % 60}m` : `${minutes}m`;\n return `Resets in ${duration} \\xB7 ${dateLabel(value)}`;\n}\nfunction UsageView({ theme, compact, data, loading, error, onRefresh, now = Date.now() }) {\n const { colors } = theme;\n const muted = { color: colors.foregroundMuted, fontSize: 13, lineHeight: 20 };\n const providers = data?.providers ?? [];\n const parked = providers.reduce((sum, provider) => sum + provider.parked, 0);\n return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native8.ScrollView, { contentContainerStyle: { padding: compact ? 16 : 28, gap: 24 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 8 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: 12 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { accessibilityRole: "header", style: { color: colors.foreground, fontSize: 28, fontWeight: "600", letterSpacing: -0.7 }, children: "Usage" }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { theme, label: loading ? "Refreshing\\u2026" : "Refresh", icon: "RefreshCw", disabled: loading, onPress: onRefresh, accessibilityLabel: "Refresh usage" })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "Your provider limits, reset windows and paused work in one place." })\n ] }),\n error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { accessibilityRole: "alert", style: { padding: 14, borderWidth: 1, borderColor: colors.statusDanger, borderRadius: 10, gap: 4 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color: colors.statusDanger, fontWeight: "600" }, children: "Could not refresh usage" }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: error }),\n data ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "Showing the last received data." }) : null\n ] }) : null,\n parked > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { padding: 14, backgroundColor: colors.surface1, borderLeftWidth: 3, borderLeftColor: colors.statusWarning, gap: 4 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.Text, { style: { color: colors.foreground, fontWeight: "600" }, children: [\n parked,\n " ",\n parked === 1 ? "assignment waiting" : "assignments waiting"\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "Parked work stays saved while its runtime is paused." })\n ] }) : null,\n !data && loading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { accessibilityLiveRegion: "polite", style: muted, children: "Checking Codex and Claude usage\\u2026" }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.View, { style: { flexDirection: compact ? "column" : "row", flexWrap: "wrap", gap: 16 }, children: providers.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProviderCard, { theme, provider, compact, now }, provider.runtime)) }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { borderTopWidth: 1, borderTopColor: colors.border, paddingTop: 16, gap: 4 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "Account limits reported by each provider, shared with usage outside ALP." }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { ...muted, fontSize: 12 }, children: "Updates every minute while this screen is open. Readings are cached for up to 30 seconds. This is not a billing or token-spend report." })\n ] })\n ] });\n}\nfunction ProviderCard({ theme, provider, compact, now }) {\n const { colors } = theme;\n const status = provider.pause ? "Paused" : !provider.available ? "Unavailable" : provider.limited ? "Limit reached" : "Available";\n const tone = provider.pause || provider.limited ? "warning" : provider.available ? "success" : "muted";\n const muted = { color: colors.foregroundMuted, fontSize: 12, lineHeight: 18 };\n return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { flexGrow: 1, flexBasis: compact ? "auto" : 320, width: compact ? "100%" : void 0, minWidth: 0, padding: 20, backgroundColor: colors.surface1, borderWidth: 1, borderColor: colors.border, borderRadius: 14, gap: 20 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", gap: 12 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 4 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { accessibilityRole: "header", style: { color: colors.foreground, fontSize: 20, fontWeight: "600" }, children: provider.runtime === "codex" ? "Codex" : "Claude" }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: provider.plan ? `${provider.plan} plan` : "Plan not reported" })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Pill, { theme, label: status, tone })\n ] }),\n provider.pause ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 5 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color: colors.statusWarning, fontSize: 13 }, children: provider.pause.reason }),\n provider.pause.resetsAt ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: resetLabel(provider.pause.resetsAt, now) }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.Text, { style: muted, children: [\n provider.parked,\n " ",\n provider.parked === 1 ? "assignment parked" : "assignments parked"\n ] })\n ] }) : null,\n !provider.available ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 8, paddingVertical: 16 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native8.Icon, { name: "CircleHelp", size: 22, color: colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color: colors.foreground, fontSize: 14, fontWeight: "500" }, children: "Usage is not available" }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "The provider did not return usage data. Check that its CLI is installed and signed in, then refresh." })\n ] }) : provider.windows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "The provider has not reported any usage windows." }) : provider.windows.map((window, index) => {\n const used = window.usedPercent;\n const color = used === null ? colors.foregroundMuted : used >= 95 ? colors.statusDanger : used >= 80 ? colors.statusWarning : colors.accent;\n return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 8 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "baseline", gap: 12 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color: colors.foreground, fontSize: 13, flex: 1, textTransform: "capitalize" }, children: window.name }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color, fontSize: 25, fontWeight: "600", fontVariant: ["tabular-nums"] }, children: used === null ? "\\u2014" : `${Math.round(used)}%` })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.View, { accessibilityRole: "progressbar", accessibilityLabel: `${window.name} used`, accessibilityValue: used === null ? { text: "Usage unknown" } : { min: 0, max: 100, now: used }, style: { height: 6, backgroundColor: colors.surface2, borderRadius: 3, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.View, { style: { height: 6, width: `${used ?? 0}%`, backgroundColor: color, borderRadius: 3 } }) }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: used === null ? "Usage percentage unavailable" : `${Math.round(100 - used)}% remaining` }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: resetLabel(window.resetsAt, now) })\n ] }, `${window.name}-${index}`);\n }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.Text, { style: { ...muted, borderTopWidth: 1, borderTopColor: colors.border, paddingTop: 12 }, children: [\n "Checked ",\n dateLabel(provider.checkedAt)\n ] })\n ] });\n}\n\n// integrations/paseo/index.client.tsx\nfunction contribute(client) {\n const removePanel = client.addWorkspacePanel({ id: "alp-tasks", title: "Tasks", icon: "ListTodo", context: "workspace", Component: TasksPanel });\n const removeScreen = client.addScreen({ id: TASKS_SCREEN, title: (params) => params.taskId ? `ALP task ${params.taskId}` : "ALP tasks", Component: TasksScreen });\n const removePills = addTaskPills(client);\n const removeCommand = client.addCommandCenterItem({\n id: "alp-open-tasks",\n title: "Open ALP tasks",\n icon: "ListTodo",\n keywords: ["tasks", "todo", "alp"],\n context: "workspace",\n onSelect({ openPanel }) {\n openPanel("alp-tasks");\n }\n });\n const removeScreenCommand = client.addCommandCenterItem({\n id: "alp-open-tasks-screen",\n title: "Open ALP tasks full screen",\n icon: "ListTodo",\n keywords: ["tasks", "todo", "alp", "phone"],\n context: "workspace",\n onSelect({ workspace, openScreen }) {\n openScreen(tasksScreen(workspace.id, workspace.directory || workspace.projectRootPath));\n }\n });\n const removeSlash = client.addSlashCommand({\n name: "alp-tasks",\n description: "Open the ALP tasks of this project",\n argumentHint: "[task id]",\n context: "agent",\n onSubmit({ workspace, args, openScreen }) {\n openScreen(tasksScreen(workspace.id, workspace.directory || workspace.projectRootPath, args.trim() || void 0));\n }\n });\n const removeSettings = client.addSettingsScreen({ id: "alp-settings", title: "ALP", icon: "Bot", Component: LibrarySettings });\n const removeHostSettings = [\n { id: "alp-templates", title: "Templates", icon: "Users", Component: TeamsSettings },\n { id: "alp-agents", title: "Agents", icon: "Bot", Component: AgentsSettings },\n { id: "alp-skills", title: "Skills", icon: "BookOpen", Component: SkillsSettings },\n { id: "alp-hooks", title: "Hooks", icon: "Webhook", Component: HooksSettings },\n { id: "alp-mcp", title: "MCP servers", icon: "Plug", Component: McpSettings }\n ].map((screen) => client.addSettingsScreen(screen));\n const removeUsage = client.addSettingsScreen({ id: "alp-usage", title: "Usage", icon: "ChartNoAxesCombined", Component: UsageScreen });\n const removeUsagePanel = client.addWorkspacePanel({ id: "alp-usage", title: "Usage", icon: "ChartNoAxesCombined", context: "workspace", Component: UsageScreen });\n const removeProject = client.addWorkspacePanel({ id: "alp-project", title: "ALP project", icon: "Bot", context: "workspace", Component: ProjectLibraryPanel });\n return () => {\n removePanel();\n removeScreen();\n removePills();\n removeCommand();\n removeScreenCommand();\n removeSlash();\n removeSettings();\n removeHostSettings.forEach((remove) => remove());\n removeProject();\n removeUsage();\n removeUsagePanel();\n };\n}\n\nreturn module.exports;})' };
|
|
35857
|
+
var plugin_client_default = { "id": "alp-provider", "requirements": { "paseo": ">=0.11.1 <0.13.0" }, "factory": '(function(require){const module={exports:{}};const exports=module.exports;var __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === "object" || typeof from === "function") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { value: from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);\nvar __async = (__this, __arguments, generator) => {\n return new Promise((resolve, reject) => {\n var fulfilled = (value) => {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n };\n var rejected = (value) => {\n try {\n step(generator.throw(value));\n } catch (e) {\n reject(e);\n }\n };\n var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);\n step((generator = generator.apply(__this, __arguments)).next());\n });\n};\n\n// integrations/paseo/index.client.tsx\nvar index_client_exports = {};\n__export(index_client_exports, {\n default: () => contribute\n});\nmodule.exports = __toCommonJS(index_client_exports);\n\n// integrations/paseo/client/tasks-panel.tsx\nvar import_client = require("@getpaseo/plugin/client");\nvar import_react_native = require("@getpaseo/plugin/client/react-native");\nvar import_react = require("react");\nvar import_react_native2 = require("react-native");\n\n// integrations/paseo/shared/tasks.ts\nvar import_plugin = require("@getpaseo/plugin");\nvar import_zod = require("zod");\nvar TaskRowSchema = import_zod.z.object({\n id: import_zod.z.string(),\n title: import_zod.z.string(),\n type: import_zod.z.string(),\n priority: import_zod.z.number(),\n status: import_zod.z.enum(["open", "in_progress", "review", "closed"]),\n parent: import_zod.z.string().optional(),\n assignee: import_zod.z.string().optional(),\n ready: import_zod.z.boolean(),\n /** Open tasks that must close first, including those of ancestors. */\n blockedBy: import_zod.z.array(import_zod.z.string()).optional(),\n /** Open gates, as labels. */\n waits: import_zod.z.array(import_zod.z.string()).optional(),\n /** Open human gates of this task: the user approves them here. */\n approvals: import_zod.z.array(import_zod.z.object({ gate: import_zod.z.string(), note: import_zod.z.string() })).optional(),\n handoff: import_zod.z.object({ outcome: import_zod.z.string(), summary: import_zod.z.string(), agent: import_zod.z.string().optional() }).optional(),\n closed: import_zod.z.object({ reason: import_zod.z.string(), summary: import_zod.z.string().optional(), at: import_zod.z.string() }).optional(),\n /** What the task is about, for its detail view; at most 4000 characters. */\n description: import_zod.z.string().optional(),\n labels: import_zod.z.array(import_zod.z.string()).optional(),\n paths: import_zod.z.array(import_zod.z.string()).optional(),\n /** An epic or parent task: how many of its children are closed. */\n progress: import_zod.z.object({ done: import_zod.z.number(), total: import_zod.z.number() }).optional(),\n createdAt: import_zod.z.string().optional(),\n updatedAt: import_zod.z.string()\n});\nvar Directory = import_zod.z.string().min(1);\nvar tasksList = (0, import_plugin.defineRpc)({\n name: "alp.tasks.list",\n input: import_zod.z.object({ directory: Directory }),\n output: import_zod.z.object({\n /** The ALP project containing the directory, or null when there is none. */\n projectRoot: import_zod.z.string().nullable(),\n tasks: import_zod.z.array(TaskRowSchema),\n unreadable: import_zod.z.array(import_zod.z.object({ file: import_zod.z.string(), error: import_zod.z.string() })),\n /** By provider session id: the tasks that session\'s tree worked on (ALPD \xA755). */\n sessions: import_zod.z.record(import_zod.z.string(), import_zod.z.array(import_zod.z.string())).optional()\n })\n});\nvar tasksAdd = (0, import_plugin.defineRpc)({\n name: "alp.tasks.add",\n input: import_zod.z.object({ directory: Directory, title: import_zod.z.string().trim().min(1).max(200), priority: import_zod.z.number().int().min(0).max(4).optional() }),\n output: import_zod.z.object({ id: import_zod.z.string() })\n});\nvar tasksChange = (0, import_plugin.defineRpc)({\n name: "alp.tasks.change",\n input: import_zod.z.object({\n directory: Directory,\n id: import_zod.z.string().min(1),\n action: import_zod.z.enum(["close", "reopen", "approve"]),\n /** For approve: the human gate. */\n gate: import_zod.z.string().optional(),\n note: import_zod.z.string().max(2e3).optional()\n }),\n /** landed: the first line of the report when the close landed an epic. */\n output: import_zod.z.object({ id: import_zod.z.string(), status: import_zod.z.string(), landed: import_zod.z.string().optional() })\n});\nvar rank = (a, b) => a.priority - b.priority || a.id.localeCompare(b.id);\nfunction boardSections(tasks, closedLimit = 20) {\n const open = tasks.filter((task) => task.status !== "closed");\n const sections = [\n { key: "approve", title: "Waiting for your approval", tasks: open.filter((task) => task.approvals?.length).sort(rank) },\n { key: "review", title: "In review", tasks: open.filter((task) => task.status === "review").sort(rank) },\n { key: "progress", title: "In progress", tasks: open.filter((task) => task.status === "in_progress").sort(rank) },\n { key: "ready", title: "Ready", tasks: open.filter((task) => task.ready).sort(rank) },\n { key: "waiting", title: "Blocked or waiting", tasks: open.filter((task) => task.status === "open" && !task.ready && !task.approvals?.length && task.type !== "epic").sort(rank) },\n { key: "epics", title: "Epics", tasks: open.filter((task) => task.type === "epic" && !task.approvals?.length).sort(rank) },\n { key: "closed", title: "Closed", tasks: tasks.filter((task) => task.status === "closed").sort((a, b) => (b.closed?.at ?? b.updatedAt).localeCompare(a.closed?.at ?? a.updatedAt)).slice(0, closedLimit) }\n ];\n return sections.filter((section) => section.tasks.length);\n}\n\n// integrations/paseo/client/tasks-panel.tsx\nvar import_jsx_runtime = require("react/jsx-runtime");\nvar POLL_MS = 5e3;\nvar SPLIT_FROM = 820;\nfunction TasksPanel({ theme, layout, workspaceId }) {\n const directory = (0, import_client.useWorkspace)(workspaceId, (workspace) => workspace.directory || workspace.projectRootPath);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskBoard, { theme, compact: layout.compact, directory, ...useTasks(directory) });\n}\nfunction TasksScreen({ theme, layout, params }) {\n const directory = params.directory || null;\n const tasks = useTasks(directory);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n TaskBoard,\n {\n theme,\n compact: layout.compact,\n directory,\n ...tasks,\n initial: params.taskId ? { selected: params.taskId } : void 0\n },\n params.taskId ?? ""\n );\n}\nfunction useTasks(directory) {\n const list = (0, import_client.useRpc)(tasksList);\n const add = (0, import_client.useRpc)(tasksAdd);\n const change = (0, import_client.useRpc)(tasksChange);\n const toast = (0, import_react_native.useToast)();\n const [data, setData] = (0, import_react.useState)(null);\n const [error, setError] = (0, import_react.useState)(null);\n const [tick, setTick] = (0, import_react.useState)(0);\n const refresh = (0, import_react.useCallback)(() => setTick((value) => value + 1), []);\n (0, import_react.useEffect)(() => {\n if (!directory) return;\n let live = true;\n const load = () => list({ directory }).then((result) => {\n if (live) {\n setData(result);\n setError(null);\n }\n }).catch((cause) => {\n if (live) setError(cause instanceof Error ? cause.message : String(cause));\n });\n void load();\n const timer = setInterval(load, POLL_MS);\n return () => {\n live = false;\n clearInterval(timer);\n };\n }, [directory, list, tick]);\n const onAdd = (0, import_react.useCallback)((title, priority) => __async(null, null, function* () {\n if (!directory) return false;\n try {\n const { id } = yield add({ directory, title, priority });\n toast.show(`Added ${id}`, { variant: "success" });\n refresh();\n return true;\n } catch (cause) {\n toast.error(cause instanceof Error ? cause.message : String(cause));\n return false;\n }\n }), [add, directory, refresh, toast]);\n const onAction = (0, import_react.useCallback)((_0) => __async(null, [_0], function* ({ id, action, gate }) {\n if (!directory) return;\n try {\n const { landed } = yield change({ directory, id, action, ...gate ? { gate } : {} });\n toast.show(landed ?? (action === "approve" ? `Approved ${id}` : action === "close" ? `Closed ${id}` : `Reopened ${id}`), { variant: "success" });\n refresh();\n } catch (cause) {\n toast.error(cause instanceof Error ? cause.message : String(cause));\n }\n }), [change, directory, refresh, toast]);\n return { projectRoot: data?.projectRoot ?? null, tasks: data?.tasks ?? null, unreadable: data?.unreadable.length ?? 0, error, onAdd, onAction, onRefresh: refresh };\n}\nvar PRIORITIES = [0, 1, 2, 3, 4];\nvar TYPE_ICONS = { bug: "Bug", feature: "Sparkles", task: "SquareCheck", chore: "Wrench", epic: "Target" };\nvar hovered = (state) => !!state.hovered;\nfunction age(iso, now = Date.now()) {\n if (!iso) return "";\n const minutes = Math.max(0, Math.floor((now - Date.parse(iso)) / 6e4));\n if (minutes < 60) return `${minutes}m`;\n if (minutes < 60 * 24) return `${Math.floor(minutes / 60)}h`;\n if (minutes < 60 * 24 * 14) return `${Math.floor(minutes / 1440)}d`;\n return `${Math.floor(minutes / 10080)}w`;\n}\nfunction stateOf(task) {\n if (task.status === "closed") return "closed";\n if (task.approvals?.length) return "approve";\n if (task.status === "review") return "review";\n if (task.status === "in_progress") return "progress";\n if (task.type === "epic") return task.progress?.done ? "progress" : "ready";\n return task.ready ? "ready" : "blocked";\n}\nvar STATE_LABELS = { approve: "Needs approval", review: "In review", progress: "In progress", ready: "Ready", blocked: "Blocked", closed: "Closed" };\nfunction filterTasks(tasks, filter, query) {\n const words = query.trim().toLowerCase().split(/\\s+/).filter(Boolean);\n return tasks.filter((task) => {\n if (filter === "open" && task.status === "closed") return false;\n if (filter === "ready" && !(task.ready && task.status !== "closed")) return false;\n if (filter === "closed" && task.status !== "closed") return false;\n const text = [task.id, task.title, task.type, task.assignee ?? "", ...task.labels ?? []].join(" ").toLowerCase();\n return words.every((word) => text.includes(word));\n });\n}\nfunction TaskBoard({ theme, compact, directory, projectRoot, tasks, unreadable, error, onAdd, onAction, onRefresh, initial }) {\n const styles = (0, import_react.useMemo)(() => makeStyles(theme, compact), [theme, compact]);\n const [view, setView] = (0, import_react.useState)(initial?.view ?? "list");\n const [filter, setFilter] = (0, import_react.useState)(initial?.filter ?? "open");\n const [query, setQuery] = (0, import_react.useState)("");\n const [selected, setSelected] = (0, import_react.useState)(initial?.selected ?? null);\n const [composing, setComposing] = (0, import_react.useState)(false);\n const [width, setWidth] = (0, import_react.useState)(initial?.width ?? 0);\n const shown = (0, import_react.useMemo)(() => tasks ? filterTasks(tasks, filter, query) : [], [tasks, filter, query]);\n const task = selected ? tasks?.find((candidate) => candidate.id === selected) ?? null : null;\n const split = !!task && width >= SPLIT_FROM;\n const counts = (0, import_react.useMemo)(() => ({\n open: (tasks ?? []).filter((entry) => entry.status !== "closed").length,\n ready: (tasks ?? []).filter((entry) => entry.ready && entry.status !== "closed").length,\n closed: (tasks ?? []).filter((entry) => entry.status === "closed").length,\n all: (tasks ?? []).length\n }), [tasks]);\n if (!directory) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.screen, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.muted, children: "This view needs a workspace." }) });\n const open = (id) => setSelected(id);\n const detail = task ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskDetail, { theme, styles, task, tasks: tasks ?? [], onBack: () => setSelected(null), onOpen: open, onAction }) : null;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.screen, onLayout: (event) => setWidth(event.nativeEvent.layout.width), children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.toolbar, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.toolbarRow, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.title, children: "Tasks" }),\n tasks ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.count, children: [\n counts.open,\n " open"\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: { flex: 1 } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n Segmented,\n {\n theme,\n styles,\n value: view,\n onChange: (value) => {\n setView(value);\n setSelected(null);\n },\n options: [{ key: "list", label: "List", icon: "List" }, { key: "board", label: "Board", icon: "Columns3" }, { key: "epics", label: "Epics", icon: "Target" }]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconButton, { theme, icon: "RefreshCw", label: "Refresh", onPress: onRefresh }),\n projectRoot ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconButton, { theme, icon: "Plus", label: "New task", onPress: () => setComposing(!composing), primary: true }) : null\n ] }),\n projectRoot ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.toolbarRow, children: [\n ["open", "ready", "closed", "all"].map((key) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Show ${key}`, accessibilityState: { selected: filter === key }, onPress: () => setFilter(key), style: [styles.filter, filter === key ? styles.filterOn : null], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: filter === key ? styles.filterTextOn : styles.filterText, children: [\n key[0].toUpperCase() + key.slice(1),\n " ",\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.filterCount, children: counts[key] })\n ] }) }, key)),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.search, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: "Search", size: 14, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TextInput, { style: styles.searchInput, value: query, onChangeText: setQuery, placeholder: "Filter by id, title, label, agent", placeholderTextColor: theme.colors.foregroundMuted, accessibilityLabel: "Filter tasks" })\n ] })\n ] }) : null,\n composing && projectRoot ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Composer, { theme, styles, onAdd: (title, priority) => __async(null, null, function* () {\n const added = yield onAdd(title, priority);\n if (added) setComposing(false);\n return added;\n }) }) : null\n ] }),\n error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.danger, styles.pad], children: error }) : null,\n tasks === null && !error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.muted, styles.pad], children: "Loading tasks\\u2026" }) : null,\n tasks !== null && projectRoot === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: [styles.muted, styles.pad], children: [\n directory,\n " is not an ALP project. Run alp init to start one."\n ] }) : null,\n projectRoot && tasks ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.body, children: [\n !task || split ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [styles.pane, split ? styles.paneList : null], children: [\n unreadable ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: [styles.warning, styles.pad], children: [\n unreadable,\n " unreadable task ",\n unreadable === 1 ? "file" : "files",\n " in ",\n projectRoot,\n "/.alp/tasks"\n ] }) : null,\n !tasks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, { styles, text: "No tasks yet. Add one here, with alp task add, or ask main to plan the work." }) : null,\n tasks.length && !shown.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, { styles, text: "No tasks match." }) : null,\n shown.length && view === "list" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListView, { theme, styles, tasks: shown, selected, onOpen: open, onAction }) : null,\n shown.length && view === "board" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BoardView, { theme, styles, tasks: shown, onOpen: open }) : null,\n view === "epics" && tasks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EpicsView, { theme, styles, tasks, shown, onOpen: open }) : null\n ] }) : null,\n detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [styles.pane, split ? styles.paneDetail : null], children: detail }) : null\n ] }) : null\n ] });\n}\nfunction Segmented({ theme, styles, value, options, onChange }) {\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.segmented, children: options.map((option) => {\n const on = option.key === value;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "tab", accessibilityLabel: option.label, accessibilityState: { selected: on }, onPress: () => onChange(option.key), style: [styles.segment, on ? styles.segmentOn : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: option.icon, size: 13, color: on ? theme.colors.foreground : theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: on ? styles.segmentTextOn : styles.segmentText, children: option.label })\n ] }, option.key);\n }) });\n}\nfunction IconButton({ theme, icon, label, onPress, primary }) {\n const { colors } = theme;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_react_native2.Pressable,\n {\n accessibilityRole: "button",\n accessibilityLabel: label,\n onPress,\n style: (state) => ({ padding: 7, borderRadius: 8, backgroundColor: primary ? colors.accent : hovered(state) ? colors.surface2 : "transparent" }),\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: icon, size: 15, color: primary ? colors.accentForeground : colors.foregroundMuted })\n }\n );\n}\nfunction Composer({ theme, styles, onAdd }) {\n const [title, setTitle] = (0, import_react.useState)("");\n const [priority, setPriority] = (0, import_react.useState)(2);\n const submit = () => __async(null, null, function* () {\n const text = title.trim();\n if (text && (yield onAdd(text, priority))) setTitle("");\n });\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.composer, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TextInput, { style: styles.input, value: title, onChangeText: setTitle, onSubmitEditing: submit, placeholder: "Add a task for main", placeholderTextColor: theme.colors.foregroundMuted, accessibilityLabel: "New task title", autoFocus: true }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.priorities, children: PRIORITIES.map((value) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Priority ${value}`, onPress: () => setPriority(value), style: [styles.chip, value === priority ? styles.chipOn : null], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: value === priority ? styles.chipTextOn : styles.chipText, children: [\n "P",\n value\n ] }) }, value)) }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "button", onPress: submit, style: styles.button, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.buttonText, children: "Add" }) })\n ] });\n}\nfunction Empty({ styles, text }) {\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.empty, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.muted, children: text }) });\n}\nfunction Priority({ theme, value }) {\n const { colors } = theme;\n const color = value === 0 ? colors.statusDanger : value === 1 ? colors.statusWarning : colors.foregroundMuted;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: { alignSelf: "flex-start", borderRadius: 4, borderWidth: 1, borderColor: value <= 1 ? color : colors.border, paddingHorizontal: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: { color, fontSize: 10.5, fontWeight: "600", fontVariant: ["tabular-nums"] }, children: [\n "P",\n value\n ] }) });\n}\nfunction StateDot({ theme, task }) {\n const { colors } = theme;\n const state = stateOf(task);\n const color = state === "approve" ? colors.statusWarning : state === "review" ? colors.accent : state === "progress" ? colors.statusWarning : state === "ready" ? colors.statusSuccess : state === "blocked" ? colors.statusDanger : colors.border;\n const ring = state === "progress" || state === "closed";\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { accessibilityLabel: STATE_LABELS[state], style: { width: 9, height: 9, borderRadius: 5, borderWidth: ring ? 2 : 0, borderColor: color, backgroundColor: ring ? "transparent" : color } });\n}\nfunction TaskLine({ theme, styles, task, selected, onOpen }) {\n const meta = [\n task.blockedBy?.length ? `after ${task.blockedBy.join(", ")}` : "",\n // Gates waiting for the user show with their Approve instead.\n task.waits?.length && !task.approvals?.length ? `waits on ${task.waits.join("; ")}` : "",\n task.parent ? `in ${task.parent}` : ""\n ].filter(Boolean).join(" \\xB7 ");\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Open ${task.id}`, onPress: () => onOpen(task.id), style: (state) => [styles.line, selected ? styles.lineOn : hovered(state) ? styles.lineHover : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.lineTop, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateDot, { theme, task }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: TYPE_ICONS[task.type] ?? "SquareCheck", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Priority, { theme, value: task.priority }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.id, children: task.id }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.lineTitle, numberOfLines: 1, children: task.title }),\n task.assignee ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.assignee, numberOfLines: 1, children: [\n "@",\n task.assignee\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.age, children: age(task.status === "closed" ? task.closed?.at : task.updatedAt) })\n ] }),\n meta || task.labels?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.lineMeta, children: [\n meta ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.small, numberOfLines: 1, children: meta }) : null,\n (task.labels ?? []).map((label) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.label, children: [\n "#",\n label\n ] }, label))\n ] }) : null\n ] });\n}\nvar SECTION_ICONS = { approve: "Hand", review: "Eye", progress: "LoaderCircle", ready: "CircleCheck", waiting: "CircleSlash", epics: "Target", closed: "CircleDashed" };\nfunction ListView({ theme, styles, tasks, selected, onOpen, onAction }) {\n const sections = (0, import_react.useMemo)(() => boardSections(tasks), [tasks]);\n const [hidden, setHidden] = (0, import_react.useState)({});\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { contentContainerStyle: styles.listContent, children: sections.map((section) => {\n const collapsed = hidden[section.key] ?? false;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.group, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `${collapsed ? "Show" : "Hide"} ${section.title}`, onPress: () => setHidden((current) => ({ ...current, [section.key]: !collapsed })), style: styles.groupHeader, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: collapsed ? "ChevronRight" : "ChevronDown", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: SECTION_ICONS[section.key] ?? "Circle", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.groupTitle, children: section.title }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.groupCount, children: section.tasks.length })\n ] }),\n !collapsed ? section.tasks.map((task) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskLine, { theme, styles, task, selected: task.id === selected, onOpen }),\n section.key === "approve" ? task.approvals.map((approval) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.inlineAction, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.small, numberOfLines: 2, children: approval.note || "Waiting for your approval" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, label: "Approve", primary: true, onPress: () => onAction({ id: task.id, action: "approve", gate: approval.gate }) })\n ] }, approval.gate)) : null\n ] }, `${section.key}-${task.id}`)) : null\n ] }, section.key);\n }) });\n}\nvar COLUMNS = [\n { key: "approve", title: "Needs approval" },\n { key: "blocked", title: "Blocked" },\n { key: "ready", title: "Ready" },\n { key: "progress", title: "In progress" },\n { key: "review", title: "In review" },\n { key: "closed", title: "Closed" }\n];\nfunction BoardView({ theme, styles, tasks, onOpen }) {\n const columns = COLUMNS.map((column) => ({ ...column, tasks: tasks.filter((task) => task.type !== "epic" && stateOf(task) === column.key) })).filter((column) => column.tasks.length || ["blocked", "ready", "progress"].includes(column.key));\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { horizontal: true, contentContainerStyle: styles.board, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.column, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.columnHeader, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateDot, { theme, task: { status: column.key === "closed" ? "closed" : column.key === "review" ? "review" : column.key === "progress" ? "in_progress" : "open", ready: column.key === "ready", approvals: column.key === "approve" ? [{ gate: "", note: "" }] : void 0 } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.columnTitle, children: column.title }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.groupCount, children: column.tasks.length })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.ScrollView, { contentContainerStyle: styles.columnBody, children: [\n column.tasks.map((task) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Open ${task.id}`, onPress: () => onOpen(task.id), style: (state) => [styles.card, hovered(state) ? styles.cardHover : null, column.key === "blocked" ? styles.cardBlocked : column.key === "ready" ? styles.cardReady : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.lineTop, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: TYPE_ICONS[task.type] ?? "SquareCheck", size: 12, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Priority, { theme, value: task.priority }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.id, children: task.id }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: { flex: 1 } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.age, children: age(task.updatedAt) })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.cardTitle, numberOfLines: 3, children: task.title }),\n task.assignee ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.assignee, numberOfLines: 1, children: [\n "@",\n task.assignee\n ] }) : null,\n task.blockedBy?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.blocked, numberOfLines: 1, children: [\n "after ",\n task.blockedBy.join(", ")\n ] }) : null,\n task.labels?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.cardLabels, children: task.labels.map((label) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.label, children: [\n "#",\n label\n ] }, label)) }) : null\n ] }, task.id)),\n !column.tasks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.small, styles.pad], children: "Nothing here" }) : null\n ] })\n ] }, column.key)) });\n}\nfunction EpicsView({ theme, styles, tasks, shown, onOpen }) {\n const epics = shown.filter((task) => task.type === "epic" || task.progress);\n const [opened, setOpened] = (0, import_react.useState)({});\n if (!epics.length) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, { styles, text: "No epics here. An epic is a task other tasks name as their parent." });\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { contentContainerStyle: styles.listContent, children: epics.map((epic) => {\n const children = tasks.filter((task) => task.parent === epic.id);\n const done = epic.progress?.done ?? 0;\n const total = epic.progress?.total ?? 0;\n const expanded = opened[epic.id] ?? epic.status !== "closed";\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.epic, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `Open ${epic.id}`, onPress: () => onOpen(epic.id), style: styles.lineTop, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateDot, { theme, task: epic }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: "Target", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Priority, { theme, value: epic.priority }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.id, children: epic.id }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.lineTitle, numberOfLines: 1, children: epic.title }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.progressText, children: [\n done,\n "/",\n total\n ] })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.progressTrack, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [styles.progressFill, { width: `${total ? Math.round(done / total * 100) : 0}%` }] }) }),\n children.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Pressable, { accessibilityRole: "button", accessibilityLabel: `${expanded ? "Hide" : "Show"} the tasks of ${epic.id}`, onPress: () => setOpened((current) => ({ ...current, [epic.id]: !expanded })), style: styles.treeToggle, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: expanded ? "ChevronDown" : "ChevronRight", size: 12, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.small, children: [\n children.length,\n " ",\n children.length === 1 ? "task" : "tasks"\n ] })\n ] }) : null,\n expanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.tree, children: children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskLine, { theme, styles, task: child, selected: false, onOpen }, child.id)) }) : null\n ] }, epic.id);\n }) });\n}\nfunction SmallButton({ styles, label, onPress, primary, danger }) {\n return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "button", onPress, style: [styles.smallButton, primary ? styles.smallButtonPrimary : null, danger ? styles.smallButtonDanger : null], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: primary ? styles.smallButtonTextPrimary : danger ? styles.smallButtonTextDanger : styles.smallButtonText, children: label }) });\n}\nfunction TaskDetail({ theme, styles, task, tasks, onBack, onOpen, onAction }) {\n const state = stateOf(task);\n const children = tasks.filter((entry) => entry.parent === task.id);\n const blocks = tasks.filter((entry) => entry.blockedBy?.includes(task.id) && entry.status !== "closed");\n const field = (label, value) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.field, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.fieldLabel, children: label }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.fieldValue, children: typeof value === "string" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: value }) : value })\n ] });\n const link = (id) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Pressable, { accessibilityRole: "link", accessibilityLabel: `Open ${id}`, onPress: () => onOpen(id), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.link, children: id }) }, id);\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.ScrollView, { contentContainerStyle: styles.detail, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.detailHeader, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconButton, { theme, icon: "ArrowLeft", label: "Back to the list", onPress: onBack }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.id, children: task.id }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.statePill, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateDot, { theme, task }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.small, children: STATE_LABELS[state] })\n ] })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.detailTitle, children: task.title }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.fields, children: [\n field("Type", /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.inline, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Icon, { name: TYPE_ICONS[task.type] ?? "SquareCheck", size: 13, color: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: task.type })\n ] })),\n field("Priority", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Priority, { theme, value: task.priority })),\n task.assignee ? field("Assignee", `@${task.assignee}`) : null,\n task.parent ? field("Parent", link(task.parent)) : null,\n task.blockedBy?.length ? field("Blocked by", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.inline, children: task.blockedBy.map(link) })) : null,\n blocks.length ? field("Blocks", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.inline, children: blocks.map((entry) => link(entry.id)) })) : null,\n task.waits?.length ? field("Waits on", task.waits.join("; ")) : null,\n task.labels?.length ? field("Labels", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.inline, children: task.labels.map((label) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.label, children: [\n "#",\n label\n ] }, label)) })) : null,\n task.paths?.length ? field("Paths", task.paths.join(", ")) : null,\n task.progress ? field("Progress", `${task.progress.done} of ${task.progress.total} closed`) : null,\n task.createdAt ? field("Created", `${age(task.createdAt)} ago`) : null,\n field("Updated", `${age(task.updatedAt)} ago`)\n ] }),\n task.description ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.box, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.boxTitle, children: "Description" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: task.description })\n ] }) : null,\n task.handoff ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.box, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.boxTitle, children: [\n "Handoff \\xB7 ",\n task.handoff.outcome,\n task.handoff.agent ? ` from ${task.handoff.agent}` : ""\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: task.handoff.summary })\n ] }) : null,\n task.closed ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.box, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.boxTitle, children: [\n "Closed \\xB7 ",\n task.closed.reason\n ] }),\n task.closed.summary ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.text, children: task.closed.summary }) : null\n ] }) : null,\n children.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.box, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: styles.boxTitle, children: [\n "Tasks \\xB7 ",\n children.filter((child) => child.status === "closed").length,\n "/",\n children.length,\n " closed"\n ] }),\n children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskLine, { theme, styles, task: child, selected: false, onOpen }, child.id))\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.detailActions, children: [\n (task.approvals ?? []).map((approval) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, primary: true, label: `Approve${approval.note ? `: ${approval.note.slice(0, 40)}` : ""}`, onPress: () => onAction({ id: task.id, action: "approve", gate: approval.gate }) }, approval.gate)),\n state === "review" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, primary: true, label: "Accept and close", onPress: () => onAction({ id: task.id, action: "close" }) }) : null,\n task.status !== "closed" && state !== "review" && task.type !== "epic" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, label: "Close", onPress: () => onAction({ id: task.id, action: "close" }) }) : null,\n task.status === "closed" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmallButton, { styles, label: "Reopen", onPress: () => onAction({ id: task.id, action: "reopen" }) }) : null\n ] })\n ] });\n}\nfunction makeStyles(theme, compact) {\n const { colors } = theme;\n const mono = { fontFamily: "monospace", fontVariant: ["tabular-nums"] };\n return {\n screen: { flex: 1, backgroundColor: colors.surface0 },\n pad: { paddingHorizontal: compact ? 12 : 16, paddingVertical: 8 },\n toolbar: { paddingHorizontal: compact ? 12 : 16, paddingTop: 12, paddingBottom: 10, gap: 10, borderBottomWidth: 1, borderBottomColor: colors.border },\n toolbarRow: { flexDirection: "row", alignItems: "center", gap: 6, flexWrap: "wrap" },\n title: { color: colors.foreground, fontSize: 15, fontWeight: "600" },\n count: { color: colors.foregroundMuted, fontSize: 12, marginLeft: 4 },\n segmented: { flexDirection: "row", backgroundColor: colors.surface1, borderRadius: 8, borderWidth: 1, borderColor: colors.border, padding: 2 },\n segment: { flexDirection: "row", alignItems: "center", gap: 5, paddingHorizontal: 8, paddingVertical: 4, borderRadius: 6 },\n segmentOn: { backgroundColor: colors.surface0, shadowColor: "#000", shadowOpacity: 0.08, shadowRadius: 2 },\n segmentText: { color: colors.foregroundMuted, fontSize: 12 },\n segmentTextOn: { color: colors.foreground, fontSize: 12, fontWeight: "600" },\n filter: { paddingHorizontal: 9, paddingVertical: 4, borderRadius: 999, borderWidth: 1, borderColor: colors.border },\n filterOn: { backgroundColor: colors.foreground, borderColor: colors.foreground },\n filterText: { color: colors.foreground, fontSize: 12 },\n filterTextOn: { color: colors.surface0, fontSize: 12, fontWeight: "600" },\n filterCount: { opacity: 0.6, fontSize: 11 },\n search: { flex: 1, minWidth: 160, flexDirection: "row", alignItems: "center", gap: 6, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 8, backgroundColor: colors.surface1 },\n searchInput: { flex: 1, minWidth: 0, color: colors.foreground, fontSize: 12.5, paddingVertical: 6 },\n composer: { flexDirection: compact ? "column" : "row", gap: 8, alignItems: compact ? "stretch" : "center" },\n input: { flex: compact ? void 0 : 1, minWidth: 0, color: colors.foreground, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 10, paddingVertical: 7, backgroundColor: colors.surface1 },\n priorities: { flexDirection: "row", gap: 4 },\n chip: { paddingHorizontal: 7, paddingVertical: 5, borderRadius: 6, borderWidth: 1, borderColor: colors.border },\n chipOn: { backgroundColor: colors.accent, borderColor: colors.accent },\n chipText: { color: colors.foregroundMuted, fontSize: 12 },\n chipTextOn: { color: colors.accentForeground, fontSize: 12 },\n button: { paddingHorizontal: 12, paddingVertical: 7, borderRadius: 8, backgroundColor: colors.accent },\n buttonText: { color: colors.accentForeground, fontWeight: "600" },\n body: { flex: 1, flexDirection: "row" },\n pane: { flex: 1, minWidth: 0 },\n paneList: { flex: 2, borderRightWidth: 1, borderRightColor: colors.border },\n paneDetail: { flex: 3 },\n empty: { margin: 16, borderWidth: 1, borderStyle: "dashed", borderColor: colors.border, borderRadius: 10, padding: 24, alignItems: "center" },\n listContent: { paddingVertical: 6 },\n group: { marginBottom: 4 },\n groupHeader: { flexDirection: "row", alignItems: "center", gap: 6, paddingHorizontal: compact ? 10 : 14, paddingVertical: 7 },\n groupTitle: { color: colors.foregroundMuted, fontSize: 11.5, fontWeight: "600", textTransform: "uppercase", letterSpacing: 0.4 },\n groupCount: { color: colors.foregroundMuted, fontSize: 11, opacity: 0.8 },\n line: { paddingHorizontal: compact ? 10 : 14, paddingVertical: 7, gap: 3, borderLeftWidth: 2, borderLeftColor: "transparent" },\n lineOn: { backgroundColor: colors.surface2, borderLeftColor: colors.accent },\n lineHover: { backgroundColor: colors.surface1 },\n lineTop: { flexDirection: "row", alignItems: "center", gap: 7 },\n lineTitle: { flex: 1, minWidth: 0, color: colors.foreground, fontSize: 13 },\n lineMeta: { flexDirection: "row", flexWrap: "wrap", gap: 6, paddingLeft: 16 },\n id: { color: colors.foregroundMuted, fontSize: 11.5, ...mono },\n age: { color: colors.foregroundMuted, fontSize: 11, ...mono },\n assignee: { color: colors.accent, fontSize: 11.5, maxWidth: 110 },\n label: { color: colors.foregroundMuted, fontSize: 11, backgroundColor: colors.surface2, borderRadius: 4, paddingHorizontal: 5, paddingVertical: 1 },\n inlineAction: { flexDirection: "row", alignItems: "center", gap: 10, paddingLeft: compact ? 26 : 30, paddingRight: 14, paddingBottom: 8 },\n board: { padding: 12, gap: 10, alignItems: "flex-start" },\n column: { width: 248, backgroundColor: colors.surface1, borderRadius: 10, borderWidth: 1, borderColor: colors.border, maxHeight: 640 },\n columnHeader: { flexDirection: "row", alignItems: "center", gap: 7, paddingHorizontal: 12, paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: colors.border },\n columnTitle: { flex: 1, color: colors.foreground, fontSize: 12.5, fontWeight: "600" },\n columnBody: { padding: 8, gap: 8 },\n card: { backgroundColor: colors.surface0, borderRadius: 8, borderWidth: 1, borderColor: colors.border, borderLeftWidth: 3, padding: 10, gap: 5 },\n cardHover: { borderColor: colors.foregroundMuted },\n cardBlocked: { borderLeftColor: colors.statusDanger },\n cardReady: { borderLeftColor: colors.statusSuccess },\n cardLabels: { flexDirection: "row", flexWrap: "wrap", gap: 6 },\n blocked: { color: colors.statusDanger, fontSize: 11.5 },\n cardTitle: { color: colors.foreground, fontSize: 13, lineHeight: 18 },\n epic: { marginHorizontal: compact ? 10 : 14, marginVertical: 6, padding: 12, borderRadius: 10, borderWidth: 1, borderColor: colors.border, backgroundColor: colors.surface1, gap: 8 },\n progressTrack: { height: 6, borderRadius: 3, backgroundColor: colors.surface2, overflow: "hidden" },\n progressFill: { height: 6, borderRadius: 3, backgroundColor: colors.statusSuccess },\n progressText: { color: colors.foregroundMuted, fontSize: 11.5, ...mono },\n treeToggle: { flexDirection: "row", alignItems: "center", gap: 4 },\n tree: { marginLeft: 6, borderLeftWidth: 1, borderLeftColor: colors.border, backgroundColor: colors.surface0, borderRadius: 6 },\n detail: { padding: compact ? 12 : 18, gap: 14 },\n detailHeader: { flexDirection: "row", alignItems: "center", gap: 8 },\n statePill: { flexDirection: "row", alignItems: "center", gap: 6, borderWidth: 1, borderColor: colors.border, borderRadius: 999, paddingHorizontal: 8, paddingVertical: 2 },\n detailTitle: { color: colors.foreground, fontSize: 17, fontWeight: "600", lineHeight: 23 },\n fields: { borderWidth: 1, borderColor: colors.border, borderRadius: 10, overflow: "hidden" },\n field: { flexDirection: "row", alignItems: "center", gap: 12, paddingHorizontal: 12, paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: colors.border },\n fieldLabel: { width: 84, color: colors.foregroundMuted, fontSize: 12 },\n fieldValue: { flex: 1, minWidth: 0 },\n inline: { flexDirection: "row", alignItems: "center", gap: 6, flexWrap: "wrap" },\n box: { borderRadius: 10, backgroundColor: colors.surface1, borderWidth: 1, borderColor: colors.border, padding: 12, gap: 6 },\n boxTitle: { color: colors.foregroundMuted, fontSize: 11.5, fontWeight: "600", textTransform: "uppercase", letterSpacing: 0.4 },\n detailActions: { flexDirection: "row", gap: 8, flexWrap: "wrap" },\n smallButton: { paddingHorizontal: 10, paddingVertical: 6, borderRadius: 7, borderWidth: 1, borderColor: colors.border, backgroundColor: colors.surface1 },\n smallButtonPrimary: { backgroundColor: colors.accent, borderColor: colors.accent },\n smallButtonDanger: { borderColor: colors.statusDanger },\n smallButtonText: { color: colors.foreground, fontSize: 12.5, fontWeight: "500" },\n smallButtonTextPrimary: { color: colors.accentForeground, fontSize: 12.5, fontWeight: "600" },\n smallButtonTextDanger: { color: colors.statusDanger, fontSize: 12.5 },\n text: { color: colors.foreground, fontSize: 13, lineHeight: 19 },\n small: { color: colors.foregroundMuted, fontSize: 12 },\n muted: { color: colors.foregroundMuted, fontSize: 13 },\n danger: { color: colors.statusDanger, fontSize: 13 },\n warning: { color: colors.statusWarning, fontSize: 12 },\n link: { color: colors.accent, fontSize: 13, ...mono }\n };\n}\n\n// integrations/paseo/client/task-pills.ts\nvar TASKS_SCREEN = "alp-tasks";\nvar POLL_MS2 = 2e4;\nvar MENU_LIMIT = 8;\nvar PAGE = 200;\nfunction tasksScreen(workspaceId, directory, taskId) {\n return { screenId: TASKS_SCREEN, params: { workspaceId, directory, ...taskId ? { taskId } : {} } };\n}\nvar ORDER = ["approve", "review", "progress", "ready", "blocked"];\nvar STATES = {\n approve: { label: "Approve", icon: "Hand" },\n review: { label: "Review", icon: "Eye" },\n progress: { label: "In progress", icon: "LoaderCircle" },\n ready: { label: "Ready", icon: "CircleCheck" },\n blocked: { label: "Blocked", icon: "CircleSlash" },\n closed: { label: "Done", icon: "CheckCheck" }\n};\nfunction sessionWork(board, sessions = []) {\n const ids = sessions.map((id) => board?.sessions?.[id]).find(Boolean) ?? [];\n const index = new Map((board?.tasks ?? []).map((task) => [task.id, task]));\n return ids.flatMap((id) => index.has(id) ? [{ task: index.get(id), state: stateOf(index.get(id)) }] : []);\n}\nfunction menuTasks(tasks) {\n return tasks.filter((task) => task.status !== "closed" && task.type !== "epic").map((task) => ({ task, state: stateOf(task) })).sort((a, b) => ORDER.indexOf(a.state) - ORDER.indexOf(b.state) || a.task.priority - b.task.priority || a.task.id.localeCompare(b.task.id));\n}\nfunction taskButton(board, open, sessions = []) {\n const listed = board ? menuTasks(board.tasks) : [];\n const worked = sessionWork(board, sessions);\n const done = worked.filter((entry2) => entry2.state === "closed").length;\n const mine = new Set(worked.map((entry2) => entry2.task.id));\n const shown = [...worked, ...listed.filter((entry2) => !mine.has(entry2.task.id))];\n const entry = ({ task, state }, index) => ({\n kind: "item",\n id: `task-${index}`,\n title: `${STATES[state].label} \\xB7 ${task.title}`,\n icon: STATES[state].icon,\n behavior: { kind: "action", onPress: () => open(task.id) }\n });\n const items = shown.slice(0, MENU_LIMIT).map(entry);\n if (worked.length && items.length > worked.length) items.splice(worked.length, 0, { kind: "separator", id: "session-end" });\n if (items.length) items.push({ kind: "separator", id: "tasks-end" });\n const more = shown.length - MENU_LIMIT;\n items.push({ kind: "item", id: "all-tasks", title: more > 0 ? `All tasks (${more} more)` : "All tasks", icon: "ListTodo", behavior: { kind: "action", onPress: () => open() } });\n return {\n title: worked.length ? `ALP tasks: ${done} of ${worked.length} done in this session, ${listed.length} open` : listed.length ? `ALP tasks: ${listed.length} open` : "ALP tasks",\n icon: "ListTodo",\n label: worked.length ? `Tasks \\xB7 ${done}/${worked.length}` : listed.length ? `Tasks \\xB7 ${listed.length}` : "Tasks",\n visible: board?.projectRoot !== null,\n behavior: { kind: "menu", items }\n };\n}\nfunction signature(board, sessions) {\n return JSON.stringify(board && [board.projectRoot !== null, [...sessionWork(board, sessions), ...menuTasks(board.tasks)].map(({ task, state }) => [task.id, state, task.title])]);\n}\nfunction addTaskPills(client) {\n const agents = /* @__PURE__ */ new Map();\n const directories = /* @__PURE__ */ new Map();\n const boards = /* @__PURE__ */ new Map();\n const pills = /* @__PURE__ */ new Map();\n let subscription = null;\n let stopped = false;\n let retry;\n let polling = false;\n let again = false;\n const opener = (agent, directory) => (taskId) => client.openScreen(tasksScreen(agent.workspaceId, directory, taskId));\n const directoryOf = (agent) => {\n let found = directories.get(agent.workspaceId);\n if (!found) {\n found = client.paseo.workspaces.ref(agent.workspaceId).refresh().then((workspace) => workspace?.workspaceDirectory || workspace?.projectRootPath || agent.cwd).catch(() => {\n directories.delete(agent.workspaceId);\n return agent.cwd;\n });\n directories.set(agent.workspaceId, found);\n }\n return found;\n };\n const show = (agent) => __async(null, null, function* () {\n const directory = yield directoryOf(agent);\n if (stopped || pills.has(agent.id) || agents.get(agent.id) !== agent) return;\n const board = boards.get(directory) ?? null;\n try {\n const registration = client.addComposerPill({ id: "alp-tasks", workspaceId: agent.workspaceId, agentId: agent.id, button: taskButton(board, opener(agent, directory), agent.sessions) });\n pills.set(agent.id, { agent, directory, registration, signature: signature(board, agent.sessions) });\n } catch {\n return;\n }\n if (!board) void poll();\n });\n const hide = (id) => {\n agents.delete(id);\n pills.get(id)?.registration.remove();\n pills.delete(id);\n };\n const accept = (snapshot) => {\n const known = agents.get(snapshot.id);\n if (snapshot.provider !== "alp" || !snapshot.workspaceId || snapshot.archivedAt) {\n if (known) hide(snapshot.id);\n return;\n }\n const sessions = [snapshot.persistence?.sessionId, snapshot.id].filter((id) => Boolean(id));\n if (known?.workspaceId === snapshot.workspaceId && known.sessions.join() === sessions.join()) return;\n if (known) hide(snapshot.id);\n const agent = { id: snapshot.id, workspaceId: snapshot.workspaceId, cwd: snapshot.cwd, sessions };\n agents.set(agent.id, agent);\n void show(agent);\n };\n const load = (page) => __async(null, null, function* () {\n const seen = /* @__PURE__ */ new Set();\n for (let current = page; ; ) {\n for (const { agent } of current.entries) {\n seen.add(agent.id);\n accept(agent);\n }\n const cursor = current.pageInfo.nextCursor;\n if (!current.pageInfo.hasMore || !cursor || stopped) break;\n current = yield client.paseo.agents.list({ scope: "active", page: { limit: PAGE, cursor } });\n }\n for (const id of [...agents.keys()]) if (!seen.has(id)) hide(id);\n });\n const watch = () => __async(null, null, function* () {\n try {\n const first = yield client.paseo.agents.list({ scope: "active", page: { limit: PAGE }, subscribe: {} });\n if (stopped) {\n void first.subscription.release().catch(() => {\n });\n return;\n }\n subscription = first.subscription;\n first.subscription.subscribe({\n snapshot: (snapshot) => {\n void load(snapshot).catch(() => {\n });\n },\n update: (message2) => {\n if (message2.type !== "agent_update") return;\n if (message2.payload.kind === "remove") hide(message2.payload.agentId);\n else accept(message2.payload.agent);\n }\n });\n } catch {\n if (!stopped) retry = setTimeout(() => void watch(), POLL_MS2);\n }\n });\n const poll = () => __async(null, null, function* () {\n if (polling) {\n again = true;\n return;\n }\n polling = true;\n try {\n const shown = new Set([...pills.values()].map((pill) => pill.directory));\n for (const directory of shown) {\n if (stopped) return;\n try {\n boards.set(directory, yield client.rpc(tasksList, { directory }));\n } catch {\n continue;\n }\n for (const pill of pills.values()) if (pill.directory === directory) render(pill);\n }\n for (const directory of [...boards.keys()]) if (!shown.has(directory)) boards.delete(directory);\n } finally {\n polling = false;\n if (again && !stopped) {\n again = false;\n void poll();\n }\n }\n });\n const render = (pill) => {\n const board = boards.get(pill.directory) ?? null;\n const next = signature(board, pill.agent.sessions);\n if (next === pill.signature) return;\n pill.signature = next;\n pill.registration.update(taskButton(board, opener(pill.agent, pill.directory), pill.agent.sessions));\n };\n const timer = setInterval(() => void poll(), POLL_MS2);\n void watch();\n return () => {\n stopped = true;\n clearInterval(timer);\n if (retry !== void 0) clearTimeout(retry);\n for (const id of [...pills.keys()]) hide(id);\n void subscription?.release().catch(() => {\n });\n };\n}\n\n// integrations/paseo/client/team-model-settings.tsx\nvar import_react3 = require("react");\nvar import_react_native5 = require("react-native");\nvar import_client2 = require("@getpaseo/plugin/client");\nvar import_ui = require("@getpaseo/plugin/client/ui");\n\n// integrations/paseo/shared/library.ts\nvar import_plugin2 = require("@getpaseo/plugin");\nvar import_zod2 = require("zod");\nvar Directory2 = import_zod2.z.string().min(1).optional();\nvar KindSchema = import_zod2.z.enum(["agents", "skills", "mcp", "hooks", "teams", "providers"]);\nvar ScopeSchema = import_zod2.z.enum(["library", "project"]);\nvar Name = import_zod2.z.string().regex(/^[\\w.-]+$/).refine((name) => name !== "." && name !== "..");\nvar Source = import_zod2.z.enum(["builtin", "library", "project"]);\nvar EntryRowSchema = import_zod2.z.object({\n name: import_zod2.z.string(),\n source: Source,\n overrides: Source.optional(),\n path: import_zod2.z.string().optional(),\n description: import_zod2.z.string().optional(),\n usedBy: import_zod2.z.array(import_zod2.z.string()).optional()\n});\nvar libraryList = (0, import_plugin2.defineRpc)({\n name: "alp.library.list",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema }),\n output: import_zod2.z.object({\n projectRoot: import_zod2.z.string().nullable(),\n library: import_zod2.z.string(),\n entries: import_zod2.z.array(EntryRowSchema),\n /**\n * Set when the library can only be looked at from here (ALP remote mode): why, and where to\n * change it. `unlisted` says why there are no entries at all (no granted workspace open).\n */\n readOnly: import_zod2.z.object({ reason: import_zod2.z.string(), unlisted: import_zod2.z.string().optional() }).optional()\n })\n});\nvar libraryGet = (0, import_plugin2.defineRpc)({\n name: "alp.library.get",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema, name: Name, scope: ScopeSchema.optional() }),\n output: import_zod2.z.object({\n kind: KindSchema,\n name: import_zod2.z.string(),\n source: Source,\n overrides: Source.optional(),\n content: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()),\n /** Pass back with a save or delete; a different current revision refuses it. */\n revision: import_zod2.z.string().nullable(),\n usedBy: import_zod2.z.array(import_zod2.z.string()),\n /** Agents: the skills the library gives it by name (role-skills.json). */\n librarySkills: import_zod2.z.array(import_zod2.z.string()).optional(),\n /** ALP remote mode: JSON Pointers of the values `content` holds as a secret marker, not as the value. */\n secrets: import_zod2.z.array(import_zod2.z.string()).optional()\n })\n});\nvar librarySkills = (0, import_plugin2.defineRpc)({\n name: "alp.library.skills",\n input: import_zod2.z.object({ agent: Name, skills: import_zod2.z.array(Name) }),\n output: import_zod2.z.object({ skills: import_zod2.z.array(import_zod2.z.string()) })\n});\nvar librarySave = (0, import_plugin2.defineRpc)({\n name: "alp.library.save",\n input: import_zod2.z.object({\n directory: Directory2,\n kind: KindSchema,\n name: Name,\n scope: ScopeSchema,\n content: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()),\n /** null creates; a string replaces that revision; omitted overwrites. */\n revision: import_zod2.z.string().nullable().optional()\n }),\n output: import_zod2.z.object({ revision: import_zod2.z.string().nullable(), syncedProjects: import_zod2.z.number().int().nonnegative().optional(), syncErrors: import_zod2.z.array(import_zod2.z.string()).optional() })\n});\nvar libraryDelete = (0, import_plugin2.defineRpc)({\n name: "alp.library.delete",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema, name: Name, scope: ScopeSchema, revision: import_zod2.z.string().optional() }),\n /** now: the layer that applies again after removing an override. */\n output: import_zod2.z.object({ removed: import_zod2.z.boolean(), now: Source.optional() })\n});\nvar libraryDuplicate = (0, import_plugin2.defineRpc)({\n name: "alp.library.duplicate",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema, from: Name, to: Name, scope: ScopeSchema }),\n output: import_zod2.z.object({ revision: import_zod2.z.string().nullable() })\n});\nvar libraryRename = (0, import_plugin2.defineRpc)({\n name: "alp.library.rename",\n input: import_zod2.z.object({ directory: Directory2, kind: KindSchema, from: Name, to: Name, scope: ScopeSchema }),\n output: import_zod2.z.object({ revision: import_zod2.z.string().nullable() })\n});\nvar libraryTest = (0, import_plugin2.defineRpc)({\n name: "alp.library.test",\n input: import_zod2.z.object({ directory: Directory2, kind: import_zod2.z.enum(["mcp", "hooks", "providers"]), name: Name, scope: ScopeSchema.optional() }),\n output: import_zod2.z.object({\n ok: import_zod2.z.boolean(),\n /** MCP: the server and its tools. */\n server: import_zod2.z.object({ name: import_zod2.z.string().optional(), version: import_zod2.z.string().optional() }).optional(),\n tools: import_zod2.z.array(import_zod2.z.object({ name: import_zod2.z.string(), description: import_zod2.z.string().optional() })).optional(),\n /** Hooks: how the sample run went. */\n exitCode: import_zod2.z.number().nullable().optional(),\n signal: import_zod2.z.string().nullable().optional(),\n timedOut: import_zod2.z.boolean().optional(),\n wouldBlock: import_zod2.z.boolean().optional(),\n stdout: import_zod2.z.string().optional(),\n stderr: import_zod2.z.string().optional(),\n durationMs: import_zod2.z.number().optional(),\n /** Providers: who the ACP agent says it is, and what it supports. */\n protocolVersion: import_zod2.z.number().optional(),\n agent: import_zod2.z.object({ name: import_zod2.z.string().optional(), title: import_zod2.z.string().optional(), version: import_zod2.z.string().optional() }).optional(),\n loadSession: import_zod2.z.boolean().optional(),\n mcpHttp: import_zod2.z.boolean().optional(),\n authMethods: import_zod2.z.array(import_zod2.z.string()).optional()\n })\n});\nvar LanguageSettingSchema = import_zod2.z.object({\n language: import_zod2.z.string().nullable(),\n applies: import_zod2.z.string(),\n default: import_zod2.z.string(),\n /** Why it cannot be changed from here (ALP remote mode). */\n readOnly: import_zod2.z.string().optional()\n});\nvar languageGet = (0, import_plugin2.defineRpc)({\n name: "alp.settings.language.get",\n input: import_zod2.z.object({}),\n output: LanguageSettingSchema\n});\nvar languageSet = (0, import_plugin2.defineRpc)({\n name: "alp.settings.language.set",\n input: import_zod2.z.object({ language: import_zod2.z.string().trim().min(1).max(40).nullable() }),\n output: LanguageSettingSchema\n});\nvar libraryModels = (0, import_plugin2.defineRpc)({\n name: "alp.library.models",\n input: import_zod2.z.object({}),\n output: import_zod2.z.object({ models: import_zod2.z.array(import_zod2.z.object({ id: import_zod2.z.string(), label: import_zod2.z.string(), efforts: import_zod2.z.array(import_zod2.z.string()), effort: import_zod2.z.string().optional() })) })\n});\n\n// integrations/paseo/shared/team-models.ts\nvar MODEL_PRESETS = [\n { label: "Claude only", value: "claude" },\n { label: "Codex only", value: "codex" },\n { label: "OpenCode only", value: "opencode" },\n { label: "Antigravity only", value: "antigravity" },\n { label: "Mix \\xB7 Claude + Codex", value: "mix" }\n];\nfunction presetTeamModels(team, preset, models) {\n const next = JSON.parse(JSON.stringify(team));\n const find = (provider) => models.find((model) => provider === "opencode" ? model.id === "acp:opencode" || model.id.startsWith("acp:opencode/") : model.id.startsWith(`${provider}:`));\n const primary = find(preset === "mix" ? "claude" : preset);\n const secondary = preset === "mix" ? find("codex") : primary;\n if (!primary || !secondary) throw new Error("No models available for this preset. Configure the provider in Settings first.");\n const assign = (target, model) => {\n target.model = model.id;\n if (model.effort) target.thinking = model.effort;\n else delete target.thinking;\n };\n for (const [name, member] of Object.entries(next.members ?? {})) {\n if (name !== "oracle") assign(member, name === next.main ? primary : secondary);\n }\n if (next.supervisor) assign(next.supervisor, secondary);\n if (next.members?.oracle) {\n next.oracleModels = [.../* @__PURE__ */ new Set([primary.id, secondary.id])];\n next.oracleThinking = Object.fromEntries([primary, secondary].filter((model) => model.effort).map((model) => [model.id, model.effort]));\n }\n next.modelSetup = { mode: "default", preset };\n return next;\n}\nfunction modelSetupFor(team, models) {\n if (team.modelSetup) return team.modelSetup;\n for (const { value } of MODEL_PRESETS) {\n let expected;\n try {\n expected = presetTeamModels(team, value, models);\n } catch {\n continue;\n }\n const same = (a, b) => a.model === b.model && a.thinking === b.thinking;\n if (!Object.entries(team.members ?? {}).filter(([name]) => name !== "oracle").every(([name, member]) => same(member, expected.members[name]))) continue;\n if (team.supervisor && !same(team.supervisor, expected.supervisor)) continue;\n if (team.members?.oracle && (JSON.stringify(team.oracleModels) !== JSON.stringify(expected.oracleModels) || expected.oracleModels.some((id) => (team.oracleThinking?.[id] ?? team.oracleThinking?.[id.split(":")[0]]) !== expected.oracleThinking?.[id]))) continue;\n return { mode: "default", preset: value };\n }\n return { mode: "custom" };\n}\n\n// integrations/paseo/client/side-nav.tsx\nvar import_react_native3 = require("@getpaseo/plugin/client/react-native");\nvar import_react2 = require("react");\nvar import_react_native4 = require("react-native");\nvar import_jsx_runtime2 = require("react/jsx-runtime");\nvar hovered2 = (state) => !!state.hovered;\nvar COLLAPSE_BELOW = 640;\nvar EXPANDED = 216;\nvar COLLAPSED = 52;\nfunction SideNavLayout(props) {\n const { theme, compact, groups, active, onSelect } = props;\n const styles = (0, import_react2.useMemo)(() => layoutStyles(theme), [theme]);\n const [width, setWidth] = (0, import_react2.useState)(0);\n const [choice, setChoice] = (0, import_react2.useState)(props.initialCollapsed);\n const [open, setOpen] = (0, import_react2.useState)(false);\n const collapsed = choice ?? (width > 0 && width < COLLAPSE_BELOW);\n const select = (item, child) => {\n onSelect(item, child);\n setOpen(false);\n };\n const aside = (mode) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(\n Aside,\n {\n styles,\n theme,\n title: props.title,\n subtitle: props.subtitle,\n groups,\n active,\n onSelect: select,\n collapsed: mode === "fixed" && collapsed,\n onToggle: mode === "fixed" ? () => setChoice(!collapsed) : () => setOpen(false),\n overlay: mode === "overlay"\n }\n );\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: props.embedded ? { width: "100%" } : styles.root, onLayout: (event) => setWidth(event.nativeEvent.layout.width), children: [\n !props.embedded && !compact ? aside("fixed") : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: props.embedded ? { minWidth: 0 } : styles.main, children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: [styles.header, props.embedded ? { paddingHorizontal: 0, paddingTop: 0 } : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.headerRow, children: [\n compact && !props.embedded ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "button", accessibilityLabel: "Open navigation", onPress: () => setOpen(true), style: styles.iconButton, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: "Menu", size: 18, color: theme.colors.foreground }) }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.crumbs, children: [\n props.breadcrumb.map((part, index) => [\n index ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.crumbSeparator, children: "/" }, `separator-${index}`) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: index === props.breadcrumb.length - 1 ? styles.crumbCurrent : styles.crumb, numberOfLines: 1, children: part }, `${index}-${part}`)\n ]),\n props.badges\n ] }),\n props.actions ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: styles.actions, children: props.actions }) : null\n ] }),\n props.tabs?.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, contentContainerStyle: styles.tabs, children: props.tabs.map((tab) => {\n const on = tab.key === props.tab;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "tab", accessibilityLabel: tab.label, accessibilityState: { selected: on }, onPress: () => props.onTab?.(tab.key), style: [styles.tab, on ? styles.tabOn : null], children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.Text, { style: on ? styles.tabTextOn : styles.tabText, children: [\n tab.label,\n tab.count !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.tabCount, children: ` ${tab.count}` }) : null\n ] }) }, tab.key);\n }) }) : null\n ] }),\n props.embedded ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: [styles.bodyContent, { paddingHorizontal: 0 }], children: props.children }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.ScrollView, { style: styles.body, contentContainerStyle: styles.bodyContent, children: props.children }),\n props.footer ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: [styles.footer, props.embedded ? { paddingHorizontal: 0 } : null], children: props.footer }) : null\n ] }),\n !props.embedded && compact && open ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.overlay, children: [\n aside("overlay"),\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "button", accessibilityLabel: "Close navigation", onPress: () => setOpen(false), style: styles.scrim })\n ] }) : null\n ] });\n}\nfunction Aside({ styles, theme, title, subtitle, groups, active, onSelect, collapsed, onToggle, overlay }) {\n const { colors } = theme;\n const [opened, setOpened] = (0, import_react2.useState)({});\n const tone = (value) => value === "accent" ? colors.accent : value === "warning" ? colors.statusWarning : colors.border;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: [styles.aside, { width: collapsed ? COLLAPSED : EXPANDED }, overlay ? styles.asideOverlay : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: [styles.asideHeader, collapsed ? styles.asideHeaderCollapsed : null], children: [\n !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.asideTitleBox, children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.asideTitle, numberOfLines: 1, children: title }),\n subtitle ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.asideSubtitle, numberOfLines: 1, children: subtitle }) : null\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "button", accessibilityLabel: overlay ? "Close navigation" : collapsed ? "Expand navigation" : "Collapse navigation", onPress: onToggle, style: styles.iconButton, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: overlay ? "X" : collapsed ? "PanelLeftOpen" : "PanelLeftClose", size: 16, color: colors.foregroundMuted }) })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.ScrollView, { contentContainerStyle: styles.asideList, children: groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { style: styles.group, children: [\n !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.groupLabel, children: group.label }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: styles.groupRule }),\n group.items.map((item) => {\n const selected = active.item === item.key;\n const expanded = !collapsed && (opened[item.key] ?? selected) && !!item.children?.length;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native4.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(\n import_react_native4.Pressable,\n {\n accessibilityRole: "button",\n accessibilityLabel: item.label,\n accessibilityState: { selected: selected && !active.child },\n onPress: () => {\n onSelect(item.key);\n setOpened((current) => ({ ...current, [item.key]: true }));\n },\n style: (state) => [styles.item, collapsed ? styles.itemCollapsed : null, selected ? styles.itemOn : hovered2(state) ? styles.itemHover : null],\n children: [\n selected ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: styles.itemBar }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: item.icon, size: 16, color: selected ? colors.accent : colors.foregroundMuted }),\n !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: [styles.itemLabel, selected ? styles.itemLabelOn : null], numberOfLines: 1, children: item.label }) : null,\n !collapsed && item.count !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.count, children: item.count }) : null,\n !collapsed && item.children?.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Pressable, { accessibilityRole: "button", accessibilityLabel: `${expanded ? "Hide" : "Show"} ${item.label}`, hitSlop: 8, onPress: () => setOpened((current) => ({ ...current, [item.key]: !expanded })), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: expanded ? "ChevronDown" : "ChevronRight", size: 14, color: colors.foregroundMuted }) }) : null\n ]\n }\n ),\n expanded ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: styles.children, children: item.children.map((child) => {\n const on = selected && active.child === child.key;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(\n import_react_native4.Pressable,\n {\n accessibilityRole: "button",\n accessibilityLabel: `${item.label} ${child.label}`,\n accessibilityState: { selected: on },\n onPress: () => onSelect(item.key, child.key),\n style: (state) => [styles.child, on ? styles.childOn : hovered2(state) ? styles.itemHover : null],\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: [styles.dot, { backgroundColor: tone(child.tone) }] }),\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: [styles.childLabel, on ? styles.itemLabelOn : null], numberOfLines: 1, children: child.label }),\n child.hint ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: styles.childHint, numberOfLines: 1, children: child.hint }) : null\n ]\n },\n child.key\n );\n }) }) : null\n ] }, item.key);\n })\n ] }, group.key)) })\n ] });\n}\nfunction Pill({ theme, label, tone = "muted" }) {\n const { colors } = theme;\n const color = tone === "accent" ? colors.accent : tone === "success" ? colors.statusSuccess : tone === "warning" ? colors.statusWarning : tone === "danger" ? colors.statusDanger : colors.foregroundMuted;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.View, { style: { borderRadius: 999, borderWidth: 1, borderColor: tone === "muted" ? colors.border : color, paddingHorizontal: 7, paddingVertical: 1, alignSelf: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: { color, fontSize: 11, fontWeight: "500" }, children: label }) });\n}\nfunction Button({ theme, label, onPress, kind = "plain", icon, disabled, accessibilityLabel }) {\n const { colors } = theme;\n const color = kind === "primary" ? colors.accentForeground : kind === "danger" ? colors.statusDanger : colors.foreground;\n return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(\n import_react_native4.Pressable,\n {\n accessibilityRole: "button",\n accessibilityLabel: accessibilityLabel ?? label,\n disabled,\n onPress,\n style: (state) => ({\n flexDirection: "row",\n alignItems: "center",\n gap: 6,\n borderRadius: 8,\n paddingHorizontal: 12,\n paddingVertical: 7,\n opacity: disabled ? 0.5 : 1,\n backgroundColor: kind === "primary" ? colors.accent : hovered2(state) ? colors.surface2 : colors.surface1,\n borderWidth: kind === "primary" ? 0 : 1,\n borderColor: kind === "danger" ? colors.statusDanger : colors.border\n }),\n children: [\n icon ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Icon, { name: icon, size: 14, color }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native4.Text, { style: { color, fontSize: 13, fontWeight: kind === "primary" ? "600" : "500" }, children: label })\n ]\n }\n );\n}\nfunction layoutStyles(theme) {\n const { colors } = theme;\n return {\n root: { flex: 1, flexDirection: "row", backgroundColor: colors.surface0, minHeight: 560, borderWidth: 1, borderColor: colors.border, borderRadius: 12, overflow: "hidden" },\n aside: { backgroundColor: colors.surface1, borderRightWidth: 1, borderRightColor: colors.border },\n asideOverlay: { height: "100%", shadowColor: "#000", shadowOpacity: 0.2, shadowRadius: 16 },\n asideHeader: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 12, paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: colors.border, gap: 8 },\n asideHeaderCollapsed: { justifyContent: "center", paddingHorizontal: 0 },\n asideTitleBox: { flex: 1, minWidth: 0 },\n asideTitle: { color: colors.foreground, fontSize: 14, fontWeight: "600" },\n asideSubtitle: { color: colors.foregroundMuted, fontSize: 11, marginTop: 1 },\n asideList: { paddingVertical: 8, gap: 10 },\n group: { gap: 1 },\n groupLabel: { color: colors.foregroundMuted, fontSize: 11, fontWeight: "600", letterSpacing: 0.4, textTransform: "uppercase", paddingHorizontal: 14, paddingBottom: 4 },\n groupRule: { height: 1, backgroundColor: colors.border, marginHorizontal: 12, marginBottom: 4 },\n item: { flexDirection: "row", alignItems: "center", gap: 10, marginHorizontal: 6, paddingHorizontal: 8, paddingVertical: 7, borderRadius: 7 },\n itemCollapsed: { justifyContent: "center", paddingHorizontal: 0 },\n itemOn: { backgroundColor: colors.surface2 },\n itemHover: { backgroundColor: colors.surface2 },\n itemBar: { position: "absolute", left: -6, top: 6, bottom: 6, width: 3, borderRadius: 2, backgroundColor: colors.accent },\n itemLabel: { flex: 1, color: colors.foreground, fontSize: 13 },\n itemLabelOn: { color: colors.foreground, fontWeight: "600" },\n count: { color: colors.foregroundMuted, fontSize: 11, fontVariant: ["tabular-nums"] },\n children: { marginLeft: 22, borderLeftWidth: 1, borderLeftColor: colors.border, marginVertical: 2, paddingLeft: 4 },\n child: { flexDirection: "row", alignItems: "center", gap: 8, marginRight: 6, paddingHorizontal: 8, paddingVertical: 5, borderRadius: 6 },\n childOn: { backgroundColor: colors.surface2 },\n childLabel: { flex: 1, color: colors.foreground, fontSize: 12.5 },\n childHint: { color: colors.foregroundMuted, fontSize: 11 },\n dot: { width: 6, height: 6, borderRadius: 3 },\n main: { flex: 1, minWidth: 0 },\n header: { borderBottomWidth: 1, borderBottomColor: colors.border, paddingHorizontal: 20, paddingTop: 14, gap: 10 },\n headerRow: { flexDirection: "row", alignItems: "center", gap: 10, minHeight: 32 },\n crumbs: { flex: 1, minWidth: 0, flexDirection: "row", alignItems: "center", gap: 8, flexWrap: "wrap" },\n crumb: { color: colors.foregroundMuted, fontSize: 13 },\n crumbSeparator: { color: colors.foregroundMuted, fontSize: 13, opacity: 0.6 },\n crumbCurrent: { color: colors.foreground, fontSize: 16, fontWeight: "600" },\n actions: { flexDirection: "row", gap: 8, alignItems: "center" },\n tabs: { flexDirection: "row", gap: 4 },\n tab: { paddingHorizontal: 10, paddingVertical: 8, borderBottomWidth: 2, borderBottomColor: "transparent" },\n tabOn: { borderBottomColor: colors.accent },\n tabText: { color: colors.foregroundMuted, fontSize: 13 },\n tabTextOn: { color: colors.foreground, fontSize: 13, fontWeight: "600" },\n tabCount: { color: colors.foregroundMuted, fontSize: 11 },\n body: { flex: 1 },\n bodyContent: { padding: 20, gap: 16 },\n footer: { flexDirection: "row", alignItems: "center", gap: 10, paddingHorizontal: 20, paddingVertical: 12, borderTopWidth: 1, borderTopColor: colors.border, backgroundColor: colors.surface1 },\n iconButton: { padding: 6, borderRadius: 6 },\n overlay: { position: "absolute", left: 0, top: 0, right: 0, bottom: 0, flexDirection: "row" },\n scrim: { flex: 1, backgroundColor: "rgba(0,0,0,0.25)" }\n };\n}\n\n// integrations/paseo/client/team-model-settings.tsx\nvar import_jsx_runtime3 = require("react/jsx-runtime");\nvar clone = (team) => JSON.parse(JSON.stringify(team));\nfunction TeamModelSettings({ team, theme, onChange }) {\n const readModels = (0, import_client2.useRpc)(libraryModels);\n const [models, setModels] = (0, import_react3.useState)([]);\n const [error, setError] = (0, import_react3.useState)("");\n const [customFields, setCustomFields] = (0, import_react3.useState)({});\n const setup = modelSetupFor(team, models);\n const mode = setup.mode;\n const preset = setup.preset ?? "mix";\n (0, import_react3.useEffect)(() => {\n let live = true;\n readModels({}).then((result) => {\n if (live) {\n setModels(result.models);\n setError("");\n }\n }).catch((cause) => {\n if (live) setError(String(cause.message ?? cause));\n });\n return () => {\n live = false;\n };\n }, [readModels]);\n const edit = (work) => {\n const next = clone(team);\n next.modelSetup = { mode: "custom" };\n work(next);\n onChange(next);\n setError("");\n };\n const selectPreset = (value) => {\n try {\n onChange(presetTeamModels(team, value, models));\n setCustomFields({});\n setError("");\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n }\n };\n const chooseModel = (label, value, set) => {\n const known = models.find((model) => model.id === value);\n const options = [...label.startsWith("oracle-") ? [] : [{ label: "Inherit", value: "" }], ...models.map((model) => ({ value: model.id, label: model.label }))];\n if (value && !known) options.push({ label: value, value });\n options.push({ label: "Custom model ID", value: "__custom" });\n return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSelect, { label: "Model", value: customFields[label] ? "__custom" : value, options, onValueChange: (id) => {\n setCustomFields((previous) => ({ ...previous, [label]: id === "__custom" }));\n if (id !== "__custom") edit((next) => set(next, id, models.find((model) => model.id === id)?.effort));\n } }),\n customFields[label] || value && !known ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsInput, { label: "Custom model ID", hint: "claude:model, codex:model, antigravity:model or acp:provider/model", initialValue: value, onChangeText: (id) => edit((next) => set(next, id.trim())) }, `${label}-custom`) : null\n ] });\n };\n const effort = (model, value, set) => {\n const known = models.find((choice) => choice.id === model);\n const values = known ? known.efforts : ["none", "off", "low", "medium", "high", "xhigh", "max", "ultra", "ultracode"];\n const options = [{ label: "Inherit", value: "" }, ...[.../* @__PURE__ */ new Set([...values, ...value ? [value] : []])].map((value2) => ({ label: value2, value: value2 }))];\n return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSelect, { label: "Effort", value, options, onValueChange: (value2) => edit((next) => set(next, value2)) });\n };\n const assign = (target, id, thinking) => {\n if (id) target.model = id;\n else delete target.model;\n if (thinking) target.thinking = thinking;\n else delete target.thinking;\n };\n const setEffort = (target, value) => {\n if (value) target.thinking = value;\n else delete target.thinking;\n };\n const lenses = team.oracleModels ?? ["claude:claude-fable-5-1", "codex:gpt-6-astra"];\n return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: "Model setup", children: [\n /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSelect, { label: "Mode", value: mode, options: [{ label: "Default presets", value: "default" }, { label: "Custom", value: "custom" }], onValueChange: (value) => value === "default" ? selectPreset(preset) : edit(() => {\n }) }),\n mode === "default" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSelect, { label: "Preset", value: preset, options: MODEL_PRESETS, onValueChange: selectPreset }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: "Save with template", hint: "Save writes these model choices into settings.json for this team immediately. Project template overrides still apply to Host templates." }),\n error ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native5.Text, { accessibilityRole: "alert", style: { color: theme?.colors.statusDanger }, children: error }) : null\n ] }),\n mode === "default" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: "Preset models", children: [\n Object.entries(team.members ?? {}).filter(([name]) => name !== "oracle").map(([name, member]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: name, hint: member.model }, name)),\n team.supervisor ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: "Supervisor", hint: team.supervisor.model }) : null,\n team.members?.oracle ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: "Oracle", hint: lenses.join(", ") }) : null\n ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react3.Fragment, { children: [\n Object.entries(team.members ?? {}).filter(([name]) => name !== "oracle").map(([name, member]) => {\n const config = member;\n return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: name === team.main ? `${name} \\xB7 main` : name, children: [\n chooseModel(name, config.model ?? "", (next, id, effort2) => assign(next.members[name], id, effort2)),\n effort(config.model ?? team.members[team.main]?.model ?? "", config.thinking ?? "", (next, value) => setEffort(next.members[name], value))\n ] }, name);\n }),\n team.supervisor ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: "Supervisor", children: [\n chooseModel("supervisor", team.supervisor.model ?? "", (next, id, effort2) => assign(next.supervisor, id, effort2)),\n effort(team.supervisor.model ?? "", team.supervisor.thinking ?? "", (next, value) => setEffort(next.supervisor, value))\n ] }) : null,\n team.members?.oracle ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [\n lenses.map((id, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui.SettingsSection, { title: `Oracle ${index + 1}`, children: [\n chooseModel(`oracle-${index}`, id, (next, value, effort2) => {\n next.oracleModels = [...lenses];\n next.oracleModels[index] = value;\n next.oracleThinking ?? (next.oracleThinking = {});\n delete next.oracleThinking[id];\n if (effort2) next.oracleThinking[value] = effort2;\n }),\n effort(id, team.oracleThinking?.[id] ?? team.oracleThinking?.[id.split(":")[0]] ?? "", (next, value) => {\n next.oracleThinking ?? (next.oracleThinking = {});\n delete next.oracleThinking[id.split(":")[0]];\n if (value) next.oracleThinking[id] = value;\n else delete next.oracleThinking[id];\n }),\n theme && lenses.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { theme, label: "Remove model", onPress: () => edit((next) => {\n next.oracleModels = lenses.filter((_, i) => i !== index);\n }) }) : null\n ] }, index)),\n theme ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { theme, label: "Add oracle model", onPress: () => edit((next) => {\n next.oracleModels = [...lenses, ""];\n setCustomFields((previous) => ({ ...previous, [`oracle-${lenses.length}`]: true }));\n }) }) : null\n ] }) : null\n ] }, "custom-models"),\n JSON.stringify(team).includes("antigravity:") ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsSection, { title: "Antigravity", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui.SettingsRow, { label: "Advisory roles", hint: \'Reviewer, Oracle and Supervisor require readOnlyMode: "instructions" in the Antigravity provider. Review copies and custom permission rules are unsupported.\' }) }) : null\n ] });\n}\n\n// integrations/paseo/client/library.tsx\nvar import_client3 = require("@getpaseo/plugin/client");\nvar import_react_native6 = require("@getpaseo/plugin/client/react-native");\nvar import_ui2 = require("@getpaseo/plugin/client/ui");\nvar import_react4 = require("react");\nvar import_react_native7 = require("react-native");\nvar import_jsx_runtime4 = require("react/jsx-runtime");\nvar KINDS = [\n { kind: "teams", title: "Teams", one: "team", icon: "Users", group: "Organisation" },\n { kind: "agents", title: "Agents", one: "agent", icon: "Bot", group: "Organisation" },\n { kind: "skills", title: "Skills", one: "skill", icon: "BookOpen", group: "Capabilities" },\n { kind: "mcp", title: "MCP servers", one: "MCP server", icon: "Plug", group: "Capabilities" },\n { kind: "hooks", title: "Hooks", one: "hook", icon: "Webhook", group: "Capabilities" },\n // ACP agents (ALPD \xA746): in the library only, so the project panel leaves them out.\n { kind: "providers", title: "Providers", one: "provider", icon: "Cpu", group: "Runtimes" }\n];\nvar shownIn = (scope) => KINDS.filter((item) => scope === "library" || item.kind !== "providers");\nvar kindOf = (kind) => KINDS.find((item) => item.kind === kind);\nvar HOOK_EVENTS = ["session.start", "turn.end", "assignment.start", "assignment.end", "handoff", "task.close", "merge"];\nvar BLOCKING_EVENTS = ["handoff", "task.close", "merge"];\nvar ROLES = ["lead", "peer", "advisor", "reviewer"];\nvar MODES = ["", "read-only", "workspace-write", "full-access"];\nvar NAME = /^[\\w.-]+$/;\nvar clone2 = (value) => JSON.parse(JSON.stringify(value));\nvar message = (cause) => cause instanceof Error ? cause.message : String(cause);\nvar sourceLabel = (source) => source === "builtin" ? "built-in" : source;\nvar sourceTone = (source) => source === "project" ? "warning" : source === "library" ? "accent" : "muted";\nvar LANGUAGES = [\n { label: "Ti\\u1EBFng Vi\\u1EC7t", value: "Vietnamese" },\n { label: "English", value: "English" },\n { label: "\\u65E5\\u672C\\u8A9E", value: "Japanese" },\n { label: "\\uD55C\\uAD6D\\uC5B4", value: "Korean" },\n { label: "\\u4E2D\\u6587", value: "Chinese" },\n { label: "Fran\\xE7ais", value: "French" },\n { label: "Deutsch", value: "German" },\n { label: "Espa\\xF1ol", value: "Spanish" }\n];\nfunction LibrarySettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library" });\n}\nfunction TeamsSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "teams", embedded: true });\n}\nfunction AgentsSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "agents", embedded: true });\n}\nfunction SkillsSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "skills", embedded: true });\n}\nfunction HooksSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "hooks", embedded: true });\n}\nfunction McpSettings({ theme, layout }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "library", initialKind: "mcp", embedded: true });\n}\nfunction ProjectLibraryPanel({ theme, layout, workspaceId }) {\n const directory = (0, import_client3.useWorkspace)(workspaceId, (workspace) => workspace.directory || workspace.projectRootPath);\n if (!directory) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: { padding: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: { color: theme.colors.foregroundMuted }, children: "This panel needs a workspace." }) });\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryManager, { theme, compact: layout.compact, scope: "project", directory });\n}\nfunction LibraryManager({ theme, compact, scope, directory, embedded = false, initialKind = "teams" }) {\n const list = (0, import_client3.useRpc)(libraryList);\n const get = (0, import_client3.useRpc)(libraryGet);\n const save = (0, import_client3.useRpc)(librarySave);\n const remove = (0, import_client3.useRpc)(libraryDelete);\n const duplicate = (0, import_client3.useRpc)(libraryDuplicate);\n const probe = (0, import_client3.useRpc)(libraryTest);\n const give = (0, import_client3.useRpc)(librarySkills);\n const readLanguage = (0, import_client3.useRpc)(languageGet);\n const writeLanguage = (0, import_client3.useRpc)(languageSet);\n const toast = (0, import_react_native6.useToast)();\n const [language, setLanguageState] = (0, import_react4.useState)(null);\n const [lists, setLists] = (0, import_react4.useState)({});\n const [where, setWhere] = (0, import_react4.useState)(null);\n const [error, setError] = (0, import_react4.useState)(null);\n const [selection, setSelection] = (0, import_react4.useState)({ kind: initialKind });\n const [entry, setEntry] = (0, import_react4.useState)(null);\n const [tick, setTick] = (0, import_react4.useState)(0);\n const refresh = (0, import_react4.useCallback)(() => setTick((value) => value + 1), []);\n const base = directory ? { directory } : {};\n (0, import_react4.useEffect)(() => {\n let live = true;\n Promise.all(KINDS.map(({ kind }) => list({ ...base, kind }).then((result) => [kind, result]))).then((results) => {\n if (!live) return;\n setLists(Object.fromEntries(results.map(([kind, result]) => [kind, result.entries])));\n setWhere({ projectRoot: results[0][1].projectRoot, library: results[0][1].library, ...results[0][1].readOnly ? { readOnly: results[0][1].readOnly } : {} });\n setError(null);\n }).catch((cause) => {\n if (live) setError(message(cause));\n });\n return () => {\n live = false;\n };\n }, [list, directory, tick]);\n (0, import_react4.useEffect)(() => {\n if (scope !== "library") return;\n let live = true;\n readLanguage({}).then((result) => {\n if (live) setLanguageState(result);\n }).catch((cause) => {\n if (live) setError(message(cause));\n });\n return () => {\n live = false;\n };\n }, [readLanguage, scope, tick]);\n (0, import_react4.useEffect)(() => {\n if (!selection.name || selection.creating) {\n setEntry(null);\n return;\n }\n let live = true;\n get({ ...base, kind: selection.kind, name: selection.name }).then((result) => {\n if (live) setEntry(result);\n }).catch((cause) => {\n if (live) {\n toast.error(message(cause));\n setSelection({ kind: selection.kind });\n }\n });\n return () => {\n live = false;\n };\n }, [selection, get, directory, tick]);\n const run = (0, import_react4.useCallback)((work, done) => __async(null, null, function* () {\n try {\n yield work();\n toast.show(done, { variant: "success" });\n refresh();\n return true;\n } catch (cause) {\n toast.error(message(cause));\n return false;\n }\n }), [toast, refresh]);\n const actions = {\n select: (next) => setSelection(next),\n duplicate: (kind, from, to) => run(() => duplicate({ ...base, kind, from, to, scope }), `Copied ${from} to ${to}`),\n // In the project panel: copy what applies into .alp/, or drop the project\'s copy.\n override: (kind, name) => run(() => duplicate({ ...base, kind, from: name, to: name, scope: "project" }), `${name} is now overridden in this project`),\n useLibrary: (kind, name) => run(() => remove({ ...base, kind, name, scope: "project" }), `${name} follows the library again`),\n save: (kind, name, content, revision, creating) => __async(null, null, function* () {\n try {\n const result = yield save({ ...base, kind, name, scope, content, revision });\n const synced = result.syncedProjects ?? 0;\n toast.show(`Saved ${name}${synced ? ` \\xB7 Updated settings in ${synced} project${synced === 1 ? "" : "s"}` : ""}`, { variant: "success" });\n if (result.syncErrors?.length) toast.error(`Template saved, but some project settings could not be updated: ${result.syncErrors.join("; ")}`);\n refresh();\n if (creating) setSelection({ kind, name });\n return true;\n } catch (cause) {\n toast.error(message(cause));\n return false;\n }\n }),\n giveSkills: (agent, skills) => run(() => give({ agent, skills }), `Saved the skills of ${agent}`),\n setLanguage: (next) => run(() => writeLanguage({ language: next }), next ? `Agents now write to you in ${next}` : "Agents write to you in the default language again"),\n remove: (kind, name, revision) => __async(null, null, function* () {\n const removed = yield run(() => remove({ ...base, kind, name, scope, ...revision ? { revision } : {} }), `Removed ${name}`);\n if (removed) setSelection({ kind });\n return removed;\n }),\n test: (kind, name) => __async(null, null, function* () {\n try {\n return yield probe({ ...base, kind, name });\n } catch (cause) {\n toast.error(message(cause));\n return null;\n }\n })\n };\n const shown = selection.name && !selection.creating && entry?.name !== selection.name ? { kind: selection.kind } : selection;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LibraryWorkspace, { theme, compact, scope, where, lists, error, selection: shown, entry: shown.name ? entry : null, actions, language, embedded });\n}\nfunction navGroups(scope, lists) {\n const groups = scope === "library" ? [{ key: "General", label: "General", items: [{ key: "language", label: "Language", icon: "Languages" }] }] : [];\n for (const item of shownIn(scope)) {\n let group = groups.find((candidate) => candidate.label === item.group);\n if (!group) groups.push(group = { key: item.group, label: item.group, items: [] });\n const rows = lists[item.kind];\n group.items.push({\n key: item.kind,\n label: item.title,\n icon: item.icon,\n ...rows ? { count: rows.length } : {},\n children: (rows ?? []).map((row) => ({ key: row.name, label: row.name, tone: sourceTone(row.source) }))\n });\n }\n return groups;\n}\nfunction LibraryWorkspace({ theme, compact, scope, where, lists, error, selection, entry, actions, initialCollapsed, language, embedded }) {\n const styles = (0, import_react4.useMemo)(() => makeStyles2(theme, compact), [theme, compact]);\n const title = scope === "library" ? "ALP library" : "ALP project";\n const subtitle = scope === "library" ? where?.library : where?.projectRoot ?? void 0;\n const groups = navGroups(scope, lists);\n const onSelect = (kind2, name) => actions.select(kind2 === "language" ? { kind: kind2 } : { kind: kind2, ...name ? { name } : {} });\n if (scope === "project" && where?.readOnly?.unlisted) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.screen, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: where.readOnly.unlisted }) });\n }\n if (scope === "project" && where && !where.projectRoot) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.screen, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "This workspace is not an ALP project. Run alp init to start one." }) });\n }\n if (selection.kind === "language") {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LanguageSettings, { theme, compact, language: language ?? null, error, actions, layout: { title, subtitle, groups, onSelect, initialCollapsed, embedded }, styles });\n }\n const kind = kindOf(selection.kind);\n if (where?.readOnly && (selection.name || selection.creating)) {\n const viewed = !where.readOnly.unlisted && entry && entry.name === selection.name && entry.kind === selection.kind ? entry : null;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(\n SideNavLayout,\n {\n theme,\n compact,\n title,\n subtitle,\n groups,\n active: { item: selection.kind, ...selection.name ? { child: selection.name } : {} },\n onSelect,\n initialCollapsed,\n embedded,\n breadcrumb: [kind.title, selection.name ?? "Read only"],\n badges: viewed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: sourceLabel(viewed.source), tone: sourceTone(viewed.source) }) : null,\n actions: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, icon: "ArrowLeft", label: `All ${kind.title.toLowerCase()}`, onPress: () => actions.select({ kind: selection.kind }) }),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: where.readOnly.reason }),\n error || where.readOnly.unlisted ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: error ?? where.readOnly.unlisted }) : selection.creating ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "Create entries on the ALP host." }) : !viewed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "Loading\\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n viewed.overrides ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.small, children: [\n "Overrides ",\n sourceLabel(viewed.overrides),\n "."\n ] }) : null,\n viewed.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.small, children: [\n "Used by ",\n viewed.usedBy.join(", "),\n "."\n ] }) : null,\n viewed.librarySkills?.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.small, children: [\n "Library skills: ",\n viewed.librarySkills.join(", "),\n "."\n ] }) : null,\n viewed.secrets?.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.muted, children: [\n "Secrets hidden: ",\n viewed.secrets.join(", "),\n ". Secret markers stand for values kept on the ALP host."\n ] }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { selectable: true, style: styles.small, children: JSON.stringify(viewed.content, null, 2) })\n ] })\n ]\n }\n );\n }\n if (selection.name || selection.creating) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(\n EntryEditor,\n {\n theme,\n compact,\n scope,\n kind: selection.kind,\n entry: selection.creating ? null : entry,\n lists,\n actions,\n layout: { title, subtitle, groups, onSelect, initialCollapsed, embedded }\n },\n `${selection.kind}/${selection.name ?? "new"}/${entry?.revision ?? "new"}/${(entry?.librarySkills ?? []).join(",")}`\n );\n }\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(KindOverview, { theme, compact, scope, kind: kind.kind, rows: lists[kind.kind], error, where, actions, layout: { title, subtitle, groups, onSelect, initialCollapsed, embedded }, styles });\n}\nvar OTHER = "other";\nfunction LanguageSettings({ theme, compact, language, error, actions, layout, styles }) {\n const named = language && LANGUAGES.some((option) => option.value === language.applies);\n const [choice, setChoice] = (0, import_react4.useState)(null);\n const [typed, setTyped] = (0, import_react4.useState)("");\n const shown = choice ?? (language ? named ? language.applies : OTHER : "");\n const typedValid = typed.trim().length > 0 && typed.trim().length <= 40;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(\n SideNavLayout,\n {\n theme,\n compact,\n title: layout.title,\n subtitle: layout.subtitle,\n groups: layout.groups,\n active: { item: "language" },\n onSelect: layout.onSelect,\n initialCollapsed: layout.initialCollapsed,\n embedded: layout.embedded,\n breadcrumb: ["Library", "Language"],\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "The language you read. Main writes its replies, questions, approval requests and task titles in it, other agents put their questions to you in it, and ALP asks for approvals and writes its notices in it. Agents may talk among themselves in any language." }),\n error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.danger, children: error }) : null,\n !language && !error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "Loading\\u2026" }) : null,\n language?.readOnly ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Language", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.name, children: [\n language.applies,\n language.language ? "" : " (default)"\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: language.readOnly })\n ] }) : !language ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Language", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(\n import_ui2.SettingsSelect,\n {\n label: "Language",\n hint: language.language ? `Set in your settings.json` : `Not set: ${language.default} applies`,\n value: shown,\n options: [...LANGUAGES, { label: named || !language.language ? "Other\\u2026" : `${language.applies} (other)`, value: OTHER }],\n onValueChange: (value) => __async(null, null, function* () {\n setChoice(value);\n if (value !== OTHER && (yield actions.setLanguage(value))) setChoice(null);\n })\n }\n ),\n shown === OTHER ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Other language", hint: "Its name in English, such as Thai or Indonesian", initialValue: named ? "" : language.language ?? "", placeholder: "Thai", onChangeText: setTyped }) : null,\n shown === OTHER ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsAction, { label: "Use this language", actionLabel: "Save", disabled: !typedValid, onPress: () => __async(null, null, function* () {\n if (typedValid && (yield actions.setLanguage(typed.trim()))) setChoice(null);\n }) }) : null,\n language.language ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsAction, { label: `Use the default (${language.default})`, hint: "Removes the setting", actionLabel: "Reset", onPress: () => __async(null, null, function* () {\n if (yield actions.setLanguage(null)) setChoice(null);\n }) }) : null\n ] })\n ]\n }\n );\n}\nvar SOURCES = [{ key: "all", label: "All" }, { key: "builtin", label: "Built-in" }, { key: "library", label: "Library" }, { key: "project", label: "Project" }];\nfunction KindOverview({ theme, compact, scope, kind, rows, error, where, actions, layout, styles }) {\n const { title, one } = kindOf(kind);\n const [filter, setFilter] = (0, import_react4.useState)("all");\n const [copying, setCopying] = (0, import_react4.useState)(null);\n const [copyName, setCopyName] = (0, import_react4.useState)("");\n const tabs = SOURCES.map((source) => ({ ...source, count: (rows ?? []).filter((row) => source.key === "all" || row.source === source.key).length })).filter((tab) => tab.key === "all" || tab.count);\n const shown = (rows ?? []).filter((row) => filter === "all" || row.source === filter);\n const readOnly = where?.readOnly;\n const intro = readOnly ? `The ${title.toLowerCase()} ${scope === "project" ? "this project uses on the ALP host" : "of the ALP host"}, by name.` : kind === "providers" ? "Agents that speak the Agent Client Protocol. They live in your library only." : scope === "library" ? "Every project uses your library. Built-ins follow ALP updates; saving one makes your own copy of that name." : "What this project overrides. Override an entry to change it here only; Use library drops the project\'s copy.";\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(\n SideNavLayout,\n {\n theme,\n compact,\n title: layout.title,\n subtitle: layout.subtitle,\n groups: layout.groups,\n active: { item: kind },\n onSelect: layout.onSelect,\n initialCollapsed: layout.initialCollapsed,\n embedded: layout.embedded,\n breadcrumb: layout.embedded ? [] : [scope === "library" ? "Library" : "Project", title],\n tabs,\n tab: filter,\n onTab: setFilter,\n actions: readOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, kind: "primary", icon: "Plus", label: `New ${one}`, onPress: () => actions.select({ kind, creating: true }) }),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: intro }),\n readOnly ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: readOnly.reason }) : null,\n error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.danger, children: error }) : null,\n !rows && !error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: "Loading\\u2026" }) : null,\n readOnly?.unlisted ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.empty, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, children: readOnly.unlisted }) }) : rows && !shown.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.empty, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.muted, children: [\n "No ",\n title.toLowerCase(),\n " ",\n filter === "all" ? "yet" : `from the ${sourceLabel(filter)}`,\n "."\n ] }) }) : null,\n shown.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: styles.table, children: shown.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: [styles.tableRow, index ? styles.tableRowRule : null], children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Pressable, { accessibilityRole: "button", accessibilityLabel: `Open ${one} ${row.name}`, onPress: () => actions.select({ kind, name: row.name }), style: styles.rowMain, children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: styles.rowTitle, children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.name, children: row.name }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: sourceLabel(row.source), tone: sourceTone(row.source) }),\n row.overrides ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: `overrides ${sourceLabel(row.overrides)}` }) : null\n ] }),\n row.description ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.muted, numberOfLines: 2, children: row.description }) : null,\n row.usedBy?.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.small, numberOfLines: 1, children: [\n "Used by ",\n row.usedBy.join(", ")\n ] }) : null\n ] }),\n readOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: [styles.rowActions, compact ? styles.rowActionsCompact : null], children: [\n scope === "project" && row.source === "project" && row.overrides ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, label: "Use library", onPress: () => actions.useLibrary(kind, row.name) }) : null,\n scope === "project" && row.source !== "project" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, label: "Override in this project", onPress: () => actions.override(kind, row.name) }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, icon: "Copy", label: "Duplicate", accessibilityLabel: `Duplicate ${one} ${row.name}`, onPress: () => {\n setCopying(row.name);\n setCopyName(`${row.name}-copy`);\n } })\n ] }),\n copying === row.name ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: styles.copyRow, children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.TextInput, { style: styles.input, value: copyName, onChangeText: setCopyName, accessibilityLabel: "Name of the copy", placeholder: "Name of the copy", placeholderTextColor: theme.colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, kind: "primary", label: "Copy", onPress: () => __async(null, null, function* () {\n if (NAME.test(copyName) && (yield actions.duplicate(kind, row.name, copyName))) setCopying(null);\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, label: "Cancel", onPress: () => setCopying(null) })\n ] }) : null\n ] }, row.name)) }) : null\n ]\n }\n );\n}\nfunction blank(kind, name = "new") {\n if (kind === "agents") return { instructions: `# ${name}\n\nDescribe what this agent does, and how.\n`, config: {} };\n if (kind === "skills") return { body: `---\nname: ${name}\ndescription: When to use this skill.\n---\n\n# ${name}\n\nSteps and checks.\n` };\n if (kind === "mcp") return { server: { command: "" } };\n if (kind === "hooks") return { hook: { event: "handoff", command: "", blocking: false } };\n if (kind === "providers") return { provider: { kind: "acp", label: name, command: "" } };\n return { team: { label: name, main: "main", members: { main: {} }, delegation: {}, supervisor: false }, houseRules: "" };\n}\nfunction entryTabs(kind, saved) {\n const tabs = {\n agents: [["general", "General"], ["instructions", "Instructions"], ["capabilities", "Skills, MCP & hooks"]],\n teams: [["models", "Models & effort"], ["general", "General"], ["members", "Members"], ["delegation", "Delegation"], ["supervisor", "Supervisor"], ["rules", "House rules"]],\n skills: [["body", "SKILL.md"]],\n mcp: [["server", "Server"], ["test", "Test"]],\n hooks: [["hook", "Hook"], ["test", "Test"]],\n providers: [["agent", "ACP agent"], ["test", "Test"]]\n };\n return tabs[kind].filter(([key]) => key !== "test" || saved).map(([key, label]) => ({ key, label }));\n}\nfunction EntryEditor({ theme, compact, scope, kind, entry, lists, actions, layout, initialTab }) {\n const styles = (0, import_react4.useMemo)(() => makeStyles2(theme, compact), [theme, compact]);\n const { one, title } = kindOf(kind);\n const tabs = entryTabs(kind, !!entry);\n const [tab, setTab] = (0, import_react4.useState)(initialTab && tabs.some((candidate) => candidate.key === initialTab) ? initialTab : tabs[0].key);\n const [name, setName] = (0, import_react4.useState)(entry?.name ?? "");\n const original = (0, import_react4.useMemo)(() => clone2(entry?.content ?? blank(kind)), [entry, kind]);\n const [content, setContent] = (0, import_react4.useState)(() => clone2(original));\n const [result, setResult] = (0, import_react4.useState)(null);\n const own = entry?.source === scope;\n const update = (change) => setContent((current) => {\n const draft = clone2(current);\n change(draft);\n return draft;\n });\n const valid = NAME.test(name);\n const changed = !entry || JSON.stringify(content) !== JSON.stringify(original);\n const givenOriginal = (0, import_react4.useMemo)(() => entry?.librarySkills ?? [], [entry]);\n const [given, setGiven] = (0, import_react4.useState)(givenOriginal);\n const givesSkills = kind === "agents" && scope === "library";\n const givenChanged = givesSkills && [...given].sort().join() !== [...givenOriginal].sort().join();\n const dirty = changed || givenChanged;\n const onSave = () => __async(null, null, function* () {\n if (!valid) return;\n if (changed && !(yield actions.save(kind, name, content, own ? entry.revision : null, !entry))) return;\n if (givenChanged) yield actions.giveSkills(name, given);\n });\n const note = entry ? entry.source === "builtin" ? `Built into ALP. Saving makes ${scope === "library" ? "your library\'s" : "this project\'s"} own ${entry.name}, which overrides it.` : own ? `In ${scope === "library" ? "your library" : "this project"}${entry.overrides ? `; overrides the ${sourceLabel(entry.overrides)} one` : ""}.` : `From the ${sourceLabel(entry.source)}. Saving makes this project\'s own copy.` : null;\n const form = { content, update, lists, styles, theme };\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(\n SideNavLayout,\n {\n theme,\n compact,\n title: layout.title,\n subtitle: layout.subtitle,\n groups: layout.groups,\n active: { item: kind, ...entry ? { child: entry.name } : {} },\n onSelect: layout.onSelect,\n initialCollapsed: layout.initialCollapsed,\n embedded: layout.embedded,\n breadcrumb: [title, entry ? entry.name : `New ${one}`],\n badges: entry ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: sourceLabel(entry.source), tone: sourceTone(entry.source) }),\n entry.overrides ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pill, { theme, label: `overrides ${sourceLabel(entry.overrides)}` }) : null\n ] }) : null,\n actions: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, icon: "ArrowLeft", label: `All ${title.toLowerCase()}`, onPress: () => actions.select({ kind }) }),\n tabs,\n tab,\n onTab: setTab,\n footer: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, kind: "primary", label: entry && entry.source === "builtin" && (changed || !givenChanged) ? "Save as my own" : "Save", disabled: !valid || !dirty, onPress: () => {\n void onSave();\n } }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.small, children: !valid ? "Name the entry first" : dirty ? "Unsaved changes" : own ? "Saved" : "No changes" }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.View, { style: { flex: 1 } }),\n entry && own ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { theme, kind: "danger", label: entry.overrides ? `Remove (the ${sourceLabel(entry.overrides)} one applies again)` : "Remove", onPress: () => actions.remove(kind, entry.name, entry.revision) }) : null\n ] }),\n children: [\n note || entry?.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { style: styles.banner, children: [\n note ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.bannerText, children: note }) : null,\n entry?.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.small, children: [\n "Used by ",\n entry.usedBy.join(", "),\n "."\n ] }) : null\n ] }) : null,\n !entry && tab === tabs[0].key ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSection, { title: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Name", hint: "Letters, digits, \'.\', \'_\' or \'-\'", error: name && !valid ? "Not a valid name" : null, initialValue: name, onChangeText: setName }) }) : null,\n kind === "agents" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AgentForm, { ...form, tab, given: entry?.librarySkills ?? [], ...givesSkills ? { draftGiven: given, setGiven } : {} }) : null,\n kind === "teams" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TeamForm, { ...form, tab }) : null,\n kind === "skills" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Multiline, { value: content.body ?? "", onChange: (text) => update((draft) => {\n draft.body = text;\n }), styles, theme, label: "SKILL.md", tall: true }) : null,\n kind === "mcp" && tab === "server" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(McpForm, { content, update }) : null,\n kind === "hooks" && tab === "hook" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HookForm, { content, update, lists }) : null,\n kind === "providers" && tab === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ProviderForm, { content, update }) : null,\n tab === "test" && entry ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Test", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsAction, { label: kind === "mcp" ? "Start the server and list its tools" : kind === "providers" ? "Start the agent and ask what it supports" : "Run once with a sample event", hint: "The test runs what is saved.", actionLabel: "Test", onPress: () => __async(null, null, function* () {\n return setResult(yield actions.test(kind, entry.name));\n }) }),\n result ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TestResult, { kind, result, styles }) : null\n ] }) : null\n ]\n }\n );\n}\nvar names = (lists, kind) => (lists[kind] ?? []).map((row) => row.name);\nvar toggle = (list, name, on) => {\n const set = new Set(list ?? []);\n if (on) set.add(name);\n else set.delete(name);\n return [...set];\n};\nvar setOrDelete = (target, key, value) => {\n if (value === "" || value === void 0 || Array.isArray(value) && !value.length) delete target[key];\n else target[key] = value;\n};\nvar CONTEXT_SIZES = [2e5, 4e5, 6e5, 1e6];\nvar contextOptions = (current) => [\n { label: "Auto (the model\'s)", value: "" },\n ...[.../* @__PURE__ */ new Set([...CONTEXT_SIZES, ...typeof current === "number" ? [current] : []])].sort((a, b) => a - b).map((tokens) => ({ label: tokens >= 1e6 ? `${tokens / 1e6}M tokens` : `${Math.round(tokens / 1e3)}k tokens`, value: String(tokens) }))\n];\nfunction AgentForm({ content, update, lists, styles, theme, tab, given = [], draftGiven, setGiven }) {\n const config = content.config ?? {};\n const field = (key) => (text) => update((draft) => {\n draft.config ?? (draft.config = {});\n setOrDelete(draft.config, key, text.trim());\n });\n const show = (key) => !tab || tab === key;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n show("general") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Agent", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Description", initialValue: config.description ?? "", onChangeText: field("description") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Provider", hint: "The team or project settings may choose another", value: config.provider ?? "", options: [{ label: "Default", value: "" }, { label: "Codex", value: "codex" }, { label: "Claude Code", value: "claude" }, ...names(lists, "providers").map((provider) => ({ label: `${provider} (ACP)`, value: provider }))], onValueChange: field("provider") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Model", hint: "Such as claude:claude-sonnet-5-5, codex:gpt-6-sol or acp:gemini", initialValue: config.model ?? "", onChangeText: field("model") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Thinking", hint: "Effort, such as low, medium or high", initialValue: config.thinking ?? "", onChangeText: field("thinking") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(\n import_ui2.SettingsSelect,\n {\n label: "Context",\n hint: "How much context it works with before the runtime compacts it",\n value: typeof config.context === "number" ? String(config.context) : "",\n options: contextOptions(config.context),\n onValueChange: (value) => update((draft) => {\n draft.config ?? (draft.config = {});\n setOrDelete(draft.config, "context", value ? Number(value) : "");\n })\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Default mode", value: config.mode ?? "", options: MODES.map((mode) => ({ label: mode || "As its requester chooses", value: mode })), onValueChange: field("mode") })\n ] }) : null,\n show("instructions") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Multiline, { value: content.instructions ?? "", onChange: (text) => update((draft) => {\n draft.instructions = text;\n }), styles, theme, label: "AGENT.md", tall: true }) : null,\n show("capabilities") ? ["skills", "mcp", "hooks"].map((kind) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: kindOf(kind).title, children: [\n !names(lists, kind).length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsRow, { label: `No ${kindOf(kind).title.toLowerCase()} to choose from yet` }) : null,\n names(lists, kind).map((name) => {\n const own = (config[kind] ?? []).includes(name);\n const configToggle = (on) => update((draft) => {\n draft.config ?? (draft.config = {});\n setOrDelete(draft.config, kind, toggle(draft.config[kind], name, on));\n });\n if (kind !== "skills") return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: name, value: own, onValueChange: configToggle }, name);\n if (setGiven) {\n const library = (draftGiven ?? given).includes(name);\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(\n import_ui2.SettingsSwitch,\n {\n label: name,\n hint: given.includes(name) ? "Default for this agent" : void 0,\n value: library || own,\n onValueChange: (on) => {\n setGiven(toggle(draftGiven ?? given, name, on));\n if (!on && own) configToggle(false);\n }\n },\n name\n );\n }\n if (given.includes(name)) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: name, hint: "Given by your library; change it in Settings \\u2192 ALP", value: true, disabled: true, onValueChange: () => {\n } }, name);\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: name, value: own, onValueChange: configToggle }, name);\n })\n ] }, kind)) : null\n ] });\n}\nfunction withMember(team, agent, on) {\n const next = clone2(team);\n next.members ?? (next.members = {});\n next.delegation ?? (next.delegation = {});\n if (on) {\n next.members[agent] = { role: "peer" };\n return next;\n }\n delete next.members[agent];\n delete next.delegation[agent];\n for (const owner of Object.keys(next.delegation)) {\n next.delegation[owner] = next.delegation[owner].filter((target) => target !== agent);\n if (!next.delegation[owner].length) delete next.delegation[owner];\n }\n return next;\n}\nfunction withDelegation(team, owner, target, on) {\n const next = clone2(team);\n next.delegation ?? (next.delegation = {});\n const targets = toggle(next.delegation[owner], target, on);\n if (targets.length) next.delegation[owner] = targets;\n else delete next.delegation[owner];\n return next;\n}\nvar EFFORTS = ["", "none", "low", "medium", "high", "xhigh", "max"];\nvar effortOptions = EFFORTS.map((value) => ({ label: value || "Inherit", value }));\nfunction TeamModels({ content, update, theme }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TeamModelSettings, { team: content.team ?? {}, theme, onChange: (next) => update((draft) => {\n draft.team = next;\n }) });\n}\nfunction TeamForm({ content, update, lists, styles, theme, tab }) {\n const show = (key) => !tab || tab === key;\n const team = content.team ?? {};\n const agents = names(lists, "agents");\n const members = Object.keys(team.members ?? {});\n const others = members.filter((member) => member !== team.main);\n const cycle = delegationCycle(team.delegation ?? {});\n const text = (key) => (value) => update((draft) => {\n setOrDelete(draft.team, key, value.trim());\n });\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n show("models") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TeamModels, { content, update, lists, styles, theme }) : null,\n show("general") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Team", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Label", hint: "Shown in the model picker", initialValue: team.label ?? "", onChangeText: text("label") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Description", initialValue: team.description ?? "", onChangeText: text("description") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Most peers at once", initialValue: team.maxPeers === void 0 ? "" : String(team.maxPeers), onChangeText: (value) => update((draft) => {\n setOrDelete(draft.team, "maxPeers", value.trim() ? Number(value) : "");\n }) })\n ] }) : null,\n show("members") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: [team.main, ...agents.filter((agent) => agent !== team.main && agent !== team.supervisor?.agent)].filter(Boolean).map((agent) => {\n const member = team.members?.[agent];\n const main = agent === team.main;\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: main ? `${agent} \\xB7 main` : agent, info: main ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.small, children: "The agent you talk with." }) : void 0, children: [\n !main ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: "In this team", value: !!member, onValueChange: (on) => update((draft) => {\n draft.team = withMember(draft.team, agent, on);\n }) }) : null,\n member && !main ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Role", value: member.role ?? "peer", options: ROLES.map((role) => ({ label: role, value: role })), onValueChange: (role) => update((draft) => {\n draft.team.members[agent].role = role;\n }) }) : null\n ] }, agent);\n }) }) : null,\n show("delegation") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n cycle ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.danger, children: [\n "Cycle at ",\n cycle,\n ": ALP refuses it"\n ] }) : null,\n members.map((owner) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: `${owner} may delegate to`, info: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.small, children: (team.delegation?.[owner] ?? []).join(", ") || "no one" }), children: [\n others.filter((target) => target !== owner).map((target) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: target, value: (team.delegation?.[owner] ?? []).includes(target), onValueChange: (on) => update((draft) => {\n draft.team = withDelegation(draft.team, owner, target, on);\n }) }, `${owner}-${target}`)),\n !others.filter((target) => target !== owner).length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsRow, { label: "No other members" }) : null\n ] }, owner))\n ] }) : null,\n show("supervisor") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Supervisor", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: "Review main\'s process after each turn", value: !!team.supervisor, onValueChange: (on) => update((draft) => {\n draft.team.supervisor = on ? { agent: "supervisor" } : false;\n }) }),\n team.supervisor ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Supervisor agent", value: team.supervisor.agent, options: agents.filter((agent) => !members.includes(agent)).map((agent) => ({ label: agent, value: agent })), onValueChange: (agent) => update((draft) => {\n draft.team.supervisor.agent = agent;\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsRow, { label: "Model & effort", hint: "Configure in Models & effort" })\n ] }) : null\n ] }) : null,\n show("rules") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Multiline, { value: content.houseRules ?? "", onChange: (value) => update((draft) => {\n draft.houseRules = value;\n }), styles, theme, label: "House rules", placeholder: "The team\'s rules and process, which every member reads (HOUSE_RULES.md)", tall: true }) : null\n ] });\n}\nfunction delegationCycle(graph) {\n const visiting = /* @__PURE__ */ new Set();\n const done = /* @__PURE__ */ new Set();\n const visit = (owner) => {\n if (visiting.has(owner)) return owner;\n if (done.has(owner)) return null;\n visiting.add(owner);\n for (const target of graph[owner] ?? []) {\n const found = visit(target);\n if (found) return found;\n }\n visiting.delete(owner);\n done.add(owner);\n return null;\n };\n for (const owner of Object.keys(graph)) {\n const found = visit(owner);\n if (found) return found;\n }\n return null;\n}\nvar lines = (text) => text.split("\\n").map((line) => line.trim()).filter(Boolean);\nvar pairs = (text) => Object.fromEntries(lines(text).filter((line) => line.includes("=")).map((line) => [line.slice(0, line.indexOf("=")).trim(), line.slice(line.indexOf("=") + 1).trim()]));\nvar unpairs = (map) => Object.entries(map ?? {}).map(([key, value]) => `${key}=${value}`).join("\\n");\nfunction McpForm({ content, update }) {\n const server = content.server ?? {};\n const http = server.url !== void 0;\n const set = (key, value) => update((draft) => {\n setOrDelete(draft.server, key, value);\n });\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Server", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Transport", value: http ? "http" : "stdio", options: [{ label: "Command (stdio)", value: "stdio" }, { label: "URL (HTTP)", value: "http" }], onValueChange: (kind) => update((draft) => {\n draft.server = kind === "http" ? { url: "" } : { command: "" };\n }) }),\n http ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "URL", initialValue: server.url ?? "", onChangeText: (value) => update((draft) => {\n draft.server.url = value.trim();\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Headers", hint: "Name=value, separated by \';\'", initialValue: unpairs(server.headers).replaceAll("\\n", "; "), onChangeText: (value) => set("headers", Object.keys(pairs(value.replaceAll(";", "\\n"))).length ? pairs(value.replaceAll(";", "\\n")) : void 0) })\n ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Command", initialValue: server.command ?? "", onChangeText: (value) => update((draft) => {\n draft.server.command = value.trim();\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Arguments", hint: "Separated by spaces", initialValue: (server.args ?? []).join(" "), onChangeText: (value) => set("args", value.split(/\\s+/).filter(Boolean)) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Environment", hint: "NAME=value, separated by \';\'", initialValue: unpairs(server.env).replaceAll("\\n", "; "), onChangeText: (value) => set("env", Object.keys(pairs(value.replaceAll(";", "\\n"))).length ? pairs(value.replaceAll(";", "\\n")) : void 0) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Working directory", hint: "Relative to the mcp directory", initialValue: server.cwd ?? "", onChangeText: (value) => set("cwd", value.trim()) })\n ] })\n ] });\n}\nfunction ProviderForm({ content, update }) {\n const provider = content.provider ?? {};\n const set = (key, value) => update((draft) => {\n draft.provider ?? (draft.provider = { kind: "acp" });\n setOrDelete(draft.provider, key, value);\n });\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "ACP agent", info: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { children: "Any agent that speaks the Agent Client Protocol on stdio. ALP answers its permission requests by the session\'s mode; it cannot steer it mid-turn or sandbox its commands." }), children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Label", initialValue: provider.label ?? "", onChangeText: (value) => set("label", value.trim()) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Description", initialValue: provider.description ?? "", onChangeText: (value) => set("description", value.trim()) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Command", hint: "Such as gemini, or an absolute path", initialValue: provider.command ?? "", onChangeText: (value) => update((draft) => {\n draft.provider.command = value.trim();\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Arguments", hint: "Separated by spaces, such as --experimental-acp", initialValue: (provider.args ?? []).join(" "), onChangeText: (value) => set("args", value.split(/\\s+/).filter(Boolean)) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Environment", hint: "NAME=value, separated by \';\'", initialValue: unpairs(provider.env).replaceAll("\\n", "; "), onChangeText: (value) => set("env", Object.keys(pairs(value.replaceAll(";", "\\n"))).length ? pairs(value.replaceAll(";", "\\n")) : void 0) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Models", hint: "Ids the agent offers, separated by \',\'; empty lets any through", initialValue: (provider.models ?? []).map((model) => model.id).join(", "), onChangeText: (value) => set("models", value.split(",").map((id) => id.trim()).filter(Boolean).map((id) => (provider.models ?? []).find((model) => model.id === id) ?? { id })) })\n ] });\n}\nfunction HookForm({ content, update, lists }) {\n const hook = content.hook ?? {};\n const set = (key, value) => update((draft) => {\n setOrDelete(draft.hook, key, value);\n });\n const blocking = BLOCKING_EVENTS.includes(hook.event);\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui2.SettingsSection, { title: "Hook", children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Event", value: hook.event ?? "handoff", options: HOOK_EVENTS.map((event) => ({ label: event, value: event })), onValueChange: (event) => update((draft) => {\n draft.hook.event = event;\n if (!BLOCKING_EVENTS.includes(event)) delete draft.hook.blocking;\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Command", hint: "Runs in the session\'s directory; the event arrives as JSON on stdin", initialValue: hook.command ?? "", onChangeText: (value) => update((draft) => {\n draft.hook.command = value;\n }) }),\n blocking ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSwitch, { label: "Block the action when it fails", hint: "Its stderr becomes the reason the agent reads", value: !!hook.blocking, onValueChange: (on) => set("blocking", on || void 0) }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Timeout (seconds)", initialValue: hook.timeoutSec === void 0 ? "" : String(hook.timeoutSec), onChangeText: (value) => set("timeoutSec", value.trim() ? Number(value) : "") }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsSelect, { label: "Only for agent", value: hook.match?.agent ?? "", options: [{ label: "Every agent", value: "" }, ...names(lists, "agents").map((agent) => ({ label: agent, value: agent }))], onValueChange: (agent) => update((draft) => {\n var _a;\n (_a = draft.hook).match ?? (_a.match = {});\n setOrDelete(draft.hook.match, "agent", agent);\n if (!Object.keys(draft.hook.match).length) delete draft.hook.match;\n }) }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui2.SettingsInput, { label: "Only for tasks labeled", initialValue: hook.match?.label ?? "", onChangeText: (label) => update((draft) => {\n var _a;\n (_a = draft.hook).match ?? (_a.match = {});\n setOrDelete(draft.hook.match, "label", label.trim());\n if (!Object.keys(draft.hook.match).length) delete draft.hook.match;\n }) })\n ] });\n}\nfunction TestResult({ kind, result, styles }) {\n if (kind === "providers") {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.success, children: [\n result.agent?.title ?? result.agent?.name ?? "The agent",\n result.agent?.version ? ` ${result.agent.version}` : "",\n " speaks ACP ",\n result.protocolVersion\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.muted, children: [\n result.loadSession ? "Resumes sessions" : "Cannot resume sessions",\n result.mcpHttp ? "; takes HTTP MCP servers" : "; takes stdio MCP servers only",\n result.authMethods?.length ? `; signs in with ${result.authMethods.join(", ")}` : ""\n ] })\n ] });\n }\n if (kind === "mcp") {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.success, children: [\n result.server?.name ?? "The server",\n result.server?.version ? ` ${result.server.version}` : "",\n " offers ",\n result.tools?.length ?? 0,\n " tools"\n ] }),\n (result.tools ?? []).map((tool) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: styles.muted, children: [\n tool.name,\n tool.description ? ` \\u2014 ${tool.description.split("\\n")[0]}` : ""\n ] }, tool.name))\n ] });\n }\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.View, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native7.Text, { style: result.ok ? styles.success : styles.danger, children: [\n result.timedOut ? "Timed out" : `Exit ${result.exitCode ?? result.signal}`,\n " in ",\n result.durationMs,\n " ms",\n result.wouldBlock ? "; as a blocking hook it would refuse the action" : ""\n ] }),\n result.stdout ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.code, children: result.stdout }) : null,\n result.stderr ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.Text, { style: styles.code, children: result.stderr }) : null\n ] });\n}\nfunction Multiline({ value, onChange, styles, theme, label, placeholder, tall }) {\n return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native7.TextInput, { style: [styles.multiline, tall ? styles.tall : null], value, onChangeText: onChange, multiline: true, accessibilityLabel: label, placeholder: placeholder ?? label, placeholderTextColor: theme.colors.foregroundMuted });\n}\nfunction makeStyles2(theme, compact) {\n const { colors } = theme;\n return {\n screen: { flex: 1, backgroundColor: colors.surface0, padding: compact ? 12 : 20 },\n muted: { color: colors.foregroundMuted, fontSize: 13, lineHeight: 19 },\n small: { color: colors.foregroundMuted, fontSize: 12 },\n danger: { color: colors.statusDanger, fontSize: 13 },\n success: { color: colors.statusSuccess, fontSize: 13 },\n name: { color: colors.foreground, fontSize: 14, fontWeight: "600" },\n empty: { borderWidth: 1, borderStyle: "dashed", borderColor: colors.border, borderRadius: 10, padding: 24, alignItems: "center" },\n table: { borderWidth: 1, borderColor: colors.border, borderRadius: 10, backgroundColor: colors.surface1, overflow: "hidden" },\n tableRow: { flexDirection: compact ? "column" : "row", flexWrap: "wrap", alignItems: compact ? "stretch" : "center", gap: 10, paddingHorizontal: 14, paddingVertical: 12 },\n tableRowRule: { borderTopWidth: 1, borderTopColor: colors.border },\n rowMain: { flex: 1, minWidth: 0, gap: 3 },\n rowTitle: { flexDirection: "row", alignItems: "center", gap: 8, flexWrap: "wrap" },\n rowActions: { flexDirection: "row", gap: 8, alignItems: "center" },\n rowActionsCompact: { flexWrap: "wrap" },\n copyRow: { flexBasis: "100%", flexDirection: "row", gap: 8, alignItems: "center" },\n input: { flex: 1, color: colors.foreground, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 10, paddingVertical: 7, backgroundColor: colors.surface0 },\n banner: { borderRadius: 10, backgroundColor: colors.surface1, borderWidth: 1, borderColor: colors.border, paddingHorizontal: 14, paddingVertical: 10, gap: 4 },\n bannerText: { color: colors.foreground, fontSize: 13 },\n multiline: { minHeight: 160, color: colors.foreground, borderWidth: 1, borderColor: colors.border, borderRadius: 10, padding: 12, fontFamily: "monospace", fontSize: 13, lineHeight: 19, backgroundColor: colors.surface1, textAlignVertical: "top" },\n tall: { minHeight: 420 },\n code: { color: colors.foreground, fontFamily: "monospace", fontSize: 12 }\n };\n}\n\n// integrations/paseo/client/usage.tsx\nvar import_client4 = require("@getpaseo/plugin/client");\nvar import_react_native8 = require("@getpaseo/plugin/client/react-native");\nvar import_react5 = require("react");\nvar import_react_native9 = require("react-native");\n\n// integrations/paseo/shared/usage.ts\nvar import_plugin3 = require("@getpaseo/plugin");\nvar import_zod3 = require("zod");\nvar Pause = import_zod3.z.object({ reason: import_zod3.z.string(), since: import_zod3.z.string(), resetsAt: import_zod3.z.string().optional() });\nvar usageGet = (0, import_plugin3.defineRpc)({\n name: "alp.usage.get",\n input: import_zod3.z.object({ refresh: import_zod3.z.boolean().optional() }),\n output: import_zod3.z.object({\n providers: import_zod3.z.array(import_zod3.z.object({\n runtime: import_zod3.z.enum(["codex", "claude"]),\n available: import_zod3.z.boolean(),\n checkedAt: import_zod3.z.string(),\n plan: import_zod3.z.string().nullable(),\n limited: import_zod3.z.boolean(),\n windows: import_zod3.z.array(import_zod3.z.object({ name: import_zod3.z.string(), usedPercent: import_zod3.z.number().nullable(), resetsAt: import_zod3.z.string().nullable() })),\n pause: Pause.nullable(),\n parked: import_zod3.z.number()\n }))\n })\n});\n\n// integrations/paseo/client/usage.tsx\nvar import_jsx_runtime5 = require("react/jsx-runtime");\nfunction UsageScreen({ theme, layout }) {\n const read = (0, import_client4.useRpc)(usageGet);\n const [data, setData] = (0, import_react5.useState)(null);\n const [error, setError] = (0, import_react5.useState)(null);\n const [loading, setLoading] = (0, import_react5.useState)(true);\n const [tick, setTick] = (0, import_react5.useState)(0);\n const forceRefresh = (0, import_react5.useRef)(false);\n (0, import_react5.useEffect)(() => {\n let live = true;\n setLoading(true);\n const refresh = forceRefresh.current;\n forceRefresh.current = false;\n read({ refresh }).then((result) => {\n if (live) {\n setData(result);\n setError(null);\n }\n }).catch((cause) => {\n if (live) setError(cause instanceof Error ? cause.message : String(cause));\n }).finally(() => {\n if (live) setLoading(false);\n });\n return () => {\n live = false;\n };\n }, [read, tick]);\n (0, import_react5.useEffect)(() => {\n const timer = setInterval(() => setTick((value) => value + 1), 6e4);\n return () => clearInterval(timer);\n }, []);\n return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UsageView, { theme, compact: layout.compact, data, loading, error, onRefresh: () => {\n forceRefresh.current = true;\n setTick((value) => value + 1);\n } });\n}\nfunction dateLabel(value) {\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" }) : "Unknown";\n}\nfunction resetLabel(value, now) {\n if (!value) return "Reset time unavailable";\n const minutes = Math.ceil((Date.parse(value) - now) / 6e4);\n if (minutes <= 0) return "Reset time passed \\xB7 awaiting provider update";\n const duration = minutes >= 1440 ? `${Math.floor(minutes / 1440)}d ${Math.floor(minutes % 1440 / 60)}h` : minutes >= 60 ? `${Math.floor(minutes / 60)}h ${minutes % 60}m` : `${minutes}m`;\n return `Resets in ${duration} \\xB7 ${dateLabel(value)}`;\n}\nfunction UsageView({ theme, compact, data, loading, error, onRefresh, now = Date.now() }) {\n const { colors } = theme;\n const muted = { color: colors.foregroundMuted, fontSize: 13, lineHeight: 20 };\n const providers = data?.providers ?? [];\n const parked = providers.reduce((sum, provider) => sum + provider.parked, 0);\n return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native8.ScrollView, { contentContainerStyle: { padding: compact ? 16 : 28, gap: 24 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 8 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: 12 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { accessibilityRole: "header", style: { color: colors.foreground, fontSize: 28, fontWeight: "600", letterSpacing: -0.7 }, children: "Usage" }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { theme, label: loading ? "Refreshing\\u2026" : "Refresh", icon: "RefreshCw", disabled: loading, onPress: onRefresh, accessibilityLabel: "Refresh usage" })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "Your provider limits, reset windows and paused work in one place." })\n ] }),\n error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { accessibilityRole: "alert", style: { padding: 14, borderWidth: 1, borderColor: colors.statusDanger, borderRadius: 10, gap: 4 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color: colors.statusDanger, fontWeight: "600" }, children: "Could not refresh usage" }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: error }),\n data ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "Showing the last received data." }) : null\n ] }) : null,\n parked > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { padding: 14, backgroundColor: colors.surface1, borderLeftWidth: 3, borderLeftColor: colors.statusWarning, gap: 4 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.Text, { style: { color: colors.foreground, fontWeight: "600" }, children: [\n parked,\n " ",\n parked === 1 ? "assignment waiting" : "assignments waiting"\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "Parked work stays saved while its runtime is paused." })\n ] }) : null,\n !data && loading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { accessibilityLiveRegion: "polite", style: muted, children: "Checking Codex and Claude usage\\u2026" }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.View, { style: { flexDirection: compact ? "column" : "row", flexWrap: "wrap", gap: 16 }, children: providers.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProviderCard, { theme, provider, compact, now }, provider.runtime)) }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { borderTopWidth: 1, borderTopColor: colors.border, paddingTop: 16, gap: 4 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "Account limits reported by each provider, shared with usage outside ALP." }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { ...muted, fontSize: 12 }, children: "Updates every minute while this screen is open. Readings are cached for up to 30 seconds. This is not a billing or token-spend report." })\n ] })\n ] });\n}\nfunction ProviderCard({ theme, provider, compact, now }) {\n const { colors } = theme;\n const status = provider.pause ? "Paused" : !provider.available ? "Unavailable" : provider.limited ? "Limit reached" : "Available";\n const tone = provider.pause || provider.limited ? "warning" : provider.available ? "success" : "muted";\n const muted = { color: colors.foregroundMuted, fontSize: 12, lineHeight: 18 };\n return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { flexGrow: 1, flexBasis: compact ? "auto" : 320, width: compact ? "100%" : void 0, minWidth: 0, padding: 20, backgroundColor: colors.surface1, borderWidth: 1, borderColor: colors.border, borderRadius: 14, gap: 20 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", gap: 12 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 4 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { accessibilityRole: "header", style: { color: colors.foreground, fontSize: 20, fontWeight: "600" }, children: provider.runtime === "codex" ? "Codex" : "Claude" }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: provider.plan ? `${provider.plan} plan` : "Plan not reported" })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Pill, { theme, label: status, tone })\n ] }),\n provider.pause ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 5 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color: colors.statusWarning, fontSize: 13 }, children: provider.pause.reason }),\n provider.pause.resetsAt ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: resetLabel(provider.pause.resetsAt, now) }) : null,\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.Text, { style: muted, children: [\n provider.parked,\n " ",\n provider.parked === 1 ? "assignment parked" : "assignments parked"\n ] })\n ] }) : null,\n !provider.available ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 8, paddingVertical: 16 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native8.Icon, { name: "CircleHelp", size: 22, color: colors.foregroundMuted }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color: colors.foreground, fontSize: 14, fontWeight: "500" }, children: "Usage is not available" }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "The provider did not return usage data. Check that its CLI is installed and signed in, then refresh." })\n ] }) : provider.windows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: "The provider has not reported any usage windows." }) : provider.windows.map((window, index) => {\n const used = window.usedPercent;\n const color = used === null ? colors.foregroundMuted : used >= 95 ? colors.statusDanger : used >= 80 ? colors.statusWarning : colors.accent;\n return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { gap: 8 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "baseline", gap: 12 }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color: colors.foreground, fontSize: 13, flex: 1, textTransform: "capitalize" }, children: window.name }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: { color, fontSize: 25, fontWeight: "600", fontVariant: ["tabular-nums"] }, children: used === null ? "\\u2014" : `${Math.round(used)}%` })\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.View, { accessibilityRole: "progressbar", accessibilityLabel: `${window.name} used`, accessibilityValue: used === null ? { text: "Usage unknown" } : { min: 0, max: 100, now: used }, style: { height: 6, backgroundColor: colors.surface2, borderRadius: 3, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.View, { style: { height: 6, width: `${used ?? 0}%`, backgroundColor: color, borderRadius: 3 } }) }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: used === null ? "Usage percentage unavailable" : `${Math.round(100 - used)}% remaining` }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native9.Text, { style: muted, children: resetLabel(window.resetsAt, now) })\n ] }, `${window.name}-${index}`);\n }),\n /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native9.Text, { style: { ...muted, borderTopWidth: 1, borderTopColor: colors.border, paddingTop: 12 }, children: [\n "Checked ",\n dateLabel(provider.checkedAt)\n ] })\n ] });\n}\n\n// integrations/paseo/index.client.tsx\nfunction contribute(client) {\n const removePanel = client.addWorkspacePanel({ id: "alp-tasks", title: "Tasks", icon: "ListTodo", context: "workspace", Component: TasksPanel });\n const removeScreen = client.addScreen({ id: TASKS_SCREEN, title: (params) => params.taskId ? `ALP task ${params.taskId}` : "ALP tasks", Component: TasksScreen });\n const removePills = addTaskPills(client);\n const removeCommand = client.addCommandCenterItem({\n id: "alp-open-tasks",\n title: "Open ALP tasks",\n icon: "ListTodo",\n keywords: ["tasks", "todo", "alp"],\n context: "workspace",\n onSelect({ openPanel }) {\n openPanel("alp-tasks");\n }\n });\n const removeScreenCommand = client.addCommandCenterItem({\n id: "alp-open-tasks-screen",\n title: "Open ALP tasks full screen",\n icon: "ListTodo",\n keywords: ["tasks", "todo", "alp", "phone"],\n context: "workspace",\n onSelect({ workspace, openScreen }) {\n openScreen(tasksScreen(workspace.id, workspace.directory || workspace.projectRootPath));\n }\n });\n const removeSlash = client.addSlashCommand({\n name: "alp-tasks",\n description: "Open the ALP tasks of this project",\n argumentHint: "[task id]",\n context: "agent",\n onSubmit({ workspace, args, openScreen }) {\n openScreen(tasksScreen(workspace.id, workspace.directory || workspace.projectRootPath, args.trim() || void 0));\n }\n });\n const removeSettings = client.addSettingsScreen({ id: "alp-settings", title: "ALP", icon: "Bot", Component: LibrarySettings });\n const removeHostSettings = [\n { id: "alp-templates", title: "Templates", icon: "Users", Component: TeamsSettings },\n { id: "alp-agents", title: "Agents", icon: "Bot", Component: AgentsSettings },\n { id: "alp-skills", title: "Skills", icon: "BookOpen", Component: SkillsSettings },\n { id: "alp-hooks", title: "Hooks", icon: "Webhook", Component: HooksSettings },\n { id: "alp-mcp", title: "MCP servers", icon: "Plug", Component: McpSettings }\n ].map((screen) => client.addSettingsScreen(screen));\n const removeUsage = client.addSettingsScreen({ id: "alp-usage", title: "Usage", icon: "ChartNoAxesCombined", Component: UsageScreen });\n const removeUsagePanel = client.addWorkspacePanel({ id: "alp-usage", title: "Usage", icon: "ChartNoAxesCombined", context: "workspace", Component: UsageScreen });\n const removeProject = client.addWorkspacePanel({ id: "alp-project", title: "ALP project", icon: "Bot", context: "workspace", Component: ProjectLibraryPanel });\n return () => {\n removePanel();\n removeScreen();\n removePills();\n removeCommand();\n removeScreenCommand();\n removeSlash();\n removeSettings();\n removeHostSettings.forEach((remove) => remove());\n removeProject();\n removeUsage();\n removeUsagePanel();\n };\n}\n\nreturn module.exports;})' };
|
|
35730
35858
|
|
|
35731
35859
|
// packages/core/src/library-edit.js
|
|
35732
|
-
import { mkdir as mkdir9, rename as
|
|
35733
|
-
import { createHash as createHash6, randomUUID as
|
|
35860
|
+
import { lstat as lstat4, mkdir as mkdir9, readdir as readdir8, rename as rename5, rm as rm3, stat as stat8, writeFile as writeFile10 } from "node:fs/promises";
|
|
35861
|
+
import { createHash as createHash6, randomUUID as randomUUID8 } from "node:crypto";
|
|
35734
35862
|
import path18 from "node:path";
|
|
35735
35863
|
var EDIT_KINDS = ["agents", "skills", "mcp", "hooks", "teams", "providers"];
|
|
35736
35864
|
var validName3 = (name) => typeof name === "string" && /^[\w.-]+$/.test(name) && name !== "." && name !== "..";
|
|
@@ -35762,6 +35890,42 @@ function base(scope, { root, library }, kind) {
|
|
|
35762
35890
|
return fail4("INVALID_SCOPE", `Scope must be library or project, not '${scope}'`);
|
|
35763
35891
|
}
|
|
35764
35892
|
var revisionOf = (content) => content === void 0 ? null : createHash6("sha256").update(JSON.stringify(content)).digest("hex").slice(0, 16);
|
|
35893
|
+
function assertProjectDataContent(kind, content) {
|
|
35894
|
+
const deny = () => fail4("UNSAFE_LIBRARY_WRITE", "Project-data writes allow only instruction entries and non-executable agent configuration");
|
|
35895
|
+
if (!object7(content) || !["agents", "skills"].includes(kind)) deny();
|
|
35896
|
+
const keys2 = kind === "skills" ? ["body"] : ["instructions", "config"];
|
|
35897
|
+
if (Object.keys(content).some((key) => !keys2.includes(key))) deny();
|
|
35898
|
+
const text = kind === "skills" ? content.body : content.instructions;
|
|
35899
|
+
if (typeof text !== "string" || !text.trim()) deny();
|
|
35900
|
+
if (content.config !== void 0) {
|
|
35901
|
+
const config2 = content.config;
|
|
35902
|
+
if (!object7(config2)) deny();
|
|
35903
|
+
const allowed = ["description", "model", "thinking", "context", "autocompact"];
|
|
35904
|
+
if (Object.keys(config2).some((key) => !allowed.includes(key))) deny();
|
|
35905
|
+
for (const key of ["description", "thinking"]) if (config2[key] !== void 0 && typeof config2[key] !== "string") deny();
|
|
35906
|
+
if (config2.model !== void 0 && (typeof config2.model !== "string" || !/^(codex|claude):[^\s/\\:]{1,240}$/.test(config2.model))) deny();
|
|
35907
|
+
for (const key of ["context", "autocompact"]) if (config2[key] !== void 0 && !(typeof config2[key] === "string" || typeof config2[key] === "number" && Number.isFinite(config2[key]))) deny();
|
|
35908
|
+
}
|
|
35909
|
+
}
|
|
35910
|
+
async function projectDataEntry(kind, name, { scope, root, library, templates: templates2 }) {
|
|
35911
|
+
if (scope !== "project" || !root || !["agents", "skills"].includes(kind)) fail4("UNSAFE_LIBRARY_WRITE", "Project-data writes require project scope and agents or skills");
|
|
35912
|
+
nameOf(name);
|
|
35913
|
+
const directory = base(scope, { root, library }, kind);
|
|
35914
|
+
await safeEntryPaths(directory, kind, name);
|
|
35915
|
+
const found = await layers(kind, name, { root, library, templates: templates2 });
|
|
35916
|
+
if (found.library !== void 0 || found.builtin !== void 0) fail4("UNSAFE_LIBRARY_WRITE", "Project-data writes cannot shadow or reveal a library or built-in entry");
|
|
35917
|
+
if (found.project !== void 0) assertProjectDataContent(kind, found.project);
|
|
35918
|
+
const owned = path18.join(directory, kind, name);
|
|
35919
|
+
const files = await readdir8(owned).catch((error51) => {
|
|
35920
|
+
if (error51.code === "ENOENT") return [];
|
|
35921
|
+
throw error51;
|
|
35922
|
+
});
|
|
35923
|
+
const allowed = new Set(FILES[kind](name).map(([file2]) => path18.basename(file2)));
|
|
35924
|
+
for (const file2 of files) {
|
|
35925
|
+
const info = await lstat4(path18.join(owned, file2));
|
|
35926
|
+
if (!allowed.has(file2) || !info.isFile() || info.isSymbolicLink() || info.nlink !== 1) fail4("UNSAFE_LIBRARY_WRITE", "Project-data entries cannot contain sidecars, links or executable assets");
|
|
35927
|
+
}
|
|
35928
|
+
}
|
|
35765
35929
|
async function safeEntryPaths(directory, kind, name) {
|
|
35766
35930
|
for (const [file2] of FILES[kind](name)) {
|
|
35767
35931
|
await assertNoSymlinks(directory, path18.join(kind, file2));
|
|
@@ -35954,14 +36118,18 @@ async function check2(kind, name, content, { scope, root, library, templates: te
|
|
|
35954
36118
|
}
|
|
35955
36119
|
async function writeAtomic(file2, text) {
|
|
35956
36120
|
await mkdir9(path18.dirname(file2), { recursive: true });
|
|
35957
|
-
const temporary = `${file2}.${
|
|
35958
|
-
await
|
|
36121
|
+
const temporary = `${file2}.${randomUUID8().slice(0, 8)}.tmp`;
|
|
36122
|
+
await writeFile10(temporary, text);
|
|
35959
36123
|
await moveFile(temporary, file2);
|
|
35960
36124
|
}
|
|
35961
36125
|
var exists2 = (target) => stat8(target).then(() => true, () => false);
|
|
35962
|
-
async function saveEntry(kind, name, content, { scope, root, library, templates: templates2, revision } = {}) {
|
|
36126
|
+
async function saveEntry(kind, name, content, { scope, root, library, templates: templates2, revision, policy } = {}) {
|
|
35963
36127
|
kindOf(kind);
|
|
35964
36128
|
nameOf(name);
|
|
36129
|
+
if (policy === "project-data") {
|
|
36130
|
+
assertProjectDataContent(kind, content);
|
|
36131
|
+
await projectDataEntry(kind, name, { scope, root, library, templates: templates2 });
|
|
36132
|
+
}
|
|
35965
36133
|
const directory = base(scope, { root, library }, kind);
|
|
35966
36134
|
await safeEntryPaths(directory, kind, name);
|
|
35967
36135
|
await check2(kind, name, content, { scope, root, library, templates: templates2 });
|
|
@@ -35983,9 +36151,10 @@ async function saveEntry(kind, name, content, { scope, root, library, templates:
|
|
|
35983
36151
|
}
|
|
35984
36152
|
return { revision: revisionOf(await readLayer(kind, name, directory)) };
|
|
35985
36153
|
}
|
|
35986
|
-
async function deleteEntry(kind, name, { scope, root, library, templates: templates2, revision } = {}) {
|
|
36154
|
+
async function deleteEntry(kind, name, { scope, root, library, templates: templates2, revision, policy } = {}) {
|
|
35987
36155
|
kindOf(kind);
|
|
35988
36156
|
nameOf(name);
|
|
36157
|
+
if (policy === "project-data") await projectDataEntry(kind, name, { scope, root, library, templates: templates2 });
|
|
35989
36158
|
const directory = base(scope, { root, library }, kind);
|
|
35990
36159
|
const current = await readLayer(kind, name, directory);
|
|
35991
36160
|
if (current === void 0) fail4("NOT_FOUND", `No ${kind} entry '${name}' in the ${scope}`);
|
|
@@ -36001,14 +36170,25 @@ async function deleteEntry(kind, name, { scope, root, library, templates: templa
|
|
|
36001
36170
|
const now3 = scope === "project" && found.library !== void 0 ? "library" : "builtin";
|
|
36002
36171
|
return { removed: true, ...fallback !== void 0 ? { now: now3 } : {} };
|
|
36003
36172
|
}
|
|
36004
|
-
async function duplicateEntry(kind, from, to, { scope, root, library, templates: templates2 } = {}) {
|
|
36173
|
+
async function duplicateEntry(kind, from, to, { scope, root, library, templates: templates2, policy } = {}) {
|
|
36174
|
+
kindOf(kind);
|
|
36175
|
+
nameOf(from);
|
|
36176
|
+
nameOf(to);
|
|
36177
|
+
if (policy === "project-data") {
|
|
36178
|
+
await projectDataEntry(kind, from, { scope, root, library, templates: templates2 });
|
|
36179
|
+
await projectDataEntry(kind, to, { scope, root, library, templates: templates2 });
|
|
36180
|
+
}
|
|
36005
36181
|
const { content } = await getEntry(kind, from, { root, library, templates: templates2 });
|
|
36006
|
-
return saveEntry(kind, to, structuredClone(content), { scope, root, library, templates: templates2, revision: null });
|
|
36182
|
+
return saveEntry(kind, to, structuredClone(content), { scope, root, library, templates: templates2, revision: null, policy });
|
|
36007
36183
|
}
|
|
36008
|
-
async function renameEntry(kind, from, to, { scope, root, library, templates: templates2 } = {}) {
|
|
36184
|
+
async function renameEntry(kind, from, to, { scope, root, library, templates: templates2, policy } = {}) {
|
|
36009
36185
|
kindOf(kind);
|
|
36010
36186
|
nameOf(from);
|
|
36011
36187
|
nameOf(to);
|
|
36188
|
+
if (policy === "project-data") {
|
|
36189
|
+
await projectDataEntry(kind, from, { scope, root, library, templates: templates2 });
|
|
36190
|
+
await projectDataEntry(kind, to, { scope, root, library, templates: templates2 });
|
|
36191
|
+
}
|
|
36012
36192
|
const directory = base(scope, { root, library }, kind);
|
|
36013
36193
|
const content = await readLayer(kind, from, directory);
|
|
36014
36194
|
if (content === void 0) fail4("NOT_FOUND", `No ${kind} entry '${from}' in the ${scope}`);
|
|
@@ -36018,9 +36198,9 @@ async function renameEntry(kind, from, to, { scope, root, library, templates: te
|
|
|
36018
36198
|
await check2(kind, to, content, { scope, root, library, templates: templates2 });
|
|
36019
36199
|
if (ownDirectory(kind)) {
|
|
36020
36200
|
if (await exists2(path18.join(directory, kind, to))) fail4("REVISION_CONFLICT", `${path18.join(directory, kind, to)} already exists`);
|
|
36021
|
-
await
|
|
36201
|
+
await rename5(path18.join(directory, kind, from), path18.join(directory, kind, to));
|
|
36022
36202
|
} else {
|
|
36023
|
-
await
|
|
36203
|
+
await rename5(path18.join(directory, kind, `${from}.json`), path18.join(directory, kind, `${to}.json`));
|
|
36024
36204
|
}
|
|
36025
36205
|
return { revision: revisionOf(await readLayer(kind, to, directory)) };
|
|
36026
36206
|
}
|
|
@@ -36530,7 +36710,9 @@ var libraryGet = defineRpc2({
|
|
|
36530
36710
|
revision: external_exports.string().nullable(),
|
|
36531
36711
|
usedBy: external_exports.array(external_exports.string()),
|
|
36532
36712
|
/** Agents: the skills the library gives it by name (role-skills.json). */
|
|
36533
|
-
librarySkills: external_exports.array(external_exports.string()).optional()
|
|
36713
|
+
librarySkills: external_exports.array(external_exports.string()).optional(),
|
|
36714
|
+
/** ALP remote mode: JSON Pointers of the values `content` holds as a secret marker, not as the value. */
|
|
36715
|
+
secrets: external_exports.array(external_exports.string()).optional()
|
|
36534
36716
|
})
|
|
36535
36717
|
});
|
|
36536
36718
|
var librarySkills2 = defineRpc2({
|
|
@@ -36806,7 +36988,7 @@ function createUsage(read) {
|
|
|
36806
36988
|
|
|
36807
36989
|
// integrations/paseo/server/paseo/workspaces.ts
|
|
36808
36990
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
36809
|
-
import { mkdir as mkdir10, readFile as readFile11, stat as stat9, writeFile as
|
|
36991
|
+
import { mkdir as mkdir10, readFile as readFile11, stat as stat9, writeFile as writeFile11 } from "node:fs/promises";
|
|
36810
36992
|
import path21 from "node:path";
|
|
36811
36993
|
|
|
36812
36994
|
// node_modules/@getpaseo/protocol/dist/agent-state-bucket.js
|
|
@@ -36894,7 +37076,7 @@ function createWorkspaces({ home: home2, broadcast, agents, inDevelopment, log:
|
|
|
36894
37076
|
saving = saving.then(async () => {
|
|
36895
37077
|
await mkdir10(path21.dirname(file2), { recursive: true });
|
|
36896
37078
|
const temporary = `${file2}.${process.pid}.tmp`;
|
|
36897
|
-
await
|
|
37079
|
+
await writeFile11(temporary, text);
|
|
36898
37080
|
await moveFile(temporary, file2);
|
|
36899
37081
|
}).catch((error51) => log3(`web workspaces not saved: ${error51?.message ?? error51}`));
|
|
36900
37082
|
return saving;
|
|
@@ -37367,8 +37549,8 @@ function createWorkspaces({ home: home2, broadcast, agents, inDevelopment, log:
|
|
|
37367
37549
|
}
|
|
37368
37550
|
|
|
37369
37551
|
// integrations/paseo/server/paseo/relay.ts
|
|
37370
|
-
import { randomUUID as
|
|
37371
|
-
import { readFile as readFile12, rename as
|
|
37552
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
37553
|
+
import { readFile as readFile12, rename as rename7, writeFile as writeFile12, mkdir as mkdir11 } from "node:fs/promises";
|
|
37372
37554
|
import path22 from "node:path";
|
|
37373
37555
|
|
|
37374
37556
|
// node_modules/@getpaseo/relay/dist/crypto.js
|
|
@@ -38267,9 +38449,9 @@ async function relayKeyPair(home2) {
|
|
|
38267
38449
|
const keyPair = generateKeyPair();
|
|
38268
38450
|
const publicKeyB64 = exportPublicKey(keyPair.publicKey);
|
|
38269
38451
|
await mkdir11(home2, { recursive: true, mode: 448 });
|
|
38270
|
-
const temporary = `${file2}.${
|
|
38271
|
-
await
|
|
38272
|
-
await
|
|
38452
|
+
const temporary = `${file2}.${randomUUID9().slice(0, 8)}.tmp`;
|
|
38453
|
+
await writeFile12(temporary, JSON.stringify({ v: 2, publicKeyB64, secretKeyB64: exportSecretKey(keyPair.secretKey) }, null, 2) + "\n", { mode: 384 });
|
|
38454
|
+
await rename7(temporary, file2);
|
|
38273
38455
|
return { keyPair, publicKeyB64 };
|
|
38274
38456
|
}
|
|
38275
38457
|
function pairingUrl(offer) {
|
|
@@ -38769,8 +38951,8 @@ async function markReady(home2) {
|
|
|
38769
38951
|
lock.ready = true;
|
|
38770
38952
|
const file2 = integrationLockPath(home2);
|
|
38771
38953
|
const tmp = `${file2}.${process.pid}.tmp`;
|
|
38772
|
-
await
|
|
38773
|
-
await
|
|
38954
|
+
await writeFile13(tmp, JSON.stringify(lock), { mode: 384 });
|
|
38955
|
+
await rename8(tmp, file2);
|
|
38774
38956
|
}
|
|
38775
38957
|
async function clearReady(home2) {
|
|
38776
38958
|
const lock = await readIntegrationLock(home2);
|
|
@@ -38778,8 +38960,8 @@ async function clearReady(home2) {
|
|
|
38778
38960
|
lock.ready = false;
|
|
38779
38961
|
const file2 = integrationLockPath(home2);
|
|
38780
38962
|
const tmp = `${file2}.${process.pid}.tmp`;
|
|
38781
|
-
await
|
|
38782
|
-
await
|
|
38963
|
+
await writeFile13(tmp, JSON.stringify(lock), { mode: 384 });
|
|
38964
|
+
await rename8(tmp, file2);
|
|
38783
38965
|
}
|
|
38784
38966
|
async function releaseIntegrationLock(home2) {
|
|
38785
38967
|
const lock = await readIntegrationLock(home2);
|
|
@@ -38947,8 +39129,8 @@ if (process.argv.includes("--register")) {
|
|
|
38947
39129
|
const entry = fileURLToPath(import.meta.url);
|
|
38948
39130
|
const file2 = path24.join(home, "integrations", "web.json");
|
|
38949
39131
|
const tmp = `${file2}.${process.pid}.tmp`;
|
|
38950
|
-
await
|
|
38951
|
-
await
|
|
39132
|
+
await writeFile13(tmp, JSON.stringify({ main: entry, registeredAt: (/* @__PURE__ */ new Date()).toISOString() }), { mode: 384 });
|
|
39133
|
+
await rename8(tmp, file2);
|
|
38952
39134
|
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} registered ${entry}`);
|
|
38953
39135
|
process.exit(0);
|
|
38954
39136
|
}
|