@hachej/boring-agent 0.1.89 → 0.1.91

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.
Files changed (39) hide show
  1. package/dist/{chunk-GOM3VJOJ.js → chunk-2GBHYJVC.js} +31 -1
  2. package/dist/{chunk-I7UEASPG.js → chunk-BHH5NH7P.js} +5534 -8253
  3. package/dist/{chunk-M32FXCIN.js → chunk-CJ2BW2W2.js} +23 -8
  4. package/dist/{chunk-WZCTVT57.js → chunk-IWBC6SF7.js} +94 -112
  5. package/dist/chunk-NITBKFG6.js +1246 -0
  6. package/dist/{chunk-BDYXKHWY.js → chunk-PZC76CIA.js} +7 -1
  7. package/dist/core/index.d.ts +5 -5
  8. package/dist/core/index.js +2 -2
  9. package/dist/{createHarness-CCQLHKUF.js → createHarness-PMYRKDE4.js} +2 -2
  10. package/dist/errors-BEmw9HMp.d.ts +200 -0
  11. package/dist/front/index.d.ts +30 -5
  12. package/dist/front/index.js +230 -44
  13. package/dist/{harness-VvP0l5Mj.d.ts → harness-Bt_GMNYR.d.ts} +2 -2
  14. package/dist/{workspaceAgentDispatcher-CKEeNPjW.d.ts → lease-2aXepSBL.d.ts} +254 -59
  15. package/dist/{protocol-B_OQKfbI.d.ts → middleware-CzW8n7B7.d.ts} +20 -18
  16. package/dist/piChatEvent-DBO3M5lu.d.ts +367 -0
  17. package/dist/{piChatSessionService-DPjJ0g71.d.ts → piChatSessionService-BaaVWke7.d.ts} +5 -1
  18. package/dist/{sandbox-DthfJaOB.d.ts → sandbox-DAD8cWQR.d.ts} +14 -1
  19. package/dist/server/agent-host/testing/gatewayConformance.d.ts +41 -0
  20. package/dist/server/agent-host/testing/gatewayConformance.js +465 -0
  21. package/dist/server/index.d.ts +507 -708
  22. package/dist/server/index.js +53 -50
  23. package/dist/server/worker/index.d.ts +9 -7
  24. package/dist/server/worker/index.js +19 -28
  25. package/dist/shared/index.d.ts +119 -27
  26. package/dist/shared/index.js +65 -282
  27. package/dist/types-jcMapYr9.d.ts +759 -0
  28. package/docs/ACCESSIBILITY.md +4 -5
  29. package/docs/API.md +3 -0
  30. package/docs/AUTHORING.md +68 -0
  31. package/docs/ERROR_CODES.md +29 -0
  32. package/docs/README.md +1 -0
  33. package/docs/RISKS-MULTI-TAB.md +1 -1
  34. package/docs/runtime-provisioning.md +1 -1
  35. package/docs/runtime.md +9 -6
  36. package/package.json +18 -9
  37. package/dist/chunk-DGRKMMXO.js +0 -8
  38. package/dist/chunk-XPQEF32D.js +0 -385
  39. package/dist/piChatEvent-nmOBSNU9.d.ts +0 -367
@@ -3,10 +3,6 @@ import {
3
3
  cn,
4
4
  copyTextToClipboard
5
5
  } from "../chunk-BOIV2I3N.js";
6
- import {
7
- WORKSPACE_AGENT_PLUGINS_RELOADED_EVENT,
8
- WORKSPACE_COMMAND_NOTIFY_EVENT
9
- } from "../chunk-DGRKMMXO.js";
10
6
  import {
11
7
  CommandReceiptSchema,
12
8
  FollowUpReceiptSchema,
@@ -15,12 +11,14 @@ import {
15
11
  PromptReceiptSchema,
16
12
  QueueClearReceiptSchema,
17
13
  StopReceiptSchema,
14
+ WORKSPACE_AGENT_PLUGINS_RELOADED_EVENT,
15
+ WORKSPACE_COMMAND_NOTIFY_EVENT,
18
16
  extractToolUiMetadata,
19
17
  sanitizeToolUiMetadata
20
- } from "../chunk-BDYXKHWY.js";
18
+ } from "../chunk-PZC76CIA.js";
21
19
  import {
22
20
  ErrorCode
23
- } from "../chunk-GOM3VJOJ.js";
21
+ } from "../chunk-2GBHYJVC.js";
24
22
 
25
23
  // src/front/upload/uploadFile.ts
26
24
  function readAsDataUrl(file) {
@@ -4414,7 +4412,16 @@ function parsePiChatNdjsonLine(line) {
4414
4412
  } catch (error) {
4415
4413
  return { type: "malformed-json", line, error };
4416
4414
  }
4417
- const parsed = PiChatStreamFrameSchema.safeParse(value);
4415
+ let frameValue = value;
4416
+ if (typeof value === "object" && value !== null && "ref" in value && "seq" in value && "event" in value) {
4417
+ const envelope = value;
4418
+ const eventSeq = typeof envelope.event === "object" && envelope.event !== null ? envelope.event.seq : void 0;
4419
+ if (typeof envelope.seq !== "number" || envelope.seq !== eventSeq) {
4420
+ return { type: "schema-error", line, error: new Error("addressed event envelope seq mismatch") };
4421
+ }
4422
+ frameValue = envelope.event;
4423
+ }
4424
+ const parsed = PiChatStreamFrameSchema.safeParse(frameValue);
4418
4425
  if (!parsed.success) {
4419
4426
  return { type: "schema-error", line, error: parsed.error };
4420
4427
  }
@@ -4469,7 +4476,8 @@ function parsePiChatReplayRangeError(status, body) {
4469
4476
  const record = body;
4470
4477
  const payload = typeof record.error === "object" && record.error !== null ? record.error : record;
4471
4478
  const details = typeof payload.details === "object" && payload.details !== null ? payload.details : void 0;
4472
- const reason = payload.code === PI_CHAT_REPLAY_GAP_CODE || payload.code === PI_CHAT_CURSOR_AHEAD_CODE ? payload.code : payload.message === PI_CHAT_REPLAY_GAP_CODE || payload.message === PI_CHAT_CURSOR_AHEAD_CODE ? payload.message : details?.reason === PI_CHAT_REPLAY_GAP_CODE || details?.reason === PI_CHAT_CURSOR_AHEAD_CODE ? details.reason : void 0;
4479
+ const gatewayReason = payload.code === "AGENT_SESSION_REPLAY_GAP" ? PI_CHAT_REPLAY_GAP_CODE : payload.code === "AGENT_SESSION_CURSOR_AHEAD" ? PI_CHAT_CURSOR_AHEAD_CODE : void 0;
4480
+ const reason = gatewayReason ?? (payload.code === PI_CHAT_REPLAY_GAP_CODE || payload.code === PI_CHAT_CURSOR_AHEAD_CODE ? payload.code : payload.message === PI_CHAT_REPLAY_GAP_CODE || payload.message === PI_CHAT_CURSOR_AHEAD_CODE ? payload.message : details?.reason === PI_CHAT_REPLAY_GAP_CODE || details?.reason === PI_CHAT_CURSOR_AHEAD_CODE ? details.reason : void 0);
4473
4481
  if (reason !== PI_CHAT_REPLAY_GAP_CODE && reason !== PI_CHAT_CURSOR_AHEAD_CODE) return null;
4474
4482
  const latestSeq = readLatestSeq(payload) ?? readLatestSeq(record);
4475
4483
  if (latestSeq === void 0) return null;
@@ -4678,8 +4686,9 @@ var RemotePiSession = class {
4678
4686
  try {
4679
4687
  const headers = await this.requestHeaders();
4680
4688
  if (!this.isGenerationActive(generation)) return;
4681
- const raw = await this.fetchJson(this.stateUrl(), { method: "GET", headers });
4689
+ const responseBody = await this.fetchJson(this.stateUrl(), { method: "GET", headers });
4682
4690
  if (!this.isGenerationActive(generation)) return;
4691
+ const raw = this.options.agentTypeId ? addressedSnapshot(responseBody) : responseBody;
4683
4692
  this.recordLargeStateWarning(raw);
4684
4693
  if (readProtocolVersion(raw) !== SUPPORTED_PROTOCOL_VERSION) {
4685
4694
  this.dispatchProtocolError(`Unsupported Pi chat protocol version: ${String(readProtocolVersion(raw) ?? "missing")}`);
@@ -4734,7 +4743,7 @@ var RemotePiSession = class {
4734
4743
  markOpen();
4735
4744
  return;
4736
4745
  }
4737
- const response = await this.fetchImpl(buildPiChatEventsUrl({ apiBaseUrl: this.apiBaseUrl, sessionId: this.options.sessionId, cursor }), {
4746
+ const response = await this.fetchImpl(this.eventsUrl(cursor), {
4738
4747
  method: "GET",
4739
4748
  headers,
4740
4749
  signal: controller.signal
@@ -4852,12 +4861,19 @@ var RemotePiSession = class {
4852
4861
  const raw = await this.fetchJson(this.sessionUrl(path), {
4853
4862
  method: "POST",
4854
4863
  headers: { ...headers, "Content-Type": "application/json" },
4855
- body: JSON.stringify(payload)
4864
+ body: JSON.stringify(this.addressedCommandPayload(path, payload))
4856
4865
  });
4857
4866
  if (!this.isGenerationActive(generation)) {
4858
4867
  throw abortError("Remote Pi session disposed before command receipt.");
4859
4868
  }
4860
- return schema.parse(raw);
4869
+ return schema.parse(this.addressedCommandReceipt(path, raw));
4870
+ }
4871
+ addressedCommandReceipt(path, receipt) {
4872
+ if (!this.options.agentTypeId || path !== "/followup" || typeof receipt !== "object" || receipt === null) {
4873
+ return receipt;
4874
+ }
4875
+ const record = receipt;
4876
+ return record.disposition === "followup" ? { ...record, queued: true } : receipt;
4861
4877
  }
4862
4878
  rollbackOptimisticMessage(clientNonce) {
4863
4879
  if (this.disposed) return;
@@ -4898,9 +4914,42 @@ var RemotePiSession = class {
4898
4914
  stateUrl() {
4899
4915
  return this.sessionUrl("/state");
4900
4916
  }
4917
+ eventsUrl(cursor) {
4918
+ if (!this.options.agentTypeId) {
4919
+ return buildPiChatEventsUrl({ apiBaseUrl: this.apiBaseUrl, sessionId: this.options.sessionId, cursor });
4920
+ }
4921
+ return `${this.sessionUrl("/events")}?cursor=${encodeURIComponent(String(cursor))}`;
4922
+ }
4901
4923
  sessionUrl(path) {
4924
+ if (this.options.agentTypeId) {
4925
+ return `${this.apiBaseUrl}/api/v1/agents/${encodeURIComponent(this.options.agentTypeId)}/sessions/${encodeURIComponent(this.options.sessionId)}${path}`;
4926
+ }
4902
4927
  return `${this.apiBaseUrl}/api/v1/agent/pi-chat/${encodeURIComponent(this.options.sessionId)}${path}`;
4903
4928
  }
4929
+ addressedCommandPayload(path, payload) {
4930
+ if (!this.options.agentTypeId || typeof payload !== "object" || payload === null) return payload;
4931
+ const record = payload;
4932
+ if (typeof record.requestId === "string" && record.requestId.length > 0) return payload;
4933
+ if (path === "/prompt" && typeof record.clientNonce === "string" && typeof record.message === "string") {
4934
+ const { message, displayMessage, ...gatewayFields } = record;
4935
+ return {
4936
+ ...gatewayFields,
4937
+ requestId: record.clientNonce,
4938
+ content: message,
4939
+ ...typeof displayMessage === "string" ? { displayContent: displayMessage } : {}
4940
+ };
4941
+ }
4942
+ if (path === "/followup" && typeof record.clientNonce === "string" && typeof record.clientSeq === "number" && typeof record.message === "string") {
4943
+ const { message, displayMessage, ...gatewayFields } = record;
4944
+ return {
4945
+ ...gatewayFields,
4946
+ requestId: `${record.clientNonce}:${record.clientSeq}`,
4947
+ content: message,
4948
+ ...typeof displayMessage === "string" ? { displayContent: displayMessage } : {}
4949
+ };
4950
+ }
4951
+ return payload;
4952
+ }
4904
4953
  dispatchProtocolError(message) {
4905
4954
  if (this.disposed) return;
4906
4955
  const error = { code: ErrorCode.enum.INTERNAL_ERROR, message, retryable: true };
@@ -4945,6 +4994,12 @@ var RemotePiSession = class {
4945
4994
  return this.isGenerationActive(generation) && runId === this.streamRunId;
4946
4995
  }
4947
4996
  };
4997
+ function addressedSnapshot(value) {
4998
+ if (typeof value !== "object" || value === null || !("state" in value)) {
4999
+ throw new Error("Addressed session state response did not include state.");
5000
+ }
5001
+ return value.state;
5002
+ }
4948
5003
  function createRemotePiSession(options) {
4949
5004
  return new RemotePiSession(options);
4950
5005
  }
@@ -5121,7 +5176,8 @@ function isNetworkFetchError(error) {
5121
5176
  function usePiSessions(options = {}) {
5122
5177
  const enabled = options.enabled ?? true;
5123
5178
  const apiBaseUrl = options.apiBaseUrl?.replace(/\/$/, "") ?? "";
5124
- const sessionsApiPath = options.sessionsApiPath ?? DEFAULT_SESSIONS_API_PATH;
5179
+ const addressed = typeof options.agentTypeId === "string" && options.agentTypeId.length > 0;
5180
+ const sessionsApiPath = options.sessionsApiPath ?? (addressed ? `/api/v1/agents/${encodeURIComponent(options.agentTypeId)}/sessions` : DEFAULT_SESSIONS_API_PATH);
5125
5181
  const storageScope = options.storageScope ?? "default";
5126
5182
  const fetchImpl = useMemo3(() => options.fetch ?? globalThis.fetch.bind(globalThis), [options.fetch]);
5127
5183
  const createRemoteSession = options.createRemoteSession ?? createRemotePiSession;
@@ -5148,6 +5204,7 @@ function usePiSessions(options = {}) {
5148
5204
  const activeSessionIdRef = useRef8(activeSessionId);
5149
5205
  const hasMoreRef = useRef8(hasMore);
5150
5206
  const canonicalLoadedCountRef = useRef8(0);
5207
+ const nextCursorRef = useRef8(void 0);
5151
5208
  const loadMoreRequestSeqRef = useRef8(0);
5152
5209
  const loadMoreInFlightRef = useRef8(false);
5153
5210
  const pendingCreatedRef = useRef8(/* @__PURE__ */ new Map());
@@ -5174,16 +5231,21 @@ function usePiSessions(options = {}) {
5174
5231
  const activeSessionKnown = Boolean(activeSessionId && sessions.some((session) => session.id === activeSessionId));
5175
5232
  const requestHeaders = useCallback7(() => normalizedHeaders, [normalizedHeaders]);
5176
5233
  const sessionsUrl = useCallback7((suffix = "") => `${apiBaseUrl}${sessionsApiPath}${suffix}`, [apiBaseUrl, sessionsApiPath]);
5177
- const sessionsListUrl = useCallback7((offset = 0, includeId) => {
5234
+ const sessionsListUrl = useCallback7((offset = 0, includeId, cursor) => {
5178
5235
  const query = new URLSearchParams();
5179
- if (offset > 0) {
5236
+ if (addressed) {
5180
5237
  query.set("limit", String(SESSION_PAGE_SIZE));
5181
- query.set("offset", String(offset));
5238
+ if (cursor) query.set("cursor", cursor);
5239
+ } else {
5240
+ if (offset > 0) {
5241
+ query.set("limit", String(SESSION_PAGE_SIZE));
5242
+ query.set("offset", String(offset));
5243
+ }
5244
+ if (offset <= 0 && includeId) query.set("activeSessionId", includeId);
5182
5245
  }
5183
- if (offset <= 0 && includeId) query.set("activeSessionId", includeId);
5184
5246
  if (query.size === 0) return sessionsUrl();
5185
5247
  return sessionsUrl(`?${query.toString()}`);
5186
- }, [sessionsUrl]);
5248
+ }, [addressed, sessionsUrl]);
5187
5249
  const persistActive = useCallback7((id) => {
5188
5250
  writeActiveSessionId(id, { storageScope, storage: options.storage });
5189
5251
  }, [options.storage, storageScope]);
@@ -5206,7 +5268,7 @@ function usePiSessions(options = {}) {
5206
5268
  const pendingCreated = pendingCreatedRef.current;
5207
5269
  for (const session of data) pendingCreated.delete(session.id);
5208
5270
  const canonicalCount = canonicalPageCount(data);
5209
- const pageMayHaveMore = data.length >= SESSION_PAGE_SIZE;
5271
+ const pageMayHaveMore = addressed ? applyOptions.nextCursor !== void 0 : data.length >= SESSION_PAGE_SIZE;
5210
5272
  const wasExhaustedBeyondFirstPage = applyOptions.background && !hasMoreRef.current && canonicalLoadedCountRef.current >= canonicalCount;
5211
5273
  const requestedActiveReturned = Boolean(requestedActiveId && data.some((session) => session.id === requestedActiveId));
5212
5274
  const current = applyOptions.background && pageMayHaveMore ? sessionsRef.current.filter((session) => !requestedActiveId || requestedActiveReturned || session.id !== requestedActiveId) : [];
@@ -5217,6 +5279,7 @@ function usePiSessions(options = {}) {
5217
5279
  dataStorageScopeRef.current = storageScope;
5218
5280
  setDataStorageScope(storageScope);
5219
5281
  setSessions(merged);
5282
+ nextCursorRef.current = applyOptions.nextCursor;
5220
5283
  setHasMore(nextHasMore);
5221
5284
  setActiveSessionId((previous) => {
5222
5285
  const preferred = replacingScope ? replacingScopePreferred : previous ?? preferredSessionId();
@@ -5224,7 +5287,7 @@ function usePiSessions(options = {}) {
5224
5287
  persistActive(next);
5225
5288
  return next;
5226
5289
  });
5227
- }, [dataSourceKey, ensurePendingScope, persistActive, preferredSessionId, storageScope]);
5290
+ }, [addressed, dataSourceKey, ensurePendingScope, persistActive, preferredSessionId, storageScope]);
5228
5291
  const refresh = useCallback7(async (refreshOptions = {}) => {
5229
5292
  const version = ++refreshVersionRef.current;
5230
5293
  const isCurrent = () => mountedRef.current && version === refreshVersionRef.current;
@@ -5251,10 +5314,10 @@ function usePiSessions(options = {}) {
5251
5314
  setLoadingMore(false);
5252
5315
  if (!background) setLoading(true);
5253
5316
  try {
5254
- let data;
5317
+ let page;
5255
5318
  for (let attempt = 0; ; attempt += 1) {
5256
5319
  try {
5257
- data = await fetchSessionList(fetchImpl, sessionsListUrl(0, preferredSessionId()), requestHeaders());
5320
+ page = await fetchSessionList(fetchImpl, sessionsListUrl(0, preferredSessionId()), requestHeaders(), addressed);
5258
5321
  break;
5259
5322
  } catch (err) {
5260
5323
  const transient = err instanceof SessionsPreparingError || isNetworkFetchError(err);
@@ -5265,16 +5328,18 @@ function usePiSessions(options = {}) {
5265
5328
  if (!isCurrent()) return;
5266
5329
  }
5267
5330
  }
5268
- if (!isCurrent() || !data) return;
5269
- applySessions(data, { background });
5331
+ if (!isCurrent() || !page) return;
5332
+ applySessions(page.sessions, { background, nextCursor: page.nextCursor });
5270
5333
  setError(void 0);
5271
5334
  setLoading(false);
5272
5335
  } catch (err) {
5273
5336
  if (!isCurrent()) return;
5274
- if (!background) setError(err instanceof Error ? err : new Error(String(err)));
5337
+ const error2 = err instanceof Error ? err : new Error(String(err));
5338
+ if (!background) setError(error2);
5275
5339
  setLoading(false);
5340
+ if (refreshOptions.throwOnError) throw error2;
5276
5341
  }
5277
- }, [applySessions, enabled, fetchImpl, persistActive, preferredSessionId, requestHeaders, retryBaseMs, retryMaxMs, retryMaxRetries, sessionsListUrl]);
5342
+ }, [addressed, applySessions, enabled, fetchImpl, persistActive, preferredSessionId, requestHeaders, retryBaseMs, retryMaxMs, retryMaxRetries, sessionsListUrl]);
5278
5343
  useEffect8(() => {
5279
5344
  mountedRef.current = true;
5280
5345
  void refresh();
@@ -5293,11 +5358,13 @@ function usePiSessions(options = {}) {
5293
5358
  const offset = canonicalLoadedCountRef.current;
5294
5359
  setLoadingMore(true);
5295
5360
  try {
5296
- const data = await fetchSessionList(fetchImpl, sessionsListUrl(offset), requestHeaders());
5361
+ const page = await fetchSessionList(fetchImpl, sessionsListUrl(offset, void 0, nextCursorRef.current), requestHeaders(), addressed);
5362
+ const data = page.sessions;
5297
5363
  if (!mountedRef.current || requestSeq !== loadMoreRequestSeqRef.current || version !== refreshVersionRef.current || scope !== requestScopeRef.current) return;
5298
5364
  const merged = mergeSessions(sessionsRef.current, data);
5299
- const nextHasMore = data.length >= SESSION_PAGE_SIZE;
5365
+ const nextHasMore = addressed ? page.nextCursor !== void 0 : data.length >= SESSION_PAGE_SIZE;
5300
5366
  canonicalLoadedCountRef.current += data.length;
5367
+ nextCursorRef.current = page.nextCursor;
5301
5368
  setSessions(merged);
5302
5369
  setHasMore(nextHasMore);
5303
5370
  setError(void 0);
@@ -5317,7 +5384,7 @@ function usePiSessions(options = {}) {
5317
5384
  setLoadingMore(false);
5318
5385
  }
5319
5386
  }
5320
- }, [enabled, fetchImpl, hasMore, loading, loadingMore, persistActive, requestHeaders, requestScopeKey, sessionsListUrl]);
5387
+ }, [addressed, enabled, fetchImpl, hasMore, loading, loadingMore, persistActive, requestHeaders, requestScopeKey, sessionsListUrl]);
5321
5388
  useEffect8(() => {
5322
5389
  if (!enabled || !connectActiveSession || !activeSessionId || !activeSessionKnown) {
5323
5390
  setActivePiSession(void 0);
@@ -5326,6 +5393,7 @@ function usePiSessions(options = {}) {
5326
5393
  const session = createRemoteSession({
5327
5394
  ...remoteSessionOptionsRef.current,
5328
5395
  sessionId: activeSessionId,
5396
+ agentTypeId: options.agentTypeId,
5329
5397
  workspaceId: options.workspaceId,
5330
5398
  storageScope,
5331
5399
  apiBaseUrl,
@@ -5336,7 +5404,7 @@ function usePiSessions(options = {}) {
5336
5404
  return () => {
5337
5405
  session.dispose();
5338
5406
  };
5339
- }, [activeSessionId, activeSessionKnown, apiBaseUrl, connectActiveSession, createRemoteSession, enabled, fetchImpl, remoteSessionOptionsKey, options.workspaceId, requestHeaders, storageScope]);
5407
+ }, [activeSessionId, activeSessionKnown, apiBaseUrl, connectActiveSession, createRemoteSession, enabled, fetchImpl, remoteSessionOptionsKey, options.agentTypeId, options.workspaceId, requestHeaders, storageScope]);
5340
5408
  const create = useCallback7(async (init) => {
5341
5409
  if (!enabled) throw new Error("Pi sessions are disabled");
5342
5410
  const response = await fetchImpl(sessionsUrl(), {
@@ -5349,7 +5417,8 @@ function usePiSessions(options = {}) {
5349
5417
  setError(err);
5350
5418
  throw err;
5351
5419
  }
5352
- const session = toSessionSummary(await response.json());
5420
+ const body = await response.json();
5421
+ const session = addressed ? addressedCreatedSession(body, init?.title) : toSessionSummary(body);
5353
5422
  ensurePendingScope();
5354
5423
  pendingCreatedRef.current.set(session.id, session);
5355
5424
  setDataStorageScope(storageScope);
@@ -5358,7 +5427,7 @@ function usePiSessions(options = {}) {
5358
5427
  persistActive(session.id);
5359
5428
  void refresh();
5360
5429
  return session;
5361
- }, [enabled, ensurePendingScope, fetchImpl, persistActive, refresh, requestHeaders, sessionsUrl, storageScope]);
5430
+ }, [addressed, enabled, ensurePendingScope, fetchImpl, persistActive, refresh, requestHeaders, sessionsUrl, storageScope]);
5362
5431
  const switchSession = useCallback7((id) => {
5363
5432
  const known = sessionsRef.current.some((session) => session.id === id);
5364
5433
  const next = known ? id : sessionsRef.current[0]?.id;
@@ -5396,6 +5465,7 @@ function usePiSessions(options = {}) {
5396
5465
  loadMoreRequestSeqRef.current += 1;
5397
5466
  loadMoreInFlightRef.current = false;
5398
5467
  canonicalLoadedCountRef.current = canonicalPageCount(sessionsRef.current);
5468
+ nextCursorRef.current = void 0;
5399
5469
  loadedDataSourceRef.current = dataSourceKey;
5400
5470
  dataStorageScopeRef.current = storageScope;
5401
5471
  setDataStorageScope(storageScope);
@@ -5424,13 +5494,23 @@ function usePiSessions(options = {}) {
5424
5494
  reset
5425
5495
  };
5426
5496
  }
5427
- async function fetchSessionList(fetchImpl, url, headers) {
5497
+ async function fetchSessionList(fetchImpl, url, headers, addressed) {
5428
5498
  const response = await fetchImpl(url, Object.keys(headers).length > 0 ? { headers } : void 0);
5429
5499
  if (response.status === 503) throw new SessionsPreparingError();
5430
5500
  if (!response.ok) throw new Error(`Failed to load sessions: ${response.status}`);
5431
5501
  const body = await response.json();
5432
- if (!Array.isArray(body)) throw new Error("Failed to load sessions: invalid response");
5433
- return body.map(toSessionSummary);
5502
+ if (!addressed) {
5503
+ if (!Array.isArray(body)) throw new Error("Failed to load sessions: invalid response");
5504
+ return { sessions: body.map(toSessionSummary) };
5505
+ }
5506
+ if (typeof body !== "object" || body === null || !Array.isArray(body.sessions)) {
5507
+ throw new Error("Failed to load sessions: invalid response");
5508
+ }
5509
+ const page = body;
5510
+ return {
5511
+ sessions: page.sessions.map(toAddressedSessionSummary),
5512
+ ...typeof page.nextCursor === "string" ? { nextCursor: page.nextCursor } : {}
5513
+ };
5434
5514
  }
5435
5515
  function toSessionSummary(value) {
5436
5516
  if (typeof value !== "object" || value === null) throw new Error("invalid session summary");
@@ -5445,6 +5525,36 @@ function toSessionSummary(value) {
5445
5525
  turnCount: typeof record.turnCount === "number" ? record.turnCount : 0
5446
5526
  };
5447
5527
  }
5528
+ function toAddressedSessionSummary(value) {
5529
+ if (typeof value !== "object" || value === null) throw new Error("invalid addressed session summary");
5530
+ const record = value;
5531
+ const ref = record.ref;
5532
+ if (typeof ref !== "object" || ref === null || typeof ref.sessionId !== "string") {
5533
+ throw new Error("invalid addressed session ref");
5534
+ }
5535
+ const createdAt = typeof record.createdAt === "number" ? new Date(record.createdAt).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString();
5536
+ const updatedAt = typeof record.updatedAt === "number" ? new Date(record.updatedAt).toISOString() : createdAt;
5537
+ return {
5538
+ id: ref.sessionId,
5539
+ title: typeof record.title === "string" ? record.title : "Untitled",
5540
+ createdAt,
5541
+ updatedAt,
5542
+ turnCount: 0
5543
+ };
5544
+ }
5545
+ function addressedCreatedSession(value, title) {
5546
+ if (typeof value !== "object" || value === null || typeof value.sessionId !== "string") {
5547
+ throw new Error("invalid addressed session ref");
5548
+ }
5549
+ const now = (/* @__PURE__ */ new Date()).toISOString();
5550
+ return {
5551
+ id: value.sessionId,
5552
+ title: title ?? "Untitled",
5553
+ createdAt: now,
5554
+ updatedAt: now,
5555
+ turnCount: 0
5556
+ };
5557
+ }
5448
5558
  function canonicalPageCount(data) {
5449
5559
  return Math.min(data.length, SESSION_PAGE_SIZE);
5450
5560
  }
@@ -8009,10 +8119,10 @@ function ThinkingLevelGlyph({ level }) {
8009
8119
  }
8010
8120
  );
8011
8121
  }
8012
- function modelTriggerLabel(value, options) {
8122
+ function modelTriggerLabel(value, options, emptyLabel = "Default model") {
8013
8123
  const current = value ? options.find((m) => m.provider === value.provider && m.id === value.id) : void 0;
8014
8124
  const rawTriggerLabel = current?.label ?? value?.id;
8015
- return value ? rawTriggerLabel && current?.label && current.label !== value.id && /[A-Z]/.test(current.label) ? current.label : displayModelLabel(rawTriggerLabel ?? value.id) : "Default model";
8125
+ return value ? rawTriggerLabel && current?.label && current.label !== value.id && /[A-Z]/.test(current.label) ? current.label : displayModelLabel(rawTriggerLabel ?? value.id) : emptyLabel;
8016
8126
  }
8017
8127
  function modelMenuOptions(_value, options) {
8018
8128
  return options.filter((m) => m.available);
@@ -8032,11 +8142,12 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
8032
8142
  disabled,
8033
8143
  trigger = "button",
8034
8144
  open = false,
8145
+ emptyLabel,
8035
8146
  onClick,
8036
8147
  className,
8037
8148
  ...props
8038
8149
  }, ref) {
8039
- const triggerLabel = modelTriggerLabel(value, options);
8150
+ const triggerLabel = modelTriggerLabel(value, options, emptyLabel);
8040
8151
  const triggerDisplay = value ? `${triggerLabel} (${displayProviderLabel(value.provider)})` : triggerLabel;
8041
8152
  return /* @__PURE__ */ jsx27(
8042
8153
  "button",
@@ -8100,7 +8211,7 @@ function ModelPickerMenu({
8100
8211
  onClose?.();
8101
8212
  return;
8102
8213
  }
8103
- if (disabled || isTextInputTarget(event.target)) return;
8214
+ if (disabled || isTextInputTarget(event.target) || keyboardOptions.length === 0) return;
8104
8215
  if (event.key === "ArrowDown") {
8105
8216
  event.preventDefault();
8106
8217
  setKeyboardActiveIndex((index) => Math.min(index + 1, keyboardOptions.length - 1));
@@ -8202,7 +8313,12 @@ function ModelSelect({
8202
8313
  options,
8203
8314
  disabled,
8204
8315
  trigger = "button",
8205
- openSignal
8316
+ openSignal,
8317
+ className,
8318
+ emptyLabel,
8319
+ ariaInvalid,
8320
+ ariaDescribedBy,
8321
+ hideDefaultOption = false
8206
8322
  }) {
8207
8323
  const [open, setOpen] = useState16(false);
8208
8324
  const previousOpenSignalRef = useRef13(openSignal);
@@ -8225,7 +8341,11 @@ function ModelSelect({
8225
8341
  options,
8226
8342
  disabled,
8227
8343
  trigger,
8228
- open
8344
+ open,
8345
+ className,
8346
+ emptyLabel,
8347
+ "aria-invalid": ariaInvalid || void 0,
8348
+ "aria-describedby": ariaDescribedBy
8229
8349
  }
8230
8350
  ) }),
8231
8351
  /* @__PURE__ */ jsx27(
@@ -8244,6 +8364,62 @@ function ModelSelect({
8244
8364
  onChange,
8245
8365
  options,
8246
8366
  disabled,
8367
+ hideDefaultOption,
8368
+ onClose: () => setOpen(false),
8369
+ className: "mb-0 rounded-none border-0 bg-transparent shadow-none"
8370
+ }
8371
+ )
8372
+ }
8373
+ )
8374
+ ] });
8375
+ }
8376
+ function ThinkingSelect({
8377
+ value,
8378
+ onChange,
8379
+ disabled,
8380
+ trigger = "button",
8381
+ openSignal,
8382
+ className
8383
+ }) {
8384
+ const [open, setOpen] = useState16(false);
8385
+ const previousOpenSignalRef = useRef13(openSignal);
8386
+ useEffect17(() => {
8387
+ if (disabled) setOpen(false);
8388
+ }, [disabled]);
8389
+ useEffect17(() => {
8390
+ if (disabled || openSignal === void 0) {
8391
+ previousOpenSignalRef.current = openSignal;
8392
+ return;
8393
+ }
8394
+ if (previousOpenSignalRef.current !== openSignal) setOpen(true);
8395
+ previousOpenSignalRef.current = openSignal;
8396
+ }, [disabled, openSignal]);
8397
+ return /* @__PURE__ */ jsxs25(Popover, { open, onOpenChange: disabled ? void 0 : setOpen, children: [
8398
+ /* @__PURE__ */ jsx27(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx27(
8399
+ ThinkingSelectTrigger,
8400
+ {
8401
+ value,
8402
+ disabled,
8403
+ trigger,
8404
+ open,
8405
+ className
8406
+ }
8407
+ ) }),
8408
+ /* @__PURE__ */ jsx27(
8409
+ PopoverContent,
8410
+ {
8411
+ align: trigger === "slash" ? "center" : "end",
8412
+ side: "top",
8413
+ sideOffset: trigger === "slash" ? 54 : 6,
8414
+ collisionPadding: 12,
8415
+ "data-boring-agent": "",
8416
+ className: cn("w-[min(92vw,240px)]", selectorContentClass),
8417
+ children: /* @__PURE__ */ jsx27(
8418
+ ThinkingPickerMenu,
8419
+ {
8420
+ value,
8421
+ onChange,
8422
+ disabled,
8247
8423
  onClose: () => setOpen(false),
8248
8424
  className: "mb-0 rounded-none border-0 bg-transparent shadow-none"
8249
8425
  }
@@ -9531,6 +9707,7 @@ function getHeaderValue(headers, name) {
9531
9707
  import { useCallback as useCallback17, useEffect as useEffect20, useMemo as useMemo12, useRef as useRef16, useState as useState19, useSyncExternalStore } from "react";
9532
9708
  function useExternalRemotePiSession({
9533
9709
  sessionId,
9710
+ agentTypeId,
9534
9711
  workspaceId,
9535
9712
  storageScope,
9536
9713
  apiBaseUrl,
@@ -9554,6 +9731,7 @@ function useExternalRemotePiSession({
9554
9731
  const next = (createRemoteSession ?? createRemotePiSession)({
9555
9732
  ...remoteSessionOptionsRef.current,
9556
9733
  sessionId,
9734
+ agentTypeId,
9557
9735
  workspaceId,
9558
9736
  storageScope,
9559
9737
  apiBaseUrl,
@@ -9562,7 +9740,7 @@ function useExternalRemotePiSession({
9562
9740
  });
9563
9741
  setSession(next);
9564
9742
  return () => next.dispose();
9565
- }, [apiBaseUrl, createRemoteSession, fetch2, remoteSessionOptionsKey, requestHeaders, sessionId, storageScope, workspaceId]);
9743
+ }, [agentTypeId, apiBaseUrl, createRemoteSession, fetch2, remoteSessionOptionsKey, requestHeaders, sessionId, storageScope, workspaceId]);
9566
9744
  return session;
9567
9745
  }
9568
9746
  var remoteSessionOptionObjectIds2 = /* @__PURE__ */ new WeakMap();
@@ -9729,6 +9907,7 @@ function normalizeAgentPluginReloadResult(result) {
9729
9907
  }
9730
9908
  function PiChatPanel({
9731
9909
  sessionId,
9910
+ agentTypeId,
9732
9911
  extraCommands,
9733
9912
  apiBaseUrl,
9734
9913
  workspaceId,
@@ -9804,6 +9983,7 @@ function PiChatPanel({
9804
9983
  }), [hydrateMessages, remoteSessionOptions]);
9805
9984
  const sessions = usePiSessions({
9806
9985
  apiBaseUrl,
9986
+ agentTypeId,
9807
9987
  workspaceId,
9808
9988
  storageScope,
9809
9989
  requestHeaders,
@@ -9828,6 +10008,7 @@ function PiChatPanel({
9828
10008
  }, [externalSessionId, sessions.refresh]);
9829
10009
  const externalPiSession = useExternalRemotePiSession({
9830
10010
  sessionId: externalSessionId,
10011
+ agentTypeId,
9831
10012
  workspaceId,
9832
10013
  storageScope,
9833
10014
  apiBaseUrl,
@@ -10424,9 +10605,13 @@ function PiChatPanel({
10424
10605
  useEffect21(() => {
10425
10606
  if (typeof window === "undefined" || !activeChatSessionId) return;
10426
10607
  window.dispatchEvent(new CustomEvent("boring:chat-session-status", {
10427
- detail: { sessionId: activeChatSessionId, working: isStreaming }
10608
+ detail: {
10609
+ sessionId: activeChatSessionId,
10610
+ ...agentTypeId ? { agentTypeId } : {},
10611
+ working: isStreaming
10612
+ }
10428
10613
  }));
10429
- }, [activeChatSessionId, isStreaming]);
10614
+ }, [activeChatSessionId, agentTypeId, isStreaming]);
10430
10615
  const onTextareaKeyDown = useCallback18((event) => {
10431
10616
  if (event.key === "Escape" && isStreaming) {
10432
10617
  if (event.defaultPrevented || mentionState !== null || slashQuery !== null) {
@@ -10646,6 +10831,7 @@ export {
10646
10831
  Reasoning,
10647
10832
  ReasoningContent,
10648
10833
  ReasoningTrigger,
10834
+ ThinkingSelect,
10649
10835
  ToolCallGroup,
10650
10836
  activeSessionStorageKey,
10651
10837
  builtinCommands,
@@ -1,4 +1,4 @@
1
- import { l as SessionCtx, b as PiChatEvent, S as SessionStore } from './piChatEvent-nmOBSNU9.js';
1
+ import { l as SessionCtx, b as PiChatEvent, S as SessionStore } from './piChatEvent-DBO3M5lu.js';
2
2
  import { AgentSessionEvent, PromptOptions } from '@mariozechner/pi-coding-agent';
3
3
 
4
4
  interface TelemetrySink {
@@ -268,4 +268,4 @@ interface RunContext {
268
268
  allowPromptDispatch?: boolean;
269
269
  }
270
270
 
271
- export { type AgentHarness as A, type ToolResult as B, noopTelemetry as C, safeCapture as D, sessionStreamPath as E, type JSONSchema as J, type MessageAttachment as M, type RunContext as R, type SendMessageInput as S, type TelemetrySink as T, type AgentReadiness as a, type Agent as b, AGENT_NOT_IMPLEMENTED_UNTIL_T1 as c, type AgentActor as d, type AgentCoreHarness as e, type AgentCoreHarnessFactory as f, type AgentCorePromptInput as g, type AgentCoreSessionAdapter as h, type AgentCoreSessionSnapshot as i, type AgentEvent as j, type AgentMessageContent as k, type AgentMessagePart as l, AgentNotImplementedError as m, type AgentReadinessStatus as n, type AgentResolveInputResponse as o, type AgentSendInput as p, type AgentStartReceipt as q, type AgentStreamOptions as r, type ToolReadinessRequirement as s, type AgentConfig as t, type AgentTool as u, type AgentHarnessFactory as v, type AgentHarnessFactoryInput as w, type AgentRuntimeAdapter as x, type TelemetryEvent as y, type ToolExecContext as z };
271
+ export { type AgentHarness as A, type ToolResult as B, noopTelemetry as C, safeCapture as D, sessionStreamPath as E, type JSONSchema as J, type MessageAttachment as M, type RunContext as R, type SendMessageInput as S, type TelemetrySink as T, type AgentReadiness as a, type Agent as b, AGENT_NOT_IMPLEMENTED_UNTIL_T1 as c, type AgentActor as d, type AgentCoreHarness as e, type AgentCoreHarnessFactory as f, type AgentCorePromptInput as g, type AgentCoreSessionAdapter as h, type AgentCoreSessionSnapshot as i, type AgentEvent as j, type AgentMessageContent as k, type AgentMessagePart as l, AgentNotImplementedError as m, type AgentReadinessStatus as n, type AgentResolveInputResponse as o, type AgentSendInput as p, type AgentStartReceipt as q, type AgentStreamOptions as r, type AgentConfig as s, type AgentTool as t, type AgentHarnessFactory as u, type AgentHarnessFactoryInput as v, type ToolReadinessRequirement as w, type AgentRuntimeAdapter as x, type TelemetryEvent as y, type ToolExecContext as z };