@agentproto/cli 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -40,7 +40,7 @@ agentproto pair <offer|accept|ls|revoke|exec> pairing over
40
40
  agentproto rendezvous serve [--port <n>] [--host <ip>] run a rendezvous broker
41
41
  ```
42
42
 
43
- `agentproto --help` prints the full usage; `--version` prints the package version.
43
+ > `agentproto --help` prints the full usage; `--version` prints the package version.
44
44
 
45
45
  ## Quick start
46
46
 
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { promises, existsSync, readFileSync, chmodSync, mkdirSync, writeFileSync, readdirSync, accessSync, constants, renameSync, createReadStream, createWriteStream, statSync, openSync, closeSync } from 'fs';
3
+ import { promises, existsSync, readFileSync, chmodSync, mkdirSync, writeFileSync, readdirSync, accessSync, constants, renameSync, createReadStream, createWriteStream, statSync, realpathSync, openSync, closeSync } from 'fs';
4
4
  import { homedir, userInfo, hostname, platform, tmpdir } from 'os';
5
5
  import { join, resolve, isAbsolute, dirname, normalize, basename, delimiter, relative } from 'path';
6
6
  import * as childProc from 'child_process';
@@ -46,7 +46,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
46
46
  import { runRendezvousCli } from '@agentproto/rendezvous/cli';
47
47
 
48
48
  /**
49
- * @agentproto/cli v0.9.0
49
+ * @agentproto/cli v0.10.0
50
50
  * The `agentproto` binary — install / run / serve AIP-45 agent CLIs.
51
51
  */
52
52
  // Provide a real `require` in the ESM bundle. Some bundled deps (e.g.
@@ -16753,9 +16753,18 @@ function isWorkflowHandle(v2) {
16753
16753
  }
16754
16754
  async function importEntryHandle(workflowMdPath, entry) {
16755
16755
  const abs = isAbsolute(entry) ? entry : join(dirname(workflowMdPath), entry);
16756
+ let href = pathToFileURL(abs).href;
16757
+ if (!process.env.VITEST) {
16758
+ try {
16759
+ const url = pathToFileURL(abs);
16760
+ url.searchParams.set("v", String((await stat(abs)).mtimeMs));
16761
+ href = url.href;
16762
+ } catch {
16763
+ }
16764
+ }
16756
16765
  let mod;
16757
16766
  try {
16758
- mod = await import(pathToFileURL(abs).href);
16767
+ mod = await import(href);
16759
16768
  } catch (err) {
16760
16769
  throw new WorkflowLoadError(
16761
16770
  `cannot import entry '${entry}': ${err instanceof Error ? err.message : String(err)}`
@@ -19068,9 +19077,19 @@ function setActiveWorkspace(config, slug) {
19068
19077
  function findWorkspace(config, slug) {
19069
19078
  return config.workspaces.find((w) => w.slug === sanitizeSlug(slug));
19070
19079
  }
19080
+ function canonical(p2) {
19081
+ try {
19082
+ return realpathSync(resolve(p2));
19083
+ } catch {
19084
+ return resolve(p2);
19085
+ }
19086
+ }
19071
19087
  function findWorkspaceByPath(config, dir) {
19072
- const resolved = resolve(dir);
19073
- const candidates2 = config.workspaces.filter((w) => resolved.startsWith(resolve(w.path) + "/") || resolved === resolve(w.path)).sort((a, b2) => b2.path.length - a.path.length);
19088
+ const resolved = canonical(dir);
19089
+ const candidates2 = config.workspaces.filter((w) => {
19090
+ const wPath = canonical(w.path);
19091
+ return resolved.startsWith(wPath + "/") || resolved === wPath;
19092
+ }).sort((a, b2) => b2.path.length - a.path.length);
19074
19093
  return candidates2[0];
19075
19094
  }
19076
19095
  function getActiveWorkspace(config) {
@@ -19156,6 +19175,76 @@ async function loadConfig2(path) {
19156
19175
  return {};
19157
19176
  }
19158
19177
  }
19178
+ var markerSchema = z.object({ worktreeId: z.string() });
19179
+ function statOrUndefined(path) {
19180
+ try {
19181
+ return statSync(path);
19182
+ } catch {
19183
+ return void 0;
19184
+ }
19185
+ }
19186
+ function readWorktreeGitDir(dir) {
19187
+ const link = (() => {
19188
+ try {
19189
+ return readFileSync(join(dir, ".git"), "utf8");
19190
+ } catch {
19191
+ return void 0;
19192
+ }
19193
+ })();
19194
+ if (link === void 0) return void 0;
19195
+ const target = /^gitdir:\s*(.+)$/m.exec(link)?.[1]?.trim();
19196
+ if (!target) return void 0;
19197
+ const gitDir = isAbsolute(target) ? target : resolve(dir, target);
19198
+ return statOrUndefined(join(gitDir, "gitdir"))?.isFile() === true ? gitDir : void 0;
19199
+ }
19200
+ function readMainRepoPath(gitDir) {
19201
+ let raw;
19202
+ try {
19203
+ raw = readFileSync(join(gitDir, "commondir"), "utf8").trim();
19204
+ } catch {
19205
+ return void 0;
19206
+ }
19207
+ if (!raw) return void 0;
19208
+ const commonGitDir = isAbsolute(raw) ? raw : resolve(gitDir, raw);
19209
+ return dirname(commonGitDir);
19210
+ }
19211
+ function readWorktreeId(gitDir) {
19212
+ let raw;
19213
+ try {
19214
+ raw = readFileSync(join(gitDir, "agentproto-worktree.json"), "utf8");
19215
+ } catch {
19216
+ return void 0;
19217
+ }
19218
+ let parsed;
19219
+ try {
19220
+ parsed = JSON.parse(raw);
19221
+ } catch {
19222
+ return void 0;
19223
+ }
19224
+ const result = markerSchema.safeParse(parsed);
19225
+ return result.success ? result.data.worktreeId : void 0;
19226
+ }
19227
+ function resolveWorktreeIdentity(cwd) {
19228
+ let dir = resolve(cwd);
19229
+ for (; ; ) {
19230
+ const dotGit = statOrUndefined(join(dir, ".git"));
19231
+ if (dotGit) {
19232
+ if (!dotGit.isFile()) return void 0;
19233
+ const gitDir = readWorktreeGitDir(dir);
19234
+ if (gitDir === void 0) return void 0;
19235
+ const worktreeId = readWorktreeId(gitDir);
19236
+ const mainRepoPath = readMainRepoPath(gitDir);
19237
+ return {
19238
+ worktreePath: dir,
19239
+ ...worktreeId === void 0 ? {} : { worktreeId },
19240
+ ...mainRepoPath === void 0 ? {} : { mainRepoPath }
19241
+ };
19242
+ }
19243
+ const parent = dirname(dir);
19244
+ if (parent === dir) return void 0;
19245
+ dir = parent;
19246
+ }
19247
+ }
19159
19248
  var providers_store_exports = {};
19160
19249
  __reExport(providers_store_exports, dist_exports);
19161
19250
  function resolveSpawnDefaults(defaults, adapterSlug, input2) {
@@ -19706,15 +19795,38 @@ async function spawnAgentSession(deps2, input2) {
19706
19795
  try {
19707
19796
  const config = await loadWorkspacesConfig();
19708
19797
  if (!cwd) {
19709
- const ws = input2.workspaceSlug ? findWorkspace(config, input2.workspaceSlug) : getActiveWorkspace(config);
19710
- if (ws) {
19711
- cwd = ws.path;
19712
- resolvedSlug = ws.slug;
19798
+ if (input2.workspaceSlug) {
19799
+ const ws = findWorkspace(config, input2.workspaceSlug);
19800
+ if (ws) {
19801
+ cwd = ws.path;
19802
+ resolvedSlug = ws.slug;
19803
+ }
19804
+ } else if (callerScope) {
19805
+ const parentCwd = callerScope.ownerSessionId ? registry.get(callerScope.ownerSessionId)?.cwd : void 0;
19806
+ if (parentCwd) {
19807
+ cwd = parentCwd;
19808
+ const ws = findWorkspaceByPath(config, parentCwd);
19809
+ if (ws) {
19810
+ resolvedSlug = ws.slug;
19811
+ }
19812
+ }
19813
+ } else {
19814
+ const ws = getActiveWorkspace(config);
19815
+ if (ws) {
19816
+ cwd = ws.path;
19817
+ resolvedSlug = ws.slug;
19818
+ }
19713
19819
  }
19714
19820
  } else if (!resolvedSlug) {
19715
19821
  const ws = findWorkspaceByPath(config, cwd);
19716
19822
  if (ws) {
19717
19823
  resolvedSlug = ws.slug;
19824
+ } else {
19825
+ const identity = resolveWorktreeIdentity(cwd);
19826
+ if (identity?.mainRepoPath) {
19827
+ const baseWs = findWorkspaceByPath(config, identity.mainRepoPath);
19828
+ if (baseWs) resolvedSlug = baseWs.slug;
19829
+ }
19718
19830
  }
19719
19831
  }
19720
19832
  } catch {
@@ -19920,7 +20032,8 @@ async function spawnAgentSession(deps2, input2) {
19920
20032
  const effectivePrompt = input2.prompt ? `${composeRoleContext(role, input2.promptAppend, roleRegistry)}
19921
20033
 
19922
20034
  ${input2.prompt}` : input2.prompt;
19923
- const initialTitle = input2.prompt ? deriveSessionTitle(input2.prompt) : void 0;
20035
+ const explicitTitle = input2.title?.trim() ? input2.title.trim() : void 0;
20036
+ const initialTitle = explicitTitle ?? (input2.prompt ? deriveSessionTitle(input2.prompt) : void 0);
19924
20037
  let settleClaim;
19925
20038
  if (input2.idempotencyKey) {
19926
20039
  const claims = claimsFor(registry);
@@ -22731,6 +22844,90 @@ function registerSessionTools(rawServer, opts) {
22731
22844
  }
22732
22845
  }
22733
22846
  );
22847
+ server.tool(
22848
+ "session_rename",
22849
+ "Set or clear a session's user-facing name \u2014 the label the sessions tree, transcript header, and tab show. `label` out-ranks `title` in that display chain, so a user rename should write `label` (the default a UI picks) to be sure it shows; `title` is the auto-derived first-sentence fallback. For EACH of `title`/`label`: a non-empty string sets it (trimmed + length-capped), an empty string clears it (reverting to the derived title / a friendly `adapter \xB7 id` fallback), and omitting it leaves that field untouched. Persists across daemon restarts. Does NOT rename the adapter-native session or touch the running agent.",
22850
+ {
22851
+ idOrName: z.string().min(1).describe("Session id or name to rename \u2014 from `session_list`."),
22852
+ label: z.string().optional().describe(
22853
+ "New label (the winning display field). Empty string clears it. Omit to leave the label untouched."
22854
+ ),
22855
+ title: z.string().optional().describe(
22856
+ "New title (the auto-derived fallback slot). Empty string clears it, reverting to the first-sentence derivation. Omit to leave it untouched."
22857
+ )
22858
+ },
22859
+ async (input2) => {
22860
+ const prev = registry.findByIdOrName(input2.idOrName);
22861
+ if (!prev) {
22862
+ return {
22863
+ content: [
22864
+ {
22865
+ type: "text",
22866
+ text: JSON.stringify({ error: `no session "${input2.idOrName}" found` })
22867
+ }
22868
+ ],
22869
+ isError: true
22870
+ };
22871
+ }
22872
+ if (callerScope) {
22873
+ const subtree = collectSubtree(
22874
+ callerScope.ownerSessionId,
22875
+ registry.list({ includeArchived: true })
22876
+ );
22877
+ if (!subtree.has(prev.id)) {
22878
+ return {
22879
+ content: [
22880
+ {
22881
+ type: "text",
22882
+ text: JSON.stringify({
22883
+ error: "orchestrator_session_out_of_scope",
22884
+ message: `session_rename: session "${prev.id}" is not in your subtree \u2014 a scoped orchestrator can only rename sessions it (transitively) spawned.`,
22885
+ ok: false,
22886
+ sessionId: prev.id
22887
+ })
22888
+ }
22889
+ ],
22890
+ isError: true
22891
+ };
22892
+ }
22893
+ }
22894
+ if (input2.title === void 0 && input2.label === void 0) {
22895
+ return {
22896
+ content: [
22897
+ {
22898
+ type: "text",
22899
+ text: JSON.stringify({
22900
+ error: "nothing_to_rename",
22901
+ message: "session_rename: supply at least one of `title` or `label`.",
22902
+ ok: false,
22903
+ sessionId: prev.id
22904
+ })
22905
+ }
22906
+ ],
22907
+ isError: true
22908
+ };
22909
+ }
22910
+ try {
22911
+ const desc = registry.renameSession(prev.id, {
22912
+ ...input2.title !== void 0 ? { title: input2.title } : {},
22913
+ ...input2.label !== void 0 ? { label: input2.label } : {}
22914
+ });
22915
+ return {
22916
+ content: [{ type: "text", text: JSON.stringify(desc, null, 2) }]
22917
+ };
22918
+ } catch (err) {
22919
+ return {
22920
+ content: [
22921
+ {
22922
+ type: "text",
22923
+ text: `session_rename: ${err instanceof Error ? err.message : String(err)}`
22924
+ }
22925
+ ],
22926
+ isError: true
22927
+ };
22928
+ }
22929
+ }
22930
+ );
22734
22931
  server.tool(
22735
22932
  "terminal_start",
22736
22933
  "Spawn a process under a real PTY (node-pty) on the host. Bytes (including ANSI escapes, alt-screen sequences) flow through the daemon's byte ring buffer; subscribers attach via the WS at /sessions/:id/pty. Use for interactive TUIs (claude, vim, htop) or to orchestrate shells from another agent. Returns the session descriptor.",
@@ -25997,60 +26194,6 @@ function createTerminalTranscriptWriter(opts) {
25997
26194
  }
25998
26195
  };
25999
26196
  }
26000
- var markerSchema = z.object({ worktreeId: z.string() });
26001
- function statOrUndefined(path) {
26002
- try {
26003
- return statSync(path);
26004
- } catch {
26005
- return void 0;
26006
- }
26007
- }
26008
- function readWorktreeGitDir(dir) {
26009
- const link = (() => {
26010
- try {
26011
- return readFileSync(join(dir, ".git"), "utf8");
26012
- } catch {
26013
- return void 0;
26014
- }
26015
- })();
26016
- if (link === void 0) return void 0;
26017
- const target = /^gitdir:\s*(.+)$/m.exec(link)?.[1]?.trim();
26018
- if (!target) return void 0;
26019
- const gitDir = isAbsolute(target) ? target : resolve(dir, target);
26020
- return statOrUndefined(join(gitDir, "gitdir"))?.isFile() === true ? gitDir : void 0;
26021
- }
26022
- function readWorktreeId(gitDir) {
26023
- let raw;
26024
- try {
26025
- raw = readFileSync(join(gitDir, "agentproto-worktree.json"), "utf8");
26026
- } catch {
26027
- return void 0;
26028
- }
26029
- let parsed;
26030
- try {
26031
- parsed = JSON.parse(raw);
26032
- } catch {
26033
- return void 0;
26034
- }
26035
- const result = markerSchema.safeParse(parsed);
26036
- return result.success ? result.data.worktreeId : void 0;
26037
- }
26038
- function resolveWorktreeIdentity(cwd) {
26039
- let dir = resolve(cwd);
26040
- for (; ; ) {
26041
- const dotGit = statOrUndefined(join(dir, ".git"));
26042
- if (dotGit) {
26043
- if (!dotGit.isFile()) return void 0;
26044
- const gitDir = readWorktreeGitDir(dir);
26045
- if (gitDir === void 0) return void 0;
26046
- const worktreeId = readWorktreeId(gitDir);
26047
- return worktreeId === void 0 ? { worktreePath: dir } : { worktreePath: dir, worktreeId };
26048
- }
26049
- const parent = dirname(dir);
26050
- if (parent === dir) return void 0;
26051
- dir = parent;
26052
- }
26053
- }
26054
26197
  function normalizeAgentPromptOptions(raw) {
26055
26198
  if (!Array.isArray(raw)) return void 0;
26056
26199
  const labels = raw.map((o) => {
@@ -27586,6 +27729,33 @@ function createSessionsRegistry(opts) {
27586
27729
  stampProcessAlive(rt.desc);
27587
27730
  return rt.desc;
27588
27731
  },
27732
+ renameSession(id, patch) {
27733
+ const rt = sessions.get(id);
27734
+ if (!rt) throw new Error(`renameSession: no session "${id}"`);
27735
+ const apply = (field) => {
27736
+ const raw = patch[field];
27737
+ if (raw === void 0) return;
27738
+ const trimmed = raw === null ? "" : raw.trim();
27739
+ if (trimmed === "") {
27740
+ rt.desc[field] = void 0;
27741
+ return;
27742
+ }
27743
+ const points = Array.from(trimmed);
27744
+ rt.desc[field] = points.length > MAX_LENGTH ? points.slice(0, MAX_LENGTH).join("") : trimmed;
27745
+ };
27746
+ apply("title");
27747
+ apply("label");
27748
+ schedulePersist();
27749
+ sessionEvents?.emit({
27750
+ type: "session:renamed",
27751
+ sessionId: id,
27752
+ ...rt.desc.title !== void 0 ? { title: rt.desc.title } : {},
27753
+ ...rt.desc.label !== void 0 ? { label: rt.desc.label } : {},
27754
+ ts: (/* @__PURE__ */ new Date()).toISOString()
27755
+ });
27756
+ stampProcessAlive(rt.desc);
27757
+ return rt.desc;
27758
+ },
27589
27759
  listPendingPermissions(filter) {
27590
27760
  const all = Array.from(pendingPermissions.values());
27591
27761
  const scoped = filter?.sessionId ? all.filter((p2) => p2.sessionId === filter.sessionId) : all;
@@ -30718,6 +30888,9 @@ async function handleSessions(req, res, path, registry, resolveAgentAdapter, pty
30718
30888
  })() : {},
30719
30889
  ...typeof b2.prompt === "string" ? { prompt: b2.prompt } : {},
30720
30890
  ...typeof b2.label === "string" ? { label: b2.label } : {},
30891
+ // Explicit title override (SPEC-3 FIX C, `--title`) — wins over the
30892
+ // first-sentence derivation from the prompt (see session-spawn.ts).
30893
+ ...typeof b2.title === "string" ? { title: b2.title } : {},
30721
30894
  ...typeof b2.idempotencyKey === "string" && b2.idempotencyKey.length > 0 ? { idempotencyKey: b2.idempotencyKey } : {},
30722
30895
  ...typeof b2.role === "string" && b2.role.length > 0 ? { role: b2.role } : {},
30723
30896
  ...typeof b2.promptAppend === "string" ? { promptAppend: b2.promptAppend } : {},
@@ -30974,6 +31147,49 @@ async function handleSessions(req, res, path, registry, resolveAgentAdapter, pty
30974
31147
  }
30975
31148
  return true;
30976
31149
  }
31150
+ const terminalInputMatch = path.match(/^\/sessions\/([^/]+)\/terminal\/input$/);
31151
+ if (terminalInputMatch && req.method === "POST") {
31152
+ const id2 = terminalInputMatch[1];
31153
+ if (!id2) return false;
31154
+ if (!ptyEnabled) {
31155
+ json(501, {
31156
+ error: "pty_not_configured",
31157
+ message: "POST /sessions/:id/terminal/input needs the host to inject `spawnPty` into createGateway (node-pty optional dep \u2014 install in @agentproto/cli)."
31158
+ });
31159
+ return true;
31160
+ }
31161
+ const desc = registry.get(id2);
31162
+ if (!desc) {
31163
+ json(404, { error: "no_session", message: `no session "${id2}"` });
31164
+ return true;
31165
+ }
31166
+ const body = await readJsonBody(req);
31167
+ const text6 = body?.text;
31168
+ if (typeof text6 !== "string") {
31169
+ json(400, { error: "missing_text", message: "Body `text` must be a string." });
31170
+ return true;
31171
+ }
31172
+ if (desc.kind !== "terminal" || desc.pty !== true) {
31173
+ json(400, {
31174
+ error: "not_a_pty",
31175
+ message: `session "${id2}" is not a live PTY (kind=${desc.kind})`
31176
+ });
31177
+ return true;
31178
+ }
31179
+ const enter = body?.enter !== false;
31180
+ let ok = true;
31181
+ if (text6.length > 0) ok = registry.writeTerminalInput(id2, text6) && ok;
31182
+ if (enter) ok = registry.writeTerminalInput(id2, "\r") && ok;
31183
+ if (!ok) {
31184
+ json(400, {
31185
+ error: "not_a_pty",
31186
+ message: `session "${id2}" has no live PTY to write to`
31187
+ });
31188
+ return true;
31189
+ }
31190
+ json(200, { ok: true });
31191
+ return true;
31192
+ }
30977
31193
  const modelMatch = path.match(/^\/sessions\/([^/]+)\/model$/);
30978
31194
  if (modelMatch && req.method === "POST") {
30979
31195
  const id2 = modelMatch[1];
@@ -31097,6 +31313,31 @@ async function handleSessions(req, res, path, registry, resolveAgentAdapter, pty
31097
31313
  }
31098
31314
  return true;
31099
31315
  }
31316
+ const renameMatch = path.match(/^\/sessions\/([^/]+)$/);
31317
+ if (renameMatch && req.method === "PATCH") {
31318
+ const rawIdOrName2 = renameMatch[1];
31319
+ if (!rawIdOrName2) return false;
31320
+ const resolved = registry.findByIdOrName(rawIdOrName2);
31321
+ if (!resolved) {
31322
+ json(404, { error: "session_not_found", id: rawIdOrName2 });
31323
+ return true;
31324
+ }
31325
+ const body = await readJsonBody(req);
31326
+ const b2 = body && typeof body === "object" ? body : {};
31327
+ const field = (v2) => typeof v2 === "string" ? v2 : v2 === null ? null : void 0;
31328
+ const patch = {
31329
+ ..."title" in b2 ? { title: field(b2.title) } : {},
31330
+ ..."label" in b2 ? { label: field(b2.label) } : {}
31331
+ };
31332
+ try {
31333
+ const desc = registry.renameSession(resolved.id, patch);
31334
+ json(200, desc);
31335
+ } catch (err) {
31336
+ const msg = err instanceof Error ? err.message : String(err);
31337
+ json(msg.includes("no session") ? 404 : 500, { error: "rename_failed", message: msg });
31338
+ }
31339
+ return true;
31340
+ }
31100
31341
  if (path === "/sessions" && req.method === "POST") {
31101
31342
  const body = await readJsonBody(req);
31102
31343
  if (!body || typeof body !== "object") {
@@ -40837,9 +41078,9 @@ async function discoverDaemon() {
40837
41078
  }
40838
41079
  async function readRuntimeJsonWithStatus(workspacePath) {
40839
41080
  const path = resolve(workspacePath, ".agentproto", "runtime.json");
40840
- let stat9;
41081
+ let stat10;
40841
41082
  try {
40842
- stat9 = await promises.stat(path);
41083
+ stat10 = await promises.stat(path);
40843
41084
  } catch {
40844
41085
  return { endpoint: null };
40845
41086
  }
@@ -40862,7 +41103,7 @@ async function readRuntimeJsonWithStatus(workspacePath) {
40862
41103
  stale: {
40863
41104
  path,
40864
41105
  pid: parsed.pid ?? null,
40865
- mtime: stat9.mtime ?? null
41106
+ mtime: stat10.mtime ?? null
40866
41107
  }
40867
41108
  };
40868
41109
  }
@@ -43825,8 +44066,8 @@ async function runServe(args) {
43825
44066
  values.workspace ?? cfgDaemon.workspace ?? process.cwd()
43826
44067
  );
43827
44068
  try {
43828
- const stat9 = await promises.stat(workspace);
43829
- if (!stat9.isDirectory()) {
44069
+ const stat10 = await promises.stat(workspace);
44070
+ if (!stat10.isDirectory()) {
43830
44071
  process.stderr.write(
43831
44072
  `agentproto serve: --workspace "${workspace}" is not a directory.
43832
44073
  `
@@ -44233,7 +44474,7 @@ ${color.dim}\u2500\u2500 shutting down (${signal}) \u2500\u2500${color.reset}
44233
44474
  async function runOneTunnel(opts, gateway, announcedTools, spawnPty, signal, reconnectState) {
44234
44475
  if (!opts.connect) throw new Error("runOneTunnel: --connect not set");
44235
44476
  const headers = {
44236
- "user-agent": `agentproto/${"0.9.0"}`
44477
+ "user-agent": `agentproto/${"0.10.0"}`
44237
44478
  };
44238
44479
  if (opts.token) headers.authorization = `Bearer ${opts.token}`;
44239
44480
  const ws = new WebSocket3(opts.connect, { headers });
@@ -46105,7 +46346,8 @@ Usage:
46105
46346
  [--base-url <url>] [--auth-token <token>]
46106
46347
  [--options-json <json|@file>]
46107
46348
  [--prompt <text>]
46108
- [--label <text>] [--attach] [--json]
46349
+ [--label <text>] [--title <text>]
46350
+ [--attach] [--json]
46109
46351
  [--orchestrator | --orchestrator-json <json>]
46110
46352
  [--mcp-servers-json <json|@file>]
46111
46353
  [--hold-permissions] [--no-color]
@@ -46243,6 +46485,7 @@ async function runStart(args) {
46243
46485
  "options-json": { type: "string" },
46244
46486
  prompt: { type: "string", short: "p" },
46245
46487
  label: { type: "string" },
46488
+ title: { type: "string" },
46246
46489
  attach: { type: "boolean" },
46247
46490
  json: { type: "boolean" },
46248
46491
  "no-color": { type: "boolean" },
@@ -46372,6 +46615,7 @@ async function runStart(args) {
46372
46615
  if (options !== void 0 && Object.keys(options).length > 0) body.options = options;
46373
46616
  if (values.prompt) body.prompt = values.prompt;
46374
46617
  if (values.label) body.label = values.label;
46618
+ if (values.title) body.title = values.title;
46375
46619
  if (orchestrator !== void 0) body.orchestrator = orchestrator;
46376
46620
  if (mcpServers !== void 0) body.mcpServers = mcpServers;
46377
46621
  if (values["hold-permissions"]) body.permissionHold = true;
@@ -50017,8 +50261,8 @@ async function fileExists3(path) {
50017
50261
  }
50018
50262
  async function dirExists(path) {
50019
50263
  try {
50020
- const stat9 = await promises.stat(path);
50021
- return stat9.isDirectory();
50264
+ const stat10 = await promises.stat(path);
50265
+ return stat10.isDirectory();
50022
50266
  } catch {
50023
50267
  return false;
50024
50268
  }
@@ -52869,7 +53113,7 @@ async function main(argv) {
52869
53113
  const verbIdx = argv.findIndex((a) => VERBS.has(a));
52870
53114
  if (verbIdx === -1) {
52871
53115
  if (argv.includes("--version") || argv.includes("-v")) {
52872
- process.stdout.write(`agentproto ${"0.9.0"}
53116
+ process.stdout.write(`agentproto ${"0.10.0"}
52873
53117
  `);
52874
53118
  return 0;
52875
53119
  }