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
|
@@ -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
|
|
5
|
-
import { attachLinearConnector, findLinearConnector, provisionLinearConnector } from "./connect.js";
|
|
4
|
+
import { type SetupApplyContext, type SetupPrepareContext } from "../types.js";
|
|
5
|
+
import { attachLinearConnector, findLinearConnector, provisionLinearConnector, type LinearConnectorRef } from "./connect.js";
|
|
6
6
|
export interface LinearSetupDeps {
|
|
7
7
|
attachConnector: typeof attachLinearConnector;
|
|
8
8
|
deriveConnectorSlug: typeof deriveSlackConnectorSlug;
|
|
9
|
-
ensureVercelProject: typeof ensureVercelProject;
|
|
10
9
|
findConnector: typeof findLinearConnector;
|
|
11
10
|
provisionConnector: typeof provisionLinearConnector;
|
|
12
11
|
writeTextFile: typeof writeTextFile;
|
|
13
12
|
}
|
|
14
|
-
/** Linear does not allow its brand name in a managed app's name. */
|
|
15
13
|
export declare function linearSafeConnectorSlug(slug: string): string;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
type ConnectorPlan = {
|
|
15
|
+
kind: "reuse";
|
|
16
|
+
connector: LinearConnectorRef;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "create";
|
|
19
|
+
slug: string;
|
|
20
|
+
};
|
|
21
|
+
export interface LinearSetupPlan {
|
|
22
|
+
connector: ConnectorPlan;
|
|
23
|
+
project: VercelProjectReference;
|
|
24
|
+
}
|
|
25
|
+
export declare function prepareLinearSetup(context: SetupPrepareContext, deps?: LinearSetupDeps): Promise<LinearSetupPlan>;
|
|
26
|
+
export declare function applyLinearSetup(plan: LinearSetupPlan, context: SetupApplyContext, deps?: LinearSetupDeps): Promise<{
|
|
27
|
+
facts: never[];
|
|
28
|
+
deploymentRequired: true;
|
|
29
|
+
}>;
|
|
30
|
+
export declare const LINEAR_SETUP: import("../types.js").SetupIntegration;
|
|
31
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{attachLinearConnector,findLinearConnector,provisionLinearConnector}from"./connect.js";import{join}from"node:path";import{deriveSlackConnectorSlug,normalizeSlackConnectorSlug}from"#setup/scaffold/index.js";import{WizardCancelledError}from"#setup/step.js";import{select,text}from"#setup/ask.js";import{
|
|
1
|
+
import{defineSetupIntegration}from"../types.js";import{attachLinearConnector,findLinearConnector,provisionLinearConnector}from"./connect.js";import{join}from"node:path";import{deriveSlackConnectorSlug,normalizeSlackConnectorSlug}from"#setup/scaffold/index.js";import{WizardCancelledError}from"#setup/step.js";import{select,text}from"#setup/ask.js";import{writeTextFile}from"#setup/scaffold/files.js";const defaultDeps={attachConnector:attachLinearConnector,deriveConnectorSlug:deriveSlackConnectorSlug,findConnector:findLinearConnector,provisionConnector:provisionLinearConnector,writeTextFile};function linearSafeConnectorSlug(e){return normalizeSlackConnectorSlug(e.replaceAll(/linear/gi,``).replace(/[-_]{2,}/g,`-`)||`agent`)}function connectTemplate(e){return`import { connectLinearCredentials } from "@vercel/connect/eve";
|
|
2
2
|
import { linearChannel } from "eve/channels/linear";
|
|
3
3
|
|
|
4
4
|
export default linearChannel({
|
|
5
5
|
credentials: connectLinearCredentials(${JSON.stringify(e)}),
|
|
6
6
|
});
|
|
7
|
-
`}async function
|
|
7
|
+
`}async function prepareLinearSetup(e,t=defaultDeps){if(e.environment.vercel.kind===`unavailable`)throw Error("Linear setup requires an authenticated Vercel CLI. Run `vercel login`, then retry.");let n=await e.resolveVercelProject(`Linear`),r=linearSafeConnectorSlug(await t.deriveConnectorSlug(e.appRoot)),i=linearSafeConnectorSlug(await e.asker.ask(text({key:`linear.connector-name`,message:`Name your Linear agent`,recommended:r,validate:e=>e.trim().length===0?`A Linear agent name is required.`:null}))),a=await t.findConnector({project:n,projectRoot:e.appRoot,slug:i,signal:e.signal});if(a===void 0)return{project:n,connector:{kind:`create`,slug:i}};let o=await e.asker.ask(select({key:`linear.existing-connector`,message:`A Linear connector named "${i}" already exists. What would you like to do?`,options:[{id:`reuse`,label:`Reuse existing connector`,value:`reuse`},{id:`new`,label:`Create a new connector`,value:`new`},{id:`exit`,label:`Exit setup`,value:`exit`}],recommended:`reuse`}));if(o===`exit`)throw new WizardCancelledError;return o===`reuse`?{project:n,connector:{kind:`reuse`,connector:a}}:{project:n,connector:{kind:`create`,slug:linearSafeConnectorSlug(await e.asker.ask(text({key:`linear.new-connector-name`,message:`Name the new Linear agent`,recommended:`${i}-2`,validate:e=>e.trim().length===0?`A Linear agent name is required.`:null})))}}}async function applyLinearSetup(e,t,n=defaultDeps){let r=e.connector.kind===`reuse`?(await n.attachConnector({connector:e.connector.connector,log:t.presenter.log,project:e.project,projectRoot:t.appRoot,signal:t.signal}),e.connector.connector):await n.provisionConnector({log:t.presenter.log,project:e.project,projectRoot:t.appRoot,slug:e.connector.slug,signal:t.signal});return await n.writeTextFile(join(t.appRoot,`agent/channels/linear.ts`),connectTemplate(r.uid),{force:t.force}),t.presenter.nextSteps([`Deploy the agent, then open the Linear app in Vercel Connect and install it in the workspace where you want to delegate issues and comments.`,`Delegate an issue or mention the agent in an Agent Session to start a conversation.`]),{facts:[],deploymentRequired:!0}}const LINEAR_SETUP=defineSetupIntegration({kind:`linear`,label:`Linear Agent`,hint:`Delegate Linear issues and comments`,prepare:prepareLinearSetup,apply:applyLinearSetup});export{LINEAR_SETUP,applyLinearSetup,linearSafeConnectorSlug,prepareLinearSetup};
|
|
@@ -21,13 +21,20 @@ export interface ProvisionPhotonProjectOptions {
|
|
|
21
21
|
export interface UsePhotonProjectOptions {
|
|
22
22
|
projectId: string;
|
|
23
23
|
projectSecret: string;
|
|
24
|
-
|
|
24
|
+
dedicatedLine?: string;
|
|
25
|
+
phoneNumber?: string;
|
|
25
26
|
deps?: PhotonManagementDeps;
|
|
26
27
|
}
|
|
27
28
|
export interface PhotonManagementDeps {
|
|
28
29
|
fetch: typeof fetch;
|
|
29
30
|
delay(ms: number, signal?: AbortSignal): Promise<void>;
|
|
30
31
|
}
|
|
32
|
+
/** Returns the least-loaded dedicated iMessage line, when the project has one. */
|
|
33
|
+
export declare function findDedicatedPhotonLine(input: {
|
|
34
|
+
projectId: string;
|
|
35
|
+
projectSecret: string;
|
|
36
|
+
deps?: Pick<PhotonManagementDeps, "fetch">;
|
|
37
|
+
}): Promise<string | undefined>;
|
|
31
38
|
/** Authorizes Photon and creates an isolated iMessage project for one eve agent. */
|
|
32
39
|
export declare function provisionPhotonProject(options: ProvisionPhotonProjectOptions): Promise<PhotonManagedProject>;
|
|
33
40
|
/** Validates existing Photon credentials and registers the agent's iMessage user. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{setTimeout}from"node:timers/promises";const PHOTON_DASHBOARD_HOST=`https://app.photon.codes`,PHOTON_DEVICE_CLIENT_ID=`photon-cli`,E164=/^\+[1-9]\d{6,14}$/;function validatePhotonPhoneNumber(e){let t=e.trim();return E164.test(t)?t.startsWith(`+1`)&&t.length!==12?`US and Canadian numbers must be +1 followed by exactly 10 digits`:null:`Use E.164 format: + followed by 7–15 digits, for example +15551234567`}const DeviceAuthorizationSchema=z.object({device_code:z.string().min(1),user_code:z.string().min(1),verification_uri_complete:z.string().url().optional(),verification_uri:z.string().url().optional(),expires_in:z.number().positive().optional(),interval:z.number().positive().optional()}),DeviceTokenSchema=z.object({access_token:z.string().min(1).optional(),accessToken:z.string().min(1).optional()}),ProjectSchema=z.object({id:z.string().min(1)}),ProjectSecretSchema=z.object({projectSecret:z.string().min(1)}),ErrorResponseSchema=z.object({error:z.unknown().optional(),message:z.unknown().optional()}),PhoneRegistrationSchema=z.object({
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{setTimeout}from"node:timers/promises";const PHOTON_DASHBOARD_HOST=`https://app.photon.codes`,PHOTON_SPECTRUM_HOST=`https://spectrum.photon.codes`,PHOTON_DEVICE_CLIENT_ID=`photon-cli`,E164=/^\+[1-9]\d{6,14}$/;function validatePhotonPhoneNumber(e){let t=e.trim();return E164.test(t)?t.startsWith(`+1`)&&t.length!==12?`US and Canadian numbers must be +1 followed by exactly 10 digits`:null:`Use E.164 format: + followed by 7–15 digits, for example +15551234567`}const DeviceAuthorizationSchema=z.object({device_code:z.string().min(1),user_code:z.string().min(1),verification_uri_complete:z.string().url().optional(),verification_uri:z.string().url().optional(),expires_in:z.number().positive().optional(),interval:z.number().positive().optional()}),DeviceTokenSchema=z.object({access_token:z.string().min(1).optional(),accessToken:z.string().min(1).optional()}),ProjectSchema=z.object({id:z.string().min(1)}),ProjectSecretSchema=z.object({projectSecret:z.string().min(1)}),ErrorResponseSchema=z.object({error:z.unknown().optional(),message:z.unknown().optional()}),PhoneRegistrationSchema=z.object({data:z.object({assignedPhoneNumber:z.string().min(1)})}),DedicatedLineSchema=z.object({data:z.object({line:z.object({phoneNumber:z.string().min(1)})})}),defaultDeps={fetch,delay:(e,n)=>setTimeout(e,void 0,{signal:n})};function errorDetail(e,t){let n=ErrorResponseSchema.safeParse(e);return String(n.success?n.data.error??n.data.message??t:t)}function parsePhotonResponse(e,t,n){let r=e.safeParse(t);if(!r.success)throw Error(n);return r.data}async function json(e,t){let n=await e.json().catch(()=>void 0);if(!e.ok)throw Error(`Photon ${t} failed: ${errorDetail(n,e.statusText)}`);return n}function bearer(e){return{authorization:`Bearer ${e}`,"content-type":`application/json`}}function basic(e,t){return{authorization:`Basic ${Buffer.from(`${e}:${t}`).toString(`base64`)}`,"content-type":`application/json`}}async function requestDeviceCode(e){let t=await e.fetch(`${PHOTON_DASHBOARD_HOST}/api/auth/device/code`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({client_id:PHOTON_DEVICE_CLIENT_ID,scope:`openid profile email`})}),r=parsePhotonResponse(DeviceAuthorizationSchema,await json(t,`device login`),`Photon returned an invalid device authorization response.`),a=r.verification_uri_complete??r.verification_uri;if(a===void 0)throw Error(`Photon returned an invalid device authorization response.`);return{deviceCode:r.device_code,userCode:r.user_code,verificationUrl:a,expiresIn:r.expires_in??1800,interval:r.interval??5}}async function pollForToken(e,t,r){let a=Date.now()+e.expiresIn*1e3,o=e.interval*1e3;for(;Date.now()<a;){await t.delay(o,r);let a=await t.fetch(`${PHOTON_DASHBOARD_HOST}/api/auth/device/token`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({grant_type:`urn:ietf:params:oauth:grant-type:device_code`,device_code:e.deviceCode,client_id:PHOTON_DEVICE_CLIENT_ID}),signal:r}),s=await a.json().catch(()=>void 0);if(a.ok){let e=parsePhotonResponse(DeviceTokenSchema,s,`Photon approved device login without returning an access token.`);if(e.access_token!==void 0)return e.access_token;if(e.accessToken!==void 0)return e.accessToken;throw Error(`Photon approved device login without returning an access token.`)}let c=ErrorResponseSchema.safeParse(s),l=c.success?c.data.error??c.data.message:void 0;if(l!==`authorization_pending`){if(l===`slow_down`||a.status===429){o+=a.status===429?1e4:5e3;continue}throw Error(`Photon device login failed: ${String(l??a.statusText)}`)}}throw Error(`Photon device login timed out.`)}async function createProject(e,t,r){let i=await r.fetch(`${PHOTON_DASHBOARD_HOST}/api/projects`,{method:`POST`,headers:bearer(e),body:JSON.stringify({name:t,location:`United States`,platforms:[`imessage`],template:!1,observability:!1})});return parsePhotonResponse(ProjectSchema,await json(i,`project creation`),`Photon did not return a project ID.`).id}async function regenerateSecret(e,t,r){let i=await r.fetch(`${PHOTON_DASHBOARD_HOST}/api/projects/${encodeURIComponent(t)}/regenerate-secret`,{method:`POST`,headers:bearer(e),body:`{}`});return parsePhotonResponse(ProjectSecretSchema,await json(i,`project credential provisioning`),`Photon did not return the new project secret.`).projectSecret}async function registerUser(e,t,n,i){let a=await i.fetch(`${PHOTON_SPECTRUM_HOST}/projects/${encodeURIComponent(e)}/users/`,{method:`POST`,headers:basic(e,t),body:JSON.stringify({type:`shared`,phoneNumber:n})});return parsePhotonResponse(PhoneRegistrationSchema,await json(a,`phone registration`),`Photon returned an invalid phone registration response.`).data.assignedPhoneNumber}async function findDedicatedPhotonLine(e){let t=await(e.deps?.fetch??fetch)(`${PHOTON_SPECTRUM_HOST}/projects/${encodeURIComponent(e.projectId)}/lines/route`,{headers:basic(e.projectId,e.projectSecret)});if(t.status!==404)return parsePhotonResponse(DedicatedLineSchema,await json(t,`dedicated line lookup`),`Photon returned an invalid dedicated line response.`).data.line.phoneNumber}async function deleteProject(e,t,r){let i=await r.fetch(`${PHOTON_DASHBOARD_HOST}/api/projects/${encodeURIComponent(t)}`,{method:`DELETE`,headers:bearer(e)});!i.ok&&i.status!==404&&await json(i,`project cleanup`)}async function provisionPhotonProject(e){let t=e.phoneNumber.trim(),n=validatePhotonPhoneNumber(t);if(n!==null)throw Error(`Photon phone number is invalid. ${n}.`);let r=e.deps??defaultDeps,i=await requestDeviceCode(r);e.onAuthorization({userCode:i.userCode,verificationUrl:i.verificationUrl});let a=await pollForToken(i,r,e.signal),o=await createProject(a,e.projectName,r),cleanup=()=>deleteProject(a,o,r);try{let e=await regenerateSecret(a,o,r),n=await registerUser(o,e,t,r);return n===void 0?{projectId:o,projectSecret:e,cleanup}:{projectId:o,projectSecret:e,assignedPhoneNumber:n,cleanup}}catch(e){throw await cleanup().catch(()=>{}),e}}async function usePhotonProject(e){let t=e.projectId.trim(),n=e.projectSecret.trim();if(!t||!n)throw Error(`Photon project ID and project secret are required.`);let r=e.dedicatedLine??await findDedicatedPhotonLine({projectId:t,projectSecret:n,deps:e.deps});if(r!==void 0)return{projectId:t,projectSecret:n,assignedPhoneNumber:r,cleanup:async()=>{}};if(e.phoneNumber===void 0)throw Error(`Photon phone number is required for projects without a dedicated line.`);let i=e.phoneNumber.trim(),a=validatePhotonPhoneNumber(i);if(a!==null)throw Error(`Photon phone number is invalid. ${a}.`);return{projectId:t,projectSecret:n,assignedPhoneNumber:await registerUser(t,n,i,e.deps??defaultDeps),cleanup:async()=>{}}}export{findDedicatedPhotonLine,provisionPhotonProject,usePhotonProject,validatePhotonPhoneNumber};
|
|
@@ -1,39 +1,43 @@
|
|
|
1
1
|
import { appendEnv } from "../../append-env.js";
|
|
2
|
-
import {
|
|
3
|
-
import { provisionPhotonProject, usePhotonProject } from "./management.js";
|
|
2
|
+
import type { VercelProjectReference } from "../../project-resolution.js";
|
|
4
3
|
import { openUrl } from "../../primitives/open-url.js";
|
|
5
4
|
import { deriveSlackConnectorSlug } from "../../scaffold/index.js";
|
|
6
5
|
import { writeTextFile } from "../../scaffold/files.js";
|
|
7
|
-
import type {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
export interface PhotonSetupOptions {
|
|
6
|
+
import type { SetupApplyContext, SetupPrepareContext } from "../types.js";
|
|
7
|
+
import { provisionPhotonConnector } from "./connect.js";
|
|
8
|
+
import { findDedicatedPhotonLine, provisionPhotonProject, usePhotonProject } from "./management.js";
|
|
9
|
+
export interface PhotonSetupPlan {
|
|
12
10
|
agentName: string;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
credentials: "vercel-connect" | "environment";
|
|
12
|
+
photonProject: "create" | {
|
|
13
|
+
projectId: string;
|
|
14
|
+
projectSecret: string;
|
|
15
|
+
};
|
|
16
|
+
photonProjectName?: string;
|
|
17
|
+
dedicatedLine?: string;
|
|
18
|
+
phoneNumber?: string;
|
|
19
|
+
vercelProject?: VercelProjectReference;
|
|
19
20
|
}
|
|
20
|
-
/** Outcome of Photon project provisioning and channel scaffolding. */
|
|
21
|
-
export type PhotonSetupResult = {
|
|
22
|
-
kind: "done";
|
|
23
|
-
assignedPhoneNumber?: string;
|
|
24
|
-
dashboardUrl: string;
|
|
25
|
-
} | {
|
|
26
|
-
kind: "cancelled";
|
|
27
|
-
};
|
|
28
21
|
export interface PhotonSetupDeps {
|
|
29
22
|
appendEnv: typeof appendEnv;
|
|
30
23
|
deriveConnectorSlug: typeof deriveSlackConnectorSlug;
|
|
31
|
-
|
|
24
|
+
findDedicatedLine: typeof findDedicatedPhotonLine;
|
|
32
25
|
openUrl: typeof openUrl;
|
|
33
26
|
provisionConnector: typeof provisionPhotonConnector;
|
|
34
27
|
provisionProject: typeof provisionPhotonProject;
|
|
35
28
|
useProject: typeof usePhotonProject;
|
|
36
29
|
writeTextFile: typeof writeTextFile;
|
|
37
30
|
}
|
|
38
|
-
|
|
39
|
-
export declare function
|
|
31
|
+
export declare function preparePhotonSetup(context: SetupPrepareContext, deps?: PhotonSetupDeps): Promise<PhotonSetupPlan>;
|
|
32
|
+
export declare function applyPhotonSetup(plan: PhotonSetupPlan, context: SetupApplyContext, deps?: PhotonSetupDeps): Promise<{
|
|
33
|
+
facts: ({
|
|
34
|
+
label: string;
|
|
35
|
+
value: string;
|
|
36
|
+
kind: "url";
|
|
37
|
+
} | {
|
|
38
|
+
label: string;
|
|
39
|
+
value: string;
|
|
40
|
+
kind: "phone";
|
|
41
|
+
})[];
|
|
42
|
+
deploymentRequired: true;
|
|
43
|
+
}>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{appendEnv}from"../../append-env.js";import{text}from"../../ask.js";import{writeTextFile}from"../../scaffold/files.js";import{deriveSlackConnectorSlug}from"../../scaffold/update/channels.js";import"../../scaffold/index.js";import{
|
|
1
|
+
import{appendEnv}from"../../append-env.js";import{select,text}from"../../ask.js";import{writeTextFile}from"../../scaffold/files.js";import{deriveSlackConnectorSlug}from"../../scaffold/update/channels.js";import"../../scaffold/index.js";import{provisionPhotonConnector}from"./connect.js";import{findDedicatedPhotonLine,provisionPhotonProject,usePhotonProject,validatePhotonPhoneNumber}from"./management.js";import{openUrl}from"../../primitives/open-url.js";import{basename,join}from"node:path";const defaultDeps={appendEnv,deriveConnectorSlug:deriveSlackConnectorSlug,findDedicatedLine:findDedicatedPhotonLine,openUrl,provisionConnector:provisionPhotonConnector,provisionProject:provisionPhotonProject,useProject:usePhotonProject,writeTextFile};function connectTemplate(e){return`import { connectPhotonCredentials } from "@vercel/connect/eve";
|
|
2
2
|
import { photonIMessageChannel } from "eve/channels/photon";
|
|
3
3
|
|
|
4
4
|
export default photonIMessageChannel({
|
|
5
5
|
credentials: connectPhotonCredentials(${JSON.stringify(e)}),
|
|
6
6
|
});
|
|
7
|
-
`}async function
|
|
7
|
+
`}async function preparePhotonSetup(e,r=defaultDeps){let i=basename(e.appRoot),a=await e.asker.ask(select({key:`photon-credentials`,message:`How would you like to configure Photon?`,options:[{id:`vercel`,value:`vercel-connect`,label:`Set up Vercel Connect`,hint:`Use a linked Vercel project`},{id:`portable`,value:`environment`,label:`Use portable credentials`,hint:`Configure the Photon webhook manually after deployment`}],recommended:e.environment.vercel.kind===`available`?`vercel-connect`:`environment`,required:!0}));if(a===`vercel-connect`&&e.environment.vercel.kind===`unavailable`)throw Error("Vercel Connect requires an authenticated Vercel CLI. Run `vercel login`, then retry Photon setup.");let o=`eve · ${i||`agent`}`,s=await e.asker.askEditable({key:`photon-project-source`,message:`Photon project`,options:[{id:`create`,value:`create`,label:`Create a new Photon project`,hint:`Name: ${o}`},{id:`existing`,value:`existing`,label:`Use an existing Photon project`,hint:`Enter its project credentials`}],recommended:`create`,required:!0,editable:{key:`photon-project-name`,value:`create`,label:`Name`,recommended:o,validate:e=>e.trim().length===0?`Project name cannot be empty.`:null}}),c=`create`;if(s.value===`existing`){let t=await e.asker.ask(text({key:`photon-project-id`,message:`Photon project ID`,required:!0})),r=await e.asker.ask(text({key:`photon-project-secret`,message:`Photon project secret`,required:!0,sensitive:!0,environment:`IMESSAGE_PROJECT_SECRET`}));c={projectId:t.trim(),projectSecret:r.trim()}}let l=c===`create`?void 0:await r.findDedicatedLine(c),u=l===void 0?await e.asker.ask(text({key:`photon-phone-number`,message:`Your iMessage phone number`,placeholder:`+15551234567`,required:!0,validate:validatePhotonPhoneNumber})):void 0,d=a===`vercel-connect`?await e.resolveVercelProject(`Photon`):void 0,f={agentName:i,credentials:a,photonProject:c,dedicatedLine:l,phoneNumber:u};return s.value===`create`&&(f.photonProjectName=s.text??o),d!==void 0&&(f.vercelProject=d),f}async function resolvePhotonProject(e,t,n){if(e.photonProject!==`create`)return n.useProject({...e.photonProject,dedicatedLine:e.dedicatedLine,phoneNumber:e.phoneNumber});if(e.phoneNumber===void 0)throw Error(`Photon phone number is required.`);let r=t.presenter.log.spinner?.(`Waiting for Photon approval…`,{kind:`external-action`,emphasis:`browser`}),i;try{let r=await n.provisionProject({projectName:e.photonProjectName??`eve · ${e.agentName||`agent`}`,phoneNumber:e.phoneNumber,signal:t.signal,onAuthorization(e){i=t.presenter.beginExternalAction({message:`Authorize Photon`,url:e.verificationUrl,userCode:e.userCode}),n.openUrl(e.verificationUrl)}});return i?.complete(),r}finally{r?.stop()}}async function applyPhotonSetup(e,t,n=defaultDeps){let r=await resolvePhotonProject(e,t,n);try{let i=join(t.appRoot,`agent/channels/photon.ts`);if(e.credentials===`vercel-connect`){let a=await n.deriveConnectorSlug(t.appRoot,e.agentName),o=await n.provisionConnector({credentials:r,log:t.presenter.log,project:e.vercelProject,projectRoot:t.appRoot,slug:a,signal:t.signal});await n.writeTextFile(i,connectTemplate(o.uid),{force:t.force})}else await n.appendEnv(join(t.appRoot,`.env.local`),{IMESSAGE_PROJECT_ID:r.projectId,IMESSAGE_PROJECT_SECRET:r.projectSecret}),await n.writeTextFile(i,`import { photonIMessageChannel } from "eve/channels/photon";
|
|
8
8
|
|
|
9
9
|
async function photonCredentials() {
|
|
10
10
|
const projectId = process.env.IMESSAGE_PROJECT_ID;
|
|
@@ -17,4 +17,4 @@ export default photonIMessageChannel({
|
|
|
17
17
|
credentials: photonCredentials,
|
|
18
18
|
webhookSecret: process.env.IMESSAGE_WEBHOOK_SECRET,
|
|
19
19
|
});
|
|
20
|
-
`,{force:
|
|
20
|
+
`,{force:t.force}),t.presenter.nextSteps([`Deploy the agent, then create a Photon webhook pointing to https://<your-host>/eve/v1/photon.`,`Copy the webhook signing secret into IMESSAGE_WEBHOOK_SECRET, alongside IMESSAGE_PROJECT_ID and IMESSAGE_PROJECT_SECRET, in your host's encrypted environment variables.`]);t.presenter.log.success(`Scaffolded channel: photon`),r.assignedPhoneNumber!==void 0&&t.presenter.note(r.assignedPhoneNumber,`Text your agent`,{tone:`success`});let a=`https://app.photon.codes/dashboard/${r.projectId}`;return t.presenter.note(a,`Photon project`,{tone:`success`}),{facts:[{label:`Photon project dashboard`,value:a,kind:`url`},...r.assignedPhoneNumber===void 0?[]:[{label:`Agent phone number`,value:r.assignedPhoneNumber,kind:`phone`}]],deploymentRequired:!0}}catch(e){throw await r.cleanup().catch(()=>{}),e}}export{applyPhotonSetup,preparePhotonSetup};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{defineSetupIntegration}from"../types.js";import{applyPhotonSetup,preparePhotonSetup}from"./setup-flow.js";const PHOTON_SETUP=defineSetupIntegration({kind:`photon`,label:`Photon`,hint:`Messages through Photon`,prepare:preparePhotonSetup,apply:applyPhotonSetup});export{PHOTON_SETUP};
|
|
@@ -3,4 +3,4 @@ import type { SetupIntegration } from "./types.js";
|
|
|
3
3
|
export declare const SETUP_INTEGRATIONS: readonly SetupIntegration[];
|
|
4
4
|
/** Resolves one built-in setup integration by its registry setup name. */
|
|
5
5
|
export declare function setupIntegration(kind: string): SetupIntegration;
|
|
6
|
-
export {
|
|
6
|
+
export { createSetupContexts, createSetupPresenter } from "./shared/ui.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DISCORD_SETUP}from"./discord/setup.js";import{GITHUB_SETUP}from"./github/setup.js";import{LINEAR_SETUP}from"./linear/setup.js";import{PHOTON_SETUP}from"./photon/setup.js";import{SLACK_SETUP}from"./slack/setup.js";import{WEB_SETUP}from"./web/setup.js";import{
|
|
1
|
+
import{DISCORD_SETUP}from"./discord/setup.js";import{GITHUB_SETUP}from"./github/setup.js";import{LINEAR_SETUP}from"./linear/setup.js";import{PHOTON_SETUP}from"./photon/setup.js";import{SLACK_SETUP}from"./slack/setup.js";import{WEB_SETUP}from"./web/setup.js";import{createSetupContexts,createSetupPresenter}from"./shared/ui.js";const SETUP_INTEGRATIONS=[WEB_SETUP,SLACK_SETUP,DISCORD_SETUP,GITHUB_SETUP,LINEAR_SETUP,PHOTON_SETUP];function setupIntegration(e){let t=SETUP_INTEGRATIONS.find(t=>t.kind===e);if(t===void 0)throw Error(`Integration setup "${e}" is not available in this version of eve. Upgrade eve and try again.`);return t}export{SETUP_INTEGRATIONS,createSetupContexts,createSetupPresenter,setupIntegration};
|
|
@@ -1,25 +1,28 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { detectDeployment } from "#setup/project-resolution.js";
|
|
1
|
+
import { type Asker } from "#setup/ask.js";
|
|
2
|
+
import { detectDeployment, type VercelProjectReference } from "#setup/project-resolution.js";
|
|
3
3
|
import type { Prompter } from "#setup/prompter.js";
|
|
4
4
|
import { getVercelAuthStatus } from "#setup/vercel-project.js";
|
|
5
|
+
import type { IntegrationSetupResult, SetupExternalAction } from "./types.js";
|
|
5
6
|
/** Inputs shared by every registry-owned integration setup flow. */
|
|
6
7
|
export interface RunIntegrationSetupOptions {
|
|
7
8
|
appRoot: string;
|
|
8
9
|
prompter: Prompter;
|
|
10
|
+
/** Defaults to the interactive adapter; agent drivers inject an answer-backed asker. */
|
|
11
|
+
asker?: Asker;
|
|
9
12
|
signal?: AbortSignal;
|
|
10
|
-
|
|
13
|
+
force?: boolean;
|
|
14
|
+
beginExternalAction?: (input: {
|
|
15
|
+
url: string;
|
|
16
|
+
userCode?: string;
|
|
17
|
+
message: string;
|
|
18
|
+
}) => SetupExternalAction;
|
|
19
|
+
resolveVercelProject?: SetupProjectResolver;
|
|
11
20
|
}
|
|
12
21
|
/** Effects shared by the built-in integration setup runner. */
|
|
22
|
+
export type SetupProjectResolver = (integration: string) => Promise<VercelProjectReference>;
|
|
13
23
|
export interface IntegrationSetupRunnerDeps {
|
|
14
24
|
detectDeployment: typeof detectDeployment;
|
|
15
25
|
getVercelAuthStatus: typeof getVercelAuthStatus;
|
|
16
26
|
}
|
|
17
|
-
/** Outcome returned by one registry-owned integration setup flow. */
|
|
18
|
-
export type IntegrationSetupOutcome = {
|
|
19
|
-
kind: "cancelled";
|
|
20
|
-
} | {
|
|
21
|
-
kind: "done";
|
|
22
|
-
facts?: readonly RegistrySetupFact[];
|
|
23
|
-
};
|
|
24
27
|
/** Runs one built-in integration setup flow selected by its registry setup name. */
|
|
25
|
-
export declare function runIntegrationSetup(kind: string, options: RunIntegrationSetupOptions, deps?: IntegrationSetupRunnerDeps): Promise<
|
|
28
|
+
export declare function runIntegrationSetup(kind: string, options: RunIntegrationSetupOptions, deps?: IntegrationSetupRunnerDeps): Promise<IntegrationSetupResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{createSetupContexts}from"./shared/ui.js";import{setupIntegration}from"./registry.js";import{describeIntegrationSetupEnvironment,integrationSetupEnvironment}from"./shared/environment.js";import{resolveIntegrationVercelProject}from"./shared/vercel-project.js";import{detectDeployment,projectResolutionFromDeployment}from"#setup/project-resolution.js";import{interactiveAsker}from"#setup/ask.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";const defaultDeps={detectDeployment,getVercelAuthStatus};async function runIntegrationSetup(t,n,r=defaultDeps){let i=setupIntegration(t);n.prompter.intro(`Set up ${i.label}`),n.prompter.log.message(`Checking Vercel setup...`);let[a,o]=await Promise.all([r.detectDeployment(n.appRoot,{signal:n.signal}),r.getVercelAuthStatus(n.appRoot,{signal:n.signal})]),s=integrationSetupEnvironment(o,projectResolutionFromDeployment(a));return n.prompter.log.info(describeIntegrationSetupEnvironment(s)),i.run(createSetupContexts({appRoot:n.appRoot,asker:n.asker??interactiveAsker(n.prompter),environment:s,prompter:n.prompter,resolveVercelProject:n.resolveVercelProject??(e=>resolveIntegrationVercelProject({appRoot:n.appRoot,integration:e,signal:n.signal})),signal:n.signal,force:n.force,beginExternalAction:n.beginExternalAction}))}export{runIntegrationSetup};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type SetupPrerequisite = {
|
|
2
|
+
kind: "command";
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
command: string;
|
|
6
|
+
} | {
|
|
7
|
+
kind: "environment";
|
|
8
|
+
code: string;
|
|
9
|
+
message: string;
|
|
10
|
+
variable: string;
|
|
11
|
+
sensitive: true;
|
|
12
|
+
};
|
|
13
|
+
/** A setup blocker whose prerequisite must be satisfied by the caller. */
|
|
14
|
+
export declare class SetupPrerequisiteRequired extends Error {
|
|
15
|
+
readonly prerequisite: SetupPrerequisite;
|
|
16
|
+
constructor(prerequisite: SetupPrerequisite);
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var SetupPrerequisiteRequired=class extends Error{prerequisite;constructor(e){super(e.message),this.name=`SetupPrerequisiteRequired`,this.prerequisite=e}};export{SetupPrerequisiteRequired};
|
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Asker } from "../../ask.js";
|
|
2
2
|
import type { Prompter } from "../../prompter.js";
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}): Promise<boolean>;
|
|
12
|
-
nextSteps(lines: readonly string[]): void;
|
|
13
|
-
}
|
|
14
|
-
/** Adapts the shared setup asker and prompter to the channel hook UI. */
|
|
15
|
-
export declare function createIntegrationSetupUi(input: {
|
|
3
|
+
import type { SetupApplyContext, SetupExternalAction, SetupPrepareContext, SetupPresenter } from "../types.js";
|
|
4
|
+
export declare function createSetupPresenter(prompter: Prompter, beginExternalAction?: (input: {
|
|
5
|
+
url: string;
|
|
6
|
+
userCode?: string;
|
|
7
|
+
message: string;
|
|
8
|
+
}) => SetupExternalAction): SetupPresenter;
|
|
9
|
+
export declare function createSetupContexts(input: {
|
|
10
|
+
appRoot: string;
|
|
16
11
|
asker: Asker;
|
|
12
|
+
environment: SetupPrepareContext["environment"];
|
|
17
13
|
prompter: Prompter;
|
|
18
|
-
|
|
14
|
+
resolveVercelProject: SetupPrepareContext["resolveVercelProject"];
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
force?: boolean;
|
|
17
|
+
beginExternalAction?: (input: {
|
|
18
|
+
url: string;
|
|
19
|
+
userCode?: string;
|
|
20
|
+
message: string;
|
|
21
|
+
}) => SetupExternalAction;
|
|
22
|
+
}): {
|
|
23
|
+
prepare: SetupPrepareContext;
|
|
24
|
+
apply: SetupApplyContext;
|
|
25
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
`),`Next steps`,{tone:`success`})}}}export{
|
|
1
|
+
function createSetupPresenter(e,t){return{log:e.log,note:e.note.bind(e),nextSteps(t){t.length>0&&e.note(t.join(`
|
|
2
|
+
`),`Next steps`,{tone:`success`})},beginExternalAction(n){return t===void 0?(e.log.message(n.message),e.log.message(n.url),n.userCode!==void 0&&e.log.message(`Code: ${n.userCode}`),{complete(){}}):t(n)}}}function createSetupContexts(e){let t=createSetupPresenter(e.prompter,e.beginExternalAction),n={appRoot:e.appRoot,presenter:t};return e.signal!==void 0&&(n.signal=e.signal),e.force!==void 0&&(n.force=e.force),{prepare:{...n,asker:e.asker,environment:e.environment,resolveVercelProject:e.resolveVercelProject},apply:n}}export{createSetupContexts,createSetupPresenter};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { readProjectLink, type VercelProjectReference } from "#setup/project-resolution.js";
|
|
2
|
+
export interface IntegrationVercelProjectDeps {
|
|
3
|
+
readProjectLink: typeof readProjectLink;
|
|
4
|
+
}
|
|
5
|
+
/** Requires the caller to link a Vercel project before integration setup begins applying. */
|
|
6
|
+
export declare function resolveIntegrationVercelProject(input: {
|
|
7
|
+
appRoot: string;
|
|
8
|
+
integration: string;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
deps?: IntegrationVercelProjectDeps;
|
|
11
|
+
}): Promise<VercelProjectReference>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{SetupPrerequisiteRequired}from"./prerequisite.js";import{readProjectLink}from"#setup/project-resolution.js";const defaultDeps={readProjectLink};async function resolveIntegrationVercelProject(e){e.signal?.throwIfAborted();let t=await(e.deps??defaultDeps).readProjectLink(e.appRoot);if(t!==void 0)return t;throw new SetupPrerequisiteRequired({kind:`command`,code:`vercel-project-link`,message:`Vercel Connect setup requires a linked Vercel project. Run \`eve link\`, then retry ${e.integration} setup.`,command:`eve link`})}export{resolveIntegrationVercelProject};
|
|
@@ -1,16 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { provisionSlackbot, reconcileSlackUid } from "#setup/slackbot.js";
|
|
4
|
-
import
|
|
5
|
-
/** Effects used by Slack setup. */
|
|
1
|
+
import type { VercelProjectReference } from "#setup/project-resolution.js";
|
|
2
|
+
import { deriveSlackConnectorSlug, ensureChannel, type SlackConnectorSlug } from "#setup/scaffold/index.js";
|
|
3
|
+
import { inspectSlackbotConnectors, provisionSlackbot, reconcileSlackUid, type SlackConnectorSelection } from "#setup/slackbot.js";
|
|
4
|
+
import { type SetupApplyContext, type SetupPrepareContext } from "../types.js";
|
|
6
5
|
export interface SlackSetupDeps {
|
|
7
6
|
deriveSlackConnectorSlug: typeof deriveSlackConnectorSlug;
|
|
8
7
|
ensureChannel: typeof ensureChannel;
|
|
9
|
-
|
|
8
|
+
inspectConnectors: typeof inspectSlackbotConnectors;
|
|
10
9
|
provisionSlackbot: typeof provisionSlackbot;
|
|
11
10
|
reconcileSlackUid: typeof reconcileSlackUid;
|
|
12
11
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
type SlackSetupPlan = {
|
|
13
|
+
credentials: "environment";
|
|
14
|
+
slug: SlackConnectorSlug;
|
|
15
|
+
} | {
|
|
16
|
+
credentials: "vercel-connect";
|
|
17
|
+
slug: SlackConnectorSlug;
|
|
18
|
+
project: VercelProjectReference;
|
|
19
|
+
connector: SlackConnectorSelection;
|
|
20
|
+
};
|
|
21
|
+
export declare function prepareSlackSetup(context: SetupPrepareContext, deps?: SlackSetupDeps): Promise<SlackSetupPlan>;
|
|
22
|
+
export declare function applySlackSetup(plan: SlackSetupPlan, context: SetupApplyContext, deps?: SlackSetupDeps): Promise<{
|
|
23
|
+
facts: {
|
|
24
|
+
label: string;
|
|
25
|
+
value: string;
|
|
26
|
+
kind: "url";
|
|
27
|
+
}[];
|
|
28
|
+
deploymentRequired: true;
|
|
29
|
+
}>;
|
|
30
|
+
export declare const SLACK_SETUP: import("../types.js").SetupIntegration;
|
|
31
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{installScaffoldDependencies,reportOverwrittenFiles}from"../shared/scaffold.js";import{deriveSlackConnectorSlug,ensureChannel}from"#setup/scaffold/index.js";import{WizardCancelledError}from"#setup/step.js";import{
|
|
1
|
+
import{defineSetupIntegration}from"../types.js";import{installScaffoldDependencies,reportOverwrittenFiles}from"../shared/scaffold.js";import{deriveSlackConnectorSlug,ensureChannel}from"#setup/scaffold/index.js";import{WizardCancelledError}from"#setup/step.js";import{select}from"#setup/ask.js";import{inspectSlackbotConnectors,provisionSlackbot,reconcileSlackUid}from"#setup/slackbot.js";import{slackMessageDeepLink}from"#setup/slack-connect.js";function slackbotFailureCopy(e){switch(e.state){case`not-installed`:return{reason:`Slackbot is not connected to a Slack workspace. Slack channel was not added.`,followUp:"Re-run `eve add channel/slack` after the workspace install is complete."};case`cleanup-failed`:return{reason:`The abandoned Slack connector could not be removed. Slack channel was not added.`,followUp:`Resolve the cleanup warning above before trying again.`};case`connector-lookup-failed`:return{reason:`Existing Slack connectors could not be inspected. Slack channel was not added.`,followUp:"Restore Vercel CLI access, then re-run `eve add channel/slack`."};case`installation-check-failed`:return{reason:`Slack workspace installation could not be verified. Slack channel was not added.`,followUp:"Verify Vercel Connect is reachable, then re-run `eve add channel/slack`."};case`existing-not-installed`:return{reason:`The existing Slack connector is not connected to a Slack workspace. Slack channel was not added.`,followUp:`Resolve the existing connector warning above before trying again.`};case`detach-failed`:return{reason:`Slackbot provisioning could not replace the existing trigger destination. Slack channel was not added.`,followUp:"Run the `vercel connect detach` and `vercel connect attach` commands above."};case`attach-failed`:return{reason:`Slackbot provisioning did not attach this project. Slack channel was not added.`,followUp:"Finish event delivery with the `vercel connect attach` command above."};case`create-failed`:return{reason:`Slackbot creation failed.`,followUp:"Add it later with `eve add channel/slack`."}}}const defaultDeps={deriveSlackConnectorSlug,ensureChannel,inspectConnectors:inspectSlackbotConnectors,provisionSlackbot,reconcileSlackUid};async function chooseConnector(e,t,n){return t.length===0?`create`:e.asker.ask(select({key:`slack-connector`,message:`Which Slack app would you like to use?`,options:[...t.map(e=>({id:e.uid,value:e,label:`Use ${e.uid}`,hint:e.uid===n?.uid?`Matches this agent`:void 0})),{id:`create`,value:`create`,label:`Create a new Slack app`}],recommended:n??t[0]??`create`,required:!0}))}async function prepareSlackSetup(e,t=defaultDeps){let n=await e.asker.ask(select({key:`slack-credentials`,message:`How would you like to configure Slack?`,options:[{id:`vercel`,value:`vercel-connect`,label:`Set up Vercel Connect`,hint:`Use a linked Vercel project`},{id:`portable`,value:`environment`,label:`Use portable credentials`,hint:`Read Slack tokens from environment variables`}],recommended:`vercel-connect`,required:!0})),r=await t.deriveSlackConnectorSlug(e.appRoot);if(n===`environment`)return{credentials:n,slug:r};if(e.environment.vercel.kind===`unavailable`)throw Error("Vercel Connect requires an authenticated Vercel CLI. Run `vercel login`, then retry Slack setup.");let i=await e.resolveVercelProject(`Slack`);if(i.projectId.length===0)throw Error(`Slack setup with Vercel Connect requires a linked Vercel project.`);let a=await t.inspectConnectors(e.presenter.log,e.appRoot,r,e.signal);return{credentials:n,slug:r,project:i,connector:a.state===`found`?await chooseConnector(e,a.connectors,a.preferred):`create`}}async function applySlackSetup(e,r,i=defaultDeps){if(e.credentials===`environment`){let t=await i.ensureChannel({projectRoot:r.appRoot,kind:`slack`,slackConnectorSlug:e.slug,slackCredentials:`environment`,force:r.force,skipDependencyMutation:!0});return reportOverwrittenFiles(r.presenter.log,t.filesOverwritten),r.presenter.log.success(`Scaffolded channel: slack`),r.presenter.nextSteps([`Set SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET in .env.local (listed in .env.example).`,`Configure your Slack app to send events to /eve/v1/slack on your public agent URL.`]),{facts:[],deploymentRequired:!0}}let o=await i.provisionSlackbot(r.presenter.log,r.appRoot,e.slug,void 0,{signal:r.signal,selectConnector:async()=>e.connector});if(r.signal?.throwIfAborted(),o.state===`cancelled`)throw new WizardCancelledError;if(o.state!==`attached`){let e=slackbotFailureCopy(o);throw Error(`${e.reason} ${e.followUp}`)}let s=await i.ensureChannel({projectRoot:r.appRoot,kind:`slack`,slackConnectorUid:o.connectorUid,slackConnectorSlug:e.slug,force:r.force,skipDependencyMutation:!0});if(reportOverwrittenFiles(r.presenter.log,s.filesOverwritten),s.action===`skipped`&&!await i.reconcileSlackUid(r.presenter.log,r.appRoot,o,`slack/${e.slug}`))throw Error(`Slack connector UID update is required before deployment.`);return r.presenter.log.success(`Scaffolded channel: slack`),await installScaffoldDependencies({changed:s.packageJsonUpdated.length>0,log:r.presenter.log,projectPath:r.appRoot,signal:r.signal}),{facts:o.chatUrl===void 0?[]:[{label:`Agent Slack DM`,value:slackMessageDeepLink(o.chatUrl),kind:`url`}],deploymentRequired:!0}}const SLACK_SETUP=defineSetupIntegration({kind:`slack`,label:`Slack`,hint:`Slack app mentions and DMs`,prepare:prepareSlackSetup,apply:applySlackSetup});export{SLACK_SETUP,applySlackSetup,prepareSlackSetup};
|
|
@@ -1,26 +1,56 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Asker } from "#setup/ask.js";
|
|
2
|
+
import type { Prompter } from "#setup/prompter.js";
|
|
3
|
+
import type { VercelProjectReference } from "#setup/project-resolution.js";
|
|
4
|
+
import type { RegistrySetupCompletion } from "#setup/registry-setup-protocol.js";
|
|
2
5
|
import type { IntegrationSetupEnvironment } from "./shared/environment.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
export interface SetupExternalAction {
|
|
7
|
+
complete(): void;
|
|
8
|
+
}
|
|
9
|
+
export type SetupPresenter = Pick<Prompter, "log" | "note"> & {
|
|
10
|
+
nextSteps(lines: readonly string[]): void;
|
|
11
|
+
beginExternalAction(input: {
|
|
12
|
+
url: string;
|
|
13
|
+
userCode?: string;
|
|
14
|
+
message: string;
|
|
15
|
+
}): SetupExternalAction;
|
|
16
|
+
};
|
|
17
|
+
export interface SetupPrepareContext {
|
|
6
18
|
readonly appRoot: string;
|
|
19
|
+
readonly asker: Asker;
|
|
7
20
|
readonly environment: IntegrationSetupEnvironment;
|
|
8
|
-
readonly
|
|
9
|
-
readonly
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
readonly presenter: SetupPresenter;
|
|
22
|
+
readonly resolveVercelProject: (integration: string) => Promise<VercelProjectReference>;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
force?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface SetupApplyContext {
|
|
27
|
+
readonly appRoot: string;
|
|
28
|
+
readonly presenter: SetupPresenter;
|
|
29
|
+
signal?: AbortSignal;
|
|
30
|
+
force?: boolean;
|
|
12
31
|
}
|
|
13
|
-
/** Outcome from one registry-owned integration setup flow. */
|
|
14
32
|
export type IntegrationSetupResult = {
|
|
15
33
|
readonly kind: "done";
|
|
16
|
-
readonly
|
|
34
|
+
readonly completion: RegistrySetupCompletion;
|
|
17
35
|
} | {
|
|
18
36
|
readonly kind: "cancelled";
|
|
19
37
|
};
|
|
20
|
-
|
|
21
|
-
export interface SetupIntegration {
|
|
38
|
+
interface SetupIntegrationDefinition<Plan> {
|
|
22
39
|
readonly kind: string;
|
|
23
40
|
readonly label: string;
|
|
24
41
|
readonly hint?: string;
|
|
25
|
-
|
|
42
|
+
prepare(context: SetupPrepareContext): Promise<Plan>;
|
|
43
|
+
apply(plan: Plan, context: SetupApplyContext): Promise<RegistrySetupCompletion>;
|
|
44
|
+
}
|
|
45
|
+
export interface SetupIntegration {
|
|
46
|
+
readonly kind: string;
|
|
47
|
+
readonly label: string;
|
|
48
|
+
hint?: string;
|
|
49
|
+
run(input: {
|
|
50
|
+
prepare: SetupPrepareContext;
|
|
51
|
+
apply: SetupApplyContext;
|
|
52
|
+
}): Promise<IntegrationSetupResult>;
|
|
26
53
|
}
|
|
54
|
+
/** Captures an integration's private plan type behind one executable lifecycle. */
|
|
55
|
+
export declare function defineSetupIntegration<Plan>(definition: SetupIntegrationDefinition<Plan>): SetupIntegration;
|
|
56
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{};
|
|
1
|
+
import{WizardCancelledError}from"#setup/step.js";function defineSetupIntegration(t){let n={kind:t.kind,label:t.label,async run(n){try{let e=await t.prepare(n.prepare);return{kind:`done`,completion:await t.apply(e,n.apply)}}catch(t){if(t instanceof WizardCancelledError)return{kind:`cancelled`};throw t}}};return t.hint!==void 0&&(n.hint=t.hint),n}export{defineSetupIntegration};
|
|
@@ -1,3 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { detectPackageManager } from "#setup/package-manager.js";
|
|
2
|
+
import { ensureChannel } from "#setup/scaffold/index.js";
|
|
3
|
+
import { installScaffoldDependencies } from "../shared/scaffold.js";
|
|
4
|
+
import { type SetupApplyContext, type SetupPrepareContext } from "../types.js";
|
|
5
|
+
export interface WebSetupDeps {
|
|
6
|
+
detectPackageManager: typeof detectPackageManager;
|
|
7
|
+
ensureChannel: typeof ensureChannel;
|
|
8
|
+
installScaffoldDependencies: typeof installScaffoldDependencies;
|
|
9
|
+
}
|
|
10
|
+
export interface WebSetupPlan {
|
|
11
|
+
configureVercelServices: boolean;
|
|
12
|
+
packageManager: Awaited<ReturnType<typeof detectPackageManager>>["kind"];
|
|
13
|
+
}
|
|
14
|
+
export declare function prepareWebSetup(context: SetupPrepareContext, deps?: WebSetupDeps): Promise<WebSetupPlan>;
|
|
15
|
+
export declare function applyWebSetup(plan: WebSetupPlan, context: SetupApplyContext, deps?: WebSetupDeps): Promise<{
|
|
16
|
+
facts: never[];
|
|
17
|
+
deploymentRequired?: undefined;
|
|
18
|
+
} | {
|
|
19
|
+
facts: never[];
|
|
20
|
+
deploymentRequired: true;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const WEB_SETUP: import("../types.js").SetupIntegration;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{installScaffoldDependencies,reportOverwrittenFiles}from"../shared/scaffold.js";import{ensureChannel}from"#setup/scaffold/index.js";import{formatNodeEngineOverrideWarning}from"#setup/node-engine.js";import{detectPackageManager}from"#setup/package-manager.js";function reportCompetingNextConfigFiles(e,t){for(let n of t??[])e.warning(`Found competing Next.js config at ${n}; merge any needed settings into next.config.ts and remove it before starting the preview, or Next.js may ignore the generated eve rewrite.`)}const
|
|
1
|
+
import{defineSetupIntegration}from"../types.js";import{installScaffoldDependencies,reportOverwrittenFiles}from"../shared/scaffold.js";import{ensureChannel}from"#setup/scaffold/index.js";import{formatNodeEngineOverrideWarning}from"#setup/node-engine.js";import{detectPackageManager}from"#setup/package-manager.js";function reportCompetingNextConfigFiles(e,t){for(let n of t??[])e.warning(`Found competing Next.js config at ${n}; merge any needed settings into next.config.ts and remove it before starting the preview, or Next.js may ignore the generated eve rewrite.`)}const defaultDeps={detectPackageManager,ensureChannel,installScaffoldDependencies};async function prepareWebSetup(e,t=defaultDeps){return{packageManager:(await t.detectPackageManager(e.appRoot)).kind,configureVercelServices:e.environment.vercel.kind===`available`}}async function applyWebSetup(e,t,r=defaultDeps){t.presenter.log.message(`Scaffolding Web Chat channel files...`);let i={projectRoot:t.appRoot,kind:`web`,packageManager:e.packageManager,configureVercelServices:e.configureVercelServices,force:t.force,skipDependencyMutation:!0},a=await r.ensureChannel(i);return reportOverwrittenFiles(t.presenter.log,a.filesOverwritten),a.kind===`web`&&a.action!==`skipped`&&a.nodeEngineOverride!==void 0&&t.presenter.log.warning(formatNodeEngineOverrideWarning(a.nodeEngineOverride)),reportCompetingNextConfigFiles(t.presenter.log,`competingNextConfigFiles`in a?a.competingNextConfigFiles:void 0),a.action===`skipped`?(t.presenter.log.info(`Next.js project detected. Skipping Web Chat scaffolding.`),{facts:[]}):(t.presenter.log.success(`Scaffolded channel: web`),await r.installScaffoldDependencies({changed:a.packageJsonUpdated.length>0,log:t.presenter.log,projectPath:t.appRoot,signal:t.signal}),{facts:[],deploymentRequired:!0})}const WEB_SETUP=defineSetupIntegration({kind:`web`,label:`Web Chat`,hint:`Browser-based chat interface`,prepare:prepareWebSetup,apply:applyWebSetup});export{WEB_SETUP,applyWebSetup,prepareWebSetup};
|