eve 0.76.0 → 0.76.3
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 +27 -0
- package/dist/src/channel/channel-address.d.ts +3 -1
- package/dist/src/channel/channel-address.js +1 -1
- package/dist/src/channel/session-stranded-error.d.ts +25 -0
- package/dist/src/channel/session-stranded-error.js +1 -0
- package/dist/src/channel/session.d.ts +13 -6
- package/dist/src/channel/types.d.ts +29 -1
- package/dist/src/chunks/{use-eve-agent-QmriPA-w.js → use-eve-agent-BtKWTEpm.js} +31 -14
- package/dist/src/chunks/{use-eve-agent-D2V9UhLt.js → use-eve-agent-jI6EsYAu.js} +31 -14
- package/dist/src/cli/commands/registry-project.d.ts +10 -3
- package/dist/src/cli/commands/registry-project.js +2 -2
- package/dist/src/cli/commands/registry.js +1 -1
- package/dist/src/cli/dev/tui/runner.js +3 -3
- package/dist/src/cli/dev/tui/stranded-session.d.ts +9 -0
- package/dist/src/cli/dev/tui/stranded-session.js +1 -0
- package/dist/src/client/client-error.d.ts +16 -0
- package/dist/src/client/client-error.js +1 -1
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/index.d.ts +3 -2
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/open-stream.d.ts +5 -3
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session-controls.js +1 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/transcript-reducer.d.ts +46 -0
- package/dist/src/client/transcript-reducer.js +2 -0
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +20 -20
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/context/accessors.d.ts +1 -1
- package/dist/src/context/build-callback-context.js +1 -1
- package/dist/src/context/dynamic-resolve-context.js +1 -1
- package/dist/src/context/keys.d.ts +5 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/context/providers/session.d.ts +1 -0
- package/dist/src/context/providers/session.js +1 -1
- package/dist/src/context/session-context.d.ts +8 -2
- package/dist/src/dynamic/definition.d.ts +7 -1
- package/dist/src/evals/types.d.ts +2 -1
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/eve-channel/request.js +2 -2
- package/dist/src/eve-channel/support.d.ts +2 -0
- package/dist/src/eve-channel/support.js +1 -1
- package/dist/src/execution/agent-sessions/steps.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/eve-workflow-attributes.d.ts +15 -0
- package/dist/src/execution/eve-workflow-attributes.js +1 -1
- package/dist/src/execution/install-workflow-world.d.ts +7 -0
- package/dist/src/execution/install-workflow-world.js +1 -0
- package/dist/src/execution/legacy-session/authorization.js +1 -1
- package/dist/src/execution/legacy-session/inbox.js +1 -1
- package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/handoff-steps.d.ts +11 -0
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/timeout-steps.js +1 -1
- package/dist/src/execution/session-event-stream.d.ts +6 -0
- package/dist/src/execution/session-event-stream.js +1 -1
- package/dist/src/execution/session-inbox/address.d.ts +4 -0
- package/dist/src/execution/session-inbox/address.js +1 -1
- package/dist/src/execution/session-inbox/end-stranded-session.d.ts +22 -0
- package/dist/src/execution/session-inbox/end-stranded-session.js +1 -0
- package/dist/src/execution/session-inbox/hook-release.d.ts +4 -0
- package/dist/src/execution/session-inbox/hook-release.js +1 -0
- package/dist/src/execution/session-inbox/owner.d.ts +48 -0
- package/dist/src/execution/session-inbox/owner.js +1 -0
- package/dist/src/execution/session-inbox/resume.d.ts +12 -0
- package/dist/src/execution/session-inbox/resume.js +1 -1
- package/dist/src/execution/session-inbox/runnable-owner.d.ts +13 -0
- package/dist/src/execution/session-inbox/runnable-owner.js +1 -0
- package/dist/src/execution/session-inbox/stranded-replay-guard.d.ts +16 -0
- package/dist/src/execution/session-inbox/stranded-replay-guard.js +1 -0
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +5 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/compaction/step.js +1 -1
- package/dist/src/harness/input-request-resolution.js +1 -1
- package/dist/src/harness/model-call/call.d.ts +1 -1
- package/dist/src/harness/model-call/call.js +1 -1
- package/dist/src/harness/model-call/errors.d.ts +5 -6
- package/dist/src/harness/model-call/errors.js +1 -1
- package/dist/src/harness/model-call/recovery.d.ts +4 -3
- package/dist/src/harness/model-call/request.d.ts +2 -1
- package/dist/src/harness/model-call/request.js +1 -1
- package/dist/src/harness/model-call/tools.js +1 -1
- package/dist/src/harness/model-profile.d.ts +10 -3
- package/dist/src/harness/model-profile.js +1 -1
- package/dist/src/harness/prompt-cache.d.ts +6 -3
- package/dist/src/harness/prompt-cache.js +1 -1
- package/dist/src/harness/provider-safety.d.ts +2 -1
- package/dist/src/harness/provider-safety.js +1 -1
- package/dist/src/harness/provider-tools.d.ts +1 -1
- package/dist/src/harness/provider-tools.js +1 -1
- package/dist/src/harness/session-machine/transitions.d.ts +3 -1
- package/dist/src/harness/session-machine/transitions.js +1 -1
- package/dist/src/harness/step/context.js +1 -1
- package/dist/src/harness/step-hooks.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +4 -4
- package/dist/src/internal/application/package.d.ts +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/application/stamped-package-version.d.ts +5 -0
- package/dist/src/internal/application/stamped-package-version.js +1 -0
- package/dist/src/internal/authored-definition/core.d.ts +3 -0
- package/dist/src/internal/authored-definition/core.js +1 -1
- package/dist/src/internal/model-auth/available-models.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/workflow/development-run-unavailable-error.d.ts +15 -0
- package/dist/src/internal/workflow/development-run-unavailable-error.js +1 -0
- package/dist/src/internal/workflow/development-world-server.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.d.ts +0 -4
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +2 -2
- package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
- package/dist/src/protocol/message.d.ts +14 -0
- package/dist/src/protocol/message.js +1 -1
- package/dist/src/public/channels/index.d.ts +1 -1
- package/dist/src/public/channels/index.js +1 -1
- package/dist/src/public/context/index.d.ts +1 -1
- package/dist/src/public/definitions/callback-context.d.ts +1 -1
- package/dist/src/public/definitions/channel.d.ts +1 -0
- package/dist/src/public/definitions/channel.js +1 -1
- package/dist/src/public/models/openai/chatgpt/model.js +1 -1
- package/dist/src/public/models/openai/chatgpt/transport.js +1 -1
- package/dist/src/public/tanstack/index.d.ts +40 -0
- package/dist/src/public/tanstack/index.js +1 -0
- package/dist/src/runtime/agent/resolve-model.js +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/setup/flows/model-login.js +1 -1
- package/dist/src/setup/integrations/web/framework.d.ts +8 -0
- package/dist/src/setup/integrations/web/framework.js +1 -0
- package/dist/src/setup/integrations/web/hosting.d.ts +43 -0
- package/dist/src/setup/integrations/web/hosting.js +15 -0
- package/dist/src/setup/integrations/web/setup.d.ts +6 -10
- package/dist/src/setup/integrations/web/setup.js +23 -17
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +6 -2
- package/dist/src/setup/scaffold/create/web-template.js +39 -2
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/dist/src/setup/vercel-project-framework.js +1 -1
- package/dist/src/shared/agent-definition.d.ts +25 -0
- package/dist/src/shared/agent-definition.js +1 -1
- package/dist/src/shared/chatgpt-model.d.ts +8 -0
- package/dist/src/shared/chatgpt-model.js +1 -1
- package/dist/src/subagents/callback-route.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/agent-config.md +32 -1
- package/docs/channels/custom.mdx +26 -0
- package/docs/channels/eve.mdx +8 -5
- package/docs/concepts/built-in-tools.md +17 -0
- package/docs/concepts/execution-model-and-durability.mdx +100 -0
- package/docs/concepts/project-structure.mdx +2 -2
- package/docs/concepts/sessions-runs-and-streaming.md +36 -34
- package/docs/guides/client/messages.mdx +10 -1
- package/docs/guides/deployment/overview.md +2 -2
- package/docs/guides/dev-tui.md +2 -0
- package/docs/guides/frontend/meta.json +9 -1
- package/docs/guides/frontend/nextjs.mdx +1 -1
- package/docs/guides/frontend/overview.mdx +9 -8
- package/docs/guides/frontend/tanstack.mdx +201 -0
- package/docs/guides/session-context.md +1 -0
- package/docs/install-integrations.mdx +1 -1
- package/docs/instructions.mdx +1 -1
- package/docs/reference/typescript-api.md +1 -1
- package/docs/tools/human-in-the-loop.md +2 -0
- package/docs/tutorial/ship-it.mdx +1 -1
- package/package.json +7 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.76.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 592f773: Fix `eve build` failing with "Identifier has already been declared" when a tool callback's destructured parameter or local declaration shadows a variable from an enclosing scope. This also fixes building agents that mount `eve/extensions/git`.
|
|
8
|
+
|
|
9
|
+
## 0.76.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 91f4b68: Add `modelOptions.promptCache` for models eve calls directly. `promptCache: { anthropic: { ttl: "1h" } }` switches eve's Anthropic cache breakpoints to a 1-hour lifetime. `promptCache: { anthropic: {} }` turns breakpoints on for an Anthropic model eve can't recognize from its id, such as a Bedrock application inference profile.
|
|
14
|
+
- c160b22: A session that replaces a retired stranded session names the session it replaced in `ctx.session.predecessor` (also on dynamic resolver contexts) and `session.started` `data.predecessor` (`{ sessionId }`). The new `transcriptReducer()` in `eve/client` folds a session's stream into its user and completed assistant text since the last clear; combine it with `sessions.attach(predecessor.sessionId).stream()` from `eve/server` in a `session.started` user-role dynamic instruction to give the replacement the earlier conversation.
|
|
15
|
+
- 89bd625: Add `eve/tanstack`, a Vite plugin that runs an eve agent inside a TanStack Start app: Nitro proxies `/eve/v1/**` to a local eve server in development, and Vercel builds deploy eve as a sibling service. Set `devServerTimeoutMs` to wait longer for a slow eve dev server to start. `eve build` and `eve dev` now always use Nitro's Rolldown builder, so an agent that shares its root with a TanStack Start app no longer fails to start.
|
|
16
|
+
- b664838: `eve add channel/web` now asks which framework Web Chat uses and can install a TanStack Start app under `apps/web/`, hosted as a separate Vercel service or inside the app through `eve/tanstack`; non-interactive installs keep Next.js unless you pass `--answer 'web-framework="tanstack"'`. Web Chat setup also checks for authored configuration before writing, removes the `vercel.ts` and scripts it wrote when you switch hosting modes, and renders text in the loaded Geist fonts.
|
|
17
|
+
|
|
18
|
+
## 0.76.1
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- fcbd479: A denied tool approval that carries `text` now passes that note to the model in the denial reason instead of dropping it.
|
|
23
|
+
- 9626748: Use build-stamped package metadata in bundled runtimes so serverless functions can start without resolving `eve/package.json` at runtime.
|
|
24
|
+
- 25b3f35: `/login chatgpt` now lists current subscription models such as `gpt-6-luna`, and the default `chatgpt()` model (`gpt-6-luna-fast`) works: eve sends it to Codex as `gpt-6-luna` on the priority service tier, since Codex rejects `-fast` model IDs.
|
|
25
|
+
- 416e63e: Direct OpenAI and `chatgpt()` model calls now send a per-session `promptCacheKey`, which helps OpenAI route a session's calls to the cache holding its prompt prefix. `chatgpt()` calls also send it as the `session-id` header the Codex backend routes on. An authored `providerOptions.openai.promptCacheKey` still takes precedence.
|
|
26
|
+
- b04acbb: On worlds without per-deployment routing, incompatible subagent sessions and workflow tool runs (including tasks) are now cancelled when their queue deliveries arrive, instead of attempting replay on the new eve version. Top-level sessions remain available for replacement or reset, and session timeout workflows continue to run.
|
|
27
|
+
- b04acbb: Sessions whose workflow run cannot execute after an eve upgrade (a stranded session) are no longer accepted and left unanswered, and the local World and Postgres stop replaying and failing them with `CORRUPTED_EVENT_LOG`. eve treats every World other than Vercel as running one eve version at a time, so the next message through a channel address (Slack, `from(address).send()`) ends a stranded session and starts a fresh one. Sends by session ID throw `SessionStrandedError` (`ClientSessionStrandedError` in `eve/client`), and the eve HTTP channel returns `409 session_stranded`; `reset()` ends a stranded session while `clear()` refuses one, and recorded history stays readable with `stream({ follow: false })` or `follow=false` on the stream route. On Worlds other than Vercel, a retired session's own session timeout now ends it at its deadline, so a retired session no longer stays active forever when no message arrives.
|
|
28
|
+
- cf72486: Agents whose OpenAI model is served by an endpoint without OpenAI web search, such as Amazon Bedrock through `createOpenAI({ baseURL })` or AI Gateway, now retry the step without `web_search` instead of failing every turn.
|
|
29
|
+
|
|
3
30
|
## 0.76.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
|
@@ -17,7 +17,9 @@ export type ChannelAddressDeliveryOptions<TState = undefined> = [TState] extends
|
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
19
|
* Dynamic handle for whichever durable session currently owns one channel-local address.
|
|
20
|
-
* Only {@link send} may create a session when the address is unowned
|
|
20
|
+
* Only {@link send} may create a session: when the address is unowned, or in
|
|
21
|
+
* place of a stranded session that another eve version built. Sends to a session whose
|
|
22
|
+
* owner is only unavailable throw `SessionStrandedError` and deliver nothing.
|
|
21
23
|
*/
|
|
22
24
|
interface ChannelAddress<TState = undefined> {
|
|
23
25
|
readonly continuationToken: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createSession,sessionCallbackToTurnCaller}from"#channel/session.js";import{createChannelDeliveryMetadata}from"#channel/delivery-metadata.js";import{normalizeSendInput,serializeUrlFilePartsInMessage}from"#channel/send-input.js";import{DEFAULT_TURN_POLICY}from"#channel/types.js";import{isReservedSessionCommandToken}from"#execution/session-inbox/address.js";function createChannelAddress(e){let t=e.metadata??{},n=`${e.channelName}:${e.continuationToken}`;if(isReservedSessionCommandToken(n))throw Error(`Channel address "${n}" uses eve's reserved session namespace.`);return{continuationToken:e.continuationToken,async deliver(r,i){let a=t.channelKind!==void 0&&t.channelName!==void 0?createChannelDeliveryMetadata(t):void 0,o=normalizeSendInput(r),s=sessionCallbackToTurnCaller(i.callback),c={auth:i.auth,delivery:a,kind:`send`,payload:{...o,message:serializeUrlFilePartsInMessage(o.message)},requestId:t.requestId,turnPolicy:o.message===void 0?void 0:i.turnPolicy??e.turnPolicy??DEFAULT_TURN_POLICY},l=s===void 0?c:{...c,caller:s},u=
|
|
1
|
+
import{createSession,sessionCallbackToTurnCaller}from"#channel/session.js";import{createChannelDeliveryMetadata}from"#channel/delivery-metadata.js";import{normalizeSendInput,serializeUrlFilePartsInMessage}from"#channel/send-input.js";import{DEFAULT_TURN_POLICY}from"#channel/types.js";import{isReservedSessionCommandToken}from"#execution/session-inbox/address.js";function createChannelAddress(e){let t=e.metadata??{},n=`${e.channelName}:${e.continuationToken}`;if(isReservedSessionCommandToken(n))throw Error(`Channel address "${n}" uses eve's reserved session namespace.`);return{continuationToken:e.continuationToken,async deliver(r,i){let a=t.channelKind!==void 0&&t.channelName!==void 0?createChannelDeliveryMetadata(t):void 0,o=normalizeSendInput(r),s=sessionCallbackToTurnCaller(i.callback),c={auth:i.auth,delivery:a,kind:`send`,payload:{...o,message:serializeUrlFilePartsInMessage(o.message)},requestId:t.requestId,turnPolicy:o.message===void 0?void 0:i.turnPolicy??e.turnPolicy??DEFAULT_TURN_POLICY},l=s===void 0?c:{...c,caller:s},u=i.state,d={adapter:u===void 0?e.adapter:{...e.adapter,state:{...e.adapter.state,...u}},auth:i.auth,capabilities:{requestInput:!0},callback:i.callback,channelName:e.channelName,continuationConflictCommand:l,continuationToken:n,delivery:a,initiatorAuth:i.initiatorAuth,input:{context:o.context,message:serializeUrlFilePartsInMessage(o.message)??``,outputSchema:o.outputSchema,state:o.state},requestId:t.requestId,title:i.title},toSession=n=>createSession(n,e.runtime,{...t,turnPolicy:e.turnPolicy}),f=await e.runtime.dispatchContinuation({command:l,continuationToken:n,successor:d});if(f.status===`accepted`)return toSession(f.sessionId);if(o.inputResponses&&o.inputResponses.length>0)throw Error(`Cannot deliver inputResponses — the target session was not found via continuation token.`);return toSession((await e.runtime.createSession(d)).sessionId)},async send(e,t){return await this.deliver({message:e},t)},async respond(e,t){if(e===void 0||e.length===0)throw Error(`respond() requires at least one input response.`);return await this.deliver({inputResponses:e},t)},async cancel(t){return await e.runtime.dispatchContinuation({command:{kind:`cancel`,turnId:t?.turnId},continuationToken:n})},async compact(){return await e.runtime.dispatchContinuation({command:{kind:`compact`},continuationToken:n})},async clear(){return await e.runtime.dispatchContinuation({command:{kind:`clear`},continuationToken:n})},async reset(t){return await e.runtime.dispatchContinuation({command:{kind:`reset`,reason:t?.reason},continuationToken:n})},async resolveSession(){let r=await e.runtime.resolveContinuation(n);return r===void 0?void 0:createSession(r.sessionId,e.runtime,{...t,turnPolicy:e.turnPolicy})}}}function createChannelAddressFn(e){return t=>createChannelAddress({...e,continuationToken:t})}export{createChannelAddress,createChannelAddressFn};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** The owner of a stranded session, as far as it recorded itself. */
|
|
2
|
+
interface StrandedSessionOwner {
|
|
3
|
+
/** eve version that built the owner, when it recorded one. */
|
|
4
|
+
readonly eveVersion?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Thrown when sending, responding, clearing, or following the live stream of
|
|
8
|
+
* a session whose owner another eve version built, on a World that only runs
|
|
9
|
+
* this build, so the owner can never execute again. Nothing is delivered and
|
|
10
|
+
* nothing is mutated. Historical reads with `follow: false` still succeed.
|
|
11
|
+
* Call `reset()` to end the session, then start a new one. Narrow with
|
|
12
|
+
* {@link SessionStrandedError.is}.
|
|
13
|
+
*/
|
|
14
|
+
export declare class SessionStrandedError extends Error {
|
|
15
|
+
readonly owner: StrandedSessionOwner;
|
|
16
|
+
constructor(owner: StrandedSessionOwner, message?: string);
|
|
17
|
+
/** Narrows stranded-session errors across bundle boundaries, where `instanceof` can miss. */
|
|
18
|
+
static is(error: unknown): error is SessionStrandedError;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* One actionable sentence pair that names the cause, the version, and the
|
|
22
|
+
* next step. `nextStep` replaces the default recovery instruction.
|
|
23
|
+
*/
|
|
24
|
+
export declare function describeStrandedSession(owner: StrandedSessionOwner, nextStep?: string): string;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var SessionStrandedError=class SessionStrandedError extends Error{owner;constructor(e,t){super(t??describeStrandedSession(e)),this.name=`SessionStrandedError`,this.owner=e}static is(e){return e instanceof SessionStrandedError||typeof e==`object`&&!!e&&Reflect.get(e,`name`)===`SessionStrandedError`&&typeof Reflect.get(e,`owner`)==`object`}};function describeStrandedSession(e,t){return`This session is stranded: ${e.eveVersion===void 0?`it was created by an earlier eve release`:`it was created by eve ${e.eveVersion}`} on a deployment that is no longer available, so it cannot process messages. ${t??`Reset the session to start fresh.`}`}export{SessionStrandedError,describeStrandedSession};
|
|
@@ -2,16 +2,20 @@ import type { ContextAccessor } from "#context/key.js";
|
|
|
2
2
|
import { type ChannelDeliverySource } from "#channel/delivery-metadata.js";
|
|
3
3
|
import type { MessageStreamEvent } from "#protocol/message.js";
|
|
4
4
|
import type { UserContent } from "ai";
|
|
5
|
-
import type { CancelTurnResult, ClearSessionResult, CompactSessionResult, ResetSessionResult, Runtime, SessionAuthContext, SessionCallback, SessionSendCommandResult, TurnPolicy, TurnCaller } from "#channel/types.js";
|
|
5
|
+
import type { CancelTurnResult, ClearSessionResult, CompactSessionResult, GetEventStreamOptions, ResetSessionResult, Runtime, SessionAuthContext, SessionCallback, SessionSendCommandResult, TurnPolicy, TurnCaller } from "#channel/types.js";
|
|
6
6
|
import type { SessionAuth } from "#context/keys.js";
|
|
7
7
|
import { type InputResponse, type StrictInputResponses } from "#shared/input.js";
|
|
8
8
|
import type { JsonObject } from "#shared/json.js";
|
|
9
9
|
/** Immutable-ID handle for one exact durable session. */
|
|
10
10
|
export interface Session {
|
|
11
11
|
readonly id: string;
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Sends a message to this exact session ID without creating or following a
|
|
14
|
+
* replacement. Throws `SessionStrandedError` when the session's owner cannot
|
|
15
|
+
* execute here; nothing is delivered. Call {@link reset} to end it.
|
|
16
|
+
*/
|
|
13
17
|
send(message: string | UserContent, options: SessionSendOptions): Promise<SessionSendCommandResult>;
|
|
14
|
-
/** Answers pending input requests on this exact session ID. */
|
|
18
|
+
/** Answers pending input requests on this exact session ID. Throws `SessionStrandedError` like {@link send}. */
|
|
15
19
|
respond<const TResponses extends readonly InputResponse[]>(inputResponses: StrictInputResponses<TResponses>, options: SessionRespondOptions): Promise<SessionSendCommandResult>;
|
|
16
20
|
/** Requests cancellation of this exact session's active turn. */
|
|
17
21
|
cancel(options?: {
|
|
@@ -25,9 +29,12 @@ export interface Session {
|
|
|
25
29
|
reset(options?: {
|
|
26
30
|
reason?: string;
|
|
27
31
|
}): Promise<ResetSessionResult>;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Opens the recorded stream. Following it throws `SessionStrandedError`
|
|
34
|
+
* while its owner is stranded; `follow: false` reads recorded history up to
|
|
35
|
+
* the current tail without inspecting or changing the session.
|
|
36
|
+
*/
|
|
37
|
+
getEventStream(options?: GetEventStreamOptions): Promise<ReadableStream<MessageStreamEvent>>;
|
|
31
38
|
getStreamTailIndex(): Promise<number>;
|
|
32
39
|
}
|
|
33
40
|
interface SessionDeliveryOptions {
|
|
@@ -31,7 +31,10 @@ export type CompactSessionResult = {
|
|
|
31
31
|
} | {
|
|
32
32
|
readonly status: "no_active_session";
|
|
33
33
|
};
|
|
34
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Result of queueing a manual context clear for a session. A stranded session
|
|
36
|
+
* cannot run the clear, so it throws `SessionStrandedError` instead.
|
|
37
|
+
*/
|
|
35
38
|
export type ClearSessionResult = {
|
|
36
39
|
readonly status: "accepted";
|
|
37
40
|
readonly sessionId: string;
|
|
@@ -210,6 +213,11 @@ export type SessionCommandResult<TCommand extends SessionCommand = SessionComman
|
|
|
210
213
|
export interface DispatchContinuationInput<TCommand extends SessionCommand = SessionCommand> {
|
|
211
214
|
readonly command: TCommand;
|
|
212
215
|
readonly continuationToken: string;
|
|
216
|
+
/**
|
|
217
|
+
* Fresh creation inputs for a send. Used only when the address's owner is
|
|
218
|
+
* stranded: the runtime ends it and starts this successor in its place.
|
|
219
|
+
*/
|
|
220
|
+
readonly successor?: RunInput;
|
|
213
221
|
}
|
|
214
222
|
export interface DispatchSessionInput<TCommand extends SessionCommand = SessionCommand> {
|
|
215
223
|
readonly command: TCommand;
|
|
@@ -528,7 +536,17 @@ export interface Runtime {
|
|
|
528
536
|
* completion.
|
|
529
537
|
*/
|
|
530
538
|
createSession(input: RunInput): Promise<RunHandle>;
|
|
539
|
+
/**
|
|
540
|
+
* Sends a command to whichever session owns a continuation address. When
|
|
541
|
+
* that owner is stranded, a send with a `successor` ends it and is accepted
|
|
542
|
+
* by the successor; a send without one, or a `clear`, throws
|
|
543
|
+
* `SessionStrandedError`, and a `reset` ends it.
|
|
544
|
+
*/
|
|
531
545
|
dispatchContinuation<TCommand extends SessionCommand>(input: DispatchContinuationInput<TCommand>): Promise<SessionCommandResult<TCommand>>;
|
|
546
|
+
/**
|
|
547
|
+
* Sends a command to one exact session. A send or `clear` to a stranded
|
|
548
|
+
* session throws `SessionStrandedError`; a `reset` ends it.
|
|
549
|
+
*/
|
|
532
550
|
dispatchSession<TCommand extends SessionCommand>(input: DispatchSessionInput<TCommand>): Promise<SessionCommandResult<TCommand>>;
|
|
533
551
|
/**
|
|
534
552
|
* Resolves the session that currently owns a continuation token without
|
|
@@ -549,6 +567,10 @@ export interface Runtime {
|
|
|
549
567
|
* first event to yield. Negative values read relative to the current tail.
|
|
550
568
|
* The framework HTTP session-stream route forwards the `startIndex` query
|
|
551
569
|
* parameter unchanged.
|
|
570
|
+
*
|
|
571
|
+
* A following read throws `SessionStrandedError` when the session's owner
|
|
572
|
+
* cannot execute here. A historical read (`follow: false`) never inspects
|
|
573
|
+
* or changes the session's lifecycle.
|
|
552
574
|
*/
|
|
553
575
|
getEventStream(sessionId: string, options?: GetEventStreamOptions): Promise<ReadableStream<MessageStreamEvent>>;
|
|
554
576
|
/**
|
|
@@ -569,4 +591,10 @@ export interface GetEventStreamOptions {
|
|
|
569
591
|
* (replay the entire stream).
|
|
570
592
|
*/
|
|
571
593
|
readonly startIndex?: number;
|
|
594
|
+
/**
|
|
595
|
+
* Whether to keep following events recorded after the read opens. When
|
|
596
|
+
* `false`, the stream ends at the durable tail observed when it opens, and
|
|
597
|
+
* it stays readable while the session is stranded. Defaults to `true`.
|
|
598
|
+
*/
|
|
599
|
+
readonly follow?: boolean;
|
|
572
600
|
}
|
|
@@ -550,25 +550,39 @@ var ClientError = class extends Error {
|
|
|
550
550
|
constructor(status, body, headers) {
|
|
551
551
|
const normalizedHeaders = Object.freeze(Object.fromEntries(new Headers(headers).entries()));
|
|
552
552
|
const contentType = normalizedHeaders["content-type"]?.toLowerCase();
|
|
553
|
+
const parsed = parseJsonObject$1(body);
|
|
553
554
|
let message = body || `Server returned ${status}.`;
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
const parsed = JSON.parse(body);
|
|
557
|
-
if (isObject(parsed)) {
|
|
558
|
-
if (typeof parsed.error === "string") message = parsed.error;
|
|
559
|
-
if (typeof parsed.code === "string") code = parsed.code;
|
|
560
|
-
}
|
|
561
|
-
} catch {
|
|
562
|
-
if (contentType?.includes("text/html")) message = `Server returned ${status} with an HTML response. Check the eve route and development server configuration.`;
|
|
563
|
-
}
|
|
555
|
+
if (typeof parsed?.error === "string") message = parsed.error;
|
|
556
|
+
else if (parsed === void 0 && contentType?.includes("text/html")) message = `Server returned ${status} with an HTML response. Check the eve route and development server configuration.`;
|
|
564
557
|
super(message);
|
|
565
558
|
this.name = "ClientError";
|
|
566
|
-
this.code = code;
|
|
559
|
+
this.code = typeof parsed?.code === "string" ? parsed.code : void 0;
|
|
567
560
|
this.status = status;
|
|
568
561
|
this.body = body;
|
|
569
562
|
this.headers = normalizedHeaders;
|
|
570
563
|
}
|
|
571
564
|
};
|
|
565
|
+
var ClientSessionStrandedError = class extends ClientError {
|
|
566
|
+
eveVersion;
|
|
567
|
+
constructor(status, body, headers, details) {
|
|
568
|
+
super(status, body, headers);
|
|
569
|
+
this.name = "ClientSessionStrandedError";
|
|
570
|
+
this.eveVersion = details.eveVersion;
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
function createClientError(status, body, headers) {
|
|
574
|
+
const parsed = status === 409 ? parseJsonObject$1(body) : void 0;
|
|
575
|
+
if (parsed?.code !== "session_stranded") return new ClientError(status, body, headers);
|
|
576
|
+
return new ClientSessionStrandedError(status, body, headers, { eveVersion: typeof parsed.eveVersion === "string" ? parsed.eveVersion : void 0 });
|
|
577
|
+
}
|
|
578
|
+
function parseJsonObject$1(body) {
|
|
579
|
+
try {
|
|
580
|
+
const parsed = JSON.parse(body);
|
|
581
|
+
return isObject(parsed) ? parsed : void 0;
|
|
582
|
+
} catch {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
572
586
|
|
|
573
587
|
//#endregion
|
|
574
588
|
//#region src/shared/errors.ts
|
|
@@ -1583,6 +1597,7 @@ async function* followStreamIterable(input) {
|
|
|
1583
1597
|
caughtUp = true;
|
|
1584
1598
|
input.onCaughtUp?.();
|
|
1585
1599
|
}
|
|
1600
|
+
if (event.type === "session.failed" || event.type === "session.completed") return;
|
|
1586
1601
|
if (input.follow === false && tailIndex !== void 0 && startIndex > tailIndex) return;
|
|
1587
1602
|
}
|
|
1588
1603
|
} catch (error) {
|
|
@@ -1612,6 +1627,7 @@ async function openStreamBody(input) {
|
|
|
1612
1627
|
if (controlVersion !== void 0) searchParams[EVE_STREAM_CONTROL_VERSION_QUERY] = controlVersion;
|
|
1613
1628
|
if (input.startIndex !== 0) searchParams.startIndex = String(input.startIndex);
|
|
1614
1629
|
if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
|
|
1630
|
+
if (input.follow === false) searchParams.follow = "false";
|
|
1615
1631
|
for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
|
|
1616
1632
|
input.signal?.throwIfAborted();
|
|
1617
1633
|
const url = createClientUrl(input.host, input.path, Object.keys(searchParams).length > 0 ? searchParams : void 0);
|
|
@@ -1652,7 +1668,8 @@ async function openStreamBody(input) {
|
|
|
1652
1668
|
lastStatus = response.status;
|
|
1653
1669
|
lastBody = await response.text();
|
|
1654
1670
|
lastHeaders = response.headers;
|
|
1655
|
-
|
|
1671
|
+
const error = createClientError(response.status, lastBody, response.headers);
|
|
1672
|
+
if (error instanceof ClientSessionStrandedError || !retryPolicy.retryableErrorStatuses.has(response.status)) throw error;
|
|
1656
1673
|
if (attempt < openRetryPolicy.maxAttempts - 1) {
|
|
1657
1674
|
await sleep(retryDelayMs, input.signal);
|
|
1658
1675
|
retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
|
|
@@ -1909,7 +1926,7 @@ async function postJson(input) {
|
|
|
1909
1926
|
signal: input.signal
|
|
1910
1927
|
}, input.context.redirect));
|
|
1911
1928
|
const text = await response.text();
|
|
1912
|
-
if (!response.ok) throw
|
|
1929
|
+
if (!response.ok) throw createClientError(response.status, text, response.headers);
|
|
1913
1930
|
try {
|
|
1914
1931
|
return {
|
|
1915
1932
|
payload: JSON.parse(text),
|
|
@@ -2503,7 +2520,7 @@ async function postTurn(context, path, input, requireMessage, stubs) {
|
|
|
2503
2520
|
});
|
|
2504
2521
|
if (!response.ok) {
|
|
2505
2522
|
const responseBody = await response.text();
|
|
2506
|
-
throw
|
|
2523
|
+
throw createClientError(response.status, responseBody, response.headers);
|
|
2507
2524
|
}
|
|
2508
2525
|
return response;
|
|
2509
2526
|
}
|
|
@@ -551,25 +551,39 @@ var ClientError = class extends Error {
|
|
|
551
551
|
constructor(status, body, headers) {
|
|
552
552
|
const normalizedHeaders = Object.freeze(Object.fromEntries(new Headers(headers).entries()));
|
|
553
553
|
const contentType = normalizedHeaders["content-type"]?.toLowerCase();
|
|
554
|
+
const parsed = parseJsonObject$1(body);
|
|
554
555
|
let message = body || `Server returned ${status}.`;
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const parsed = JSON.parse(body);
|
|
558
|
-
if (isObject(parsed)) {
|
|
559
|
-
if (typeof parsed.error === "string") message = parsed.error;
|
|
560
|
-
if (typeof parsed.code === "string") code = parsed.code;
|
|
561
|
-
}
|
|
562
|
-
} catch {
|
|
563
|
-
if (contentType?.includes("text/html")) message = `Server returned ${status} with an HTML response. Check the eve route and development server configuration.`;
|
|
564
|
-
}
|
|
556
|
+
if (typeof parsed?.error === "string") message = parsed.error;
|
|
557
|
+
else if (parsed === void 0 && contentType?.includes("text/html")) message = `Server returned ${status} with an HTML response. Check the eve route and development server configuration.`;
|
|
565
558
|
super(message);
|
|
566
559
|
this.name = "ClientError";
|
|
567
|
-
this.code = code;
|
|
560
|
+
this.code = typeof parsed?.code === "string" ? parsed.code : void 0;
|
|
568
561
|
this.status = status;
|
|
569
562
|
this.body = body;
|
|
570
563
|
this.headers = normalizedHeaders;
|
|
571
564
|
}
|
|
572
565
|
};
|
|
566
|
+
var ClientSessionStrandedError = class extends ClientError {
|
|
567
|
+
eveVersion;
|
|
568
|
+
constructor(status, body, headers, details) {
|
|
569
|
+
super(status, body, headers);
|
|
570
|
+
this.name = "ClientSessionStrandedError";
|
|
571
|
+
this.eveVersion = details.eveVersion;
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
function createClientError(status, body, headers) {
|
|
575
|
+
const parsed = status === 409 ? parseJsonObject$1(body) : void 0;
|
|
576
|
+
if (parsed?.code !== "session_stranded") return new ClientError(status, body, headers);
|
|
577
|
+
return new ClientSessionStrandedError(status, body, headers, { eveVersion: typeof parsed.eveVersion === "string" ? parsed.eveVersion : void 0 });
|
|
578
|
+
}
|
|
579
|
+
function parseJsonObject$1(body) {
|
|
580
|
+
try {
|
|
581
|
+
const parsed = JSON.parse(body);
|
|
582
|
+
return isObject(parsed) ? parsed : void 0;
|
|
583
|
+
} catch {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
573
587
|
|
|
574
588
|
//#endregion
|
|
575
589
|
//#region src/shared/errors.ts
|
|
@@ -1584,6 +1598,7 @@ async function* followStreamIterable(input) {
|
|
|
1584
1598
|
caughtUp = true;
|
|
1585
1599
|
input.onCaughtUp?.();
|
|
1586
1600
|
}
|
|
1601
|
+
if (event.type === "session.failed" || event.type === "session.completed") return;
|
|
1587
1602
|
if (input.follow === false && tailIndex !== void 0 && startIndex > tailIndex) return;
|
|
1588
1603
|
}
|
|
1589
1604
|
} catch (error) {
|
|
@@ -1613,6 +1628,7 @@ async function openStreamBody(input) {
|
|
|
1613
1628
|
if (controlVersion !== void 0) searchParams[EVE_STREAM_CONTROL_VERSION_QUERY] = controlVersion;
|
|
1614
1629
|
if (input.startIndex !== 0) searchParams.startIndex = String(input.startIndex);
|
|
1615
1630
|
if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
|
|
1631
|
+
if (input.follow === false) searchParams.follow = "false";
|
|
1616
1632
|
for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
|
|
1617
1633
|
input.signal?.throwIfAborted();
|
|
1618
1634
|
const url = createClientUrl(input.host, input.path, Object.keys(searchParams).length > 0 ? searchParams : void 0);
|
|
@@ -1653,7 +1669,8 @@ async function openStreamBody(input) {
|
|
|
1653
1669
|
lastStatus = response.status;
|
|
1654
1670
|
lastBody = await response.text();
|
|
1655
1671
|
lastHeaders = response.headers;
|
|
1656
|
-
|
|
1672
|
+
const error = createClientError(response.status, lastBody, response.headers);
|
|
1673
|
+
if (error instanceof ClientSessionStrandedError || !retryPolicy.retryableErrorStatuses.has(response.status)) throw error;
|
|
1657
1674
|
if (attempt < openRetryPolicy.maxAttempts - 1) {
|
|
1658
1675
|
await sleep(retryDelayMs, input.signal);
|
|
1659
1676
|
retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
|
|
@@ -1910,7 +1927,7 @@ async function postJson(input) {
|
|
|
1910
1927
|
signal: input.signal
|
|
1911
1928
|
}, input.context.redirect));
|
|
1912
1929
|
const text = await response.text();
|
|
1913
|
-
if (!response.ok) throw
|
|
1930
|
+
if (!response.ok) throw createClientError(response.status, text, response.headers);
|
|
1914
1931
|
try {
|
|
1915
1932
|
return {
|
|
1916
1933
|
payload: JSON.parse(text),
|
|
@@ -2504,7 +2521,7 @@ async function postTurn(context, path, input, requireMessage, stubs) {
|
|
|
2504
2521
|
});
|
|
2505
2522
|
if (!response.ok) {
|
|
2506
2523
|
const responseBody = await response.text();
|
|
2507
|
-
throw
|
|
2524
|
+
throw createClientError(response.status, responseBody, response.headers);
|
|
2508
2525
|
}
|
|
2509
2526
|
return response;
|
|
2510
2527
|
}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import type { RegistryConfig } from "#compiled/shadcn-registry/index.js";
|
|
2
|
+
import type { Asker } from "#setup/ask.js";
|
|
3
|
+
import { type WebChatFramework } from "#setup/integrations/web/framework.js";
|
|
2
4
|
interface AddRegistryMappingsResult {
|
|
3
5
|
added: string[];
|
|
4
6
|
skippedBuiltIn: string[];
|
|
5
7
|
skippedExisting: string[];
|
|
6
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Picks the framework `eve add channel/web` installs, before it writes any file.
|
|
11
|
+
* An app already in `apps/web` decides; an explicit answer that conflicts fails.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveWebChatFramework(appRoot: string, asker: Asker, answers?: Readonly<Record<string, unknown>>): Promise<WebChatFramework>;
|
|
7
14
|
/** Resolves and prepares the root package that owns Web Chat. */
|
|
8
|
-
export declare function prepareWebChatProjectRoot(appRoot: string): Promise<string>;
|
|
15
|
+
export declare function prepareWebChatProjectRoot(appRoot: string, framework?: WebChatFramework): Promise<string>;
|
|
9
16
|
/** Reads registry namespace mappings from package.json. */
|
|
10
17
|
export declare function readRegistryConfig(appRoot: string): Promise<RegistryConfig>;
|
|
11
|
-
export declare function addWebRegistryTsconfig(source: string, path: string): string;
|
|
18
|
+
export declare function addWebRegistryTsconfig(source: string, path: string, framework?: WebChatFramework): string;
|
|
12
19
|
/** Prepares the TypeScript host configuration shadcn registry items expect. */
|
|
13
|
-
export declare function prepareWebRegistryProject(appRoot: string): Promise<void>;
|
|
20
|
+
export declare function prepareWebRegistryProject(appRoot: string, framework?: WebChatFramework): Promise<void>;
|
|
14
21
|
/** Adds explicit registry namespace mappings to package.json. */
|
|
15
22
|
export declare function addRegistryMappings(appRoot: string, arguments_: readonly string[]): Promise<AddRegistryMappingsResult>;
|
|
16
23
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readFile,writeFile}from"node:fs/promises";import{join}from"node:path";import{resolveEveProjectContext}from"#internal/project-context.js";import{applyEdits,modify,parse}from"#compiled/jsonc-parser/index.js";import{WEB_APP_TEMPLATE_FILES}from"#setup/scaffold/create/web-template.js";function errorMessage(e){return e instanceof Error?e.message:String(e)}function isRegistrySource(e){return typeof e==`string`?!0:typeof e!=`object`||!e||!(`url`in e)?!1:typeof e.url==`string`}function parseRegistries(e,t){if(t===void 0)return{};if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`${e} has an invalid registries field.`);let n={};for(let[r,i]of Object.entries(t)){if(!r.startsWith(`@`)||!isRegistrySource(i))throw Error(`${e} has an invalid registry entry for ${r}.`);n[r]=i}return n}async function readRegistryPackage(e){let t=await resolveEveProjectContext(e),n=join(t.environmentRoot,`package.json`),r;try{r=JSON.parse(await readFile(n,`utf8`))}catch(e){throw Error(`Could not read ${n}: ${errorMessage(e)}`)}if(typeof r!=`object`||!r||Array.isArray(r))throw Error(`${n} must contain a JSON object.`);let i=r;return{path:n,document:i,config:{registries:parseRegistries(n,i.registries)}}}function parseRegistryMapping(e){let t=e.indexOf(`=`),n=t===-1?e:e.slice(0,t),r=t===-1?``:e.slice(t+1);if(!n.startsWith(`@`))throw Error(`Registry namespaces must start with @: ${n}`);if(!r.includes(`{name}`))throw Error(`Pass a registry URL containing {name}, for example ${n}=https://example.com/r/{name}.json.`);return{namespace:n,url:r}}async function
|
|
2
|
-
`};function setJsoncValue(e,t,n){return applyEdits(e,modify(e,t,n,{formattingOptions:JSONC_FORMATTING}))}function addWebRegistryTsconfig(e,t){let
|
|
1
|
+
import{readFile,writeFile}from"node:fs/promises";import{join}from"node:path";import{resolveEveProjectContext}from"#internal/project-context.js";import{applyEdits,modify,parse}from"#compiled/jsonc-parser/index.js";import{WEB_CHAT_FRAMEWORK_LABELS,WEB_FRAMEWORK_QUESTION,detectWebChatFramework}from"#setup/integrations/web/framework.js";import{WEB_APP_TANSTACK_TEMPLATE_FILES,WEB_APP_TEMPLATE_FILES}from"#setup/scaffold/create/web-template.js";function errorMessage(e){return e instanceof Error?e.message:String(e)}function isRegistrySource(e){return typeof e==`string`?!0:typeof e!=`object`||!e||!(`url`in e)?!1:typeof e.url==`string`}function parseRegistries(e,t){if(t===void 0)return{};if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`${e} has an invalid registries field.`);let n={};for(let[r,i]of Object.entries(t)){if(!r.startsWith(`@`)||!isRegistrySource(i))throw Error(`${e} has an invalid registry entry for ${r}.`);n[r]=i}return n}async function readRegistryPackage(e){let t=await resolveEveProjectContext(e),n=join(t.environmentRoot,`package.json`),r;try{r=JSON.parse(await readFile(n,`utf8`))}catch(e){throw Error(`Could not read ${n}: ${errorMessage(e)}`)}if(typeof r!=`object`||!r||Array.isArray(r))throw Error(`${n} must contain a JSON object.`);let i=r;return{path:n,document:i,config:{registries:parseRegistries(n,i.registries)}}}function parseRegistryMapping(e){let t=e.indexOf(`=`),n=t===-1?e:e.slice(0,t),r=t===-1?``:e.slice(t+1);if(!n.startsWith(`@`))throw Error(`Registry namespaces must start with @: ${n}`);if(!r.includes(`{name}`))throw Error(`Pass a registry URL containing {name}, for example ${n}=https://example.com/r/{name}.json.`);return{namespace:n,url:r}}const WEB_CHAT_SCRIPTS={next:{"dev:web":`next dev apps/web`,"build:web":`next build apps/web`},tanstack:{"dev:web":`vite dev apps/web`,"build:web":`vite build apps/web`}};function isWebChatScriptDefault(e,t){return Object.values(WEB_CHAT_SCRIPTS).some(n=>n[e]===t)}async function resolveWebChatFramework(e,t,n={}){let r=await resolveEveProjectContext(e);if(r.kind===`workspace`)throw Error(`Web Chat setup requires a selected workspace agent.`);let i=await detectWebChatFramework(join(r.environmentRoot,`apps`,`web`));if(i!==void 0&&!(WEB_FRAMEWORK_QUESTION.key in n))return i;let a=await t.ask(WEB_FRAMEWORK_QUESTION);if(i!==void 0&&a!==i)throw Error(`apps/web already contains a ${WEB_CHAT_FRAMEWORK_LABELS[i]} app. Remove apps/web to switch Web Chat to ${WEB_CHAT_FRAMEWORK_LABELS[a]}, or answer ${WEB_FRAMEWORK_QUESTION.key}="${i}".`);return a}async function prepareWebChatProjectRoot(e,t=`next`){let n=await resolveEveProjectContext(e);if(n.kind===`workspace`)throw Error(`Web Chat setup requires a selected workspace agent.`);let r=n.environmentRoot,i=join(r,`package.json`),a=await readFile(i,`utf8`),o=JSON.parse(a),s={...o.scripts};for(let[e,n]of Object.entries(WEB_CHAT_SCRIPTS[t])){let t=s[e];(t===void 0||isWebChatScriptDefault(e,t))&&(s[e]=n)}return await writeFile(i,`${JSON.stringify({...o,scripts:s},null,2)}\n`,`utf8`),r}async function readRegistryConfig(e){return(await readRegistryPackage(e)).config}const JSONC_FORMATTING={insertSpaces:!0,tabSize:2,eol:`
|
|
2
|
+
`};function setJsoncValue(e,t,n){return applyEdits(e,modify(e,t,n,{formattingOptions:JSONC_FORMATTING}))}const WEB_REGISTRY_TSCONFIG_SOURCES={next:WEB_APP_TEMPLATE_FILES[`tsconfig.json`],tanstack:WEB_APP_TANSTACK_TEMPLATE_FILES[`tsconfig.json`]};function addWebRegistryTsconfig(e,t,n=`next`){let r=[],i=parse(e,r,{allowTrailingComma:!0});if(r.length>0||typeof i!=`object`||!i||Array.isArray(i))throw Error(`Could not add Web Chat because ${t} is not a valid JSON object.`);let a=i,o=JSON.parse(WEB_REGISTRY_TSCONFIG_SOURCES[n]),s=a.compilerOptions?.paths?.[`@/*`];if(s!==void 0&&(!Array.isArray(s)||!s.includes(`./*`)))throw Error(`Could not add Web Chat because ${t} already defines @/* without mapping it to ./*.`);let c=e;for(let[e,t]of Object.entries(o.compilerOptions)){if(e===`paths`||e===`plugins`)continue;let n=a.compilerOptions?.[e];if(n===void 0)c=setJsoncValue(c,[`compilerOptions`,e],t);else if(e===`types`&&Array.isArray(n)&&Array.isArray(t)){let e=[...new Set([...n,...t])];e.length>n.length&&(c=setJsoncValue(c,[`compilerOptions`,`types`],e))}}s===void 0&&(c=setJsoncValue(c,[`compilerOptions`,`paths`,`@/*`],[`./*`]));let l=a.compilerOptions?.plugins??[],u=l.some(e=>typeof e==`object`&&!!e&&`name`in e&&e.name===`next`);return n===`next`&&!u&&(c=setJsoncValue(c,[`compilerOptions`,`plugins`],[...l,{name:`next`}])),c=setJsoncValue(c,[`include`],[...new Set([...a.include??[],...o.include])]),c=setJsoncValue(c,[`exclude`],[...new Set([...a.exclude??[],...o.exclude])]),c}async function prepareWebRegistryProject(e,t=`next`){let n=join(e,`apps`,`web`,`tsconfig.json`),r;try{r=await readFile(n,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw Error(`Could not add Web Chat because ${n} could not be read: ${errorMessage(e)}`)}let i=addWebRegistryTsconfig(r,n,t);i!==r&&await writeFile(n,i,`utf8`)}async function addRegistryMappings(e,t){if(t.length===0)throw Error(`Pass at least one registry to add.`);let n=await readRegistryPackage(e),r=t.map(parseRegistryMapping),i={...n.config.registries},a={added:[],skippedBuiltIn:[],skippedExisting:[]};for(let e of r)e.namespace===`@shadcn`||e.namespace===`@skills`?a.skippedBuiltIn.push(e.namespace):i[e.namespace]===void 0?(i[e.namespace]=e.url,a.added.push(e.namespace)):a.skippedExisting.push(e.namespace);return a.added.length>0&&await writeFile(n.path,`${JSON.stringify({...n.document,registries:i},null,2)}\n`,`utf8`),a}export{addRegistryMappings,addWebRegistryTsconfig,prepareWebChatProjectRoot,prepareWebRegistryProject,readRegistryConfig,resolveWebChatFramework};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{hasInteractiveTerminal}from"./preconditions.js";import{serializeHeadlessSetupEvent}from"./setup-headless.js";import{prepareWebChatProjectRoot,prepareWebRegistryProject,readRegistryConfig}from"./registry-project.js";import{errorMessage,reportRegistryCompletion,resolveRegistryItemForAdd,runRegistryAction,setupReminder,setupResumeCommand}from"./registry-recovery.js";import{runRegistryAddCommand}from"./registry-add-command.js";import{RegistrySetupFailedError,runDeclaredSetups}from"./registry-declared-setups.js";import{installRegistryItemTransaction}from"./registry-install-transaction.js";import{eveMetadataFromRegistryItem,parseOfficialRegistrySearchMetadata}from"./registry-metadata.js";import{prepareDeclaredPnpmBuildPolicy}from"./registry-pnpm-build-policy-flow.js";import{printRegistrySearchResults,registryViewText}from"./registry-presentation.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{createPrompter}from"#setup/prompter.js";import{WizardCancelledError}from"#setup/step.js";import{addRegistryItems,getRegistryItems,searchRegistries}from"#compiled/shadcn-registry/index.js";import semver from"#compiled/semver/index.js";const defaultAddCommandDependencies={createPrompter,hasInteractiveTerminal,loadSetupCommandRunner:async()=>(await import(`./registry-setup-command.js`)).runRegistrySetupCommand,prepareWebRegistryProject};function resolveOfficialRegistryUrl(e=process.env.EVE_DEV_OFFICIAL_REGISTRY_URL){if(e===void 0)return`https://eve.dev/r`;let t;try{t=new URL(e)}catch{throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`);if(t.username!==``||t.password!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include credentials.`);if(t.search!==``||t.hash!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include a query or fragment.`);return t.pathname=t.pathname.replace(/\/+$/,``),t.toString().replace(/\/$/,``)}const OFFICIAL_REGISTRY=resolveOfficialRegistryUrl(),OFFICIAL_CATALOG=`${OFFICIAL_REGISTRY}/registry.json`,SKILLS_REGISTRY=`@skills`;function itemAddress(e){return e.startsWith(`@`)||/^https?:\/\//.test(e)?e:`${OFFICIAL_REGISTRY}/${e}.json`}function assertCompatibleEveVersion(e){if(e===void 0)return;let t=resolveInstalledPackageInfo().version;if(semver.validRange(e)===null)throw Error(`Registry item has an invalid eve version requirement: ${e}.`);if(!semver.subset(t,e))throw Error(`This registry item requires eve ${e}, but this project is using eve ${t}. Upgrade eve and run the command again.`)}function isOfficialItemAddress(e){return e.startsWith(`${OFFICIAL_REGISTRY}/`)}function withBuiltInRegistries(e){return{...e,registries:{[SKILLS_REGISTRY]:`https://www.skills.sh/r/{name}?agent=eve`,...e.registries}}}async function readEveRegistryConfig(e){return withBuiltInRegistries(await readRegistryConfig(e))}function configuredRegistrySources(e){return Object.keys(e.registries??{})}function validateRegistrySource(e){if(e!==void 0&&!e.startsWith(`@`)&&!/^https?:\/\//.test(e))throw Error(`Registry sources must be a namespace or URL: ${e}`)}async function loadOfficialSearchMetadata(){let e=await fetch(OFFICIAL_CATALOG);if(!e.ok)throw Error(`Could not read the eve registry (${e.status}).`);return parseOfficialRegistrySearchMetadata(await e.json())}function searchItemAddress(e){return e.registry===OFFICIAL_CATALOG?e.name:e.addCommandArgument}function enrichSearchItem(e,t){let n=searchItemAddress(e);return{item:e,address:n,...t.get(n)}}function registrySourceLabel(e){return e===OFFICIAL_CATALOG?`eve`:e===SKILLS_REGISTRY?`skills.sh`:e}function searchPresentationSections(e,t,n){return e.flatMap(e=>{let r=t.get(e);return r===void 0?[]:[{label:registrySourceLabel(e),items:r.items.map(e=>enrichSearchItem(e,n)),total:r.pagination.total}]})}async function printAddSuggestions(e,t,n){try{let r=n.split(`/`).at(-1)||n,{resultsBySource:i,sources:a,metadataByAddress:o}=await searchRegistryCatalog(t,{limit:5,query:r}),s=searchPresentationSections(a,i,o);if(s.every(e=>e.items.length===0))return;e.log(`Did you mean?`),printRegistrySearchResults(e,{query:r,sections:s})}catch{}}async function searchRegistryCatalog(e,t){validateRegistrySource(t.source);let n=await readEveRegistryConfig(e),r=t.source?[t.source]:[OFFICIAL_CATALOG,...configuredRegistrySources(n).filter(e=>t.query!==void 0||e!==SKILLS_REGISTRY)],i=await Promise.all(r.map(async e=>{try{return{result:await searchRegistries([e],{config:n,limit:t.limit??500,query:t.query}),source:e}}catch(t){return{error:t,source:e}}})),a=[],o=new Map;for(let e of i)if(`error`in e)a.push({message:errorMessage(e.error),registry:e.source});else{let t=e.result.errors??[];if(a.push(...t),t.length===0){let t=e.result.items.filter(t=>t.registry===e.source);o.set(e.source,{...e.result,items:t,pagination:{...e.result.pagination,total:e.result.items.length===t.length?e.result.pagination.total:0}})}}let s=new Map(a.map(e=>[`${e.registry}\0${e.message}`,e])),c=o.has(OFFICIAL_CATALOG)?await loadOfficialSearchMetadata():new Map,l=o.get(OFFICIAL_CATALOG);if(l!==void 0){let e=l.items.filter(e=>c.get(searchItemAddress(e))?.hidden!==!0);l.items=e,l.pagination={...l.pagination,total:e.length},l.items.sort((e,t)=>{let rank=e=>c.get(searchItemAddress(e))?.implementation===`native`?0:1;return rank(e)-rank(t)})}let u=[...o.values()];return{config:n,result:{items:u.flatMap(e=>e.items),pagination:{hasMore:u.some(e=>e.pagination.hasMore),limit:t.limit??500,offset:0,total:u.reduce((e,t)=>e+t.pagination.total,0)},...s.size>0?{errors:[...s.values()]}:{}},resultsBySource:o,sources:r,metadataByAddress:c}}async function browseRegistryCatalog(e,t={}){let{result:n}=await searchRegistryCatalog(e,t);return{items:n.items.map(e=>{let t={address:e.registry===OFFICIAL_CATALOG?e.name:e.addCommandArgument,name:e.name,source:e.registry===OFFICIAL_CATALOG?`Vercel`:e.registry};return e.title!==void 0&&(t.title=e.title),e.type!==void 0&&(t.type=e.type),e.description!==void 0&&(t.description=e.description),t}),total:n.pagination.total,errors:n.errors??[]}}async function browseRegistryItems(e,t,n,r,i={}){let{result:a,resultsBySource:o,sources:s,metadataByAddress:c}=await searchRegistryCatalog(t,{limit:i.limit,query:n,source:r}),l=a.errors??[];if(i.json||o.size>0){let t=a.items.map(e=>({...e,...c.get(searchItemAddress(e))})),r={query:n,sections:searchPresentationSections(s,o,c)};i.json&&(r.json={...a,items:t}),printRegistrySearchResults(e,r)}for(let t of l)e.error(`${t.registry}: ${t.message}`);l.length>0&&(process.exitCode=1)}async function installRegistryItem(e,t,n={},r=defaultAddCommandDependencies){let i,a=[],o={error:e=>{i=e},log:e=>a.push(e)},s=process.exitCode,c;try{c=await runAddCommand(o,e,t,{...n,yes:n.prompter===void 0||n.yes,setupAuthorized:n.prompter!==void 0,throwSetupFailures:!0},r)}catch(e){if(process.exitCode=s,!(e instanceof RegistrySetupFailedError))throw e;let t={resumeCommand:e.resumeCommand,reason:e.reason};return e.prerequisite!==void 0&&(t.prerequisite=e.prerequisite),{output:a,setupIncomplete:t}}if(process.exitCode=s,i!==void 0)throw Error(i);if(c===!1)throw new WizardCancelledError;if(c===`setup-incomplete`)return{output:a,setupIncomplete:{resumeCommand:setupResumeCommand(t)}};let l={output:a};return c!==void 0&&(l.setup=c),l}async function runAddCommand(e,t,n,r,i=defaultAddCommandDependencies){let setupIncomplete=t=>(r.silent!==!0&&e.log(setupReminder(n,t)),`setup-incomplete`);return runRegistryAction(e,t,async()=>{let a=itemAddress(n),o=a===itemAddress(`channel/web`)&&r.skipInstall!==!0?await prepareWebChatProjectRoot(t):t,s=await readEveRegistryConfig(t);if(r.skipInstall===!0){if(r.overwrite===!0)throw Error(`--overwrite cannot be used with --skip-install.`);if(r.skipSetup===!0)throw Error(`--skip-install cannot be used with --skip-setup.`);if(!isOfficialItemAddress(a))throw Error(`Setup flows are currently supported only for official eve registry items.`)}let c=await resolveRegistryItemForAdd(e,async()=>(await getRegistryItems([a],{config:s}))[0],()=>printAddSuggestions(e,t,n));if(!c.found)return;let l=c.item,u=isOfficialItemAddress(a)?eveMetadataFromRegistryItem(l):void 0;if(assertCompatibleEveVersion(u?.requires),r.skipInstall===!0){if(u?.setup===void 0)throw Error(`Registry item "${n}" does not declare a setup flow.`);let a=await runDeclaredSetups({logger:e,appRoot:t,item:n,setups:u.setup,options:r,dependencies:i,resumeCommand:setupResumeCommand(n)});return a===!1&&!r.nonInteractive?setupIncomplete(`cancelled`):reportRegistryCompletion(e,n,a,r)}if(!await prepareDeclaredPnpmBuildPolicy({logger:e,appRoot:o,item:n,policies:u?.install?.pnpm?.buildScripts,options:r}))return!1;if(a===itemAddress(`channel/web`)&&await(i.prepareWebRegistryProject??prepareWebRegistryProject)(o),await installRegistryItemTransaction({appRoot:o,item:n,registryItem:l,nonInteractive:r.nonInteractive,logger:e,install:async()=>{await addRegistryItems([a],{config:s,cwd:o,overwrite:r.overwrite,silent:r.silent})}}),u?.setup===void 0)return reportRegistryCompletion(e,n,{facts:[]},r);let d=i.hasInteractiveTerminal?.()??defaultAddCommandDependencies.hasInteractiveTerminal();if(r.nonInteractive&&e.log(serializeHeadlessSetupEvent({version:1,type:`progress`,message:r.skipInstall?`Setup ${n}`:`Installed ${n}`})),r.skipSetup===!0)return r.nonInteractive?reportRegistryCompletion(e,n,{facts:[]},r):setupIncomplete(`skipped`);if(!r.nonInteractive&&!r.yes&&!d&&r.setupAuthorized!==!0)return setupIncomplete(`skipped`);if(!r.nonInteractive&&!r.yes&&r.setupAuthorized!==!0)try{if(await(r.prompter??i.createPrompter?.()??defaultAddCommandDependencies.createPrompter()).select({message:`Set up ${n} now?`,initialValue:`yes`,options:[{value:`yes`,label:`Yes`},{value:`no`,label:`No`}]})===`no`)return setupIncomplete(`skipped`)}catch(e){if(!(e instanceof WizardCancelledError))throw e;return setupIncomplete(`cancelled`)}let f=await runDeclaredSetups({logger:e,appRoot:t,item:n,setups:u.setup,options:{...r,force:r.overwrite},dependencies:i,resumeCommand:setupResumeCommand(n)});return f===!1&&!r.nonInteractive?setupIncomplete(`cancelled`):reportRegistryCompletion(e,n,f,r)},{rethrow:e=>r.throwSetupFailures===!0&&e instanceof RegistrySetupFailedError})}async function runRegistryListCommand(e,t,n,r={}){await runRegistryAction(e,t,()=>browseRegistryItems(e,t,void 0,n,r))}async function runRegistrySearchCommand(e,t,n,r,i={}){await runRegistryAction(e,t,()=>browseRegistryItems(e,t,n,r,{...i,limit:i.limit??10}))}async function runRegistryViewCommand(e,t,n,r={}){await runRegistryAction(e,t,async()=>{let i=await readEveRegistryConfig(t),a=await getRegistryItems([itemAddress(n)],{config:i}),o=a.length===1?a[0]:a;e.log(r.json?JSON.stringify(o,null,2):registryViewText(n,o))})}export{browseRegistryCatalog,installRegistryItem,resolveOfficialRegistryUrl,runAddCommand,runRegistryAddCommand,runRegistryListCommand,runRegistrySearchCommand,runRegistryViewCommand};
|
|
1
|
+
import{hasInteractiveTerminal}from"./preconditions.js";import{headlessSetupContinuation,serializeHeadlessSetupEvent}from"./setup-headless.js";import{prepareWebChatProjectRoot,prepareWebRegistryProject,readRegistryConfig,resolveWebChatFramework}from"./registry-project.js";import{errorMessage,reportRegistryCompletion,resolveRegistryItemForAdd,runRegistryAction,setupReminder,setupResumeCommand}from"./registry-recovery.js";import{runRegistryAddCommand}from"./registry-add-command.js";import{RegistrySetupFailedError,runDeclaredSetups}from"./registry-declared-setups.js";import{installRegistryItemTransaction}from"./registry-install-transaction.js";import{eveMetadataFromRegistryItem,parseOfficialRegistrySearchMetadata}from"./registry-metadata.js";import{prepareDeclaredPnpmBuildPolicy}from"./registry-pnpm-build-policy-flow.js";import{printRegistrySearchResults,registryViewText}from"./registry-presentation.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{createPrompter}from"#setup/prompter.js";import{WizardCancelledError}from"#setup/step.js";import{InvalidAnswerError,headlessAsker,interactiveAsker,withAnswers,withPolicy}from"#setup/ask.js";import{setupQuestionToWire}from"#setup/setup-question-wire.js";import{addRegistryItems,getRegistryItems,searchRegistries}from"#compiled/shadcn-registry/index.js";import semver from"#compiled/semver/index.js";const defaultAddCommandDependencies={createPrompter,hasInteractiveTerminal,loadSetupCommandRunner:async()=>(await import(`./registry-setup-command.js`)).runRegistrySetupCommand,prepareWebRegistryProject};function resolveOfficialRegistryUrl(e=process.env.EVE_DEV_OFFICIAL_REGISTRY_URL){if(e===void 0)return`https://eve.dev/r`;let t;try{t=new URL(e)}catch{throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`);if(t.username!==``||t.password!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include credentials.`);if(t.search!==``||t.hash!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include a query or fragment.`);return t.pathname=t.pathname.replace(/\/+$/,``),t.toString().replace(/\/$/,``)}const OFFICIAL_REGISTRY=resolveOfficialRegistryUrl(),OFFICIAL_CATALOG=`${OFFICIAL_REGISTRY}/registry.json`,SKILLS_REGISTRY=`@skills`;function itemAddress(e){return e.startsWith(`@`)||/^https?:\/\//.test(e)?e:`${OFFICIAL_REGISTRY}/${e}.json`}const WEB_CHAT_ITEMS={next:`channel/web`,tanstack:`channel/web-tanstack`};async function askWebChatFramework(e,t,n,r,i){let a=r.nonInteractive===!0,o=r.setupAuthorized===!0||(i.hasInteractiveTerminal??defaultAddCommandDependencies.hasInteractiveTerminal)(),s=withAnswers(r.answers??{})(r.yes===!0||a||!o?withPolicy(`assume`)(headlessAsker()):interactiveAsker(r.prompter??i.createPrompter?.()??defaultAddCommandDependencies.createPrompter()));try{return await resolveWebChatFramework(t,s,r.answers)}catch(t){if(t instanceof WizardCancelledError)return!1;if(!a||!(t instanceof InvalidAnswerError))throw t;let i=setupQuestionToWire(t.question);e.error(serializeHeadlessSetupEvent({version:1,type:`blocked`,item:n,installed:!1,completedItems:[],status:`input_required`,question:i,issue:{code:`invalid_answer`,message:t.message},next:headlessSetupContinuation({item:n,installed:!1,answers:r.answers,question:i})})),process.exitCode=2;return}}function assertCompatibleEveVersion(e){if(e===void 0)return;let t=resolveInstalledPackageInfo().version;if(semver.validRange(e)===null)throw Error(`Registry item has an invalid eve version requirement: ${e}.`);if(!semver.subset(t,e))throw Error(`This registry item requires eve ${e}, but this project is using eve ${t}. Upgrade eve and run the command again.`)}function isOfficialItemAddress(e){return e.startsWith(`${OFFICIAL_REGISTRY}/`)}function withBuiltInRegistries(e){return{...e,registries:{[SKILLS_REGISTRY]:`https://www.skills.sh/r/{name}?agent=eve`,...e.registries}}}async function readEveRegistryConfig(e){return withBuiltInRegistries(await readRegistryConfig(e))}function configuredRegistrySources(e){return Object.keys(e.registries??{})}function validateRegistrySource(e){if(e!==void 0&&!e.startsWith(`@`)&&!/^https?:\/\//.test(e))throw Error(`Registry sources must be a namespace or URL: ${e}`)}async function loadOfficialSearchMetadata(){let e=await fetch(OFFICIAL_CATALOG);if(!e.ok)throw Error(`Could not read the eve registry (${e.status}).`);return parseOfficialRegistrySearchMetadata(await e.json())}function searchItemAddress(e){return e.registry===OFFICIAL_CATALOG?e.name:e.addCommandArgument}function enrichSearchItem(e,t){let n=searchItemAddress(e);return{item:e,address:n,...t.get(n)}}function registrySourceLabel(e){return e===OFFICIAL_CATALOG?`eve`:e===SKILLS_REGISTRY?`skills.sh`:e}function searchPresentationSections(e,t,n){return e.flatMap(e=>{let r=t.get(e);return r===void 0?[]:[{label:registrySourceLabel(e),items:r.items.map(e=>enrichSearchItem(e,n)),total:r.pagination.total}]})}async function printAddSuggestions(e,t,n){try{let r=n.split(`/`).at(-1)||n,{resultsBySource:i,sources:a,metadataByAddress:o}=await searchRegistryCatalog(t,{limit:5,query:r}),s=searchPresentationSections(a,i,o);if(s.every(e=>e.items.length===0))return;e.log(`Did you mean?`),printRegistrySearchResults(e,{query:r,sections:s})}catch{}}async function searchRegistryCatalog(e,t){validateRegistrySource(t.source);let n=await readEveRegistryConfig(e),r=t.source?[t.source]:[OFFICIAL_CATALOG,...configuredRegistrySources(n).filter(e=>t.query!==void 0||e!==SKILLS_REGISTRY)],i=await Promise.all(r.map(async e=>{try{return{result:await searchRegistries([e],{config:n,limit:t.limit??500,query:t.query}),source:e}}catch(t){return{error:t,source:e}}})),a=[],o=new Map;for(let e of i)if(`error`in e)a.push({message:errorMessage(e.error),registry:e.source});else{let t=e.result.errors??[];if(a.push(...t),t.length===0){let t=e.result.items.filter(t=>t.registry===e.source);o.set(e.source,{...e.result,items:t,pagination:{...e.result.pagination,total:e.result.items.length===t.length?e.result.pagination.total:0}})}}let s=new Map(a.map(e=>[`${e.registry}\0${e.message}`,e])),c=o.has(OFFICIAL_CATALOG)?await loadOfficialSearchMetadata():new Map,l=o.get(OFFICIAL_CATALOG);if(l!==void 0){let e=l.items.filter(e=>c.get(searchItemAddress(e))?.hidden!==!0);l.items=e,l.pagination={...l.pagination,total:e.length},l.items.sort((e,t)=>{let rank=e=>c.get(searchItemAddress(e))?.implementation===`native`?0:1;return rank(e)-rank(t)})}let u=[...o.values()];return{config:n,result:{items:u.flatMap(e=>e.items),pagination:{hasMore:u.some(e=>e.pagination.hasMore),limit:t.limit??500,offset:0,total:u.reduce((e,t)=>e+t.pagination.total,0)},...s.size>0?{errors:[...s.values()]}:{}},resultsBySource:o,sources:r,metadataByAddress:c}}async function browseRegistryCatalog(e,t={}){let{result:n}=await searchRegistryCatalog(e,t);return{items:n.items.map(e=>{let t={address:e.registry===OFFICIAL_CATALOG?e.name:e.addCommandArgument,name:e.name,source:e.registry===OFFICIAL_CATALOG?`Vercel`:e.registry};return e.title!==void 0&&(t.title=e.title),e.type!==void 0&&(t.type=e.type),e.description!==void 0&&(t.description=e.description),t}),total:n.pagination.total,errors:n.errors??[]}}async function browseRegistryItems(e,t,n,r,i={}){let{result:a,resultsBySource:o,sources:s,metadataByAddress:c}=await searchRegistryCatalog(t,{limit:i.limit,query:n,source:r}),l=a.errors??[];if(i.json||o.size>0){let t=a.items.map(e=>({...e,...c.get(searchItemAddress(e))})),r={query:n,sections:searchPresentationSections(s,o,c)};i.json&&(r.json={...a,items:t}),printRegistrySearchResults(e,r)}for(let t of l)e.error(`${t.registry}: ${t.message}`);l.length>0&&(process.exitCode=1)}async function installRegistryItem(e,t,n={},r=defaultAddCommandDependencies){let i,a=[],o={error:e=>{i=e},log:e=>a.push(e)},s=process.exitCode,c;try{c=await runAddCommand(o,e,t,{...n,yes:n.prompter===void 0||n.yes,setupAuthorized:n.prompter!==void 0,throwSetupFailures:!0},r)}catch(e){if(process.exitCode=s,!(e instanceof RegistrySetupFailedError))throw e;let t={resumeCommand:e.resumeCommand,reason:e.reason};return e.prerequisite!==void 0&&(t.prerequisite=e.prerequisite),{output:a,setupIncomplete:t}}if(process.exitCode=s,i!==void 0)throw Error(i);if(c===!1)throw new WizardCancelledError;if(c===`setup-incomplete`)return{output:a,setupIncomplete:{resumeCommand:setupResumeCommand(t)}};let l={output:a};return c!==void 0&&(l.setup=c),l}async function runAddCommand(e,t,n,r,i=defaultAddCommandDependencies){let setupIncomplete=t=>(r.silent!==!0&&e.log(setupReminder(n,t)),`setup-incomplete`);return runRegistryAction(e,t,async()=>{let a=itemAddress(n),o;if(a===itemAddress(WEB_CHAT_ITEMS.next)&&r.skipInstall!==!0){let a=await askWebChatFramework(e,t,n,r,i);if(a===!1||a===void 0)return a;o=a}let s=o===void 0?a:itemAddress(WEB_CHAT_ITEMS[o]),c=o===void 0?t:await prepareWebChatProjectRoot(t,o),l=await readEveRegistryConfig(t);if(r.skipInstall===!0){if(r.overwrite===!0)throw Error(`--overwrite cannot be used with --skip-install.`);if(r.skipSetup===!0)throw Error(`--skip-install cannot be used with --skip-setup.`);if(!isOfficialItemAddress(a))throw Error(`Setup flows are currently supported only for official eve registry items.`)}let u=await resolveRegistryItemForAdd(e,async()=>(await getRegistryItems([s],{config:l}))[0],()=>printAddSuggestions(e,t,n));if(!u.found)return;let d=u.item,f=isOfficialItemAddress(a)?eveMetadataFromRegistryItem(d):void 0;if(assertCompatibleEveVersion(f?.requires),r.skipInstall===!0){if(f?.setup===void 0)throw Error(`Registry item "${n}" does not declare a setup flow.`);let a=await runDeclaredSetups({logger:e,appRoot:t,item:n,setups:f.setup,options:r,dependencies:i,resumeCommand:setupResumeCommand(n)});return a===!1&&!r.nonInteractive?setupIncomplete(`cancelled`):reportRegistryCompletion(e,n,a,r)}if(!await prepareDeclaredPnpmBuildPolicy({logger:e,appRoot:c,item:n,policies:f?.install?.pnpm?.buildScripts,options:r}))return!1;if(o!==void 0&&await(i.prepareWebRegistryProject??prepareWebRegistryProject)(c,o),await installRegistryItemTransaction({appRoot:c,item:n,registryItem:d,nonInteractive:r.nonInteractive,logger:e,install:async()=>{await addRegistryItems([s],{config:l,cwd:c,overwrite:r.overwrite,silent:r.silent})}}),f?.setup===void 0)return reportRegistryCompletion(e,n,{facts:[]},r);let p=i.hasInteractiveTerminal?.()??defaultAddCommandDependencies.hasInteractiveTerminal();if(r.nonInteractive&&e.log(serializeHeadlessSetupEvent({version:1,type:`progress`,message:r.skipInstall?`Setup ${n}`:`Installed ${n}`})),r.skipSetup===!0)return r.nonInteractive?reportRegistryCompletion(e,n,{facts:[]},r):setupIncomplete(`skipped`);if(!r.nonInteractive&&!r.yes&&!p&&r.setupAuthorized!==!0)return setupIncomplete(`skipped`);if(!r.nonInteractive&&!r.yes&&r.setupAuthorized!==!0)try{if(await(r.prompter??i.createPrompter?.()??defaultAddCommandDependencies.createPrompter()).select({message:`Set up ${n} now?`,initialValue:`yes`,options:[{value:`yes`,label:`Yes`},{value:`no`,label:`No`}]})===`no`)return setupIncomplete(`skipped`)}catch(e){if(!(e instanceof WizardCancelledError))throw e;return setupIncomplete(`cancelled`)}let m=await runDeclaredSetups({logger:e,appRoot:t,item:n,setups:f.setup,options:{...r,force:r.overwrite},dependencies:i,resumeCommand:setupResumeCommand(n)});return m===!1&&!r.nonInteractive?setupIncomplete(`cancelled`):reportRegistryCompletion(e,n,m,r)},{rethrow:e=>r.throwSetupFailures===!0&&e instanceof RegistrySetupFailedError})}async function runRegistryListCommand(e,t,n,r={}){await runRegistryAction(e,t,()=>browseRegistryItems(e,t,void 0,n,r))}async function runRegistrySearchCommand(e,t,n,r,i={}){await runRegistryAction(e,t,()=>browseRegistryItems(e,t,n,r,{...i,limit:i.limit??10}))}async function runRegistryViewCommand(e,t,n,r={}){await runRegistryAction(e,t,async()=>{let i=await readEveRegistryConfig(t),a=await getRegistryItems([itemAddress(n)],{config:i}),o=a.length===1?a[0]:a;e.log(r.json?JSON.stringify(o,null,2):registryViewText(n,o))})}export{browseRegistryCatalog,installRegistryItem,resolveOfficialRegistryUrl,runAddCommand,runRegistryAddCommand,runRegistryListCommand,runRegistrySearchCommand,runRegistryViewCommand};
|