effect-cursor-sdk 0.3.1 → 0.3.4

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.
package/README.md CHANGED
@@ -6,6 +6,8 @@ Effect-native access to the new [Cursor SDK](https://cursor.com/docs/sdk/typescr
6
6
 
7
7
  `effect-cursor-sdk` wraps `@cursor/sdk` with Effect services, layers, scoped resource management, tagged errors, observability hooks, deterministic mocks, and ready-made runtimes. The upstream SDK remains the source of truth for Cursor-owned types; this package adds Effect ergonomics without creating a parallel model that can drift.
8
8
 
9
+ If you want to build with Cursor agents, and you are using Effect, this package is for you.
10
+
9
11
  > [!WARNING]
10
12
  > This project is in early development. While all functionality is available, there is still much room for improvement. Contributions are welcome!
11
13
 
@@ -39,6 +41,12 @@ Effect-native access to the new [Cursor SDK](https://cursor.com/docs/sdk/typescr
39
41
  | MCP servers, sub-agents, local/cloud options, model options | Defaults via `CursorConfig` / `loadCursorConfig`; merged SDK `AgentOptions` ([deprecated](./DEPRECATIONS.md) at agent entry) |
40
42
  | Local run event helpers and platform helpers | Re-exported from `@cursor/sdk` |
41
43
 
44
+ ## Use cases
45
+
46
+ If you are new to the Cursor SDK, take a look at the [Cursor SDK Cookbook](https://github.com/cursor/cookbook). This cookbook provides some (cool!) examples of what you could do with the SDK.
47
+
48
+ `effect-cursor-sdk` even [uses itself](#automated-changeset-agent) to spin up a Cursor agent to create changesets for pull requests against `main`! 🤯
49
+
42
50
  ## Install
43
51
 
44
52
  ```bash
@@ -272,10 +280,10 @@ Swap `liveLayer` for `mockLayer({ ... })` in tests and the same program shape ex
272
280
 
273
281
  ## Errors
274
282
 
275
- SDK failures are mapped into tagged errors such as `CursorAuthenticationError`, `CursorRateLimitError`, `CursorConfigurationError`, `CursorNetworkError`, and `CursorUnsupportedOperationError`. The original SDK error is preserved as `cause`, with safe operation context and retryability where available.
283
+ SDK failures are mapped into tagged errors such as `CursorAuthenticationError`, `CursorRateLimitError`, `CursorConfigurationError`, `CursorAgentBusyError`, `CursorNetworkError`, and `CursorUnsupportedOperationError`. The original SDK error is preserved as `cause`, with safe operation context and retryability where available.
276
284
 
277
285
  ```ts
278
- program.pipe(
286
+ const handled = program.pipe(
279
287
  Effect.catchTag("CursorRateLimitError", (error) =>
280
288
  Effect.logWarning(`Cursor rate limited request: ${error.message}`),
281
289
  ),
@@ -368,7 +376,15 @@ User-facing changes should include a Changeset:
368
376
  bun run changeset
369
377
  ```
370
378
 
371
- On `main`, GitHub Actions uses Changesets to open a version PR when pending Changesets exist. After that PR is merged, the same workflow runs `bun run release` and publishes to NPM with the `NPM_TOKEN` repository secret.
379
+ ### Automated Changeset Agent
380
+
381
+ This repository also includes a Cursor-powered changeset agent for pull requests against `main`. The workflow in `.github/workflows/changeset-agent.yml` runs `bun run changeset:agent`, starts a scoped local Cursor SDK agent with this package, asks it to inspect the PR diff, and commits a missing `.changeset/*.md` file back to the PR branch when release impact exists.
382
+
383
+ The job runs only for same-repository, non-draft PRs because it needs both the `CURSOR_API_KEY` repository secret and write access to the PR branch. Forked PRs should add changesets manually or be handled from a trusted maintainer checkout.
384
+
385
+ Other, optional environment variables are `CURSOR_MODEL` for the Cursor model id and `CHANGESET_BASE_REF` for the diff base. See [Changeset Agent](./docs/changeset-agent.md) for the full architecture, prompt contract, security model, and local usage.
386
+
387
+ On `main`, GitHub Actions uses Changesets to open a version PR when pending Changesets exist. After that PR is merged, the same workflow runs `bun run release` and publishes to NPM.
372
388
 
373
389
  For local release preparation, apply pending Changesets and publish only after the package is approved for public release:
374
390
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Config, Context, Effect, Layer, ManagedRuntime, Metric, Option, Redacted, Schedule, Schema, Scope, Stream } from "effect";
2
- import { AgentDefinition, AgentMessage, AgentOperationOptions, AgentOptions, AuthenticationError, ConfigurationError, CursorAgentError, CursorAgentPlatform, CursorRequestOptions, GetAgentMessagesOptions, GetAgentOptions, GetRunOptions, IntegrationNotConnectedError, ListAgentsOptions, ListResult, ListRunsOptions, McpServerConfig, ModelListItem, ModelParameterDefinition, ModelParameterValue, ModelSelection, ModelVariant, NetworkError, RateLimitError, Run, RunOperation, RunResult, RunResultStatus, RunStatus, SDKAgent, SDKAgentInfo, SDKArtifact, SDKAssistantMessage, SDKImage, SDKImageDimension, SDKMessage, SDKModel, SDKRepository, SDKStatusMessage, SDKSystemMessage, SDKTaskMessage, SDKThinkingMessage, SDKToolUseMessage, SDKUser, SDKUserMessage, SDKUserMessageEvent, SendOptions, SettingSource, TextBlock, ToolUseBlock, UnknownAgentError, UnsupportedRunOperationError, createAgentPlatform, createInMemoryRunEventNotifier, createLocalRunEventNotifier, createSdkMessageRunStreamEvent, decodeLocalRunStreamEvent, decodeSdkMessageRunStreamEvent, getTurnType, isTerminalLocalRunStreamEvent, localRunStreamEventToSdkMessage, startLocalRunEventNotifierServer } from "@cursor/sdk";
2
+ import { AgentBusyError, AgentDefinition, AgentMessage, AgentOperationOptions, AgentOptions, AuthenticationError, ConfigurationError, CursorAgentError, CursorAgentPlatform, CursorRequestOptions, GetAgentMessagesOptions, GetAgentOptions, GetRunOptions, IntegrationNotConnectedError, ListAgentsOptions, ListResult, ListRunsOptions, McpServerConfig, ModelListItem, ModelParameterDefinition, ModelParameterValue, ModelSelection, ModelVariant, NetworkError, RateLimitError, Run, RunOperation, RunResult, RunResultStatus, RunStatus, SDKAgent, SDKAgentInfo, SDKArtifact, SDKAssistantMessage, SDKImage, SDKImageDimension, SDKMessage, SDKModel, SDKRepository, SDKStatusMessage, SDKSystemMessage, SDKTaskMessage, SDKThinkingMessage, SDKToolUseMessage, SDKUser, SDKUserMessage, SDKUserMessageEvent, SendOptions, SettingSource, TextBlock, ToolUseBlock, UnknownAgentError, UnsupportedRunOperationError, createAgentPlatform, createInMemoryRunEventNotifier, createLocalRunEventNotifier, createSdkMessageRunStreamEvent, decodeLocalRunStreamEvent, decodeSdkMessageRunStreamEvent, getTurnType, isTerminalLocalRunStreamEvent, localRunStreamEventToSdkMessage, startLocalRunEventNotifierServer } from "@cursor/sdk";
3
3
  import * as _$effect_Types0 from "effect/Types";
4
4
  import * as _$effect_Cause0 from "effect/Cause";
5
5
  import * as _$effect_Duration0 from "effect/Duration";
@@ -59,6 +59,16 @@ declare const CursorConfigurationError_base: new <A extends Record<string, any>
59
59
  * @category errors
60
60
  */
61
61
  declare class CursorConfigurationError extends CursorConfigurationError_base<CursorErrorFields> {}
62
+ declare const CursorAgentBusyError_base: new <A extends Record<string, any> = {}>(args: _$effect_Types0.VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => _$effect_Cause0.YieldableError & {
63
+ readonly _tag: "CursorAgentBusyError";
64
+ } & Readonly<A>;
65
+ /**
66
+ * The agent already has an active run; starting another run was rejected (409).
67
+ *
68
+ * @see {@link mapCursorError}
69
+ * @category errors
70
+ */
71
+ declare class CursorAgentBusyError extends CursorAgentBusyError_base<CursorErrorFields> {}
62
72
  declare const CursorIntegrationNotConnectedError_base: new <A extends Record<string, any> = {}>(args: _$effect_Types0.VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => _$effect_Cause0.YieldableError & {
63
73
  readonly _tag: "CursorIntegrationNotConnectedError";
64
74
  } & Readonly<A>;
@@ -154,8 +164,8 @@ declare function mapCursorError(cause: unknown, context: CursorErrorContext & {
154
164
  }): CursorStreamError;
155
165
  declare function mapCursorError(cause: unknown, context: CursorErrorContext & {
156
166
  readonly operation: "run.cancel" | "run.conversation";
157
- }): CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnsupportedOperationError | CursorUnknownError;
158
- declare function mapCursorError(cause: unknown, context: CursorErrorContext): CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError;
167
+ }): CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnsupportedOperationError | CursorUnknownError;
168
+ declare function mapCursorError(cause: unknown, context: CursorErrorContext): CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError;
159
169
  //#endregion
160
170
  //#region src/cursor-config.d.ts
161
171
  /**
@@ -436,7 +446,7 @@ interface CursorAgentServiceShape {
436
446
  * instead of raw {@link AgentOptions} (including a plain `apiKey` string). Next major: `createFromConfig`
437
447
  * is planned to become `create` with the same parameters.
438
448
  */
439
- readonly create: (options: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
449
+ readonly create: (options: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
440
450
  /**
441
451
  * Create an agent from {@link CursorConfig} and optional SDK overrides.
442
452
  *
@@ -446,12 +456,12 @@ interface CursorAgentServiceShape {
446
456
  * @see {@link loadCursorConfig}
447
457
  * @see {@link agentOptionsFromConfig}
448
458
  */
449
- readonly createFromConfig: (config: CursorConfig, overrides?: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
459
+ readonly createFromConfig: (config: CursorConfig, overrides?: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
450
460
  /**
451
461
  * @deprecated Prefer {@link CursorAgentServiceShape.resumeFromConfig} with {@link loadCursorConfig}
452
462
  * instead of raw {@link AgentOptions}. Next major: `resumeFromConfig` is planned to become `resume` with the same parameters.
453
463
  */
454
- readonly resume: (agentId: string, options?: Partial<AgentOptions>) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
464
+ readonly resume: (agentId: string, options?: Partial<AgentOptions>) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
455
465
  /**
456
466
  * Resume an agent from {@link CursorConfig} and optional SDK overrides.
457
467
  *
@@ -461,12 +471,12 @@ interface CursorAgentServiceShape {
461
471
  * @see {@link loadCursorConfig}
462
472
  * @see {@link agentOptionsFromConfig}
463
473
  */
464
- readonly resumeFromConfig: (agentId: string, config: CursorConfig, overrides?: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
474
+ readonly resumeFromConfig: (agentId: string, config: CursorConfig, overrides?: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
465
475
  /**
466
476
  * @deprecated Prefer {@link CursorAgentServiceShape.promptFromConfig} with {@link loadCursorConfig}
467
477
  * instead of raw {@link AgentOptions}. Next major: `promptFromConfig` is planned to become `prompt` with the same parameters.
468
478
  */
469
- readonly prompt: (message: string, options?: AgentOptions) => Effect.Effect<RunResult, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
479
+ readonly prompt: (message: string, options?: AgentOptions) => Effect.Effect<RunResult, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
470
480
  /**
471
481
  * One-shot prompt from {@link CursorConfig} and optional SDK overrides.
472
482
  *
@@ -476,16 +486,16 @@ interface CursorAgentServiceShape {
476
486
  * @see {@link loadCursorConfig}
477
487
  * @see {@link agentOptionsFromConfig}
478
488
  */
479
- readonly promptFromConfig: (message: string, config: CursorConfig, overrides?: AgentOptions) => Effect.Effect<RunResult, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
480
- readonly send: (agent: SDKAgent, message: string | SDKUserMessage, options?: SendOptions) => Effect.Effect<Run, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
481
- readonly reload: (agent: SDKAgent) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
489
+ readonly promptFromConfig: (message: string, config: CursorConfig, overrides?: AgentOptions) => Effect.Effect<RunResult, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
490
+ readonly send: (agent: SDKAgent, message: string | SDKUserMessage, options?: SendOptions) => Effect.Effect<Run, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
491
+ readonly reload: (agent: SDKAgent) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
482
492
  readonly close: (agent: SDKAgent) => Effect.Effect<void>;
483
- readonly dispose: (agent: SDKAgent) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
493
+ readonly dispose: (agent: SDKAgent) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
484
494
  /**
485
495
  * @deprecated Prefer {@link CursorAgentServiceShape.scopedFromConfig} with {@link loadCursorConfig}
486
496
  * instead of raw {@link AgentOptions}. Next major: `scopedFromConfig` is planned to become `scoped` with the same parameters.
487
497
  */
488
- readonly scoped: (options: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError, Scope.Scope>;
498
+ readonly scoped: (options: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError, Scope.Scope>;
489
499
  /**
490
500
  * Acquire an agent in a scope from {@link CursorConfig} and optional SDK overrides.
491
501
  *
@@ -495,7 +505,7 @@ interface CursorAgentServiceShape {
495
505
  * @see {@link loadCursorConfig}
496
506
  * @see {@link agentOptionsFromConfig}
497
507
  */
498
- readonly scopedFromConfig: (config: CursorConfig, overrides?: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError, Scope.Scope>;
508
+ readonly scopedFromConfig: (config: CursorConfig, overrides?: AgentOptions) => Effect.Effect<SDKAgent, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError, Scope.Scope>;
499
509
  }
500
510
  declare const CursorAgentService_base: Context.ServiceClass<CursorAgentService, "effect-cursor-sdk/cursor-agent/CursorAgentService", CursorAgentServiceShape>;
501
511
  /**
@@ -539,8 +549,8 @@ declare class CursorAgentService extends CursorAgentService_base {
539
549
  //#endregion
540
550
  //#region src/cursor-artifacts.d.ts
541
551
  interface CursorArtifactServiceShape {
542
- readonly listArtifacts: (agent: SDKAgent) => Effect.Effect<SDKArtifact[], CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
543
- readonly downloadArtifact: (agent: SDKAgent, path: string) => Effect.Effect<Buffer, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
552
+ readonly listArtifacts: (agent: SDKAgent) => Effect.Effect<SDKArtifact[], CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
553
+ readonly downloadArtifact: (agent: SDKAgent, path: string) => Effect.Effect<Buffer, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
544
554
  }
545
555
  declare const CursorArtifactService_base: Context.ServiceClass<CursorArtifactService, "effect-cursor-sdk/cursor-artifacts/CursorArtifactService", CursorArtifactServiceShape>;
546
556
  /**
@@ -563,17 +573,17 @@ declare class CursorArtifactService extends CursorArtifactService_base {
563
573
  //#endregion
564
574
  //#region src/cursor-inspection.d.ts
565
575
  interface CursorInspectionServiceShape {
566
- readonly listAgents: (options?: ListAgentsOptions) => Effect.Effect<ListResult<SDKAgentInfo>, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
567
- readonly getAgent: (agentId: string, options?: GetAgentOptions) => Effect.Effect<SDKAgentInfo, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
568
- readonly archiveAgent: (agentId: string, options?: AgentOperationOptions) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
569
- readonly unarchiveAgent: (agentId: string, options?: AgentOperationOptions) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
570
- readonly deleteAgent: (agentId: string, options?: AgentOperationOptions) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
571
- readonly listRuns: (agentId: string, options?: ListRunsOptions) => Effect.Effect<ListResult<Run>, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
572
- readonly getRun: (runId: string, options?: GetRunOptions) => Effect.Effect<Run, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
573
- readonly listMessages: (agentId: string, options?: GetAgentMessagesOptions) => Effect.Effect<AgentMessage[], CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
574
- readonly me: (options?: CursorRequestOptions) => Effect.Effect<SDKUser, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
575
- readonly listModels: (options?: CursorRequestOptions) => Effect.Effect<SDKModel[], CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
576
- readonly listRepositories: (options?: CursorRequestOptions) => Effect.Effect<SDKRepository[], CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
576
+ readonly listAgents: (options?: ListAgentsOptions) => Effect.Effect<ListResult<SDKAgentInfo>, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
577
+ readonly getAgent: (agentId: string, options?: GetAgentOptions) => Effect.Effect<SDKAgentInfo, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
578
+ readonly archiveAgent: (agentId: string, options?: AgentOperationOptions) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
579
+ readonly unarchiveAgent: (agentId: string, options?: AgentOperationOptions) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
580
+ readonly deleteAgent: (agentId: string, options?: AgentOperationOptions) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
581
+ readonly listRuns: (agentId: string, options?: ListRunsOptions) => Effect.Effect<ListResult<Run>, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
582
+ readonly getRun: (runId: string, options?: GetRunOptions) => Effect.Effect<Run, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
583
+ readonly listMessages: (agentId: string, options?: GetAgentMessagesOptions) => Effect.Effect<AgentMessage[], CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
584
+ readonly me: (options?: CursorRequestOptions) => Effect.Effect<SDKUser, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
585
+ readonly listModels: (options?: CursorRequestOptions) => Effect.Effect<SDKModel[], CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
586
+ readonly listRepositories: (options?: CursorRequestOptions) => Effect.Effect<SDKRepository[], CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
577
587
  }
578
588
  declare const CursorInspectionService_base: Context.ServiceClass<CursorInspectionService, "effect-cursor-sdk/cursor-inspection/CursorInspectionService", CursorInspectionServiceShape>;
579
589
  /**
@@ -906,9 +916,9 @@ declare const summarizeRunForLog: (run: {
906
916
  interface CursorRunServiceShape {
907
917
  readonly supports: (run: Run, operation: RunOperation) => boolean;
908
918
  readonly unsupportedReason: (run: Run, operation: RunOperation) => string | undefined;
909
- readonly wait: (run: Run) => Effect.Effect<RunResult, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnknownError>;
910
- readonly cancel: (run: Run) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnsupportedOperationError | CursorUnknownError>;
911
- readonly conversation: (run: Run) => ReturnType<Run["conversation"]> extends Promise<infer A> ? Effect.Effect<A, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorNetworkError | CursorUnsupportedOperationError | CursorUnknownError> : never;
919
+ readonly wait: (run: Run) => Effect.Effect<RunResult, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnknownError>;
920
+ readonly cancel: (run: Run) => Effect.Effect<void, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnsupportedOperationError | CursorUnknownError>;
921
+ readonly conversation: (run: Run) => ReturnType<Run["conversation"]> extends Promise<infer A> ? Effect.Effect<A, CursorAuthenticationError | CursorRateLimitError | CursorIntegrationNotConnectedError | CursorConfigurationError | CursorAgentBusyError | CursorNetworkError | CursorUnsupportedOperationError | CursorUnknownError> : never;
912
922
  readonly streamEvents: (run: Run) => Stream.Stream<SDKMessage, CursorStreamError>;
913
923
  readonly collectText: (run: Run) => Effect.Effect<string, CursorStreamError>;
914
924
  readonly onDidChangeStatus: (run: Run, listener: (status: RunStatus) => void) => Effect.Effect<() => void>;
@@ -1135,5 +1145,5 @@ declare const instrument: <A, E, R>(operation: CursorOperation, effect: Effect.E
1135
1145
  */
1136
1146
  declare const packageName = "effect-cursor-sdk";
1137
1147
  //#endregion
1138
- export { type AgentDefinition, type AgentMessage, type AgentOperationOptions, type AgentOptions, AuthenticationError, ConfigurationError, CursorAgentError, CursorAgentPlatform, CursorAgentService, CursorAgentServiceShape, CursorApiKey, CursorArtifactService, CursorArtifactServiceShape, CursorAuthenticationError, CursorConfig, CursorConfigurationError, CursorErrorContext, CursorInspectionService, CursorInspectionServiceShape, CursorIntegrationNotConnectedError, CursorLocalCwd, CursorMockFactoryMethod, CursorMockFixtures, CursorModelId, CursorNetworkError, CursorOperation, CursorRateLimitError, type CursorRequestOptions, CursorRunFailedError, CursorRunService, CursorRunServiceShape, CursorSdkFactory, CursorSdkFactoryShape, CursorStreamError, CursorUnknownError, CursorUnsupportedOperationError, type GetAgentMessagesOptions, type GetAgentOptions, type GetRunOptions, IntegrationNotConnectedError, type ListAgentsOptions, type ListResult, type ListRunsOptions, type McpServerConfig, MockCursorAgent, MockCursorRun, type ModelListItem, type ModelParameterDefinition, type ModelParameterValue, type ModelSelection, type ModelVariant, NetworkError, RateLimitError, type Run, type RunOperation, type RunResult, type RunResultStatus, type RunStatus, type SDKAgent, type SDKAgentInfo, type SDKArtifact, type SDKAssistantMessage, type SDKImage, type SDKImageDimension, type SDKMessage, type SDKModel, type SDKRepository, type SDKStatusMessage, type SDKSystemMessage, type SDKTaskMessage, type SDKThinkingMessage, type SDKToolUseMessage, type SDKUser, type SDKUserMessage, type SDKUserMessageEvent, type SendOptions, type SettingSource, type TextBlock, type ToolUseBlock, UnknownAgentError, UnsupportedRunOperationError, agentOptionsFromConfig, appendAssistantSdkMessageText, collectTextTracked, createAgentPlatform, createInMemoryRunEventNotifier, createLocalRunEventNotifier, createSdkMessageRunStreamEvent, cursorCatalogLoadTimeout, cursorCatalogRetrySchedule, cursorConfig, cursorOperationsFailed, cursorOperationsStarted, cursorStreamEvents, decodeLocalRunStreamEvent, decodeSdkMessageRunStreamEvent, getTurnType, instrument, isTerminalLocalRunStreamEvent, liveLayer, liveRuntime, loadCursorConfig, localRunStreamEventToSdkMessage, makeMockAgent, makeMockAssistantSdkMessage, makeMockRun, makeMockRuntime, makeMockSdkFactoryLayer, mapCursorError, mockLayer, packageName, redact, startLocalRunEventNotifierServer, streamEventsTracked, summarizeAgentOptionsForLog, summarizeRunForLog };
1148
+ export { AgentBusyError, type AgentDefinition, type AgentMessage, type AgentOperationOptions, type AgentOptions, AuthenticationError, ConfigurationError, CursorAgentBusyError, CursorAgentError, CursorAgentPlatform, CursorAgentService, CursorAgentServiceShape, CursorApiKey, CursorArtifactService, CursorArtifactServiceShape, CursorAuthenticationError, CursorConfig, CursorConfigurationError, CursorErrorContext, CursorInspectionService, CursorInspectionServiceShape, CursorIntegrationNotConnectedError, CursorLocalCwd, CursorMockFactoryMethod, CursorMockFixtures, CursorModelId, CursorNetworkError, CursorOperation, CursorRateLimitError, type CursorRequestOptions, CursorRunFailedError, CursorRunService, CursorRunServiceShape, CursorSdkFactory, CursorSdkFactoryShape, CursorStreamError, CursorUnknownError, CursorUnsupportedOperationError, type GetAgentMessagesOptions, type GetAgentOptions, type GetRunOptions, IntegrationNotConnectedError, type ListAgentsOptions, type ListResult, type ListRunsOptions, type McpServerConfig, MockCursorAgent, MockCursorRun, type ModelListItem, type ModelParameterDefinition, type ModelParameterValue, type ModelSelection, type ModelVariant, NetworkError, RateLimitError, type Run, type RunOperation, type RunResult, type RunResultStatus, type RunStatus, type SDKAgent, type SDKAgentInfo, type SDKArtifact, type SDKAssistantMessage, type SDKImage, type SDKImageDimension, type SDKMessage, type SDKModel, type SDKRepository, type SDKStatusMessage, type SDKSystemMessage, type SDKTaskMessage, type SDKThinkingMessage, type SDKToolUseMessage, type SDKUser, type SDKUserMessage, type SDKUserMessageEvent, type SendOptions, type SettingSource, type TextBlock, type ToolUseBlock, UnknownAgentError, UnsupportedRunOperationError, agentOptionsFromConfig, appendAssistantSdkMessageText, collectTextTracked, createAgentPlatform, createInMemoryRunEventNotifier, createLocalRunEventNotifier, createSdkMessageRunStreamEvent, cursorCatalogLoadTimeout, cursorCatalogRetrySchedule, cursorConfig, cursorOperationsFailed, cursorOperationsStarted, cursorStreamEvents, decodeLocalRunStreamEvent, decodeSdkMessageRunStreamEvent, getTurnType, instrument, isTerminalLocalRunStreamEvent, liveLayer, liveRuntime, loadCursorConfig, localRunStreamEventToSdkMessage, makeMockAgent, makeMockAssistantSdkMessage, makeMockRun, makeMockRuntime, makeMockSdkFactoryLayer, mapCursorError, mockLayer, packageName, redact, startLocalRunEventNotifierServer, streamEventsTracked, summarizeAgentOptionsForLog, summarizeRunForLog };
1139
1149
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Config, ConfigProvider, Context, Data, Effect, Layer, ManagedRuntime, Match, Metric, Option, Redacted, Schedule, Schema, Stream } from "effect";
2
- import { Agent, AuthenticationError, AuthenticationError as AuthenticationError$1, ConfigurationError, ConfigurationError as ConfigurationError$1, Cursor, CursorAgentError, CursorAgentError as CursorAgentError$1, CursorAgentPlatform, IntegrationNotConnectedError, IntegrationNotConnectedError as IntegrationNotConnectedError$1, NetworkError, NetworkError as NetworkError$1, RateLimitError, RateLimitError as RateLimitError$1, UnknownAgentError, UnknownAgentError as UnknownAgentError$1, UnsupportedRunOperationError, UnsupportedRunOperationError as UnsupportedRunOperationError$1, createAgentPlatform, createInMemoryRunEventNotifier, createLocalRunEventNotifier, createSdkMessageRunStreamEvent, decodeLocalRunStreamEvent, decodeSdkMessageRunStreamEvent, getTurnType, isTerminalLocalRunStreamEvent, localRunStreamEventToSdkMessage, startLocalRunEventNotifierServer } from "@cursor/sdk";
2
+ import { Agent, AgentBusyError, AgentBusyError as AgentBusyError$1, AuthenticationError, AuthenticationError as AuthenticationError$1, ConfigurationError, ConfigurationError as ConfigurationError$1, Cursor, CursorAgentError, CursorAgentError as CursorAgentError$1, CursorAgentPlatform, IntegrationNotConnectedError, IntegrationNotConnectedError as IntegrationNotConnectedError$1, NetworkError, NetworkError as NetworkError$1, RateLimitError, RateLimitError as RateLimitError$1, UnknownAgentError, UnknownAgentError as UnknownAgentError$1, UnsupportedRunOperationError, UnsupportedRunOperationError as UnsupportedRunOperationError$1, createAgentPlatform, createInMemoryRunEventNotifier, createLocalRunEventNotifier, createSdkMessageRunStreamEvent, decodeLocalRunStreamEvent, decodeSdkMessageRunStreamEvent, getTurnType, isTerminalLocalRunStreamEvent, localRunStreamEventToSdkMessage, startLocalRunEventNotifierServer } from "@cursor/sdk";
3
3
  //#region src/cursor-error.ts
4
4
  /**
5
5
  * Authentication or permission failure reported by the Cursor SDK.
@@ -24,6 +24,13 @@ var CursorRateLimitError = class extends Data.TaggedError("CursorRateLimitError"
24
24
  */
25
25
  var CursorConfigurationError = class extends Data.TaggedError("CursorConfigurationError") {};
26
26
  /**
27
+ * The agent already has an active run; starting another run was rejected (409).
28
+ *
29
+ * @see {@link mapCursorError}
30
+ * @category errors
31
+ */
32
+ var CursorAgentBusyError = class extends Data.TaggedError("CursorAgentBusyError") {};
33
+ /**
27
34
  * SCM integration is not connected for a requested cloud repository.
28
35
  *
29
36
  * @see {@link mapCursorError}
@@ -98,6 +105,8 @@ function mapCursorError(cause, context) {
98
105
  });
99
106
  }), Match.when(Match.instanceOf(ConfigurationError$1), () => {
100
107
  return new CursorConfigurationError(fields);
108
+ }), Match.when(Match.instanceOf(AgentBusyError$1), () => {
109
+ return new CursorAgentBusyError(fields);
101
110
  }), Match.when(Match.instanceOf(NetworkError$1), () => {
102
111
  return new CursorNetworkError(fields);
103
112
  }), Match.when(Match.instanceOf(UnknownAgentError$1), () => {
@@ -1532,6 +1541,6 @@ const makeMockRuntime = (fixtures = {}) => {
1532
1541
  */
1533
1542
  const packageName = "effect-cursor-sdk";
1534
1543
  //#endregion
1535
- export { AuthenticationError, ConfigurationError, CursorAgentError, CursorAgentPlatform, CursorAgentService, CursorApiKey, CursorArtifactService, CursorAuthenticationError, CursorConfig, CursorConfigurationError, CursorInspectionService, CursorIntegrationNotConnectedError, CursorLocalCwd, CursorModelId, CursorNetworkError, CursorRateLimitError, CursorRunFailedError, CursorRunService, CursorSdkFactory, CursorStreamError, CursorUnknownError, CursorUnsupportedOperationError, IntegrationNotConnectedError, MockCursorAgent, MockCursorRun, NetworkError, RateLimitError, UnknownAgentError, UnsupportedRunOperationError, agentOptionsFromConfig, appendAssistantSdkMessageText, collectTextTracked, createAgentPlatform, createInMemoryRunEventNotifier, createLocalRunEventNotifier, createSdkMessageRunStreamEvent, cursorCatalogLoadTimeout, cursorCatalogRetrySchedule, cursorConfig, cursorOperationsFailed, cursorOperationsStarted, cursorStreamEvents, decodeLocalRunStreamEvent, decodeSdkMessageRunStreamEvent, getTurnType, instrument, isTerminalLocalRunStreamEvent, liveLayer, liveRuntime, loadCursorConfig, localRunStreamEventToSdkMessage, makeMockAgent, makeMockAssistantSdkMessage, makeMockRun, makeMockRuntime, makeMockSdkFactoryLayer, mapCursorError, mockLayer, packageName, redact, startLocalRunEventNotifierServer, streamEventsTracked, summarizeAgentOptionsForLog, summarizeRunForLog };
1544
+ export { AgentBusyError, AuthenticationError, ConfigurationError, CursorAgentBusyError, CursorAgentError, CursorAgentPlatform, CursorAgentService, CursorApiKey, CursorArtifactService, CursorAuthenticationError, CursorConfig, CursorConfigurationError, CursorInspectionService, CursorIntegrationNotConnectedError, CursorLocalCwd, CursorModelId, CursorNetworkError, CursorRateLimitError, CursorRunFailedError, CursorRunService, CursorSdkFactory, CursorStreamError, CursorUnknownError, CursorUnsupportedOperationError, IntegrationNotConnectedError, MockCursorAgent, MockCursorRun, NetworkError, RateLimitError, UnknownAgentError, UnsupportedRunOperationError, agentOptionsFromConfig, appendAssistantSdkMessageText, collectTextTracked, createAgentPlatform, createInMemoryRunEventNotifier, createLocalRunEventNotifier, createSdkMessageRunStreamEvent, cursorCatalogLoadTimeout, cursorCatalogRetrySchedule, cursorConfig, cursorOperationsFailed, cursorOperationsStarted, cursorStreamEvents, decodeLocalRunStreamEvent, decodeSdkMessageRunStreamEvent, getTurnType, instrument, isTerminalLocalRunStreamEvent, liveLayer, liveRuntime, loadCursorConfig, localRunStreamEventToSdkMessage, makeMockAgent, makeMockAssistantSdkMessage, makeMockRun, makeMockRuntime, makeMockSdkFactoryLayer, mapCursorError, mockLayer, packageName, redact, startLocalRunEventNotifierServer, streamEventsTracked, summarizeAgentOptionsForLog, summarizeRunForLog };
1536
1545
 
1537
1546
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["CursorAgentError","AuthenticationError","RateLimitError","IntegrationNotConnectedError","UnsupportedRunOperationError","ConfigurationError","NetworkError","UnknownAgentError","#status","#listeners","#sendIndex"],"sources":["../src/cursor-error.ts","../src/cursor-config.ts","../src/cursor-sdk-factory.ts","../src/cursor-telemetry.ts","../src/cursor-agent.ts","../src/cursor-artifacts.ts","../src/cursor-inspection.ts","../src/cursor-mock.ts","../src/cursor-observability.ts","../src/cursor-run.ts","../src/cursor-runtime.ts","../src/index.ts"],"sourcesContent":["import {\n AuthenticationError,\n ConfigurationError,\n CursorAgentError,\n IntegrationNotConnectedError,\n NetworkError,\n RateLimitError,\n UnknownAgentError,\n UnsupportedRunOperationError,\n} from \"@cursor/sdk\";\nimport { Data, Match } from \"effect\";\n\nimport type { RunOperation } from \"./cursor-types\";\n\n/**\n * The operation being executed when an SDK error crossed into Effect.\n *\n * @category errors\n */\nexport type CursorOperation =\n | \"agent.create\"\n | \"agent.resume\"\n | \"agent.prompt\"\n | \"agent.send\"\n | \"agent.close\"\n | \"agent.reload\"\n | \"agent.dispose\"\n | \"agent.list\"\n | \"agent.get\"\n | \"agent.archive\"\n | \"agent.unarchive\"\n | \"agent.delete\"\n | \"messages.list\"\n | \"run.list\"\n | \"run.get\"\n | \"run.wait\"\n | \"run.stream\"\n | \"run.conversation\"\n | \"run.cancel\"\n | \"artifacts.list\"\n | \"artifacts.download\"\n | \"cursor.me\"\n | \"cursor.models.list\"\n | \"cursor.repositories.list\";\n\n/**\n * Safe metadata attached to wrapper errors.\n *\n * @category errors\n */\nexport interface CursorErrorContext {\n readonly operation: CursorOperation;\n readonly agentId?: string;\n readonly runId?: string;\n readonly runtime?: \"local\" | \"cloud\";\n readonly status?: string;\n}\n\ninterface CursorErrorFields extends CursorErrorContext {\n readonly message: string;\n readonly cause: unknown;\n readonly isRetryable: boolean;\n}\n\n/**\n * Authentication or permission failure reported by the Cursor SDK.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorAuthenticationError extends Data.TaggedError(\n \"CursorAuthenticationError\",\n)<CursorErrorFields> {}\n\n/**\n * Cursor rate limit or usage-limit failure.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorRateLimitError extends Data.TaggedError(\n \"CursorRateLimitError\",\n)<CursorErrorFields> {}\n\n/**\n * Invalid configuration, model, prompt, repository, or request options.\n *\n * @see {@link AgentOptions}\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorConfigurationError extends Data.TaggedError(\n \"CursorConfigurationError\",\n)<CursorErrorFields> {}\n\n/**\n * SCM integration is not connected for a requested cloud repository.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorIntegrationNotConnectedError extends Data.TaggedError(\n \"CursorIntegrationNotConnectedError\",\n)<CursorErrorFields & { readonly provider?: string; readonly helpUrl?: string }> {}\n\n/**\n * Network, service availability, timeout, or backend failure.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorNetworkError extends Data.TaggedError(\"CursorNetworkError\")<CursorErrorFields> {}\n\n/**\n * A run operation is unavailable for the current runtime or run state.\n *\n * @see {@link RunOperation}\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorUnsupportedOperationError extends Data.TaggedError(\n \"CursorUnsupportedOperationError\",\n)<CursorErrorFields & { readonly sdkOperation?: RunOperation }> {}\n\n/**\n * A run reached an error terminal state or failed to produce a usable result.\n *\n * @see {@link RunResult}\n * @category errors\n */\nexport class CursorRunFailedError extends Data.TaggedError(\n \"CursorRunFailedError\",\n)<CursorErrorFields> {}\n\n/**\n * Stream creation or iteration failed.\n *\n * @see {@link CursorRunService}\n * @see {@link SDKMessage}\n * @category errors\n */\nexport class CursorStreamError extends Data.TaggedError(\"CursorStreamError\")<CursorErrorFields> {}\n\n/**\n * Fallback for unknown SDK or JavaScript failures.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorUnknownError extends Data.TaggedError(\"CursorUnknownError\")<CursorErrorFields> {}\n\nconst messageFrom = (cause: unknown): string => {\n return cause instanceof Error ? cause.message : String(cause);\n};\n\nconst retryableFrom = (cause: unknown): boolean => {\n return cause instanceof CursorAgentError ? cause.isRetryable : false;\n};\n\n/**\n * Convert any SDK failure into a tagged Effect error.\n *\n * @param cause - Unknown value thrown by `@cursor/sdk` or JavaScript runtime code.\n * @param context - Safe operation metadata to attach to the tagged error.\n *\n * @example\n * ```ts\n * import { Effect } from \"effect\"\n * import { mapCursorError } from \"effect-cursor-sdk\"\n *\n * const effect = Effect.tryPromise({\n * try: () => run.wait(),\n * catch: (cause) => mapCursorError(cause, { operation: \"run.wait\", runId: run.id })\n * })\n * ```\n *\n * @see {@link CursorAuthenticationError}\n * @see {@link CursorUnsupportedOperationError}\n * @see {@link CursorStreamError}\n *\n * @category errors\n */\nexport function mapCursorError(\n cause: unknown,\n context: CursorErrorContext & { readonly operation: \"run.stream\" },\n): CursorStreamError;\nexport function mapCursorError(\n cause: unknown,\n context: CursorErrorContext & { readonly operation: \"run.cancel\" | \"run.conversation\" },\n):\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnsupportedOperationError\n | CursorUnknownError;\nexport function mapCursorError(\n cause: unknown,\n context: CursorErrorContext,\n):\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError;\nexport function mapCursorError(cause: unknown, context: CursorErrorContext) {\n const fields = {\n ...context,\n message: messageFrom(cause),\n cause,\n isRetryable: retryableFrom(cause),\n };\n\n if (context.operation === \"run.stream\") {\n return new CursorStreamError(fields);\n }\n\n return Match.value(cause).pipe(\n Match.when(Match.instanceOf(AuthenticationError), () => {\n return new CursorAuthenticationError(fields);\n }),\n Match.when(Match.instanceOf(RateLimitError), () => {\n return new CursorRateLimitError(fields);\n }),\n Match.when(Match.instanceOf(IntegrationNotConnectedError), (error) => {\n return new CursorIntegrationNotConnectedError({\n ...fields,\n provider: error.provider,\n helpUrl: error.helpUrl,\n });\n }),\n Match.when(Match.instanceOf(UnsupportedRunOperationError), (error) => {\n return new CursorUnsupportedOperationError({\n ...fields,\n sdkOperation: error.operation as RunOperation | undefined,\n });\n }),\n Match.when(Match.instanceOf(ConfigurationError), () => {\n return new CursorConfigurationError(fields);\n }),\n Match.when(Match.instanceOf(NetworkError), () => {\n return new CursorNetworkError(fields);\n }),\n Match.when(Match.instanceOf(UnknownAgentError), () => {\n return new CursorUnknownError(fields);\n }),\n Match.when(Match.instanceOf(CursorAgentError), () => {\n return new CursorUnknownError(fields);\n }),\n Match.orElse(() => {\n return new CursorUnknownError(fields);\n }),\n );\n}\n","import { Config, ConfigProvider, Effect, Option, Redacted, Schema } from \"effect\";\n\nimport type { AgentOptions, ModelSelection } from \"./cursor-types\";\n\n/**\n * Branded secret material for the Cursor API key.\n *\n * Values are held inside {@link Redacted} on {@link CursorConfig}; this schema\n * only brands the decoded plaintext type so it cannot be confused with other\n * strings at the type level.\n */\nexport const CursorApiKey = Schema.Redacted(Schema.String).pipe(Schema.brand(\"CursorApiKey\"));\nexport type CursorApiKey = typeof CursorApiKey.Type;\n\n/**\n * Branded model identifier from wrapper config.\n *\n * Populated from the `CURSOR_MODEL` environment variable when using\n * {@link loadCursorConfig}.\n */\nexport const CursorModelId = Schema.String.pipe(Schema.brand(\"CursorModelId\"));\nexport type CursorModelId = typeof CursorModelId.Type;\n\n/**\n * Branded local working directory for agent runs.\n *\n * Populated from `CURSOR_LOCAL_CWD` when using {@link loadCursorConfig}.\n */\nexport const CursorLocalCwd = Schema.String.pipe(Schema.brand(\"CursorLocalCwd\"));\nexport type CursorLocalCwd = typeof CursorLocalCwd.Type;\n\n/**\n * Minimal configuration owned by this wrapper.\n *\n * The SDK's `AgentOptions` type remains the source of truth for complete\n * runtime options. This schema models environment-derived defaults only.\n * Use {@link agentOptionsFromConfig} to merge those defaults into SDK-owned\n * {@link AgentOptions} at the SDK boundary.\n *\n * @remarks\n * **Preferred path:** Load defaults with {@link loadCursorConfig}, then call\n * `CursorAgentService` methods such as `createFromConfig` (and related helpers)\n * or merge manually with {@link agentOptionsFromConfig}. Passing plain\n * {@link AgentOptions} directly to deprecated `create` / `resume` / `prompt` /\n * `scoped` overloads may be removed in a future major version.\n *\n * @example\n * ```ts\n * const config = new CursorConfig({\n * apiKey: Redacted.make(CursorApiKey.make(process.env.CURSOR_API_KEY!)),\n * modelId: CursorModelId.make(\"composer-2\"),\n * cwd: CursorLocalCwd.make(process.cwd())\n * })\n * ```\n *\n * @see {@link cursorConfig}\n * @see {@link loadCursorConfig}\n *\n * @category config\n */\nexport class CursorConfig extends Schema.Class<CursorConfig>(\"CursorConfig\")({\n apiKey: Schema.optional(CursorApiKey),\n modelId: Schema.optional(CursorModelId),\n cwd: Schema.optional(CursorLocalCwd),\n}) {}\n\n/**\n * Effect Config descriptors for common Cursor environment variables.\n *\n * Reads `CURSOR_API_KEY`, `CURSOR_MODEL`, and `CURSOR_LOCAL_CWD` from the active\n * Effect {@link ConfigProvider.ConfigProvider}. All fields are optional so\n * callers can merge with explicit overrides via {@link agentOptionsFromConfig}.\n *\n * @example\n * ```ts\n * const config = yield* loadCursorConfig\n * const options = agentOptionsFromConfig(config)\n * ```\n *\n * @see {@link Config}\n * @see {@link loadCursorConfig}\n *\n * @category config\n */\nexport const cursorConfig = Config.all({\n apiKey: Config.redacted(\"CURSOR_API_KEY\").pipe(Config.option),\n modelId: Config.string(\"CURSOR_MODEL\").pipe(Config.option),\n cwd: Config.string(\"CURSOR_LOCAL_CWD\").pipe(Config.option),\n});\n\n/**\n * Build SDK `AgentOptions` from wrapper config and optional overrides.\n *\n * This is the adapter from typed, redacted {@link CursorConfig} to the SDK's\n * plain-string `apiKey` boundary. Prefer `CursorAgentService.createFromConfig`\n * (and related methods) over building {@link AgentOptions} by hand.\n *\n * @param config - Wrapper-owned environment defaults.\n * @param overrides - Complete or partial SDK-owned options to merge over the defaults.\n *\n * @example\n * ```ts\n * const options = agentOptionsFromConfig(config, {\n * cloud: {\n * repos: [{ url: \"https://github.com/acme/app\" }],\n * autoCreatePR: true\n * }\n * })\n * ```\n *\n * @see {@link CursorConfig}\n * @see {@link AgentOptions}\n *\n * @remarks\n * Explicit override values always win over environment-derived defaults.\n * For application code, prefer service methods that take {@link CursorConfig}\n * instead of calling this helper and then the deprecated `create` overload.\n *\n * @category config\n */\nexport const agentOptionsFromConfig = (\n config: CursorConfig,\n overrides: AgentOptions = {},\n): AgentOptions => {\n const model: ModelSelection | undefined =\n overrides.model ?? (config.modelId ? { id: config.modelId } : undefined);\n const hasNonEmptyLocalOverride =\n overrides.local !== undefined && Object.keys(overrides.local).length > 0;\n const local =\n config.cwd || hasNonEmptyLocalOverride\n ? {\n cwd: config.cwd,\n ...overrides.local,\n }\n : undefined;\n return {\n ...overrides,\n apiKey: overrides.apiKey ?? (config.apiKey ? Redacted.value(config.apiKey) : undefined),\n model,\n local,\n };\n};\n\n/**\n * Load environment-derived defaults as a schema-backed value.\n * It uses ConfigProvider to load the environment variables\n * with their default names (`CURSOR_API_KEY`, `CURSOR_MODEL`, `CURSOR_LOCAL_CWD`)\n * from {@link cursorConfig}.\n * Omitting `CURSOR_API_KEY` only means no default API-key-based auth will be\n * set; callers can still provide credentials via {@link agentOptionsFromConfig}\n * overrides or the `*FromConfig` service helpers.\n *\n * If the API key is not set, it will log a warning message.\n *\n * **NOTE**: omitting the API key will cause an unauthenticated error\n * in subsequent calls to the Cursor SDK API.\n *\n * @example\n * ```ts\n * const config = yield* loadCursorConfig\n * const options = agentOptionsFromConfig(config, { local: { cwd: process.cwd() } })\n * // Or use CursorAgentService.createFromConfig(config, { local: { cwd: process.cwd() } })\n * ```\n *\n * To change the way that the environment variables are loaded,\n * you can do it with Effect by providing a custom ConfigProvider.\n *\n * ```ts\n * // For example: load via custom environment object\n * const config = yield* loadCursorConfig.pipe(\n * Effect.provideService(\n * ConfigProvider.ConfigProvider,\n * ConfigProvider.fromEnv({\n * env: {\n * CURSOR_API_KEY: \"crsr_******\",\n * CURSOR_MODEL: \"composer-2\",\n * CURSOR_LOCAL_CWD: \"/workspace\",\n * },\n * }),\n * ),\n * )\n * ```\n *\n * @see {@link cursorConfig}\n * @see {@link agentOptionsFromConfig}\n *\n * @remarks\n * This effect is the preferred entry for redacted environment defaults.\n * Pair it with {@link agentOptionsFromConfig} or `CursorAgentService` helpers\n * such as `createFromConfig`.\n *\n * @category config\n */\nexport const loadCursorConfig = Effect.gen(function* () {\n const provider = yield* ConfigProvider.ConfigProvider;\n const raw = yield* cursorConfig.parse(provider);\n const apiKey = Option.getOrUndefined(raw.apiKey);\n if (apiKey === undefined || apiKey === null) {\n yield* Effect.logWarning(\n \"CURSOR_API_KEY is not set — this will cause an unauthenticated error in subsequent calls to the Cursor SDK API.\",\n );\n }\n\n const modelId = Option.getOrUndefined(raw.modelId);\n const cwd = Option.getOrUndefined(raw.cwd);\n return new CursorConfig({\n apiKey: apiKey ? CursorApiKey.make(apiKey) : undefined,\n modelId: modelId !== undefined ? CursorModelId.make(modelId) : undefined,\n cwd: cwd !== undefined ? CursorLocalCwd.make(cwd) : undefined,\n });\n});\n","import { Agent, Cursor } from \"@cursor/sdk\";\nimport { Context, Layer } from \"effect\";\n\nimport type {\n AgentMessage,\n AgentOperationOptions,\n AgentOptions,\n CursorRequestOptions,\n GetAgentMessagesOptions,\n GetAgentOptions,\n GetRunOptions,\n ListAgentsOptions,\n ListResult,\n ListRunsOptions,\n Run,\n RunResult,\n SDKAgent,\n SDKAgentInfo,\n SDKModel,\n SDKRepository,\n SDKUser,\n} from \"./cursor-types\";\n\n/* oxlint-disable eslint/no-unused-vars -- type-only imports anchor TSDoc `{@link …}`; not referenced in code */\nimport type { CursorAgentService } from \"./cursor-agent\";\nimport type { CursorArtifactService } from \"./cursor-artifacts\";\nimport type { CursorInspectionService } from \"./cursor-inspection\";\nimport type { CursorRunService } from \"./cursor-run\";\n/* oxlint-enable eslint/no-unused-vars */\n\n/**\n * Thin boundary around the static `@cursor/sdk` APIs.\n *\n * Most application code should use {@link CursorAgentService},\n * {@link CursorRunService}, {@link CursorArtifactService}, and\n * {@link CursorInspectionService}. This factory exists so live code, tests, and\n * user applications can replace SDK construction and static calls without\n * monkey-patching imports.\n *\n * So in one line: you probably won't need this.\n *\n * @example\n * ```ts\n * import { CursorSdkFactory, CursorAgentService } from \"effect-cursor-sdk\"\n * import { Layer } from \"effect\"\n *\n * const TestSdk = Layer.succeed(CursorSdkFactory)(\n * CursorSdkFactory.of({\n * create: () => mockAgent,\n * // implement the remaining factory methods for your test\n * })\n * )\n * ```\n *\n * @see {@link CursorAgentService} for creating, resuming, sending, and disposing agents.\n * @see {@link CursorRunService} for wrapping `Run` handles.\n * @see {@link CursorInspectionService} for static agent and account APIs.\n * @see {@link CursorArtifactService} for artifact APIs on an SDK agent.\n *\n * @remarks\n * **Deprecated for application code:** `create`, `resume`, and `prompt` accept\n * raw {@link AgentOptions} (including a plain `apiKey` string). Prefer\n * {@link CursorAgentService} with `loadCursorConfig` and `createFromConfig` /\n * `resumeFromConfig` / `promptFromConfig` from this package instead.\n * This factory remains the low-level adapter for tests and advanced overrides.\n *\n * @category services\n */\nexport interface CursorSdkFactoryShape {\n /**\n * @deprecated Prefer {@link CursorAgentService} with config-based helpers.\n * Low-level adapter to `Agent.create`.\n */\n readonly create: (options: AgentOptions) => Promise<SDKAgent>;\n /**\n * @deprecated Prefer {@link CursorAgentService} with config-based helpers.\n * Low-level adapter to `Agent.resume`.\n */\n readonly resume: (agentId: string, options?: Partial<AgentOptions>) => Promise<SDKAgent>;\n /**\n * @deprecated Prefer {@link CursorAgentService} with config-based helpers.\n * Low-level adapter to `Agent.prompt`.\n */\n readonly prompt: (message: string, options?: AgentOptions) => Promise<RunResult>;\n readonly listAgents: (options?: ListAgentsOptions) => Promise<ListResult<SDKAgentInfo>>;\n readonly listRuns: (agentId: string, options?: ListRunsOptions) => Promise<ListResult<Run>>;\n readonly getRun: (runId: string, options?: GetRunOptions) => Promise<Run>;\n readonly getAgent: (agentId: string, options?: GetAgentOptions) => Promise<SDKAgentInfo>;\n readonly archiveAgent: (agentId: string, options?: AgentOperationOptions) => Promise<void>;\n readonly unarchiveAgent: (agentId: string, options?: AgentOperationOptions) => Promise<void>;\n readonly deleteAgent: (agentId: string, options?: AgentOperationOptions) => Promise<void>;\n readonly listMessages: (\n agentId: string,\n options?: GetAgentMessagesOptions,\n ) => Promise<AgentMessage[]>;\n readonly me: (options?: CursorRequestOptions) => Promise<SDKUser>;\n readonly listModels: (options?: CursorRequestOptions) => Promise<SDKModel[]>;\n readonly listRepositories: (options?: CursorRequestOptions) => Promise<SDKRepository[]>;\n}\n\n/**\n * Context service that provides the live `@cursor/sdk` static API boundary.\n *\n * Use {@link CursorSdkFactory.Live} in production layers and override the\n * service in tests with {@link makeMockSdkFactoryLayer} or a custom layer.\n *\n * @example\n * ```ts\n * import { CursorSdkFactory, agentOptionsFromConfig, loadCursorConfig } from \"effect-cursor-sdk\"\n * import { Effect } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const sdk = yield* CursorSdkFactory\n * const config = yield* loadCursorConfig\n * return sdk.create(agentOptionsFromConfig(config, { model: { id: \"composer-2\" } }))\n * })\n * ```\n *\n * @see {@link CursorSdkFactoryShape}\n * @see {@link liveLayer}\n * @category services\n */\nexport class CursorSdkFactory extends Context.Service<CursorSdkFactory, CursorSdkFactoryShape>()(\n \"effect-cursor-sdk/cursor-sdk-factory/CursorSdkFactory\",\n) {\n static readonly Live = Layer.succeed(CursorSdkFactory)(\n CursorSdkFactory.of({\n create: (options: AgentOptions): Promise<SDKAgent> => {\n return Agent.create(options);\n },\n resume: (agentId: string, options?: Partial<AgentOptions>): Promise<SDKAgent> => {\n return Agent.resume(agentId, options);\n },\n prompt: (message: string, options?: AgentOptions): Promise<RunResult> => {\n return Agent.prompt(message, options);\n },\n listAgents: (options?: ListAgentsOptions): Promise<ListResult<SDKAgentInfo>> => {\n return Agent.list(options);\n },\n listRuns: (agentId: string, options?: ListRunsOptions): Promise<ListResult<Run>> => {\n return Agent.listRuns(agentId, options);\n },\n getRun: (runId: string, options?: GetRunOptions): Promise<Run> => {\n return Agent.getRun(runId, options);\n },\n getAgent: (agentId: string, options?: GetAgentOptions): Promise<SDKAgentInfo> => {\n return Agent.get(agentId, options);\n },\n archiveAgent: (agentId: string, options?: AgentOperationOptions): Promise<void> => {\n return Agent.archive(agentId, options);\n },\n unarchiveAgent: (agentId: string, options?: AgentOperationOptions): Promise<void> => {\n return Agent.unarchive(agentId, options);\n },\n deleteAgent: (agentId: string, options?: AgentOperationOptions): Promise<void> => {\n return Agent.delete(agentId, options);\n },\n listMessages: (agentId: string, options?: GetAgentMessagesOptions) => {\n return Agent.messages.list(agentId, options);\n },\n me: (options?: CursorRequestOptions): Promise<SDKUser> => {\n return Cursor.me(options);\n },\n listModels: (options?: CursorRequestOptions): Promise<SDKModel[]> => {\n return Cursor.models.list(options);\n },\n listRepositories: (options?: CursorRequestOptions): Promise<SDKRepository[]> => {\n return Cursor.repositories.list(options);\n },\n }),\n );\n}\n","/**\n * Telemetry helpers for the Effect Cursor SDK boundary.\n *\n * Services wrap SDK calls with {@link instrument}, which records Effect metrics\n * and opens an OpenTelemetry-style span per {@link CursorOperation}. Named\n * `Metric.counter` values are exported so applications can wire them into a\n * metrics backend via Effect's metrics layer.\n *\n * {@link redact} is a small helper for scrubbing structured metadata before it\n * leaves a trust boundary (for example log attributes or debug payloads).\n *\n * @see {@link CursorOperation}\n * @see {@link CursorAgentService}\n * @see {@link CursorRunService}\n * @see {@link CursorInspectionService}\n * @see {@link CursorArtifactService}\n *\n * @module\n */\n\nimport { Effect, Metric } from \"effect\";\n\nimport type { CursorOperation } from \"./cursor-error\";\n\n/**\n * Increments once when an instrumented SDK effect **starts** execution.\n *\n * Bound to the metric key `cursor_operations_started`. Used by\n * {@link instrument} on every wrapped call; pair with\n * {@link cursorOperationsFailed} to compute failure rates per operation when\n * both counters are exported to your metrics stack.\n *\n * @see {@link instrument}\n * @see {@link cursorOperationsFailed}\n *\n * @category telemetry\n */\nexport const cursorOperationsStarted = Metric.counter(\"cursor_operations_started\");\n\n/**\n * Increments once when an instrumented SDK effect **fails** (any error channel\n * value), after {@link cursorOperationsStarted} has already been recorded for\n * that run.\n *\n * Bound to the metric key `cursor_operations_failed`. Failures are tracked in\n * `Effect.tapError` so the effect still fails with the original error; this\n * counter is observability-only.\n *\n * @see {@link instrument}\n * @see {@link cursorOperationsStarted}\n *\n * @category telemetry\n */\nexport const cursorOperationsFailed = Metric.counter(\"cursor_operations_failed\");\n\n/**\n * Counter reserved for **per-message** or **per-chunk** stream throughput.\n *\n * Bound to the metric key `cursor_stream_events`. The service wrappers do not\n * attach this metric automatically to {@link CursorRunService.streamEvents};\n * export it from your app if you want to `Metric.track` inside a\n * `Stream.tapEffect` (or similar) when consuming SDK stream payloads.\n *\n * @see {@link CursorRunService}\n *\n * @category telemetry\n */\nexport const cursorStreamEvents = Metric.counter(\"cursor_stream_events\");\n\n/** String substituted for values under sensitive-looking keys. */\nconst REDACTED_MARKER = \"[redacted]\";\n\n/** Replaces non-plain objects (for example `Date`, `Map`) so they are not mistaken for empty `{}`. */\nconst OPAQUE_MARKER = \"[opaque]\";\n\n/** Replaces a value when the same object appears on the recursion stack (true cycles only). */\nconst CIRCULAR_MARKER = \"[circular]\";\n\n/** Replaces nested values when recursion depth exceeds this limit (prevents stack overflow). */\nconst MAX_REDACT_DEPTH = 64;\n\nconst isPlainObject = (value: object): boolean => {\n const proto = Object.getPrototypeOf(value);\n return proto === null || proto === Object.prototype;\n};\n\n/**\n * Lower-cased key substring / equality checks. Substrings such as `key` also\n * match `apiKey` (and unfortunately unrelated keys like `monkey`); that is an\n * intentional tradeoff for simple log scrubbing.\n */\nconst isSensitiveKeyName = (normalized: string): boolean => {\n if (normalized === \"authorization\" || normalized === \"data\") return true;\n return (\n normalized.includes(\"key\") ||\n normalized.includes(\"token\") ||\n normalized.includes(\"secret\") ||\n normalized.includes(\"password\") ||\n normalized.includes(\"passwd\") ||\n normalized.includes(\"credential\") ||\n normalized.includes(\"cookie\") ||\n normalized.includes(\"jwt\") ||\n normalized.includes(\"bearer\")\n );\n};\n\nconst redactInner = (value: unknown, path: Set<object>, depth: number): unknown => {\n if (depth > MAX_REDACT_DEPTH) {\n return OPAQUE_MARKER;\n }\n\n if (Array.isArray(value)) {\n if (path.has(value)) {\n return CIRCULAR_MARKER;\n }\n path.add(value);\n const out = value.map((item) => {\n return redactInner(item, path, depth + 1);\n });\n path.delete(value);\n return out;\n }\n\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n\n if (!isPlainObject(value)) {\n return OPAQUE_MARKER;\n }\n\n if (path.has(value)) {\n return CIRCULAR_MARKER;\n }\n\n path.add(value);\n const out = Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([key, item]) => {\n const normalized = key.toLowerCase();\n if (isSensitiveKeyName(normalized)) {\n return [key, REDACTED_MARKER];\n }\n return [key, redactInner(item, path, depth + 1)];\n }),\n );\n path.delete(value);\n return out;\n};\n\n/**\n * Deep-clones **plain** objects and arrays while replacing values under keys that\n * often carry secrets, bearer material, or large opaque blobs (for example API\n * keys, tokens, passwords, cookies, `Authorization`, or a generic `data` field).\n *\n * Matching is **substring-based on the lower-cased key name** (for example\n * `apiKey`, `CURSOR_API_TOKEN`, `client_secret`, `setCookie` all match). Primitives\n * and `null` pass through unchanged. Non-plain objects (for example `Date`, `Map`,\n * class instances) are replaced by `\"[opaque]\"` so they are not serialized as empty\n * objects. True circular references in the input are replaced by `\"[circular]\"`.\n * Recursion deeper than 64 levels falls back to `\"[opaque]\"` for the overflow branch.\n *\n * This is a best-effort redactor for logs and attributes—not a cryptographic\n * guarantee; do not rely on it for compliance redaction without review.\n *\n * @param value - Arbitrary JSON-like value to sanitize.\n * @returns A structure of the same shape with sensitive-looking entries replaced\n * by the string `\"[redacted]\"`.\n *\n * @example\n * ```ts\n * redact({ apiKey: \"secret\", nested: { token: \"x\" }, safe: 1 })\n * // => { apiKey: \"[redacted]\", nested: { token: \"[redacted]\" }, safe: 1 }\n * ```\n *\n * @category telemetry\n */\nexport const redact = (value: unknown): unknown => {\n return redactInner(value, new Set(), 0);\n};\n\n/**\n * Wraps an SDK-backed {@link Effect} with consistent\n * observability: increments {@link cursorOperationsStarted} at execution start,\n * increments {@link cursorOperationsFailed} on the error channel, and attaches\n * a span named `cursor.<operation>` (for example `cursor.agent.list`).\n *\n * The span name is stable and includes the {@link CursorOperation} tag space\n * so traces can be filtered consistently across agent, run, artifact, and\n * inspection APIs.\n *\n * @param operation - Logical SDK operation; must match {@link CursorOperation}\n * for typed error mapping and trace taxonomy.\n * @param effect - The effect produced by `Effect.tryPromise` (or similar)\n * around a single SDK call.\n * @returns The same effect type `Effect<A, E, R>` with metrics and span\n * attached; success and failure values are unchanged.\n *\n * @example\n * ```ts\n * import { Effect } from \"effect\"\n * import { instrument } from \"./cursor-telemetry\"\n *\n * const eff = instrument(\n * \"agent.get\",\n * Effect.tryPromise({\n * try: () => sdk.getAgent(id),\n * catch: (e) => e,\n * }),\n * )\n * ```\n *\n * @see {@link cursorOperationsStarted}\n * @see {@link cursorOperationsFailed}\n * @see {@link CursorOperation}\n *\n * @category telemetry\n */\nexport const instrument = <A, E, R>(\n operation: CursorOperation,\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<A, E, R> => {\n return effect.pipe(\n Effect.track(cursorOperationsStarted.pipe(Metric.withConstantInput(1))),\n Effect.tapError(() => {\n return Effect.track(Effect.void, cursorOperationsFailed.pipe(Metric.withConstantInput(1)));\n }),\n Effect.withSpan(`cursor.${operation}`),\n );\n};\n","import { Context, Effect, Layer, type Scope } from \"effect\";\n\nimport {\n CursorAuthenticationError,\n CursorConfigurationError,\n CursorIntegrationNotConnectedError,\n CursorNetworkError,\n CursorRateLimitError,\n CursorUnknownError,\n mapCursorError,\n} from \"./cursor-error\";\nimport { agentOptionsFromConfig, type CursorConfig } from \"./cursor-config\";\nimport { CursorSdkFactory } from \"./cursor-sdk-factory\";\nimport { instrument } from \"./cursor-telemetry\";\nimport type {\n AgentOptions,\n Run,\n RunResult,\n SDKAgent,\n SDKUserMessage,\n SendOptions,\n} from \"./cursor-types\";\n\n/**\n * Agent lifecycle surface backed by the Cursor SDK.\n *\n * @remarks\n * Prefer {@link loadCursorConfig} with {@link CursorAgentServiceShape.createFromConfig},\n * {@link CursorAgentServiceShape.resumeFromConfig},\n * {@link CursorAgentServiceShape.promptFromConfig}, and\n * {@link CursorAgentServiceShape.scopedFromConfig}\n * so secrets stay in `Redacted` form until {@link agentOptionsFromConfig}\n * merges into SDK {@link AgentOptions}. Plain {@link AgentOptions} entry points\n * are deprecated; see `DEPRECATIONS.md` and the README at the package root.\n */\nexport interface CursorAgentServiceShape {\n /**\n * @deprecated Prefer {@link CursorAgentServiceShape.createFromConfig} with {@link loadCursorConfig}\n * instead of raw {@link AgentOptions} (including a plain `apiKey` string). Next major: `createFromConfig`\n * is planned to become `create` with the same parameters.\n */\n readonly create: (\n options: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * Create an agent from {@link CursorConfig} and optional SDK overrides.\n *\n * @remarks\n * Next major: planned rename to `create` with the same signature once plain-`AgentOptions` entry points are removed.\n *\n * @see {@link loadCursorConfig}\n * @see {@link agentOptionsFromConfig}\n */\n readonly createFromConfig: (\n config: CursorConfig,\n overrides?: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * @deprecated Prefer {@link CursorAgentServiceShape.resumeFromConfig} with {@link loadCursorConfig}\n * instead of raw {@link AgentOptions}. Next major: `resumeFromConfig` is planned to become `resume` with the same parameters.\n */\n readonly resume: (\n agentId: string,\n options?: Partial<AgentOptions>,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * Resume an agent from {@link CursorConfig} and optional SDK overrides.\n *\n * @remarks\n * Next major: planned rename to `resume` with the same signature once plain-`AgentOptions` entry points are removed.\n *\n * @see {@link loadCursorConfig}\n * @see {@link agentOptionsFromConfig}\n */\n readonly resumeFromConfig: (\n agentId: string,\n config: CursorConfig,\n overrides?: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * @deprecated Prefer {@link CursorAgentServiceShape.promptFromConfig} with {@link loadCursorConfig}\n * instead of raw {@link AgentOptions}. Next major: `promptFromConfig` is planned to become `prompt` with the same parameters.\n */\n readonly prompt: (\n message: string,\n options?: AgentOptions,\n ) => Effect.Effect<\n RunResult,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * One-shot prompt from {@link CursorConfig} and optional SDK overrides.\n *\n * @remarks\n * Next major: planned rename to `prompt` with the same signature once plain-`AgentOptions` entry points are removed.\n *\n * @see {@link loadCursorConfig}\n * @see {@link agentOptionsFromConfig}\n */\n readonly promptFromConfig: (\n message: string,\n config: CursorConfig,\n overrides?: AgentOptions,\n ) => Effect.Effect<\n RunResult,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly send: (\n agent: SDKAgent,\n message: string | SDKUserMessage,\n options?: SendOptions,\n ) => Effect.Effect<\n Run,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly reload: (\n agent: SDKAgent,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly close: (agent: SDKAgent) => Effect.Effect<void>;\n readonly dispose: (\n agent: SDKAgent,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * @deprecated Prefer {@link CursorAgentServiceShape.scopedFromConfig} with {@link loadCursorConfig}\n * instead of raw {@link AgentOptions}. Next major: `scopedFromConfig` is planned to become `scoped` with the same parameters.\n */\n readonly scoped: (\n options: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError,\n Scope.Scope\n >;\n /**\n * Acquire an agent in a scope from {@link CursorConfig} and optional SDK overrides.\n *\n * @remarks\n * Next major: planned rename to `scoped` with the same signature once plain-`AgentOptions` entry points are removed.\n *\n * @see {@link loadCursorConfig}\n * @see {@link agentOptionsFromConfig}\n */\n readonly scopedFromConfig: (\n config: CursorConfig,\n overrides?: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError,\n Scope.Scope\n >;\n}\n\n/**\n * Effect-native agent lifecycle and prompt service.\n *\n * The service wraps `Agent.create`, `Agent.resume`, `Agent.prompt`, and\n * instance lifecycle methods while preserving SDK-owned option and result\n * types.\n *\n * @example\n * ```ts\n * import { CursorAgentService, liveLayer, loadCursorConfig } from \"effect-cursor-sdk\"\n * import { Effect } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const agents = yield* CursorAgentService\n * const config = yield* loadCursorConfig\n * const agent = yield* agents.createFromConfig(config, {\n * model: { id: \"composer-2\" },\n * local: { cwd: process.cwd() },\n * })\n * return yield* agents.send(agent, \"Summarize this repository\")\n * }).pipe(Effect.provide(liveLayer))\n * ```\n *\n * @see {@link CursorRunService} for operations on returned `Run` handles.\n * @see {@link CursorSdkFactory} for replacing SDK construction in tests.\n *\n * @remarks\n * Prefer {@link CursorAgentServiceShape.createFromConfig} and related methods\n * with {@link loadCursorConfig}; raw {@link AgentOptions} on\n * {@link CursorAgentServiceShape.create} and siblings are deprecated.\n * See `DEPRECATIONS.md` at the package root for migration and planned next-major renames\n * (`createFromConfig` → `create`, etc.).\n *\n * @category services\n */\nexport class CursorAgentService extends Context.Service<\n CursorAgentService,\n CursorAgentServiceShape\n>()(\"effect-cursor-sdk/cursor-agent/CursorAgentService\") {\n static readonly Live = Layer.effect(CursorAgentService)(\n Effect.gen(function* () {\n const sdk = yield* CursorSdkFactory;\n\n const create = (options: AgentOptions) => {\n return instrument(\n \"agent.create\",\n Effect.tryPromise({\n try: () => sdk.create(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.create\" });\n },\n }),\n );\n };\n\n const resume = (agentId: string, options?: Partial<AgentOptions>) => {\n return instrument(\n \"agent.resume\",\n Effect.tryPromise({\n try: () => sdk.resume(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.resume\", agentId });\n },\n }),\n );\n };\n\n const prompt = (message: string, options?: AgentOptions) => {\n return instrument(\n \"agent.prompt\",\n Effect.tryPromise({\n try: () => sdk.prompt(message, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.prompt\" });\n },\n }),\n );\n };\n\n const send = (agent: SDKAgent, message: string | SDKUserMessage, options?: SendOptions) => {\n return instrument(\n \"agent.send\",\n Effect.tryPromise({\n try: () => agent.send(message, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.send\", agentId: agent.agentId });\n },\n }),\n );\n };\n\n const reload = (agent: SDKAgent) => {\n return instrument(\n \"agent.reload\",\n Effect.tryPromise({\n try: () => agent.reload(),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.reload\", agentId: agent.agentId });\n },\n }),\n );\n };\n\n const close = (agent: SDKAgent): Effect.Effect<void> => {\n return instrument(\n \"agent.close\",\n Effect.sync(() => agent.close()),\n );\n };\n\n const dispose = (agent: SDKAgent) => {\n return instrument(\n \"agent.dispose\",\n Effect.tryPromise({\n try: () => agent[Symbol.asyncDispose](),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.dispose\", agentId: agent.agentId });\n },\n }),\n );\n };\n\n const scoped = (options: AgentOptions) => {\n return Effect.acquireRelease(create(options), (agent) => {\n return Effect.ignore(dispose(agent));\n });\n };\n\n const createFromConfig = (config: CursorConfig, overrides: AgentOptions = {}) => {\n return create(agentOptionsFromConfig(config, overrides));\n };\n\n const resumeFromConfig = (\n agentId: string,\n config: CursorConfig,\n overrides: AgentOptions = {},\n ) => {\n return resume(agentId, agentOptionsFromConfig(config, overrides));\n };\n\n const promptFromConfig = (\n message: string,\n config: CursorConfig,\n overrides: AgentOptions = {},\n ) => {\n return prompt(message, agentOptionsFromConfig(config, overrides));\n };\n\n const scopedFromConfig = (config: CursorConfig, overrides: AgentOptions = {}) => {\n return scoped(agentOptionsFromConfig(config, overrides));\n };\n\n return {\n create,\n createFromConfig,\n resume,\n resumeFromConfig,\n prompt,\n promptFromConfig,\n send,\n reload,\n close,\n dispose,\n scoped,\n scopedFromConfig,\n } as const;\n }),\n );\n}\n","import { Context, Effect, Layer } from \"effect\";\n\nimport {\n CursorAuthenticationError,\n CursorConfigurationError,\n CursorIntegrationNotConnectedError,\n CursorNetworkError,\n CursorRateLimitError,\n CursorUnknownError,\n mapCursorError,\n} from \"./cursor-error\";\nimport { instrument } from \"./cursor-telemetry\";\nimport type { SDKAgent, SDKArtifact } from \"./cursor-types\";\n\nexport interface CursorArtifactServiceShape {\n readonly listArtifacts: (\n agent: SDKAgent,\n ) => Effect.Effect<\n SDKArtifact[],\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly downloadArtifact: (\n agent: SDKAgent,\n path: string,\n ) => Effect.Effect<\n Buffer,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n}\n\n/**\n * Effect-native wrappers for agent artifacts.\n *\n * @example\n * ```ts\n * const artifacts = yield* CursorArtifactService\n * const items = yield* artifacts.listArtifacts(agent)\n * const bytes = yield* artifacts.downloadArtifact(agent, items[0]!.path)\n * ```\n *\n * @see {@link SDKArtifact}\n *\n * @category services\n */\nexport class CursorArtifactService extends Context.Service<\n CursorArtifactService,\n CursorArtifactServiceShape\n>()(\"effect-cursor-sdk/cursor-artifacts/CursorArtifactService\") {\n static readonly Live = Layer.succeed(CursorArtifactService)(\n CursorArtifactService.of({\n listArtifacts: (agent: SDKAgent) => {\n return instrument(\n \"artifacts.list\",\n Effect.tryPromise({\n try: () => agent.listArtifacts(),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"artifacts.list\", agentId: agent.agentId });\n },\n }),\n );\n },\n downloadArtifact: (agent: SDKAgent, path: string) => {\n return instrument(\n \"artifacts.download\",\n Effect.tryPromise({\n try: () => agent.downloadArtifact(path),\n catch: (cause) => {\n return mapCursorError(cause, {\n operation: \"artifacts.download\",\n agentId: agent.agentId,\n });\n },\n }),\n );\n },\n }),\n );\n}\n","import { Context, Effect, Layer } from \"effect\";\n\nimport {\n CursorAuthenticationError,\n CursorConfigurationError,\n CursorIntegrationNotConnectedError,\n CursorNetworkError,\n CursorRateLimitError,\n CursorUnknownError,\n mapCursorError,\n} from \"./cursor-error\";\nimport { CursorSdkFactory } from \"./cursor-sdk-factory\";\nimport { instrument } from \"./cursor-telemetry\";\nimport type {\n AgentMessage,\n AgentOperationOptions,\n CursorRequestOptions,\n GetAgentMessagesOptions,\n GetAgentOptions,\n GetRunOptions,\n ListAgentsOptions,\n ListResult,\n ListRunsOptions,\n Run,\n SDKAgentInfo,\n SDKModel,\n SDKRepository,\n SDKUser,\n} from \"./cursor-types\";\n\nexport interface CursorInspectionServiceShape {\n readonly listAgents: (\n options?: ListAgentsOptions,\n ) => Effect.Effect<\n ListResult<SDKAgentInfo>,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly getAgent: (\n agentId: string,\n options?: GetAgentOptions,\n ) => Effect.Effect<\n SDKAgentInfo,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly archiveAgent: (\n agentId: string,\n options?: AgentOperationOptions,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly unarchiveAgent: (\n agentId: string,\n options?: AgentOperationOptions,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly deleteAgent: (\n agentId: string,\n options?: AgentOperationOptions,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly listRuns: (\n agentId: string,\n options?: ListRunsOptions,\n ) => Effect.Effect<\n ListResult<Run>,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly getRun: (\n runId: string,\n options?: GetRunOptions,\n ) => Effect.Effect<\n Run,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly listMessages: (\n agentId: string,\n options?: GetAgentMessagesOptions,\n ) => Effect.Effect<\n AgentMessage[],\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly me: (\n options?: CursorRequestOptions,\n ) => Effect.Effect<\n SDKUser,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly listModels: (\n options?: CursorRequestOptions,\n ) => Effect.Effect<\n SDKModel[],\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly listRepositories: (\n options?: CursorRequestOptions,\n ) => Effect.Effect<\n SDKRepository[],\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n}\n\n/**\n * Effect-native wrappers for SDK inspection, lifecycle, and account catalog APIs.\n *\n * @example\n * ```ts\n * const inspection = yield* CursorInspectionService\n * const agents = yield* inspection.listAgents({ runtime: \"cloud\", includeArchived: true })\n * const models = yield* inspection.listModels()\n * ```\n *\n * @see {@link CursorSdkFactory}\n * @see {@link SDKAgentInfo}\n *\n * @category services\n */\nexport class CursorInspectionService extends Context.Service<\n CursorInspectionService,\n CursorInspectionServiceShape\n>()(\"effect-cursor-sdk/cursor-inspection/CursorInspectionService\") {\n static readonly Live = Layer.effect(CursorInspectionService)(\n Effect.gen(function* () {\n const sdk = yield* CursorSdkFactory;\n return {\n listAgents: (options?: ListAgentsOptions) => {\n return instrument(\n \"agent.list\",\n Effect.tryPromise({\n try: () => sdk.listAgents(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.list\" });\n },\n }),\n );\n },\n getAgent: (agentId: string, options?: GetAgentOptions) => {\n return instrument(\n \"agent.get\",\n Effect.tryPromise({\n try: () => sdk.getAgent(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.get\", agentId });\n },\n }),\n );\n },\n archiveAgent: (agentId: string, options?: AgentOperationOptions) => {\n return instrument(\n \"agent.archive\",\n Effect.tryPromise({\n try: () => sdk.archiveAgent(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.archive\", agentId });\n },\n }),\n );\n },\n unarchiveAgent: (agentId: string, options?: AgentOperationOptions) => {\n return instrument(\n \"agent.unarchive\",\n Effect.tryPromise({\n try: () => sdk.unarchiveAgent(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.unarchive\", agentId });\n },\n }),\n );\n },\n deleteAgent: (agentId: string, options?: AgentOperationOptions) => {\n return instrument(\n \"agent.delete\",\n Effect.tryPromise({\n try: () => sdk.deleteAgent(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.delete\", agentId });\n },\n }),\n );\n },\n listRuns: (agentId: string, options?: ListRunsOptions) => {\n return instrument(\n \"run.list\",\n Effect.tryPromise({\n try: () => sdk.listRuns(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"run.list\", agentId });\n },\n }),\n );\n },\n getRun: (runId: string, options?: GetRunOptions) => {\n return instrument(\n \"run.get\",\n Effect.tryPromise({\n try: () => sdk.getRun(runId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"run.get\", runId });\n },\n }),\n );\n },\n listMessages: (agentId: string, options?: GetAgentMessagesOptions) => {\n return instrument(\n \"messages.list\",\n Effect.tryPromise({\n try: () => sdk.listMessages(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"messages.list\", agentId });\n },\n }),\n );\n },\n me: (options?: CursorRequestOptions) => {\n return instrument(\n \"cursor.me\",\n Effect.tryPromise({\n try: () => sdk.me(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"cursor.me\" });\n },\n }),\n );\n },\n listModels: (options?: CursorRequestOptions) => {\n return instrument(\n \"cursor.models.list\",\n Effect.tryPromise({\n try: () => sdk.listModels(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"cursor.models.list\" });\n },\n }),\n );\n },\n listRepositories: (options?: CursorRequestOptions) => {\n return instrument(\n \"cursor.repositories.list\",\n Effect.tryPromise({\n try: () => sdk.listRepositories(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"cursor.repositories.list\" });\n },\n }),\n );\n },\n } as const;\n }),\n );\n}\n","import { Layer } from \"effect\";\n\nimport { CursorSdkFactory } from \"./cursor-sdk-factory\";\nimport type {\n AgentMessage,\n AgentOperationOptions,\n AgentOptions,\n CursorRequestOptions,\n GetAgentMessagesOptions,\n GetAgentOptions,\n GetRunOptions,\n ListAgentsOptions,\n ListResult,\n ListRunsOptions,\n Run,\n RunOperation,\n RunResult,\n RunStatus,\n SDKAgent,\n SDKAgentInfo,\n SDKArtifact,\n SDKMessage,\n SDKModel,\n SDKRepository,\n SDKUser,\n SDKUserMessage,\n SendOptions,\n} from \"./cursor-types\";\n\n/**\n * Fixture data used by the deterministic mock SDK layer.\n *\n * @example\n * ```ts\n * const fixtures: CursorMockFixtures = {\n * stream: [assistantEvent],\n * result: { id: \"run-1\", status: \"finished\", result: \"Done\" }\n * }\n * ```\n *\n * @see {@link mockLayer}\n * @see {@link makeMockSdkFactoryLayer}\n * @category testing\n */\nexport type CursorMockFactoryMethod =\n | \"create\"\n | \"resume\"\n | \"prompt\"\n | \"listAgents\"\n | \"listRuns\"\n | \"getRun\"\n | \"getAgent\"\n | \"archiveAgent\"\n | \"unarchiveAgent\"\n | \"deleteAgent\"\n | \"listMessages\"\n | \"me\"\n | \"listModels\"\n | \"listRepositories\";\n\nexport interface CursorMockFixtures {\n readonly agentId?: string;\n readonly runId?: string;\n readonly stream?: ReadonlyArray<SDKMessage>;\n readonly result?: RunResult;\n readonly artifacts?: ReadonlyArray<SDKArtifact>;\n readonly artifactData?: Buffer;\n readonly agents?: ReadonlyArray<SDKAgentInfo>;\n readonly messages?: ReadonlyArray<AgentMessage>;\n readonly models?: ReadonlyArray<SDKModel>;\n readonly repositories?: ReadonlyArray<SDKRepository>;\n readonly user?: SDKUser;\n /**\n * Per-`send` merged fixtures. Each `MockCursorAgent.send` increments the index;\n * when exhausted, further sends reuse the last entry merged with the base fixtures.\n */\n readonly sendSequence?: ReadonlyArray<Partial<CursorMockFixtures>>;\n /**\n * Reject a factory method with this error (Promise rejection).\n */\n readonly factoryErrors?: Partial<Record<CursorMockFactoryMethod, unknown>>;\n /** Override {@link Run.supports} per operation. */\n readonly runSupports?: Partial<Record<RunOperation, boolean>>;\n /** Override unsupported reasons for operations marked false in {@link runSupports}. */\n readonly runUnsupportedReason?: Partial<Record<RunOperation, string>>;\n}\n\n/**\n * Deterministic SDK `Run` implementation for tests.\n *\n * @param streamEvents - Events yielded by {@link MockCursorRun.stream}.\n * @param waitResult - Result returned by {@link MockCursorRun.wait}.\n *\n * @example\n * ```ts\n * const run = new MockCursorRun([assistantEvent], {\n * id: \"run-1\",\n * status: \"finished\",\n * result: \"Done\"\n * })\n * ```\n *\n * @see {@link makeMockRun}\n * @category testing\n */\nexport class MockCursorRun implements Run {\n readonly id: string;\n readonly agentId: string;\n readonly createdAt = Date.now();\n #status: RunStatus;\n #listeners = new Set<(status: RunStatus) => void>();\n\n constructor(\n readonly streamEvents: ReadonlyArray<SDKMessage>,\n readonly waitResult: RunResult,\n readonly behavior?: {\n readonly supports?: Partial<Record<RunOperation, boolean>>;\n readonly unsupportedReason?: Partial<Record<RunOperation, string>>;\n },\n ) {\n this.id = waitResult.id;\n this.agentId = streamEvents[0]?.agent_id ?? \"mock-agent\";\n this.#status = waitResult.status;\n }\n\n get status(): RunStatus {\n return this.#status;\n }\n get result(): string | undefined {\n return this.waitResult.result;\n }\n get model(): RunResult[\"model\"] {\n return this.waitResult.model;\n }\n get durationMs(): number | undefined {\n return this.waitResult.durationMs;\n }\n get git(): RunResult[\"git\"] {\n return this.waitResult.git;\n }\n supports(operation: RunOperation): boolean {\n const override = this.behavior?.supports?.[operation];\n return override !== undefined ? override : true;\n }\n unsupportedReason(operation: RunOperation): string | undefined {\n if (this.supports(operation)) return undefined;\n return this.behavior?.unsupportedReason?.[operation] ?? \"unsupported in mock\";\n }\n async *stream(): AsyncGenerator<SDKMessage, void> {\n yield* this.streamEvents;\n }\n async conversation(): Promise<[]> {\n return [];\n }\n async wait(): Promise<RunResult> {\n return this.waitResult;\n }\n async cancel(): Promise<void> {\n this.#status = \"cancelled\";\n for (const listener of this.#listeners) listener(this.#status);\n }\n onDidChangeStatus(listener: (status: RunStatus) => void): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n}\n\n/**\n * Deterministic SDK `Agent` implementation for tests.\n *\n * @param fixtures - Static data used by `send`, artifact methods, and metadata methods.\n *\n * @example\n * ```ts\n * const agent = new MockCursorAgent({ result: { id: \"run-1\", status: \"finished\" } })\n * const run = await agent.send(\"hello\")\n * ```\n *\n * @see {@link makeMockAgent}\n * @see {@link CursorMockFixtures}\n * @category testing\n */\nexport class MockCursorAgent implements SDKAgent {\n readonly agentId: string;\n readonly runs: Run[] = [];\n closed = false;\n #sendIndex = 0;\n\n constructor(readonly fixtures: CursorMockFixtures = {}) {\n this.agentId = fixtures.agentId ?? \"mock-agent\";\n }\n\n get model(): AgentOptions[\"model\"] | undefined {\n return this.fixtures.result?.model;\n }\n\n async send(_message: string | SDKUserMessage, _options?: SendOptions): Promise<Run> {\n const seq = this.fixtures.sendSequence;\n const piece =\n seq === undefined ? undefined : seq[Math.min(this.#sendIndex, Math.max(seq.length - 1, 0))];\n const merged: CursorMockFixtures =\n piece !== undefined ? { ...this.fixtures, ...piece } : this.fixtures;\n if (seq !== undefined) this.#sendIndex++;\n const run = makeMockRun(merged);\n this.runs.push(run);\n return run;\n }\n close(): void {\n this.closed = true;\n }\n async reload(): Promise<void> {}\n async [Symbol.asyncDispose](): Promise<void> {\n this.closed = true;\n }\n async listArtifacts(): Promise<SDKArtifact[]> {\n return [...(this.fixtures.artifacts ?? [])];\n }\n async downloadArtifact(_path: string): Promise<Buffer> {\n return this.fixtures.artifactData ?? Buffer.from(\"\");\n }\n}\n\n/**\n * Create a mock run from fixtures.\n *\n * @param fixtures - Optional mock run and stream data.\n *\n * @see {@link MockCursorRun}\n * @category testing\n */\nexport const makeMockRun = (fixtures: CursorMockFixtures = {}): MockCursorRun => {\n const runId = fixtures.runId ?? \"mock-run\";\n return new MockCursorRun(\n fixtures.stream ?? [],\n fixtures.result ?? { id: runId, status: \"finished\", result: \"\" },\n {\n supports: fixtures.runSupports,\n unsupportedReason: fixtures.runUnsupportedReason,\n },\n );\n};\n\n/**\n * Create a mock agent from fixtures.\n *\n * @param fixtures - Optional mock agent, run, artifact, and metadata data.\n *\n * @see {@link MockCursorAgent}\n * @category testing\n */\nexport const makeMockAgent = (fixtures: CursorMockFixtures = {}): MockCursorAgent => {\n return new MockCursorAgent(fixtures);\n};\n\n/**\n * Minimal assistant {@link SDKMessage} for streaming tests.\n *\n * @category testing\n */\nexport const makeMockAssistantSdkMessage = (\n text: string,\n ids: { readonly agentId?: string; readonly runId?: string } = {},\n): SDKMessage => {\n return {\n type: \"assistant\",\n agent_id: ids.agentId ?? \"mock-agent\",\n run_id: ids.runId ?? \"mock-run\",\n message: {\n role: \"assistant\",\n content: [{ type: \"text\", text }],\n },\n };\n};\n\nconst rejectFactory = (\n fixtures: CursorMockFixtures,\n method: CursorMockFactoryMethod,\n): Promise<never> | undefined => {\n const err = fixtures.factoryErrors?.[method];\n if (err !== undefined) return Promise.reject(err);\n return undefined;\n};\n\n/**\n * Layer replacing the SDK factory with deterministic mock behavior.\n *\n * This is the lowest-level mock entry point. Prefer {@link mockLayer} when you\n * want all higher-level services wired together for tests.\n *\n * @param fixtures - Static SDK responses returned by the factory methods.\n *\n * @example\n * ```ts\n * const layer = makeMockSdkFactoryLayer({\n * agents: [{ agentId: \"mock-agent\", name: \"Mock\", summary: \"Test\", lastModified: 0 }]\n * })\n * ```\n *\n * @see {@link CursorSdkFactory}\n * @see {@link mockLayer}\n * @category testing\n */\nexport const makeMockSdkFactoryLayer = (fixtures: CursorMockFixtures = {}) => {\n return Layer.succeed(\n CursorSdkFactory,\n CursorSdkFactory.of({\n create: (_options: AgentOptions): Promise<SDKAgent> => {\n const early = rejectFactory(fixtures, \"create\");\n return early ?? Promise.resolve(makeMockAgent(fixtures));\n },\n resume: (_agentId: string, _options?: Partial<AgentOptions>): Promise<SDKAgent> => {\n const early = rejectFactory(fixtures, \"resume\");\n return early ?? Promise.resolve(makeMockAgent(fixtures));\n },\n prompt: async (_message: string, _options?: AgentOptions): Promise<RunResult> => {\n const early = rejectFactory(fixtures, \"prompt\");\n if (early) return early;\n return (\n fixtures.result ?? { id: fixtures.runId ?? \"mock-run\", status: \"finished\", result: \"\" }\n );\n },\n listAgents: async (_options?: ListAgentsOptions): Promise<ListResult<SDKAgentInfo>> => {\n const early = rejectFactory(fixtures, \"listAgents\");\n if (early) return early;\n return { items: [...(fixtures.agents ?? [])] };\n },\n listRuns: async (_agentId: string, _options?: ListRunsOptions): Promise<ListResult<Run>> => {\n const early = rejectFactory(fixtures, \"listRuns\");\n if (early) return early;\n return { items: [makeMockRun(fixtures)] };\n },\n getRun: async (_runId: string, _options?: GetRunOptions): Promise<Run> => {\n const early = rejectFactory(fixtures, \"getRun\");\n if (early) return early;\n return makeMockRun(fixtures);\n },\n getAgent: async (_agentId: string, _options?: GetAgentOptions): Promise<SDKAgentInfo> => {\n const early = rejectFactory(fixtures, \"getAgent\");\n if (early) return early;\n return (\n fixtures.agents?.[0] ?? {\n agentId: fixtures.agentId ?? \"mock-agent\",\n name: \"Mock Agent\",\n summary: \"Deterministic mock agent\",\n lastModified: 0,\n }\n );\n },\n archiveAgent: async (_agentId: string, _options?: AgentOperationOptions): Promise<void> => {\n const early = rejectFactory(fixtures, \"archiveAgent\");\n if (early) return early;\n },\n unarchiveAgent: async (_agentId: string, _options?: AgentOperationOptions): Promise<void> => {\n const early = rejectFactory(fixtures, \"unarchiveAgent\");\n if (early) return early;\n },\n deleteAgent: async (_agentId: string, _options?: AgentOperationOptions): Promise<void> => {\n const early = rejectFactory(fixtures, \"deleteAgent\");\n if (early) return early;\n },\n listMessages: async (\n _agentId: string,\n _options?: GetAgentMessagesOptions,\n ): Promise<AgentMessage[]> => {\n const early = rejectFactory(fixtures, \"listMessages\");\n if (early) return early;\n return [...(fixtures.messages ?? [])];\n },\n me: async (_options?: CursorRequestOptions): Promise<SDKUser> => {\n const early = rejectFactory(fixtures, \"me\");\n if (early) return early;\n return fixtures.user ?? { apiKeyName: \"mock\", createdAt: \"1970-01-01T00:00:00.000Z\" };\n },\n listModels: async (_options?: CursorRequestOptions): Promise<SDKModel[]> => {\n const early = rejectFactory(fixtures, \"listModels\");\n if (early) return early;\n return [...(fixtures.models ?? [])];\n },\n listRepositories: async (_options?: CursorRequestOptions): Promise<SDKRepository[]> => {\n const early = rejectFactory(fixtures, \"listRepositories\");\n if (early) return early;\n return [...(fixtures.repositories ?? [])];\n },\n }),\n );\n};\n","/**\n * Reusable observability helpers: stream metrics, retry schedules, and safe summaries.\n *\n * @example\n * ```ts\n * import {\n * cursorCatalogLoadTimeout,\n * cursorCatalogRetrySchedule,\n * CursorInspectionService,\n * liveLayer,\n * } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const catalog = Effect.gen(function* () {\n * const inspection = yield* CursorInspectionService;\n * return yield* Effect.all(\n * { agents: inspection.listAgents({ runtime: \"cloud\" }), models: inspection.listModels() },\n * { concurrency: \"unbounded\" },\n * ).pipe(Effect.retry(cursorCatalogRetrySchedule), Effect.timeout(cursorCatalogLoadTimeout));\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @module\n */\nimport { Effect, Metric, Schedule, Stream } from \"effect\";\n\nimport type { CursorStreamError } from \"./cursor-error\";\nimport { redact } from \"./cursor-telemetry\";\nimport { cursorStreamEvents } from \"./cursor-telemetry\";\nimport type { AgentOptions, Run, SDKMessage } from \"./cursor-types\";\n\n/**\n * Default exponential retry for Cursor catalog-style calls (list agents, models, repos).\n *\n * Matches the pattern used in the advanced ops dashboard example: 150ms base, 3 attempts.\n *\n * @example\n * ```ts\n * import { CursorInspectionService, cursorCatalogRetrySchedule, liveLayer } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const program = Effect.gen(function* () {\n * const inspection = yield* CursorInspectionService;\n * return yield* inspection.listModels().pipe(Effect.retry(cursorCatalogRetrySchedule));\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @category observability\n */\nexport const cursorCatalogRetrySchedule = Schedule.exponential(\"150 millis\").pipe(\n Schedule.both(Schedule.recurs(3)),\n);\n\n/**\n * Default timeout for parallel catalog loads.\n *\n * @example\n * ```ts\n * import { CursorInspectionService, cursorCatalogLoadTimeout, liveLayer } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const program = Effect.gen(function* () {\n * const inspection = yield* CursorInspectionService;\n * return yield* Effect.all(\n * { user: inspection.me(), models: inspection.listModels() },\n * { concurrency: \"unbounded\" },\n * ).pipe(Effect.timeout(cursorCatalogLoadTimeout));\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @category observability\n */\nexport const cursorCatalogLoadTimeout = \"45 seconds\" as const;\n\n/**\n * Append assistant-visible text from a streamed {@link SDKMessage} (same rules as {@link CursorRunService.collectText}).\n *\n * @example\n * ```ts\n * import { appendAssistantSdkMessageText } from \"effect-cursor-sdk\";\n * import type { SDKMessage } from \"effect-cursor-sdk\";\n *\n * const events: SDKMessage[] = []; // from run.stream()\n * const text = events.reduce(appendAssistantSdkMessageText, \"\");\n * ```\n *\n * @category observability\n */\nexport const appendAssistantSdkMessageText = (text: string, event: SDKMessage): string => {\n if (event.type !== \"assistant\") return text;\n return (\n text +\n event.message.content\n .filter((block) => {\n return block.type === \"text\";\n })\n .map((block) => {\n return block.text;\n })\n .join(\"\")\n );\n};\n\n/**\n * Wraps a run event stream and increments {@link cursorStreamEvents} per emitted event.\n *\n * @example\n * ```ts\n * import { CursorRunService, streamEventsTracked, liveLayer } from \"effect-cursor-sdk\";\n * import { Effect, Stream } from \"effect\";\n * import type { Run } from \"effect-cursor-sdk\";\n *\n * declare const run: Run;\n *\n * const program = Effect.gen(function* () {\n * const runs = yield* CursorRunService;\n * yield* streamEventsTracked(runs.streamEvents(run)).pipe(Stream.runDrain);\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @category observability\n */\nexport const streamEventsTracked = <E>(\n stream: Stream.Stream<E, CursorStreamError>,\n): Stream.Stream<E, CursorStreamError> => {\n return stream.pipe(\n Stream.tap(() =>\n Effect.void.pipe(Effect.trackSuccesses(cursorStreamEvents.pipe(Metric.withConstantInput(1)))),\n ),\n );\n};\n\n/**\n * Like {@link CursorRunService.collectText}, but increments {@link cursorStreamEvents} per stream chunk.\n *\n * @param run - SDK run handle.\n * @param streamEvents - Typically `runs.streamEvents` from {@link CursorRunService}.\n *\n * @example\n * ```ts\n * import { collectTextTracked, CursorRunService, liveLayer } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n * import type { Run } from \"effect-cursor-sdk\";\n *\n * declare const run: Run;\n *\n * const text = Effect.gen(function* () {\n * const runs = yield* CursorRunService;\n * return yield* collectTextTracked(run, (r) => runs.streamEvents(r));\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @category observability\n */\nexport const collectTextTracked = (\n run: Run,\n streamEvents: (r: Run) => Stream.Stream<SDKMessage, CursorStreamError>,\n): Effect.Effect<string, CursorStreamError> => {\n return streamEventsTracked(streamEvents(run)).pipe(\n Stream.runFold(() => \"\", appendAssistantSdkMessageText),\n );\n};\n\n/**\n * Build a redacted, log-safe summary of {@link AgentOptions} **without** an API key value.\n *\n * @remarks\n * Nested structures are passed through {@link redact}. Never log raw `apiKey`.\n *\n * @example\n * ```ts\n * import { summarizeAgentOptionsForLog } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const program = Effect.gen(function* () {\n * const options = { model: { id: \"composer-2\" }, apiKey: \"secret\" };\n * yield* Effect.logInfo(\"cursor run\", summarizeAgentOptionsForLog(options));\n * });\n * ```\n *\n * @category observability\n */\nexport const summarizeAgentOptionsForLog = (options: AgentOptions): Record<string, unknown> => {\n const mcpKeys = options.mcpServers ? Object.keys(options.mcpServers) : undefined;\n return redact({\n model: options.model,\n name: options.name,\n agentId: options.agentId,\n local: options.local,\n cloud: options.cloud\n ? {\n reposCount: options.cloud.repos?.length,\n autoCreatePR: options.cloud.autoCreatePR,\n workOnCurrentBranch: options.cloud.workOnCurrentBranch,\n envType: options.cloud.env?.type,\n }\n : undefined,\n mcpServerNames: mcpKeys,\n agentsCount: options.agents ? Object.keys(options.agents).length : undefined,\n }) as Record<string, unknown>;\n};\n\n/**\n * Attach minimal run identifiers for structured logs or span attributes.\n *\n * @example\n * ```ts\n * import { summarizeRunForLog } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const program = Effect.gen(function* () {\n * const run = { id: \"run_1\", agentId: \"agt_1\", status: \"finished\" as const };\n * yield* Effect.logDebug(\"run done\", summarizeRunForLog(run));\n * });\n * ```\n *\n * @category observability\n */\nexport const summarizeRunForLog = (run: {\n readonly id: string;\n readonly agentId: string;\n readonly status?: string;\n}): Record<string, unknown> => {\n return {\n runId: run.id,\n agentId: run.agentId,\n status: run.status,\n };\n};\n","import { Context, Effect, Layer, Stream } from \"effect\";\n\nimport {\n CursorAuthenticationError,\n CursorConfigurationError,\n CursorIntegrationNotConnectedError,\n CursorNetworkError,\n CursorRateLimitError,\n CursorStreamError,\n CursorUnknownError,\n CursorUnsupportedOperationError,\n mapCursorError,\n} from \"./cursor-error\";\nimport { instrument } from \"./cursor-telemetry\";\nimport type { Run, RunOperation, RunResult, RunStatus, SDKMessage } from \"./cursor-types\";\n\nexport interface CursorRunServiceShape {\n readonly supports: (run: Run, operation: RunOperation) => boolean;\n readonly unsupportedReason: (run: Run, operation: RunOperation) => string | undefined;\n readonly wait: (\n run: Run,\n ) => Effect.Effect<\n RunResult,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly cancel: (\n run: Run,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnsupportedOperationError\n | CursorUnknownError\n >;\n readonly conversation: (\n run: Run,\n ) => ReturnType<Run[\"conversation\"]> extends Promise<infer A>\n ? Effect.Effect<\n A,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorNetworkError\n | CursorUnsupportedOperationError\n | CursorUnknownError\n >\n : never;\n readonly streamEvents: (run: Run) => Stream.Stream<SDKMessage, CursorStreamError>;\n readonly collectText: (run: Run) => Effect.Effect<string, CursorStreamError>;\n readonly onDidChangeStatus: (\n run: Run,\n listener: (status: RunStatus) => void,\n ) => Effect.Effect<() => void>;\n /**\n * Status updates as a stream (backed by {@link Run.onDidChangeStatus}).\n *\n * @example\n * ```ts\n *\n * ```\n */\n readonly streamStatusChanges: (run: Run) => Stream.Stream<RunStatus, never, never>;\n}\n\n/**\n * Effect-native helpers for SDK run handles.\n *\n * @example\n * ```ts\n * const runService = yield* CursorRunService;\n *\n * // Create a run with the agent service\n * const run = yield* agents.send(agent, \"Refactor auth\")\n *\n * // Use the run service with the created run\n * const conversation = yield* runService.conversation(run);\n * ```\n *\n * @see {@link CursorAgentService} for creating and sending runs.\n * @see {@link SDKMessage} for the SDK-owned stream event shape.\n *\n * @category services\n */\nexport class CursorRunService extends Context.Service<CursorRunService, CursorRunServiceShape>()(\n \"effect-cursor-sdk/cursor-run/CursorRunService\",\n) {\n static readonly Live = Layer.succeed(CursorRunService)(\n CursorRunService.of({\n supports: (run: Run, operation: RunOperation): boolean => {\n return run.supports(operation);\n },\n unsupportedReason: (run: Run, operation: RunOperation): string | undefined => {\n return run.unsupportedReason(operation);\n },\n wait: (run: Run) => {\n return instrument(\n \"run.wait\",\n Effect.tryPromise({\n try: () => run.wait(),\n catch: (cause) => {\n return mapCursorError(cause, {\n operation: \"run.wait\",\n agentId: run.agentId,\n runId: run.id,\n });\n },\n }),\n );\n },\n cancel: (run: Run) => {\n return instrument(\n \"run.cancel\",\n Effect.tryPromise({\n try: () => run.cancel(),\n catch: (cause) => {\n return mapCursorError(cause, {\n operation: \"run.cancel\",\n agentId: run.agentId,\n runId: run.id,\n });\n },\n }),\n );\n },\n conversation: (run: Run) => {\n return instrument(\n \"run.conversation\",\n Effect.tryPromise({\n try: () => run.conversation(),\n catch: (cause) => {\n return mapCursorError(cause, {\n operation: \"run.conversation\",\n agentId: run.agentId,\n runId: run.id,\n });\n },\n }),\n );\n },\n streamEvents: (run: Run): Stream.Stream<SDKMessage, CursorStreamError> => {\n return Stream.fromAsyncIterable(run.stream(), (cause) => {\n return mapCursorError(cause, {\n operation: \"run.stream\",\n agentId: run.agentId,\n runId: run.id,\n }) as CursorStreamError;\n });\n },\n onDidChangeStatus: (\n run: Run,\n listener: (status: RunStatus) => void,\n ): Effect.Effect<() => void> => {\n return Effect.sync(() => run.onDidChangeStatus(listener));\n },\n streamStatusChanges: (run: Run): Stream.Stream<RunStatus, never, never> => {\n return Stream.fromAsyncIterable(\n (async function* (): AsyncGenerator<RunStatus> {\n const pending: RunStatus[] = [];\n let notify: (() => void) | undefined;\n const unsub = run.onDidChangeStatus((status) => {\n pending.push(status);\n const resume = notify;\n notify = undefined;\n resume?.();\n });\n try {\n while (true) {\n if (pending.length > 0) {\n yield pending.shift()!;\n continue;\n }\n await new Promise<void>((resolve) => {\n notify = resolve;\n });\n }\n } finally {\n unsub();\n }\n })(),\n () => undefined as never,\n );\n },\n collectText: (run: Run): Effect.Effect<string, CursorStreamError> => {\n return Stream.fromAsyncIterable(run.stream(), (cause) => {\n return mapCursorError(cause, {\n operation: \"run.stream\",\n agentId: run.agentId,\n runId: run.id,\n }) as CursorStreamError;\n }).pipe(\n Stream.runFold(\n () => \"\",\n (text, event) => {\n if (event.type !== \"assistant\") return text;\n return (\n text +\n event.message.content\n .filter((block) => {\n return block.type === \"text\";\n })\n .map((block) => {\n return block.text;\n })\n .join(\"\")\n );\n },\n ),\n );\n },\n }),\n );\n}\n","import { Layer, ManagedRuntime } from \"effect\";\n\nimport { CursorAgentService } from \"./cursor-agent\";\nimport { CursorArtifactService } from \"./cursor-artifacts\";\nimport { CursorInspectionService } from \"./cursor-inspection\";\nimport { makeMockSdkFactoryLayer, type CursorMockFixtures } from \"./cursor-mock\";\nimport { CursorRunService } from \"./cursor-run\";\nimport { CursorSdkFactory } from \"./cursor-sdk-factory\";\n\n/**\n * Live service layer for the SDK-backed Effect wrapper.\n *\n * Provides {@link CursorAgentService}, {@link CursorRunService},\n * {@link CursorArtifactService}, and {@link CursorInspectionService} using\n * {@link CursorSdkFactory.Live}.\n *\n * @example\n * ```ts\n * const result = yield* program.pipe(Effect.provide(liveLayer))\n * ```\n *\n * @see {@link CursorSdkFactory}\n * @see {@link liveRuntime}\n *\n * @category layers\n */\nexport const liveLayer = Layer.mergeAll(\n CursorAgentService.Live,\n CursorRunService.Live,\n CursorArtifactService.Live,\n CursorInspectionService.Live,\n).pipe(Layer.provideMerge(CursorSdkFactory.Live));\n\n/**\n * Deterministic mock layer for tests and examples.\n *\n * @param fixtures - Static SDK responses returned by the mock factory.\n *\n * @example\n * ```ts\n * const layer = mockLayer({\n * result: { id: \"run-1\", status: \"finished\", result: \"ok\" }\n * })\n * ```\n *\n * @see {@link CursorMockFixtures}\n * @see {@link makeMockSdkFactoryLayer}\n *\n * @category layers\n */\nexport const mockLayer = (fixtures: CursorMockFixtures = {}) => {\n return Layer.mergeAll(\n CursorAgentService.Live,\n CursorRunService.Live,\n CursorArtifactService.Live,\n CursorInspectionService.Live,\n ).pipe(Layer.provideMerge(makeMockSdkFactoryLayer(fixtures)));\n};\n\n/**\n * Ready-made live runtime.\n *\n * Use this for small scripts that prefer `ManagedRuntime.runPromise` over\n * manually providing {@link liveLayer}.\n *\n * @example\n * ```ts\n * const value = await liveRuntime.runPromise(program)\n * ```\n *\n * @see {@link liveLayer}\n *\n * @category runtimes\n */\nexport const liveRuntime = ManagedRuntime.make(liveLayer);\n\n/**\n * Ready-made mock runtime.\n *\n * @param fixtures - Static SDK responses returned by the mock services.\n *\n * @example\n * ```ts\n * const runtime = makeMockRuntime({ result: { id: \"run-1\", status: \"finished\" } })\n * const value = await runtime.runPromise(program)\n * ```\n *\n * @see {@link mockLayer}\n * @see {@link CursorMockFixtures}\n *\n * @category runtimes\n */\nexport const makeMockRuntime = (fixtures: CursorMockFixtures = {}) => {\n return ManagedRuntime.make(mockLayer(fixtures));\n};\n","/**\n * Public package name.\n *\n * @category metadata\n */\nexport const packageName = \"effect-cursor-sdk\";\n\nexport * from \"./cursor-agent\";\nexport * from \"./cursor-artifacts\";\nexport * from \"./cursor-config\";\nexport * from \"./cursor-error\";\nexport * from \"./cursor-inspection\";\nexport * from \"./cursor-mock\";\nexport * from \"./cursor-observability\";\nexport * from \"./cursor-run\";\nexport * from \"./cursor-runtime\";\nexport * from \"./cursor-sdk-factory\";\nexport * from \"./cursor-telemetry\";\nexport * from \"./cursor-types\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["CursorAgentError","AuthenticationError","RateLimitError","IntegrationNotConnectedError","UnsupportedRunOperationError","ConfigurationError","AgentBusyError","NetworkError","UnknownAgentError","#status","#listeners","#sendIndex"],"sources":["../src/cursor-error.ts","../src/cursor-config.ts","../src/cursor-sdk-factory.ts","../src/cursor-telemetry.ts","../src/cursor-agent.ts","../src/cursor-artifacts.ts","../src/cursor-inspection.ts","../src/cursor-mock.ts","../src/cursor-observability.ts","../src/cursor-run.ts","../src/cursor-runtime.ts","../src/index.ts"],"sourcesContent":["import {\n AgentBusyError,\n AuthenticationError,\n ConfigurationError,\n CursorAgentError,\n IntegrationNotConnectedError,\n NetworkError,\n RateLimitError,\n UnknownAgentError,\n UnsupportedRunOperationError,\n} from \"@cursor/sdk\";\nimport { Data, Match } from \"effect\";\n\nimport type { RunOperation } from \"./cursor-types\";\n\n/**\n * The operation being executed when an SDK error crossed into Effect.\n *\n * @category errors\n */\nexport type CursorOperation =\n | \"agent.create\"\n | \"agent.resume\"\n | \"agent.prompt\"\n | \"agent.send\"\n | \"agent.close\"\n | \"agent.reload\"\n | \"agent.dispose\"\n | \"agent.list\"\n | \"agent.get\"\n | \"agent.archive\"\n | \"agent.unarchive\"\n | \"agent.delete\"\n | \"messages.list\"\n | \"run.list\"\n | \"run.get\"\n | \"run.wait\"\n | \"run.stream\"\n | \"run.conversation\"\n | \"run.cancel\"\n | \"artifacts.list\"\n | \"artifacts.download\"\n | \"cursor.me\"\n | \"cursor.models.list\"\n | \"cursor.repositories.list\";\n\n/**\n * Safe metadata attached to wrapper errors.\n *\n * @category errors\n */\nexport interface CursorErrorContext {\n readonly operation: CursorOperation;\n readonly agentId?: string;\n readonly runId?: string;\n readonly runtime?: \"local\" | \"cloud\";\n readonly status?: string;\n}\n\ninterface CursorErrorFields extends CursorErrorContext {\n readonly message: string;\n readonly cause: unknown;\n readonly isRetryable: boolean;\n}\n\n/**\n * Authentication or permission failure reported by the Cursor SDK.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorAuthenticationError extends Data.TaggedError(\n \"CursorAuthenticationError\",\n)<CursorErrorFields> {}\n\n/**\n * Cursor rate limit or usage-limit failure.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorRateLimitError extends Data.TaggedError(\n \"CursorRateLimitError\",\n)<CursorErrorFields> {}\n\n/**\n * Invalid configuration, model, prompt, repository, or request options.\n *\n * @see {@link AgentOptions}\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorConfigurationError extends Data.TaggedError(\n \"CursorConfigurationError\",\n)<CursorErrorFields> {}\n\n/**\n * The agent already has an active run; starting another run was rejected (409).\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorAgentBusyError extends Data.TaggedError(\n \"CursorAgentBusyError\",\n)<CursorErrorFields> {}\n\n/**\n * SCM integration is not connected for a requested cloud repository.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorIntegrationNotConnectedError extends Data.TaggedError(\n \"CursorIntegrationNotConnectedError\",\n)<CursorErrorFields & { readonly provider?: string; readonly helpUrl?: string }> {}\n\n/**\n * Network, service availability, timeout, or backend failure.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorNetworkError extends Data.TaggedError(\"CursorNetworkError\")<CursorErrorFields> {}\n\n/**\n * A run operation is unavailable for the current runtime or run state.\n *\n * @see {@link RunOperation}\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorUnsupportedOperationError extends Data.TaggedError(\n \"CursorUnsupportedOperationError\",\n)<CursorErrorFields & { readonly sdkOperation?: RunOperation }> {}\n\n/**\n * A run reached an error terminal state or failed to produce a usable result.\n *\n * @see {@link RunResult}\n * @category errors\n */\nexport class CursorRunFailedError extends Data.TaggedError(\n \"CursorRunFailedError\",\n)<CursorErrorFields> {}\n\n/**\n * Stream creation or iteration failed.\n *\n * @see {@link CursorRunService}\n * @see {@link SDKMessage}\n * @category errors\n */\nexport class CursorStreamError extends Data.TaggedError(\"CursorStreamError\")<CursorErrorFields> {}\n\n/**\n * Fallback for unknown SDK or JavaScript failures.\n *\n * @see {@link mapCursorError}\n * @category errors\n */\nexport class CursorUnknownError extends Data.TaggedError(\"CursorUnknownError\")<CursorErrorFields> {}\n\nconst messageFrom = (cause: unknown): string => {\n return cause instanceof Error ? cause.message : String(cause);\n};\n\nconst retryableFrom = (cause: unknown): boolean => {\n return cause instanceof CursorAgentError ? cause.isRetryable : false;\n};\n\n/**\n * Convert any SDK failure into a tagged Effect error.\n *\n * @param cause - Unknown value thrown by `@cursor/sdk` or JavaScript runtime code.\n * @param context - Safe operation metadata to attach to the tagged error.\n *\n * @example\n * ```ts\n * import { Effect } from \"effect\"\n * import { mapCursorError } from \"effect-cursor-sdk\"\n *\n * const effect = Effect.tryPromise({\n * try: () => run.wait(),\n * catch: (cause) => mapCursorError(cause, { operation: \"run.wait\", runId: run.id })\n * })\n * ```\n *\n * @see {@link CursorAuthenticationError}\n * @see {@link CursorUnsupportedOperationError}\n * @see {@link CursorStreamError}\n *\n * @category errors\n */\nexport function mapCursorError(\n cause: unknown,\n context: CursorErrorContext & { readonly operation: \"run.stream\" },\n): CursorStreamError;\nexport function mapCursorError(\n cause: unknown,\n context: CursorErrorContext & { readonly operation: \"run.cancel\" | \"run.conversation\" },\n):\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnsupportedOperationError\n | CursorUnknownError;\nexport function mapCursorError(\n cause: unknown,\n context: CursorErrorContext,\n):\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError;\nexport function mapCursorError(cause: unknown, context: CursorErrorContext) {\n const fields = {\n ...context,\n message: messageFrom(cause),\n cause,\n isRetryable: retryableFrom(cause),\n };\n\n if (context.operation === \"run.stream\") {\n return new CursorStreamError(fields);\n }\n\n return Match.value(cause).pipe(\n Match.when(Match.instanceOf(AuthenticationError), () => {\n return new CursorAuthenticationError(fields);\n }),\n Match.when(Match.instanceOf(RateLimitError), () => {\n return new CursorRateLimitError(fields);\n }),\n Match.when(Match.instanceOf(IntegrationNotConnectedError), (error) => {\n return new CursorIntegrationNotConnectedError({\n ...fields,\n provider: error.provider,\n helpUrl: error.helpUrl,\n });\n }),\n Match.when(Match.instanceOf(UnsupportedRunOperationError), (error) => {\n return new CursorUnsupportedOperationError({\n ...fields,\n sdkOperation: error.operation as RunOperation | undefined,\n });\n }),\n Match.when(Match.instanceOf(ConfigurationError), () => {\n return new CursorConfigurationError(fields);\n }),\n Match.when(Match.instanceOf(AgentBusyError), () => {\n return new CursorAgentBusyError(fields);\n }),\n Match.when(Match.instanceOf(NetworkError), () => {\n return new CursorNetworkError(fields);\n }),\n Match.when(Match.instanceOf(UnknownAgentError), () => {\n return new CursorUnknownError(fields);\n }),\n Match.when(Match.instanceOf(CursorAgentError), () => {\n return new CursorUnknownError(fields);\n }),\n Match.orElse(() => {\n return new CursorUnknownError(fields);\n }),\n );\n}\n","import { Config, ConfigProvider, Effect, Option, Redacted, Schema } from \"effect\";\n\nimport type { AgentOptions, ModelSelection } from \"./cursor-types\";\n\n/**\n * Branded secret material for the Cursor API key.\n *\n * Values are held inside {@link Redacted} on {@link CursorConfig}; this schema\n * only brands the decoded plaintext type so it cannot be confused with other\n * strings at the type level.\n */\nexport const CursorApiKey = Schema.Redacted(Schema.String).pipe(Schema.brand(\"CursorApiKey\"));\nexport type CursorApiKey = typeof CursorApiKey.Type;\n\n/**\n * Branded model identifier from wrapper config.\n *\n * Populated from the `CURSOR_MODEL` environment variable when using\n * {@link loadCursorConfig}.\n */\nexport const CursorModelId = Schema.String.pipe(Schema.brand(\"CursorModelId\"));\nexport type CursorModelId = typeof CursorModelId.Type;\n\n/**\n * Branded local working directory for agent runs.\n *\n * Populated from `CURSOR_LOCAL_CWD` when using {@link loadCursorConfig}.\n */\nexport const CursorLocalCwd = Schema.String.pipe(Schema.brand(\"CursorLocalCwd\"));\nexport type CursorLocalCwd = typeof CursorLocalCwd.Type;\n\n/**\n * Minimal configuration owned by this wrapper.\n *\n * The SDK's `AgentOptions` type remains the source of truth for complete\n * runtime options. This schema models environment-derived defaults only.\n * Use {@link agentOptionsFromConfig} to merge those defaults into SDK-owned\n * {@link AgentOptions} at the SDK boundary.\n *\n * @remarks\n * **Preferred path:** Load defaults with {@link loadCursorConfig}, then call\n * `CursorAgentService` methods such as `createFromConfig` (and related helpers)\n * or merge manually with {@link agentOptionsFromConfig}. Passing plain\n * {@link AgentOptions} directly to deprecated `create` / `resume` / `prompt` /\n * `scoped` overloads may be removed in a future major version.\n *\n * @example\n * ```ts\n * const config = new CursorConfig({\n * apiKey: Redacted.make(CursorApiKey.make(process.env.CURSOR_API_KEY!)),\n * modelId: CursorModelId.make(\"composer-2\"),\n * cwd: CursorLocalCwd.make(process.cwd())\n * })\n * ```\n *\n * @see {@link cursorConfig}\n * @see {@link loadCursorConfig}\n *\n * @category config\n */\nexport class CursorConfig extends Schema.Class<CursorConfig>(\"CursorConfig\")({\n apiKey: Schema.optional(CursorApiKey),\n modelId: Schema.optional(CursorModelId),\n cwd: Schema.optional(CursorLocalCwd),\n}) {}\n\n/**\n * Effect Config descriptors for common Cursor environment variables.\n *\n * Reads `CURSOR_API_KEY`, `CURSOR_MODEL`, and `CURSOR_LOCAL_CWD` from the active\n * Effect {@link ConfigProvider.ConfigProvider}. All fields are optional so\n * callers can merge with explicit overrides via {@link agentOptionsFromConfig}.\n *\n * @example\n * ```ts\n * const config = yield* loadCursorConfig\n * const options = agentOptionsFromConfig(config)\n * ```\n *\n * @see {@link Config}\n * @see {@link loadCursorConfig}\n *\n * @category config\n */\nexport const cursorConfig = Config.all({\n apiKey: Config.redacted(\"CURSOR_API_KEY\").pipe(Config.option),\n modelId: Config.string(\"CURSOR_MODEL\").pipe(Config.option),\n cwd: Config.string(\"CURSOR_LOCAL_CWD\").pipe(Config.option),\n});\n\n/**\n * Build SDK `AgentOptions` from wrapper config and optional overrides.\n *\n * This is the adapter from typed, redacted {@link CursorConfig} to the SDK's\n * plain-string `apiKey` boundary. Prefer `CursorAgentService.createFromConfig`\n * (and related methods) over building {@link AgentOptions} by hand.\n *\n * @param config - Wrapper-owned environment defaults.\n * @param overrides - Complete or partial SDK-owned options to merge over the defaults.\n *\n * @example\n * ```ts\n * const options = agentOptionsFromConfig(config, {\n * cloud: {\n * repos: [{ url: \"https://github.com/acme/app\" }],\n * autoCreatePR: true\n * }\n * })\n * ```\n *\n * @see {@link CursorConfig}\n * @see {@link AgentOptions}\n *\n * @remarks\n * Explicit override values always win over environment-derived defaults.\n * For application code, prefer service methods that take {@link CursorConfig}\n * instead of calling this helper and then the deprecated `create` overload.\n *\n * @category config\n */\nexport const agentOptionsFromConfig = (\n config: CursorConfig,\n overrides: AgentOptions = {},\n): AgentOptions => {\n const model: ModelSelection | undefined =\n overrides.model ?? (config.modelId ? { id: config.modelId } : undefined);\n const hasNonEmptyLocalOverride =\n overrides.local !== undefined && Object.keys(overrides.local).length > 0;\n const local =\n config.cwd || hasNonEmptyLocalOverride\n ? {\n cwd: config.cwd,\n ...overrides.local,\n }\n : undefined;\n return {\n ...overrides,\n apiKey: overrides.apiKey ?? (config.apiKey ? Redacted.value(config.apiKey) : undefined),\n model,\n local,\n };\n};\n\n/**\n * Load environment-derived defaults as a schema-backed value.\n * It uses ConfigProvider to load the environment variables\n * with their default names (`CURSOR_API_KEY`, `CURSOR_MODEL`, `CURSOR_LOCAL_CWD`)\n * from {@link cursorConfig}.\n * Omitting `CURSOR_API_KEY` only means no default API-key-based auth will be\n * set; callers can still provide credentials via {@link agentOptionsFromConfig}\n * overrides or the `*FromConfig` service helpers.\n *\n * If the API key is not set, it will log a warning message.\n *\n * **NOTE**: omitting the API key will cause an unauthenticated error\n * in subsequent calls to the Cursor SDK API.\n *\n * @example\n * ```ts\n * const config = yield* loadCursorConfig\n * const options = agentOptionsFromConfig(config, { local: { cwd: process.cwd() } })\n * // Or use CursorAgentService.createFromConfig(config, { local: { cwd: process.cwd() } })\n * ```\n *\n * To change the way that the environment variables are loaded,\n * you can do it with Effect by providing a custom ConfigProvider.\n *\n * ```ts\n * // For example: load via custom environment object\n * const config = yield* loadCursorConfig.pipe(\n * Effect.provideService(\n * ConfigProvider.ConfigProvider,\n * ConfigProvider.fromEnv({\n * env: {\n * CURSOR_API_KEY: \"crsr_******\",\n * CURSOR_MODEL: \"composer-2\",\n * CURSOR_LOCAL_CWD: \"/workspace\",\n * },\n * }),\n * ),\n * )\n * ```\n *\n * @see {@link cursorConfig}\n * @see {@link agentOptionsFromConfig}\n *\n * @remarks\n * This effect is the preferred entry for redacted environment defaults.\n * Pair it with {@link agentOptionsFromConfig} or `CursorAgentService` helpers\n * such as `createFromConfig`.\n *\n * @category config\n */\nexport const loadCursorConfig = Effect.gen(function* () {\n const provider = yield* ConfigProvider.ConfigProvider;\n const raw = yield* cursorConfig.parse(provider);\n const apiKey = Option.getOrUndefined(raw.apiKey);\n if (apiKey === undefined || apiKey === null) {\n yield* Effect.logWarning(\n \"CURSOR_API_KEY is not set — this will cause an unauthenticated error in subsequent calls to the Cursor SDK API.\",\n );\n }\n\n const modelId = Option.getOrUndefined(raw.modelId);\n const cwd = Option.getOrUndefined(raw.cwd);\n return new CursorConfig({\n apiKey: apiKey ? CursorApiKey.make(apiKey) : undefined,\n modelId: modelId !== undefined ? CursorModelId.make(modelId) : undefined,\n cwd: cwd !== undefined ? CursorLocalCwd.make(cwd) : undefined,\n });\n});\n","import { Agent, Cursor } from \"@cursor/sdk\";\nimport { Context, Layer } from \"effect\";\n\nimport type {\n AgentMessage,\n AgentOperationOptions,\n AgentOptions,\n CursorRequestOptions,\n GetAgentMessagesOptions,\n GetAgentOptions,\n GetRunOptions,\n ListAgentsOptions,\n ListResult,\n ListRunsOptions,\n Run,\n RunResult,\n SDKAgent,\n SDKAgentInfo,\n SDKModel,\n SDKRepository,\n SDKUser,\n} from \"./cursor-types\";\n\n/* oxlint-disable eslint/no-unused-vars -- type-only imports anchor TSDoc `{@link …}`; not referenced in code */\nimport type { CursorAgentService } from \"./cursor-agent\";\nimport type { CursorArtifactService } from \"./cursor-artifacts\";\nimport type { CursorInspectionService } from \"./cursor-inspection\";\nimport type { CursorRunService } from \"./cursor-run\";\n/* oxlint-enable eslint/no-unused-vars */\n\n/**\n * Thin boundary around the static `@cursor/sdk` APIs.\n *\n * Most application code should use {@link CursorAgentService},\n * {@link CursorRunService}, {@link CursorArtifactService}, and\n * {@link CursorInspectionService}. This factory exists so live code, tests, and\n * user applications can replace SDK construction and static calls without\n * monkey-patching imports.\n *\n * So in one line: you probably won't need this.\n *\n * @example\n * ```ts\n * import { CursorSdkFactory, CursorAgentService } from \"effect-cursor-sdk\"\n * import { Layer } from \"effect\"\n *\n * const TestSdk = Layer.succeed(CursorSdkFactory)(\n * CursorSdkFactory.of({\n * create: () => mockAgent,\n * // implement the remaining factory methods for your test\n * })\n * )\n * ```\n *\n * @see {@link CursorAgentService} for creating, resuming, sending, and disposing agents.\n * @see {@link CursorRunService} for wrapping `Run` handles.\n * @see {@link CursorInspectionService} for static agent and account APIs.\n * @see {@link CursorArtifactService} for artifact APIs on an SDK agent.\n *\n * @remarks\n * **Deprecated for application code:** `create`, `resume`, and `prompt` accept\n * raw {@link AgentOptions} (including a plain `apiKey` string). Prefer\n * {@link CursorAgentService} with `loadCursorConfig` and `createFromConfig` /\n * `resumeFromConfig` / `promptFromConfig` from this package instead.\n * This factory remains the low-level adapter for tests and advanced overrides.\n *\n * @category services\n */\nexport interface CursorSdkFactoryShape {\n /**\n * @deprecated Prefer {@link CursorAgentService} with config-based helpers.\n * Low-level adapter to `Agent.create`.\n */\n readonly create: (options: AgentOptions) => Promise<SDKAgent>;\n /**\n * @deprecated Prefer {@link CursorAgentService} with config-based helpers.\n * Low-level adapter to `Agent.resume`.\n */\n readonly resume: (agentId: string, options?: Partial<AgentOptions>) => Promise<SDKAgent>;\n /**\n * @deprecated Prefer {@link CursorAgentService} with config-based helpers.\n * Low-level adapter to `Agent.prompt`.\n */\n readonly prompt: (message: string, options?: AgentOptions) => Promise<RunResult>;\n readonly listAgents: (options?: ListAgentsOptions) => Promise<ListResult<SDKAgentInfo>>;\n readonly listRuns: (agentId: string, options?: ListRunsOptions) => Promise<ListResult<Run>>;\n readonly getRun: (runId: string, options?: GetRunOptions) => Promise<Run>;\n readonly getAgent: (agentId: string, options?: GetAgentOptions) => Promise<SDKAgentInfo>;\n readonly archiveAgent: (agentId: string, options?: AgentOperationOptions) => Promise<void>;\n readonly unarchiveAgent: (agentId: string, options?: AgentOperationOptions) => Promise<void>;\n readonly deleteAgent: (agentId: string, options?: AgentOperationOptions) => Promise<void>;\n readonly listMessages: (\n agentId: string,\n options?: GetAgentMessagesOptions,\n ) => Promise<AgentMessage[]>;\n readonly me: (options?: CursorRequestOptions) => Promise<SDKUser>;\n readonly listModels: (options?: CursorRequestOptions) => Promise<SDKModel[]>;\n readonly listRepositories: (options?: CursorRequestOptions) => Promise<SDKRepository[]>;\n}\n\n/**\n * Context service that provides the live `@cursor/sdk` static API boundary.\n *\n * Use {@link CursorSdkFactory.Live} in production layers and override the\n * service in tests with {@link makeMockSdkFactoryLayer} or a custom layer.\n *\n * @example\n * ```ts\n * import { CursorSdkFactory, agentOptionsFromConfig, loadCursorConfig } from \"effect-cursor-sdk\"\n * import { Effect } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const sdk = yield* CursorSdkFactory\n * const config = yield* loadCursorConfig\n * return sdk.create(agentOptionsFromConfig(config, { model: { id: \"composer-2\" } }))\n * })\n * ```\n *\n * @see {@link CursorSdkFactoryShape}\n * @see {@link liveLayer}\n * @category services\n */\nexport class CursorSdkFactory extends Context.Service<CursorSdkFactory, CursorSdkFactoryShape>()(\n \"effect-cursor-sdk/cursor-sdk-factory/CursorSdkFactory\",\n) {\n static readonly Live = Layer.succeed(CursorSdkFactory)(\n CursorSdkFactory.of({\n create: (options: AgentOptions): Promise<SDKAgent> => {\n return Agent.create(options);\n },\n resume: (agentId: string, options?: Partial<AgentOptions>): Promise<SDKAgent> => {\n return Agent.resume(agentId, options);\n },\n prompt: (message: string, options?: AgentOptions): Promise<RunResult> => {\n return Agent.prompt(message, options);\n },\n listAgents: (options?: ListAgentsOptions): Promise<ListResult<SDKAgentInfo>> => {\n return Agent.list(options);\n },\n listRuns: (agentId: string, options?: ListRunsOptions): Promise<ListResult<Run>> => {\n return Agent.listRuns(agentId, options);\n },\n getRun: (runId: string, options?: GetRunOptions): Promise<Run> => {\n return Agent.getRun(runId, options);\n },\n getAgent: (agentId: string, options?: GetAgentOptions): Promise<SDKAgentInfo> => {\n return Agent.get(agentId, options);\n },\n archiveAgent: (agentId: string, options?: AgentOperationOptions): Promise<void> => {\n return Agent.archive(agentId, options);\n },\n unarchiveAgent: (agentId: string, options?: AgentOperationOptions): Promise<void> => {\n return Agent.unarchive(agentId, options);\n },\n deleteAgent: (agentId: string, options?: AgentOperationOptions): Promise<void> => {\n return Agent.delete(agentId, options);\n },\n listMessages: (agentId: string, options?: GetAgentMessagesOptions) => {\n return Agent.messages.list(agentId, options);\n },\n me: (options?: CursorRequestOptions): Promise<SDKUser> => {\n return Cursor.me(options);\n },\n listModels: (options?: CursorRequestOptions): Promise<SDKModel[]> => {\n return Cursor.models.list(options);\n },\n listRepositories: (options?: CursorRequestOptions): Promise<SDKRepository[]> => {\n return Cursor.repositories.list(options);\n },\n }),\n );\n}\n","/**\n * Telemetry helpers for the Effect Cursor SDK boundary.\n *\n * Services wrap SDK calls with {@link instrument}, which records Effect metrics\n * and opens an OpenTelemetry-style span per {@link CursorOperation}. Named\n * `Metric.counter` values are exported so applications can wire them into a\n * metrics backend via Effect's metrics layer.\n *\n * {@link redact} is a small helper for scrubbing structured metadata before it\n * leaves a trust boundary (for example log attributes or debug payloads).\n *\n * @see {@link CursorOperation}\n * @see {@link CursorAgentService}\n * @see {@link CursorRunService}\n * @see {@link CursorInspectionService}\n * @see {@link CursorArtifactService}\n *\n * @module\n */\n\nimport { Effect, Metric } from \"effect\";\n\nimport type { CursorOperation } from \"./cursor-error\";\n\n/**\n * Increments once when an instrumented SDK effect **starts** execution.\n *\n * Bound to the metric key `cursor_operations_started`. Used by\n * {@link instrument} on every wrapped call; pair with\n * {@link cursorOperationsFailed} to compute failure rates per operation when\n * both counters are exported to your metrics stack.\n *\n * @see {@link instrument}\n * @see {@link cursorOperationsFailed}\n *\n * @category telemetry\n */\nexport const cursorOperationsStarted = Metric.counter(\"cursor_operations_started\");\n\n/**\n * Increments once when an instrumented SDK effect **fails** (any error channel\n * value), after {@link cursorOperationsStarted} has already been recorded for\n * that run.\n *\n * Bound to the metric key `cursor_operations_failed`. Failures are tracked in\n * `Effect.tapError` so the effect still fails with the original error; this\n * counter is observability-only.\n *\n * @see {@link instrument}\n * @see {@link cursorOperationsStarted}\n *\n * @category telemetry\n */\nexport const cursorOperationsFailed = Metric.counter(\"cursor_operations_failed\");\n\n/**\n * Counter reserved for **per-message** or **per-chunk** stream throughput.\n *\n * Bound to the metric key `cursor_stream_events`. The service wrappers do not\n * attach this metric automatically to {@link CursorRunService.streamEvents};\n * export it from your app if you want to `Metric.track` inside a\n * `Stream.tapEffect` (or similar) when consuming SDK stream payloads.\n *\n * @see {@link CursorRunService}\n *\n * @category telemetry\n */\nexport const cursorStreamEvents = Metric.counter(\"cursor_stream_events\");\n\n/** String substituted for values under sensitive-looking keys. */\nconst REDACTED_MARKER = \"[redacted]\";\n\n/** Replaces non-plain objects (for example `Date`, `Map`) so they are not mistaken for empty `{}`. */\nconst OPAQUE_MARKER = \"[opaque]\";\n\n/** Replaces a value when the same object appears on the recursion stack (true cycles only). */\nconst CIRCULAR_MARKER = \"[circular]\";\n\n/** Replaces nested values when recursion depth exceeds this limit (prevents stack overflow). */\nconst MAX_REDACT_DEPTH = 64;\n\nconst isPlainObject = (value: object): boolean => {\n const proto = Object.getPrototypeOf(value);\n return proto === null || proto === Object.prototype;\n};\n\n/**\n * Lower-cased key substring / equality checks. Substrings such as `key` also\n * match `apiKey` (and unfortunately unrelated keys like `monkey`); that is an\n * intentional tradeoff for simple log scrubbing.\n */\nconst isSensitiveKeyName = (normalized: string): boolean => {\n if (normalized === \"authorization\" || normalized === \"data\") return true;\n return (\n normalized.includes(\"key\") ||\n normalized.includes(\"token\") ||\n normalized.includes(\"secret\") ||\n normalized.includes(\"password\") ||\n normalized.includes(\"passwd\") ||\n normalized.includes(\"credential\") ||\n normalized.includes(\"cookie\") ||\n normalized.includes(\"jwt\") ||\n normalized.includes(\"bearer\")\n );\n};\n\nconst redactInner = (value: unknown, path: Set<object>, depth: number): unknown => {\n if (depth > MAX_REDACT_DEPTH) {\n return OPAQUE_MARKER;\n }\n\n if (Array.isArray(value)) {\n if (path.has(value)) {\n return CIRCULAR_MARKER;\n }\n path.add(value);\n const out = value.map((item) => {\n return redactInner(item, path, depth + 1);\n });\n path.delete(value);\n return out;\n }\n\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n\n if (!isPlainObject(value)) {\n return OPAQUE_MARKER;\n }\n\n if (path.has(value)) {\n return CIRCULAR_MARKER;\n }\n\n path.add(value);\n const out = Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([key, item]) => {\n const normalized = key.toLowerCase();\n if (isSensitiveKeyName(normalized)) {\n return [key, REDACTED_MARKER];\n }\n return [key, redactInner(item, path, depth + 1)];\n }),\n );\n path.delete(value);\n return out;\n};\n\n/**\n * Deep-clones **plain** objects and arrays while replacing values under keys that\n * often carry secrets, bearer material, or large opaque blobs (for example API\n * keys, tokens, passwords, cookies, `Authorization`, or a generic `data` field).\n *\n * Matching is **substring-based on the lower-cased key name** (for example\n * `apiKey`, `CURSOR_API_TOKEN`, `client_secret`, `setCookie` all match). Primitives\n * and `null` pass through unchanged. Non-plain objects (for example `Date`, `Map`,\n * class instances) are replaced by `\"[opaque]\"` so they are not serialized as empty\n * objects. True circular references in the input are replaced by `\"[circular]\"`.\n * Recursion deeper than 64 levels falls back to `\"[opaque]\"` for the overflow branch.\n *\n * This is a best-effort redactor for logs and attributes—not a cryptographic\n * guarantee; do not rely on it for compliance redaction without review.\n *\n * @param value - Arbitrary JSON-like value to sanitize.\n * @returns A structure of the same shape with sensitive-looking entries replaced\n * by the string `\"[redacted]\"`.\n *\n * @example\n * ```ts\n * redact({ apiKey: \"secret\", nested: { token: \"x\" }, safe: 1 })\n * // => { apiKey: \"[redacted]\", nested: { token: \"[redacted]\" }, safe: 1 }\n * ```\n *\n * @category telemetry\n */\nexport const redact = (value: unknown): unknown => {\n return redactInner(value, new Set(), 0);\n};\n\n/**\n * Wraps an SDK-backed {@link Effect} with consistent\n * observability: increments {@link cursorOperationsStarted} at execution start,\n * increments {@link cursorOperationsFailed} on the error channel, and attaches\n * a span named `cursor.<operation>` (for example `cursor.agent.list`).\n *\n * The span name is stable and includes the {@link CursorOperation} tag space\n * so traces can be filtered consistently across agent, run, artifact, and\n * inspection APIs.\n *\n * @param operation - Logical SDK operation; must match {@link CursorOperation}\n * for typed error mapping and trace taxonomy.\n * @param effect - The effect produced by `Effect.tryPromise` (or similar)\n * around a single SDK call.\n * @returns The same effect type `Effect<A, E, R>` with metrics and span\n * attached; success and failure values are unchanged.\n *\n * @example\n * ```ts\n * import { Effect } from \"effect\"\n * import { instrument } from \"./cursor-telemetry\"\n *\n * const eff = instrument(\n * \"agent.get\",\n * Effect.tryPromise({\n * try: () => sdk.getAgent(id),\n * catch: (e) => e,\n * }),\n * )\n * ```\n *\n * @see {@link cursorOperationsStarted}\n * @see {@link cursorOperationsFailed}\n * @see {@link CursorOperation}\n *\n * @category telemetry\n */\nexport const instrument = <A, E, R>(\n operation: CursorOperation,\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<A, E, R> => {\n return effect.pipe(\n Effect.track(cursorOperationsStarted.pipe(Metric.withConstantInput(1))),\n Effect.tapError(() => {\n return Effect.track(Effect.void, cursorOperationsFailed.pipe(Metric.withConstantInput(1)));\n }),\n Effect.withSpan(`cursor.${operation}`),\n );\n};\n","import { Context, Effect, Layer, type Scope } from \"effect\";\n\nimport {\n CursorAgentBusyError,\n CursorAuthenticationError,\n CursorConfigurationError,\n CursorIntegrationNotConnectedError,\n CursorNetworkError,\n CursorRateLimitError,\n CursorUnknownError,\n mapCursorError,\n} from \"./cursor-error\";\nimport { agentOptionsFromConfig, type CursorConfig } from \"./cursor-config\";\nimport { CursorSdkFactory } from \"./cursor-sdk-factory\";\nimport { instrument } from \"./cursor-telemetry\";\nimport type {\n AgentOptions,\n Run,\n RunResult,\n SDKAgent,\n SDKUserMessage,\n SendOptions,\n} from \"./cursor-types\";\n\n/**\n * Agent lifecycle surface backed by the Cursor SDK.\n *\n * @remarks\n * Prefer {@link loadCursorConfig} with {@link CursorAgentServiceShape.createFromConfig},\n * {@link CursorAgentServiceShape.resumeFromConfig},\n * {@link CursorAgentServiceShape.promptFromConfig}, and\n * {@link CursorAgentServiceShape.scopedFromConfig}\n * so secrets stay in `Redacted` form until {@link agentOptionsFromConfig}\n * merges into SDK {@link AgentOptions}. Plain {@link AgentOptions} entry points\n * are deprecated; see `DEPRECATIONS.md` and the README at the package root.\n */\nexport interface CursorAgentServiceShape {\n /**\n * @deprecated Prefer {@link CursorAgentServiceShape.createFromConfig} with {@link loadCursorConfig}\n * instead of raw {@link AgentOptions} (including a plain `apiKey` string). Next major: `createFromConfig`\n * is planned to become `create` with the same parameters.\n */\n readonly create: (\n options: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * Create an agent from {@link CursorConfig} and optional SDK overrides.\n *\n * @remarks\n * Next major: planned rename to `create` with the same signature once plain-`AgentOptions` entry points are removed.\n *\n * @see {@link loadCursorConfig}\n * @see {@link agentOptionsFromConfig}\n */\n readonly createFromConfig: (\n config: CursorConfig,\n overrides?: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * @deprecated Prefer {@link CursorAgentServiceShape.resumeFromConfig} with {@link loadCursorConfig}\n * instead of raw {@link AgentOptions}. Next major: `resumeFromConfig` is planned to become `resume` with the same parameters.\n */\n readonly resume: (\n agentId: string,\n options?: Partial<AgentOptions>,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * Resume an agent from {@link CursorConfig} and optional SDK overrides.\n *\n * @remarks\n * Next major: planned rename to `resume` with the same signature once plain-`AgentOptions` entry points are removed.\n *\n * @see {@link loadCursorConfig}\n * @see {@link agentOptionsFromConfig}\n */\n readonly resumeFromConfig: (\n agentId: string,\n config: CursorConfig,\n overrides?: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * @deprecated Prefer {@link CursorAgentServiceShape.promptFromConfig} with {@link loadCursorConfig}\n * instead of raw {@link AgentOptions}. Next major: `promptFromConfig` is planned to become `prompt` with the same parameters.\n */\n readonly prompt: (\n message: string,\n options?: AgentOptions,\n ) => Effect.Effect<\n RunResult,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * One-shot prompt from {@link CursorConfig} and optional SDK overrides.\n *\n * @remarks\n * Next major: planned rename to `prompt` with the same signature once plain-`AgentOptions` entry points are removed.\n *\n * @see {@link loadCursorConfig}\n * @see {@link agentOptionsFromConfig}\n */\n readonly promptFromConfig: (\n message: string,\n config: CursorConfig,\n overrides?: AgentOptions,\n ) => Effect.Effect<\n RunResult,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly send: (\n agent: SDKAgent,\n message: string | SDKUserMessage,\n options?: SendOptions,\n ) => Effect.Effect<\n Run,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly reload: (\n agent: SDKAgent,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly close: (agent: SDKAgent) => Effect.Effect<void>;\n readonly dispose: (\n agent: SDKAgent,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n /**\n * @deprecated Prefer {@link CursorAgentServiceShape.scopedFromConfig} with {@link loadCursorConfig}\n * instead of raw {@link AgentOptions}. Next major: `scopedFromConfig` is planned to become `scoped` with the same parameters.\n */\n readonly scoped: (\n options: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError,\n Scope.Scope\n >;\n /**\n * Acquire an agent in a scope from {@link CursorConfig} and optional SDK overrides.\n *\n * @remarks\n * Next major: planned rename to `scoped` with the same signature once plain-`AgentOptions` entry points are removed.\n *\n * @see {@link loadCursorConfig}\n * @see {@link agentOptionsFromConfig}\n */\n readonly scopedFromConfig: (\n config: CursorConfig,\n overrides?: AgentOptions,\n ) => Effect.Effect<\n SDKAgent,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError,\n Scope.Scope\n >;\n}\n\n/**\n * Effect-native agent lifecycle and prompt service.\n *\n * The service wraps `Agent.create`, `Agent.resume`, `Agent.prompt`, and\n * instance lifecycle methods while preserving SDK-owned option and result\n * types.\n *\n * @example\n * ```ts\n * import { CursorAgentService, liveLayer, loadCursorConfig } from \"effect-cursor-sdk\"\n * import { Effect } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const agents = yield* CursorAgentService\n * const config = yield* loadCursorConfig\n * const agent = yield* agents.createFromConfig(config, {\n * model: { id: \"composer-2\" },\n * local: { cwd: process.cwd() },\n * })\n * return yield* agents.send(agent, \"Summarize this repository\")\n * }).pipe(Effect.provide(liveLayer))\n * ```\n *\n * @see {@link CursorRunService} for operations on returned `Run` handles.\n * @see {@link CursorSdkFactory} for replacing SDK construction in tests.\n *\n * @remarks\n * Prefer {@link CursorAgentServiceShape.createFromConfig} and related methods\n * with {@link loadCursorConfig}; raw {@link AgentOptions} on\n * {@link CursorAgentServiceShape.create} and siblings are deprecated.\n * See `DEPRECATIONS.md` at the package root for migration and planned next-major renames\n * (`createFromConfig` → `create`, etc.).\n *\n * @category services\n */\nexport class CursorAgentService extends Context.Service<\n CursorAgentService,\n CursorAgentServiceShape\n>()(\"effect-cursor-sdk/cursor-agent/CursorAgentService\") {\n static readonly Live = Layer.effect(CursorAgentService)(\n Effect.gen(function* () {\n const sdk = yield* CursorSdkFactory;\n\n const create = (options: AgentOptions) => {\n return instrument(\n \"agent.create\",\n Effect.tryPromise({\n try: () => sdk.create(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.create\" });\n },\n }),\n );\n };\n\n const resume = (agentId: string, options?: Partial<AgentOptions>) => {\n return instrument(\n \"agent.resume\",\n Effect.tryPromise({\n try: () => sdk.resume(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.resume\", agentId });\n },\n }),\n );\n };\n\n const prompt = (message: string, options?: AgentOptions) => {\n return instrument(\n \"agent.prompt\",\n Effect.tryPromise({\n try: () => sdk.prompt(message, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.prompt\" });\n },\n }),\n );\n };\n\n const send = (agent: SDKAgent, message: string | SDKUserMessage, options?: SendOptions) => {\n return instrument(\n \"agent.send\",\n Effect.tryPromise({\n try: () => agent.send(message, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.send\", agentId: agent.agentId });\n },\n }),\n );\n };\n\n const reload = (agent: SDKAgent) => {\n return instrument(\n \"agent.reload\",\n Effect.tryPromise({\n try: () => agent.reload(),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.reload\", agentId: agent.agentId });\n },\n }),\n );\n };\n\n const close = (agent: SDKAgent): Effect.Effect<void> => {\n return instrument(\n \"agent.close\",\n Effect.sync(() => agent.close()),\n );\n };\n\n const dispose = (agent: SDKAgent) => {\n return instrument(\n \"agent.dispose\",\n Effect.tryPromise({\n try: () => agent[Symbol.asyncDispose](),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.dispose\", agentId: agent.agentId });\n },\n }),\n );\n };\n\n const scoped = (options: AgentOptions) => {\n return Effect.acquireRelease(create(options), (agent) => {\n return Effect.ignore(dispose(agent));\n });\n };\n\n const createFromConfig = (config: CursorConfig, overrides: AgentOptions = {}) => {\n return create(agentOptionsFromConfig(config, overrides));\n };\n\n const resumeFromConfig = (\n agentId: string,\n config: CursorConfig,\n overrides: AgentOptions = {},\n ) => {\n return resume(agentId, agentOptionsFromConfig(config, overrides));\n };\n\n const promptFromConfig = (\n message: string,\n config: CursorConfig,\n overrides: AgentOptions = {},\n ) => {\n return prompt(message, agentOptionsFromConfig(config, overrides));\n };\n\n const scopedFromConfig = (config: CursorConfig, overrides: AgentOptions = {}) => {\n return scoped(agentOptionsFromConfig(config, overrides));\n };\n\n return {\n create,\n createFromConfig,\n resume,\n resumeFromConfig,\n prompt,\n promptFromConfig,\n send,\n reload,\n close,\n dispose,\n scoped,\n scopedFromConfig,\n } as const;\n }),\n );\n}\n","import { Context, Effect, Layer } from \"effect\";\n\nimport {\n CursorAgentBusyError,\n CursorAuthenticationError,\n CursorConfigurationError,\n CursorIntegrationNotConnectedError,\n CursorNetworkError,\n CursorRateLimitError,\n CursorUnknownError,\n mapCursorError,\n} from \"./cursor-error\";\nimport { instrument } from \"./cursor-telemetry\";\nimport type { SDKAgent, SDKArtifact } from \"./cursor-types\";\n\nexport interface CursorArtifactServiceShape {\n readonly listArtifacts: (\n agent: SDKAgent,\n ) => Effect.Effect<\n SDKArtifact[],\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly downloadArtifact: (\n agent: SDKAgent,\n path: string,\n ) => Effect.Effect<\n Buffer,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n}\n\n/**\n * Effect-native wrappers for agent artifacts.\n *\n * @example\n * ```ts\n * const artifacts = yield* CursorArtifactService\n * const items = yield* artifacts.listArtifacts(agent)\n * const bytes = yield* artifacts.downloadArtifact(agent, items[0]!.path)\n * ```\n *\n * @see {@link SDKArtifact}\n *\n * @category services\n */\nexport class CursorArtifactService extends Context.Service<\n CursorArtifactService,\n CursorArtifactServiceShape\n>()(\"effect-cursor-sdk/cursor-artifacts/CursorArtifactService\") {\n static readonly Live = Layer.succeed(CursorArtifactService)(\n CursorArtifactService.of({\n listArtifacts: (agent: SDKAgent) => {\n return instrument(\n \"artifacts.list\",\n Effect.tryPromise({\n try: () => agent.listArtifacts(),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"artifacts.list\", agentId: agent.agentId });\n },\n }),\n );\n },\n downloadArtifact: (agent: SDKAgent, path: string) => {\n return instrument(\n \"artifacts.download\",\n Effect.tryPromise({\n try: () => agent.downloadArtifact(path),\n catch: (cause) => {\n return mapCursorError(cause, {\n operation: \"artifacts.download\",\n agentId: agent.agentId,\n });\n },\n }),\n );\n },\n }),\n );\n}\n","import { Context, Effect, Layer } from \"effect\";\n\nimport {\n CursorAgentBusyError,\n CursorAuthenticationError,\n CursorConfigurationError,\n CursorIntegrationNotConnectedError,\n CursorNetworkError,\n CursorRateLimitError,\n CursorUnknownError,\n mapCursorError,\n} from \"./cursor-error\";\nimport { CursorSdkFactory } from \"./cursor-sdk-factory\";\nimport { instrument } from \"./cursor-telemetry\";\nimport type {\n AgentMessage,\n AgentOperationOptions,\n CursorRequestOptions,\n GetAgentMessagesOptions,\n GetAgentOptions,\n GetRunOptions,\n ListAgentsOptions,\n ListResult,\n ListRunsOptions,\n Run,\n SDKAgentInfo,\n SDKModel,\n SDKRepository,\n SDKUser,\n} from \"./cursor-types\";\n\nexport interface CursorInspectionServiceShape {\n readonly listAgents: (\n options?: ListAgentsOptions,\n ) => Effect.Effect<\n ListResult<SDKAgentInfo>,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly getAgent: (\n agentId: string,\n options?: GetAgentOptions,\n ) => Effect.Effect<\n SDKAgentInfo,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly archiveAgent: (\n agentId: string,\n options?: AgentOperationOptions,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly unarchiveAgent: (\n agentId: string,\n options?: AgentOperationOptions,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly deleteAgent: (\n agentId: string,\n options?: AgentOperationOptions,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly listRuns: (\n agentId: string,\n options?: ListRunsOptions,\n ) => Effect.Effect<\n ListResult<Run>,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly getRun: (\n runId: string,\n options?: GetRunOptions,\n ) => Effect.Effect<\n Run,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly listMessages: (\n agentId: string,\n options?: GetAgentMessagesOptions,\n ) => Effect.Effect<\n AgentMessage[],\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly me: (\n options?: CursorRequestOptions,\n ) => Effect.Effect<\n SDKUser,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly listModels: (\n options?: CursorRequestOptions,\n ) => Effect.Effect<\n SDKModel[],\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly listRepositories: (\n options?: CursorRequestOptions,\n ) => Effect.Effect<\n SDKRepository[],\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n}\n\n/**\n * Effect-native wrappers for SDK inspection, lifecycle, and account catalog APIs.\n *\n * @example\n * ```ts\n * const inspection = yield* CursorInspectionService\n * const agents = yield* inspection.listAgents({ runtime: \"cloud\", includeArchived: true })\n * const models = yield* inspection.listModels()\n * ```\n *\n * @see {@link CursorSdkFactory}\n * @see {@link SDKAgentInfo}\n *\n * @category services\n */\nexport class CursorInspectionService extends Context.Service<\n CursorInspectionService,\n CursorInspectionServiceShape\n>()(\"effect-cursor-sdk/cursor-inspection/CursorInspectionService\") {\n static readonly Live = Layer.effect(CursorInspectionService)(\n Effect.gen(function* () {\n const sdk = yield* CursorSdkFactory;\n return {\n listAgents: (options?: ListAgentsOptions) => {\n return instrument(\n \"agent.list\",\n Effect.tryPromise({\n try: () => sdk.listAgents(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.list\" });\n },\n }),\n );\n },\n getAgent: (agentId: string, options?: GetAgentOptions) => {\n return instrument(\n \"agent.get\",\n Effect.tryPromise({\n try: () => sdk.getAgent(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.get\", agentId });\n },\n }),\n );\n },\n archiveAgent: (agentId: string, options?: AgentOperationOptions) => {\n return instrument(\n \"agent.archive\",\n Effect.tryPromise({\n try: () => sdk.archiveAgent(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.archive\", agentId });\n },\n }),\n );\n },\n unarchiveAgent: (agentId: string, options?: AgentOperationOptions) => {\n return instrument(\n \"agent.unarchive\",\n Effect.tryPromise({\n try: () => sdk.unarchiveAgent(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.unarchive\", agentId });\n },\n }),\n );\n },\n deleteAgent: (agentId: string, options?: AgentOperationOptions) => {\n return instrument(\n \"agent.delete\",\n Effect.tryPromise({\n try: () => sdk.deleteAgent(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"agent.delete\", agentId });\n },\n }),\n );\n },\n listRuns: (agentId: string, options?: ListRunsOptions) => {\n return instrument(\n \"run.list\",\n Effect.tryPromise({\n try: () => sdk.listRuns(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"run.list\", agentId });\n },\n }),\n );\n },\n getRun: (runId: string, options?: GetRunOptions) => {\n return instrument(\n \"run.get\",\n Effect.tryPromise({\n try: () => sdk.getRun(runId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"run.get\", runId });\n },\n }),\n );\n },\n listMessages: (agentId: string, options?: GetAgentMessagesOptions) => {\n return instrument(\n \"messages.list\",\n Effect.tryPromise({\n try: () => sdk.listMessages(agentId, options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"messages.list\", agentId });\n },\n }),\n );\n },\n me: (options?: CursorRequestOptions) => {\n return instrument(\n \"cursor.me\",\n Effect.tryPromise({\n try: () => sdk.me(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"cursor.me\" });\n },\n }),\n );\n },\n listModels: (options?: CursorRequestOptions) => {\n return instrument(\n \"cursor.models.list\",\n Effect.tryPromise({\n try: () => sdk.listModels(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"cursor.models.list\" });\n },\n }),\n );\n },\n listRepositories: (options?: CursorRequestOptions) => {\n return instrument(\n \"cursor.repositories.list\",\n Effect.tryPromise({\n try: () => sdk.listRepositories(options),\n catch: (cause) => {\n return mapCursorError(cause, { operation: \"cursor.repositories.list\" });\n },\n }),\n );\n },\n } as const;\n }),\n );\n}\n","import { Layer } from \"effect\";\n\nimport { CursorSdkFactory } from \"./cursor-sdk-factory\";\nimport type {\n AgentMessage,\n AgentOperationOptions,\n AgentOptions,\n CursorRequestOptions,\n GetAgentMessagesOptions,\n GetAgentOptions,\n GetRunOptions,\n ListAgentsOptions,\n ListResult,\n ListRunsOptions,\n Run,\n RunOperation,\n RunResult,\n RunStatus,\n SDKAgent,\n SDKAgentInfo,\n SDKArtifact,\n SDKMessage,\n SDKModel,\n SDKRepository,\n SDKUser,\n SDKUserMessage,\n SendOptions,\n} from \"./cursor-types\";\n\n/**\n * Fixture data used by the deterministic mock SDK layer.\n *\n * @example\n * ```ts\n * const fixtures: CursorMockFixtures = {\n * stream: [assistantEvent],\n * result: { id: \"run-1\", status: \"finished\", result: \"Done\" }\n * }\n * ```\n *\n * @see {@link mockLayer}\n * @see {@link makeMockSdkFactoryLayer}\n * @category testing\n */\nexport type CursorMockFactoryMethod =\n | \"create\"\n | \"resume\"\n | \"prompt\"\n | \"listAgents\"\n | \"listRuns\"\n | \"getRun\"\n | \"getAgent\"\n | \"archiveAgent\"\n | \"unarchiveAgent\"\n | \"deleteAgent\"\n | \"listMessages\"\n | \"me\"\n | \"listModels\"\n | \"listRepositories\";\n\nexport interface CursorMockFixtures {\n readonly agentId?: string;\n readonly runId?: string;\n readonly stream?: ReadonlyArray<SDKMessage>;\n readonly result?: RunResult;\n readonly artifacts?: ReadonlyArray<SDKArtifact>;\n readonly artifactData?: Buffer;\n readonly agents?: ReadonlyArray<SDKAgentInfo>;\n readonly messages?: ReadonlyArray<AgentMessage>;\n readonly models?: ReadonlyArray<SDKModel>;\n readonly repositories?: ReadonlyArray<SDKRepository>;\n readonly user?: SDKUser;\n /**\n * Per-`send` merged fixtures. Each `MockCursorAgent.send` increments the index;\n * when exhausted, further sends reuse the last entry merged with the base fixtures.\n */\n readonly sendSequence?: ReadonlyArray<Partial<CursorMockFixtures>>;\n /**\n * Reject a factory method with this error (Promise rejection).\n */\n readonly factoryErrors?: Partial<Record<CursorMockFactoryMethod, unknown>>;\n /** Override {@link Run.supports} per operation. */\n readonly runSupports?: Partial<Record<RunOperation, boolean>>;\n /** Override unsupported reasons for operations marked false in {@link runSupports}. */\n readonly runUnsupportedReason?: Partial<Record<RunOperation, string>>;\n}\n\n/**\n * Deterministic SDK `Run` implementation for tests.\n *\n * @param streamEvents - Events yielded by {@link MockCursorRun.stream}.\n * @param waitResult - Result returned by {@link MockCursorRun.wait}.\n *\n * @example\n * ```ts\n * const run = new MockCursorRun([assistantEvent], {\n * id: \"run-1\",\n * status: \"finished\",\n * result: \"Done\"\n * })\n * ```\n *\n * @see {@link makeMockRun}\n * @category testing\n */\nexport class MockCursorRun implements Run {\n readonly id: string;\n readonly agentId: string;\n readonly createdAt = Date.now();\n #status: RunStatus;\n #listeners = new Set<(status: RunStatus) => void>();\n\n constructor(\n readonly streamEvents: ReadonlyArray<SDKMessage>,\n readonly waitResult: RunResult,\n readonly behavior?: {\n readonly supports?: Partial<Record<RunOperation, boolean>>;\n readonly unsupportedReason?: Partial<Record<RunOperation, string>>;\n },\n ) {\n this.id = waitResult.id;\n this.agentId = streamEvents[0]?.agent_id ?? \"mock-agent\";\n this.#status = waitResult.status;\n }\n\n get status(): RunStatus {\n return this.#status;\n }\n get result(): string | undefined {\n return this.waitResult.result;\n }\n get model(): RunResult[\"model\"] {\n return this.waitResult.model;\n }\n get durationMs(): number | undefined {\n return this.waitResult.durationMs;\n }\n get git(): RunResult[\"git\"] {\n return this.waitResult.git;\n }\n supports(operation: RunOperation): boolean {\n const override = this.behavior?.supports?.[operation];\n return override !== undefined ? override : true;\n }\n unsupportedReason(operation: RunOperation): string | undefined {\n if (this.supports(operation)) return undefined;\n return this.behavior?.unsupportedReason?.[operation] ?? \"unsupported in mock\";\n }\n async *stream(): AsyncGenerator<SDKMessage, void> {\n yield* this.streamEvents;\n }\n async conversation(): Promise<[]> {\n return [];\n }\n async wait(): Promise<RunResult> {\n return this.waitResult;\n }\n async cancel(): Promise<void> {\n this.#status = \"cancelled\";\n for (const listener of this.#listeners) listener(this.#status);\n }\n onDidChangeStatus(listener: (status: RunStatus) => void): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n}\n\n/**\n * Deterministic SDK `Agent` implementation for tests.\n *\n * @param fixtures - Static data used by `send`, artifact methods, and metadata methods.\n *\n * @example\n * ```ts\n * const agent = new MockCursorAgent({ result: { id: \"run-1\", status: \"finished\" } })\n * const run = await agent.send(\"hello\")\n * ```\n *\n * @see {@link makeMockAgent}\n * @see {@link CursorMockFixtures}\n * @category testing\n */\nexport class MockCursorAgent implements SDKAgent {\n readonly agentId: string;\n readonly runs: Run[] = [];\n closed = false;\n #sendIndex = 0;\n\n constructor(readonly fixtures: CursorMockFixtures = {}) {\n this.agentId = fixtures.agentId ?? \"mock-agent\";\n }\n\n get model(): AgentOptions[\"model\"] | undefined {\n return this.fixtures.result?.model;\n }\n\n async send(_message: string | SDKUserMessage, _options?: SendOptions): Promise<Run> {\n const seq = this.fixtures.sendSequence;\n const piece =\n seq === undefined ? undefined : seq[Math.min(this.#sendIndex, Math.max(seq.length - 1, 0))];\n const merged: CursorMockFixtures =\n piece !== undefined ? { ...this.fixtures, ...piece } : this.fixtures;\n if (seq !== undefined) this.#sendIndex++;\n const run = makeMockRun(merged);\n this.runs.push(run);\n return run;\n }\n close(): void {\n this.closed = true;\n }\n async reload(): Promise<void> {}\n async [Symbol.asyncDispose](): Promise<void> {\n this.closed = true;\n }\n async listArtifacts(): Promise<SDKArtifact[]> {\n return [...(this.fixtures.artifacts ?? [])];\n }\n async downloadArtifact(_path: string): Promise<Buffer> {\n return this.fixtures.artifactData ?? Buffer.from(\"\");\n }\n}\n\n/**\n * Create a mock run from fixtures.\n *\n * @param fixtures - Optional mock run and stream data.\n *\n * @see {@link MockCursorRun}\n * @category testing\n */\nexport const makeMockRun = (fixtures: CursorMockFixtures = {}): MockCursorRun => {\n const runId = fixtures.runId ?? \"mock-run\";\n return new MockCursorRun(\n fixtures.stream ?? [],\n fixtures.result ?? { id: runId, status: \"finished\", result: \"\" },\n {\n supports: fixtures.runSupports,\n unsupportedReason: fixtures.runUnsupportedReason,\n },\n );\n};\n\n/**\n * Create a mock agent from fixtures.\n *\n * @param fixtures - Optional mock agent, run, artifact, and metadata data.\n *\n * @see {@link MockCursorAgent}\n * @category testing\n */\nexport const makeMockAgent = (fixtures: CursorMockFixtures = {}): MockCursorAgent => {\n return new MockCursorAgent(fixtures);\n};\n\n/**\n * Minimal assistant {@link SDKMessage} for streaming tests.\n *\n * @category testing\n */\nexport const makeMockAssistantSdkMessage = (\n text: string,\n ids: { readonly agentId?: string; readonly runId?: string } = {},\n): SDKMessage => {\n return {\n type: \"assistant\",\n agent_id: ids.agentId ?? \"mock-agent\",\n run_id: ids.runId ?? \"mock-run\",\n message: {\n role: \"assistant\",\n content: [{ type: \"text\", text }],\n },\n };\n};\n\nconst rejectFactory = (\n fixtures: CursorMockFixtures,\n method: CursorMockFactoryMethod,\n): Promise<never> | undefined => {\n const err = fixtures.factoryErrors?.[method];\n if (err !== undefined) return Promise.reject(err);\n return undefined;\n};\n\n/**\n * Layer replacing the SDK factory with deterministic mock behavior.\n *\n * This is the lowest-level mock entry point. Prefer {@link mockLayer} when you\n * want all higher-level services wired together for tests.\n *\n * @param fixtures - Static SDK responses returned by the factory methods.\n *\n * @example\n * ```ts\n * const layer = makeMockSdkFactoryLayer({\n * agents: [{ agentId: \"mock-agent\", name: \"Mock\", summary: \"Test\", lastModified: 0 }]\n * })\n * ```\n *\n * @see {@link CursorSdkFactory}\n * @see {@link mockLayer}\n * @category testing\n */\nexport const makeMockSdkFactoryLayer = (fixtures: CursorMockFixtures = {}) => {\n return Layer.succeed(\n CursorSdkFactory,\n CursorSdkFactory.of({\n create: (_options: AgentOptions): Promise<SDKAgent> => {\n const early = rejectFactory(fixtures, \"create\");\n return early ?? Promise.resolve(makeMockAgent(fixtures));\n },\n resume: (_agentId: string, _options?: Partial<AgentOptions>): Promise<SDKAgent> => {\n const early = rejectFactory(fixtures, \"resume\");\n return early ?? Promise.resolve(makeMockAgent(fixtures));\n },\n prompt: async (_message: string, _options?: AgentOptions): Promise<RunResult> => {\n const early = rejectFactory(fixtures, \"prompt\");\n if (early) return early;\n return (\n fixtures.result ?? { id: fixtures.runId ?? \"mock-run\", status: \"finished\", result: \"\" }\n );\n },\n listAgents: async (_options?: ListAgentsOptions): Promise<ListResult<SDKAgentInfo>> => {\n const early = rejectFactory(fixtures, \"listAgents\");\n if (early) return early;\n return { items: [...(fixtures.agents ?? [])] };\n },\n listRuns: async (_agentId: string, _options?: ListRunsOptions): Promise<ListResult<Run>> => {\n const early = rejectFactory(fixtures, \"listRuns\");\n if (early) return early;\n return { items: [makeMockRun(fixtures)] };\n },\n getRun: async (_runId: string, _options?: GetRunOptions): Promise<Run> => {\n const early = rejectFactory(fixtures, \"getRun\");\n if (early) return early;\n return makeMockRun(fixtures);\n },\n getAgent: async (_agentId: string, _options?: GetAgentOptions): Promise<SDKAgentInfo> => {\n const early = rejectFactory(fixtures, \"getAgent\");\n if (early) return early;\n return (\n fixtures.agents?.[0] ?? {\n agentId: fixtures.agentId ?? \"mock-agent\",\n name: \"Mock Agent\",\n summary: \"Deterministic mock agent\",\n lastModified: 0,\n }\n );\n },\n archiveAgent: async (_agentId: string, _options?: AgentOperationOptions): Promise<void> => {\n const early = rejectFactory(fixtures, \"archiveAgent\");\n if (early) return early;\n },\n unarchiveAgent: async (_agentId: string, _options?: AgentOperationOptions): Promise<void> => {\n const early = rejectFactory(fixtures, \"unarchiveAgent\");\n if (early) return early;\n },\n deleteAgent: async (_agentId: string, _options?: AgentOperationOptions): Promise<void> => {\n const early = rejectFactory(fixtures, \"deleteAgent\");\n if (early) return early;\n },\n listMessages: async (\n _agentId: string,\n _options?: GetAgentMessagesOptions,\n ): Promise<AgentMessage[]> => {\n const early = rejectFactory(fixtures, \"listMessages\");\n if (early) return early;\n return [...(fixtures.messages ?? [])];\n },\n me: async (_options?: CursorRequestOptions): Promise<SDKUser> => {\n const early = rejectFactory(fixtures, \"me\");\n if (early) return early;\n return fixtures.user ?? { apiKeyName: \"mock\", createdAt: \"1970-01-01T00:00:00.000Z\" };\n },\n listModels: async (_options?: CursorRequestOptions): Promise<SDKModel[]> => {\n const early = rejectFactory(fixtures, \"listModels\");\n if (early) return early;\n return [...(fixtures.models ?? [])];\n },\n listRepositories: async (_options?: CursorRequestOptions): Promise<SDKRepository[]> => {\n const early = rejectFactory(fixtures, \"listRepositories\");\n if (early) return early;\n return [...(fixtures.repositories ?? [])];\n },\n }),\n );\n};\n","/**\n * Reusable observability helpers: stream metrics, retry schedules, and safe summaries.\n *\n * @example\n * ```ts\n * import {\n * cursorCatalogLoadTimeout,\n * cursorCatalogRetrySchedule,\n * CursorInspectionService,\n * liveLayer,\n * } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const catalog = Effect.gen(function* () {\n * const inspection = yield* CursorInspectionService;\n * return yield* Effect.all(\n * { agents: inspection.listAgents({ runtime: \"cloud\" }), models: inspection.listModels() },\n * { concurrency: \"unbounded\" },\n * ).pipe(Effect.retry(cursorCatalogRetrySchedule), Effect.timeout(cursorCatalogLoadTimeout));\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @module\n */\nimport { Effect, Metric, Schedule, Stream } from \"effect\";\n\nimport type { CursorStreamError } from \"./cursor-error\";\nimport { redact } from \"./cursor-telemetry\";\nimport { cursorStreamEvents } from \"./cursor-telemetry\";\nimport type { AgentOptions, Run, SDKMessage } from \"./cursor-types\";\n\n/**\n * Default exponential retry for Cursor catalog-style calls (list agents, models, repos).\n *\n * Matches the pattern used in the advanced ops dashboard example: 150ms base, 3 attempts.\n *\n * @example\n * ```ts\n * import { CursorInspectionService, cursorCatalogRetrySchedule, liveLayer } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const program = Effect.gen(function* () {\n * const inspection = yield* CursorInspectionService;\n * return yield* inspection.listModels().pipe(Effect.retry(cursorCatalogRetrySchedule));\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @category observability\n */\nexport const cursorCatalogRetrySchedule = Schedule.exponential(\"150 millis\").pipe(\n Schedule.both(Schedule.recurs(3)),\n);\n\n/**\n * Default timeout for parallel catalog loads.\n *\n * @example\n * ```ts\n * import { CursorInspectionService, cursorCatalogLoadTimeout, liveLayer } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const program = Effect.gen(function* () {\n * const inspection = yield* CursorInspectionService;\n * return yield* Effect.all(\n * { user: inspection.me(), models: inspection.listModels() },\n * { concurrency: \"unbounded\" },\n * ).pipe(Effect.timeout(cursorCatalogLoadTimeout));\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @category observability\n */\nexport const cursorCatalogLoadTimeout = \"45 seconds\" as const;\n\n/**\n * Append assistant-visible text from a streamed {@link SDKMessage} (same rules as {@link CursorRunService.collectText}).\n *\n * @example\n * ```ts\n * import { appendAssistantSdkMessageText } from \"effect-cursor-sdk\";\n * import type { SDKMessage } from \"effect-cursor-sdk\";\n *\n * const events: SDKMessage[] = []; // from run.stream()\n * const text = events.reduce(appendAssistantSdkMessageText, \"\");\n * ```\n *\n * @category observability\n */\nexport const appendAssistantSdkMessageText = (text: string, event: SDKMessage): string => {\n if (event.type !== \"assistant\") return text;\n return (\n text +\n event.message.content\n .filter((block) => {\n return block.type === \"text\";\n })\n .map((block) => {\n return block.text;\n })\n .join(\"\")\n );\n};\n\n/**\n * Wraps a run event stream and increments {@link cursorStreamEvents} per emitted event.\n *\n * @example\n * ```ts\n * import { CursorRunService, streamEventsTracked, liveLayer } from \"effect-cursor-sdk\";\n * import { Effect, Stream } from \"effect\";\n * import type { Run } from \"effect-cursor-sdk\";\n *\n * declare const run: Run;\n *\n * const program = Effect.gen(function* () {\n * const runs = yield* CursorRunService;\n * yield* streamEventsTracked(runs.streamEvents(run)).pipe(Stream.runDrain);\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @category observability\n */\nexport const streamEventsTracked = <E>(\n stream: Stream.Stream<E, CursorStreamError>,\n): Stream.Stream<E, CursorStreamError> => {\n return stream.pipe(\n Stream.tap(() =>\n Effect.void.pipe(Effect.trackSuccesses(cursorStreamEvents.pipe(Metric.withConstantInput(1)))),\n ),\n );\n};\n\n/**\n * Like {@link CursorRunService.collectText}, but increments {@link cursorStreamEvents} per stream chunk.\n *\n * @param run - SDK run handle.\n * @param streamEvents - Typically `runs.streamEvents` from {@link CursorRunService}.\n *\n * @example\n * ```ts\n * import { collectTextTracked, CursorRunService, liveLayer } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n * import type { Run } from \"effect-cursor-sdk\";\n *\n * declare const run: Run;\n *\n * const text = Effect.gen(function* () {\n * const runs = yield* CursorRunService;\n * return yield* collectTextTracked(run, (r) => runs.streamEvents(r));\n * }).pipe(Effect.provide(liveLayer));\n * ```\n *\n * @category observability\n */\nexport const collectTextTracked = (\n run: Run,\n streamEvents: (r: Run) => Stream.Stream<SDKMessage, CursorStreamError>,\n): Effect.Effect<string, CursorStreamError> => {\n return streamEventsTracked(streamEvents(run)).pipe(\n Stream.runFold(() => \"\", appendAssistantSdkMessageText),\n );\n};\n\n/**\n * Build a redacted, log-safe summary of {@link AgentOptions} **without** an API key value.\n *\n * @remarks\n * Nested structures are passed through {@link redact}. Never log raw `apiKey`.\n *\n * @example\n * ```ts\n * import { summarizeAgentOptionsForLog } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const program = Effect.gen(function* () {\n * const options = { model: { id: \"composer-2\" }, apiKey: \"secret\" };\n * yield* Effect.logInfo(\"cursor run\", summarizeAgentOptionsForLog(options));\n * });\n * ```\n *\n * @category observability\n */\nexport const summarizeAgentOptionsForLog = (options: AgentOptions): Record<string, unknown> => {\n const mcpKeys = options.mcpServers ? Object.keys(options.mcpServers) : undefined;\n return redact({\n model: options.model,\n name: options.name,\n agentId: options.agentId,\n local: options.local,\n cloud: options.cloud\n ? {\n reposCount: options.cloud.repos?.length,\n autoCreatePR: options.cloud.autoCreatePR,\n workOnCurrentBranch: options.cloud.workOnCurrentBranch,\n envType: options.cloud.env?.type,\n }\n : undefined,\n mcpServerNames: mcpKeys,\n agentsCount: options.agents ? Object.keys(options.agents).length : undefined,\n }) as Record<string, unknown>;\n};\n\n/**\n * Attach minimal run identifiers for structured logs or span attributes.\n *\n * @example\n * ```ts\n * import { summarizeRunForLog } from \"effect-cursor-sdk\";\n * import { Effect } from \"effect\";\n *\n * const program = Effect.gen(function* () {\n * const run = { id: \"run_1\", agentId: \"agt_1\", status: \"finished\" as const };\n * yield* Effect.logDebug(\"run done\", summarizeRunForLog(run));\n * });\n * ```\n *\n * @category observability\n */\nexport const summarizeRunForLog = (run: {\n readonly id: string;\n readonly agentId: string;\n readonly status?: string;\n}): Record<string, unknown> => {\n return {\n runId: run.id,\n agentId: run.agentId,\n status: run.status,\n };\n};\n","import { Context, Effect, Layer, Stream } from \"effect\";\n\nimport {\n CursorAgentBusyError,\n CursorAuthenticationError,\n CursorConfigurationError,\n CursorIntegrationNotConnectedError,\n CursorNetworkError,\n CursorRateLimitError,\n CursorStreamError,\n CursorUnknownError,\n CursorUnsupportedOperationError,\n mapCursorError,\n} from \"./cursor-error\";\nimport { instrument } from \"./cursor-telemetry\";\nimport type { Run, RunOperation, RunResult, RunStatus, SDKMessage } from \"./cursor-types\";\n\nexport interface CursorRunServiceShape {\n readonly supports: (run: Run, operation: RunOperation) => boolean;\n readonly unsupportedReason: (run: Run, operation: RunOperation) => string | undefined;\n readonly wait: (\n run: Run,\n ) => Effect.Effect<\n RunResult,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnknownError\n >;\n readonly cancel: (\n run: Run,\n ) => Effect.Effect<\n void,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnsupportedOperationError\n | CursorUnknownError\n >;\n readonly conversation: (\n run: Run,\n ) => ReturnType<Run[\"conversation\"]> extends Promise<infer A>\n ? Effect.Effect<\n A,\n | CursorAuthenticationError\n | CursorRateLimitError\n | CursorIntegrationNotConnectedError\n | CursorConfigurationError\n | CursorAgentBusyError\n | CursorNetworkError\n | CursorUnsupportedOperationError\n | CursorUnknownError\n >\n : never;\n readonly streamEvents: (run: Run) => Stream.Stream<SDKMessage, CursorStreamError>;\n readonly collectText: (run: Run) => Effect.Effect<string, CursorStreamError>;\n readonly onDidChangeStatus: (\n run: Run,\n listener: (status: RunStatus) => void,\n ) => Effect.Effect<() => void>;\n /**\n * Status updates as a stream (backed by {@link Run.onDidChangeStatus}).\n *\n * @example\n * ```ts\n *\n * ```\n */\n readonly streamStatusChanges: (run: Run) => Stream.Stream<RunStatus, never, never>;\n}\n\n/**\n * Effect-native helpers for SDK run handles.\n *\n * @example\n * ```ts\n * const runService = yield* CursorRunService;\n *\n * // Create a run with the agent service\n * const run = yield* agents.send(agent, \"Refactor auth\")\n *\n * // Use the run service with the created run\n * const conversation = yield* runService.conversation(run);\n * ```\n *\n * @see {@link CursorAgentService} for creating and sending runs.\n * @see {@link SDKMessage} for the SDK-owned stream event shape.\n *\n * @category services\n */\nexport class CursorRunService extends Context.Service<CursorRunService, CursorRunServiceShape>()(\n \"effect-cursor-sdk/cursor-run/CursorRunService\",\n) {\n static readonly Live = Layer.succeed(CursorRunService)(\n CursorRunService.of({\n supports: (run: Run, operation: RunOperation): boolean => {\n return run.supports(operation);\n },\n unsupportedReason: (run: Run, operation: RunOperation): string | undefined => {\n return run.unsupportedReason(operation);\n },\n wait: (run: Run) => {\n return instrument(\n \"run.wait\",\n Effect.tryPromise({\n try: () => run.wait(),\n catch: (cause) => {\n return mapCursorError(cause, {\n operation: \"run.wait\",\n agentId: run.agentId,\n runId: run.id,\n });\n },\n }),\n );\n },\n cancel: (run: Run) => {\n return instrument(\n \"run.cancel\",\n Effect.tryPromise({\n try: () => run.cancel(),\n catch: (cause) => {\n return mapCursorError(cause, {\n operation: \"run.cancel\",\n agentId: run.agentId,\n runId: run.id,\n });\n },\n }),\n );\n },\n conversation: (run: Run) => {\n return instrument(\n \"run.conversation\",\n Effect.tryPromise({\n try: () => run.conversation(),\n catch: (cause) => {\n return mapCursorError(cause, {\n operation: \"run.conversation\",\n agentId: run.agentId,\n runId: run.id,\n });\n },\n }),\n );\n },\n streamEvents: (run: Run): Stream.Stream<SDKMessage, CursorStreamError> => {\n return Stream.fromAsyncIterable(run.stream(), (cause) => {\n return mapCursorError(cause, {\n operation: \"run.stream\",\n agentId: run.agentId,\n runId: run.id,\n }) as CursorStreamError;\n });\n },\n onDidChangeStatus: (\n run: Run,\n listener: (status: RunStatus) => void,\n ): Effect.Effect<() => void> => {\n return Effect.sync(() => run.onDidChangeStatus(listener));\n },\n streamStatusChanges: (run: Run): Stream.Stream<RunStatus, never, never> => {\n return Stream.fromAsyncIterable(\n (async function* (): AsyncGenerator<RunStatus> {\n const pending: RunStatus[] = [];\n let notify: (() => void) | undefined;\n const unsub = run.onDidChangeStatus((status) => {\n pending.push(status);\n const resume = notify;\n notify = undefined;\n resume?.();\n });\n try {\n while (true) {\n if (pending.length > 0) {\n yield pending.shift()!;\n continue;\n }\n await new Promise<void>((resolve) => {\n notify = resolve;\n });\n }\n } finally {\n unsub();\n }\n })(),\n () => undefined as never,\n );\n },\n collectText: (run: Run): Effect.Effect<string, CursorStreamError> => {\n return Stream.fromAsyncIterable(run.stream(), (cause) => {\n return mapCursorError(cause, {\n operation: \"run.stream\",\n agentId: run.agentId,\n runId: run.id,\n }) as CursorStreamError;\n }).pipe(\n Stream.runFold(\n () => \"\",\n (text, event) => {\n if (event.type !== \"assistant\") return text;\n return (\n text +\n event.message.content\n .filter((block) => {\n return block.type === \"text\";\n })\n .map((block) => {\n return block.text;\n })\n .join(\"\")\n );\n },\n ),\n );\n },\n }),\n );\n}\n","import { Layer, ManagedRuntime } from \"effect\";\n\nimport { CursorAgentService } from \"./cursor-agent\";\nimport { CursorArtifactService } from \"./cursor-artifacts\";\nimport { CursorInspectionService } from \"./cursor-inspection\";\nimport { makeMockSdkFactoryLayer, type CursorMockFixtures } from \"./cursor-mock\";\nimport { CursorRunService } from \"./cursor-run\";\nimport { CursorSdkFactory } from \"./cursor-sdk-factory\";\n\n/**\n * Live service layer for the SDK-backed Effect wrapper.\n *\n * Provides {@link CursorAgentService}, {@link CursorRunService},\n * {@link CursorArtifactService}, and {@link CursorInspectionService} using\n * {@link CursorSdkFactory.Live}.\n *\n * @example\n * ```ts\n * const result = yield* program.pipe(Effect.provide(liveLayer))\n * ```\n *\n * @see {@link CursorSdkFactory}\n * @see {@link liveRuntime}\n *\n * @category layers\n */\nexport const liveLayer = Layer.mergeAll(\n CursorAgentService.Live,\n CursorRunService.Live,\n CursorArtifactService.Live,\n CursorInspectionService.Live,\n).pipe(Layer.provideMerge(CursorSdkFactory.Live));\n\n/**\n * Deterministic mock layer for tests and examples.\n *\n * @param fixtures - Static SDK responses returned by the mock factory.\n *\n * @example\n * ```ts\n * const layer = mockLayer({\n * result: { id: \"run-1\", status: \"finished\", result: \"ok\" }\n * })\n * ```\n *\n * @see {@link CursorMockFixtures}\n * @see {@link makeMockSdkFactoryLayer}\n *\n * @category layers\n */\nexport const mockLayer = (fixtures: CursorMockFixtures = {}) => {\n return Layer.mergeAll(\n CursorAgentService.Live,\n CursorRunService.Live,\n CursorArtifactService.Live,\n CursorInspectionService.Live,\n ).pipe(Layer.provideMerge(makeMockSdkFactoryLayer(fixtures)));\n};\n\n/**\n * Ready-made live runtime.\n *\n * Use this for small scripts that prefer `ManagedRuntime.runPromise` over\n * manually providing {@link liveLayer}.\n *\n * @example\n * ```ts\n * const value = await liveRuntime.runPromise(program)\n * ```\n *\n * @see {@link liveLayer}\n *\n * @category runtimes\n */\nexport const liveRuntime = ManagedRuntime.make(liveLayer);\n\n/**\n * Ready-made mock runtime.\n *\n * @param fixtures - Static SDK responses returned by the mock services.\n *\n * @example\n * ```ts\n * const runtime = makeMockRuntime({ result: { id: \"run-1\", status: \"finished\" } })\n * const value = await runtime.runPromise(program)\n * ```\n *\n * @see {@link mockLayer}\n * @see {@link CursorMockFixtures}\n *\n * @category runtimes\n */\nexport const makeMockRuntime = (fixtures: CursorMockFixtures = {}) => {\n return ManagedRuntime.make(mockLayer(fixtures));\n};\n","/**\n * Public package name.\n *\n * @category metadata\n */\nexport const packageName = \"effect-cursor-sdk\";\n\nexport * from \"./cursor-agent\";\nexport * from \"./cursor-artifacts\";\nexport * from \"./cursor-config\";\nexport * from \"./cursor-error\";\nexport * from \"./cursor-inspection\";\nexport * from \"./cursor-mock\";\nexport * from \"./cursor-observability\";\nexport * from \"./cursor-run\";\nexport * from \"./cursor-runtime\";\nexport * from \"./cursor-sdk-factory\";\nexport * from \"./cursor-telemetry\";\nexport * from \"./cursor-types\";\n"],"mappings":"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"}
@@ -48,7 +48,7 @@ Mark each row when verified against the **pinned** SDK version in root [`package
48
48
 
49
49
  ### Re-exported from `cursor-types`
50
50
 
51
- Helpers and errors such as `AuthenticationError`, local run stream decoders, `createAgentPlatform`, etc. See [`src/cursor-types.ts`](../src/cursor-types.ts). New SDK exports are **not** automatic: add them here deliberately to avoid semver surprises.
51
+ Helpers and errors such as `AuthenticationError`, `AgentBusyError`, local run stream decoders, `createAgentPlatform`, etc. See [`src/cursor-types.ts`](../src/cursor-types.ts). New SDK exports are **not** automatic: add them here deliberately to avoid semver surprises.
52
52
 
53
53
  ## Optional audit script
54
54
 
@@ -0,0 +1,124 @@
1
+ # Changeset Agent
2
+
3
+ The changeset agent is a repository automation pattern built with `effect-cursor-sdk`: when a pull request against `main` is opened or updated, GitHub Actions starts a local Cursor SDK agent in the PR checkout and asks it to create a missing Changesets release note.
4
+
5
+ This is not part of the published library API. It is an executable example of using the package itself to automate a focused maintainer task.
6
+
7
+ ## What It Solves
8
+
9
+ This repository uses Changesets for versioning. Any user-facing source or documentation change should usually include a `.changeset/*.md` file so the release workflow can produce the correct package version and changelog entry.
10
+
11
+ The agent reduces reviewer overhead by handling the common case:
12
+
13
+ - A PR changes package behavior or public docs.
14
+ - The author forgot to add a changeset.
15
+ - CI asks Cursor to inspect the diff and add one concise release note.
16
+ - The workflow commits only `.changeset` changes back to the PR branch.
17
+
18
+ Manual changesets still win. If a PR already changes `.changeset/*.md`, the agent exits without adding another file.
19
+
20
+ ## Moving Parts
21
+
22
+ The feature has three pieces:
23
+
24
+ - `.github/workflows/changeset-agent.yml` runs on `pull_request` events targeting `main`.
25
+ - `scripts/create-changeset-agent.ts` contains the Effect program that starts and prompts Cursor.
26
+ - `bun run changeset:agent` is the package script used by CI and local maintainers.
27
+
28
+ The workflow provides repository context and write permissions. The script owns the agent lifecycle and release-note decision. The commit step stages only `.changeset`, so even if the agent reports extra commentary, only release-note files can be committed by the job.
29
+
30
+ ## Event Flow
31
+
32
+ 1. A same-repository PR is opened, reopened, synchronized, or marked ready for review against `main`.
33
+ 2. GitHub Actions checks out the PR head branch with full history.
34
+ 3. Bun installs dependencies with the lockfile.
35
+ 4. `bun run changeset:agent` runs `scripts/create-changeset-agent.ts`.
36
+ 5. The script compares `origin/main...HEAD` and exits early if the PR already includes a changeset.
37
+ 6. The script creates a scoped local Cursor agent using `CursorAgentService`.
38
+ 7. The agent receives a constrained prompt that allows exactly one `.changeset/*.md` file when release impact exists.
39
+ 8. The script logs the agent response and reports whether a new changeset appeared.
40
+ 9. The workflow commits and pushes only `.changeset` changes.
41
+
42
+ ## Why Same-Repository PRs Only
43
+
44
+ The workflow requires both `CURSOR_API_KEY` and `contents: write`. Those are powerful capabilities. The job therefore has this guard:
45
+
46
+ ```yaml
47
+ if: ${{ github.event.pull_request.head.repo.full_name == github.repository && !github.event.pull_request.draft }}
48
+ ```
49
+
50
+ That keeps secrets and write access away from forked pull requests. Forked PRs should continue to add changesets manually, or a maintainer can run the script from a trusted checkout.
51
+
52
+ ## Configuration
53
+
54
+ The workflow expects this repository secret:
55
+
56
+ - `CURSOR_API_KEY`: API key used by `@cursor/sdk`.
57
+
58
+ The script also reads optional environment variables:
59
+
60
+ - `CURSOR_MODEL`: Cursor model id. The workflow currently sets `composer-2.5`.
61
+ - `CHANGESET_BASE_REF`: diff base for release-impact detection. Defaults to `origin/main`.
62
+ - `GITHUB_WORKSPACE`: checkout directory in CI. Local runs default to `process.cwd()`.
63
+
64
+ The script loads Cursor credentials through `loadCursorConfig`, then converts them at the SDK boundary with `agentOptionsFromConfig`. This keeps the example aligned with the package's recommended configuration path.
65
+
66
+ ## Local Usage
67
+
68
+ From a branch with `main` fetched:
69
+
70
+ ```bash
71
+ export CURSOR_API_KEY=...
72
+ git fetch origin main
73
+ bun run changeset:agent
74
+ ```
75
+
76
+ To compare against a different base:
77
+
78
+ ```bash
79
+ CHANGESET_BASE_REF=origin/release bun run changeset:agent
80
+ ```
81
+
82
+ If the branch already contains a changeset, the command logs that fact and exits without invoking Cursor for another release note.
83
+
84
+ ## Prompt Contract
85
+
86
+ The prompt intentionally gives Cursor a narrow maintenance task. It tells the agent to:
87
+
88
+ - inspect the diff against the configured base;
89
+ - create one concise `.changeset/*.md` file only when the PR affects shipped behavior or public docs;
90
+ - choose `patch`, `minor`, or `major` using Changesets semver conventions;
91
+ - prefer `patch` unless there is a new public feature or breaking change;
92
+ - avoid editing source files, package metadata, lockfiles, or existing changesets;
93
+ - leave the workspace unchanged when no changeset is needed.
94
+
95
+ The prompt includes the changed-file list for orientation, but the agent is still expected to inspect the actual diff before deciding.
96
+
97
+ ## Idempotency
98
+
99
+ The script checks for changed `.changeset/*.md` files before starting Cursor. That prevents duplicate release notes on repeated `synchronize` events.
100
+
101
+ After Cursor finishes, the script lists `.changeset/*.md` files again and logs any newly created file. The workflow then checks `git status --porcelain .changeset` so untracked new files are detected; if the tree is clean under `.changeset`, it exits successfully without committing.
102
+
103
+ ## Failure Modes
104
+
105
+ Common failures are intentionally visible in CI:
106
+
107
+ - Missing or invalid `CURSOR_API_KEY` fails during agent creation.
108
+ - Cursor rate limits or network issues surface through the package's mapped Cursor errors.
109
+ - A missing `origin/main` ref causes the git diff command to fail; the workflow avoids this by using `fetch-depth: 0`.
110
+ - Forked PRs do not run the job because the workflow guard blocks them.
111
+
112
+ When the agent decides no changeset is required, the workflow succeeds and commits nothing.
113
+
114
+ ## Release Workflow Relationship
115
+
116
+ The changeset agent only creates release-note files on PR branches. It does not version, publish, or alter the release workflow.
117
+
118
+ Publishing still works through the existing Changesets process:
119
+
120
+ - PRs add `.changeset/*.md`.
121
+ - The release workflow creates or updates the version PR on `main`.
122
+ - Merging the version PR publishes with `bun run release`.
123
+
124
+ This separation keeps the agent focused on authoring missing release metadata, while Changesets remains the source of truth for version calculation and changelog generation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-cursor-sdk",
3
- "version": "0.3.1",
3
+ "version": "0.3.4",
4
4
  "description": "Effect-based wrapper around the Cursor SDK",
5
5
  "keywords": [
6
6
  "cursor",
@@ -40,6 +40,7 @@
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsdown",
43
+ "changeset:agent": "node --import tsx ./scripts/create-changeset-agent.ts",
43
44
  "changeset": "changeset",
44
45
  "prepare": "effect-language-service patch",
45
46
  "prepack": "bun run build",
@@ -63,13 +64,14 @@
63
64
  "verify:publish": "bun run typecheck && bun run sdk-audit && bun run lint && bun run test && bun run build && bun run lint:package"
64
65
  },
65
66
  "dependencies": {
66
- "@cursor/sdk": "^1.0.12",
67
+ "@cursor/sdk": "^1.0.13",
67
68
  "effect-cursor-sdk": "."
68
69
  },
69
70
  "devDependencies": {
70
71
  "@changesets/changelog-github": "^0.6.0",
71
72
  "@changesets/cli": "^2.31.0",
72
73
  "@effect/language-service": "^0.85.1",
74
+ "@effect/platform-node": "^4.0.0-beta.57",
73
75
  "@effect/vitest": "4.0.0-beta.57",
74
76
  "@types/bun": "latest",
75
77
  "@vitest/coverage-v8": "^4.1.5",
@@ -78,6 +80,7 @@
78
80
  "oxlint": "^1.61.0",
79
81
  "publint": "^0.3.12",
80
82
  "tsdown": "^0.21.10",
83
+ "tsx": "^4.21.0",
81
84
  "typescript": "^6.0.3",
82
85
  "vitest": "^4.1.5"
83
86
  },