@promptbook/cli 0.113.0-5 → 0.113.0-7

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 (105) hide show
  1. package/apps/agents-server/src/app/admin/update/AdvancedOriginRepositoryPanel.tsx +76 -0
  2. package/apps/agents-server/src/app/admin/update/CurrentDeploymentCard.tsx +160 -0
  3. package/apps/agents-server/src/app/admin/update/PendingCommitsCard.tsx +86 -0
  4. package/apps/agents-server/src/app/admin/update/TargetEnvironmentCard.tsx +331 -0
  5. package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +20 -873
  6. package/apps/agents-server/src/app/admin/update/UpdateJobCard.tsx +329 -0
  7. package/apps/agents-server/src/app/admin/update/UpdateOverview.ts +74 -0
  8. package/apps/agents-server/src/app/admin/update/buildDeploymentTimeBehindLabel.ts +29 -0
  9. package/apps/agents-server/src/app/admin/update/formatHumanReadableTimestamp.ts +18 -0
  10. package/apps/agents-server/src/app/admin/update/getUpdateJobFailureMessage.ts +13 -0
  11. package/apps/agents-server/src/app/admin/update/getUpdateJobSuccessMessage.ts +13 -0
  12. package/apps/agents-server/src/app/admin/update/useUpdateClientState.ts +441 -0
  13. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +13 -1
  14. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageClient.tsx +14 -559
  15. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageHeader.tsx +84 -0
  16. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageSection.tsx +52 -0
  17. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedCodePreview.tsx +138 -0
  18. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedHarnessSection.tsx +98 -0
  19. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/SourceBookSection.tsx +66 -0
  20. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeErrorBanner.tsx +30 -0
  21. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeExportWarningBanner.tsx +62 -0
  22. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/Transpiler.ts +9 -0
  23. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/useAgentCodeExportState.ts +478 -0
  24. package/apps/agents-server/src/app/system/utilities/mocked-chats/cloneMockedChatPreset.ts +17 -0
  25. package/apps/agents-server/src/app/system/utilities/mocked-chats/confirmDeleteMockedChat.ts +16 -0
  26. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedMessage.ts +81 -0
  27. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedParticipant.ts +146 -0
  28. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedSettings.ts +19 -0
  29. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDuplicatedDraft.ts +66 -0
  30. package/apps/agents-server/src/app/system/utilities/mocked-chats/findMockedChatById.ts +51 -0
  31. package/apps/agents-server/src/app/system/utilities/mocked-chats/persistMockedChats.ts +51 -0
  32. package/apps/agents-server/src/app/system/utilities/mocked-chats/useMockedChatsEditorState.ts +16 -426
  33. package/apps/agents-server/src/components/Homepage/buildFreeGraphBoxLayout.ts +446 -0
  34. package/apps/agents-server/src/components/Homepage/buildGraphLayoutNodes.ts +415 -157
  35. package/apps/agents-server/src/components/Homepage/useAgentsGraphCanvasState.ts +2 -1
  36. package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +3 -1541
  37. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteQueryBuilder.ts +623 -0
  38. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteSupabaseClient.ts +64 -0
  39. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/ensureTable.ts +93 -0
  40. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteFilters.ts +202 -0
  41. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteMutationPayload.ts +131 -0
  42. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteRowOperations.ts +102 -0
  43. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteSql.ts +59 -0
  44. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTableSchema.ts +329 -0
  45. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTypes.ts +84 -0
  46. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteValueCodec.ts +63 -0
  47. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/normalizeSqliteError.ts +22 -0
  48. package/apps/agents-server/src/search/createDefaultServerSearchProviders/loadLocalOrganizationSearchDataset.ts +12 -1
  49. package/apps/agents-server/src/tools/send_email.ts +1 -2
  50. package/apps/agents-server/src/utils/agentOrganization/loadAgentOrganizationState.ts +13 -1
  51. package/apps/agents-server/src/utils/createLocalAgentSourceImporter.ts +159 -0
  52. package/apps/agents-server/src/utils/createMissingImportedAgentFallback.ts +60 -0
  53. package/apps/agents-server/src/utils/customDomainRouting.ts +157 -12
  54. package/apps/agents-server/src/utils/externalChatRunner/processExternalUserChatJob.ts +1 -1
  55. package/apps/agents-server/src/utils/importAgentWithFallback.ts +1 -58
  56. package/apps/agents-server/src/utils/localAgentRouteReferences.ts +167 -0
  57. package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +1 -1
  58. package/apps/agents-server/src/utils/managementApi/managementApiAgents.ts +17 -3
  59. package/apps/agents-server/src/utils/messages/sendMessage.ts +5 -3
  60. package/apps/agents-server/src/utils/resolveAgentStateFromSource.ts +7 -1
  61. package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +54 -5
  62. package/apps/agents-server/src/utils/resolveServerAgentContext.ts +12 -1
  63. package/apps/agents-server/src/utils/resolveStoredAgentState.ts +2 -1
  64. package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition/SpeechToTextFailoverRecognitionProviderRuntime.ts +0 -1
  65. package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition.ts +34 -2
  66. package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +39 -9
  67. package/apps/agents-server/tests/e2e/support/ChatHistoryNavigationSupport.ts +5 -0
  68. package/esm/index.es.js +96 -57
  69. package/esm/index.es.js.map +1 -1
  70. package/esm/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
  71. package/esm/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
  72. package/esm/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
  73. package/esm/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
  74. package/esm/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
  75. package/esm/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
  76. package/esm/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
  77. package/esm/src/version.d.ts +1 -1
  78. package/package.json +1 -1
  79. package/src/avatars/avatarAnimationScheduler.ts +2 -1
  80. package/src/avatars/visuals/octopus3d3AvatarVisual.ts +6 -2
  81. package/src/avatars/visuals/octopus3d4AvatarVisual.ts +14 -18
  82. package/src/book-components/Chat/Chat/insertDictationChunk.ts +3 -3
  83. package/src/book-components/Chat/Chat/learnDictationDictionary.ts +1 -1
  84. package/src/book-components/Chat/Chat/useChatInputAreaDictation.ts +133 -26
  85. package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +3 -1
  86. package/src/cli/cli-commands/coder/boilerplateTemplates.ts +14 -21
  87. package/src/cli/cli-commands/coder/find-refactor-candidates.ts +9 -2
  88. package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +1 -4
  89. package/src/cli/cli-commands/coder/run.ts +3 -27
  90. package/src/cli/cli-commands/common/createPositiveIntegerOptionParser.ts +31 -0
  91. package/src/commitments/TEAM/TEAM.ts +5 -5
  92. package/src/other/templates/getTemplatesPipelineCollection.ts +678 -728
  93. package/src/utils/ascii-art/convertImageDataToAsciiArt.ts +1 -4
  94. package/src/version.ts +2 -2
  95. package/src/versions.txt +1 -0
  96. package/umd/index.umd.js +96 -57
  97. package/umd/index.umd.js.map +1 -1
  98. package/umd/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
  99. package/umd/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
  100. package/umd/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
  101. package/umd/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
  102. package/umd/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
  103. package/umd/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
  104. package/umd/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
  105. package/umd/src/version.d.ts +1 -1
@@ -0,0 +1,167 @@
1
+ import type { string_agent_url } from '../../../../src/types/typeAliases';
2
+
3
+ /**
4
+ * Parsed local agent route reference.
5
+ */
6
+ export type LocalAgentRouteReference = {
7
+ /**
8
+ * Matched same-instance server origin.
9
+ */
10
+ readonly localServerUrl: string;
11
+
12
+ /**
13
+ * Decoded route identifier after `/agents/`.
14
+ */
15
+ readonly agentIdentifier: string;
16
+ };
17
+
18
+ /**
19
+ * Exact local route alias for one agent URL.
20
+ */
21
+ export type LocalAgentUrlReference = LocalAgentRouteReference & {
22
+ /**
23
+ * Normalized exact local agent URL.
24
+ */
25
+ readonly agentUrl: string;
26
+ };
27
+
28
+ /**
29
+ * Normalizes same-instance server URLs for route matching.
30
+ *
31
+ * @param localServerUrls - Raw server URLs.
32
+ * @returns Unique normalized origins without trailing slash.
33
+ */
34
+ export function normalizeLocalServerUrls(localServerUrls: ReadonlyArray<string>): ReadonlyArray<string> {
35
+ return [
36
+ ...new Set(
37
+ localServerUrls
38
+ .map((localServerUrl) => normalizeServerUrl(localServerUrl))
39
+ .filter((localServerUrl) => localServerUrl.length > 0),
40
+ ),
41
+ ];
42
+ }
43
+
44
+ /**
45
+ * Normalizes exact local agent URL aliases for route matching.
46
+ *
47
+ * @param localAgentUrls - Raw local agent URLs.
48
+ * @returns Unique normalized route references.
49
+ */
50
+ export function normalizeLocalAgentUrlReferences(
51
+ localAgentUrls: ReadonlyArray<string_agent_url>,
52
+ ): ReadonlyArray<LocalAgentUrlReference> {
53
+ const localAgentUrlReferences: Array<LocalAgentUrlReference> = [];
54
+ const seenAgentUrls = new Set<string>();
55
+
56
+ for (const localAgentUrl of localAgentUrls) {
57
+ const localAgentRouteReference = parseLocalAgentRouteReference(localAgentUrl);
58
+
59
+ if (!localAgentRouteReference) {
60
+ continue;
61
+ }
62
+
63
+ const normalizedAgentUrl = createLocalAgentUrl(
64
+ localAgentRouteReference.localServerUrl,
65
+ localAgentRouteReference.agentIdentifier,
66
+ );
67
+
68
+ if (seenAgentUrls.has(normalizedAgentUrl)) {
69
+ continue;
70
+ }
71
+
72
+ seenAgentUrls.add(normalizedAgentUrl);
73
+ localAgentUrlReferences.push({
74
+ ...localAgentRouteReference,
75
+ agentUrl: normalizedAgentUrl,
76
+ });
77
+ }
78
+
79
+ return localAgentUrlReferences;
80
+ }
81
+
82
+ /**
83
+ * Extracts a local agent identifier from a same-instance agent URL.
84
+ *
85
+ * @param agentUrl - Referenced agent URL.
86
+ * @param localServerUrls - Normalized same-instance server origins.
87
+ * @param localAgentUrlReferences - Exact agent URL aliases that should resolve locally.
88
+ * @returns Route reference or `null` when the URL belongs to another server.
89
+ */
90
+ export function resolveLocalAgentRouteReference(
91
+ agentUrl: string_agent_url,
92
+ localServerUrls: ReadonlyArray<string>,
93
+ localAgentUrlReferences: ReadonlyArray<LocalAgentUrlReference>,
94
+ ): LocalAgentRouteReference | null {
95
+ const localAgentRouteReference = parseLocalAgentRouteReference(agentUrl);
96
+
97
+ if (!localAgentRouteReference) {
98
+ return null;
99
+ }
100
+
101
+ if (localServerUrls.includes(localAgentRouteReference.localServerUrl)) {
102
+ return localAgentRouteReference;
103
+ }
104
+
105
+ const normalizedAgentUrl = createLocalAgentUrl(
106
+ localAgentRouteReference.localServerUrl,
107
+ localAgentRouteReference.agentIdentifier,
108
+ );
109
+ return (
110
+ localAgentUrlReferences.find((localAgentUrlReference) => localAgentUrlReference.agentUrl === normalizedAgentUrl) ||
111
+ null
112
+ );
113
+ }
114
+
115
+ /**
116
+ * Builds one local agent profile URL.
117
+ *
118
+ * @param localServerUrl - Same-instance server origin.
119
+ * @param agentIdentifier - Route agent identifier.
120
+ * @returns Local agent URL.
121
+ */
122
+ export function createLocalAgentUrl(localServerUrl: string, agentIdentifier: string): string_agent_url {
123
+ return `${localServerUrl.replace(/\/+$/g, '')}/agents/${encodeURIComponent(agentIdentifier)}` as string_agent_url;
124
+ }
125
+
126
+ /**
127
+ * Normalizes one server URL to its origin.
128
+ *
129
+ * @param serverUrl - Raw server URL.
130
+ * @returns Normalized origin or an empty string when invalid.
131
+ */
132
+ function normalizeServerUrl(serverUrl: string): string {
133
+ try {
134
+ return new URL(serverUrl).origin.replace(/\/+$/g, '');
135
+ } catch {
136
+ return serverUrl.replace(/\/+$/g, '');
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Extracts a local route reference from an agent profile URL.
142
+ *
143
+ * @param agentUrl - Referenced agent URL.
144
+ * @returns Route reference or `null` when the URL is not an agent profile route.
145
+ */
146
+ function parseLocalAgentRouteReference(agentUrl: string_agent_url): LocalAgentRouteReference | null {
147
+ let parsedAgentUrl: URL;
148
+
149
+ try {
150
+ parsedAgentUrl = new URL(agentUrl);
151
+ } catch {
152
+ return null;
153
+ }
154
+
155
+ const localServerUrl = normalizeServerUrl(parsedAgentUrl.origin);
156
+ const pathSegments = parsedAgentUrl.pathname.split('/').filter(Boolean);
157
+ const agentIdentifier = pathSegments[0] === 'agents' ? pathSegments[1] : null;
158
+
159
+ if (!agentIdentifier) {
160
+ return null;
161
+ }
162
+
163
+ return {
164
+ localServerUrl,
165
+ agentIdentifier: decodeURIComponent(agentIdentifier),
166
+ };
167
+ }
@@ -144,7 +144,7 @@ async function enqueueLocalUserChatJob(job: UserChatJobRecord): Promise<ProcessL
144
144
  throw new Error(`User message "${job.userMessageId}" was not found in chat "${job.chatId}".`);
145
145
  }
146
146
 
147
- const threadMessages = createUserChatRunnerThreadMessages({
147
+ const threadMessages = await createUserChatRunnerThreadMessages({
148
148
  messages: chat.messages,
149
149
  userMessageId: job.userMessageId,
150
150
  resolveInitialAgentMessage: () => parseAgentSource(agentSourceSnapshot.agentSource).initialMessage,
@@ -4,8 +4,10 @@ import { loadLocalOrganizationSearchDataset } from '../../search/createDefaultSe
4
4
  import { stringifyJsonForSearch } from '../../search/createDefaultServerSearchProviders/stringifyJsonForSearch';
5
5
  import { $getTableName } from '../../database/$getTableName';
6
6
  import { $provideSupabaseForServer } from '../../database/$provideSupabaseForServer';
7
+ import { $provideAgentCollectionForServer } from '../../tools/$provideAgentCollectionForServer';
7
8
  import type { OwnedAgentRow } from '../agentOwnership';
8
9
  import { $provideAgentReferenceResolver } from '../agentReferenceResolver/$provideAgentReferenceResolver';
10
+ import { createLocalAgentSourceImporter } from '../createLocalAgentSourceImporter';
9
11
  import { getWellKnownAgentUrl } from '../getWellKnownAgentUrl';
10
12
  import { resolveCurrentOrInternalServerOrigin } from '../resolveCurrentOrInternalServerOrigin';
11
13
  import { resolveStoredAgentState } from '../resolveStoredAgentState';
@@ -42,10 +44,22 @@ export type ManagementAgentListItem = {
42
44
  * @returns Resolved agent state derived from the stored unresolved source.
43
45
  */
44
46
  export async function resolveOwnedAgentDerivedState(row: OwnedAgentRow) {
47
+ const localServerUrl = await resolveCurrentOrInternalServerOrigin();
48
+ const adamAgentUrl = await getWellKnownAgentUrl('ADAM');
49
+ const agentReferenceResolver = await $provideAgentReferenceResolver();
50
+ const agentSourceImporter = createLocalAgentSourceImporter({
51
+ collection: await $provideAgentCollectionForServer(),
52
+ localServerUrls: [localServerUrl],
53
+ localAgentUrls: [adamAgentUrl],
54
+ adamAgentUrl,
55
+ fallbackResolver: agentReferenceResolver,
56
+ });
57
+
45
58
  return resolveStoredAgentState(row, {
46
- localServerUrl: await resolveCurrentOrInternalServerOrigin(),
47
- adamAgentUrl: await getWellKnownAgentUrl('ADAM'),
48
- agentReferenceResolver: await $provideAgentReferenceResolver(),
59
+ localServerUrl,
60
+ adamAgentUrl,
61
+ agentReferenceResolver,
62
+ agentSourceImporter,
49
63
  });
50
64
  }
51
65
 
@@ -3,6 +3,7 @@ import { EMAIL_PROVIDERS } from '../../message-providers';
3
3
  import type { MessageProvider } from '../../message-providers/interfaces/MessageProvider';
4
4
  import type { OutboundEmail } from '../../message-providers/email/_common/Email';
5
5
  import { createMessage } from './createMessage';
6
+ import { humanizeOutboundEmail } from './humanizeOutboundEmail';
6
7
  import { sendMessageAttempt } from './sendMessageAttempt';
7
8
 
8
9
  /**
@@ -63,14 +64,15 @@ export function isSendMessageDeliveryError(error: unknown): error is SendMessage
63
64
  * Persists a message and, for outbound emails, creates send attempts until one provider succeeds.
64
65
  */
65
66
  export async function sendMessage(message: OutboundEmail, options?: SendMessageOptions): Promise<SendMessageResult> {
66
- const insertedMessage = await createMessage(message);
67
+ const email = humanizeOutboundEmail(message);
68
+ const insertedMessage = await createMessage(email);
67
69
  const baseResult: SendMessageResult = {
68
70
  messageId: insertedMessage.id,
69
71
  status: 'stored-only',
70
72
  attempts: [],
71
73
  };
72
74
 
73
- if (message.direction !== 'OUTBOUND' || message.channel !== 'EMAIL') {
75
+ if (email.direction !== 'OUTBOUND' || email.channel !== 'EMAIL') {
74
76
  return baseResult;
75
77
  }
76
78
 
@@ -88,7 +90,7 @@ export async function sendMessage(message: OutboundEmail, options?: SendMessageO
88
90
  messageId: insertedMessage.id,
89
91
  providerName,
90
92
  provider,
91
- message,
93
+ message: email,
92
94
  });
93
95
 
94
96
  baseResult.attempts.push(attempt);
@@ -3,7 +3,7 @@ import type { AgentReferenceResolver } from '../../../../src/book-2.0/agent-sour
3
3
  import type { FederatedAgentImportConfiguration } from '../constants/federatedAgentImport';
4
4
  import { parseAgentSource } from '../../../../src/book-2.0/agent-source/parseAgentSource';
5
5
  import { resolveTeamCapabilitiesFromAgentSource } from './agentReferenceResolver/resolveTeamCapabilitiesFromAgentSource';
6
- import { resolveInheritedAgentSource } from './resolveInheritedAgentSource';
6
+ import { resolveInheritedAgentSource, type AgentSourceImporter } from './resolveInheritedAgentSource';
7
7
 
8
8
  /**
9
9
  * Options for deriving the canonical resolved agent state from an editable source.
@@ -33,6 +33,11 @@ export type ResolveAgentStateFromSourceOptions = {
33
33
  * Retry configuration used when loading imported agents from federated servers.
34
34
  */
35
35
  readonly federatedAgentImportConfiguration?: FederatedAgentImportConfiguration;
36
+
37
+ /**
38
+ * Optional importer for same-instance agent sources.
39
+ */
40
+ readonly agentSourceImporter?: AgentSourceImporter;
36
41
  };
37
42
 
38
43
  /**
@@ -112,6 +117,7 @@ export async function resolveAgentStateFromSource(
112
117
  currentAgentAliases: options.currentAgentAliases,
113
118
  agentReferenceResolver: options.agentReferenceResolver,
114
119
  federatedAgentImportConfiguration: options.federatedAgentImportConfiguration,
120
+ agentSourceImporter: options.agentSourceImporter,
115
121
  });
116
122
  const resolvedAgentProfile = parseAgentSource(resolvedAgentSource);
117
123
  const resolvedTeamCapabilities = await resolveTeamCapabilitiesFromAgentSource(
@@ -231,8 +231,42 @@ type ResolveInheritedAgentSourceOptions = ImportAgentOptions & {
231
231
  * Retry configuration used for federated imported-agent loading.
232
232
  */
233
233
  readonly federatedAgentImportConfiguration?: FederatedAgentImportConfiguration;
234
+ /**
235
+ * Optional same-instance source importer used before falling back to HTTP import.
236
+ */
237
+ readonly agentSourceImporter?: AgentSourceImporter;
234
238
  };
235
239
 
240
+ /**
241
+ * Context passed to a custom agent source importer.
242
+ */
243
+ export type AgentSourceImporterContext = {
244
+ /**
245
+ * Commitment that requested the imported source.
246
+ */
247
+ readonly commitmentType: 'FROM' | 'IMPORT';
248
+
249
+ /**
250
+ * Import options propagated from the current resolution pass.
251
+ */
252
+ readonly importAgentOptions: ImportAgentOptions;
253
+
254
+ /**
255
+ * Retry configuration used by the default HTTP importer.
256
+ */
257
+ readonly federatedAgentImportConfiguration: FederatedAgentImportConfiguration;
258
+ };
259
+
260
+ /**
261
+ * Imports one agent source before the resolver falls back to the default HTTP importer.
262
+ *
263
+ * Return `null` when the importer does not own the given URL.
264
+ */
265
+ export type AgentSourceImporter = (
266
+ agentUrl: string_agent_url,
267
+ context: AgentSourceImporterContext,
268
+ ) => Promise<string_book | null>;
269
+
236
270
  /**
237
271
  * Parent inheritance state derived before rewriting the source body.
238
272
  */
@@ -277,6 +311,11 @@ type AgentImportContext = {
277
311
  */
278
312
  readonly importAgentOptions: ImportAgentOptions;
279
313
 
314
+ /**
315
+ * Optional importer for same-instance agent sources.
316
+ */
317
+ readonly agentSourceImporter?: AgentSourceImporter;
318
+
280
319
  /**
281
320
  * Original resolution options used for cycle detection.
282
321
  */
@@ -364,6 +403,7 @@ function createAgentImportContext(options?: ResolveInheritedAgentSourceOptions):
364
403
  recursionLevel: options?.recursionLevel || 0,
365
404
  inheritancePath: createResolutionLineage(options),
366
405
  },
406
+ agentSourceImporter: options?.agentSourceImporter,
367
407
  resolutionOptions: options,
368
408
  };
369
409
  }
@@ -427,11 +467,20 @@ async function importAgentCorpus(
427
467
  ): Promise<string> {
428
468
  assertNoResolutionCycle(agentUrl, commitmentType, context.resolutionOptions);
429
469
 
430
- const importedAgentSource = await importAgentWithFallback(
431
- agentUrl,
432
- context.importAgentOptions,
433
- context.federatedAgentImportConfiguration,
434
- );
470
+ const locallyImportedAgentSource = context.agentSourceImporter
471
+ ? await context.agentSourceImporter(agentUrl, {
472
+ commitmentType,
473
+ importAgentOptions: context.importAgentOptions,
474
+ federatedAgentImportConfiguration: context.federatedAgentImportConfiguration,
475
+ })
476
+ : null;
477
+ const importedAgentSource =
478
+ locallyImportedAgentSource ??
479
+ (await importAgentWithFallback(
480
+ agentUrl,
481
+ context.importAgentOptions,
482
+ context.federatedAgentImportConfiguration,
483
+ ));
435
484
 
436
485
  return getAgentSourceCorpus(importedAgentSource as string_book);
437
486
  }
@@ -1,6 +1,7 @@
1
1
  import type { AgentReferenceResolver } from '../../../../src/book-2.0/agent-source/AgentReferenceResolver';
2
2
  import type { AgentCollection } from '../../../../src/collection/agent-collection/AgentCollection';
3
3
  import { resolveBookScopedAgentContext, type ResolvedBookScopedAgentContext } from './agentReferenceResolver/bookScopedAgentReferences';
4
+ import { createLocalAgentSourceImporter } from './createLocalAgentSourceImporter';
4
5
  import { loadFederatedAgentImportConfiguration } from './federatedAgentImportConfiguration';
5
6
  import { getWellKnownAgentUrl } from './getWellKnownAgentUrl';
6
7
  import { resolveAgentStateFromSource, type ResolvedAgentState } from './resolveAgentStateFromSource';
@@ -46,12 +47,22 @@ export async function resolveServerAgentContext(
46
47
  ): Promise<ResolvedServerAgentContext> {
47
48
  const bookScopedAgentContext = await resolveBookScopedAgentContext(options);
48
49
  const federatedAgentImportConfiguration = await loadFederatedAgentImportConfiguration();
50
+ const adamAgentUrl = await getWellKnownAgentUrl('ADAM');
51
+ const agentSourceImporter = createLocalAgentSourceImporter({
52
+ collection: options.collection,
53
+ localServerUrls: [options.localServerUrl],
54
+ localAgentUrls: [adamAgentUrl],
55
+ adamAgentUrl,
56
+ fallbackResolver: options.fallbackResolver,
57
+ federatedAgentImportConfiguration,
58
+ });
49
59
  const resolvedAgentState = await resolveAgentStateFromSource(bookScopedAgentContext.unresolvedAgentSource, {
50
- adamAgentUrl: await getWellKnownAgentUrl('ADAM'),
60
+ adamAgentUrl,
51
61
  canonicalAgentUrl: bookScopedAgentContext.canonicalAgentUrl,
52
62
  currentAgentAliases: bookScopedAgentContext.currentAgentAliases,
53
63
  agentReferenceResolver: bookScopedAgentContext.scopedAgentReferenceResolver,
54
64
  federatedAgentImportConfiguration,
65
+ agentSourceImporter,
55
66
  });
56
67
 
57
68
  return {
@@ -30,7 +30,7 @@ export type ResolvedStoredAgentState<TAgent extends StoredAgentSourceRecord> = T
30
30
  */
31
31
  export type ResolveStoredAgentStateOptions = Pick<
32
32
  ResolveAgentStateFromSourceOptions,
33
- 'adamAgentUrl' | 'agentReferenceResolver' | 'federatedAgentImportConfiguration'
33
+ 'adamAgentUrl' | 'agentReferenceResolver' | 'federatedAgentImportConfiguration' | 'agentSourceImporter'
34
34
  > & {
35
35
  /**
36
36
  * Public/current server origin used to build canonical local agent URLs.
@@ -91,6 +91,7 @@ export async function resolveStoredAgentState<TAgent extends StoredAgentSourceRe
91
91
  currentAgentAliases: createCanonicalLocalAgentAliases(agent, options.localServerUrl),
92
92
  agentReferenceResolver: options.agentReferenceResolver,
93
93
  federatedAgentImportConfiguration,
94
+ agentSourceImporter: options.agentSourceImporter,
94
95
  });
95
96
 
96
97
  return {
@@ -172,7 +172,6 @@ export class SpeechToTextFailoverRecognitionProviderRuntime {
172
172
  }
173
173
  }
174
174
 
175
- this.options.onForceIdleStop();
176
175
  return false;
177
176
  }
178
177
 
@@ -302,13 +302,45 @@ export class SpeechToTextFailoverRecognition implements SpeechRecognition {
302
302
  * Handles stall watchdog restart/failover escalation.
303
303
  */
304
304
  private handleStallDetected(): void {
305
+ void this.handleStallDetectedAsync();
306
+ }
307
+
308
+ /**
309
+ * Handles stall watchdog restart/failover escalation.
310
+ */
311
+ private async handleStallDetectedAsync(): Promise<void> {
312
+ const providerId = this.providerRuntime.currentProviderId;
313
+
305
314
  if (!this.providerRuntime.hasRestartedCurrentProvider) {
306
315
  this.providerRuntime.markCurrentProviderRestarted();
307
- void this.providerRuntime.restartCurrentProvider('stall-detected');
316
+ this.telemetryReporter.emit({
317
+ type: 'provider-restart',
318
+ providerId,
319
+ elapsedMs: Date.now() - this.sessionStartedAtMs,
320
+ detail: 'stall-detected',
321
+ });
322
+
323
+ const restartSucceeded = await this.providerRuntime.restartCurrentProvider('stall-detected');
324
+ if (restartSucceeded) {
325
+ return;
326
+ }
327
+ }
328
+
329
+ const failoverSucceeded = await this.providerRuntime.failoverToNextProvider('stall-after-restart');
330
+ if (failoverSucceeded) {
308
331
  return;
309
332
  }
310
333
 
311
- void this.providerRuntime.failoverToNextProvider('stall-after-restart');
334
+ this._state = 'ERROR';
335
+ this.emit({
336
+ type: 'ERROR',
337
+ message: 'Speech recognition stalled while audio was detected. No fallback speech-to-text provider was available.',
338
+ code: 'unknown',
339
+ providerId,
340
+ canRetry: true,
341
+ canOpenBrowserSettings: false,
342
+ });
343
+ this.forceIdleStop();
312
344
  }
313
345
 
314
346
  /**
@@ -1,4 +1,6 @@
1
1
  import type { ChatMessage } from '../../../../../src/_packages/types.index';
2
+ import { appendChatAttachmentContextWithContent } from '../../../../../src/utils/chat/chatAttachments/appendChatAttachmentContextWithContent';
3
+
2
4
  /**
3
5
  * Lifecycle states rendered on canonical server-owned chat messages.
4
6
  */
@@ -99,11 +101,11 @@ export function resolvePromptThreadBeforeUserMessage(
99
101
  /**
100
102
  * Creates the complete chat thread mirrored to a runner before it writes the next answer.
101
103
  */
102
- export function createUserChatRunnerThreadMessages(options: {
104
+ export async function createUserChatRunnerThreadMessages(options: {
103
105
  messages: ReadonlyArray<ChatMessage>;
104
106
  userMessageId: string;
105
107
  resolveInitialAgentMessage: () => string | null | undefined;
106
- }): Array<UserChatRunnerThreadMessage> {
108
+ }): Promise<Array<UserChatRunnerThreadMessage>> {
107
109
  const userMessage = options.messages.find((message) => message.id === options.userMessageId);
108
110
  if (!userMessage) {
109
111
  return [];
@@ -111,19 +113,16 @@ export function createUserChatRunnerThreadMessages(options: {
111
113
 
112
114
  const previousThreadMessages = resolvePromptThreadBeforeUserMessage(options.messages, options.userMessageId);
113
115
 
114
- return [
116
+ const threadMessages = [
115
117
  ...createInitialUserChatRunnerThreadMessages({
116
118
  isFirstUserTurn: previousThreadMessages.length === 0,
117
119
  resolveInitialAgentMessage: options.resolveInitialAgentMessage,
118
120
  }),
119
121
  ...previousThreadMessages,
120
122
  userMessage,
121
- ]
122
- .filter(isUserChatRunnerThreadMessage)
123
- .map((message) => ({
124
- sender: message.sender,
125
- content: message.content,
126
- }));
123
+ ].filter(isUserChatRunnerThreadMessage);
124
+
125
+ return await Promise.all(threadMessages.map(createUserChatRunnerThreadMessage));
127
126
  }
128
127
 
129
128
  /**
@@ -176,3 +175,34 @@ function isUserChatRunnerThreadMessage(message: ChatMessage): message is ChatMes
176
175
  const isRunnerSender = message.sender === 'USER' || message.sender === 'AGENT';
177
176
  return message.isComplete !== false && isRunnerSender;
178
177
  }
178
+
179
+ /**
180
+ * Creates one runner-visible message with attachment context inlined into user-authored content.
181
+ *
182
+ * @private helper of `createUserChatRunnerThreadMessages`
183
+ */
184
+ async function createUserChatRunnerThreadMessage(
185
+ message: ChatMessage & UserChatRunnerThreadMessage,
186
+ ): Promise<UserChatRunnerThreadMessage> {
187
+ return {
188
+ sender: message.sender,
189
+ content: await createUserChatRunnerThreadMessageContent(message),
190
+ };
191
+ }
192
+
193
+ /**
194
+ * Adds attachment URLs and best-effort text previews to user messages mirrored into runner `.book` files.
195
+ *
196
+ * @private helper of `createUserChatRunnerThreadMessage`
197
+ */
198
+ async function createUserChatRunnerThreadMessageContent(
199
+ message: ChatMessage & UserChatRunnerThreadMessage,
200
+ ): Promise<string> {
201
+ if (message.sender !== 'USER' || !message.attachments || message.attachments.length === 0) {
202
+ return message.content;
203
+ }
204
+
205
+ return await appendChatAttachmentContextWithContent(message.content, message.attachments, {
206
+ allowLocalhost: true,
207
+ });
208
+ }
@@ -212,6 +212,7 @@ async function delayNextMatchingRequest(
212
212
  options: DelayNextMatchingRequestOptions,
213
213
  ): Promise<DelayedRequestControl> {
214
214
  let hasInterceptedTargetRequest = false;
215
+ let isReleased = false;
215
216
  let releaseRequest: (() => void) | null = null;
216
217
  let markStarted: (() => void) | null = null;
217
218
  let markFinished: (() => void) | null = null;
@@ -239,6 +240,9 @@ async function delayNextMatchingRequest(
239
240
 
240
241
  await new Promise<void>((resolve) => {
241
242
  releaseRequest = resolve;
243
+ if (isReleased) {
244
+ resolve();
245
+ }
242
246
  });
243
247
 
244
248
  try {
@@ -255,6 +259,7 @@ async function delayNextMatchingRequest(
255
259
  waitUntilStarted,
256
260
  waitUntilFinished,
257
261
  release() {
262
+ isReleased = true;
258
263
  releaseRequest?.();
259
264
  },
260
265
  async dispose() {