@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.
@@ -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 rename7, stat as stat10, unlink as unlink4, writeFile as writeFile12 } from "node:fs/promises";
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 writeFile2, stat as stat2 } from "node:fs/promises";
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
- await releaseHold(home2);
15450
- const lock = await readLock(home2);
15451
- if (lockAlive(lock)) return lock.ready ? lock.socket : whenReady(home2, timeoutMs);
15452
- const service = serviceFor({ home: home2, env });
15453
- if (service && await installedProgram(service)) {
15454
- await startService(service);
15455
- return whenReady(home2, timeoutMs);
15456
- }
15457
- return ensureDaemon({ home: home2, entry, env, timeoutMs });
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 }).then(() => log3(`alpd ${reason}`), (error51) => log3(`could not start alpd: ${error51?.message ?? error51}`)).finally(() => {
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 writeFile3 } from "node:fs/promises";
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 rename(from, to);
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 rename2, stat as stat3, writeFile as writeFile4 } from "node:fs/promises";
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 writeFile4(`${webFile(home2)}.tmp`, JSON.stringify(info), { mode: 384 });
16116
- await rename2(`${webFile(home2)}.tmp`, webFile(home2));
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 writeFile5 } from "node:fs/promises";
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}.${randomUUID().slice(0, 8)}.tmp`;
16178
- await writeFile5(temporary, JSON.stringify(next, null, 2) + "\n");
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}.${randomUUID().slice(0, 8)}.tmp`;
16188
- await writeFile5(temporary, JSON.stringify(next, null, 2) + "\n");
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 randomUUID6 } from "node:crypto";
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 readdir3 } from "node:fs/promises";
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 readdir2, stat as stat4 } from "node:fs/promises";
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 writeFile6 } from "node:fs/promises";
16278
- import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
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 readdir(new URL(`${relative}/`, root), { withFileTypes: true })) {
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 writeFile6(target, content, { flag: "wx" }).catch((error51) => {
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 writeFile6(target, content);
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}.${randomUUID2().slice(0, 8)}.tmp`;
16333
- await writeFile6(temporary, JSON.stringify(manifest, null, 2) + "\n");
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 readdir2(directory, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
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 readdir3(directory, { withFileTypes: true })).filter((entry) => entry.isDirectory() && validName2(entry.name)).map((entry) => entry.name).sort();
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 readdir4, rmdir, stat as stat5, writeFile as writeFile7 } from "node:fs/promises";
16628
- import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
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 readdir4(tasksDir(projectRoot));
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 rmdir(lock).catch(() => {
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 rmdir(lock).catch(() => {
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 writeFile7(path11.join(dir, ".gitignore"), GITIGNORE, { flag: "wx" }).catch((error51) => {
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}.${randomUUID3().slice(0, 8)}.tmp`;
16882
- await writeFile7(temporary, JSON.stringify(task, null, 2) + "\n");
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${randomUUID3()}`).digest("hex");
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 readdir5, readFile as readFile8 } from "node:fs/promises";
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 readdir5(path12.join(library, "providers"));
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 writeFile8, lstat as lstat3, readFile as readFile9, rename as rename3, rm as rm2 } from "node:fs/promises";
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 randomUUID4 } from "node:crypto";
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}.${randomUUID4()}.tmp`;
33749
+ const temporary = `${file2}.${randomUUID5()}.tmp`;
33664
33750
  try {
33665
- await writeFile8(temporary, JSON.stringify(next, null, 2) + "\n", { flag: "wx", mode: info.mode });
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 rename3(temporary, file2);
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 randomUUID5 } from "node:crypto";
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 ?? randomUUID5(),
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
- roots.delete(id2);
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") stream(root, { type: "turn_completed", provider: PROVIDER, turnId: event.turnId }, envelope.ts);
34723
- else if (event.state === "canceled") stream(root, { type: "turn_canceled", provider: PROVIDER, turnId: event.turnId, reason: event.error?.message ?? "Stopped" }, envelope.ts);
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 alp.request("session.attach", { sessionId: root, replay: true });
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
- replaying.delete(root);
34759
- attaching.delete(root);
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-${randomUUID6()}`;
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 ?? randomUUID6(), content: [{ type: "text", text: prompt }] });
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 ?? randomUUID6(),
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 readdir6, realpath as realpath2, stat as stat7 } from "node:fs/promises";
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) => readdir6(directory, { withFileTypes: true }).catch(() => []);
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 readdir6(real, { withFileTypes: true })) {
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 rename4, rm as rm3, stat as stat8, writeFile as writeFile9 } from "node:fs/promises";
35733
- import { createHash as createHash6, randomUUID as randomUUID7 } from "node:crypto";
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}.${randomUUID7().slice(0, 8)}.tmp`;
35958
- await writeFile9(temporary, text);
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 rename4(path18.join(directory, kind, from), path18.join(directory, kind, to));
36201
+ await rename5(path18.join(directory, kind, from), path18.join(directory, kind, to));
36022
36202
  } else {
36023
- await rename4(path18.join(directory, kind, `${from}.json`), path18.join(directory, kind, `${to}.json`));
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 writeFile10 } from "node:fs/promises";
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 writeFile10(temporary, text);
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 randomUUID8 } from "node:crypto";
37371
- import { readFile as readFile12, rename as rename6, writeFile as writeFile11, mkdir as mkdir11 } from "node:fs/promises";
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}.${randomUUID8().slice(0, 8)}.tmp`;
38271
- await writeFile11(temporary, JSON.stringify({ v: 2, publicKeyB64, secretKeyB64: exportSecretKey(keyPair.secretKey) }, null, 2) + "\n", { mode: 384 });
38272
- await rename6(temporary, file2);
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 writeFile12(tmp, JSON.stringify(lock), { mode: 384 });
38773
- await rename7(tmp, file2);
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 writeFile12(tmp, JSON.stringify(lock), { mode: 384 });
38782
- await rename7(tmp, file2);
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 writeFile12(tmp, JSON.stringify({ main: entry, registeredAt: (/* @__PURE__ */ new Date()).toISOString() }), { mode: 384 });
38951
- await rename7(tmp, file2);
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
  }