@usewhisper/sdk 3.1.0 → 3.3.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.
Files changed (5) hide show
  1. package/index.d.mts +43 -13
  2. package/index.d.ts +43 -13
  3. package/index.js +208 -45
  4. package/index.mjs +208 -45
  5. package/package.json +1 -1
package/index.d.mts CHANGED
@@ -215,6 +215,7 @@ interface RuntimeClientOptions {
215
215
  compatMode?: CompatMode;
216
216
  timeouts?: Partial<TimeoutBudgets>;
217
217
  retryPolicy?: RetryPolicy;
218
+ fetchImpl?: typeof fetch;
218
219
  }
219
220
  interface RuntimeResponse<T> {
220
221
  data: T;
@@ -325,6 +326,7 @@ declare class RuntimeClient {
325
326
  private readonly diagnostics;
326
327
  private readonly inFlight;
327
328
  private readonly sendApiKeyHeader;
329
+ private readonly fetchImpl;
328
330
  constructor(options: RuntimeClientOptions, diagnostics?: DiagnosticsStore);
329
331
  getDiagnosticsStore(): DiagnosticsStore;
330
332
  getCompatMode(): CompatMode;
@@ -414,11 +416,13 @@ interface MemoryWriteAck$1 {
414
416
  success: boolean;
415
417
  mode?: "async" | "sync";
416
418
  trace_id?: string;
419
+ memory_id?: string;
417
420
  job_id?: string;
418
421
  status_url?: string;
419
422
  accepted_at?: string;
420
423
  visibility_sla_ms?: number;
421
424
  pending_visibility?: boolean;
425
+ semantic_status?: "pending" | "ready";
422
426
  queued?: boolean;
423
427
  event_id?: string;
424
428
  created?: number;
@@ -619,6 +623,7 @@ interface WhisperClientConfig {
619
623
  baseUrl?: string;
620
624
  project?: string;
621
625
  compatMode?: CompatMode;
626
+ fetch?: typeof fetch;
622
627
  timeouts?: Partial<TimeoutBudgets>;
623
628
  retryPolicy?: RetryPolicy;
624
629
  cache?: {
@@ -1036,6 +1041,9 @@ interface CanonicalSourceCreateParams {
1036
1041
  name?: string;
1037
1042
  auto_index?: boolean;
1038
1043
  metadata?: Record<string, string>;
1044
+ ingestion_profile?: "auto" | "repo" | "web_docs" | "pdf_layout" | "video_transcript" | "plain_text";
1045
+ strategy_override?: "fixed" | "recursive" | "semantic" | "hierarchical" | "adaptive";
1046
+ profile_config?: Record<string, any>;
1039
1047
  owner?: string;
1040
1048
  repo?: string;
1041
1049
  branch?: string;
@@ -1147,6 +1155,20 @@ interface MemoryWriteAck {
1147
1155
  pending_visibility?: boolean;
1148
1156
  [key: string]: any;
1149
1157
  }
1158
+ interface MemoryWriteResult {
1159
+ id: string;
1160
+ success: boolean;
1161
+ path: "sota" | "legacy";
1162
+ fallback_used: boolean;
1163
+ mode?: "async" | "sync";
1164
+ memory_id?: string;
1165
+ job_id?: string;
1166
+ status_url?: string;
1167
+ accepted_at?: string;
1168
+ visibility_sla_ms?: number;
1169
+ pending_visibility?: boolean;
1170
+ semantic_status?: "pending" | "ready";
1171
+ }
1150
1172
  type WhisperErrorCode = "INVALID_API_KEY" | "PROJECT_NOT_FOUND" | "PROJECT_AMBIGUOUS" | "RATE_LIMITED" | "TEMPORARY_UNAVAILABLE" | "NETWORK_ERROR" | "TIMEOUT" | "REQUEST_FAILED" | "MISSING_PROJECT";
1151
1173
  declare class WhisperError extends Error {
1152
1174
  code: WhisperErrorCode;
@@ -1175,9 +1197,13 @@ declare class WhisperContext {
1175
1197
  withProject(project: string): WhisperContext;
1176
1198
  private getRequiredProject;
1177
1199
  private refreshProjectCache;
1200
+ private fetchResolvedProject;
1201
+ resolveProject(projectRef?: string): Promise<Project>;
1178
1202
  private resolveProjectId;
1179
1203
  private getProjectRefCandidates;
1180
1204
  private withProjectRefFallback;
1205
+ private shouldRetryWithResolvedProjectId;
1206
+ private withProjectPathFallback;
1181
1207
  private classifyError;
1182
1208
  private isEndpointNotFoundError;
1183
1209
  private inferOperation;
@@ -1194,6 +1220,14 @@ declare class WhisperContext {
1194
1220
  getProject(id: string): Promise<Project & {
1195
1221
  sources: Source[];
1196
1222
  }>;
1223
+ listSources(project?: string): Promise<{
1224
+ project: {
1225
+ id: string;
1226
+ name: string;
1227
+ slug: string;
1228
+ };
1229
+ sources: Source[];
1230
+ }>;
1197
1231
  deleteProject(id: string): Promise<{
1198
1232
  deleted: boolean;
1199
1233
  }>;
@@ -1214,6 +1248,9 @@ declare class WhisperContext {
1214
1248
  allow_stt_fallback?: boolean;
1215
1249
  max_duration_minutes?: number;
1216
1250
  name?: string;
1251
+ ingestion_profile?: "auto" | "repo" | "web_docs" | "pdf_layout" | "video_transcript" | "plain_text";
1252
+ strategy_override?: "fixed" | "recursive" | "semantic" | "hierarchical" | "adaptive";
1253
+ profile_config?: Record<string, any>;
1217
1254
  }): Promise<{
1218
1255
  source_id: string;
1219
1256
  sync_job_id?: string | null;
@@ -1227,6 +1264,9 @@ declare class WhisperContext {
1227
1264
  content: string;
1228
1265
  metadata?: Record<string, any>;
1229
1266
  file_path?: string;
1267
+ ingestion_profile?: "auto" | "repo" | "web_docs" | "pdf_layout" | "video_transcript" | "plain_text";
1268
+ strategy_override?: "fixed" | "recursive" | "semantic" | "hierarchical" | "adaptive";
1269
+ profile_config?: Record<string, any>;
1230
1270
  }>): Promise<{
1231
1271
  ingested: number;
1232
1272
  }>;
@@ -1251,12 +1291,7 @@ declare class WhisperContext {
1251
1291
  async?: boolean;
1252
1292
  write_mode?: "async" | "sync";
1253
1293
  allow_legacy_fallback?: boolean;
1254
- }): Promise<{
1255
- id: string;
1256
- success: boolean;
1257
- path: "sota" | "legacy";
1258
- fallback_used: boolean;
1259
- }>;
1294
+ }): Promise<MemoryWriteResult>;
1260
1295
  addMemoriesBulk(params: {
1261
1296
  project?: string;
1262
1297
  memories: Array<{
@@ -1645,12 +1680,7 @@ declare class WhisperContext {
1645
1680
  getStatus: (sourceId: string) => Promise<VideoIngestionStatus>;
1646
1681
  };
1647
1682
  readonly memory: {
1648
- add: (params: Parameters<WhisperContext["addMemory"]>[0]) => Promise<{
1649
- id: string;
1650
- success: boolean;
1651
- path: "sota" | "legacy";
1652
- fallback_used: boolean;
1653
- }>;
1683
+ add: (params: Parameters<WhisperContext["addMemory"]>[0]) => Promise<MemoryWriteResult>;
1654
1684
  addBulk: (params: Parameters<WhisperContext["addMemoriesBulk"]>[0]) => Promise<any>;
1655
1685
  extract: (params: Parameters<WhisperContext["extractMemories"]>[0]) => Promise<MemoryExtractionResult>;
1656
1686
  extractSession: (params: Parameters<WhisperContext["extractSessionMemories"]>[0]) => Promise<{
@@ -1784,4 +1814,4 @@ declare class WhisperContext {
1784
1814
  };
1785
1815
  }
1786
1816
 
1787
- export { type CanonicalSourceCreateParams, type CanonicalSourceCreateResult, type CanonicalSourceType, type ExtractedMemory, LangChainMemoryAdapter, LangGraphCheckpointAdapter, type Memory, type MemoryExtractionResult, type MemoryKind, type MemoryLatencyBreakdown, type MemorySearchResponse, type MemoryWriteAck, type Project, type QueryParams, type QueryResult, type Source, type VideoIngestionStatus, type VideoSourceMetadata, Whisper, WhisperAgentMiddleware, WhisperClient, type WhisperConfig, WhisperContext, Whisper as WhisperDefault, WhisperError, type WhisperErrorCode, WhisperClient as WhisperRuntimeClient, createAgentMiddleware, createLangChainMemoryAdapter, createLangGraphCheckpointAdapter, WhisperContext as default, memoryGraphToMermaid };
1817
+ export { type CanonicalSourceCreateParams, type CanonicalSourceCreateResult, type CanonicalSourceType, type ExtractedMemory, LangChainMemoryAdapter, LangGraphCheckpointAdapter, type Memory, type MemoryExtractionResult, type MemoryKind, type MemoryLatencyBreakdown, type MemorySearchResponse, type MemoryWriteAck, type MemoryWriteResult, type Project, type QueryParams, type QueryResult, type Source, type VideoIngestionStatus, type VideoSourceMetadata, Whisper, WhisperAgentMiddleware, WhisperClient, type WhisperConfig, WhisperContext, Whisper as WhisperDefault, WhisperError, type WhisperErrorCode, WhisperClient as WhisperRuntimeClient, createAgentMiddleware, createLangChainMemoryAdapter, createLangGraphCheckpointAdapter, WhisperContext as default, memoryGraphToMermaid };
package/index.d.ts CHANGED
@@ -215,6 +215,7 @@ interface RuntimeClientOptions {
215
215
  compatMode?: CompatMode;
216
216
  timeouts?: Partial<TimeoutBudgets>;
217
217
  retryPolicy?: RetryPolicy;
218
+ fetchImpl?: typeof fetch;
218
219
  }
219
220
  interface RuntimeResponse<T> {
220
221
  data: T;
@@ -325,6 +326,7 @@ declare class RuntimeClient {
325
326
  private readonly diagnostics;
326
327
  private readonly inFlight;
327
328
  private readonly sendApiKeyHeader;
329
+ private readonly fetchImpl;
328
330
  constructor(options: RuntimeClientOptions, diagnostics?: DiagnosticsStore);
329
331
  getDiagnosticsStore(): DiagnosticsStore;
330
332
  getCompatMode(): CompatMode;
@@ -414,11 +416,13 @@ interface MemoryWriteAck$1 {
414
416
  success: boolean;
415
417
  mode?: "async" | "sync";
416
418
  trace_id?: string;
419
+ memory_id?: string;
417
420
  job_id?: string;
418
421
  status_url?: string;
419
422
  accepted_at?: string;
420
423
  visibility_sla_ms?: number;
421
424
  pending_visibility?: boolean;
425
+ semantic_status?: "pending" | "ready";
422
426
  queued?: boolean;
423
427
  event_id?: string;
424
428
  created?: number;
@@ -619,6 +623,7 @@ interface WhisperClientConfig {
619
623
  baseUrl?: string;
620
624
  project?: string;
621
625
  compatMode?: CompatMode;
626
+ fetch?: typeof fetch;
622
627
  timeouts?: Partial<TimeoutBudgets>;
623
628
  retryPolicy?: RetryPolicy;
624
629
  cache?: {
@@ -1036,6 +1041,9 @@ interface CanonicalSourceCreateParams {
1036
1041
  name?: string;
1037
1042
  auto_index?: boolean;
1038
1043
  metadata?: Record<string, string>;
1044
+ ingestion_profile?: "auto" | "repo" | "web_docs" | "pdf_layout" | "video_transcript" | "plain_text";
1045
+ strategy_override?: "fixed" | "recursive" | "semantic" | "hierarchical" | "adaptive";
1046
+ profile_config?: Record<string, any>;
1039
1047
  owner?: string;
1040
1048
  repo?: string;
1041
1049
  branch?: string;
@@ -1147,6 +1155,20 @@ interface MemoryWriteAck {
1147
1155
  pending_visibility?: boolean;
1148
1156
  [key: string]: any;
1149
1157
  }
1158
+ interface MemoryWriteResult {
1159
+ id: string;
1160
+ success: boolean;
1161
+ path: "sota" | "legacy";
1162
+ fallback_used: boolean;
1163
+ mode?: "async" | "sync";
1164
+ memory_id?: string;
1165
+ job_id?: string;
1166
+ status_url?: string;
1167
+ accepted_at?: string;
1168
+ visibility_sla_ms?: number;
1169
+ pending_visibility?: boolean;
1170
+ semantic_status?: "pending" | "ready";
1171
+ }
1150
1172
  type WhisperErrorCode = "INVALID_API_KEY" | "PROJECT_NOT_FOUND" | "PROJECT_AMBIGUOUS" | "RATE_LIMITED" | "TEMPORARY_UNAVAILABLE" | "NETWORK_ERROR" | "TIMEOUT" | "REQUEST_FAILED" | "MISSING_PROJECT";
1151
1173
  declare class WhisperError extends Error {
1152
1174
  code: WhisperErrorCode;
@@ -1175,9 +1197,13 @@ declare class WhisperContext {
1175
1197
  withProject(project: string): WhisperContext;
1176
1198
  private getRequiredProject;
1177
1199
  private refreshProjectCache;
1200
+ private fetchResolvedProject;
1201
+ resolveProject(projectRef?: string): Promise<Project>;
1178
1202
  private resolveProjectId;
1179
1203
  private getProjectRefCandidates;
1180
1204
  private withProjectRefFallback;
1205
+ private shouldRetryWithResolvedProjectId;
1206
+ private withProjectPathFallback;
1181
1207
  private classifyError;
1182
1208
  private isEndpointNotFoundError;
1183
1209
  private inferOperation;
@@ -1194,6 +1220,14 @@ declare class WhisperContext {
1194
1220
  getProject(id: string): Promise<Project & {
1195
1221
  sources: Source[];
1196
1222
  }>;
1223
+ listSources(project?: string): Promise<{
1224
+ project: {
1225
+ id: string;
1226
+ name: string;
1227
+ slug: string;
1228
+ };
1229
+ sources: Source[];
1230
+ }>;
1197
1231
  deleteProject(id: string): Promise<{
1198
1232
  deleted: boolean;
1199
1233
  }>;
@@ -1214,6 +1248,9 @@ declare class WhisperContext {
1214
1248
  allow_stt_fallback?: boolean;
1215
1249
  max_duration_minutes?: number;
1216
1250
  name?: string;
1251
+ ingestion_profile?: "auto" | "repo" | "web_docs" | "pdf_layout" | "video_transcript" | "plain_text";
1252
+ strategy_override?: "fixed" | "recursive" | "semantic" | "hierarchical" | "adaptive";
1253
+ profile_config?: Record<string, any>;
1217
1254
  }): Promise<{
1218
1255
  source_id: string;
1219
1256
  sync_job_id?: string | null;
@@ -1227,6 +1264,9 @@ declare class WhisperContext {
1227
1264
  content: string;
1228
1265
  metadata?: Record<string, any>;
1229
1266
  file_path?: string;
1267
+ ingestion_profile?: "auto" | "repo" | "web_docs" | "pdf_layout" | "video_transcript" | "plain_text";
1268
+ strategy_override?: "fixed" | "recursive" | "semantic" | "hierarchical" | "adaptive";
1269
+ profile_config?: Record<string, any>;
1230
1270
  }>): Promise<{
1231
1271
  ingested: number;
1232
1272
  }>;
@@ -1251,12 +1291,7 @@ declare class WhisperContext {
1251
1291
  async?: boolean;
1252
1292
  write_mode?: "async" | "sync";
1253
1293
  allow_legacy_fallback?: boolean;
1254
- }): Promise<{
1255
- id: string;
1256
- success: boolean;
1257
- path: "sota" | "legacy";
1258
- fallback_used: boolean;
1259
- }>;
1294
+ }): Promise<MemoryWriteResult>;
1260
1295
  addMemoriesBulk(params: {
1261
1296
  project?: string;
1262
1297
  memories: Array<{
@@ -1645,12 +1680,7 @@ declare class WhisperContext {
1645
1680
  getStatus: (sourceId: string) => Promise<VideoIngestionStatus>;
1646
1681
  };
1647
1682
  readonly memory: {
1648
- add: (params: Parameters<WhisperContext["addMemory"]>[0]) => Promise<{
1649
- id: string;
1650
- success: boolean;
1651
- path: "sota" | "legacy";
1652
- fallback_used: boolean;
1653
- }>;
1683
+ add: (params: Parameters<WhisperContext["addMemory"]>[0]) => Promise<MemoryWriteResult>;
1654
1684
  addBulk: (params: Parameters<WhisperContext["addMemoriesBulk"]>[0]) => Promise<any>;
1655
1685
  extract: (params: Parameters<WhisperContext["extractMemories"]>[0]) => Promise<MemoryExtractionResult>;
1656
1686
  extractSession: (params: Parameters<WhisperContext["extractSessionMemories"]>[0]) => Promise<{
@@ -1784,4 +1814,4 @@ declare class WhisperContext {
1784
1814
  };
1785
1815
  }
1786
1816
 
1787
- export { type CanonicalSourceCreateParams, type CanonicalSourceCreateResult, type CanonicalSourceType, type ExtractedMemory, LangChainMemoryAdapter, LangGraphCheckpointAdapter, type Memory, type MemoryExtractionResult, type MemoryKind, type MemoryLatencyBreakdown, type MemorySearchResponse, type MemoryWriteAck, type Project, type QueryParams, type QueryResult, type Source, type VideoIngestionStatus, type VideoSourceMetadata, Whisper, WhisperAgentMiddleware, WhisperClient, type WhisperConfig, WhisperContext, Whisper as WhisperDefault, WhisperError, type WhisperErrorCode, WhisperClient as WhisperRuntimeClient, createAgentMiddleware, createLangChainMemoryAdapter, createLangGraphCheckpointAdapter, WhisperContext as default, memoryGraphToMermaid };
1817
+ export { type CanonicalSourceCreateParams, type CanonicalSourceCreateResult, type CanonicalSourceType, type ExtractedMemory, LangChainMemoryAdapter, LangGraphCheckpointAdapter, type Memory, type MemoryExtractionResult, type MemoryKind, type MemoryLatencyBreakdown, type MemorySearchResponse, type MemoryWriteAck, type MemoryWriteResult, type Project, type QueryParams, type QueryResult, type Source, type VideoIngestionStatus, type VideoSourceMetadata, Whisper, WhisperAgentMiddleware, WhisperClient, type WhisperConfig, WhisperContext, Whisper as WhisperDefault, WhisperError, type WhisperErrorCode, WhisperClient as WhisperRuntimeClient, createAgentMiddleware, createLangChainMemoryAdapter, createLangGraphCheckpointAdapter, WhisperContext as default, memoryGraphToMermaid };
package/index.js CHANGED
@@ -184,6 +184,7 @@ var RuntimeClient = class {
184
184
  diagnostics;
185
185
  inFlight = /* @__PURE__ */ new Map();
186
186
  sendApiKeyHeader;
187
+ fetchImpl;
187
188
  constructor(options, diagnostics) {
188
189
  if (!options.apiKey) {
189
190
  throw new RuntimeClientError({
@@ -208,6 +209,7 @@ var RuntimeClient = class {
208
209
  ...options.timeouts || {}
209
210
  };
210
211
  this.sendApiKeyHeader = process.env.WHISPER_SEND_X_API_KEY === "1";
212
+ this.fetchImpl = options.fetchImpl || fetch;
211
213
  this.diagnostics = diagnostics || new DiagnosticsStore(1e3);
212
214
  }
213
215
  getDiagnosticsStore() {
@@ -328,7 +330,7 @@ var RuntimeClient = class {
328
330
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
329
331
  try {
330
332
  const attachApiKeyHeader = this.shouldAttachApiKeyHeader(normalizedEndpoint);
331
- const response = await fetch(`${this.baseUrl}${normalizedEndpoint}`, {
333
+ const response = await this.fetchImpl(`${this.baseUrl}${normalizedEndpoint}`, {
332
334
  method,
333
335
  signal: controller.signal,
334
336
  keepalive: method !== "GET",
@@ -1037,7 +1039,7 @@ var MemoryModule = class {
1037
1039
  async add(params) {
1038
1040
  const project = this.resolveProject(params.project);
1039
1041
  const queueEnabled = this.options.queueEnabled !== false;
1040
- const useQueue = queueEnabled && params.write_mode !== "sync" && params.async !== false;
1042
+ const useQueue = queueEnabled && (params.write_mode === "async" || params.async === true);
1041
1043
  if (useQueue) {
1042
1044
  const queued = await this.queue.enqueue({
1043
1045
  project,
@@ -1082,14 +1084,18 @@ var MemoryModule = class {
1082
1084
  metadata: params.metadata,
1083
1085
  document_date: params.document_date,
1084
1086
  event_date: params.event_date,
1085
- write_mode: "sync"
1087
+ write_mode: params.write_mode === "async" || params.async === true ? "async" : "sync"
1086
1088
  }
1087
1089
  });
1088
1090
  this.invalidate(project, params.user_id, params.session_id);
1089
1091
  return {
1090
1092
  success: true,
1091
1093
  mode: "sync",
1092
- trace_id: response.traceId
1094
+ trace_id: response.trace_id || response.traceId,
1095
+ memory_id: response.memory_id || response.memory?.id,
1096
+ semantic_status: response.semantic_status || response.memory?.semantic_status,
1097
+ pending_visibility: Boolean(response.pending_visibility),
1098
+ visibility_sla_ms: response.visibility_sla_ms
1093
1099
  };
1094
1100
  } catch (error) {
1095
1101
  if (this.client.getCompatMode() !== "fallback" || !isEndpointNotFound(error)) {
@@ -1127,7 +1133,7 @@ var MemoryModule = class {
1127
1133
  });
1128
1134
  }
1129
1135
  const queueEnabled = this.options.queueEnabled !== false;
1130
- const useQueue = queueEnabled && params.write_mode !== "sync" && params.async !== false;
1136
+ const useQueue = queueEnabled && (params.write_mode === "async" || params.async === true);
1131
1137
  if (useQueue) {
1132
1138
  const queued = await Promise.all(
1133
1139
  params.memories.map(
@@ -1171,7 +1177,7 @@ var MemoryModule = class {
1171
1177
  ...memory,
1172
1178
  memory_type: toSotaType(memory.memory_type)
1173
1179
  })),
1174
- write_mode: "sync"
1180
+ write_mode: params.write_mode === "async" || params.async === true ? "async" : "sync"
1175
1181
  }
1176
1182
  });
1177
1183
  for (const memory of params.memories) {
@@ -1604,7 +1610,8 @@ var WhisperClient = class _WhisperClient {
1604
1610
  baseUrl: config.baseUrl,
1605
1611
  compatMode: config.compatMode || "fallback",
1606
1612
  timeouts: config.timeouts,
1607
- retryPolicy: config.retryPolicy
1613
+ retryPolicy: config.retryPolicy,
1614
+ fetchImpl: config.fetch
1608
1615
  },
1609
1616
  this.diagnosticsStore
1610
1617
  );
@@ -2416,9 +2423,71 @@ var WhisperContext = class _WhisperContext {
2416
2423
  this.projectRefToId.set(p.slug, p.id);
2417
2424
  this.projectRefToId.set(p.name, p.id);
2418
2425
  }
2426
+ if (this.defaultProject) {
2427
+ const hasDefaultProject = this.projectCache.some(
2428
+ (project) => project.id === this.defaultProject || project.slug === this.defaultProject || project.name === this.defaultProject
2429
+ );
2430
+ if (!hasDefaultProject) {
2431
+ const resolvedDefault = await this.fetchResolvedProject(this.defaultProject);
2432
+ if (resolvedDefault) {
2433
+ this.projectCache = [...this.projectCache, resolvedDefault];
2434
+ this.projectRefToId.set(resolvedDefault.id, resolvedDefault.id);
2435
+ this.projectRefToId.set(resolvedDefault.slug, resolvedDefault.id);
2436
+ this.projectRefToId.set(resolvedDefault.name, resolvedDefault.id);
2437
+ }
2438
+ }
2439
+ }
2419
2440
  this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
2420
2441
  return this.projectCache;
2421
2442
  }
2443
+ async fetchResolvedProject(projectRef) {
2444
+ if (!projectRef) return null;
2445
+ try {
2446
+ const response = await this.request(`/v1/projects/resolve?project=${encodeURIComponent(projectRef)}`, { method: "GET" });
2447
+ return response?.resolved || null;
2448
+ } catch (error) {
2449
+ if (error instanceof WhisperError && error.code === "PROJECT_NOT_FOUND") {
2450
+ return null;
2451
+ }
2452
+ throw error;
2453
+ }
2454
+ }
2455
+ async resolveProject(projectRef) {
2456
+ const resolvedRef = this.getRequiredProject(projectRef);
2457
+ const cachedProjects = await this.refreshProjectCache(false);
2458
+ const cachedProject = cachedProjects.find(
2459
+ (project) => project.id === resolvedRef || project.slug === resolvedRef || project.name === resolvedRef
2460
+ );
2461
+ if (cachedProject) {
2462
+ return cachedProject;
2463
+ }
2464
+ const resolvedProject = await this.fetchResolvedProject(resolvedRef);
2465
+ if (resolvedProject) {
2466
+ this.projectRefToId.set(resolvedProject.id, resolvedProject.id);
2467
+ this.projectRefToId.set(resolvedProject.slug, resolvedProject.id);
2468
+ this.projectRefToId.set(resolvedProject.name, resolvedProject.id);
2469
+ this.projectCache = [
2470
+ ...this.projectCache.filter((project) => project.id !== resolvedProject.id),
2471
+ resolvedProject
2472
+ ];
2473
+ this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
2474
+ return resolvedProject;
2475
+ }
2476
+ if (isLikelyProjectId(resolvedRef)) {
2477
+ return {
2478
+ id: resolvedRef,
2479
+ orgId: "",
2480
+ name: resolvedRef,
2481
+ slug: resolvedRef,
2482
+ createdAt: (/* @__PURE__ */ new Date(0)).toISOString(),
2483
+ updatedAt: (/* @__PURE__ */ new Date(0)).toISOString()
2484
+ };
2485
+ }
2486
+ throw new WhisperError({
2487
+ code: "PROJECT_NOT_FOUND",
2488
+ message: `Project '${resolvedRef}' not found`
2489
+ });
2490
+ }
2422
2491
  async resolveProjectId(projectRef) {
2423
2492
  if (this.projectRefToId.has(projectRef)) {
2424
2493
  return this.projectRefToId.get(projectRef);
@@ -2439,6 +2508,18 @@ var WhisperContext = class _WhisperContext {
2439
2508
  if (isLikelyProjectId(projectRef)) {
2440
2509
  return projectRef;
2441
2510
  }
2511
+ const resolvedProject = await this.fetchResolvedProject(projectRef);
2512
+ if (resolvedProject) {
2513
+ this.projectRefToId.set(resolvedProject.id, resolvedProject.id);
2514
+ this.projectRefToId.set(resolvedProject.slug, resolvedProject.id);
2515
+ this.projectRefToId.set(resolvedProject.name, resolvedProject.id);
2516
+ this.projectCache = [
2517
+ ...this.projectCache.filter((project) => project.id !== resolvedProject.id),
2518
+ resolvedProject
2519
+ ];
2520
+ this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
2521
+ return resolvedProject.id;
2522
+ }
2442
2523
  throw new WhisperError({
2443
2524
  code: "PROJECT_NOT_FOUND",
2444
2525
  message: `Project '${projectRef}' not found`
@@ -2494,6 +2575,26 @@ var WhisperContext = class _WhisperContext {
2494
2575
  message: `Project '${projectRef}' not found`
2495
2576
  });
2496
2577
  }
2578
+ shouldRetryWithResolvedProjectId(error) {
2579
+ return error instanceof WhisperError && error.status === 404 && !this.isEndpointNotFoundError(error);
2580
+ }
2581
+ async withProjectPathFallback(projectRef, execute) {
2582
+ try {
2583
+ return await execute(projectRef);
2584
+ } catch (error) {
2585
+ if (!this.shouldRetryWithResolvedProjectId(error)) {
2586
+ throw error;
2587
+ }
2588
+ }
2589
+ const resolvedProjectId = await this.resolveProjectId(projectRef);
2590
+ if (resolvedProjectId === projectRef) {
2591
+ throw new WhisperError({
2592
+ code: "PROJECT_NOT_FOUND",
2593
+ message: `Project '${projectRef}' not found`
2594
+ });
2595
+ }
2596
+ return execute(resolvedProjectId);
2597
+ }
2497
2598
  classifyError(status, message) {
2498
2599
  if (status === 401 || /api key|unauthorized|forbidden/i.test(message)) {
2499
2600
  return { code: "INVALID_API_KEY", retryable: false };
@@ -2609,29 +2710,42 @@ var WhisperContext = class _WhisperContext {
2609
2710
  return projects;
2610
2711
  }
2611
2712
  async getProject(id) {
2612
- const projectId = await this.resolveProjectId(id);
2613
- return this.request(`/v1/projects/${projectId}`);
2713
+ return this.withProjectPathFallback(
2714
+ this.getRequiredProject(id),
2715
+ (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}`)
2716
+ );
2717
+ }
2718
+ async listSources(project) {
2719
+ const projectRef = this.getRequiredProject(project);
2720
+ return this.withProjectRefFallback(
2721
+ projectRef,
2722
+ (resolvedProject) => this.request(`/v1/sources?project=${encodeURIComponent(resolvedProject)}`, { method: "GET" })
2723
+ );
2614
2724
  }
2615
2725
  async deleteProject(id) {
2616
2726
  const projectId = await this.resolveProjectId(id);
2617
2727
  return this.request(`/v1/projects/${projectId}`, { method: "DELETE" });
2618
2728
  }
2619
2729
  async addSource(projectId, params) {
2620
- const resolvedProjectId = await this.resolveProjectId(projectId);
2621
- return this.request(`/v1/projects/${resolvedProjectId}/sources`, {
2622
- method: "POST",
2623
- body: JSON.stringify(params)
2624
- });
2730
+ return this.withProjectPathFallback(
2731
+ this.getRequiredProject(projectId),
2732
+ (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/sources`, {
2733
+ method: "POST",
2734
+ body: JSON.stringify(params)
2735
+ })
2736
+ );
2625
2737
  }
2626
2738
  async syncSource(sourceId) {
2627
2739
  return this.request(`/v1/sources/${sourceId}/sync`, { method: "POST" });
2628
2740
  }
2629
2741
  async addSourceByType(projectId, params) {
2630
- const resolvedProjectId = await this.resolveProjectId(projectId);
2631
- return this.request(`/v1/projects/${resolvedProjectId}/add_source`, {
2632
- method: "POST",
2633
- body: JSON.stringify(params)
2634
- });
2742
+ return this.withProjectPathFallback(
2743
+ this.getRequiredProject(projectId),
2744
+ (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/add_source`, {
2745
+ method: "POST",
2746
+ body: JSON.stringify(params)
2747
+ })
2748
+ );
2635
2749
  }
2636
2750
  async getSourceStatus(sourceId) {
2637
2751
  return this.request(`/v1/sources/${sourceId}/status`, { method: "GET" });
@@ -2668,6 +2782,9 @@ var WhisperContext = class _WhisperContext {
2668
2782
  if (params.auth_ref) config.auth_ref = params.auth_ref;
2669
2783
  }
2670
2784
  if (params.metadata) config.metadata = params.metadata;
2785
+ if (params.ingestion_profile) config.ingestion_profile = params.ingestion_profile;
2786
+ if (params.strategy_override) config.strategy_override = params.strategy_override;
2787
+ if (params.profile_config) config.profile_config = params.profile_config;
2671
2788
  config.auto_index = params.auto_index ?? true;
2672
2789
  const created = await this.addSource(project, {
2673
2790
  name: params.name || `${params.type}-source-${Date.now()}`,
@@ -2690,14 +2807,16 @@ var WhisperContext = class _WhisperContext {
2690
2807
  };
2691
2808
  }
2692
2809
  async ingest(projectId, documents) {
2693
- const resolvedProjectId = await this.resolveProjectId(projectId);
2694
- return this.request(`/v1/projects/${resolvedProjectId}/ingest`, {
2695
- method: "POST",
2696
- body: JSON.stringify({ documents })
2697
- });
2810
+ return this.withProjectPathFallback(
2811
+ this.getRequiredProject(projectId),
2812
+ (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/ingest`, {
2813
+ method: "POST",
2814
+ body: JSON.stringify({ documents })
2815
+ })
2816
+ );
2698
2817
  }
2699
2818
  async addContext(params) {
2700
- const projectId = await this.resolveProjectId(this.getRequiredProject(params.project));
2819
+ const projectId = (await this.resolveProject(this.getRequiredProject(params.project))).id;
2701
2820
  return this.ingest(projectId, [
2702
2821
  {
2703
2822
  title: params.title || "Context",
@@ -2749,15 +2868,42 @@ var WhisperContext = class _WhisperContext {
2749
2868
  importance: params.importance,
2750
2869
  metadata: params.metadata,
2751
2870
  async: params.async,
2752
- write_mode: params.write_mode
2871
+ write_mode: params.write_mode || (params.async === true ? "async" : "sync")
2753
2872
  })
2754
2873
  });
2755
- const id2 = direct?.memory?.id || direct?.id || direct?.memory_id || direct?.job_id;
2874
+ const mode = direct?.mode === "async" ? "async" : direct?.mode === "sync" ? "sync" : void 0;
2875
+ const memoryId = direct?.memory?.id || direct?.memory_id || (mode !== "async" ? direct?.id : void 0);
2876
+ const jobId = direct?.job_id || (mode === "async" ? direct?.id : void 0);
2877
+ const id2 = memoryId || jobId || "";
2756
2878
  if (id2) {
2757
- return { id: id2, success: true, path: "sota", fallback_used: false };
2879
+ return {
2880
+ id: id2,
2881
+ success: true,
2882
+ path: "sota",
2883
+ fallback_used: false,
2884
+ mode,
2885
+ ...memoryId ? { memory_id: memoryId } : {},
2886
+ ...jobId ? { job_id: jobId } : {},
2887
+ ...direct?.status_url ? { status_url: direct.status_url } : {},
2888
+ ...direct?.accepted_at ? { accepted_at: direct.accepted_at } : {},
2889
+ ...direct?.visibility_sla_ms ? { visibility_sla_ms: direct.visibility_sla_ms } : {},
2890
+ ...direct?.pending_visibility !== void 0 ? { pending_visibility: Boolean(direct.pending_visibility) } : {},
2891
+ ...direct?.semantic_status ? { semantic_status: direct.semantic_status } : {}
2892
+ };
2758
2893
  }
2759
2894
  if (direct?.success === true) {
2760
- return { id: "", success: true, path: "sota", fallback_used: false };
2895
+ return {
2896
+ id: "",
2897
+ success: true,
2898
+ path: "sota",
2899
+ fallback_used: false,
2900
+ mode,
2901
+ ...direct?.status_url ? { status_url: direct.status_url } : {},
2902
+ ...direct?.accepted_at ? { accepted_at: direct.accepted_at } : {},
2903
+ ...direct?.visibility_sla_ms ? { visibility_sla_ms: direct.visibility_sla_ms } : {},
2904
+ ...direct?.pending_visibility !== void 0 ? { pending_visibility: Boolean(direct.pending_visibility) } : {},
2905
+ ...direct?.semantic_status ? { semantic_status: direct.semantic_status } : {}
2906
+ };
2761
2907
  }
2762
2908
  } catch (error) {
2763
2909
  if (params.allow_legacy_fallback === false) {
@@ -2785,7 +2931,15 @@ var WhisperContext = class _WhisperContext {
2785
2931
  message: "Memory create succeeded but no memory id was returned by the API"
2786
2932
  });
2787
2933
  }
2788
- return { id, success: true, path: "legacy", fallback_used: true };
2934
+ return {
2935
+ id,
2936
+ success: true,
2937
+ path: "legacy",
2938
+ fallback_used: true,
2939
+ mode: "sync",
2940
+ memory_id: id,
2941
+ semantic_status: "ready"
2942
+ };
2789
2943
  });
2790
2944
  }
2791
2945
  async addMemoriesBulk(params) {
@@ -3072,28 +3226,37 @@ var WhisperContext = class _WhisperContext {
3072
3226
  });
3073
3227
  }
3074
3228
  async createSharedContext(params) {
3075
- const project = await this.resolveProjectId(this.getRequiredProject(params.project));
3076
- return this.request("/v1/context/share", {
3077
- method: "POST",
3078
- body: JSON.stringify({ ...params, project })
3079
- });
3229
+ const projectRef = this.getRequiredProject(params.project);
3230
+ return this.withProjectRefFallback(
3231
+ projectRef,
3232
+ (project) => this.request("/v1/context/share", {
3233
+ method: "POST",
3234
+ body: JSON.stringify({ ...params, project })
3235
+ })
3236
+ );
3080
3237
  }
3081
3238
  async loadSharedContext(shareId) {
3082
3239
  return this.request(`/v1/context/shared/${shareId}`);
3083
3240
  }
3084
3241
  async resumeFromSharedContext(params) {
3085
- const project = await this.resolveProjectId(this.getRequiredProject(params.project));
3086
- return this.request("/v1/context/resume", {
3087
- method: "POST",
3088
- body: JSON.stringify({ ...params, project })
3089
- });
3242
+ const projectRef = this.getRequiredProject(params.project);
3243
+ return this.withProjectRefFallback(
3244
+ projectRef,
3245
+ (project) => this.request("/v1/context/resume", {
3246
+ method: "POST",
3247
+ body: JSON.stringify({ ...params, project })
3248
+ })
3249
+ );
3090
3250
  }
3091
3251
  async consolidateMemories(params) {
3092
- const project = await this.resolveProjectId(this.getRequiredProject(params.project));
3093
- return this.request("/v1/memory/consolidate", {
3094
- method: "POST",
3095
- body: JSON.stringify({ ...params, project })
3096
- });
3252
+ const projectRef = this.getRequiredProject(params.project);
3253
+ return this.withProjectRefFallback(
3254
+ projectRef,
3255
+ (project) => this.request("/v1/memory/consolidate", {
3256
+ method: "POST",
3257
+ body: JSON.stringify({ ...params, project })
3258
+ })
3259
+ );
3097
3260
  }
3098
3261
  async updateImportanceDecay(params) {
3099
3262
  const project = await this.resolveProjectId(this.getRequiredProject(params.project));
package/index.mjs CHANGED
@@ -135,6 +135,7 @@ var RuntimeClient = class {
135
135
  diagnostics;
136
136
  inFlight = /* @__PURE__ */ new Map();
137
137
  sendApiKeyHeader;
138
+ fetchImpl;
138
139
  constructor(options, diagnostics) {
139
140
  if (!options.apiKey) {
140
141
  throw new RuntimeClientError({
@@ -159,6 +160,7 @@ var RuntimeClient = class {
159
160
  ...options.timeouts || {}
160
161
  };
161
162
  this.sendApiKeyHeader = process.env.WHISPER_SEND_X_API_KEY === "1";
163
+ this.fetchImpl = options.fetchImpl || fetch;
162
164
  this.diagnostics = diagnostics || new DiagnosticsStore(1e3);
163
165
  }
164
166
  getDiagnosticsStore() {
@@ -279,7 +281,7 @@ var RuntimeClient = class {
279
281
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
280
282
  try {
281
283
  const attachApiKeyHeader = this.shouldAttachApiKeyHeader(normalizedEndpoint);
282
- const response = await fetch(`${this.baseUrl}${normalizedEndpoint}`, {
284
+ const response = await this.fetchImpl(`${this.baseUrl}${normalizedEndpoint}`, {
283
285
  method,
284
286
  signal: controller.signal,
285
287
  keepalive: method !== "GET",
@@ -988,7 +990,7 @@ var MemoryModule = class {
988
990
  async add(params) {
989
991
  const project = this.resolveProject(params.project);
990
992
  const queueEnabled = this.options.queueEnabled !== false;
991
- const useQueue = queueEnabled && params.write_mode !== "sync" && params.async !== false;
993
+ const useQueue = queueEnabled && (params.write_mode === "async" || params.async === true);
992
994
  if (useQueue) {
993
995
  const queued = await this.queue.enqueue({
994
996
  project,
@@ -1033,14 +1035,18 @@ var MemoryModule = class {
1033
1035
  metadata: params.metadata,
1034
1036
  document_date: params.document_date,
1035
1037
  event_date: params.event_date,
1036
- write_mode: "sync"
1038
+ write_mode: params.write_mode === "async" || params.async === true ? "async" : "sync"
1037
1039
  }
1038
1040
  });
1039
1041
  this.invalidate(project, params.user_id, params.session_id);
1040
1042
  return {
1041
1043
  success: true,
1042
1044
  mode: "sync",
1043
- trace_id: response.traceId
1045
+ trace_id: response.trace_id || response.traceId,
1046
+ memory_id: response.memory_id || response.memory?.id,
1047
+ semantic_status: response.semantic_status || response.memory?.semantic_status,
1048
+ pending_visibility: Boolean(response.pending_visibility),
1049
+ visibility_sla_ms: response.visibility_sla_ms
1044
1050
  };
1045
1051
  } catch (error) {
1046
1052
  if (this.client.getCompatMode() !== "fallback" || !isEndpointNotFound(error)) {
@@ -1078,7 +1084,7 @@ var MemoryModule = class {
1078
1084
  });
1079
1085
  }
1080
1086
  const queueEnabled = this.options.queueEnabled !== false;
1081
- const useQueue = queueEnabled && params.write_mode !== "sync" && params.async !== false;
1087
+ const useQueue = queueEnabled && (params.write_mode === "async" || params.async === true);
1082
1088
  if (useQueue) {
1083
1089
  const queued = await Promise.all(
1084
1090
  params.memories.map(
@@ -1122,7 +1128,7 @@ var MemoryModule = class {
1122
1128
  ...memory,
1123
1129
  memory_type: toSotaType(memory.memory_type)
1124
1130
  })),
1125
- write_mode: "sync"
1131
+ write_mode: params.write_mode === "async" || params.async === true ? "async" : "sync"
1126
1132
  }
1127
1133
  });
1128
1134
  for (const memory of params.memories) {
@@ -1555,7 +1561,8 @@ var WhisperClient = class _WhisperClient {
1555
1561
  baseUrl: config.baseUrl,
1556
1562
  compatMode: config.compatMode || "fallback",
1557
1563
  timeouts: config.timeouts,
1558
- retryPolicy: config.retryPolicy
1564
+ retryPolicy: config.retryPolicy,
1565
+ fetchImpl: config.fetch
1559
1566
  },
1560
1567
  this.diagnosticsStore
1561
1568
  );
@@ -2367,9 +2374,71 @@ var WhisperContext = class _WhisperContext {
2367
2374
  this.projectRefToId.set(p.slug, p.id);
2368
2375
  this.projectRefToId.set(p.name, p.id);
2369
2376
  }
2377
+ if (this.defaultProject) {
2378
+ const hasDefaultProject = this.projectCache.some(
2379
+ (project) => project.id === this.defaultProject || project.slug === this.defaultProject || project.name === this.defaultProject
2380
+ );
2381
+ if (!hasDefaultProject) {
2382
+ const resolvedDefault = await this.fetchResolvedProject(this.defaultProject);
2383
+ if (resolvedDefault) {
2384
+ this.projectCache = [...this.projectCache, resolvedDefault];
2385
+ this.projectRefToId.set(resolvedDefault.id, resolvedDefault.id);
2386
+ this.projectRefToId.set(resolvedDefault.slug, resolvedDefault.id);
2387
+ this.projectRefToId.set(resolvedDefault.name, resolvedDefault.id);
2388
+ }
2389
+ }
2390
+ }
2370
2391
  this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
2371
2392
  return this.projectCache;
2372
2393
  }
2394
+ async fetchResolvedProject(projectRef) {
2395
+ if (!projectRef) return null;
2396
+ try {
2397
+ const response = await this.request(`/v1/projects/resolve?project=${encodeURIComponent(projectRef)}`, { method: "GET" });
2398
+ return response?.resolved || null;
2399
+ } catch (error) {
2400
+ if (error instanceof WhisperError && error.code === "PROJECT_NOT_FOUND") {
2401
+ return null;
2402
+ }
2403
+ throw error;
2404
+ }
2405
+ }
2406
+ async resolveProject(projectRef) {
2407
+ const resolvedRef = this.getRequiredProject(projectRef);
2408
+ const cachedProjects = await this.refreshProjectCache(false);
2409
+ const cachedProject = cachedProjects.find(
2410
+ (project) => project.id === resolvedRef || project.slug === resolvedRef || project.name === resolvedRef
2411
+ );
2412
+ if (cachedProject) {
2413
+ return cachedProject;
2414
+ }
2415
+ const resolvedProject = await this.fetchResolvedProject(resolvedRef);
2416
+ if (resolvedProject) {
2417
+ this.projectRefToId.set(resolvedProject.id, resolvedProject.id);
2418
+ this.projectRefToId.set(resolvedProject.slug, resolvedProject.id);
2419
+ this.projectRefToId.set(resolvedProject.name, resolvedProject.id);
2420
+ this.projectCache = [
2421
+ ...this.projectCache.filter((project) => project.id !== resolvedProject.id),
2422
+ resolvedProject
2423
+ ];
2424
+ this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
2425
+ return resolvedProject;
2426
+ }
2427
+ if (isLikelyProjectId(resolvedRef)) {
2428
+ return {
2429
+ id: resolvedRef,
2430
+ orgId: "",
2431
+ name: resolvedRef,
2432
+ slug: resolvedRef,
2433
+ createdAt: (/* @__PURE__ */ new Date(0)).toISOString(),
2434
+ updatedAt: (/* @__PURE__ */ new Date(0)).toISOString()
2435
+ };
2436
+ }
2437
+ throw new WhisperError({
2438
+ code: "PROJECT_NOT_FOUND",
2439
+ message: `Project '${resolvedRef}' not found`
2440
+ });
2441
+ }
2373
2442
  async resolveProjectId(projectRef) {
2374
2443
  if (this.projectRefToId.has(projectRef)) {
2375
2444
  return this.projectRefToId.get(projectRef);
@@ -2390,6 +2459,18 @@ var WhisperContext = class _WhisperContext {
2390
2459
  if (isLikelyProjectId(projectRef)) {
2391
2460
  return projectRef;
2392
2461
  }
2462
+ const resolvedProject = await this.fetchResolvedProject(projectRef);
2463
+ if (resolvedProject) {
2464
+ this.projectRefToId.set(resolvedProject.id, resolvedProject.id);
2465
+ this.projectRefToId.set(resolvedProject.slug, resolvedProject.id);
2466
+ this.projectRefToId.set(resolvedProject.name, resolvedProject.id);
2467
+ this.projectCache = [
2468
+ ...this.projectCache.filter((project) => project.id !== resolvedProject.id),
2469
+ resolvedProject
2470
+ ];
2471
+ this.projectCacheExpiresAt = Date.now() + PROJECT_CACHE_TTL_MS;
2472
+ return resolvedProject.id;
2473
+ }
2393
2474
  throw new WhisperError({
2394
2475
  code: "PROJECT_NOT_FOUND",
2395
2476
  message: `Project '${projectRef}' not found`
@@ -2445,6 +2526,26 @@ var WhisperContext = class _WhisperContext {
2445
2526
  message: `Project '${projectRef}' not found`
2446
2527
  });
2447
2528
  }
2529
+ shouldRetryWithResolvedProjectId(error) {
2530
+ return error instanceof WhisperError && error.status === 404 && !this.isEndpointNotFoundError(error);
2531
+ }
2532
+ async withProjectPathFallback(projectRef, execute) {
2533
+ try {
2534
+ return await execute(projectRef);
2535
+ } catch (error) {
2536
+ if (!this.shouldRetryWithResolvedProjectId(error)) {
2537
+ throw error;
2538
+ }
2539
+ }
2540
+ const resolvedProjectId = await this.resolveProjectId(projectRef);
2541
+ if (resolvedProjectId === projectRef) {
2542
+ throw new WhisperError({
2543
+ code: "PROJECT_NOT_FOUND",
2544
+ message: `Project '${projectRef}' not found`
2545
+ });
2546
+ }
2547
+ return execute(resolvedProjectId);
2548
+ }
2448
2549
  classifyError(status, message) {
2449
2550
  if (status === 401 || /api key|unauthorized|forbidden/i.test(message)) {
2450
2551
  return { code: "INVALID_API_KEY", retryable: false };
@@ -2560,29 +2661,42 @@ var WhisperContext = class _WhisperContext {
2560
2661
  return projects;
2561
2662
  }
2562
2663
  async getProject(id) {
2563
- const projectId = await this.resolveProjectId(id);
2564
- return this.request(`/v1/projects/${projectId}`);
2664
+ return this.withProjectPathFallback(
2665
+ this.getRequiredProject(id),
2666
+ (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}`)
2667
+ );
2668
+ }
2669
+ async listSources(project) {
2670
+ const projectRef = this.getRequiredProject(project);
2671
+ return this.withProjectRefFallback(
2672
+ projectRef,
2673
+ (resolvedProject) => this.request(`/v1/sources?project=${encodeURIComponent(resolvedProject)}`, { method: "GET" })
2674
+ );
2565
2675
  }
2566
2676
  async deleteProject(id) {
2567
2677
  const projectId = await this.resolveProjectId(id);
2568
2678
  return this.request(`/v1/projects/${projectId}`, { method: "DELETE" });
2569
2679
  }
2570
2680
  async addSource(projectId, params) {
2571
- const resolvedProjectId = await this.resolveProjectId(projectId);
2572
- return this.request(`/v1/projects/${resolvedProjectId}/sources`, {
2573
- method: "POST",
2574
- body: JSON.stringify(params)
2575
- });
2681
+ return this.withProjectPathFallback(
2682
+ this.getRequiredProject(projectId),
2683
+ (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/sources`, {
2684
+ method: "POST",
2685
+ body: JSON.stringify(params)
2686
+ })
2687
+ );
2576
2688
  }
2577
2689
  async syncSource(sourceId) {
2578
2690
  return this.request(`/v1/sources/${sourceId}/sync`, { method: "POST" });
2579
2691
  }
2580
2692
  async addSourceByType(projectId, params) {
2581
- const resolvedProjectId = await this.resolveProjectId(projectId);
2582
- return this.request(`/v1/projects/${resolvedProjectId}/add_source`, {
2583
- method: "POST",
2584
- body: JSON.stringify(params)
2585
- });
2693
+ return this.withProjectPathFallback(
2694
+ this.getRequiredProject(projectId),
2695
+ (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/add_source`, {
2696
+ method: "POST",
2697
+ body: JSON.stringify(params)
2698
+ })
2699
+ );
2586
2700
  }
2587
2701
  async getSourceStatus(sourceId) {
2588
2702
  return this.request(`/v1/sources/${sourceId}/status`, { method: "GET" });
@@ -2619,6 +2733,9 @@ var WhisperContext = class _WhisperContext {
2619
2733
  if (params.auth_ref) config.auth_ref = params.auth_ref;
2620
2734
  }
2621
2735
  if (params.metadata) config.metadata = params.metadata;
2736
+ if (params.ingestion_profile) config.ingestion_profile = params.ingestion_profile;
2737
+ if (params.strategy_override) config.strategy_override = params.strategy_override;
2738
+ if (params.profile_config) config.profile_config = params.profile_config;
2622
2739
  config.auto_index = params.auto_index ?? true;
2623
2740
  const created = await this.addSource(project, {
2624
2741
  name: params.name || `${params.type}-source-${Date.now()}`,
@@ -2641,14 +2758,16 @@ var WhisperContext = class _WhisperContext {
2641
2758
  };
2642
2759
  }
2643
2760
  async ingest(projectId, documents) {
2644
- const resolvedProjectId = await this.resolveProjectId(projectId);
2645
- return this.request(`/v1/projects/${resolvedProjectId}/ingest`, {
2646
- method: "POST",
2647
- body: JSON.stringify({ documents })
2648
- });
2761
+ return this.withProjectPathFallback(
2762
+ this.getRequiredProject(projectId),
2763
+ (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/ingest`, {
2764
+ method: "POST",
2765
+ body: JSON.stringify({ documents })
2766
+ })
2767
+ );
2649
2768
  }
2650
2769
  async addContext(params) {
2651
- const projectId = await this.resolveProjectId(this.getRequiredProject(params.project));
2770
+ const projectId = (await this.resolveProject(this.getRequiredProject(params.project))).id;
2652
2771
  return this.ingest(projectId, [
2653
2772
  {
2654
2773
  title: params.title || "Context",
@@ -2700,15 +2819,42 @@ var WhisperContext = class _WhisperContext {
2700
2819
  importance: params.importance,
2701
2820
  metadata: params.metadata,
2702
2821
  async: params.async,
2703
- write_mode: params.write_mode
2822
+ write_mode: params.write_mode || (params.async === true ? "async" : "sync")
2704
2823
  })
2705
2824
  });
2706
- const id2 = direct?.memory?.id || direct?.id || direct?.memory_id || direct?.job_id;
2825
+ const mode = direct?.mode === "async" ? "async" : direct?.mode === "sync" ? "sync" : void 0;
2826
+ const memoryId = direct?.memory?.id || direct?.memory_id || (mode !== "async" ? direct?.id : void 0);
2827
+ const jobId = direct?.job_id || (mode === "async" ? direct?.id : void 0);
2828
+ const id2 = memoryId || jobId || "";
2707
2829
  if (id2) {
2708
- return { id: id2, success: true, path: "sota", fallback_used: false };
2830
+ return {
2831
+ id: id2,
2832
+ success: true,
2833
+ path: "sota",
2834
+ fallback_used: false,
2835
+ mode,
2836
+ ...memoryId ? { memory_id: memoryId } : {},
2837
+ ...jobId ? { job_id: jobId } : {},
2838
+ ...direct?.status_url ? { status_url: direct.status_url } : {},
2839
+ ...direct?.accepted_at ? { accepted_at: direct.accepted_at } : {},
2840
+ ...direct?.visibility_sla_ms ? { visibility_sla_ms: direct.visibility_sla_ms } : {},
2841
+ ...direct?.pending_visibility !== void 0 ? { pending_visibility: Boolean(direct.pending_visibility) } : {},
2842
+ ...direct?.semantic_status ? { semantic_status: direct.semantic_status } : {}
2843
+ };
2709
2844
  }
2710
2845
  if (direct?.success === true) {
2711
- return { id: "", success: true, path: "sota", fallback_used: false };
2846
+ return {
2847
+ id: "",
2848
+ success: true,
2849
+ path: "sota",
2850
+ fallback_used: false,
2851
+ mode,
2852
+ ...direct?.status_url ? { status_url: direct.status_url } : {},
2853
+ ...direct?.accepted_at ? { accepted_at: direct.accepted_at } : {},
2854
+ ...direct?.visibility_sla_ms ? { visibility_sla_ms: direct.visibility_sla_ms } : {},
2855
+ ...direct?.pending_visibility !== void 0 ? { pending_visibility: Boolean(direct.pending_visibility) } : {},
2856
+ ...direct?.semantic_status ? { semantic_status: direct.semantic_status } : {}
2857
+ };
2712
2858
  }
2713
2859
  } catch (error) {
2714
2860
  if (params.allow_legacy_fallback === false) {
@@ -2736,7 +2882,15 @@ var WhisperContext = class _WhisperContext {
2736
2882
  message: "Memory create succeeded but no memory id was returned by the API"
2737
2883
  });
2738
2884
  }
2739
- return { id, success: true, path: "legacy", fallback_used: true };
2885
+ return {
2886
+ id,
2887
+ success: true,
2888
+ path: "legacy",
2889
+ fallback_used: true,
2890
+ mode: "sync",
2891
+ memory_id: id,
2892
+ semantic_status: "ready"
2893
+ };
2740
2894
  });
2741
2895
  }
2742
2896
  async addMemoriesBulk(params) {
@@ -3023,28 +3177,37 @@ var WhisperContext = class _WhisperContext {
3023
3177
  });
3024
3178
  }
3025
3179
  async createSharedContext(params) {
3026
- const project = await this.resolveProjectId(this.getRequiredProject(params.project));
3027
- return this.request("/v1/context/share", {
3028
- method: "POST",
3029
- body: JSON.stringify({ ...params, project })
3030
- });
3180
+ const projectRef = this.getRequiredProject(params.project);
3181
+ return this.withProjectRefFallback(
3182
+ projectRef,
3183
+ (project) => this.request("/v1/context/share", {
3184
+ method: "POST",
3185
+ body: JSON.stringify({ ...params, project })
3186
+ })
3187
+ );
3031
3188
  }
3032
3189
  async loadSharedContext(shareId) {
3033
3190
  return this.request(`/v1/context/shared/${shareId}`);
3034
3191
  }
3035
3192
  async resumeFromSharedContext(params) {
3036
- const project = await this.resolveProjectId(this.getRequiredProject(params.project));
3037
- return this.request("/v1/context/resume", {
3038
- method: "POST",
3039
- body: JSON.stringify({ ...params, project })
3040
- });
3193
+ const projectRef = this.getRequiredProject(params.project);
3194
+ return this.withProjectRefFallback(
3195
+ projectRef,
3196
+ (project) => this.request("/v1/context/resume", {
3197
+ method: "POST",
3198
+ body: JSON.stringify({ ...params, project })
3199
+ })
3200
+ );
3041
3201
  }
3042
3202
  async consolidateMemories(params) {
3043
- const project = await this.resolveProjectId(this.getRequiredProject(params.project));
3044
- return this.request("/v1/memory/consolidate", {
3045
- method: "POST",
3046
- body: JSON.stringify({ ...params, project })
3047
- });
3203
+ const projectRef = this.getRequiredProject(params.project);
3204
+ return this.withProjectRefFallback(
3205
+ projectRef,
3206
+ (project) => this.request("/v1/memory/consolidate", {
3207
+ method: "POST",
3208
+ body: JSON.stringify({ ...params, project })
3209
+ })
3210
+ );
3048
3211
  }
3049
3212
  async updateImportanceDecay(params) {
3050
3213
  const project = await this.resolveProjectId(this.getRequiredProject(params.project));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usewhisper/sdk",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "whisperContractVersion": "2026.03.09",
5
5
  "scripts": {
6
6
  "build": "tsup ../src/sdk/index.ts --format esm,cjs --dts --out-dir .",