@usewhisper/sdk 3.8.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/index.d.mts +182 -65
  2. package/index.d.ts +182 -65
  3. package/index.js +173 -75
  4. package/index.mjs +173 -75
  5. package/package.json +1 -1
package/index.js CHANGED
@@ -2126,9 +2126,33 @@ ${lines.join("\n")}`;
2126
2126
  }
2127
2127
  });
2128
2128
  }
2129
+ async resolveLearningScope(overrides) {
2130
+ const merged = {
2131
+ ...this.baseContext,
2132
+ ...overrides
2133
+ };
2134
+ const { scope } = await this.resolveScope(overrides);
2135
+ return {
2136
+ project: scope.project,
2137
+ sessionId: merged.sessionId || scope.sessionId,
2138
+ userId: merged.userId
2139
+ };
2140
+ }
2129
2141
  async afterTurn(input, context = {}) {
2130
2142
  this.pushTouchedFiles(input.touchedFiles);
2131
- const { scope } = await this.resolveScope(context);
2143
+ if (input.auto_learn === false) {
2144
+ return {
2145
+ success: true,
2146
+ sessionIngested: false,
2147
+ memoriesCreated: 0,
2148
+ relationsCreated: 0,
2149
+ invalidatedCount: 0,
2150
+ mergedCount: 0,
2151
+ droppedCount: 0,
2152
+ warnings: []
2153
+ };
2154
+ }
2155
+ const scope = await this.resolveLearningScope(context);
2132
2156
  const result = await this.args.adapter.ingestSession({
2133
2157
  project: scope.project,
2134
2158
  session_id: scope.sessionId,
@@ -2511,6 +2535,19 @@ var WhisperClient = class _WhisperClient {
2511
2535
  });
2512
2536
  return response.data;
2513
2537
  }
2538
+ async learn(params) {
2539
+ const project = (await this.resolveProject(params.project)).id;
2540
+ const response = await this.runtimeClient.request({
2541
+ endpoint: "/v1/learn",
2542
+ method: "POST",
2543
+ operation: params.mode === "conversation" ? "session" : "bulk",
2544
+ body: {
2545
+ ...params,
2546
+ project
2547
+ }
2548
+ });
2549
+ return response.data;
2550
+ }
2514
2551
  createAgentRuntime(options = {}) {
2515
2552
  const baseContext = {
2516
2553
  workspacePath: options.workspacePath,
@@ -2559,6 +2596,14 @@ var WhisperClient = class _WhisperClient {
2559
2596
  sessionId: params.sessionId || context.sessionId || ""
2560
2597
  })
2561
2598
  },
2599
+ learn: (params) => base.learn({
2600
+ ...params,
2601
+ project: params.project || context.project || base.config.project,
2602
+ ...params.mode === "conversation" ? {
2603
+ user_id: params.user_id ?? context.userId,
2604
+ session_id: params.session_id || context.sessionId || ""
2605
+ } : {}
2606
+ }),
2562
2607
  queue: base.queue,
2563
2608
  diagnostics: base.diagnostics
2564
2609
  };
@@ -2770,6 +2815,9 @@ ${context}` : "",
2770
2815
  * Capture from multiple messages (e.g., full conversation)
2771
2816
  */
2772
2817
  async captureSession(messages, options) {
2818
+ if (options?.auto_learn === false) {
2819
+ return { success: true, extracted: 0 };
2820
+ }
2773
2821
  try {
2774
2822
  const filteredMessages = messages.filter((m) => m.role !== "system");
2775
2823
  const runtime = this.runtimeClient.createAgentRuntime({
@@ -2780,7 +2828,8 @@ ${context}` : "",
2780
2828
  });
2781
2829
  const result = await runtime.afterTurn({
2782
2830
  userMessage: [...filteredMessages].reverse().find((m) => m.role === "user")?.content || "",
2783
- assistantMessage: [...filteredMessages].reverse().find((m) => m.role === "assistant")?.content || ""
2831
+ assistantMessage: [...filteredMessages].reverse().find((m) => m.role === "assistant")?.content || "",
2832
+ auto_learn: options?.auto_learn
2784
2833
  });
2785
2834
  return {
2786
2835
  success: true,
@@ -2817,7 +2866,8 @@ User: ${params.userMessage}` : params.userMessage;
2817
2866
  {
2818
2867
  userId: params.userId,
2819
2868
  sessionId: params.sessionId,
2820
- project: params.project
2869
+ project: params.project,
2870
+ auto_learn: params.auto_learn
2821
2871
  }
2822
2872
  );
2823
2873
  return {
@@ -2827,6 +2877,18 @@ User: ${params.userMessage}` : params.userMessage;
2827
2877
  extracted: captureResult.extracted
2828
2878
  };
2829
2879
  }
2880
+ async learn(input) {
2881
+ const params = input.mode === "conversation" ? {
2882
+ ...input,
2883
+ project: input.project ?? this.options.project,
2884
+ user_id: input.user_id ?? this.userId,
2885
+ session_id: input.session_id || this.sessionId || "default"
2886
+ } : {
2887
+ ...input,
2888
+ project: input.project ?? this.options.project
2889
+ };
2890
+ return this.runtimeClient.learn(params);
2891
+ }
2830
2892
  /**
2831
2893
  * Direct access to WhisperContext for advanced usage
2832
2894
  */
@@ -2912,7 +2974,8 @@ User: ${userMessage}`;
2912
2974
  {
2913
2975
  userId: params.userId,
2914
2976
  sessionId: params.sessionId,
2915
- project: params.project
2977
+ project: params.project,
2978
+ auto_learn: params.auto_learn
2916
2979
  }
2917
2980
  );
2918
2981
  }
@@ -2924,7 +2987,8 @@ User: ${userMessage}`;
2924
2987
  assistantMessage: response,
2925
2988
  userId: params.userId,
2926
2989
  sessionId: params.sessionId,
2927
- project: params.project
2990
+ project: params.project,
2991
+ auto_learn: params.auto_learn
2928
2992
  });
2929
2993
  return {
2930
2994
  response,
@@ -3814,91 +3878,125 @@ var WhisperContext = class _WhisperContext {
3814
3878
  return this.request(`/v1/sources/${sourceId}/sync`, { method: "POST" });
3815
3879
  }
3816
3880
  async addSourceByType(projectId, params) {
3817
- return this.withProjectPathFallback(
3818
- this.getRequiredProject(projectId),
3819
- (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/add_source`, {
3820
- method: "POST",
3821
- body: JSON.stringify(params)
3822
- })
3823
- );
3881
+ const result = await this.learn({
3882
+ mode: "source",
3883
+ project: projectId,
3884
+ type: "video",
3885
+ name: params.name,
3886
+ url: params.url,
3887
+ platform: params.platform,
3888
+ language: params.language,
3889
+ options: {
3890
+ async: true,
3891
+ auto_index: params.auto_sync ?? true,
3892
+ ingestion_profile: params.ingestion_profile,
3893
+ strategy_override: params.strategy_override,
3894
+ profile_config: params.profile_config,
3895
+ allow_stt_fallback: params.allow_stt_fallback,
3896
+ max_duration_minutes: params.max_duration_minutes
3897
+ }
3898
+ });
3899
+ return {
3900
+ source_id: result.source_id,
3901
+ sync_job_id: result.job_id ?? null,
3902
+ status: result.status === "processing" || result.status === "queued" ? result.status : "created"
3903
+ };
3824
3904
  }
3825
3905
  async getSourceStatus(sourceId) {
3826
3906
  return this.request(`/v1/sources/${sourceId}/status`, { method: "GET" });
3827
3907
  }
3828
3908
  async createCanonicalSource(project, params) {
3829
- const connector_type = params.type === "github" ? "github" : params.type === "web" ? "website" : params.type === "pdf" ? "pdf" : params.type === "local" ? "local-folder" : "slack";
3830
- const config = {};
3831
- if (params.type === "github") {
3832
- if (!params.owner || !params.repo) throw new WhisperError({ code: "REQUEST_FAILED", message: "github source requires owner and repo" });
3833
- config.owner = params.owner;
3834
- config.repo = params.repo;
3835
- if (params.branch) config.branch = params.branch;
3836
- if (params.paths) config.paths = params.paths;
3837
- } else if (params.type === "web") {
3838
- if (!params.url) throw new WhisperError({ code: "REQUEST_FAILED", message: "web source requires url" });
3839
- config.url = params.url;
3840
- if (params.crawl_depth !== void 0) config.crawl_depth = params.crawl_depth;
3841
- if (params.include_paths) config.include_paths = params.include_paths;
3842
- if (params.exclude_paths) config.exclude_paths = params.exclude_paths;
3843
- } else if (params.type === "pdf") {
3844
- if (!params.url && !params.file_path) throw new WhisperError({ code: "REQUEST_FAILED", message: "pdf source requires url or file_path" });
3845
- if (params.url) config.url = params.url;
3846
- if (params.file_path) config.file_path = params.file_path;
3847
- } else if (params.type === "local") {
3848
- if (!params.path) throw new WhisperError({ code: "REQUEST_FAILED", message: "local source requires path" });
3849
- config.path = params.path;
3850
- if (params.glob) config.glob = params.glob;
3851
- if (params.max_files !== void 0) config.max_files = params.max_files;
3852
- } else {
3853
- config.channel_ids = params.channel_ids || [];
3854
- if (params.since) config.since = params.since;
3855
- if (params.workspace_id) config.workspace_id = params.workspace_id;
3856
- if (params.token) config.token = params.token;
3857
- if (params.auth_ref) config.auth_ref = params.auth_ref;
3858
- }
3859
- if (params.metadata) config.metadata = params.metadata;
3860
- if (params.ingestion_profile) config.ingestion_profile = params.ingestion_profile;
3861
- if (params.strategy_override) config.strategy_override = params.strategy_override;
3862
- if (params.profile_config) config.profile_config = params.profile_config;
3863
- config.auto_index = params.auto_index ?? true;
3864
- const created = await this.addSource(project, {
3865
- name: params.name || `${params.type}-source-${Date.now()}`,
3866
- connector_type,
3867
- config
3909
+ const result = await this.learn({
3910
+ mode: "source",
3911
+ project,
3912
+ type: params.type,
3913
+ name: params.name,
3914
+ metadata: params.metadata,
3915
+ owner: params.owner,
3916
+ repo: params.repo,
3917
+ branch: params.branch,
3918
+ paths: params.paths,
3919
+ url: params.url,
3920
+ file_path: params.file_path,
3921
+ path: params.path,
3922
+ channel_ids: params.channel_ids,
3923
+ since: params.since,
3924
+ token: params.token,
3925
+ auth_ref: params.auth_ref,
3926
+ platform: params.platform,
3927
+ language: params.language,
3928
+ options: {
3929
+ async: true,
3930
+ auto_index: params.auto_index ?? true,
3931
+ ingestion_profile: params.ingestion_profile,
3932
+ strategy_override: params.strategy_override,
3933
+ profile_config: params.profile_config,
3934
+ crawl_depth: params.crawl_depth,
3935
+ include_paths: params.include_paths,
3936
+ exclude_paths: params.exclude_paths,
3937
+ glob: params.glob,
3938
+ max_files: params.max_files,
3939
+ max_pages: params.max_pages,
3940
+ extract_mode: params.extract_mode,
3941
+ workspace_id: params.workspace_id,
3942
+ allow_stt_fallback: params.allow_stt_fallback,
3943
+ max_duration_minutes: params.max_duration_minutes,
3944
+ max_chunks: params.max_chunks
3945
+ }
3868
3946
  });
3869
- let status = "queued";
3870
- let jobId = null;
3871
- if (params.auto_index ?? true) {
3872
- const syncRes = await this.syncSource(created.id);
3873
- status = "indexing";
3874
- jobId = String(syncRes?.id || syncRes?.job_id || "");
3875
- }
3876
3947
  return {
3877
- source_id: created.id,
3878
- status,
3879
- job_id: jobId,
3880
- index_started: params.auto_index ?? true,
3948
+ source_id: result.source_id,
3949
+ status: result.status === "processing" ? "indexing" : result.status === "created" ? "queued" : result.status,
3950
+ job_id: result.job_id ?? null,
3951
+ index_started: result.index_started,
3881
3952
  warnings: []
3882
3953
  };
3883
3954
  }
3884
3955
  async ingest(projectId, documents) {
3885
- return this.withProjectPathFallback(
3886
- this.getRequiredProject(projectId),
3887
- (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/ingest`, {
3888
- method: "POST",
3889
- body: JSON.stringify({ documents })
3890
- })
3956
+ await Promise.all(
3957
+ documents.map(
3958
+ (doc) => this.learn({
3959
+ mode: "text",
3960
+ project: projectId,
3961
+ title: doc.title,
3962
+ content: doc.content,
3963
+ metadata: {
3964
+ ...doc.metadata || {},
3965
+ ...doc.file_path ? { file_path: doc.file_path } : {}
3966
+ },
3967
+ options: {
3968
+ async: true,
3969
+ ingestion_profile: doc.ingestion_profile,
3970
+ strategy_override: doc.strategy_override,
3971
+ profile_config: doc.profile_config
3972
+ }
3973
+ })
3974
+ )
3891
3975
  );
3976
+ return { ingested: documents.length };
3892
3977
  }
3893
3978
  async addContext(params) {
3894
- const projectId = (await this.resolveProject(this.getRequiredProject(params.project))).id;
3895
- return this.ingest(projectId, [
3896
- {
3897
- title: params.title || "Context",
3898
- content: params.content,
3899
- metadata: params.metadata || { source: "addContext" }
3979
+ await this.learn({
3980
+ mode: "text",
3981
+ project: this.getRequiredProject(params.project),
3982
+ title: params.title || "Context",
3983
+ content: params.content,
3984
+ metadata: params.metadata || { source: "addContext" },
3985
+ options: {
3986
+ async: true
3900
3987
  }
3901
- ]);
3988
+ });
3989
+ return { ingested: 1 };
3990
+ }
3991
+ async learn(params) {
3992
+ const projectRef = this.getRequiredProject(params.project);
3993
+ return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/learn", {
3994
+ method: "POST",
3995
+ body: JSON.stringify({
3996
+ ...params,
3997
+ project
3998
+ })
3999
+ }));
3902
4000
  }
3903
4001
  async listMemories(params) {
3904
4002
  const projectRef = this.getRequiredProject(params.project);
package/index.mjs CHANGED
@@ -2077,9 +2077,33 @@ ${lines.join("\n")}`;
2077
2077
  }
2078
2078
  });
2079
2079
  }
2080
+ async resolveLearningScope(overrides) {
2081
+ const merged = {
2082
+ ...this.baseContext,
2083
+ ...overrides
2084
+ };
2085
+ const { scope } = await this.resolveScope(overrides);
2086
+ return {
2087
+ project: scope.project,
2088
+ sessionId: merged.sessionId || scope.sessionId,
2089
+ userId: merged.userId
2090
+ };
2091
+ }
2080
2092
  async afterTurn(input, context = {}) {
2081
2093
  this.pushTouchedFiles(input.touchedFiles);
2082
- const { scope } = await this.resolveScope(context);
2094
+ if (input.auto_learn === false) {
2095
+ return {
2096
+ success: true,
2097
+ sessionIngested: false,
2098
+ memoriesCreated: 0,
2099
+ relationsCreated: 0,
2100
+ invalidatedCount: 0,
2101
+ mergedCount: 0,
2102
+ droppedCount: 0,
2103
+ warnings: []
2104
+ };
2105
+ }
2106
+ const scope = await this.resolveLearningScope(context);
2083
2107
  const result = await this.args.adapter.ingestSession({
2084
2108
  project: scope.project,
2085
2109
  session_id: scope.sessionId,
@@ -2462,6 +2486,19 @@ var WhisperClient = class _WhisperClient {
2462
2486
  });
2463
2487
  return response.data;
2464
2488
  }
2489
+ async learn(params) {
2490
+ const project = (await this.resolveProject(params.project)).id;
2491
+ const response = await this.runtimeClient.request({
2492
+ endpoint: "/v1/learn",
2493
+ method: "POST",
2494
+ operation: params.mode === "conversation" ? "session" : "bulk",
2495
+ body: {
2496
+ ...params,
2497
+ project
2498
+ }
2499
+ });
2500
+ return response.data;
2501
+ }
2465
2502
  createAgentRuntime(options = {}) {
2466
2503
  const baseContext = {
2467
2504
  workspacePath: options.workspacePath,
@@ -2510,6 +2547,14 @@ var WhisperClient = class _WhisperClient {
2510
2547
  sessionId: params.sessionId || context.sessionId || ""
2511
2548
  })
2512
2549
  },
2550
+ learn: (params) => base.learn({
2551
+ ...params,
2552
+ project: params.project || context.project || base.config.project,
2553
+ ...params.mode === "conversation" ? {
2554
+ user_id: params.user_id ?? context.userId,
2555
+ session_id: params.session_id || context.sessionId || ""
2556
+ } : {}
2557
+ }),
2513
2558
  queue: base.queue,
2514
2559
  diagnostics: base.diagnostics
2515
2560
  };
@@ -2721,6 +2766,9 @@ ${context}` : "",
2721
2766
  * Capture from multiple messages (e.g., full conversation)
2722
2767
  */
2723
2768
  async captureSession(messages, options) {
2769
+ if (options?.auto_learn === false) {
2770
+ return { success: true, extracted: 0 };
2771
+ }
2724
2772
  try {
2725
2773
  const filteredMessages = messages.filter((m) => m.role !== "system");
2726
2774
  const runtime = this.runtimeClient.createAgentRuntime({
@@ -2731,7 +2779,8 @@ ${context}` : "",
2731
2779
  });
2732
2780
  const result = await runtime.afterTurn({
2733
2781
  userMessage: [...filteredMessages].reverse().find((m) => m.role === "user")?.content || "",
2734
- assistantMessage: [...filteredMessages].reverse().find((m) => m.role === "assistant")?.content || ""
2782
+ assistantMessage: [...filteredMessages].reverse().find((m) => m.role === "assistant")?.content || "",
2783
+ auto_learn: options?.auto_learn
2735
2784
  });
2736
2785
  return {
2737
2786
  success: true,
@@ -2768,7 +2817,8 @@ User: ${params.userMessage}` : params.userMessage;
2768
2817
  {
2769
2818
  userId: params.userId,
2770
2819
  sessionId: params.sessionId,
2771
- project: params.project
2820
+ project: params.project,
2821
+ auto_learn: params.auto_learn
2772
2822
  }
2773
2823
  );
2774
2824
  return {
@@ -2778,6 +2828,18 @@ User: ${params.userMessage}` : params.userMessage;
2778
2828
  extracted: captureResult.extracted
2779
2829
  };
2780
2830
  }
2831
+ async learn(input) {
2832
+ const params = input.mode === "conversation" ? {
2833
+ ...input,
2834
+ project: input.project ?? this.options.project,
2835
+ user_id: input.user_id ?? this.userId,
2836
+ session_id: input.session_id || this.sessionId || "default"
2837
+ } : {
2838
+ ...input,
2839
+ project: input.project ?? this.options.project
2840
+ };
2841
+ return this.runtimeClient.learn(params);
2842
+ }
2781
2843
  /**
2782
2844
  * Direct access to WhisperContext for advanced usage
2783
2845
  */
@@ -2863,7 +2925,8 @@ User: ${userMessage}`;
2863
2925
  {
2864
2926
  userId: params.userId,
2865
2927
  sessionId: params.sessionId,
2866
- project: params.project
2928
+ project: params.project,
2929
+ auto_learn: params.auto_learn
2867
2930
  }
2868
2931
  );
2869
2932
  }
@@ -2875,7 +2938,8 @@ User: ${userMessage}`;
2875
2938
  assistantMessage: response,
2876
2939
  userId: params.userId,
2877
2940
  sessionId: params.sessionId,
2878
- project: params.project
2941
+ project: params.project,
2942
+ auto_learn: params.auto_learn
2879
2943
  });
2880
2944
  return {
2881
2945
  response,
@@ -3765,91 +3829,125 @@ var WhisperContext = class _WhisperContext {
3765
3829
  return this.request(`/v1/sources/${sourceId}/sync`, { method: "POST" });
3766
3830
  }
3767
3831
  async addSourceByType(projectId, params) {
3768
- return this.withProjectPathFallback(
3769
- this.getRequiredProject(projectId),
3770
- (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/add_source`, {
3771
- method: "POST",
3772
- body: JSON.stringify(params)
3773
- })
3774
- );
3832
+ const result = await this.learn({
3833
+ mode: "source",
3834
+ project: projectId,
3835
+ type: "video",
3836
+ name: params.name,
3837
+ url: params.url,
3838
+ platform: params.platform,
3839
+ language: params.language,
3840
+ options: {
3841
+ async: true,
3842
+ auto_index: params.auto_sync ?? true,
3843
+ ingestion_profile: params.ingestion_profile,
3844
+ strategy_override: params.strategy_override,
3845
+ profile_config: params.profile_config,
3846
+ allow_stt_fallback: params.allow_stt_fallback,
3847
+ max_duration_minutes: params.max_duration_minutes
3848
+ }
3849
+ });
3850
+ return {
3851
+ source_id: result.source_id,
3852
+ sync_job_id: result.job_id ?? null,
3853
+ status: result.status === "processing" || result.status === "queued" ? result.status : "created"
3854
+ };
3775
3855
  }
3776
3856
  async getSourceStatus(sourceId) {
3777
3857
  return this.request(`/v1/sources/${sourceId}/status`, { method: "GET" });
3778
3858
  }
3779
3859
  async createCanonicalSource(project, params) {
3780
- const connector_type = params.type === "github" ? "github" : params.type === "web" ? "website" : params.type === "pdf" ? "pdf" : params.type === "local" ? "local-folder" : "slack";
3781
- const config = {};
3782
- if (params.type === "github") {
3783
- if (!params.owner || !params.repo) throw new WhisperError({ code: "REQUEST_FAILED", message: "github source requires owner and repo" });
3784
- config.owner = params.owner;
3785
- config.repo = params.repo;
3786
- if (params.branch) config.branch = params.branch;
3787
- if (params.paths) config.paths = params.paths;
3788
- } else if (params.type === "web") {
3789
- if (!params.url) throw new WhisperError({ code: "REQUEST_FAILED", message: "web source requires url" });
3790
- config.url = params.url;
3791
- if (params.crawl_depth !== void 0) config.crawl_depth = params.crawl_depth;
3792
- if (params.include_paths) config.include_paths = params.include_paths;
3793
- if (params.exclude_paths) config.exclude_paths = params.exclude_paths;
3794
- } else if (params.type === "pdf") {
3795
- if (!params.url && !params.file_path) throw new WhisperError({ code: "REQUEST_FAILED", message: "pdf source requires url or file_path" });
3796
- if (params.url) config.url = params.url;
3797
- if (params.file_path) config.file_path = params.file_path;
3798
- } else if (params.type === "local") {
3799
- if (!params.path) throw new WhisperError({ code: "REQUEST_FAILED", message: "local source requires path" });
3800
- config.path = params.path;
3801
- if (params.glob) config.glob = params.glob;
3802
- if (params.max_files !== void 0) config.max_files = params.max_files;
3803
- } else {
3804
- config.channel_ids = params.channel_ids || [];
3805
- if (params.since) config.since = params.since;
3806
- if (params.workspace_id) config.workspace_id = params.workspace_id;
3807
- if (params.token) config.token = params.token;
3808
- if (params.auth_ref) config.auth_ref = params.auth_ref;
3809
- }
3810
- if (params.metadata) config.metadata = params.metadata;
3811
- if (params.ingestion_profile) config.ingestion_profile = params.ingestion_profile;
3812
- if (params.strategy_override) config.strategy_override = params.strategy_override;
3813
- if (params.profile_config) config.profile_config = params.profile_config;
3814
- config.auto_index = params.auto_index ?? true;
3815
- const created = await this.addSource(project, {
3816
- name: params.name || `${params.type}-source-${Date.now()}`,
3817
- connector_type,
3818
- config
3860
+ const result = await this.learn({
3861
+ mode: "source",
3862
+ project,
3863
+ type: params.type,
3864
+ name: params.name,
3865
+ metadata: params.metadata,
3866
+ owner: params.owner,
3867
+ repo: params.repo,
3868
+ branch: params.branch,
3869
+ paths: params.paths,
3870
+ url: params.url,
3871
+ file_path: params.file_path,
3872
+ path: params.path,
3873
+ channel_ids: params.channel_ids,
3874
+ since: params.since,
3875
+ token: params.token,
3876
+ auth_ref: params.auth_ref,
3877
+ platform: params.platform,
3878
+ language: params.language,
3879
+ options: {
3880
+ async: true,
3881
+ auto_index: params.auto_index ?? true,
3882
+ ingestion_profile: params.ingestion_profile,
3883
+ strategy_override: params.strategy_override,
3884
+ profile_config: params.profile_config,
3885
+ crawl_depth: params.crawl_depth,
3886
+ include_paths: params.include_paths,
3887
+ exclude_paths: params.exclude_paths,
3888
+ glob: params.glob,
3889
+ max_files: params.max_files,
3890
+ max_pages: params.max_pages,
3891
+ extract_mode: params.extract_mode,
3892
+ workspace_id: params.workspace_id,
3893
+ allow_stt_fallback: params.allow_stt_fallback,
3894
+ max_duration_minutes: params.max_duration_minutes,
3895
+ max_chunks: params.max_chunks
3896
+ }
3819
3897
  });
3820
- let status = "queued";
3821
- let jobId = null;
3822
- if (params.auto_index ?? true) {
3823
- const syncRes = await this.syncSource(created.id);
3824
- status = "indexing";
3825
- jobId = String(syncRes?.id || syncRes?.job_id || "");
3826
- }
3827
3898
  return {
3828
- source_id: created.id,
3829
- status,
3830
- job_id: jobId,
3831
- index_started: params.auto_index ?? true,
3899
+ source_id: result.source_id,
3900
+ status: result.status === "processing" ? "indexing" : result.status === "created" ? "queued" : result.status,
3901
+ job_id: result.job_id ?? null,
3902
+ index_started: result.index_started,
3832
3903
  warnings: []
3833
3904
  };
3834
3905
  }
3835
3906
  async ingest(projectId, documents) {
3836
- return this.withProjectPathFallback(
3837
- this.getRequiredProject(projectId),
3838
- (projectPathRef) => this.request(`/v1/projects/${encodeURIComponent(projectPathRef)}/ingest`, {
3839
- method: "POST",
3840
- body: JSON.stringify({ documents })
3841
- })
3907
+ await Promise.all(
3908
+ documents.map(
3909
+ (doc) => this.learn({
3910
+ mode: "text",
3911
+ project: projectId,
3912
+ title: doc.title,
3913
+ content: doc.content,
3914
+ metadata: {
3915
+ ...doc.metadata || {},
3916
+ ...doc.file_path ? { file_path: doc.file_path } : {}
3917
+ },
3918
+ options: {
3919
+ async: true,
3920
+ ingestion_profile: doc.ingestion_profile,
3921
+ strategy_override: doc.strategy_override,
3922
+ profile_config: doc.profile_config
3923
+ }
3924
+ })
3925
+ )
3842
3926
  );
3927
+ return { ingested: documents.length };
3843
3928
  }
3844
3929
  async addContext(params) {
3845
- const projectId = (await this.resolveProject(this.getRequiredProject(params.project))).id;
3846
- return this.ingest(projectId, [
3847
- {
3848
- title: params.title || "Context",
3849
- content: params.content,
3850
- metadata: params.metadata || { source: "addContext" }
3930
+ await this.learn({
3931
+ mode: "text",
3932
+ project: this.getRequiredProject(params.project),
3933
+ title: params.title || "Context",
3934
+ content: params.content,
3935
+ metadata: params.metadata || { source: "addContext" },
3936
+ options: {
3937
+ async: true
3851
3938
  }
3852
- ]);
3939
+ });
3940
+ return { ingested: 1 };
3941
+ }
3942
+ async learn(params) {
3943
+ const projectRef = this.getRequiredProject(params.project);
3944
+ return this.withProjectRefFallback(projectRef, (project) => this.request("/v1/learn", {
3945
+ method: "POST",
3946
+ body: JSON.stringify({
3947
+ ...params,
3948
+ project
3949
+ })
3950
+ }));
3853
3951
  }
3854
3952
  async listMemories(params) {
3855
3953
  const projectRef = this.getRequiredProject(params.project);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usewhisper/sdk",
3
- "version": "3.8.0",
3
+ "version": "3.10.0",
4
4
  "whisperContractVersion": "2026.03.10",
5
5
  "scripts": {
6
6
  "build": "tsup ../src/sdk/index.ts --format esm,cjs --dts --out-dir .",