eve 0.43.0 → 0.44.1
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/CHANGELOG.md +26 -0
- package/dist/src/channel/adapter.d.ts +2 -1
- package/dist/src/channel/instrumentation.js +1 -1
- package/dist/src/chunks/{use-eve-agent-C0SG1Ttk.js → use-eve-agent-BsLJiIbc.js} +224 -62
- package/dist/src/chunks/{use-eve-agent-D71oDil7.js → use-eve-agent-DpUEwS23.js} +222 -62
- package/dist/src/cli/commands/extension-init.js +1 -1
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/registry-project.d.ts +3 -0
- package/dist/src/cli/commands/registry-project.js +2 -1
- package/dist/src/cli/commands/registry.d.ts +2 -0
- package/dist/src/cli/commands/registry.js +1 -1
- package/dist/src/cli/dev/tui/setup-commands.js +1 -1
- package/dist/src/cli/dev/tui/traces/trace-view.js +1 -1
- package/dist/src/client/eve-agent-store-helpers.d.ts +12 -0
- package/dist/src/client/eve-agent-store-helpers.js +2 -0
- package/dist/src/client/eve-agent-store.d.ts +8 -6
- package/dist/src/client/eve-agent-store.js +1 -2
- package/dist/src/client/ndjson.d.ts +3 -1
- package/dist/src/client/ndjson.js +3 -3
- package/dist/src/client/open-stream.d.ts +3 -0
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/compiled/jsonc-parser/index.d.ts +19 -0
- package/dist/src/compiler/extension-compatibility.d.ts +2 -2
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.d.ts +5 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +4 -2
- package/dist/src/context/keys.js +1 -1
- package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
- package/dist/src/execution/dispatch-turn-step.js +1 -1
- package/dist/src/execution/eve-workflow-attributes.d.ts +3 -0
- package/dist/src/execution/eve-workflow-attributes.js +1 -1
- package/dist/src/execution/pending-turn-state.d.ts +9 -0
- package/dist/src/execution/pending-turn-state.js +1 -0
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/execution/workflow-trace-context.js +1 -1
- package/dist/src/harness/channel-delivery-instrumentation.js +1 -1
- package/dist/src/harness/instrumentation/content-policy.d.ts +6 -0
- package/dist/src/harness/instrumentation/content-policy.js +1 -0
- package/dist/src/harness/instrumentation/lifecycle.d.ts +6 -0
- package/dist/src/harness/instrumentation/native-events.d.ts +2 -0
- package/dist/src/harness/instrumentation/native-events.js +1 -1
- package/dist/src/harness/instrumentation/runtime-context.js +1 -1
- package/dist/src/harness/prepare-trace-context.d.ts +2 -0
- package/dist/src/harness/prepare-trace-context.js +1 -1
- package/dist/src/harness/runtime-actions.js +1 -1
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-remote-agent-transform.js +2 -2
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.d.ts +4 -4
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +3 -4
- package/dist/src/internal/workflow-bundle/stable-module-id.d.ts +6 -0
- package/dist/src/internal/workflow-bundle/stable-module-id.js +1 -0
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/public/channels/chat-sdk/audience.d.ts +2 -0
- package/dist/src/public/channels/chat-sdk/audience.js +1 -0
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +2 -0
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/discord/audience.d.ts +5 -0
- package/dist/src/public/channels/discord/audience.js +1 -0
- package/dist/src/public/channels/discord/discordChannel.d.ts +2 -0
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/discord/inbound.d.ts +1 -0
- package/dist/src/public/channels/discord/inbound.js +1 -1
- package/dist/src/public/channels/discord/index.d.ts +1 -0
- package/dist/src/public/channels/index.d.ts +3 -2
- package/dist/src/public/channels/slack/slackChannel.d.ts +4 -0
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/index.d.ts +1 -0
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/audience.d.ts +3 -0
- package/dist/src/public/channels/telegram/audience.js +1 -0
- package/dist/src/public/channels/telegram/index.d.ts +1 -0
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/channels/twilio/twilioChannel.d.ts +2 -0
- package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
- package/dist/src/public/definitions/channel.d.ts +1 -0
- package/dist/src/public/instrumentation/otel.d.ts +6 -10
- package/dist/src/public/instrumentation/otel.js +1 -1
- package/dist/src/public/tools/approval/approval-helpers.js +1 -1
- package/dist/src/react/use-eve-agent.d.ts +10 -1
- package/dist/src/react/use-eve-agent.js +1 -1
- package/dist/src/runtime/attributes/emit.d.ts +1 -1
- package/dist/src/runtime/attributes/normalize.d.ts +1 -1
- package/dist/src/runtime/attributes/normalize.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +2 -2
- package/dist/src/runtime/framework-tools/subagent/local.js +1 -1
- package/dist/src/runtime/sessions/runtime-context-keys.js +1 -1
- package/dist/src/setup/integrations/linq/connect.js +1 -1
- package/dist/src/setup/primitives/pm/npm.js +1 -1
- package/dist/src/setup/primitives/pm/pnpm.js +5 -9
- package/dist/src/setup/primitives/pm/types.d.ts +0 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +10 -4
- package/dist/src/setup/scaffold/create/web-template.js +669 -74
- package/dist/src/shared/channel-audience.d.ts +7 -0
- package/dist/src/shared/channel-audience.js +1 -0
- package/dist/src/shared/channel-definition.d.ts +2 -1
- package/dist/src/shared/durable-dynamic-tool-callbacks.d.ts +43 -19
- package/dist/src/shared/durable-dynamic-tool-callbacks.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.d.ts +4 -0
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tasks/delivery-context.d.ts +9 -0
- package/dist/src/tasks/delivery-context.js +5 -2
- package/dist/src/tracing/agent-action-instrumentation.js +1 -1
- package/dist/src/tracing/agent-approval-instrumentation.js +1 -1
- package/dist/src/tracing/agent-channel-delivery-instrumentation.js +1 -1
- package/dist/src/tracing/agent-otel-provider.d.ts +2 -0
- package/dist/src/tracing/agent-otel-provider.js +2 -2
- package/dist/src/tracing/agent-otel-session-context.d.ts +2 -0
- package/dist/src/tracing/agent-otel-session-context.js +1 -1
- package/dist/src/tracing/agent-trace-context-store.js +1 -1
- package/dist/src/tracing/agent-trace-state.d.ts +3 -0
- package/dist/src/tracing/channel-audience-context.d.ts +4 -0
- package/dist/src/tracing/channel-audience-context.js +1 -0
- package/dist/src/tracing/content-attributes.js +1 -1
- package/dist/src/tracing/content-span-processor.d.ts +7 -7
- package/dist/src/tracing/content-span-processor.js +1 -1
- package/dist/src/tracing/install-instrumentation-runtime.js +1 -1
- package/dist/src/tracing/local-instrumentation-runtime.d.ts +3 -0
- package/dist/src/tracing/local-instrumentation-runtime.js +1 -1
- package/dist/src/tracing/local-traces.d.ts +1 -10
- package/dist/src/tracing/local-traces.js +1 -1
- package/dist/src/tracing/otel-declaration.d.ts +34 -27
- package/dist/src/tracing/otel-declaration.js +1 -1
- package/dist/src/tracing/sampled-trace.d.ts +2 -0
- package/dist/src/tracing/sampled-trace.js +1 -0
- package/dist/src/tracing/span-export-policy.d.ts +41 -0
- package/dist/src/tracing/span-export-policy.js +1 -0
- package/dist/src/tracing/suppress-tracing.d.ts +2 -0
- package/dist/src/tracing/suppress-tracing.js +1 -0
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.d.ts +4 -0
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/custom.mdx +2 -0
- package/docs/concepts/sessions-runs-and-streaming.md +1 -1
- package/docs/guides/dynamic-capabilities.md +10 -2
- package/docs/guides/frontend/nextjs.mdx +23 -0
- package/docs/guides/frontend/overview.mdx +24 -9
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +9 -9
- package/docs/guides/frontend/use-eve-agent-vue.mdx +9 -9
- package/docs/guides/instrumentation.md +2 -0
- package/docs/tools/overview.mdx +5 -4
- package/docs/tutorial/ship-it.mdx +1 -1
- package/package.json +1 -1
|
@@ -3,6 +3,10 @@ import { type InstrumentationProvider } from "#public/instrumentation/provider.j
|
|
|
3
3
|
import type { InstrumentationRuntimeContextInput } from "#public/instrumentation/index.js";
|
|
4
4
|
import type { JsonObject } from "#shared/json.js";
|
|
5
5
|
import type { ResolvedContentOptions } from "#tracing/content-attributes.js";
|
|
6
|
+
import type { ChannelAudience } from "#shared/channel-audience.js";
|
|
7
|
+
import { type SpanExportPolicy } from "#tracing/span-export-policy.js";
|
|
8
|
+
export type { SpanAttributeDecision, SpanExportAttributeValue, SpanExportContext, SpanExportPolicy, SpanExportPredicate, } from "#tracing/span-export-policy.js";
|
|
9
|
+
export { composeSpanExportPolicies, redactSpanInputs, redactSpanOutputs, } from "#tracing/span-export-policy.js";
|
|
6
10
|
/**
|
|
7
11
|
* The process-wide OpenTelemetry settings, declared by `otel()`.
|
|
8
12
|
*
|
|
@@ -28,6 +32,11 @@ export interface OtelOptions {
|
|
|
28
32
|
* outgoing HTTP spans. Defaults to `false`.
|
|
29
33
|
*/
|
|
30
34
|
readonly traceChannelRequests?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Process-wide head gate for an agent session trace. Defaults to retaining
|
|
37
|
+
* only public conversations. A thrown error rejects the trace.
|
|
38
|
+
*/
|
|
39
|
+
readonly tracePolicy?: TraceCapturePolicy;
|
|
31
40
|
/**
|
|
32
41
|
* Resource attributes merged into eve's own, which already carry the
|
|
33
42
|
* service name.
|
|
@@ -52,22 +61,27 @@ export interface OtelOptions {
|
|
|
52
61
|
*/
|
|
53
62
|
readonly instrumentations?: readonly unknown[];
|
|
54
63
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
*/
|
|
64
|
+
export interface ManagedTraceOptions {
|
|
65
|
+
/** Destination policy applied before spans are exported. */
|
|
66
|
+
readonly exportPolicy?: SpanExportPolicy;
|
|
67
|
+
/** @deprecated Use `exportPolicy: redactSpanInputs()` instead. */
|
|
68
|
+
readonly recordInputs?: boolean;
|
|
69
|
+
/** @deprecated Use `exportPolicy: redactSpanOutputs()` instead. */
|
|
70
|
+
readonly recordOutputs?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** @deprecated Compose `redactSpanInputs()` and `redactSpanOutputs()` into an export policy. */
|
|
64
73
|
export interface ContentOptions {
|
|
65
|
-
/** Record model prompts and tool call inputs. Defaults to `false`. */
|
|
66
74
|
readonly recordInputs?: boolean;
|
|
67
|
-
/** Record model responses and tool call outputs. Defaults to `false`. */
|
|
68
75
|
readonly recordOutputs?: boolean;
|
|
69
76
|
}
|
|
70
|
-
|
|
77
|
+
export interface TraceCaptureContext {
|
|
78
|
+
readonly agentName?: string;
|
|
79
|
+
readonly audience: ChannelAudience;
|
|
80
|
+
readonly rootSessionId: string;
|
|
81
|
+
readonly sessionId: string;
|
|
82
|
+
}
|
|
83
|
+
export type TraceCapturePolicy = (trace: TraceCaptureContext) => boolean;
|
|
84
|
+
/** Where one `otelIntegration()` sends spans. */
|
|
71
85
|
export interface OtelIntegrationOptions extends ContentOptions {
|
|
72
86
|
/** Merged into the pipeline in declaration order. */
|
|
73
87
|
readonly spanProcessors?: readonly SpanProcessor[];
|
|
@@ -98,7 +112,7 @@ export interface OtelDeclaration extends InstrumentationProvider {
|
|
|
98
112
|
/** One declared destination. A process may have as many as it has files. */
|
|
99
113
|
export interface OtelIntegration extends InstrumentationProvider {
|
|
100
114
|
readonly [OTEL_INTEGRATION]: true;
|
|
101
|
-
/**
|
|
115
|
+
/** @deprecated Content is captured upstream and redacted by destination policies. */
|
|
102
116
|
readonly content: ResolvedContentOptions;
|
|
103
117
|
readonly runtimeContext?: (input: InstrumentationRuntimeContextInput) => JsonObject | undefined;
|
|
104
118
|
readonly spanProcessors: readonly SpanProcessorOrName[];
|
|
@@ -118,13 +132,14 @@ export declare function otel(options?: OtelOptions): OtelDeclaration;
|
|
|
118
132
|
* the one-line form of a hosted backend enough. Pass `spanProcessors` instead
|
|
119
133
|
* when the destination needs its own batching, sampling, or filtering.
|
|
120
134
|
*
|
|
121
|
-
*
|
|
122
|
-
* this destination, and
|
|
123
|
-
* what was said.
|
|
135
|
+
* The export policy wraps every processor here, an author's included: they are
|
|
136
|
+
* this destination, and nothing beneath the policy sees what it removes.
|
|
124
137
|
*/
|
|
125
138
|
export declare function otelIntegration(options?: OtelIntegrationOptions): OtelIntegration;
|
|
139
|
+
/** @internal Local and Agent Runs destination declaration. */
|
|
140
|
+
export declare function managedOtelIntegration(options?: OtelIntegrationOptions & ManagedTraceOptions): OtelIntegration;
|
|
126
141
|
/** Vercel Agent Runs through the production request-context transport. @internal */
|
|
127
|
-
export declare function agentRunsIntegration(options?:
|
|
142
|
+
export declare function agentRunsIntegration(options?: ManagedTraceOptions): OtelIntegration;
|
|
128
143
|
export declare function resolveContentOptions(options: ContentOptions): ResolvedContentOptions;
|
|
129
144
|
export declare function isOtelDeclaration(value: unknown): value is OtelDeclaration;
|
|
130
145
|
export declare function isOtelIntegration(value: unknown): value is OtelIntegration;
|
|
@@ -140,11 +155,8 @@ export interface OtelPipeline {
|
|
|
140
155
|
export interface OtelHarnessSettings {
|
|
141
156
|
readonly functionId?: string;
|
|
142
157
|
readonly traceChannelRequests: boolean;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
* exports. `agent/instrumentation.ts` sets this directly; a provider
|
|
146
|
-
* directory arrives at it as the union of its destinations.
|
|
147
|
-
*/
|
|
158
|
+
readonly tracePolicy?: TraceCapturePolicy;
|
|
159
|
+
/** Legacy `defineInstrumentation()` capture settings. Provider destinations capture fully. */
|
|
148
160
|
readonly recordInputs?: boolean;
|
|
149
161
|
readonly recordOutputs?: boolean;
|
|
150
162
|
}
|
|
@@ -169,11 +181,6 @@ export interface CollectedOtel {
|
|
|
169
181
|
* happened to visit first. With one declaration per file that collision needs
|
|
170
182
|
* two files both exporting `otel()`, which is the only way to reach it.
|
|
171
183
|
*
|
|
172
|
-
* Content capture is the union of what the destinations asked for, because it
|
|
173
|
-
* governs what is written rather than what is exported. Each destination's own
|
|
174
|
-
* processors already drop what it declined.
|
|
175
|
-
*
|
|
176
184
|
* @internal
|
|
177
185
|
*/
|
|
178
186
|
export declare function collectOtelPipeline(values: readonly unknown[]): CollectedOtel;
|
|
179
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PROVIDER}from"#public/instrumentation/provider.js";import{batchSpanProcessor}from"#tracing/batch-span-processor.js";import{contentFilteringProcessor}from"#tracing/content-span-processor.js";import{vercelRuntimeSpanProcessor}from"#tracing/vercel-runtime-span-exporter.js";const OTEL_DECLARATION=Symbol.for(`eve.instrumentation.otel`),OTEL_INTEGRATION=Symbol.for(`eve.instrumentation.otel-integration`);function otel(t={}){return{[OTEL_DECLARATION]:!0,[PROVIDER]:!0,options:t}}function otelIntegration(
|
|
1
|
+
import{PROVIDER}from"#public/instrumentation/provider.js";import{composeSpanExportPolicies,composeSpanExportPolicies as composeSpanExportPolicies$1,redactSpanInputs,redactSpanInputs as redactSpanInputs$1,redactSpanOutputs,redactSpanOutputs as redactSpanOutputs$1}from"#tracing/span-export-policy.js";import{batchSpanProcessor}from"#tracing/batch-span-processor.js";import{contentFilteringProcessor}from"#tracing/content-span-processor.js";import{vercelRuntimeSpanProcessor}from"#tracing/vercel-runtime-span-exporter.js";const OTEL_DECLARATION=Symbol.for(`eve.instrumentation.otel`),OTEL_INTEGRATION=Symbol.for(`eve.instrumentation.otel-integration`);function otel(t={}){return{[OTEL_DECLARATION]:!0,[PROVIDER]:!0,options:t}}function otelIntegration(e={}){return createOtelIntegration(e)}function managedOtelIntegration(e={}){return createOtelIntegration(e,e.exportPolicy)}function createOtelIntegration(t,n){let r=t.spanProcessors??[],i=t.traceExporter===void 0?r:[...r,batchSpanProcessor(t.traceExporter)];return{[OTEL_INTEGRATION]:!0,[PROVIDER]:!0,content:resolveContentOptions(t),runtimeContext:t.runtimeContext,spanProcessors:i.map(e=>withExportPolicies(e,legacyContentRedactionPolicy(t),n))}}function agentRunsIntegration(t={}){return{[OTEL_INTEGRATION]:!0,[PROVIDER]:!0,content:resolveContentOptions(t),spanProcessors:[withExportPolicies(vercelRuntimeSpanProcessor(),legacyContentRedactionPolicy(t),t.exportPolicy)]}}function legacyContentRedactionPolicy(e){let t=[];return e.recordInputs===!1&&t.push(redactSpanInputs$1()),e.recordOutputs===!1&&t.push(redactSpanOutputs$1()),t.length===0?void 0:composeSpanExportPolicies$1(...t)}function resolveContentOptions(e){return{recordInputs:e.recordInputs!==!1,recordOutputs:e.recordOutputs!==!1}}function withExportPolicies(e,...t){let n=e;for(let e of t.toReversed())n=contentFilteringProcessor(n,e);return n}function isOtelDeclaration(e){return typeof e==`object`&&!!e&&e[OTEL_DECLARATION]===!0}function isOtelIntegration(e){return typeof e==`object`&&!!e&&e[OTEL_INTEGRATION]===!0}function collectOtelPipeline(e){let t=[],n=[],r,i=!1,a=!1;for(let o of e){if(isOtelIntegration(o)){i=!0,a=!0,t.push(...o.spanProcessors),o.runtimeContext!==void 0&&n.push(o.runtimeContext);continue}if(isOtelDeclaration(o)){if(r!==void 0)throw Error("Instrumentation declares `otel()` more than once. One process has one OpenTelemetry tracer provider, so it has one resource, one sampler, and one propagator set — declare them in a single `otel()`.");i=!0,r=o}}let o=r?.options??{},s={functionId:o.functionId,recordInputs:a,recordOutputs:a,traceChannelRequests:o.traceChannelRequests===!0};return o.tracePolicy!==void 0&&Object.assign(s,{tracePolicy:o.tracePolicy}),{declared:i,pipeline:{instrumentations:o.instrumentations,propagators:o.propagators,resource:o.resource,sampler:o.sampler,spanProcessors:t},runtimeContextResolvers:n,settings:s}}export{agentRunsIntegration,collectOtelPipeline,composeSpanExportPolicies,isOtelDeclaration,isOtelIntegration,managedOtelIntegration,otel,otelIntegration,redactSpanInputs,redactSpanOutputs,resolveContentOptions};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{TraceFlags}from"#compiled/@opentelemetry/api/index.js";function isSampledTrace(e){return(e.traceFlags&TraceFlags.SAMPLED)===TraceFlags.SAMPLED}export{isSampledTrace};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ChannelAudience } from "#shared/channel-audience.js";
|
|
2
|
+
export interface SpanExportContext {
|
|
3
|
+
readonly attributes: Readonly<Record<string, unknown>>;
|
|
4
|
+
readonly audience: ChannelAudience;
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly spanId: string;
|
|
7
|
+
readonly traceId: string;
|
|
8
|
+
}
|
|
9
|
+
export type SpanExportPredicate = (span: SpanExportContext) => boolean;
|
|
10
|
+
export type SpanExportAttributeValue = string | number | boolean | readonly string[] | readonly number[] | readonly boolean[];
|
|
11
|
+
export type SpanAttributeDecision = {
|
|
12
|
+
readonly action: "keep";
|
|
13
|
+
} | {
|
|
14
|
+
readonly action: "drop";
|
|
15
|
+
} | {
|
|
16
|
+
readonly action: "replace";
|
|
17
|
+
readonly value: SpanExportAttributeValue;
|
|
18
|
+
};
|
|
19
|
+
export interface SpanExportPolicy {
|
|
20
|
+
/** Return false to block one span without blocking its trace. */
|
|
21
|
+
readonly span?: SpanExportPredicate;
|
|
22
|
+
/** Drop or replace individual span attributes after content filtering. */
|
|
23
|
+
readonly attribute?: (input: {
|
|
24
|
+
readonly key: string;
|
|
25
|
+
readonly span: SpanExportContext;
|
|
26
|
+
readonly value: unknown;
|
|
27
|
+
}) => SpanAttributeDecision;
|
|
28
|
+
}
|
|
29
|
+
/** Redact input content from every matching span. */
|
|
30
|
+
export declare function redactSpanInputs(when?: SpanExportPredicate): SpanExportPolicy;
|
|
31
|
+
/** Redact output content, exception details, and status messages from every matching span. */
|
|
32
|
+
export declare function redactSpanOutputs(when?: SpanExportPredicate): SpanExportPolicy;
|
|
33
|
+
/** Compose policies in declaration order. A drop or redaction from any policy is final. */
|
|
34
|
+
export declare function composeSpanExportPolicies(...policies: readonly SpanExportPolicy[]): SpanExportPolicy;
|
|
35
|
+
/** @internal */
|
|
36
|
+
export declare function spanExportPolicyStages(policy: SpanExportPolicy): readonly SpanExportPolicy[];
|
|
37
|
+
/** @internal */
|
|
38
|
+
export declare function contentRedactionForSpan(policy: SpanExportPolicy | undefined, span: SpanExportContext): {
|
|
39
|
+
readonly redactInputs: boolean;
|
|
40
|
+
readonly redactOutputs: boolean;
|
|
41
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const contentRedactions=new WeakMap,composedPolicies=new WeakMap;function redactSpanInputs(t=()=>!0){let n={};return contentRedactions.set(n,{inputs:[t],outputs:[]}),n}function redactSpanOutputs(t=()=>!0){let n={};return contentRedactions.set(n,{inputs:[],outputs:[t]}),n}function composeSpanExportPolicies(...e){if(e.length===0)return{};if(e.length===1)return e[0];let n={};return composedPolicies.set(n,e.flatMap(spanExportPolicyStages)),n}function spanExportPolicyStages(e){return composedPolicies.get(e)??[e]}function contentRedactionForSpan(t,n){let r=t===void 0?void 0:contentRedactions.get(t);return{redactInputs:r?.inputs.some(e=>matches(e,n))??!1,redactOutputs:r?.outputs.some(e=>matches(e,n))??!1}}function matches(e,t){try{return e(t)}catch{return!0}}export{composeSpanExportPolicies,contentRedactionForSpan,redactSpanInputs,redactSpanOutputs,spanExportPolicyStages};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createContextKey}from"#compiled/@opentelemetry/api/index.js";const SUPPRESS_TRACING_KEY=createContextKey(`OpenTelemetry SDK Context Key SUPPRESS_TRACING`);function suppressTracing(e){return e.setValue(SUPPRESS_TRACING_KEY,!0)}export{suppressTracing};
|
package/dist/src/vue/index.js
CHANGED
|
@@ -33,6 +33,8 @@ export interface UseEveAgentReturn<TData> {
|
|
|
33
33
|
readonly error: ComputedRef<Error | undefined>;
|
|
34
34
|
/** Raw server events from this session (authoritative stream). */
|
|
35
35
|
readonly events: ComputedRef<readonly MessageStreamEvent[]>;
|
|
36
|
+
/** Replay the attached durable session and follow its in-flight turn, if any. */
|
|
37
|
+
readonly resume: () => Promise<void>;
|
|
36
38
|
/** Clear all state and start a new session. */
|
|
37
39
|
readonly reset: () => void;
|
|
38
40
|
/** Send a message with optional turn settings. */
|
|
@@ -98,6 +100,8 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
|
|
|
98
100
|
* @default defaultMessageReducer()
|
|
99
101
|
*/
|
|
100
102
|
readonly reducer?: EveAgentReducer<TData>;
|
|
103
|
+
/** Replay the attached durable session after mount. Requires `initialSession` or `session`. */
|
|
104
|
+
readonly resume?: boolean;
|
|
101
105
|
/**
|
|
102
106
|
* Externally owned {@link ClientSession} to bind instead of creating one.
|
|
103
107
|
*
|
package/docs/channels/custom.mdx
CHANGED
|
@@ -306,6 +306,8 @@ export default defineChannel({
|
|
|
306
306
|
|
|
307
307
|
The projection is re-evaluated whenever adapter state changes after channel event handlers run. Dynamic tool resolvers read it via `ctx.channel.metadata` and narrow it with `isChannel`. See [Dynamic capabilities](../guides/dynamic-capabilities) for the full consumption pattern.
|
|
308
308
|
|
|
309
|
+
Metadata may include an `audience` classification: `public`, `private`, or `unknown`. Omit it when the channel cannot classify the conversation confidently; eve normalizes missing and invalid values to `unknown`. Consumers must treat `unknown` as non-public.
|
|
310
|
+
|
|
309
311
|
When a parent agent dispatches a subagent, the framework forwards the parent's channel metadata projection to the child. The same `metadata(state)` projector also serves instrumentation metadata resolvers.
|
|
310
312
|
|
|
311
313
|
## Continuation tokens
|
|
@@ -86,7 +86,7 @@ Note: consider the privacy, confidentiality, and user-experience implications fo
|
|
|
86
86
|
|
|
87
87
|
A delegated subagent publishes progress on its own child-session stream. The parent only emits `subagent.called` with a `childSessionId`, which a client uses to attach.
|
|
88
88
|
|
|
89
|
-
`step.failed` and `turn.failed` carry `{ code, message, details? }` for the failed fragment or turn, and `session.failed` is the terminal session-level variant. `turn.cancelled` is not a failure: the cancelled turn ends without any failure event, `session.waiting` follows, and the session accepts the next message normally
|
|
89
|
+
`step.failed` and `turn.failed` carry `{ code, message, details? }` for the failed fragment or turn, and `session.failed` is the terminal session-level variant. `turn.cancelled` is not a failure: the cancelled turn ends without any failure event, `session.waiting` follows, and the session accepts the next message normally. Whatever the turn streamed before cancellation stays on the stream. Durable history keeps the accepted user input and previously settled work, but discards incomplete assistant output and unfinished tool state. When a turn requested an output schema, the finalized payload lands on `result.completed` as `data.result` before the turn boundary. `authorization.required` carries the sign-in challenge (`data.authorization` may include `url`, `userCode`, `expiresAt`, `instructions`), and `authorization.completed` carries `data.outcome` (`"authorized" | "declined" | "failed" | "timed-out"`).
|
|
90
90
|
|
|
91
91
|
## The event envelope
|
|
92
92
|
|
|
@@ -166,7 +166,15 @@ Write callback properties as inline function expressions, arrows, method shortha
|
|
|
166
166
|
|
|
167
167
|
Closure values must be JSON-serializable. Plain objects, arrays, strings, finite numbers, booleans, and `null` are supported; `undefined` object properties are omitted. Functions, class instances, `Date`, `Map`, symbols, non-finite numbers, and cyclic values fail resolution with the tool name and callback phase instead of being serialized lossily.
|
|
168
168
|
|
|
169
|
-
Call expressions such as `execute: makeExecutor()` are not transformed. Put the callback body directly in `defineTool()` inside an authored module; eve-provided factories may also supply pre-registered callbacks. eve rejects a dynamic tool if any present callback lacks durable metadata
|
|
169
|
+
Call expressions such as `execute: makeExecutor()` are not transformed. Put the callback body directly in `defineTool()` inside an authored module; eve-provided factories may also supply pre-registered callbacks. eve rejects a dynamic tool if any present callback lacks durable metadata.
|
|
170
|
+
|
|
171
|
+
### Identity and redeploys
|
|
172
|
+
|
|
173
|
+
A parked call binds to its callback by **tool name and phase** — the same identity a static tool uses — never by source position. This gives dynamic tools static-tool semantics across deploys:
|
|
174
|
+
|
|
175
|
+
- Editing a callback body (or anything else that does not change tool names) is safe: replaying a parked call runs the latest deployed code with the closure values snapshotted when the call was made.
|
|
176
|
+
- If a persisted callback has no registered implementation (fresh process after a crash, or after a redeploy), eve re-runs `session.started` resolvers once to rebind it, then replays.
|
|
177
|
+
- If the tool no longer exists under that name, replay fails closed with an explicit error instead of invoking something else. Turn-scoped and step-scoped tools are not rebound; a parked call to a missing one errors.
|
|
170
178
|
|
|
171
179
|
### Naming
|
|
172
180
|
|
|
@@ -189,7 +197,7 @@ A dynamic tool or skill whose name matches an **authored** one **overrides** it
|
|
|
189
197
|
| `turn.started` | Once per turn | Every model call in the turn |
|
|
190
198
|
| `step.started` | Before each model call | That model call |
|
|
191
199
|
|
|
192
|
-
¹ Workflow recovery can redeliver a resolver event, so keep resolvers idempotent. Replaying a parked callback does not depend on running the resolver again.
|
|
200
|
+
¹ Workflow recovery can redeliver a resolver event, so keep resolvers idempotent. Replaying a parked callback does not depend on running the resolver again — except for the one-shot rebind described under [Identity and redeploys](#identity-and-redeploys).
|
|
193
201
|
|
|
194
202
|
### Execution order
|
|
195
203
|
|
|
@@ -90,6 +90,29 @@ const agent = useEveAgent({
|
|
|
90
90
|
|
|
91
91
|
The browser still needs a production authentication policy. See [Authenticate browser requests](./overview#authenticate-browser-requests) for the default fail-closed behavior and channel configuration.
|
|
92
92
|
|
|
93
|
+
## Use the generated Web Chat routes
|
|
94
|
+
|
|
95
|
+
`eve init --channel-web-nextjs` and `eve add channel/web` generate a chat UI with URL-addressed durable sessions:
|
|
96
|
+
|
|
97
|
+
- `/` is the initial landing page.
|
|
98
|
+
- `/s` opens the conversation layout without creating an eve session. The first message creates the session.
|
|
99
|
+
- `/s/[sessionId]` attaches to that durable session, replays its transcript, and follows an in-flight turn.
|
|
100
|
+
|
|
101
|
+
After the first message is accepted, Web Chat replaces the browser URL with `/s/{sessionId}` without remounting the active stream. Reloading that URL passes the session to `useEveAgent` with `resume: true`, so completed history is replayed and an unfinished response continues streaming. **New chat** navigates to the sessionless `/s` route; it does not reset or delete the prior session, which remains available at its URL.
|
|
102
|
+
|
|
103
|
+
The generated UI keeps transcript scroll position in browser `sessionStorage`. This is presentation state only and is not written to the eve session.
|
|
104
|
+
|
|
105
|
+
For a custom Next.js chat route, pass the route session ID explicitly:
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
const agent = useEveAgent({
|
|
109
|
+
initialSession: { sessionId, streamIndex: 0 },
|
|
110
|
+
resume: true,
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
See [Resumable sessions](./overview#resumable-sessions) for persistence and replay semantics.
|
|
115
|
+
|
|
93
116
|
## Dev vs deploy topology
|
|
94
117
|
|
|
95
118
|
- **Local dev.** `npm run dev` boots the eve dev server next to `next dev` and rewrites the eve routes over to it. The browser only ever talks to the Next.js origin.
|
|
@@ -26,7 +26,7 @@ For a public demo, use `none()` from `eve/channels/auth` to admit anonymous requ
|
|
|
26
26
|
|
|
27
27
|
## Basic chat (React)
|
|
28
28
|
|
|
29
|
-
The hook lives in `eve/react`. Render `data.messages`,
|
|
29
|
+
The hook lives in `eve/react`. Render `data.messages`, use `status` to steer follow-ups during an active turn, and send text with `send`:
|
|
30
30
|
|
|
31
31
|
```tsx
|
|
32
32
|
"use client";
|
|
@@ -44,7 +44,7 @@ export function Chat() {
|
|
|
44
44
|
const form = new FormData(event.currentTarget);
|
|
45
45
|
const message = String(form.get("message") ?? "").trim();
|
|
46
46
|
if (message.length > 0) {
|
|
47
|
-
void agent.send(message);
|
|
47
|
+
void agent.send(message, isBusy ? { turnPolicy: "steer" } : undefined);
|
|
48
48
|
}
|
|
49
49
|
}}
|
|
50
50
|
>
|
|
@@ -56,10 +56,8 @@ export function Chat() {
|
|
|
56
56
|
)}
|
|
57
57
|
</article>
|
|
58
58
|
))}
|
|
59
|
-
<input name="message"
|
|
60
|
-
<button
|
|
61
|
-
Send
|
|
62
|
-
</button>
|
|
59
|
+
<input name="message" />
|
|
60
|
+
<button type="submit">Send</button>
|
|
63
61
|
</form>
|
|
64
62
|
);
|
|
65
63
|
}
|
|
@@ -78,6 +76,7 @@ export function Chat() {
|
|
|
78
76
|
| `session` | Serializable fixed session cursor (`sessionId`, `streamIndex`). |
|
|
79
77
|
| `send` | Send text or a multi-part message, with per-turn options. |
|
|
80
78
|
| `respond` | Answer pending HITL input requests, with per-turn options. |
|
|
79
|
+
| `resume` | Replay an attached session and follow its in-flight turn. |
|
|
81
80
|
| `cancel` | Request durable cancellation of the active turn. |
|
|
82
81
|
| `reset` | Clear local events, data, errors, and the local session cursor. |
|
|
83
82
|
|
|
@@ -105,7 +104,13 @@ await agent.send([
|
|
|
105
104
|
]);
|
|
106
105
|
```
|
|
107
106
|
|
|
108
|
-
Assistant text, reasoning, tool calls, and tool results stream into `data` as they arrive, and `status` moves from `ready` to `submitted` to `streaming` and back.
|
|
107
|
+
Assistant text, reasoning, tool calls, and tool results stream into `data` as they arrive, and `status` moves from `ready` to `submitted` to `streaming` and back. To replace an active turn with a follow-up, send the message with `turnPolicy: "steer"`. eve accepts the message through the durable session, cancels the active turn, and keeps the hook attached through the replacement turn:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
await agent.send(message, { turnPolicy: "steer" });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Other message sends and HITL responses reject while the hook is processing a turn. Call `cancel()` to stop the durable server-side turn without replacing it, and `reset()` to clear local state so the next send starts a fresh durable session.
|
|
109
114
|
|
|
110
115
|
`cancel()` can be called as soon as `status` is `"submitted"`; the hook waits for the active response to identify its turn when necessary, sends one guarded cancellation request, and keeps the event stream attached. The promise resolves when eve accepts the request or reports that no turn is active, and rejects if the cancellation request fails. The turn then settles on the same stream as `turn.cancelled` followed by `session.waiting`, so the session is safe to continue.
|
|
111
116
|
|
|
@@ -275,6 +280,7 @@ const [saved] = useState<SavedEveChat>(() => {
|
|
|
275
280
|
const agent = useEveAgent({
|
|
276
281
|
initialEvents: saved.events ?? [],
|
|
277
282
|
initialSession: saved.session,
|
|
283
|
+
resume: saved.session !== undefined,
|
|
278
284
|
onFinish(snapshot) {
|
|
279
285
|
localStorage.setItem(
|
|
280
286
|
"eve-chat",
|
|
@@ -295,9 +301,18 @@ then save a final snapshot in `onFinish`.
|
|
|
295
301
|
|
|
296
302
|
`initialEvents` must be an ordered prefix of the same session's stream, but its endpoint does not have to line up exactly with where the stream resumes. Every event carries a stable [`meta.id`](/docs/concepts/sessions-runs-and-streaming#the-event-envelope), and the store drops any event whose id it has already applied — so a saved log that overlaps the replayed prefix renders once, and `onEvent` only fires for events your UI has not seen.
|
|
297
303
|
|
|
298
|
-
For multiple chat threads, keep one saved event log and session cursor per thread. `agent`, `host`, `reducer`, `session`, `initialEvents`, `initialSession`, `auth`, `headers`, and `
|
|
304
|
+
For multiple chat threads, keep one saved event log and session cursor per thread. `agent`, `host`, `reducer`, `session`, `initialEvents`, `initialSession`, `auth`, `headers`, `optimistic`, and `resume` are read when the hook creates its store, so remount the chat component when switching threads, for example with `key={chat.id}`.
|
|
305
|
+
|
|
306
|
+
Pass `resume: true` with `initialSession` to rebuild the projection from the durable stream after mount. If the stream ends at an in-flight turn, the binding stays attached until that turn reaches its boundary. If the stream already ends at a settled session boundary, replay stops at the history tail.
|
|
307
|
+
|
|
308
|
+
```tsx
|
|
309
|
+
const agent = useEveAgent({
|
|
310
|
+
initialSession: { sessionId, streamIndex: 0 },
|
|
311
|
+
resume: true,
|
|
312
|
+
});
|
|
313
|
+
```
|
|
299
314
|
|
|
300
|
-
If the user can refresh or navigate immediately after pressing send, create your app-level chat row
|
|
315
|
+
If the user can refresh or navigate immediately after pressing send, create your app-level chat row before calling `send()`, then persist the session ID from `onSessionChange`. This lets the reloaded UI mount with that ID and pass `resume: true` while the durable turn is still running.
|
|
301
316
|
|
|
302
317
|
## Custom hosts and headers
|
|
303
318
|
|
|
@@ -44,14 +44,14 @@ Call the binding once for a conversation and read its reactive getters directly.
|
|
|
44
44
|
|
|
45
45
|
The state fields are reactive getters; the commands are ordinary methods:
|
|
46
46
|
|
|
47
|
-
| Property
|
|
48
|
-
|
|
|
49
|
-
| `data`
|
|
50
|
-
| `status`
|
|
51
|
-
| `error`
|
|
52
|
-
| `events`
|
|
53
|
-
| `session`
|
|
54
|
-
| `send`, `respond`, `cancel`, `reset` | Methods |
|
|
47
|
+
| Property | Svelte shape |
|
|
48
|
+
| ---------------------------------------------- | --------------------------------- |
|
|
49
|
+
| `data` | `TData` |
|
|
50
|
+
| `status` | `UseEveAgentStatus` |
|
|
51
|
+
| `error` | `Error \| undefined` |
|
|
52
|
+
| `events` | `readonly MessageStreamEvent[]` |
|
|
53
|
+
| `session` | `ClientSessionState \| undefined` |
|
|
54
|
+
| `send`, `respond`, `resume`, `cancel`, `reset` | Methods |
|
|
55
55
|
|
|
56
56
|
Read the getters directly in templates, `$derived`, or `$effect`. The [shared returned-state reference](./overview#returned-state) describes what each value and command does.
|
|
57
57
|
|
|
@@ -106,7 +106,7 @@ See [Human-in-the-loop prompts](./overview#human-in-the-loop-prompts) for reques
|
|
|
106
106
|
|
|
107
107
|
## Cancel, reset, and resume
|
|
108
108
|
|
|
109
|
-
Call `agent.cancel()` to stop the durable server-side turn while the binding remains attached through settlement. Destroying the component only disconnects its local stream; it does not cancel server execution. Call `agent.reset()` to clear local state and start a new session. Pass `initialSession` and `
|
|
109
|
+
Call `agent.cancel()` to stop the durable server-side turn while the binding remains attached through settlement. Destroying the component only disconnects its local stream; it does not cancel server execution. Call `agent.reset()` to clear local state and start a new session. Pass `initialSession`, `initialEvents`, and `resume: true` to restore a saved conversation and follow an in-flight turn. Use `agent.resume()` directly when restoration is controlled imperatively. See [Resumable sessions](./overview#resumable-sessions) for the persistence contract and [Sending and streaming](./overview#sending-and-streaming) for cancellation behavior.
|
|
110
110
|
|
|
111
111
|
## Custom host and credentials
|
|
112
112
|
|
|
@@ -43,14 +43,14 @@ async function handleSubmit() {
|
|
|
43
43
|
|
|
44
44
|
The state fields are computed refs; the commands are ordinary methods:
|
|
45
45
|
|
|
46
|
-
| Property
|
|
47
|
-
|
|
|
48
|
-
| `data`
|
|
49
|
-
| `status`
|
|
50
|
-
| `error`
|
|
51
|
-
| `events`
|
|
52
|
-
| `session`
|
|
53
|
-
| `send`, `respond`, `cancel`, `reset` | Methods |
|
|
46
|
+
| Property | Vue shape |
|
|
47
|
+
| ---------------------------------------------- | ---------------------------------------------- |
|
|
48
|
+
| `data` | `ComputedRef<TData>` |
|
|
49
|
+
| `status` | `ComputedRef<UseEveAgentStatus>` |
|
|
50
|
+
| `error` | `ComputedRef<Error \| undefined>` |
|
|
51
|
+
| `events` | `ComputedRef<readonly MessageStreamEvent[]>` |
|
|
52
|
+
| `session` | `ComputedRef<ClientSessionState \| undefined>` |
|
|
53
|
+
| `send`, `respond`, `resume`, `cancel`, `reset` | Methods |
|
|
54
54
|
|
|
55
55
|
Destructuring preserves reactivity because each state value remains a ref. Read refs with `.value` in `<script>` and without `.value` in a template. The [shared returned-state reference](./overview#returned-state) describes what each value and command does.
|
|
56
56
|
|
|
@@ -108,7 +108,7 @@ See [Human-in-the-loop prompts](./overview#human-in-the-loop-prompts) for reques
|
|
|
108
108
|
|
|
109
109
|
## Cancel, reset, and resume
|
|
110
110
|
|
|
111
|
-
Call `cancel()` to stop the durable server-side turn while the composable remains attached through settlement. Disposing the component only disconnects its local stream; it does not cancel server execution. Call `reset()` to clear local state and start a new session. Pass `initialSession` and `
|
|
111
|
+
Call `cancel()` to stop the durable server-side turn while the composable remains attached through settlement. Disposing the component only disconnects its local stream; it does not cancel server execution. Call `reset()` to clear local state and start a new session. Pass `initialSession`, `initialEvents`, and `resume: true` to restore a saved conversation and follow an in-flight turn. Use `resume()` directly when restoration is controlled imperatively. See [Resumable sessions](./overview#resumable-sessions) for the persistence contract and [Sending and streaming](./overview#sending-and-streaming) for cancellation behavior.
|
|
112
112
|
|
|
113
113
|
## Custom host and credentials
|
|
114
114
|
|
|
@@ -58,6 +58,8 @@ You are responsible for ensuring any observability or eval provider is approved
|
|
|
58
58
|
|
|
59
59
|
The third configurable surface, [runtime context events](#runtime-context), attaches per-model-call values to these spans.
|
|
60
60
|
|
|
61
|
+
Built-in messaging channels classify their instrumentation metadata with an `audience`: `public`, `private`, or `unknown`. Slack public channels and Chat SDK workspace-visible threads are public; direct and private conversations are private; platform surfaces without enough visibility evidence remain unknown.
|
|
62
|
+
|
|
61
63
|
## Channel delivery traces
|
|
62
64
|
|
|
63
65
|
Instrumentation providers receive `channel.delivery.started` followed by
|
package/docs/tools/overview.mdx
CHANGED
|
@@ -70,10 +70,11 @@ progress with `task.send({ kind: "update", message })` and the terminal result w
|
|
|
70
70
|
in-memory callback dies with the process — so the cross-process executor wire remains
|
|
71
71
|
framework-owned and is not yet a stable authored-tool API.
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
After the initiating turn accepts background tasks, eve supplies runtime-authored state for that
|
|
74
|
+
cohort and instructs the model to acknowledge that the work started without waiting for results.
|
|
75
|
+
Later task-triggered parent turns receive fresh state for the same cohort. The model is instructed
|
|
76
|
+
to keep related intermediate results silent while any task remains pending. Once every related
|
|
77
|
+
task is terminal, the state includes their outputs so the model can combine the useful results.
|
|
77
78
|
|
|
78
79
|
### The `ctx` parameter
|
|
79
80
|
|
|
@@ -73,7 +73,7 @@ export default function Page() {
|
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
`agent.data.messages` and `agent.status` cover most chat UIs. The
|
|
76
|
+
`agent.data.messages` and `agent.status` cover most chat UIs. The generated Web Chat renders HITL prompts directly in the conversation: approvals get action controls, and `ask_question` gets a visible form with vertical choices, a text field, or both. The spend approval from [Step 8](./guard-the-spend) uses the same response path. For the full API, see [Frontend](../guides/frontend/overview).
|
|
77
77
|
|
|
78
78
|
## Replace `placeholderAuth`
|
|
79
79
|
|