-
[OPIK-5937] [SDK] feat: allow direct Prompt and ChatPrompt instantiation (#6317)
发布于
2026-04-20 08:06:09 +00:00 - [OPIK-5937] [SDK] feat: allow direct Prompt and ChatPrompt instantiation
Add global client singleton (getGlobalClient/setGlobalClient/resetGlobalClient)
mirroring Python's pattern. Prompt and ChatPrompt now accept an optionalopik
parameter (deprecated) and auto-sync with the backend on construction via the
global client when no explicit client is provided.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- fix: guard _performSync against unsynced returns and recursive sync loop
- Add skipAutoSync flag to BasePromptData so Client.ts unsynced fallbacks
do not re-trigger _performSync (prevents infinite recursion when
createPrompt() fails and returns a new unsynced Prompt). - Extract shared sync logic into BasePrompt._syncViaCreate: only calls
updateSyncState when the returned instance has synced===true and all
required fields (id, versionId, commit) present; otherwise logs a
warning and leaves _synced false so requireSynced() cannot pass with
undefined IDs. - Simplify Prompt._performSync and ChatPrompt._performSync to delegate
to _syncViaCreate.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- refactor(prompt): remove fallback unsynced instance from createPrompt/createChatPrompt
API errors now propagate to the caller instead of returning an unsynced
local-only instance, matching Python SDK behaviour. Removes skipAutoSync
flag which was only needed to prevent infinite recursion from that fallback.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- test(prompt): add direct instantiation tests and fix deprecation overloads
- Use constructor overloads so @deprecated only triggers when opik arg is passed
- Add unit tests covering background sync, ready(), format(), and error resilience
- Fix test mocks to use Object.defineProperty instead of private field access
- Remove unused OpikApiTimeoutError import from Client.ts
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- test(client): update createPrompt/createChatPrompt error tests to expect throws
Removes tests that asserted unsynced fallback instances were returned on
OpikApiError/OpikApiTimeoutError — that behaviour no longer exists.
Replaces them with tests that assert the errors propagate to the caller.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- refactor(prompt): use opik presence to guard auto-sync, restore fallback on API error
Auto-sync in the constructor now fires only when no explicit opik client
is passed (direct instantiation). When opik is passed (internal client
calls and backward-compat usage), no auto-sync fires — the client manages
the lifecycle. This naturally prevents recursion without a skipAutoSync flag.createPrompt/createChatPrompt restore the fallback: OpikApiError and
OpikApiTimeoutError return a local-only unsynced instance instead of
throwing, matching the original behaviour.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- refactor(client): move fallback catch into createPromptInternal via createUnsyncedInstance param
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- fix(prompt): propagate projectName through updateSyncState after background sync
Direct new Prompt/ChatPrompt instances stayed projectName === undefined after
a successful backend sync because updateSyncState only updated id/versionId/
commit/changeDescription. projectName is now a private-backed field updated
alongside the other sync state.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- fix(agent-config): defer trace metadata injection until unsynced prompts are ready
When a directly-instantiated Prompt/ChatPrompt (still background-syncing)
is used as a config field and the config is accessed before ready()
resolves, metadata injection is now deferred until all pending prompt
syncs complete, using the already-captured trace context.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- feat(prompt): add sync timeout; inject fallback metadata on agent-config timeout
- PROMPT_SYNC_TIMEOUT_MS (5s) in BasePrompt races background sync;
on timeout ready() rejects so callers can detect the failure - AGENT_CONFIG_PROMPT_READY_TIMEOUT_MS (5s) in agent-config Config;
deferred metadata injection fires after timeout using fallback —
unsynced prompt fields get undefined commit (same as API error path)
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- feat(prompt): await prompt sync at getOrCreateConfig time; minimal injection
Before hitting the backend in getOrCreateConfig, all unsynced BasePrompt
values in fallback are awaited. If they do not sync within
AGENT_CONFIG_PROMPT_READY_TIMEOUT_MS (5s), the call is treated as a fetch
failure and fallback values are used immediately without a backend call.
injectTraceMetadata is now fully synchronous — unsynced prompts in
metadata get undefined commit (same as the fallback path).Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- fix(prompt): resolve ready() on sync timeout instead of rejecting
Timeout in _syncViaCreate now logs a warning and returns (same as API
error path) rather than throwing. ready() always resolves; the prompt
stays unsynced and can be retried via syncWithBackend().Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
-
CR
-
fix(agent-config): verify all prompts synced before auto-creating config
Combine timeout check and sync-state check into _allPromptsSynced().
After ready() resolves, re-verify that every prompt actually synced
(commit is populated). If any failed, return fallback config instead
of serializing broken prompt references into the blueprint.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
-
Restore comments
-
[OPIK-5937] [SDK] refactor: optimize timeout test and improve sync error messages
Improvements:
- Optimize timeout test to use fast fake timers with chunked advancement (18ms vs 5.5s)
- Add detailed comment explaining Vitest fake timer + Promise.allSettled() edge case
- Add unhandled rejection protection in _syncViaCreate() to prevent late rejections
- Update error/warning messages to guide users: await prompt.ready() → syncWithBackend()
The timeout test now uses chunked advancement (3 x 2000ms) instead of single large advance
to properly flush microtask queue in Vitest fake timer environment. All 1118 unit tests pass
in 8.69s total.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- [OPIK-5937] [SDK] refactor: make prompt sync implicit in version operations
Prompts now automatically handle initialization when accessing version operations like getVersions(), delete(), and updateProperties(). Users no longer need to manually call .ready() before these operations.
Changes:
- Updated BasePrompt methods to implicitly await .ready()
- Replaced requireSynced() with warnIfNotSynced() for graceful degradation
- Updated documentation to remove all sync implementation details
- Simplified examples to showcase natural, seamless usage
This improves user experience by removing unnecessary abstraction leaks about background initialization.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- fix: resolve TypeScript type narrowing in _syncViaCreate
Explicitly check for undefined result from createPromise when it rejects after timeout, allowing TypeScript to properly narrow the type for subsequent operations.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- refactor: restore hard guard for unsync'd prompts in backend operations
Replace warnIfNotSynced() with ensureSynced() to throw an error if sync failed.
This prevents passing undefined prompt IDs to backend API calls and gives users
clear feedback when initialization failed.Users should call syncWithBackend() to retry persisting the prompt.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- feat: wait for prompt initialization in evaluate function
Ensure all prompts linked to experiments are ready before evaluation begins.
This guarantees prompts are initialized when passed to the experiment.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
Co-authored-by: Claude Sonnet 4.6 noreply@anthropic.com
下载附件