eve 0.31.2 → 0.32.0
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 +30 -0
- package/dist/src/chunks/{use-eve-agent-CF5D6jSV.js → use-eve-agent-CX87G1vU.js} +30 -5
- package/dist/src/chunks/{use-eve-agent-DbYZLG0h.js → use-eve-agent-DwyRde1N.js} +30 -5
- package/dist/src/cli/commands/integration-connect.d.ts +1 -0
- package/dist/src/cli/commands/integration-connect.js +1 -1
- package/dist/src/cli/commands/integration-setup.d.ts +4 -0
- package/dist/src/cli/commands/integration-setup.js +1 -1
- package/dist/src/cli/commands/register-integration-commands.js +1 -1
- package/dist/src/cli/commands/register-registry-commands.js +1 -1
- package/dist/src/cli/commands/registry-declared-setups.d.ts +23 -0
- package/dist/src/cli/commands/registry-declared-setups.js +1 -0
- package/dist/src/cli/commands/registry-metadata.d.ts +69 -0
- package/dist/src/cli/commands/registry-metadata.js +1 -1
- package/dist/src/cli/commands/registry-package.d.ts +3 -3
- package/dist/src/cli/commands/registry-package.js +1 -1
- package/dist/src/cli/commands/registry-presentation.d.ts +20 -0
- package/dist/src/cli/commands/registry-presentation.js +7 -0
- package/dist/src/cli/commands/registry-search-presentation.d.ts +16 -0
- package/dist/src/cli/commands/registry-search-presentation.js +6 -0
- package/dist/src/cli/commands/registry-setup-command.d.ts +5 -2
- package/dist/src/cli/commands/registry-setup-command.js +1 -2
- package/dist/src/cli/commands/registry.d.ts +16 -7
- package/dist/src/cli/commands/registry.js +1 -6
- package/dist/src/cli/commands/setup-answers.d.ts +2 -0
- package/dist/src/cli/commands/setup-answers.js +1 -0
- package/dist/src/cli/commands/setup-headless.d.ts +79 -0
- package/dist/src/cli/commands/setup-headless.js +1 -0
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/setup-commands.js +3 -3
- package/dist/src/cli/dev/tui/setup-flow.d.ts +8 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +12 -12
- package/dist/src/cli/dev/tui/traces/trace-conversation.d.ts +1 -1
- package/dist/src/cli/dev/tui/tui-prompter.js +1 -1
- package/dist/src/client/url.d.ts +5 -0
- package/dist/src/client/url.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +8 -8
- package/dist/src/compiled/@ai-sdk/anthropic/index.d.ts +33 -13
- package/dist/src/compiled/@ai-sdk/anthropic/index.js +4 -2
- package/dist/src/compiled/@ai-sdk/google/index.d.ts +50 -3
- package/dist/src/compiled/@ai-sdk/google/index.js +7 -7
- package/dist/src/compiled/@ai-sdk/mcp/index.d.ts +33 -3
- package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/openai/index.d.ts +140 -9
- package/dist/src/compiled/@ai-sdk/openai/index.js +9 -6
- package/dist/src/compiled/@ai-sdk/otel/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/provider/index.d.ts +300 -6
- package/dist/src/compiled/@ai-sdk/provider-utils/index.d.ts +70 -20
- package/dist/src/compiled/@opentelemetry/api/index.d.ts +2 -1
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +1 -1
- package/dist/src/compiled/@vercel/otel/index.d.ts +6 -0
- package/dist/src/compiled/@vercel/sandbox/index.js +1 -1
- package/dist/src/compiled/_chunks/node/undici-CUIybhQ2.js +95 -0
- package/dist/src/compiled/_chunks/workflow/dist-eUxFublw.js +77 -0
- package/dist/src/compiled/shadcn-registry/index.js +309 -215
- package/dist/src/compiler/extension-compatibility.d.ts +10 -10
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/context/build-callback-context.js +1 -1
- package/dist/src/execution/authorization-callback-match.d.ts +14 -0
- package/dist/src/execution/authorization-callback-match.js +1 -0
- package/dist/src/execution/next-driver-action.d.ts +1 -0
- package/dist/src/execution/parked-delivery-wait.d.ts +16 -1
- package/dist/src/execution/parked-delivery-wait.js +1 -1
- package/dist/src/execution/sandbox/abort-bound-session.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/docker.js +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.d.ts +1 -0
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/execution/sandbox/ensure.js +1 -1
- package/dist/src/execution/session-command-inbox.d.ts +26 -1
- package/dist/src/execution/session-command-inbox.js +1 -1
- package/dist/src/execution/turn-execution-cursor.d.ts +1 -0
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-steps.d.ts +3 -4
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/authorization.d.ts +24 -11
- package/dist/src/harness/authorization.js +1 -1
- package/dist/src/harness/input-extraction.js +1 -1
- package/dist/src/harness/input-requests.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/tool-loop.js +2 -2
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/connection.js +1 -1
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/protocol/routes.d.ts +8 -6
- package/dist/src/protocol/routes.js +1 -1
- package/dist/src/public/channels/linear/linearChannel.d.ts +2 -0
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/linear/verify.js +1 -1
- package/dist/src/public/channels/slack/attachments.js +1 -1
- package/dist/src/public/channels/slack/defaults.js +1 -1
- package/dist/src/public/channels/slack/hitl.d.ts +14 -1
- package/dist/src/public/channels/slack/hitl.js +2 -2
- package/dist/src/public/connections/index.d.ts +1 -0
- package/dist/src/public/definitions/callback-context.d.ts +2 -2
- package/dist/src/public/definitions/connections/mcp.d.ts +9 -0
- package/dist/src/public/definitions/connections/openapi.d.ts +9 -0
- package/dist/src/public/definitions/connections/tool-call.d.ts +21 -0
- package/dist/src/public/definitions/connections/tool-call.js +1 -0
- package/dist/src/public/definitions/sandbox.d.ts +1 -1
- package/dist/src/public/definitions/tool.d.ts +9 -9
- package/dist/src/public/sandbox/index.d.ts +1 -1
- package/dist/src/public/tools/web-search.d.ts +2 -2
- package/dist/src/runtime/connections/callback-route.d.ts +4 -5
- package/dist/src/runtime/connections/callback-route.js +1 -1
- package/dist/src/runtime/connections/mcp-client.js +1 -1
- package/dist/src/runtime/connections/openapi-client.js +1 -1
- package/dist/src/runtime/connections/provided-arguments.d.ts +9 -0
- package/dist/src/runtime/connections/provided-arguments.js +1 -0
- package/dist/src/runtime/connections/scoped-authorization.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +2 -2
- package/dist/src/runtime/framework-tools/todo.js +1 -1
- package/dist/src/runtime/input/types.d.ts +1 -4
- package/dist/src/runtime/resolve-connection.js +1 -1
- package/dist/src/runtime/types.d.ts +2 -0
- package/dist/src/sandbox/state.d.ts +1 -0
- package/dist/src/setup/ask-editable.d.ts +22 -0
- package/dist/src/setup/ask-editable.js +1 -0
- package/dist/src/setup/ask-signals.d.ts +23 -0
- package/dist/src/setup/ask-signals.js +1 -0
- package/dist/src/setup/ask.d.ts +24 -25
- package/dist/src/setup/ask.js +1 -1
- package/dist/src/setup/boxes/deploy-project.js +1 -1
- package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
- package/dist/src/setup/connection-connector.js +3 -2
- package/dist/src/setup/flows/registry-session.d.ts +33 -0
- package/dist/src/setup/flows/registry-session.js +1 -0
- package/dist/src/setup/flows/registry.d.ts +16 -0
- package/dist/src/setup/flows/registry.js +1 -1
- package/dist/src/setup/index.js +1 -1
- package/dist/src/setup/integrations/discord/setup.d.ts +19 -7
- package/dist/src/setup/integrations/discord/setup.js +4 -3
- package/dist/src/setup/integrations/github/setup.d.ts +36 -7
- package/dist/src/setup/integrations/github/setup.js +2 -2
- package/dist/src/setup/integrations/linear/setup.d.ts +21 -9
- package/dist/src/setup/integrations/linear/setup.js +2 -2
- package/dist/src/setup/integrations/photon/management.d.ts +8 -1
- package/dist/src/setup/integrations/photon/management.js +1 -1
- package/dist/src/setup/integrations/photon/setup-flow.d.ts +28 -24
- package/dist/src/setup/integrations/photon/setup-flow.js +3 -3
- package/dist/src/setup/integrations/photon/setup.d.ts +1 -3
- package/dist/src/setup/integrations/photon/setup.js +1 -1
- package/dist/src/setup/integrations/registry.d.ts +1 -1
- package/dist/src/setup/integrations/registry.js +1 -1
- package/dist/src/setup/integrations/runner.d.ts +14 -11
- package/dist/src/setup/integrations/runner.js +1 -1
- package/dist/src/setup/integrations/shared/prerequisite.d.ts +17 -0
- package/dist/src/setup/integrations/shared/prerequisite.js +1 -0
- package/dist/src/setup/integrations/shared/ui.d.ts +22 -15
- package/dist/src/setup/integrations/shared/ui.js +2 -2
- package/dist/src/setup/integrations/shared/vercel-project.d.ts +11 -0
- package/dist/src/setup/integrations/shared/vercel-project.js +1 -0
- package/dist/src/setup/integrations/slack/setup.d.ts +25 -10
- package/dist/src/setup/integrations/slack/setup.js +1 -1
- package/dist/src/setup/integrations/types.d.ts +43 -13
- package/dist/src/setup/integrations/types.js +1 -1
- package/dist/src/setup/integrations/web/setup.d.ts +22 -3
- package/dist/src/setup/integrations/web/setup.js +1 -1
- package/dist/src/setup/prompter.d.ts +8 -0
- package/dist/src/setup/question-options.d.ts +15 -0
- package/dist/src/setup/question-options.js +1 -0
- package/dist/src/setup/registry-setup-client.d.ts +3 -4
- package/dist/src/setup/registry-setup-client.js +2 -2
- package/dist/src/setup/registry-setup-completion.d.ts +3 -0
- package/dist/src/setup/registry-setup-completion.js +1 -0
- package/dist/src/setup/registry-setup-protocol.d.ts +22 -3
- package/dist/src/setup/registry-setup-protocol.js +1 -1
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +55 -3
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/dist/src/setup/setup-question-wire.d.ts +48 -0
- package/dist/src/setup/setup-question-wire.js +1 -0
- package/dist/src/setup/slackbot.d.ts +5 -1
- package/dist/src/setup/slackbot.js +1 -1
- package/dist/src/setup/state.d.ts +2 -2
- package/dist/src/shared/sandbox-backend.d.ts +6 -0
- package/dist/src/shared/sandbox-session.d.ts +15 -0
- package/dist/src/shared/tool-definition.d.ts +2 -2
- package/dist/src/shared/tool-schema.d.ts +5 -4
- package/dist/src/shared/tool-schema.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tracing/agent-otel-provider.d.ts +5 -38
- package/dist/src/tracing/agent-otel-provider.js +2 -2
- package/dist/src/tracing/agent-span-id-generator.d.ts +15 -0
- package/dist/src/tracing/agent-span-id-generator.js +1 -0
- package/dist/src/tracing/agent-trace-context-store.d.ts +1 -1
- package/dist/src/tracing/agent-trace-context-store.js +1 -1
- package/dist/src/tracing/agent-trace-state.d.ts +41 -0
- package/dist/src/tracing/agent-trace-state.js +1 -0
- package/dist/src/tracing/local-instrumentation-runtime.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/chat-sdk.mdx +1 -1
- package/docs/channels/github.mdx +1 -1
- package/docs/channels/linear.mdx +4 -2
- package/docs/channels/overview.mdx +2 -2
- package/docs/channels/slack.mdx +154 -40
- package/docs/concepts/default-harness.md +3 -3
- package/docs/concepts/sessions-runs-and-streaming.md +1 -1
- package/docs/connections/mcp.mdx +35 -1
- package/docs/connections/openapi.mdx +24 -0
- package/docs/guides/dev-tui.md +58 -142
- package/docs/guides/dynamic-workflows.md +2 -0
- package/docs/guides/frontend/overview.mdx +4 -2
- package/docs/guides/hooks.md +25 -3
- package/docs/guides/session-context.md +18 -0
- package/docs/install-integrations.mdx +2 -0
- package/docs/reference/cli.md +5 -3
- package/docs/reference/typescript-api.md +1 -1
- package/docs/sandbox.mdx +25 -5
- package/docs/skills.mdx +12 -1
- package/docs/subagents.mdx +1 -1
- package/docs/tools/human-in-the-loop.md +1 -1
- package/docs/tutorial/ship-it.mdx +1 -1
- package/package.json +10 -10
- package/dist/src/compiled/_chunks/node/undici-DWL_MYmT.js +0 -95
- package/dist/src/compiled/_chunks/workflow/dist-CZxNEvEs.js +0 -79
|
@@ -32,10 +32,7 @@ export declare const inputRequestKindSchema: z.ZodEnum<{
|
|
|
32
32
|
"session-limit": "session-limit";
|
|
33
33
|
"tool-approval": "tool-approval";
|
|
34
34
|
}>;
|
|
35
|
-
/**
|
|
36
|
-
* Unified input request surfaced to the client when the agent needs user
|
|
37
|
-
* input before continuing.
|
|
38
|
-
*/
|
|
35
|
+
/** Unified input request surfaced when the agent needs user input. */
|
|
39
36
|
export type InputRequest = z.infer<typeof inputRequestSchema>;
|
|
40
37
|
/**
|
|
41
38
|
* Zod schema for one input request.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{normalizeAuthorizationSpec}from"#runtime/connections/validate-authorization.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveConnectionDefinition(t,n,r){try{let i=expectObjectRecord(await loadResolvedModuleExport({definition:t,kindLabel:`connection`,moduleMap:n,nodeId:r}),`Expected the connection export "${t.exportName??`default`}" from "${t.logicalPath}" to return an object.`),a={kind:`connection`,logicalPath:t.logicalPath,name:t.connectionName},o=`connection-source:${t.sourceId}`;stampDefinitionKey(i,o),registerDefinitionSource(o,a),registerDefinitionSource(`connection:${t.url}`,a);let s=i.auth!==void 0,c=i.headers!==void 0,l=t.protocol===`openapi`?i.operations:i.tools,u={connectionName:t.connectionName,description:t.description,exportName:t.exportName,logicalPath:t.logicalPath,protocol:t.protocol,sourceId:t.sourceId,sourceKind:`module`,url:t.url};if(s)if(typeof i.auth==`function`)u.authorization=i.auth;else try{u.authorization=normalizeAuthorizationSpec(i.auth,`Connection "${t.connectionName}" at "${t.logicalPath}":`)}catch(e){throw new ResolveAgentError(toErrorMessage(e),{logicalPath:t.logicalPath,sourceId:t.sourceId})}return c&&(u.headers=i.headers),l!==void 0&&(u.tools=l),t.protocol===`openapi`&&i.spec!==void 0&&(u.spec=i.spec),typeof i.approval==`function`&&(u.approval=i.approval),u}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve connection "${t.connectionName}" from "${t.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:t.logicalPath,sourceId:t.sourceId})}}export{resolveConnectionDefinition};
|
|
1
|
+
import{expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{normalizeAuthorizationSpec}from"#runtime/connections/validate-authorization.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveConnectionDefinition(t,n,r){try{let i=expectObjectRecord(await loadResolvedModuleExport({definition:t,kindLabel:`connection`,moduleMap:n,nodeId:r}),`Expected the connection export "${t.exportName??`default`}" from "${t.logicalPath}" to return an object.`),a={kind:`connection`,logicalPath:t.logicalPath,name:t.connectionName},o=`connection-source:${t.sourceId}`;stampDefinitionKey(i,o),registerDefinitionSource(o,a),registerDefinitionSource(`connection:${t.url}`,a);let s=i.auth!==void 0,c=i.headers!==void 0,l=t.protocol===`openapi`?i.operations:i.tools,u={connectionName:t.connectionName,description:t.description,exportName:t.exportName,logicalPath:t.logicalPath,protocol:t.protocol,sourceId:t.sourceId,sourceKind:`module`,url:t.url};if(s)if(typeof i.auth==`function`)u.authorization=i.auth;else try{u.authorization=normalizeAuthorizationSpec(i.auth,`Connection "${t.connectionName}" at "${t.logicalPath}":`)}catch(e){throw new ResolveAgentError(toErrorMessage(e),{logicalPath:t.logicalPath,sourceId:t.sourceId})}return c&&(u.headers=i.headers),i.toolCall!==void 0&&(u.toolCall=i.toolCall),l!==void 0&&(u.tools=l),t.protocol===`openapi`&&i.spec!==void 0&&(u.spec=i.spec),typeof i.approval==`function`&&(u.approval=i.approval),u}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve connection "${t.connectionName}" from "${t.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:t.logicalPath,sourceId:t.sourceId})}}export{resolveConnectionDefinition};
|
|
@@ -10,6 +10,7 @@ import type { OutboundAuthFn } from "#public/agents/auth.js";
|
|
|
10
10
|
import type { StreamEventHook } from "#public/definitions/hook.js";
|
|
11
11
|
import type { Approval } from "#public/definitions/approval.js";
|
|
12
12
|
import type { ToolModelOutput } from "#public/definitions/tool.js";
|
|
13
|
+
import type { ConnectionToolCallDefinition } from "#public/definitions/connections/tool-call.js";
|
|
13
14
|
import type { AuthorizationDefinition, ConnectionAuthResolver, ConnectionProtocol, HeadersDefinition, ToolFilterDefinition } from "#runtime/connections/types.js";
|
|
14
15
|
import type { OpenAPISpecSource } from "#public/definitions/connections/openapi.js";
|
|
15
16
|
import type { CompiledWorkspaceResourceRoot } from "#compiler/manifest.js";
|
|
@@ -78,6 +79,7 @@ export interface ResolvedConnectionDefinition extends ResolvedModuleSourceRef {
|
|
|
78
79
|
readonly connectionName: string;
|
|
79
80
|
readonly description: string;
|
|
80
81
|
readonly headers?: Readonly<HeadersDefinition>;
|
|
82
|
+
readonly toolCall?: Readonly<ConnectionToolCallDefinition>;
|
|
81
83
|
/**
|
|
82
84
|
* Wire protocol. Selects the runtime client implementation. `tools`
|
|
83
85
|
* carries the connection's operation/tool filter regardless of
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Prompter } from "./prompter.js";
|
|
2
|
+
import type { SelectOption } from "./ask.js";
|
|
3
|
+
export interface EditableSelectQuestion<T> {
|
|
4
|
+
key: string;
|
|
5
|
+
message: string;
|
|
6
|
+
options: readonly SelectOption<T>[];
|
|
7
|
+
recommended?: T;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
editable: {
|
|
10
|
+
key: string;
|
|
11
|
+
value: T;
|
|
12
|
+
label: string;
|
|
13
|
+
recommended: string;
|
|
14
|
+
validate?: (raw: string) => string | null;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface EditableSelectAnswer<T> {
|
|
18
|
+
value: T;
|
|
19
|
+
text?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Renders the specialized one-row editable select through a terminal prompter. */
|
|
22
|
+
export declare function renderEditableQuestion<T>(prompter: Prompter, question: EditableSelectQuestion<T>): Promise<EditableSelectAnswer<T>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{optionById,requiredOptionId}from"./question-options.js";function selectedValue(t,n){let r=optionById(t,n);if(r!==void 0)return r.value;let i=t.options.map(e=>e.id).join(`, `);throw Error(`Invalid answer for "${t.key}": ${String(n)}. Expected one of: ${i}.`)}async function renderEditableQuestion(e,n){let r=requiredOptionId(n,n.editable.value,`configured editable value`),i=n.options.map(e=>({value:e.id,label:e.label,hint:e.hint,featured:e.featured})),a=n.recommended===void 0?void 0:requiredOptionId(n,n.recommended,`recommendation`);if(e.selectEditable!==void 0){let t=await e.selectEditable({message:n.message,options:i,initialValue:a,editable:{value:r,defaultValue:n.editable.recommended,formatHint:e=>`${n.editable.label}: ${e}`,validate:e=>n.editable.validate?.(e)??void 0}}),o=selectedValue(n,t.value);return o===n.editable.value?{value:o,text:t.kind===`edited`?t.text.trim():n.editable.recommended.trim()}:{value:o}}let o=selectedValue(n,await e.select({message:n.message,options:i,initialValue:a}));return o===n.editable.value?{value:o,text:(await e.text({message:n.editable.label,defaultValue:n.editable.recommended,validate:e=>n.editable.validate?.(e)??void 0})).trim()}:{value:o}}export{renderEditableQuestion};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { EditableSelectQuestion } from "./ask-editable.js";
|
|
2
|
+
import type { MultiSelectQuestion, Question } from "./ask.js";
|
|
3
|
+
/** Thrown when a skippable question is skipped, so the box can branch on it. */
|
|
4
|
+
export declare class SkippedSignal extends Error {
|
|
5
|
+
readonly key: string;
|
|
6
|
+
constructor(key: string);
|
|
7
|
+
}
|
|
8
|
+
/** Any question the channel can carry, for signals that quote one. */
|
|
9
|
+
export type AnyQuestion = Question<unknown> | EditableSelectQuestion<unknown> | MultiSelectQuestion<unknown>;
|
|
10
|
+
/**
|
|
11
|
+
* Headless refusal that keeps the whole question: an agent driver can relay
|
|
12
|
+
* exactly what is missing (key, message, options) instead of a bare string.
|
|
13
|
+
*/
|
|
14
|
+
export declare class InteractionRequired extends Error {
|
|
15
|
+
readonly question: AnyQuestion;
|
|
16
|
+
constructor(question: AnyQuestion);
|
|
17
|
+
}
|
|
18
|
+
/** Thrown when a pre-supplied answer fails the question's own validation. */
|
|
19
|
+
export declare class InvalidAnswerError extends Error {
|
|
20
|
+
readonly question: AnyQuestion;
|
|
21
|
+
constructor(question: AnyQuestion, message: string);
|
|
22
|
+
get key(): string;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var SkippedSignal=class extends Error{key;constructor(e){super(`Skipped: ${e}`),this.name=`SkippedSignal`,this.key=e}},InteractionRequired=class extends Error{question;constructor(e){super(`Interaction required for "${e.key}": ${e.message}`),this.name=`InteractionRequired`,this.question=e}},InvalidAnswerError=class extends Error{question;constructor(e,t){super(t),this.name=`InvalidAnswerError`,this.question=e}get key(){return this.question.key}};export{InteractionRequired,InvalidAnswerError,SkippedSignal};
|
package/dist/src/setup/ask.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { type EditableSelectAnswer, type EditableSelectQuestion } from "./ask-editable.js";
|
|
2
|
+
export type { EditableSelectAnswer, EditableSelectQuestion } from "./ask-editable.js";
|
|
3
|
+
export { InteractionRequired, InvalidAnswerError, SkippedSignal, type AnyQuestion, } from "./ask-signals.js";
|
|
1
4
|
import type { Prompter } from "./prompter.js";
|
|
2
5
|
/** One choice in a select question. */
|
|
3
6
|
export interface SelectOption<T> {
|
|
@@ -67,7 +70,14 @@ export type Question<T> = {
|
|
|
67
70
|
} | {
|
|
68
71
|
kind: "text";
|
|
69
72
|
validate?: (raw: string) => string | null;
|
|
70
|
-
sensitive?:
|
|
73
|
+
sensitive?: false;
|
|
74
|
+
/** Presentation hint: ghost text shown while the input is empty. */
|
|
75
|
+
placeholder?: string;
|
|
76
|
+
} | {
|
|
77
|
+
kind: "text";
|
|
78
|
+
validate?: (raw: string) => string | null;
|
|
79
|
+
sensitive: true;
|
|
80
|
+
environment: string;
|
|
71
81
|
/** Presentation hint: ghost text shown while the input is empty. */
|
|
72
82
|
placeholder?: string;
|
|
73
83
|
});
|
|
@@ -113,20 +123,29 @@ export declare const confirm: (q: {
|
|
|
113
123
|
required?: boolean;
|
|
114
124
|
internal?: boolean;
|
|
115
125
|
}) => Question<boolean>;
|
|
116
|
-
|
|
117
|
-
export declare const text: (q: {
|
|
126
|
+
interface TextQuestionInput {
|
|
118
127
|
key: string;
|
|
119
128
|
message: string;
|
|
120
129
|
detected?: string;
|
|
121
130
|
recommended?: string;
|
|
122
131
|
required?: boolean;
|
|
123
132
|
validate?: (raw: string) => string | null;
|
|
124
|
-
sensitive?: boolean;
|
|
125
133
|
placeholder?: string;
|
|
126
|
-
}
|
|
134
|
+
}
|
|
135
|
+
/** Builds a text question without spelling the discriminant at call sites. */
|
|
136
|
+
export declare function text(q: TextQuestionInput & {
|
|
137
|
+
sensitive: true;
|
|
138
|
+
environment: string;
|
|
139
|
+
}): Question<string>;
|
|
140
|
+
export declare function text(q: TextQuestionInput & {
|
|
141
|
+
sensitive?: false;
|
|
142
|
+
environment?: never;
|
|
143
|
+
}): Question<string>;
|
|
127
144
|
/** The capability boxes see. Pure and flow-agnostic: Prompter's successor. */
|
|
128
145
|
export interface Asker {
|
|
129
146
|
ask<T>(question: Question<T>): Promise<T>;
|
|
147
|
+
/** A single choice whose one row carries an editable string value. */
|
|
148
|
+
askEditable<T>(question: EditableSelectQuestion<T>): Promise<EditableSelectAnswer<T>>;
|
|
130
149
|
/**
|
|
131
150
|
* The multi-select channel. Paired with {@link ask} instead of being a
|
|
132
151
|
* question kind because the answer type (`T[]`) differs from the option type
|
|
@@ -136,26 +155,6 @@ export interface Asker {
|
|
|
136
155
|
}
|
|
137
156
|
/** A ladder rung: wraps an asker and resolves (or rewrites) some questions. */
|
|
138
157
|
export type AskerDecorator = (inner: Asker) => Asker;
|
|
139
|
-
/** Thrown when a skippable question is skipped, so the box can branch on it. */
|
|
140
|
-
export declare class SkippedSignal extends Error {
|
|
141
|
-
readonly key: string;
|
|
142
|
-
constructor(key: string);
|
|
143
|
-
}
|
|
144
|
-
/** Any question the channel can carry, for signals that quote one. */
|
|
145
|
-
export type AnyQuestion = Question<unknown> | MultiSelectQuestion<unknown>;
|
|
146
|
-
/**
|
|
147
|
-
* Headless refusal that keeps the whole question: an agent driver can relay
|
|
148
|
-
* exactly what is missing (key, message, options) instead of a bare string.
|
|
149
|
-
*/
|
|
150
|
-
export declare class InteractionRequired extends Error {
|
|
151
|
-
readonly question: AnyQuestion;
|
|
152
|
-
constructor(question: AnyQuestion);
|
|
153
|
-
}
|
|
154
|
-
/** Thrown when a pre-supplied answer fails the question's own validation. */
|
|
155
|
-
export declare class InvalidAnswerError extends Error {
|
|
156
|
-
readonly key: string;
|
|
157
|
-
constructor(key: string, message: string);
|
|
158
|
-
}
|
|
159
158
|
/** How a question got its value, so nothing is silently assumed. */
|
|
160
159
|
export type ResolutionSource = "answer" | "detected" | "assumed" | "asked" | "skipped";
|
|
161
160
|
/** One announced question outcome. */
|
package/dist/src/setup/ask.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const select=e=>({...e,kind:`select`}),confirm=e=>({...e,kind:`confirm`})
|
|
1
|
+
import{optionById,optionByValue,requiredOptionId}from"./question-options.js";import{renderEditableQuestion}from"./ask-editable.js";import{InteractionRequired,InvalidAnswerError,SkippedSignal}from"./ask-signals.js";import{SetupPrerequisiteRequired}from"./integrations/shared/prerequisite.js";const select=e=>({...e,kind:`select`}),confirm=e=>({...e,kind:`confirm`});function text(e){return{...e,kind:`text`}}function announce(e,t,n,r){return e?.onResolved?.({key:t,value:n,source:r}),n}function coerceAnswer(t,n){if(t.kind===`select`){let r=String(n),i=optionById(t,r);if(!i){let e=t.options.map(e=>e.id).join(`, `);throw new InvalidAnswerError(t,`Invalid answer for "${t.key}": ${r}. Expected one of: ${e}.`)}return i.value}if(t.kind===`confirm`){let e=typeof n==`boolean`?n:n===`true`||n!==`false`&&null;if(e===null)throw new InvalidAnswerError(t,`Invalid answer for "${t.key}": expected a boolean.`);return e}let r=String(n),i=t.validate?.(r);if(i)throw new InvalidAnswerError(t,i);return r}function coerceManyAnswer(t,n){if(!Array.isArray(n))throw new InvalidAnswerError(t,`Invalid answer for "${t.key}": expected an array of option ids.`);let r=[];for(let i of n){let n=String(i),o=optionById(t,n);if(!o){let e=t.options.map(e=>e.id).join(`, `);throw new InvalidAnswerError(t,`Invalid answer for "${t.key}": ${n}. Expected one of: ${e}.`)}if(o.disabled){let e=o.disabledReason===void 0?``:` (${o.disabledReason})`;throw new InvalidAnswerError(t,`Invalid answer for "${t.key}": ${n} is unavailable${e}.`)}r.includes(o.value)||r.push(o.value)}for(let e of t.options)e.locked===!0&&!r.includes(e.value)&&r.push(e.value);return r}async function renderQuestion(e,t){if(t.kind===`select`){let r=t.detected??t.recommended;return coerceAnswer(t,await e.select({message:t.message,options:t.options.map(e=>({value:e.id,label:e.label,hint:e.hint,featured:e.featured})),initialValue:r===void 0?void 0:requiredOptionId(t,r,t.detected===void 0?`recommendation`:`detected value`),search:t.search,placeholder:t.placeholder}))}if(t.kind===`confirm`){let n=t.detected??t.recommended;return coerceAnswer(t,await e.select({message:t.message,options:[{value:`yes`,label:`Yes`},{value:`no`,label:`No`}],initialValue:n===void 0?void 0:n?`yes`:`no`})===`yes`)}let r=t.validate,i=r===void 0?void 0:e=>r(e)??void 0,a=t.detected??t.recommended;return coerceAnswer(t,t.sensitive?await e.password({message:t.message,validate:i}):await e.text({message:t.message,placeholder:t.placeholder,defaultValue:a===void 0?void 0:String(a),validate:i}))}async function renderManyQuestion(t,r){let i=r.detected??r.recommended;return(await t.select({multiple:!0,message:r.message,options:r.options.map(e=>({value:e.id,label:e.label,hint:e.hint,featured:e.featured,disabled:e.disabled,disabledReason:e.disabledReason,locked:e.locked,lockedReason:e.lockedReason})),initialValues:i===void 0?void 0:i.map(e=>requiredOptionId(r,e,r.detected===void 0?`recommendation`:`detected value`)),required:r.requireSelection,search:r.search,placeholder:r.placeholder})).map(t=>{let n=optionById(r,t);if(!n)throw new InvalidAnswerError(r,`Invalid answer for "${r.key}": ${t} is not an option id.`);return n.value})}function interactiveAsker(e,t){return{async ask(n){let r=await renderQuestion(e,n);return n.internal?r:announce(t,n.key,r,`asked`)},async askEditable(n){let i=await renderEditableQuestion(e,n);return announce(t,n.key,i.value,`asked`),i.text!==void 0&&announce(t,n.editable.key,i.text,`asked`),i},async askMany(n){let r=await renderManyQuestion(e,n);return n.internal?r:announce(t,n.key,r,`asked`)}}}function headlessAsker(e){function refuse(t){throw t.required?new InteractionRequired(t):(announce(e,t.key,void 0,`skipped`),new SkippedSignal(t.key))}return{async ask(e){return refuse(e)},async askEditable(e){return refuse(e)},async askMany(e){return refuse(e)}}}function withAnswers(e,n){return r=>({async ask(t){if(t.key in e){let r=coerceAnswer(t,e[t.key]);return announce(n,t.key,r,`answer`)}if(t.kind===`text`&&t.sensitive===!0){let e=process.env[t.environment];if(e!==void 0)return coerceAnswer(t,e);try{return await r.ask(t)}catch(e){throw e instanceof InteractionRequired?new SetupPrerequisiteRequired({kind:`environment`,code:t.key,message:`Set ${t.environment}, then retry setup.`,variable:t.environment,sensitive:!0}):e}}return r.ask(t)},async askEditable(i){if(!(i.key in e))return r.askEditable(i);let o=coerceAnswer(select({key:i.key,message:i.message,options:i.options}),e[i.key]);if(announce(n,i.key,o,`answer`),o!==i.editable.value)return{value:o};if(!(i.editable.key in e))return{value:o,text:(await r.ask(text({key:i.editable.key,message:optionByValue(i,o)?.label??i.message,recommended:i.editable.recommended,required:i.required,validate:i.editable.validate}))).trim()};let s=String(e[i.editable.key]),c=i.editable.validate?.(s);if(c)throw new InvalidAnswerError(text({key:i.editable.key,message:i.editable.label,required:i.required}),c);let l=s.trim();return announce(n,i.editable.key,l,`answer`),{value:o,text:l}},async askMany(t){if(t.key in e){let r=coerceManyAnswer(t,e[t.key]);return announce(n,t.key,r,`answer`)}return r.askMany(t)}})}function withRequired(e){return t=>({async ask(n){return!n.required&&e.includes(n.key)?t.ask({...n,required:!0}):t.ask(n)},async askEditable(n){return t.askEditable(!n.required&&e.includes(n.key)?{...n,required:!0}:n)},async askMany(n){return!n.required&&e.includes(n.key)?t.askMany({...n,required:!0}):t.askMany(n)}})}function withPolicy(e,t){return r=>({async ask(i){if(e===`assume`){if(i.detected!==void 0)return i.kind===`select`&&requiredOptionId(i,i.detected,`detected value`),announce(t,i.key,i.detected,`detected`);if(i.recommended!==void 0)return i.kind===`select`&&requiredOptionId(i,i.recommended,`recommendation`),announce(t,i.key,i.recommended,`assumed`);if(!i.required)throw announce(t,i.key,void 0,`skipped`),new SkippedSignal(i.key);return r.ask(i)}return i.detected!==void 0&&await r.ask(confirm({key:i.key,message:`Use the detected value for "${i.key}"?`,internal:!0}))?announce(t,i.key,i.detected,`detected`):r.ask(i)},async askEditable(i){if(e!==`assume`||i.recommended===void 0)return r.askEditable(i);requiredOptionId(i,i.editable.value,`configured editable value`),requiredOptionId(i,i.recommended,`recommendation`);let a=i.recommended===i.editable.value?{value:i.recommended,text:i.editable.recommended}:{value:i.recommended};return announce(t,i.key,a.value,`assumed`),a.text!==void 0&&announce(t,i.editable.key,a.text,`assumed`),a},async askMany(i){if(e===`assume`){if(i.detected!==void 0){for(let e of i.detected)requiredOptionId(i,e,`detected value`);return announce(t,i.key,[...i.detected],`detected`)}if(i.recommended!==void 0){for(let e of i.recommended)requiredOptionId(i,e,`recommendation`);return announce(t,i.key,[...i.recommended],`assumed`)}if(!i.required)throw announce(t,i.key,void 0,`skipped`),new SkippedSignal(i.key);return r.askMany(i)}return i.detected!==void 0&&await r.ask(confirm({key:i.key,message:`Use the detected value for "${i.key}"?`,internal:!0}))?announce(t,i.key,[...i.detected],`detected`):r.askMany(i)}})}export{InteractionRequired,InvalidAnswerError,SkippedSignal,confirm,headlessAsker,interactiveAsker,select,text,withAnswers,withPolicy,withRequired};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{detectDeployment,isProjectResolved,mergeProjectResolution,projectResolutionFromDeployResult,projectResolutionFromDeployment}from"../project-resolution.js";import{hasVercelProject,requireProjectPath}from"../state.js";import{syncHostFrameworkPreset}from"../vercel-project-framework.js";import{detectPackageManager}from"#setup/package-manager.js";import{runVercel}from"#setup/primitives/run-vercel.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{runPackageManagerInstall}from"#setup/primitives/pm/run.js";const VERCEL_DEPLOY_ENV={VERCEL_USE_EXPERIMENTAL_FRAMEWORKS:`1`};function deployProject(s){let c=s.deps??{runVercel,detectPackageManager,runPackageManagerInstall,detectDeployment,syncHostFrameworkPreset};return{id:`deploy-project`,shouldRun(e){return s.skip||!e.deploymentPending?!1:hasVercelProject(e)||s.ensureLinkedProject===`interactive-vercel-link`},async gather(){return{headless:s.headless??!1}},async perform({state:e,input:n,signal:r}){let i=requireProjectPath(e),{log:a}=s.prompter,o=createPromptCommandOutput(a),l=e.project;if(!isProjectResolved(l)){if(n.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Deployment needs this directory linked to a Vercel project.`});if(a.message(`Linking this directory to a Vercel project before deployment...`),!await c.runVercel([`link`],{cwd:i,signal:r}))throw r?.throwIfAborted(),Error(`Vercel project linking failed. Deployment did not start.`);if(l=mergeProjectResolution(l,projectResolutionFromDeployment(await c.detectDeployment(i,{signal:r}))),!isProjectResolved(l))throw Error(`Vercel project linking failed. Deployment did not start.`)}if(await c.syncHostFrameworkPreset(s.prompter,i,o,r?{signal:r}:{}),!e.deploymentDependenciesInstalled){let e=await c.detectPackageManager(i);if(!await withPhase(a,`Installing project dependencies before deployment (${e.kind} install)...`,()=>c.runPackageManagerInstall(e.kind,i,{onOutput:o,signal:r})))throw r?.throwIfAborted(),Error(`Dependency installation failed. Deployment did not start.`)}let u=
|
|
1
|
+
import{detectDeployment,isProjectResolved,mergeProjectResolution,projectResolutionFromDeployResult,projectResolutionFromDeployment}from"../project-resolution.js";import{hasVercelProject,requireProjectPath}from"../state.js";import{syncHostFrameworkPreset}from"../vercel-project-framework.js";import{detectPackageManager}from"#setup/package-manager.js";import{runVercel}from"#setup/primitives/run-vercel.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{runPackageManagerInstall}from"#setup/primitives/pm/run.js";const VERCEL_DEPLOY_ENV={VERCEL_USE_EXPERIMENTAL_FRAMEWORKS:`1`};function deployProject(s){let c=s.deps??{runVercel,detectPackageManager,runPackageManagerInstall,detectDeployment,syncHostFrameworkPreset};return{id:`deploy-project`,shouldRun(e){return s.skip||!e.deploymentPending?!1:hasVercelProject(e)||s.ensureLinkedProject===`interactive-vercel-link`},async gather(){return{headless:s.headless??!1}},async perform({state:e,input:n,signal:r}){let i=requireProjectPath(e),{log:a}=s.prompter,o=createPromptCommandOutput(a),l=e.project;if(!isProjectResolved(l)){if(n.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Deployment needs this directory linked to a Vercel project.`});if(a.message(`Linking this directory to a Vercel project before deployment...`),!await c.runVercel([`link`],{cwd:i,signal:r}))throw r?.throwIfAborted(),Error(`Vercel project linking failed. Deployment did not start.`);if(l=mergeProjectResolution(l,projectResolutionFromDeployment(await c.detectDeployment(i,{signal:r}))),!isProjectResolved(l))throw Error(`Vercel project linking failed. Deployment did not start.`)}if(await c.syncHostFrameworkPreset(s.prompter,i,o,r?{signal:r}:{}),!e.deploymentDependenciesInstalled){let e=await c.detectPackageManager(i);if(!await withPhase(a,`Installing project dependencies before deployment (${e.kind} install)...`,()=>c.runPackageManagerInstall(e.kind,i,{onOutput:o,signal:r})))throw r?.throwIfAborted(),Error(`Dependency installation failed. Deployment did not start.`)}let u=[`deploy`,`--prod`,`--yes`,...n.headless?[`--non-interactive`]:[]],d=await withPhase(a,`Deploying the agent to Vercel production...`,()=>c.runVercel(u,{cwd:i,extraEnv:VERCEL_DEPLOY_ENV,nonInteractive:n.headless,onOutput:o,signal:r}));if(r?.throwIfAborted(),!d)throw a.error("`vercel deploy --prod` failed. The deploy output above shows the cause; fix it, then retry."),Error(`Deployment failed after channel setup.`);let f=await withPhase(a,`Pulling Vercel environment variables into .env.local...`,()=>c.runVercel([`env`,`pull`,`--yes`],{cwd:i,nonInteractive:n.headless,onOutput:o,signal:r}));r?.throwIfAborted(),f||a.warning(`Deployment succeeded, but pulling Vercel environment variables did not complete.`);let p=await c.detectDeployment(i,{signal:r}),m=p.state===`deployed`?p.productionUrl:void 0;return m===void 0?a.warning(`Deployment succeeded, but eve could not verify its production URL.`):a.info(`Production URL: ${m}`),{project:projectResolutionFromDeployResult(l,{deployed:!0,productionUrl:m}),deploymentPending:!1,deploymentDependenciesInstalled:!0}},apply(e,t){return{...e,project:t.project,deploymentPending:t.deploymentPending,deploymentDependenciesInstalled:t.deploymentDependenciesInstalled}}}}export{deployProject};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{select,text}from"../ask.js";import{detectProjectResolution,isProjectResolved,mergeProjectResolution}from"../project-resolution.js";import{withSpinner}from"../with-spinner.js";import{pathExists}from"../path-exists.js";import{assertNewProjectNameAvailable,isVercelAuthenticated,pickNewProjectName,pickProject,pickTeam,requireAuth,resolveProjectByNameOrId,resolveTeam,validateTeam}from"../vercel-project.js";import{join,resolve}from"node:path";import{byokProviderEnvVar}from"#setup/scaffold/index.js";import{whimsyFor}from"#setup/cli/index.js";function vercelDemands(e){return{connectSlugs:e.connectionSelection.filter(e=>e.entry.auth?.kind===`connect`).map(e=>e.slug)}}function connectClause(e){let t=e.length===1?`authenticates`:`authenticate`;return`${e.join(`, `)} ${t} through Vercel Connect`}function vercelRequirements(e){let t=[];return e.connectSlugs.length>0&&t.push(connectClause(e.connectSlugs)),t}function resolveProvisioning(l){let u=l.deps??{requireAuth,isVercelAuthenticated,detectProjectResolution,pathExists,validateTeam,resolveTeam,pickTeam,pickProject,pickNewProjectName,assertNewProjectNameAvailable,resolveProjectByNameOrId},parent=()=>resolve(l.targetDirectory??process.cwd());async function detectAdoptableLink(e,t){if(e.projectPath.kind!==`resolved`)return;let n=e.projectPath.path;if(await u.pathExists(join(n,`.vercel`,`project.json`)))return withSpinner(l.prompter,whimsyFor(`project-detect`),async()=>{let e=await u.detectProjectResolution(n,{signal:t});if(!(!isProjectResolved(e)||!await u.isVercelAuthenticated(n,{signal:t})))return e})}async function plansFromFlags(e,t,n,r){if(t.skipVercel)return n.apiKey===void 0?{vercelProject:{kind:`none`},aiGateway:{kind:`byop`},modelWiring:`self`}:{vercelProject:{kind:`none`},aiGateway:{kind:`byok`,apiGatewayKey:n.apiKey},modelWiring:`gateway`};if(t.team===void 0||t.team.length===0)throw Error(`Headless Vercel provisioning requires --team <slug> or --scope <slug> so the current CLI scope is not applied silently.`);await u.requireAuth(parent(),void 0,{signal:r}),await u.validateTeam(l.prompter,parent(),t.team,{signal:r});let i=await u.resolveTeam(parent(),t.team,{signal:r}),a=n.apiKey===void 0?{kind:`inherit`}:{kind:`byok`,apiGatewayKey:n.apiKey},o;if(t.project===void 0)o={kind:`new`,project:e,team:i};else{let e=await u.resolveProjectByNameOrId(parent(),i,t.project,{signal:r});if(e===null)throw Error(`Vercel project "${t.project}" was not found in ${i}.`);o={kind:`existing`,project:e,team:i}}return o.kind===`new`&&await u.assertNewProjectNameAvailable(parent(),i,o.project,{signal:r}),{vercelProject:o,aiGateway:a,modelWiring:`gateway`}}async function promptPlans(n,r){let i=l.prompter,a=n.agentName,o=l.adoptExistingLink===!1?void 0:await detectAdoptableLink(n,r);if(o!==void 0)return i.log.info(`This directory is already linked to a Vercel project, so your agent will run there — the AI Gateway authenticates through your Vercel login.`),{vercelProject:{kind:`none`},aiGateway:{kind:`inherit`},modelWiring:`gateway`,project:o};let s=vercelRequirements(vercelDemands(n)),c=!0;if(s.length>0?i.log.info(`${s.join(` and `)}, so your agent will run on Vercel.`):c=await l.asker.ask(select({key:`deploy`,message:`Where should your agent run?`,options:[{id:`vercel`,value:!0,label:`On Vercel`,hint:`AI Gateway, Durable Workflow, Sandbox, and more`},{id:`local`,value:!1,label:`Locally for now`,hint:`run with eve dev, deploy any time later`}],recommended:!0,required:!0})),c){await u.requireAuth(parent(),i,{signal:r});let t={signal:r,selectMessage:l.teamSelectMessage},n=await u.pickTeam(i,parent(),void 0,t),o=[{value:`new`,label:`Create a new project`,hint:`Name: ${a}`},{value:`link`,label:`Link an existing project`}],s=l.projectSelection!==`existing-only`&&l.prompter.selectEditable?await l.prompter.selectEditable({message:`Vercel project`,options:o,initialValue:`new`,editable:{value:`new`,defaultValue:a,formatHint:e=>`Name: ${e}`,validate:e=>e.trim().length===0?`Project name cannot be empty.`:void 0}}):void 0;if((l.projectSelection===`existing-only`?`link`:s?.value??await l.asker.ask(select({key:`vercel-project`,message:`Vercel project`,options:[{id:`new`,value:`new`,label:`Create a new project`,hint:`Name: ${a}`},{id:`link`,value:`link`,label:`Link an existing project`}],recommended:`new`,required:!0})))===`new`){let e=s?.kind===`edited`?s.text:a;return{vercelProject:{kind:`new`,project:await u.pickNewProjectName(i,parent(),n,e,{signal:r}),team:n},aiGateway:{kind:`inherit`},modelWiring:`gateway`}}return{vercelProject:await u.pickProject(i,parent(),n,{allowCreateWhenEmpty:l.projectSelection!==`existing-only`,suggestedName:a,signal:r}),aiGateway:{kind:`inherit`},modelWiring:`gateway`}}return await l.asker.ask(select({key:`credential`,message:`How should your agent reach the model?`,options:[{id:`api-key`,value:`api-key`,label:`Use my own AI Gateway API key`,hint:`AI_GATEWAY_API_KEY`},{id:`local`,value:`local`,label:`Use my own provider API key`,hint:byokProviderEnvVar(n.modelId)}],recommended:`api-key`,required:!0}))===`api-key`?{vercelProject:{kind:`none`},aiGateway:{kind:`byok`,apiGatewayKey:await l.asker.ask(text({key:`gateway-api-key`,message:`Enter your AI_GATEWAY_API_KEY`,sensitive:!0,validate:e=>e.trim().length===0?`API key cannot be empty.`:null,required:!0}))},modelWiring:`gateway`}:{vercelProject:{kind:`none`},aiGateway:{kind:`byop`},modelWiring:`self`}}return{id:`resolve-provisioning`,async gather({state:e,signal:t}){if(l.mode.headless){let n=await plansFromFlags(e.agentName,l.mode.project,l.mode.aiGateway,t);if(n.vercelProject.kind===`none`){let t=vercelDemands(e);if(t.connectSlugs.length>0)throw Error(`${connectClause(t.connectSlugs)}, which needs a Vercel project. Remove --skip-vercel to add ${t.connectSlugs.length===1?`it`:`them`}.`)}return n}return promptPlans(e,t)},async perform({input:e}){return e},apply(e,t){return{...e,vercelProject:t.vercelProject,aiGateway:t.aiGateway,modelWiring:t.modelWiring,project:t.project===void 0?e.project:mergeProjectResolution(e.project,t.project)}}}}export{resolveProvisioning};
|
|
1
|
+
import{select,text}from"../ask.js";import{detectProjectResolution,isProjectResolved,mergeProjectResolution}from"../project-resolution.js";import{withSpinner}from"../with-spinner.js";import{pathExists}from"../path-exists.js";import{assertNewProjectNameAvailable,isVercelAuthenticated,pickNewProjectName,pickProject,pickTeam,requireAuth,resolveProjectByNameOrId,resolveTeam,validateTeam}from"../vercel-project.js";import{join,resolve}from"node:path";import{byokProviderEnvVar}from"#setup/scaffold/index.js";import{whimsyFor}from"#setup/cli/index.js";function vercelDemands(e){return{connectSlugs:e.connectionSelection.filter(e=>e.entry.auth?.kind===`connect`).map(e=>e.slug)}}function connectClause(e){let t=e.length===1?`authenticates`:`authenticate`;return`${e.join(`, `)} ${t} through Vercel Connect`}function vercelRequirements(e){let t=[];return e.connectSlugs.length>0&&t.push(connectClause(e.connectSlugs)),t}function resolveProvisioning(l){let u=l.deps??{requireAuth,isVercelAuthenticated,detectProjectResolution,pathExists,validateTeam,resolveTeam,pickTeam,pickProject,pickNewProjectName,assertNewProjectNameAvailable,resolveProjectByNameOrId},parent=()=>resolve(l.targetDirectory??process.cwd());async function detectAdoptableLink(e,t){if(e.projectPath.kind!==`resolved`)return;let n=e.projectPath.path;if(await u.pathExists(join(n,`.vercel`,`project.json`)))return withSpinner(l.prompter,whimsyFor(`project-detect`),async()=>{let e=await u.detectProjectResolution(n,{signal:t});if(!(!isProjectResolved(e)||!await u.isVercelAuthenticated(n,{signal:t})))return e})}async function plansFromFlags(e,t,n,r){if(t.skipVercel)return n.apiKey===void 0?{vercelProject:{kind:`none`},aiGateway:{kind:`byop`},modelWiring:`self`}:{vercelProject:{kind:`none`},aiGateway:{kind:`byok`,apiGatewayKey:n.apiKey},modelWiring:`gateway`};if(t.team===void 0||t.team.length===0)throw Error(`Headless Vercel provisioning requires --team <slug> or --scope <slug> so the current CLI scope is not applied silently.`);await u.requireAuth(parent(),void 0,{signal:r}),await u.validateTeam(l.prompter,parent(),t.team,{signal:r});let i=await u.resolveTeam(parent(),t.team,{signal:r}),a=n.apiKey===void 0?{kind:`inherit`}:{kind:`byok`,apiGatewayKey:n.apiKey},o;if(t.project===void 0)o={kind:`new`,project:e,team:i};else{let e=await u.resolveProjectByNameOrId(parent(),i,t.project,{signal:r});if(e===null)throw Error(`Vercel project "${t.project}" was not found in ${i}.`);o={kind:`existing`,project:e,team:i}}return o.kind===`new`&&await u.assertNewProjectNameAvailable(parent(),i,o.project,{signal:r}),{vercelProject:o,aiGateway:a,modelWiring:`gateway`}}async function promptPlans(n,r){let i=l.prompter,a=n.agentName,o=l.adoptExistingLink===!1?void 0:await detectAdoptableLink(n,r);if(o!==void 0)return i.log.info(`This directory is already linked to a Vercel project, so your agent will run there — the AI Gateway authenticates through your Vercel login.`),{vercelProject:{kind:`none`},aiGateway:{kind:`inherit`},modelWiring:`gateway`,project:o};let s=vercelRequirements(vercelDemands(n)),c=!0;if(s.length>0?i.log.info(`${s.join(` and `)}, so your agent will run on Vercel.`):c=await l.asker.ask(select({key:`deploy`,message:`Where should your agent run?`,options:[{id:`vercel`,value:!0,label:`On Vercel`,hint:`AI Gateway, Durable Workflow, Sandbox, and more`},{id:`local`,value:!1,label:`Locally for now`,hint:`run with eve dev, deploy any time later`}],recommended:!0,required:!0})),c){await u.requireAuth(parent(),i,{signal:r});let t={signal:r,selectMessage:l.teamSelectMessage},n=await u.pickTeam(i,parent(),void 0,t),o=[{value:`new`,label:`Create a new project`,hint:`Name: ${a}`},{value:`link`,label:`Link an existing project`}],s=l.projectSelection!==`existing-only`&&l.prompter.selectEditable?await l.prompter.selectEditable({message:`Vercel project`,options:o,initialValue:`new`,editable:{value:`new`,defaultValue:a,formatHint:e=>`Name: ${e}`,validate:e=>e.trim().length===0?`Project name cannot be empty.`:void 0}}):void 0;if((l.projectSelection===`existing-only`?`link`:s?.value??await l.asker.ask(select({key:`vercel-project`,message:`Vercel project`,options:[{id:`new`,value:`new`,label:`Create a new project`,hint:`Name: ${a}`},{id:`link`,value:`link`,label:`Link an existing project`}],recommended:`new`,required:!0})))===`new`){let e=s?.kind===`edited`?s.text:a;return{vercelProject:{kind:`new`,project:await u.pickNewProjectName(i,parent(),n,e,{signal:r}),team:n},aiGateway:{kind:`inherit`},modelWiring:`gateway`}}return{vercelProject:await u.pickProject(i,parent(),n,{allowCreateWhenEmpty:l.projectSelection!==`existing-only`,suggestedName:a,signal:r}),aiGateway:{kind:`inherit`},modelWiring:`gateway`}}return await l.asker.ask(select({key:`credential`,message:`How should your agent reach the model?`,options:[{id:`api-key`,value:`api-key`,label:`Use my own AI Gateway API key`,hint:`AI_GATEWAY_API_KEY`},{id:`local`,value:`local`,label:`Use my own provider API key`,hint:byokProviderEnvVar(n.modelId)}],recommended:`api-key`,required:!0}))===`api-key`?{vercelProject:{kind:`none`},aiGateway:{kind:`byok`,apiGatewayKey:await l.asker.ask(text({key:`gateway-api-key`,message:`Enter your AI_GATEWAY_API_KEY`,sensitive:!0,environment:`AI_GATEWAY_API_KEY`,validate:e=>e.trim().length===0?`API key cannot be empty.`:null,required:!0}))},modelWiring:`gateway`}:{vercelProject:{kind:`none`},aiGateway:{kind:`byop`},modelWiring:`self`}}return{id:`resolve-provisioning`,async gather({state:e,signal:t}){if(l.mode.headless){let n=await plansFromFlags(e.agentName,l.mode.project,l.mode.aiGateway,t);if(n.vercelProject.kind===`none`){let t=vercelDemands(e);if(t.connectSlugs.length>0)throw Error(`${connectClause(t.connectSlugs)}, which needs a Vercel project. Remove --skip-vercel to add ${t.connectSlugs.length===1?`it`:`them`}.`)}return n}return promptPlans(e,t)},async perform({input:e}){return e},apply(e,t){return{...e,vercelProject:t.vercelProject,aiGateway:t.aiGateway,modelWiring:t.modelWiring,project:t.project===void 0?e.project:mergeProjectResolution(e.project,t.project)}}}}export{resolveProvisioning};
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import{readProjectLink}from"#setup/project-resolution.js";import{captureVercel,runVercel,runVercelCaptureStdout}from"#setup/primitives/run-vercel.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";const CREATED_CONNECTOR=/\bConnector created:\s*(scl_[A-Za-z0-9_-]+)\b/u;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function parseJson(e){try{return JSON.parse(e)}catch{return}}function
|
|
2
|
-
`))
|
|
1
|
+
import{readProjectLink}from"#setup/project-resolution.js";import{captureVercel,runVercel,runVercelCaptureStdout}from"#setup/primitives/run-vercel.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";const CREATED_CONNECTOR=/\bConnector created:\s*(scl_[A-Za-z0-9_-]+)\b/u;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function parseJson(e){try{return JSON.parse(e)}catch{return}}function connectorCreationFailure(e,t){let n=t?.split(`
|
|
2
|
+
`).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`Vercel CLI `)).at(-1);return n===void 0?`Could not create the ${e} connector.`:`Could not create the ${e} connector. Vercel returned: ${n}`}function parseConnectorRef(e){if(!isRecord(e)||typeof e.uid!=`string`||typeof e.id!=`string`)return;let t={uid:e.uid,id:e.id};return typeof e.name==`string`&&(t.name=e.name),t}function parseCreatedConnector(e){let t=parseJson(e),n=parseConnectorRef(t);if(!isRecord(t)||n===void 0)return;let r=t.supportedSubjectTypes;return Array.isArray(r)&&r.includes(`user`)?n:void 0}function parseConnectorList(e,t){let n=[];for(let r of e){if(!isRecord(r)||typeof r.service==`string`&&r.service!==t)continue;let e=parseConnectorRef(r);e!==void 0&&n.push(e)}return n}function parseConnectorListPage(e,t){if(!isRecord(e)||!Array.isArray(e.connectors))return;let n=typeof e.cursor==`string`?e.cursor:void 0;return n===void 0?{connectors:parseConnectorList(e.connectors,t)}:{connectors:parseConnectorList(e.connectors,t),cursor:n}}async function listConnectors(e,n,r){let i=[],a=new Set,o;do{let s=[`connect`,`list`,`-F`,`json`,`--all-projects`,`--service`,e.service,`--scope`,n.orgId];o!==void 0&&s.push(`--next`,o);let c=await captureVercel(s,{cwd:e.projectRoot,onOutput:r,signal:e.signal});if(!c.ok)throw Error(c.failure.message);let l=parseConnectorListPage(parseJson(c.stdout),e.service);if(l===void 0)throw Error(`Vercel returned an invalid connector list for ${e.service}.`);i.push(...l.connectors);let u=l.cursor;if(u!==void 0&&a.has(u))throw Error(`The connector list repeated cursor ${u}.`);u!==void 0&&a.add(u),o=u}while(o!==void 0);return i}async function supportsUserAuthorization(e,n,r,i){let a=await captureVercel([`api`,`/v1/connect/connectors/${encodeURIComponent(r.id)}`,`--scope`,n.orgId,`--raw`],{cwd:e.projectRoot,onOutput:i,signal:e.signal});if(!a.ok)throw Error(`Could not verify connector ${r.uid}.`);let o=parseJson(a.stdout);if(!isRecord(o)||o.id!==r.id||o.uid!==r.uid||typeof o.service==`string`&&o.service!==e.service)throw Error(`Vercel returned invalid details for connector ${r.uid}.`);let s=o.supportedSubjectTypes;return Array.isArray(s)&&s.includes(`user`)}function connectorNames(e){let t=new Set;for(let n of e){n.name!==void 0&&t.add(n.name.toLowerCase());let e=n.uid.slice(n.uid.lastIndexOf(`/`)+1).trim();e.length>0&&t.add(e.toLowerCase())}return t}function connectorMatchesCanonicalName(e,t){let n=t.toLowerCase();return e.name?.toLowerCase()===n||e.uid.slice(e.uid.lastIndexOf(`/`)+1).trim().toLowerCase()===n}function nextConnectorName(e,t){if(!t.has(e.toLowerCase()))return e;let n=2;for(;t.has(`${e}-${n}`.toLowerCase());)n+=1;return`${e}-${n}`}async function cleanupCreatedConnectionConnector(t){let r=t.orgId??(await readProjectLink(t.projectRoot))?.orgId,a=[`connect`,`remove`,t.connectorId,`--disconnect-all`,`--yes`];if(r!==void 0&&a.push(`--scope`,r),!await runVercel(a,{cwd:t.projectRoot,onOutput:createPromptCommandOutput(t.log)}))throw Error(`Could not remove connector ${t.connectorId}; run \`vercel connect remove ${t.connectorId} --disconnect-all --yes\`.`)}async function attach(e,t,r,i){return runVercel([`connect`,`attach`,r,`--yes`,`--scope`,t.orgId],{cwd:e.projectRoot,onOutput:i,signal:e.signal})}async function resolveFallbackConnector(e,t,n,i,s){let c=s;for(;;){if(await e.prompter.select({message:`Which connector should ${e.slug} use?`,hintLayout:`inline`,notices:[{tone:`warning`,text:c}],options:[{value:`find`,label:`Find a new one`,hint:`Browse existing connectors`},{value:`create`,label:`Create a new one`,hint:`Register another connector`}]})===`find`){let r=[];for(let a of i)await supportsUserAuthorization(e,t,a,n)&&r.push(a);if(r.length===0){c=`No existing ${e.service} connectors support user authorization.`;continue}let a=new Map(r.map(e=>[e.uid,e])),o=await e.prompter.select({message:`Select a connector for ${e.slug}`,hintLayout:`inline`,search:!0,placeholder:`type to search connectors`,options:r.map(e=>({value:e.uid,label:e.uid,hint:e.name??e.id}))}),s=a.get(o);if(s===void 0)throw Error(`Connector ${o} is no longer available.`);return{kind:`existing`,connector:s}}let s=connectorNames(i),l=(await e.prompter.text({message:`New connector name`,defaultValue:nextConnectorName(e.slug,s),validate:e=>{let t=e.trim().toLowerCase();return t.length===0?`A name is required.`:s.has(t)?`A connector with this name already exists.`:void 0}})).trim(),u=[],createOutput=e=>{u.push(e.text),n(e)},d=await withPhase(e.log,`Waiting for you to complete setup in the browser…`,()=>runVercelCaptureStdout([`connect`,`create`,e.service,`--name`,l,`-F`,`json`,`--scope`,t.orgId],{cwd:e.projectRoot,onOutput:createOutput,signal:e.signal}),{kind:`external-action`,emphasis:`browser`}),f=parseConnectorRef(parseJson(d.stdout))?.id??CREATED_CONNECTOR.exec(u.join(`
|
|
3
|
+
`))?.[1],p=d.ok?parseCreatedConnector(d.stdout):void 0;if(p!==void 0)return{kind:`created`,connector:p};let m=d.ok?`The ${e.service} connector does not support user authorization.`:connectorCreationFailure(e.service,d.stderr);if(f!==void 0){try{await cleanupCreatedConnectionConnector({log:e.log,projectRoot:e.projectRoot,connectorId:f,orgId:t.orgId})}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`${m} ${t}`)}e.signal?.throwIfAborted()}throw Error(m)}}async function setupConnectionConnector(e){let t=createPromptCommandOutput(e.log),n=e.project,r=await listConnectors(e,n,t),a=r.find(t=>connectorMatchesCanonicalName(t,e.canonicalConnectorName)),o=`Could not find a connector named ${e.canonicalConnectorName}.`;if(a!==void 0)if(await supportsUserAuthorization(e,n,a,t)){if(await attach(e,n,a.uid,t))return e.log.success(`Attached ${a.uid} connector`),{kind:`existing`,connectorUid:a.uid};e.signal?.throwIfAborted(),o=`Could not attach ${a.uid}.`}else o=`${a.uid} does not support user authorization.`;let s=await resolveFallbackConnector(e,n,t,r,o);if(!await attach(e,n,s.connector.uid,t)){if(s.kind===`created`){let t=`Could not attach ${s.connector.uid} to the linked project.`;try{await cleanupCreatedConnectionConnector({log:e.log,projectRoot:e.projectRoot,connectorId:s.connector.id,orgId:n.orgId})}catch(e){let n=e instanceof Error?e.message:String(e);throw Error(`${t} ${n}`)}throw e.signal?.throwIfAborted(),Error(t)}throw Error(`Could not attach ${s.connector.uid} to the linked project.`)}return e.log.success(`Attached ${s.connector.uid} connector`),s.kind===`created`?{kind:`created`,connectorUid:s.connector.uid,connectorId:s.connector.id}:{kind:`existing`,connectorUid:s.connector.uid}}export{cleanupCreatedConnectionConnector,parseCreatedConnector,setupConnectionConnector};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Prompter } from "#setup/prompter.js";
|
|
2
|
+
import { detectDeployment } from "#setup/project-resolution.js";
|
|
3
|
+
import type { RegistrySetupCompletion, RegistrySetupFact } from "#setup/registry-setup-protocol.js";
|
|
4
|
+
import { runDeployFlow } from "./deploy.js";
|
|
5
|
+
export interface RegistrySessionDeps {
|
|
6
|
+
detectDeployment: typeof detectDeployment;
|
|
7
|
+
runDeployFlow: typeof runDeployFlow;
|
|
8
|
+
}
|
|
9
|
+
export interface RegistrySessionItemResult {
|
|
10
|
+
address: string;
|
|
11
|
+
title: string;
|
|
12
|
+
facts: readonly RegistrySetupFact[];
|
|
13
|
+
output: readonly string[];
|
|
14
|
+
}
|
|
15
|
+
export interface RegistrySessionResult {
|
|
16
|
+
kind: "done";
|
|
17
|
+
addedItems: readonly string[];
|
|
18
|
+
items: readonly RegistrySessionItemResult[];
|
|
19
|
+
facts: readonly RegistrySetupFact[];
|
|
20
|
+
output: readonly string[];
|
|
21
|
+
deployed?: "production";
|
|
22
|
+
}
|
|
23
|
+
export interface RegistrySession {
|
|
24
|
+
add(item: string, title: string, output: readonly string[], setup?: RegistrySetupCompletion): void;
|
|
25
|
+
result(deployed?: "production"): RegistrySessionResult;
|
|
26
|
+
continueAfterInstall(input: {
|
|
27
|
+
appRoot: string;
|
|
28
|
+
prompter: Prompter;
|
|
29
|
+
signal?: AbortSignal;
|
|
30
|
+
}): Promise<"add-more" | RegistrySessionResult>;
|
|
31
|
+
}
|
|
32
|
+
/** Owns the accumulated output and deployment decision for one `/add` session. */
|
|
33
|
+
export declare function createRegistrySession(deps: RegistrySessionDeps): RegistrySession;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./deploy.js";import"#setup/project-resolution.js";import{mergeRegistrySetupCompletions}from"#setup/registry-setup-completion.js";function createRegistrySession(t){let n=[],r=[],i=[],a={facts:[]},o=``,s=[];function result(e){let t={kind:`done`,addedItems:n,items:r,facts:a.facts,output:i};return e!==void 0&&(t.deployed=e),t}return{add(t,c,l,u={facts:[]}){n.push(t),r.push({address:t,title:c,facts:u.facts,output:l}),i.push(...l),o=c,s=u.facts,a=mergeRegistrySetupCompletions(a,u)},result,async continueAfterInstall(e){if(a.deploymentRequired!==!0)return result();let n=await t.detectDeployment(e.appRoot,{signal:e.signal}),r=n.state===`linked`||n.state===`deployed`;for(e.prompter.replaceContent?.({headline:`Added ${o}`,facts:s});;){let n=await e.prompter.select({message:`What would you like to do next?`,initialValue:`add-more`,hintLayout:`inline`,options:[{value:`add-more`,label:`Add more`},...r?[{value:`deploy`,label:`Deploy`}]:[],{value:`finish`,label:`Finish`}]});if(n===`add-more`)return e.prompter.replaceContent?.(),`add-more`;if(n===`finish`)return result();if(await e.prompter.select({message:`Deploy to prod?`,initialValue:`yes`,options:[{value:`yes`,label:`Yes`},{value:`back`,label:`Back`}]})!==`back`)return result((await t.runDeployFlow({appRoot:e.appRoot,prompter:e.prompter,signal:e.signal,interactive:!0})).kind===`deployed`?`production`:void 0)}}}}export{createRegistrySession};
|
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
import type { Prompter } from "#setup/prompter.js";
|
|
2
|
+
import { runDeployFlow } from "#setup/flows/deploy.js";
|
|
3
|
+
import { detectDeployment } from "#setup/project-resolution.js";
|
|
4
|
+
import type { RegistrySetupFact } from "#setup/registry-setup-protocol.js";
|
|
2
5
|
export interface RegistryFlowDeps {
|
|
3
6
|
browseRegistryCatalog: (typeof import("#cli/commands/registry.js"))["browseRegistryCatalog"];
|
|
7
|
+
detectDeployment: typeof detectDeployment;
|
|
4
8
|
getRegistryItemManifest: (typeof import("#cli/commands/registry.js"))["getRegistryItemManifest"];
|
|
5
9
|
installRegistryItem: (typeof import("#cli/commands/registry.js"))["installRegistryItem"];
|
|
10
|
+
runDeployFlow: typeof runDeployFlow;
|
|
6
11
|
}
|
|
7
12
|
export type RegistryFlowResult = {
|
|
8
13
|
kind: "done";
|
|
9
14
|
addedItems: readonly string[];
|
|
15
|
+
items: readonly import("./registry-session.js").RegistrySessionItemResult[];
|
|
16
|
+
facts: readonly RegistrySetupFact[];
|
|
10
17
|
output?: readonly string[];
|
|
18
|
+
deployed?: "production";
|
|
11
19
|
} | {
|
|
12
20
|
kind: "cancelled";
|
|
13
21
|
};
|
|
22
|
+
export declare class RegistryFlowFailedError extends Error {
|
|
23
|
+
readonly completed: Extract<RegistryFlowResult, {
|
|
24
|
+
kind: "done";
|
|
25
|
+
}>;
|
|
26
|
+
constructor(error: unknown, completed: Extract<RegistryFlowResult, {
|
|
27
|
+
kind: "done";
|
|
28
|
+
}>);
|
|
29
|
+
}
|
|
14
30
|
/** Runs the categorized interactive registry catalog used by the dev TUI's `/add`. */
|
|
15
31
|
export declare function runRegistryFlow(input: {
|
|
16
32
|
appRoot: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{WizardCancelledError}from"#setup/step.js";import{withSpinner}from"#setup/with-spinner.js";const ADDRESS_PREFIX=`address:`,BACK=`action:back`,DONE=`action:done`,ALL=`category:all`,REGISTRY_CATEGORIES=[{value:`category:channel`,prefix:`channel/`,label:`Channels`,hint:`Where people talk to your agent — Web, Slack, Discord, Teams`,browseLabel:`Browse channels`},{value:`category:connection`,prefix:`connection/`,label:`MCP connections`,hint:`Connect services like Linear, Notion, GitHub, and Vercel`,browseLabel:`Browse MCP connections`},{value:`category:extension`,prefix:`extension/`,label:`Extensions`,hint:`Add browser automation, memory, and developer tools`,browseLabel:`Browse extensions`},{value:`category:instrumentation`,prefix:`instrumentation/`,label:`Observability`,hint:`Trace, evaluate, and monitor your agent`,browseLabel:`Browse observability integrations`}];function itemLabel(e){return e.title===void 0?(e.name.split(`/`).at(-1)??e.name).split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `):e.title}function itemRows(e){return e.map((e,t)=>({value:`item:${t}`,label:itemLabel(e),hint:e.description??e.type}))}function categoryRows(){return[...REGISTRY_CATEGORIES.map(e=>({value:e.value,label:e.label,hint:e.hint})),{value:ALL,label:`Browse all`,hint:`Search every integration or enter an item address`},{value:DONE,label:`Return to chat`,trailingAction:!0}]}function categoryFor(e){return REGISTRY_CATEGORIES.find(t=>t.value===e)}function itemsForCategory(e,t){if(t===ALL)return e;let n=categoryFor(t);return n===void 0?e:e.filter(e=>e.address.startsWith(n.prefix)||e.name.startsWith(n.prefix))}function stringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function itemSource(e){if(e.startsWith(`@`))return e.split(`/`)[0]??e;if(/^https?:\/\//u.test(e))try{return new URL(e).host}catch{return e}return`Vercel`}function manifestRecord(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:{}}function summarizeDetails(e,t=3){let n=e.slice(0,t),r=e.length-n.length;return r>0?`${n.join(`, `)} … (+${r} more)`:n.join(`, `)}function itemDetails(e,t){let n=[{label:`Source`,value:e.source}],r=[...stringArray(t.dependencies),...stringArray(t.devDependencies),...stringArray(t.registryDependencies)];r.length>0&&n.push({label:`Packages`,value:summarizeDetails(r)});let i=t.envVars;if(typeof i==`object`&&i&&!Array.isArray(i)){let e=Object.keys(i);e.length>0&&n.push({label:`Environment`,value:summarizeDetails(e)})}let a=(Array.isArray(t.files)?t.files:[]).flatMap(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return[];let t=e.target;return typeof t==`string`?[t]:[]});return a.length>0&&n.push({label:`Files`,value:summarizeDetails(a)}),n}async function inspectItem(e,n,r,
|
|
1
|
+
import{createRegistrySession}from"./registry-session.js";import{runDeployFlow}from"#setup/flows/deploy.js";import{WizardCancelledError}from"#setup/step.js";import{detectDeployment}from"#setup/project-resolution.js";import{withSpinner}from"#setup/with-spinner.js";const ADDRESS_PREFIX=`address:`,BACK=`action:back`,DONE=`action:done`,ALL=`category:all`,REGISTRY_CATEGORIES=[{value:`category:channel`,prefix:`channel/`,label:`Channels`,hint:`Where people talk to your agent — Web, Slack, Discord, Teams`,browseLabel:`Browse channels`},{value:`category:connection`,prefix:`connection/`,label:`MCP connections`,hint:`Connect services like Linear, Notion, GitHub, and Vercel`,browseLabel:`Browse MCP connections`},{value:`category:extension`,prefix:`extension/`,label:`Extensions`,hint:`Add browser automation, memory, and developer tools`,browseLabel:`Browse extensions`},{value:`category:instrumentation`,prefix:`instrumentation/`,label:`Observability`,hint:`Trace, evaluate, and monitor your agent`,browseLabel:`Browse observability integrations`}];var RegistryFlowFailedError=class extends Error{completed;constructor(e,t){super(e instanceof Error?e.message:String(e),{cause:e}),this.name=`RegistryFlowFailedError`,this.completed=t}};function itemLabel(e){return e.title===void 0?(e.name.split(`/`).at(-1)??e.name).split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `):e.title}function itemRows(e){return e.map((e,t)=>({value:`item:${t}`,label:itemLabel(e),hint:e.description??e.type}))}function categoryRows(){return[...REGISTRY_CATEGORIES.map(e=>({value:e.value,label:e.label,hint:e.hint})),{value:ALL,label:`Browse all`,hint:`Search every integration or enter an item address`},{value:DONE,label:`Return to chat`,trailingAction:!0}]}function categoryFor(e){return REGISTRY_CATEGORIES.find(t=>t.value===e)}function itemsForCategory(e,t){if(t===ALL)return e;let n=categoryFor(t);return n===void 0?e:e.filter(e=>e.address.startsWith(n.prefix)||e.name.startsWith(n.prefix))}function stringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function itemSource(e){if(e.startsWith(`@`))return e.split(`/`)[0]??e;if(/^https?:\/\//u.test(e))try{return new URL(e).host}catch{return e}return`Vercel`}function manifestRecord(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:{}}function summarizeDetails(e,t=3){let n=e.slice(0,t),r=e.length-n.length;return r>0?`${n.join(`, `)} … (+${r} more)`:n.join(`, `)}function itemDetails(e,t){let n=[{label:`Source`,value:e.source}],r=[...stringArray(t.dependencies),...stringArray(t.devDependencies),...stringArray(t.registryDependencies)];r.length>0&&n.push({label:`Packages`,value:summarizeDetails(r)});let i=t.envVars;if(typeof i==`object`&&i&&!Array.isArray(i)){let e=Object.keys(i);e.length>0&&n.push({label:`Environment`,value:summarizeDetails(e)})}let a=(Array.isArray(t.files)?t.files:[]).flatMap(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return[];let t=e.target;return typeof t==`string`?[t]:[]});return a.length>0&&n.push({label:`Files`,value:summarizeDetails(a)}),n}async function inspectItem(e,t,n,r,a,o){let s=a??manifestRecord(await withSpinner(e,`Loading registry item…`,()=>t.getRegistryItemManifest(n,r.address)));for(;;){let i={message:typeof s.title==`string`?s.title:r.name,metadata:itemDetails(r,s),options:[{value:`add`,label:`Add to project`},{value:`back`,label:`Back`}]},a=typeof s.description==`string`?s.description:r.description;if(a!==void 0&&(i.description=a),await e.select(i)===`back`)return{kind:`back`};let c=e.log.spinner?.(`Installing ${itemLabel(r)} and dependencies…`);try{c?.stop();let install=()=>t.installRegistryItem(n,r.address,{silent:!0,prompter:e,signal:o});return{kind:`added`,...await(e.withExclusiveTerminal?.(install)??install())}}finally{c?.stop()}}}async function resolveAddressItem(e,t,n,r){let a=manifestRecord(await withSpinner(e,`Loading registry item…`,()=>t.getRegistryItemManifest(n,r))),o={address:r,name:typeof a.name==`string`?a.name:r,source:itemSource(r)};return typeof a.type==`string`&&(o.type=a.type),typeof a.description==`string`&&(o.description=a.description),{item:o,manifest:a}}async function runRegistryFlow(c){let l;(c.deps?.browseRegistryCatalog===void 0||c.deps.getRegistryItemManifest===void 0||c.deps.installRegistryItem===void 0)&&(l=await import(`#cli/commands/registry.js`));let u={browseRegistryCatalog:c.deps?.browseRegistryCatalog??l.browseRegistryCatalog,detectDeployment:c.deps?.detectDeployment??detectDeployment,getRegistryItemManifest:c.deps?.getRegistryItemManifest??l.getRegistryItemManifest,installRegistryItem:c.deps?.installRegistryItem??l.installRegistryItem,runDeployFlow:c.deps?.runDeployFlow??runDeployFlow},d=[],f=createRegistrySession(u);try{for(;;){c.signal?.throwIfAborted();let e=await withSpinner(c.prompter,`Loading registry…`,()=>u.browseRegistryCatalog(c.appRoot));d=[...d,...e.errors.map(e=>({tone:`warning`,text:`${e.registry}: ${e.message}`}))];let t=await c.prompter.select({message:`Add an integration`,options:categoryRows(),hintLayout:`inline`,notices:d});if(d=[],t===DONE)return f.result();let n=itemsForCategory(e.items,t),r=itemRows(n);r.push({value:BACK,label:`Back`,trailingAction:!0});let l=await c.prompter.select({message:categoryFor(t)?.browseLabel??`Browse integrations`,options:r,search:!0,placeholder:`Search integrations or enter an item address`,searchAction:{label:e=>`Add “${e}”`,value:e=>`${ADDRESS_PREFIX}${e.trim()}`},hintLayout:`inline`});if(l===BACK)continue;let p=l.startsWith(ADDRESS_PREFIX)?await resolveAddressItem(c.prompter,u,c.appRoot,l.slice(8)):{item:n[Number(l.slice(5))]};if(p.item===void 0)throw Error(`The selected registry item is no longer available.`);let m=await inspectItem(c.prompter,u,c.appRoot,p.item,`manifest`in p?p.manifest:void 0,c.signal);if(m.kind!==`added`)continue;f.add(p.item.address,itemLabel(p.item),m.output,m.setup);let h=await f.continueAfterInstall({appRoot:c.appRoot,prompter:c.prompter,signal:c.signal});if(h!==`add-more`)return h}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};let t=f.result();throw t.addedItems.length>0?new RegistryFlowFailedError(e,t):e}}export{RegistryFlowFailedError,runRegistryFlow};
|
package/dist/src/setup/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{runRemoteAuthFlow}from"../cli/dev/tui/remote-auth.js";import{InteractionRequired}from"./ask.js";import{runVercel}from"./primitives/run-vercel.js";import{detectDeployment,detectProjectResolution,projectProductionUrlFromResolution}from"./project-resolution.js";import{runVercelEnvPull}from"./run-vercel-link.js";import{createDefaultSetupState,requireProjectPath,snapshotSetupState}from"./state.js";import{getPackageManagerStrategy}from"./primitives/pm/index.js";import{linkProject,requireAuth,resolveProjectByNameOrId,resolveTeam}from"./vercel-project.js";import{createPromptCommandOutput}from"./cli/command-output.js";import"./cli/index.js";import{setupConnectionConnector}from"./connection-connector.js";import{WizardCancelledError}from"./step.js";import{runHeadless,runInteractive}from"./runner.js";import{HeadlessPromptError,createHeadlessPrompter,formatHeadlessEvent}from"./headless.js";import{createPrompter}from"./prompter.js";import{runPackageManagerInstall,runPnpmInstall,spawnPackageManager,spawnPnpm}from"./primitives/pm/run.js";import"./primitives/index.js";import{provisionSlackbot,reconcileSlackUid}from"./slackbot.js";export{HeadlessPromptError,InteractionRequired,WizardCancelledError,createDefaultSetupState,createHeadlessPrompter,createPromptCommandOutput,createPrompter,detectDeployment,detectProjectResolution,formatHeadlessEvent,getPackageManagerStrategy,linkProject,projectProductionUrlFromResolution,provisionSlackbot,reconcileSlackUid,requireAuth,requireProjectPath,resolveProjectByNameOrId,resolveTeam,runHeadless,runInteractive,runPackageManagerInstall,runPnpmInstall,runRemoteAuthFlow,runVercel,runVercelEnvPull,setupConnectionConnector,snapshotSetupState,spawnPackageManager,spawnPnpm};
|
|
1
|
+
import{runRemoteAuthFlow}from"../cli/dev/tui/remote-auth.js";import{InteractionRequired}from"./ask-signals.js";import"./ask.js";import{runVercel}from"./primitives/run-vercel.js";import{detectDeployment,detectProjectResolution,projectProductionUrlFromResolution}from"./project-resolution.js";import{runVercelEnvPull}from"./run-vercel-link.js";import{createDefaultSetupState,requireProjectPath,snapshotSetupState}from"./state.js";import{getPackageManagerStrategy}from"./primitives/pm/index.js";import{linkProject,requireAuth,resolveProjectByNameOrId,resolveTeam}from"./vercel-project.js";import{createPromptCommandOutput}from"./cli/command-output.js";import"./cli/index.js";import{setupConnectionConnector}from"./connection-connector.js";import{WizardCancelledError}from"./step.js";import{runHeadless,runInteractive}from"./runner.js";import{HeadlessPromptError,createHeadlessPrompter,formatHeadlessEvent}from"./headless.js";import{createPrompter}from"./prompter.js";import{runPackageManagerInstall,runPnpmInstall,spawnPackageManager,spawnPnpm}from"./primitives/pm/run.js";import"./primitives/index.js";import{provisionSlackbot,reconcileSlackUid}from"./slackbot.js";export{HeadlessPromptError,InteractionRequired,WizardCancelledError,createDefaultSetupState,createHeadlessPrompter,createPromptCommandOutput,createPrompter,detectDeployment,detectProjectResolution,formatHeadlessEvent,getPackageManagerStrategy,linkProject,projectProductionUrlFromResolution,provisionSlackbot,reconcileSlackUid,requireAuth,requireProjectPath,resolveProjectByNameOrId,resolveTeam,runHeadless,runInteractive,runPackageManagerInstall,runPnpmInstall,runRemoteAuthFlow,runVercel,runVercelEnvPull,setupConnectionConnector,snapshotSetupState,spawnPackageManager,spawnPnpm};
|
|
@@ -1,19 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { VercelProjectReference } from "#setup/project-resolution.js";
|
|
2
2
|
import { deriveSlackConnectorSlug } from "#setup/scaffold/index.js";
|
|
3
3
|
import { writeTextFile } from "#setup/scaffold/files.js";
|
|
4
|
-
import
|
|
4
|
+
import { type SetupApplyContext, type SetupPrepareContext } from "../types.js";
|
|
5
5
|
import { configureDiscordInteractionsEndpoint, registerDiscordCommand, resolveDiscordApplication } from "./api.js";
|
|
6
6
|
import { provisionDiscordConnector } from "./connect.js";
|
|
7
7
|
export interface DiscordSetupDeps {
|
|
8
8
|
configureEndpoint: typeof configureDiscordInteractionsEndpoint;
|
|
9
9
|
deriveConnectorSlug: typeof deriveSlackConnectorSlug;
|
|
10
|
-
ensureVercelProject: typeof ensureVercelProject;
|
|
11
10
|
provisionConnector: typeof provisionDiscordConnector;
|
|
12
11
|
registerCommand: typeof registerDiscordCommand;
|
|
13
12
|
resolveApplication: typeof resolveDiscordApplication;
|
|
14
13
|
writeTextFile: typeof writeTextFile;
|
|
15
14
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
export interface DiscordSetupPlan {
|
|
16
|
+
botToken: string;
|
|
17
|
+
commandName: string;
|
|
18
|
+
commandDescription: string;
|
|
19
|
+
project: VercelProjectReference;
|
|
20
|
+
slug: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function prepareDiscordSetup(context: SetupPrepareContext, deps?: DiscordSetupDeps): Promise<DiscordSetupPlan>;
|
|
23
|
+
export declare function applyDiscordSetup(plan: DiscordSetupPlan, context: SetupApplyContext, deps?: DiscordSetupDeps): Promise<{
|
|
24
|
+
deploymentRequired: true;
|
|
25
|
+
facts: {
|
|
26
|
+
label: string;
|
|
27
|
+
value: string;
|
|
28
|
+
kind: "url";
|
|
29
|
+
}[];
|
|
30
|
+
}>;
|
|
31
|
+
export declare const DISCORD_SETUP: import("../types.js").SetupIntegration;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import{configureDiscordInteractionsEndpoint,registerDiscordCommand,resolveDiscordApplication}from"./api.js";import{provisionDiscordConnector}from"./connect.js";import{join}from"node:path";import{deriveSlackConnectorSlug}from"#setup/scaffold/index.js";import{
|
|
1
|
+
import{configureDiscordInteractionsEndpoint,registerDiscordCommand,resolveDiscordApplication}from"./api.js";import{provisionDiscordConnector}from"./connect.js";import{defineSetupIntegration}from"../types.js";import{join}from"node:path";import{deriveSlackConnectorSlug}from"#setup/scaffold/index.js";import{text}from"#setup/ask.js";import{writeTextFile}from"#setup/scaffold/files.js";const defaultDeps={configureEndpoint:configureDiscordInteractionsEndpoint,deriveConnectorSlug:deriveSlackConnectorSlug,provisionConnector:provisionDiscordConnector,registerCommand:registerDiscordCommand,resolveApplication:resolveDiscordApplication,writeTextFile};function validateCommandName(e){let t=e.trim();return t?t.length>32?`Command name must be 32 characters or fewer.`:/^[a-z0-9_-]+$/.test(t)?null:`Use lowercase letters, numbers, hyphens, or underscores.`:`Command name is required.`}function connectTemplate(e){return`import { connectDiscordCredentials } from "@vercel/connect/eve";
|
|
2
2
|
import { discordChannel } from "eve/channels/discord";
|
|
3
3
|
|
|
4
4
|
export default discordChannel({
|
|
5
5
|
credentials: connectDiscordCredentials(${JSON.stringify(e)}),
|
|
6
6
|
});
|
|
7
|
-
`}async function
|
|
8
|
-
|
|
7
|
+
`}async function prepareDiscordSetup(e,t=defaultDeps){if(e.environment.vercel.kind===`unavailable`)throw Error("Discord setup requires an authenticated Vercel CLI. Run `vercel login`, then retry.");e.presenter.log.info(`Create a Discord application or open an existing one, then go to Bot → Reset Token and copy the new bot token.
|
|
8
|
+
Create: https://discord.com/developers/applications?new_application=true
|
|
9
|
+
Existing applications: https://discord.com/developers/applications`);let n=(await e.asker.ask(text({key:`discord-bot-token`,message:`Discord bot token`,required:!0,sensitive:!0,environment:`DISCORD_BOT_TOKEN`}))).trim(),r=await e.asker.ask(text({key:`discord-command-name`,message:`Discord command name`,detected:`ask`,required:!0,validate:validateCommandName})),i=await e.asker.ask(text({key:`discord-command-description`,message:`Discord command description`,detected:`Ask the eve agent`,required:!0,validate:e=>e.trim().length===0?`Command description is required.`:e.trim().length>100?`Command description must be 100 characters or fewer.`:null})),a=await e.resolveVercelProject(`Discord`);return{botToken:n,commandName:r.trim(),commandDescription:i.trim(),project:a,slug:await t.deriveConnectorSlug(e.appRoot)}}async function applyDiscordSetup(e,t,n=defaultDeps){let r=await n.resolveApplication(e.botToken),i=await n.provisionConnector({botToken:e.botToken,log:t.presenter.log,project:e.project,projectRoot:t.appRoot,slug:e.slug,signal:t.signal});await n.registerCommand(r.id,e.botToken,{name:e.commandName,description:e.commandDescription}),await n.configureEndpoint(e.botToken,i.id),await n.writeTextFile(join(t.appRoot,`agent/channels/discord.ts`),connectTemplate(i.uid),{force:t.force});let o=`https://discord.com/oauth2/authorize?client_id=${encodeURIComponent(r.id)}&scope=bot%20applications.commands&permissions=3072`;return t.presenter.nextSteps([`Install the Discord application, then try /${e.commandName}: ${o}`]),{deploymentRequired:!0,facts:[{label:`Discord application dashboard`,value:`https://discord.com/developers/applications/${r.id}/information`,kind:`url`}]}}const DISCORD_SETUP=defineSetupIntegration({kind:`discord`,label:`Discord`,hint:`Slash commands and interactions`,prepare:prepareDiscordSetup,apply:applyDiscordSetup});export{DISCORD_SETUP,applyDiscordSetup,prepareDiscordSetup};
|
|
@@ -1,15 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { VercelProjectReference } from "#setup/project-resolution.js";
|
|
2
2
|
import { deriveSlackConnectorSlug } from "#setup/scaffold/index.js";
|
|
3
3
|
import { writeTextFile } from "#setup/scaffold/files.js";
|
|
4
|
-
import
|
|
4
|
+
import { type SetupApplyContext, type SetupPrepareContext } from "../types.js";
|
|
5
5
|
import { provisionGitHubConnector } from "./connect.js";
|
|
6
6
|
export interface GitHubSetupDeps {
|
|
7
7
|
deriveConnectorSlug: typeof deriveSlackConnectorSlug;
|
|
8
|
-
ensureVercelProject: typeof ensureVercelProject;
|
|
9
8
|
provisionConnector: typeof provisionGitHubConnector;
|
|
10
9
|
writeTextFile: typeof writeTextFile;
|
|
11
10
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
declare const GITHUB_EVENT_OPTIONS: readonly [{
|
|
12
|
+
readonly id: "issue_comment";
|
|
13
|
+
readonly label: "New issue and PR comments";
|
|
14
|
+
readonly value: "issue_comment";
|
|
15
|
+
readonly hint: "Reply when a new timeline comment includes `@<bot-name>`.";
|
|
16
|
+
}, {
|
|
17
|
+
readonly id: "pull_request_review_comment";
|
|
18
|
+
readonly label: "New inline PR review comments";
|
|
19
|
+
readonly value: "pull_request_review_comment";
|
|
20
|
+
readonly hint: "Reply when a new inline review comment includes `@<bot-name>`.";
|
|
21
|
+
}, {
|
|
22
|
+
readonly id: "issues";
|
|
23
|
+
readonly label: "New issues";
|
|
24
|
+
readonly value: "issues";
|
|
25
|
+
readonly hint: "Add comments to new issues.";
|
|
26
|
+
}, {
|
|
27
|
+
readonly id: "pull_request";
|
|
28
|
+
readonly label: "New PRs";
|
|
29
|
+
readonly value: "pull_request";
|
|
30
|
+
readonly hint: "Add comments to new pull requests.";
|
|
31
|
+
}];
|
|
32
|
+
type GitHubWebhookEvent = (typeof GITHUB_EVENT_OPTIONS)[number]["value"];
|
|
33
|
+
export interface GitHubSetupPlan {
|
|
34
|
+
events: readonly GitHubWebhookEvent[];
|
|
35
|
+
project: VercelProjectReference;
|
|
36
|
+
slug: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function prepareGitHubSetup(context: SetupPrepareContext, deps?: GitHubSetupDeps): Promise<GitHubSetupPlan>;
|
|
39
|
+
export declare function applyGitHubSetup(plan: GitHubSetupPlan, context: SetupApplyContext, deps?: GitHubSetupDeps): Promise<{
|
|
40
|
+
facts: never[];
|
|
41
|
+
deploymentRequired: true;
|
|
42
|
+
}>;
|
|
43
|
+
export declare const GITHUB_SETUP: import("../types.js").SetupIntegration;
|
|
44
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{provisionGitHubConnector}from"./connect.js";import{join}from"node:path";import{deriveSlackConnectorSlug}from"#setup/scaffold/index.js";import{
|
|
1
|
+
import{defineSetupIntegration}from"../types.js";import{provisionGitHubConnector}from"./connect.js";import{join}from"node:path";import{deriveSlackConnectorSlug}from"#setup/scaffold/index.js";import{writeTextFile}from"#setup/scaffold/files.js";const defaultDeps={deriveConnectorSlug:deriveSlackConnectorSlug,provisionConnector:provisionGitHubConnector,writeTextFile},githubEventsQuestion={key:`github-events`,message:`What should this GitHub App respond to?`,options:[{id:`issue_comment`,label:`New issue and PR comments`,value:`issue_comment`,hint:"Reply when a new timeline comment includes `@<bot-name>`."},{id:`pull_request_review_comment`,label:`New inline PR review comments`,value:`pull_request_review_comment`,hint:"Reply when a new inline review comment includes `@<bot-name>`."},{id:`issues`,label:`New issues`,value:`issues`,hint:`Add comments to new issues.`},{id:`pull_request`,label:`New PRs`,value:`pull_request`,hint:`Add comments to new pull requests.`}],recommended:[`issue_comment`,`pull_request_review_comment`],required:!0,requireSelection:!0};function connectTemplate(e,t,n){let r=[n.includes(`issues`)?` onIssue(ctx, issue) {
|
|
2
2
|
if (issue.action !== "opened") return null;
|
|
3
3
|
return { auth: defaultGitHubAuth(ctx) };
|
|
4
4
|
},`:void 0,n.includes(`pull_request`)?` onPullRequest(ctx, pullRequest) {
|
|
@@ -12,4 +12,4 @@ export default githubChannel({
|
|
|
12
12
|
botName: ${JSON.stringify(t)},
|
|
13
13
|
credentials: connectGitHubCredentials(${JSON.stringify(e)}),${a}
|
|
14
14
|
});
|
|
15
|
-
`}async function
|
|
15
|
+
`}async function prepareGitHubSetup(e,t=defaultDeps){if(e.environment.vercel.kind===`unavailable`)throw Error("GitHub setup requires an authenticated Vercel CLI. Run `vercel login`, then retry.");return{events:await e.asker.askMany(githubEventsQuestion),project:await e.resolveVercelProject(`GitHub`),slug:await t.deriveConnectorSlug(e.appRoot)}}async function applyGitHubSetup(e,t,r=defaultDeps){t.presenter.log.info(`GitHub App`),t.presenter.log.info(`Vercel Connect creates a GitHub App and routes verified webhooks to your deployed agent.`);let i=await r.provisionConnector({log:t.presenter.log,events:e.events,project:e.project,projectRoot:t.appRoot,slug:e.slug,signal:t.signal});return await r.writeTextFile(join(t.appRoot,`agent/channels/github.ts`),connectTemplate(i.uid,i.appSlug,e.events),{force:t.force}),t.presenter.nextSteps([`Deploy the agent, then open the GitHub App in Vercel Connect and install it in the organization or account where you want to use it.`,`Add @${i.appSlug} to a new issue, pull request, or review comment to invoke the agent. GitHub may not autocomplete or render the token as a linked mention.`]),{facts:[],deploymentRequired:!0}}const GITHUB_SETUP=defineSetupIntegration({kind:`github`,label:`GitHub`,hint:`Respond to issues, pull requests, and comments`,prepare:prepareGitHubSetup,apply:applyGitHubSetup});export{GITHUB_SETUP,applyGitHubSetup,prepareGitHubSetup};
|