@@ -4,6 +4,7 @@ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
44import { AnthropicInstrumentation } from "@traceloop/instrumentation-anthropic" ;
55import { CohereInstrumentation } from "@traceloop/instrumentation-cohere" ;
66import { OpenAIInstrumentation } from "@traceloop/instrumentation-openai" ;
7+ import { SyncClient } from "./sync" ;
78
89import { HumanloopClient as BaseHumanloopClient } from "./Client" ;
910import { ChatMessage } from "./api" ;
@@ -210,6 +211,7 @@ export class HumanloopClient extends BaseHumanloopClient {
210211 Anthropic ?: any ;
211212 CohereAI ?: any ;
212213 } ;
214+ protected readonly _syncClient : SyncClient ;
213215
214216 protected get opentelemetryTracer ( ) : Tracer {
215217 return HumanloopTracerSingleton . getInstance ( {
@@ -254,6 +256,8 @@ export class HumanloopClient extends BaseHumanloopClient {
254256 ) {
255257 super ( _options ) ;
256258
259+ this . _syncClient = new SyncClient ( this ) ;
260+
257261 this . instrumentProviders = _options . instrumentProviders || { } ;
258262
259263 this . _prompts_overloaded = overloadLog ( super . prompts ) ;
@@ -560,6 +564,45 @@ ${RESET}`,
560564 ) ;
561565 }
562566
567+ /**
568+ * Pull Prompt and Agent files from Humanloop to local filesystem.
569+ *
570+ * This method will:
571+ * 1. Fetch Prompt and Agent files from your Humanloop workspace
572+ * 2. Save them to the local filesystem using the client's files_directory (set during initialization)
573+ * 3. Maintain the same directory structure as in Humanloop
574+ * 4. Add appropriate file extensions (.prompt or .agent)
575+ *
576+ * The path parameter can be used in two ways:
577+ * - If it points to a specific file (e.g. "path/to/file.prompt" or "path/to/file.agent"), only that file will be pulled
578+ * - If it points to a directory (e.g. "path/to/directory"), all Prompt and Agent files in that directory will be pulled
579+ * - If no path is provided, all Prompt and Agent files will be pulled
580+ *
581+ * The operation will overwrite existing files with the latest version from Humanloop
582+ * but will not delete local files that don't exist in the remote workspace.
583+ *
584+ * Currently only supports syncing prompt and agent files. Other file types will be skipped.
585+ *
586+ * The files will be saved with the following structure:
587+ * ```
588+ * {files_directory}/
589+ * ├── prompts/
590+ * │ ├── my_prompt.prompt
591+ * │ └── nested/
592+ * │ └── another_prompt.prompt
593+ * └── agents/
594+ * └── my_agent.agent
595+ * ```
596+ *
597+ * @param path - Optional path to either a specific file (e.g. "path/to/file.prompt") or a directory (e.g. "path/to/directory").
598+ * If not provided, all Prompt and Agent files will be pulled.
599+ * @param environment - The environment to pull the files from.
600+ * @returns List of successfully processed file paths.
601+ */
602+ public async pull ( path ?: string , environment ?: string ) : Promise < string [ ] > {
603+ return this . _syncClient . pull ( path , environment ) ;
604+ }
605+
563606 public get evaluations ( ) : ExtendedEvaluations {
564607 return this . _evaluations ;
565608 }
0 commit comments