eve 0.52.3 → 0.52.4

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.
Files changed (138) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/src/cli/commands/registry-add-command.d.ts +3 -0
  3. package/dist/src/cli/commands/registry-add-command.js +1 -0
  4. package/dist/src/cli/commands/registry-metadata.d.ts +4 -1
  5. package/dist/src/cli/commands/registry-metadata.js +1 -1
  6. package/dist/src/cli/commands/registry.d.ts +1 -2
  7. package/dist/src/cli/commands/registry.js +1 -1
  8. package/dist/src/compiled/.vendor-stamp.json +1 -1
  9. package/dist/src/compiler/extension-compatibility.d.ts +2 -2
  10. package/dist/src/compiler/extension-compatibility.js +1 -1
  11. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  12. package/dist/src/evals/reporters/index.d.ts +1 -0
  13. package/dist/src/evals/reporters/index.js +1 -1
  14. package/dist/src/evals/runner/reporters/datadog.d.ts +137 -0
  15. package/dist/src/evals/runner/reporters/datadog.js +3 -0
  16. package/dist/src/execution/parked-delivery-wait.js +1 -1
  17. package/dist/src/execution/sandbox/bindings/vercel-options.d.ts +10 -0
  18. package/dist/src/execution/sandbox/bindings/vercel-options.js +1 -0
  19. package/dist/src/execution/sandbox/bindings/vercel.js +2 -1
  20. package/dist/src/execution/sandbox/shell-quote.d.ts +1 -12
  21. package/dist/src/execution/sandbox/shell-quote.js +1 -1
  22. package/dist/src/execution/session-command-inbox.js +1 -1
  23. package/dist/src/execution/tasks/child/workflow.js +1 -1
  24. package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
  25. package/dist/src/execution/tool-auth.d.ts +4 -32
  26. package/dist/src/execution/tool-auth.js +1 -1
  27. package/dist/src/execution/tools/connection-search.js +2 -2
  28. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  29. package/dist/src/execution/tools/subagent/accept-event-step.d.ts +1 -1
  30. package/dist/src/execution/tools/subagent/accept-event-step.js +1 -1
  31. package/dist/src/execution/tools/subagent/invoke-agent.js +1 -1
  32. package/dist/src/execution/tools/subagent/invoke-step.js +1 -1
  33. package/dist/src/execution/tools/workflow/ask.d.ts +3 -2
  34. package/dist/src/execution/tools/workflow/ask.js +1 -1
  35. package/dist/src/execution/tools/workflow/authorization-completion.d.ts +3 -0
  36. package/dist/src/execution/tools/workflow/authorization-completion.js +1 -0
  37. package/dist/src/execution/tools/workflow/body.d.ts +2 -0
  38. package/dist/src/execution/tools/workflow/body.js +1 -1
  39. package/dist/src/execution/tools/workflow/step-context.d.ts +31 -0
  40. package/dist/src/execution/tools/workflow/step-context.js +1 -0
  41. package/dist/src/execution/tools/workflow/step-execution.d.ts +3 -0
  42. package/dist/src/execution/tools/workflow/step-execution.js +1 -0
  43. package/dist/src/execution/tools/workflow/step.d.ts +3 -0
  44. package/dist/src/execution/tools/workflow/step.js +1 -0
  45. package/dist/src/execution/turn-workflow-tool-run.js +1 -1
  46. package/dist/src/execution/wire/session-inbox-contract.d.ts +7 -0
  47. package/dist/src/execution/wire/session-inbox-contract.js +1 -1
  48. package/dist/src/execution/wire/session-inbox-resume.d.ts +2 -0
  49. package/dist/src/execution/wire/session-inbox-resume.js +1 -1
  50. package/dist/src/harness/authorization.d.ts +5 -2
  51. package/dist/src/harness/authorization.js +1 -1
  52. package/dist/src/internal/application/package.js +1 -1
  53. package/dist/src/internal/authored-definition/connection.js +1 -1
  54. package/dist/src/internal/authored-package-boundary.js +1 -1
  55. package/dist/src/internal/vercel/build-command.d.ts +2 -1
  56. package/dist/src/internal/vercel/build-command.js +1 -1
  57. package/dist/src/internal/workflow-bundle/builder-support.js +1 -1
  58. package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
  59. package/dist/src/internal/workflow-bundle/workflow-transformer.d.ts +3 -5
  60. package/dist/src/internal/workflow-bundle/workflow-transformer.js +4 -3
  61. package/dist/src/public/channels/github/checkout.js +1 -1
  62. package/dist/src/public/channels/slack/activity.js +1 -1
  63. package/dist/src/runtime/authorization-context.d.ts +14 -0
  64. package/dist/src/runtime/authorization-context.js +1 -0
  65. package/dist/src/runtime/connections/mcp-client.js +1 -1
  66. package/dist/src/runtime/connections/scoped-authorization.d.ts +18 -2
  67. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  68. package/dist/src/runtime/resolve-connection.js +1 -1
  69. package/dist/src/runtime/sandbox/keys.js +1 -1
  70. package/dist/src/sandbox/backends/default.d.ts +2 -0
  71. package/dist/src/sandbox/backends/default.js +1 -1
  72. package/dist/src/self-modification/agent.d.ts +5 -2
  73. package/dist/src/self-modification/agent.js +1 -1
  74. package/dist/src/self-modification/config.d.ts +52 -0
  75. package/dist/src/self-modification/config.js +1 -0
  76. package/dist/src/self-modification/credentials.d.ts +18 -0
  77. package/dist/src/self-modification/credentials.js +1 -0
  78. package/dist/src/self-modification/extension/eve-add.d.ts +7 -2
  79. package/dist/src/self-modification/extension/eve-add.js +1 -1
  80. package/dist/src/self-modification/extension/extension.d.ts +46 -1
  81. package/dist/src/self-modification/extension/extension.js +1 -1
  82. package/dist/src/self-modification/extension/instructions.js +23 -9
  83. package/dist/src/self-modification/extension/production-registry-add.d.ts +42 -0
  84. package/dist/src/self-modification/extension/production-registry-add.js +1 -0
  85. package/dist/src/self-modification/extension/tools/edit_file.js +1 -1
  86. package/dist/src/self-modification/extension/tools/publish.d.ts +7 -0
  87. package/dist/src/self-modification/extension/tools/publish.js +1 -0
  88. package/dist/src/self-modification/extension/tools/registry_add.d.ts +39 -7
  89. package/dist/src/self-modification/extension/tools/registry_add.js +1 -1
  90. package/dist/src/self-modification/extension/tools/search_registry.d.ts +1 -0
  91. package/dist/src/self-modification/extension/tools/search_registry.js +1 -1
  92. package/dist/src/self-modification/filesystem.js +1 -1
  93. package/dist/src/self-modification/git-workspace.d.ts +31 -0
  94. package/dist/src/self-modification/git-workspace.js +1 -0
  95. package/dist/src/self-modification/git.d.ts +6 -0
  96. package/dist/src/self-modification/git.js +1 -0
  97. package/dist/src/self-modification/github-publisher.d.ts +27 -0
  98. package/dist/src/self-modification/github-publisher.js +2 -0
  99. package/dist/src/self-modification/identifiers.d.ts +4 -0
  100. package/dist/src/self-modification/identifiers.js +1 -0
  101. package/dist/src/self-modification/mode.d.ts +4 -0
  102. package/dist/src/self-modification/mode.js +1 -0
  103. package/dist/src/self-modification/network-policy.d.ts +1 -0
  104. package/dist/src/self-modification/network-policy.js +1 -0
  105. package/dist/src/self-modification/proposal.d.ts +39 -0
  106. package/dist/src/self-modification/proposal.js +2 -0
  107. package/dist/src/self-modification/sandbox.d.ts +25 -1
  108. package/dist/src/self-modification/sandbox.js +1 -1
  109. package/dist/src/self-modification/setup.d.ts +34 -0
  110. package/dist/src/self-modification/setup.js +22 -0
  111. package/dist/src/self-modification/workspace-lock.d.ts +2 -0
  112. package/dist/src/self-modification/workspace-lock.js +1 -0
  113. package/dist/src/setup/integrations/registry.js +1 -1
  114. package/dist/src/setup/integrations/runner.js +1 -1
  115. package/dist/src/setup/integrations/self-modification/setup.d.ts +29 -0
  116. package/dist/src/setup/integrations/self-modification/setup.js +1 -0
  117. package/dist/src/setup/integrations/types.d.ts +2 -0
  118. package/dist/src/setup/integrations/types.js +1 -1
  119. package/dist/src/setup/scaffold/create/project.js +1 -1
  120. package/dist/src/shared/empty-delivery.js +1 -1
  121. package/dist/src/shared/git.d.ts +16 -0
  122. package/dist/src/shared/git.js +1 -0
  123. package/dist/src/shared/shell-quote.d.ts +2 -0
  124. package/dist/src/shared/shell-quote.js +1 -0
  125. package/dist/src/shared/vercel-services.js +1 -1
  126. package/dist/src/tasks/session-index.d.ts +1 -1
  127. package/dist/src/tasks/session-index.js +1 -1
  128. package/dist/src/tasks/session-task-cohorts.d.ts +10 -0
  129. package/dist/src/tasks/session-task-cohorts.js +1 -0
  130. package/dist/src/tools/workflow-definition.d.ts +5 -2
  131. package/docs/concepts/sessions-runs-and-streaming.md +2 -0
  132. package/docs/evals/reporters.mdx +20 -1
  133. package/docs/sandbox.mdx +2 -0
  134. package/docs/subagents/index.mdx +10 -0
  135. package/docs/tools/workflows.mdx +61 -2
  136. package/package.json +17 -1
  137. package/dist/src/self-modification/extension/source-lock.d.ts +0 -2
  138. package/dist/src/self-modification/extension/source-lock.js +0 -1
@@ -0,0 +1 @@
1
+ const SELF_MODIFICATION_GITHUB_TOKEN_ENV=`EVE_SELF_MODIFICATION_GITHUB_TOKEN`;function hasGitHubCredential(){return(process.env.EVE_SELF_MODIFICATION_GITHUB_TOKEN?.trim().length??0)>0}function createGitHubCredentialProvider(e){return e.kind===`pat`?defaultGitHubCredentialProvider:createVercelConnectCredentialProvider(e.connector)}async function resolveGitHubCredential(e){return defaultGitHubCredentialProvider.resolve(e)}const defaultGitHubCredentialProvider={async resolve(){let e=process.env[SELF_MODIFICATION_GITHUB_TOKEN_ENV];if(e===void 0||e.trim().length===0)throw Error(`Self-modification requires ${SELF_MODIFICATION_GITHUB_TOKEN_ENV} in the deployment environment.`);return e.trim()}};function createVercelConnectCredentialProvider(e){return{async resolve(t){try{let{getToken:n}=await import(`@vercel/connect`),r=await n(e,{authorizationDetails:[{type:`github_app_installation`,repositories:[`${t.repository.owner}/${t.repository.repo}`]}],scopes:t.capability===`checkout`?[`contents:read`,`metadata:read`]:[`contents:write`,`pull_requests:write`,`metadata:read`],subject:{type:`app`}});if(r.trim().length===0)throw Error(`empty token`);return r}catch(t){throw Error(`Self-modification could not obtain a GitHub credential from Vercel Connect for ${e}. Install and attach the configured GitHub connector to this Vercel project, install the managed GitHub App for the configured repository, then retry.`,{cause:t})}}}}export{SELF_MODIFICATION_GITHUB_TOKEN_ENV,createGitHubCredentialProvider,createVercelConnectCredentialProvider,defaultGitHubCredentialProvider,hasGitHubCredential,resolveGitHubCredential};
@@ -13,11 +13,17 @@ export type EveAddOutcome = {
13
13
  readonly message: string;
14
14
  readonly changed?: readonly string[];
15
15
  };
16
- interface HeadlessEvent {
16
+ export interface HeadlessEvent {
17
17
  readonly version?: number;
18
18
  readonly type: string;
19
19
  readonly item?: string;
20
+ readonly completedItems?: readonly string[];
21
+ readonly deploymentRequired?: boolean;
22
+ readonly installed?: boolean;
20
23
  readonly message?: string;
24
+ readonly question?: unknown;
25
+ readonly url?: string;
26
+ readonly userCode?: string;
21
27
  readonly failureCode?: string;
22
28
  readonly rolledBack?: boolean;
23
29
  readonly changed?: readonly string[];
@@ -53,4 +59,3 @@ export declare function runEveAdd(input: {
53
59
  readonly signal?: AbortSignal | undefined;
54
60
  readonly spawn?: SpawnLike | undefined;
55
61
  }): Promise<EveAddOutcome>;
56
- export {};
@@ -1,2 +1,2 @@
1
1
  import{findPackageJSON}from"node:module";import{readFile}from"node:fs/promises";import{dirname,isAbsolute,relative,resolve}from"node:path";import{spawn,spawnSync}from"node:child_process";import{pathToFileURL}from"node:url";const INSTALL_TIMEOUT_MS=6e5;function terminateChildTree(e,t){if(e.pid!==void 0){if(process.platform===`win32`){let n=process.env.SystemRoot??process.env.WINDIR;if(n!==void 0&&n!==``&&spawnSync(resolve(n,`System32`,`taskkill.exe`),[`/pid`,String(e.pid),`/t`,...t===`SIGKILL`?[`/f`]:[]],{stdio:`ignore`,windowsHide:!0}).status===0)return}else try{process.kill(-e.pid,t);return}catch{}}e.kill(t)}function isChildTreeAlive(e){if(process.platform===`win32`||e.pid===void 0)return!1;try{return process.kill(-e.pid,0),!0}catch{return!1}}async function resolveEveExecutable(e){let t=findPackageJSON(`eve`,pathToFileURL(resolve(e,`package.json`)));if(t===void 0)throw Error(`The "eve" package is not installed under ${e}, so registry items cannot be installed from here.`);let n=dirname(t),r=JSON.parse(await readFile(t,`utf8`)),i=typeof r==`object`&&r?r.bin:void 0,a=typeof i==`string`?i:typeof i==`object`&&i?i.eve:void 0;if(typeof a!=`string`||a.length===0)throw Error(`The installed "eve" package does not declare an "eve" binary.`);let o=resolve(n,a),s=relative(n,o);if(s.startsWith(`..`)||isAbsolute(s))throw Error(`The installed "eve" package declares its binary outside the package.`);return o}function readTerminalHeadlessEvent(e){let t;for(let n of e.split(`
2
- `)){let e=n.trim();if(!e.startsWith(`{`))continue;let r;try{r=JSON.parse(e)}catch{continue}if(typeof r!=`object`||!r)continue;let i=r;i.version===1&&(i.type===`completed`||i.type===`blocked`||i.type===`failed`||i.type===`cancelled`)&&(t=i)}return t}async function runEveAdd(e){let t=await resolveEveExecutable(e.appRoot),n=e.spawn??spawn;return await new Promise(r=>{let i=n(process.execPath,[t,`add`,e.address,`--non-interactive`,`--skip-setup`],{cwd:e.appRoot,detached:process.platform!==`win32`,env:process.env,stdio:[`ignore`,`pipe`,`pipe`]}),a=``,collect=e=>{a=`${a}${String(e)}`.slice(-64e3)};i.stdout?.on(`data`,collect),i.stderr?.on(`data`,collect);let o=!1,s,c,l,finish=t=>{o||(o=!0,clearTimeout(u),c!==void 0&&clearTimeout(c),l!==void 0&&clearTimeout(l),e.signal?.removeEventListener(`abort`,abort),r(t))},finishAfterTreeExits=e=>{if(isChildTreeAlive(i)){l=setTimeout(()=>finishAfterTreeExits(e),25),l.unref?.();return}finish(s??e)},stop=e=>{s===void 0&&(s=e,terminateChildTree(i,`SIGTERM`),c=setTimeout(()=>terminateChildTree(i,`SIGKILL`),5e3),c.unref?.())},abort=()=>{stop({kind:`failed`,message:`Installing ${e.address} was cancelled.`})},u=setTimeout(()=>{stop({kind:`failed`,message:`Installing ${e.address} did not finish within ${INSTALL_TIMEOUT_MS/6e4} minutes.`})},INSTALL_TIMEOUT_MS);u.unref?.(),e.signal?.aborted===!0?abort():e.signal?.addEventListener(`abort`,abort,{once:!0}),i.on(`error`,()=>{stop({kind:`failed`,message:`Could not run \`eve add ${e.address}\`. Run the command in a terminal for details.`})}),i.on(`close`,t=>{let n,r=readTerminalHeadlessEvent(a);if(t===0&&r?.type===`completed`&&r.item===e.address)n={kind:`installed`};else if(r?.type===`blocked`&&r.item===e.address)n={kind:`blocked`,message:`Installing ${e.address} stopped for input that only a terminal can supply.`};else if(r?.type===`failed`&&r.item===e.address&&typeof r.message==`string`){let e=r.failureCode===`pnpm_build_policy`?"Dependency installation stopped because pnpm requires build-script decisions. Run `pnpm approve-builds`, then retry the eve add command.":`Dependency installation failed. Retry the eve add command in a terminal for details.`,t=Array.isArray(r.changed)?r.changed.filter(e=>typeof e==`string`&&e.length<=300&&!e.includes(`..`)&&/^[\w@+./ -]+$/u.test(e)):[],i=r.rolledBack===!0?`${e} Project files were restored.`:t.length===0?`${e} The install may have partially changed the project.`:`${e} The install partially changed: ${t.join(`, `)}. Restore those files, then retry.`;n=t.length===0?{kind:`failed`,message:i}:{kind:`failed`,message:i,changed:t}}else n={kind:`failed`,message:`\`eve add ${e.address}\` failed and may have partially changed the project. Run it in a terminal for details.`};finishAfterTreeExits(n)})})}export{readTerminalHeadlessEvent,resolveEveExecutable,runEveAdd};
2
+ `)){let e=n.trim();if(!e.startsWith(`{`))continue;let r;try{r=JSON.parse(e)}catch{continue}if(typeof r!=`object`||!r)continue;let i=r;i.version===1&&(i.type===`completed`||i.type===`blocked`||i.type===`failed`||i.type===`cancelled`||i.type===`external_action`)&&(t=i)}return t}async function runEveAdd(e){let t=await resolveEveExecutable(e.appRoot),n=e.spawn??spawn;return await new Promise(r=>{let i=n(process.execPath,[t,`add`,e.address,`--non-interactive`,`--skip-setup`],{cwd:e.appRoot,detached:process.platform!==`win32`,env:process.env,stdio:[`ignore`,`pipe`,`pipe`]}),a=``,collect=e=>{a=`${a}${String(e)}`.slice(-64e3)};i.stdout?.on(`data`,collect),i.stderr?.on(`data`,collect);let o=!1,s,c,l,finish=t=>{o||(o=!0,clearTimeout(u),c!==void 0&&clearTimeout(c),l!==void 0&&clearTimeout(l),e.signal?.removeEventListener(`abort`,abort),r(t))},finishAfterTreeExits=e=>{if(isChildTreeAlive(i)){l=setTimeout(()=>finishAfterTreeExits(e),25),l.unref?.();return}finish(s??e)},stop=e=>{s===void 0&&(s=e,terminateChildTree(i,`SIGTERM`),c=setTimeout(()=>terminateChildTree(i,`SIGKILL`),5e3),c.unref?.())},abort=()=>{stop({kind:`failed`,message:`Installing ${e.address} was cancelled.`})},u=setTimeout(()=>{stop({kind:`failed`,message:`Installing ${e.address} did not finish within ${INSTALL_TIMEOUT_MS/6e4} minutes.`})},INSTALL_TIMEOUT_MS);u.unref?.(),e.signal?.aborted===!0?abort():e.signal?.addEventListener(`abort`,abort,{once:!0}),i.on(`error`,()=>{stop({kind:`failed`,message:`Could not run \`eve add ${e.address}\`. Run the command in a terminal for details.`})}),i.on(`close`,t=>{let n,r=readTerminalHeadlessEvent(a);if(t===0&&r?.type===`completed`&&r.item===e.address)n={kind:`installed`};else if(r?.type===`blocked`&&r.item===e.address)n={kind:`blocked`,message:`Installing ${e.address} stopped for input that only a terminal can supply.`};else if(r?.type===`failed`&&r.item===e.address&&typeof r.message==`string`){let e=r.failureCode===`pnpm_build_policy`?"Dependency installation stopped because pnpm requires build-script decisions. Run `pnpm approve-builds`, then retry the eve add command.":`Dependency installation failed. Retry the eve add command in a terminal for details.`,t=Array.isArray(r.changed)?r.changed.filter(e=>typeof e==`string`&&e.length<=300&&!e.includes(`..`)&&/^[\w@+./ -]+$/u.test(e)):[],i=r.rolledBack===!0?`${e} Project files were restored.`:t.length===0?`${e} The install may have partially changed the project.`:`${e} The install partially changed: ${t.join(`, `)}. Restore those files, then retry.`;n=t.length===0?{kind:`failed`,message:i}:{kind:`failed`,message:i,changed:t}}else n={kind:`failed`,message:`\`eve add ${e.address}\` failed and may have partially changed the project. Run it in a terminal for details.`};finishAfterTreeExits(n)})})}export{readTerminalHeadlessEvent,resolveEveExecutable,runEveAdd};
@@ -1,2 +1,47 @@
1
- declare const _default: import("eve/extension").NoConfigExtensionHandle;
1
+ import { z } from "zod";
2
+ export declare const selfModificationConfigSchema: z.ZodObject<{
3
+ local: z.ZodOptional<z.ZodObject<{
4
+ enabled: z.ZodOptional<z.ZodBoolean>;
5
+ }, z.core.$strip>>;
6
+ deployed: z.ZodOptional<z.ZodObject<{
7
+ credentials: z.ZodOptional<z.ZodObject<{
8
+ pat: z.ZodOptional<z.ZodLiteral<true>>;
9
+ vercelConnect: z.ZodOptional<z.ZodObject<{
10
+ connector: z.ZodString;
11
+ }, z.core.$strip>>;
12
+ }, z.core.$strip>>;
13
+ source: z.ZodObject<{
14
+ git: z.ZodObject<{
15
+ directory: z.ZodString;
16
+ repository: z.ZodString;
17
+ }, z.core.$strip>;
18
+ }, z.core.$strip>;
19
+ target: z.ZodObject<{
20
+ branch: z.ZodString;
21
+ }, z.core.$strip>;
22
+ }, z.core.$strip>>;
23
+ }, z.core.$strip>;
24
+ /** Extension mount configured with the same policy as the agent and sandbox. */
25
+ declare const _default: import("eve/extension").ExtensionHandle<z.ZodObject<{
26
+ local: z.ZodOptional<z.ZodObject<{
27
+ enabled: z.ZodOptional<z.ZodBoolean>;
28
+ }, z.core.$strip>>;
29
+ deployed: z.ZodOptional<z.ZodObject<{
30
+ credentials: z.ZodOptional<z.ZodObject<{
31
+ pat: z.ZodOptional<z.ZodLiteral<true>>;
32
+ vercelConnect: z.ZodOptional<z.ZodObject<{
33
+ connector: z.ZodString;
34
+ }, z.core.$strip>>;
35
+ }, z.core.$strip>>;
36
+ source: z.ZodObject<{
37
+ git: z.ZodObject<{
38
+ directory: z.ZodString;
39
+ repository: z.ZodString;
40
+ }, z.core.$strip>;
41
+ }, z.core.$strip>;
42
+ target: z.ZodObject<{
43
+ branch: z.ZodString;
44
+ }, z.core.$strip>;
45
+ }, z.core.$strip>>;
46
+ }, z.core.$strip>>;
2
47
  export default _default;
@@ -1 +1 @@
1
- import{defineExtension}from"eve/extension";var extension_default=defineExtension();export{extension_default as default};
1
+ import{boolean,literal,object,string}from"../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/schemas.js";import"../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/index.js";import{defineExtension}from"eve/extension";const selfModificationConfigSchema=object({local:object({enabled:boolean().optional()}).optional(),deployed:object({credentials:object({pat:literal(!0).optional(),vercelConnect:object({connector:string()}).optional()}).optional(),source:object({git:object({directory:string(),repository:string()})}),target:object({branch:string()})}).optional()});var extension_default=defineExtension({config:selfModificationConfigSchema});export{extension_default as default,selfModificationConfigSchema};
@@ -1,25 +1,39 @@
1
- import{defineDynamic,defineInstructions}from"eve/instructions";const instructions=`You are an expert coding assistant operating inside of an eve agent. You help users by reading files, editing code, and writing new files that shape the behavior of the agent itself.
1
+ import{resolveSelfModificationConfig}from"../config.js";import{resolveSelfModificationMode}from"../mode.js";import extension_default from"./extension.js";import{defineDynamic,defineInstructions}from"eve/instructions";const introduction=`You are an expert coding assistant operating inside of an eve agent. You help users by reading files, editing code, and writing new files that shape the behavior of the agent itself.
2
2
 
3
3
  The source code of the eve agent is mounted read-write at /source. Use bash only for read-only discovery and available validation commands. Never modify source files with bash, sed, awk, redirection, or scripting. /source is the authored agent directory.
4
4
 
5
5
  Use selfmod__edit_file for precise changes to existing files; every edits[].oldText must match exactly. When changing multiple separate locations in one file, use one call with multiple entries in edits[]. Each oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits; merge nearby changes into one edit. Keep oldText as small as possible while still being unique. Use write_file only for new files or complete rewrites.
6
6
 
7
- Use selfmod__search_models to get the list of available models.
7
+ Use selfmod__search_models to get the list of available models.`,workingGuidance=`Batch independent read-only tool calls and edits to different files in one response. Do not edit the same file concurrently.
8
8
 
9
- Before writing an integration by hand, check whether the eve registry already ships it with selfmod__search_registry. If it has an item that fulfills the requirement, install it with selfmod__registry_add using its address. If the registry does not have any matches that will fulfill the requirement, or if the developer asks for a custom implementation, write the integration yourself.
10
-
11
- The selfmod__registry_add tool will complete installation for items that need no setup. In the local dev TUI, a \`needs-terminal\` result from the tool call automatically opens the existing setup panel for the user to complete setup there. In headless development, relay the terminal command the tool names.
12
-
13
- Batch independent tool calls in one response.
9
+ Run selfmod__registry_add separately from file edits and other registry installations. Complete all edits and registry installations before publication, and call publish by itself.
14
10
 
15
11
  Skip task lists for simple work - only use them for complex actions. Never spend a turn only reporting status or updating the task list - batch them with other calls.
16
12
 
17
13
  Registry installation is outside the source sandbox.
18
14
 
19
- The eve framework documentation is mounted read-only at /eve-docs. Read the eve guide directly relevant to an unfamiliar public API. Prefer an existing local implementation pattern over broad documentation research.
15
+ The eve framework documentation is mounted read-only at /eve-docs. Read the eve guide directly relevant to an unfamiliar public API. Prefer an existing local implementation pattern over broad documentation research.`,developmentMarkdown=`${introduction}
16
+
17
+ Before writing an integration by hand, check whether the eve registry already ships it with selfmod__search_registry. If it has an item that fulfills the requirement, install it with selfmod__registry_add using its address. If the registry does not have any matches that will fulfill the requirement, or if the developer asks for a custom implementation, write the integration yourself.
18
+
19
+ The selfmod__registry_add tool will complete installation for items that need no setup. In the local dev TUI, a \`needs-terminal\` result from the tool call automatically opens the existing setup panel for the user to complete setup there. In headless development, relay the terminal command the tool names.
20
+
21
+ ${workingGuidance}
22
+
23
+ Local eve dev logs are available read-only at /logs.
20
24
 
21
25
  You cannot access application files outside the authored agent directory or run host binaries such as git, node, pnpm, or tsc.
22
26
 
23
27
  Treat a successful file-edit tool result as confirmation; do not reread a file solely to verify that the edit succeeded. Do not approximate unavailable build or test commands with broad source searches.
24
28
 
25
- Local trace segments are mounted read-only at /traces when available. Inspect other traces only when the user asks about another session or broader behavior.`;function readTrace(e){return e.data?.trace}var instructions_default=defineDynamic({events:{"session.started":e=>{let t=readTrace(e);if(t===void 0)return defineInstructions({markdown:instructions});let n=(t.traceFlags&1)==1?`If local segments were captured,`:`This trace was not sampled, so local segments may be absent. If any are present,`;return defineInstructions({markdown:`${instructions}\n\nThe invoking trace has ID ${t.traceId}. ${n} inspect them at /traces/${t.traceId}.`})}}});export{instructions_default as default};
29
+ Local trace segments are mounted read-only at /traces when available. Inspect other traces only when the user asks about another session or broader behavior.`,developmentInstructions=defineInstructions({markdown:developmentMarkdown}),deployedInstructions=defineInstructions({markdown:`${introduction}
30
+
31
+ Before writing an integration by hand, check whether the official eve registry already ships it with selfmod__search_registry. If it has a suitable item, call selfmod__registry_add with the exact address. The tool may return \`completed\`, \`input-required\`, \`external-action-required\`, \`cancelled\`, or \`failed\`. Supply only non-secret structured answers when continuing an \`input-required\` setup; set \`installed: true\` so the continuation does not reinstall source. Never request, accept, or repeat secret values. External authorization and secret binding are incomplete follow-up boundaries, not evidence that an integration is active.
32
+
33
+ ${workingGuidance}
34
+
35
+ The configured target branch is checked out as a disposable workspace under /workspace/repository. Make ordinary changes through /source, which is the writable view of the configured application's agent/ directory. Publication validates the final repository snapshot, including registry, manifest, and lockfile changes. Never modify Git refs, access GitHub directly, or use shell commands to write files. The sandbox has no reusable GitHub credential after checkout.
36
+
37
+ Before publication, review and summarize the complete intended scope. Call publish once with a concise title and summary. A successful result is only a draft pull request. Return its URL and changed paths, and state that merge and deployment have not occurred.
38
+
39
+ Treat a successful file-edit tool result as confirmation; do not reread a file solely to verify that the edit succeeded. Do not approximate unavailable build or test commands with broad source searches.`});function readTrace(e){return e.data?.trace}var instructions_default=defineDynamic({events:{"session.started":e=>{let t=resolveSelfModificationMode(resolveSelfModificationConfig(extension_default.config));if(t===`deployed`)return deployedInstructions;if(t!==`local`)return null;let n=readTrace(e);if(n===void 0)return developmentInstructions;let r=(n.traceFlags&1)==1?`If local segments were captured,`:`This trace was not sampled, so local segments may be absent. If any are present,`;return defineInstructions({markdown:`${developmentMarkdown}\n\nThe invoking trace has ID ${n.traceId}. ${r} inspect them at /traces/${n.traceId}.`})}}});export{instructions_default as default};
@@ -0,0 +1,42 @@
1
+ import type { SandboxSession } from "eve/sandbox";
2
+ import type { PreparedSelfModificationWorkspace } from "../git-workspace.js";
3
+ export type ProductionRegistryInstallResult = {
4
+ readonly kind: "completed";
5
+ readonly completedItems: readonly string[];
6
+ readonly changedPaths: readonly string[];
7
+ readonly deploymentRequired: boolean;
8
+ } | {
9
+ readonly kind: "input-required";
10
+ readonly installed: boolean;
11
+ readonly question: unknown;
12
+ } | {
13
+ readonly kind: "external-action-required";
14
+ readonly installed: boolean;
15
+ readonly message: string;
16
+ readonly url: string;
17
+ readonly userCode?: string;
18
+ } | {
19
+ readonly kind: "failed" | "cancelled";
20
+ readonly message: string;
21
+ };
22
+ export declare function assertOfficialRegistryAddress(address: string): void;
23
+ /** Installs only official items and rolls back this invocation's tree on terminal failure. */
24
+ export declare function installProductionRegistryItem(input: {
25
+ readonly address: string;
26
+ readonly answers?: Readonly<Record<string, unknown>>;
27
+ readonly installed?: boolean;
28
+ readonly sandbox: Pick<SandboxSession, "run">;
29
+ readonly signal?: AbortSignal;
30
+ readonly workspace: PreparedSelfModificationWorkspace;
31
+ }): Promise<ProductionRegistryInstallResult>;
32
+ export declare function acceptsNonSecretSetupAnswers(question: {
33
+ readonly key: string;
34
+ readonly kind: string;
35
+ }, answers: Readonly<Record<string, unknown>>): boolean;
36
+ interface PackageRoot {
37
+ readonly kind: "npm" | "pnpm";
38
+ readonly root: string;
39
+ }
40
+ export declare function locatePackageManagerRoot(sandbox: Pick<SandboxSession, "run">, applicationRoot: string, repositoryRoot: string, signal?: AbortSignal): Promise<PackageRoot | undefined>;
41
+ export declare function bootstrapCommand(root: PackageRoot): string;
42
+ export {};
@@ -0,0 +1 @@
1
+ import{assertFullSha}from"../identifiers.js";import{readTerminalHeadlessEvent}from"./eve-add.js";import{gitOutput,runGitCommand}from"../git.js";import{shellQuote}from"#shared/shell-quote.js";const OFFICIAL_ADDRESS=/^(?:(?:channel|connection|extension|instrumentation)\/)?[a-z0-9][a-z0-9._-]*$/u;function assertOfficialRegistryAddress(e){if(!OFFICIAL_ADDRESS.test(e))throw Error(`Production registry installation requires an exact official eve registry address.`)}async function installProductionRegistryItem(e){assertOfficialRegistryAddress(e.address);let t=e.workspace.directory===`.`?e.workspace.repositoryPath:`${e.workspace.repositoryPath}/${e.workspace.directory}`,n=await locatePackageManagerRoot(e.sandbox,t,e.workspace.repositoryPath,e.signal);if(n===void 0)return{kind:`failed`,message:`The proposal checkout has no supported lockfile.`};if(!await runChecked(e.sandbox,`mkdir -p ${quote(`${e.workspace.repositoryPath}/.git/info`)} && printf '\\nnode_modules/\\n**/node_modules/\\n' >> ${quote(`${e.workspace.repositoryPath}/.git/info/exclude`)}`,e.signal)||!await runChecked(e.sandbox,bootstrapCommand(n),e.signal))return{kind:`failed`,message:`Could not prepare the proposal checkout's locked dependencies.`};let r=await locateEveExecutable(e.sandbox,t,n.root,e.signal);if(r===void 0)return{kind:`failed`,message:`The proposal checkout's locked dependencies do not provide the eve CLI.`};let i=await captureTree(e.sandbox,e.workspace.repositoryPath);if(e.answers!==void 0){if(e.installed!==!0)return{kind:`failed`,message:`Setup answers require a prior installed input-required result.`};let n;try{n=await e.sandbox.run({abortSignal:e.signal,command:isolatedCommand(t,`${quote(r)} add ${quote(e.address)} --non-interactive --skip-install`)})}finally{await restoreTree(e.sandbox,e.workspace.repositoryPath,i)}let a=readTerminalHeadlessEvent(`${String(n.stdout??``)}\n${String(n.stderr??``)}`);if(a?.type!==`blocked`||a.item!==e.address)return{kind:`failed`,message:`Setup continuation is no longer waiting for a validated question.`};let o=setupQuestion(a.question);if(o===void 0)return{kind:`failed`,message:`Registry setup returned an invalid continuation question.`};if(o.kind===`environment`)return{kind:`input-required`,installed:!0,question:a.question};if(!acceptsNonSecretSetupAnswers(o,e.answers))return{kind:`failed`,message:`Setup answers must contain only the current non-secret question.`}}let a=Object.entries(e.answers??{}).flatMap(([e,t])=>[`--answer`,`${e}=${JSON.stringify(t)}`]);try{let n=`${quote(r)} add ${quote(e.address)} --non-interactive ${e.installed===!0?`--skip-install `:``}${a.map(quote).join(` `)}`,o=await e.sandbox.run({abortSignal:e.signal,command:isolatedCommand(t,n)}),s=readTerminalHeadlessEvent(`${String(o.stdout??``)}\n${String(o.stderr??``)}`);if(s?.type===`completed`&&s.item===e.address&&o.exitCode===0){let t=await captureTree(e.sandbox,e.workspace.repositoryPath);return{kind:`completed`,changedPaths:await changedPaths(e.sandbox,e.workspace.repositoryPath,i,t),completedItems:s.completedItems?.filter(e=>OFFICIAL_ADDRESS.test(e))??[],deploymentRequired:s.deploymentRequired===!0}}if(s?.type===`blocked`&&s.item===e.address)return{kind:`input-required`,installed:s.installed===!0,question:s.question??s};if(s?.type===`external_action`&&typeof s.url==`string`&&typeof s.message==`string`){let t={kind:`external-action-required`,installed:e.installed===!0,message:s.message,url:s.url};return typeof s.userCode==`string`&&(t.userCode=s.userCode),t}return await restoreTree(e.sandbox,e.workspace.repositoryPath,i),s?.type===`cancelled`||e.signal?.aborted===!0?{kind:`cancelled`,message:`Installing ${e.address} was cancelled.`}:{kind:`failed`,message:`Installing ${e.address} failed.`}}catch(t){throw await restoreTree(e.sandbox,e.workspace.repositoryPath,i),t}}function acceptsNonSecretSetupAnswers(e,t){return e.kind!==`environment`&&Object.keys(t).length===1&&t[e.key]!==void 0}function setupQuestion(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e;if(typeof t.key==`string`&&t.key.length!==0&&typeof t.kind==`string`)return{key:t.key,kind:t.sensitive===!0?`environment`:t.kind}}async function locatePackageManagerRoot(e,t,n,r){let i=await e.run({abortSignal:r,command:`root=${quote(t)}; repository=${quote(n)}; while :; do if test -f "$root/pnpm-lock.yaml"; then printf 'pnpm\\t%s' "$root"; exit 0; fi; if test -f "$root/package-lock.json"; then printf 'npm\\t%s' "$root"; exit 0; fi; test "$root" = "$repository" && exit 0; root=\${root%/*}; done`});if(i.exitCode!==0)throw Error(`Could not inspect the proposal package workspace.`);let a=/^(pnpm|npm)\t([^\n]+)$/u.exec(String(i.stdout??``));if(a===null)return;let o=a[2];if(o!==n&&!o.startsWith(`${n}/`))throw Error(`Package manager root escaped the proposal repository.`);return{kind:a[1],root:o}}function bootstrapCommand(e){return isolatedCommand(e.root,e.kind===`pnpm`?`corepack pnpm --dir ${quote(e.root)} install --frozen-lockfile --ignore-scripts`:`npm ci --prefix ${quote(e.root)} --ignore-scripts`)}async function locateEveExecutable(e,t,n,r){let i=[`${t}/node_modules/.bin/eve`,`${n}/node_modules/.bin/eve`],a=await e.run({abortSignal:r,command:`for executable in ${i.map(quote).join(` `)}; do if test -x "$executable"; then printf '%s' "$executable"; exit 0; fi; done`});if(a.exitCode!==0)throw Error(`Could not inspect the checkout's eve executable.`);return i.includes(String(a.stdout??``))?String(a.stdout):void 0}async function captureTree(e,t){await runGitCommand(e,`git -C ${quote(t)} add -A -- .`);let n=await gitOutput(e,`git -C ${quote(t)} write-tree`);return assertFullSha(n,`registry tree`),n}async function restoreTree(e,t,n){await runGitCommand(e,`git -C ${quote(t)} read-tree --reset -u ${quote(n)}`),await runGitCommand(e,`git -C ${quote(t)} clean -fd -- .`)}async function changedPaths(e,t,n,r){return(await gitOutput(e,`git -C ${quote(t)} diff-tree -r --no-commit-id --name-only -z ${quote(n)} ${quote(r)}`,!1)).split(`\0`).filter(e=>e.length>0)}async function runChecked(e,t,n){return(await e.run({abortSignal:n,command:t})).exitCode===0}function isolatedCommand(e,t){return`env -i HOME=/tmp/eve-selfmod-home PATH=/usr/local/bin:/usr/bin:/bin CI=1 npm_config_ignore_scripts=true sh -c ${quote(`cd ${quote(e)} && ${t}`)}`}function quote(e){return shellQuote(e)}export{acceptsNonSecretSetupAnswers,assertOfficialRegistryAddress,bootstrapCommand,installProductionRegistryItem,locatePackageManagerRoot};
@@ -1 +1 @@
1
- import{withAuthoredSourceLock}from"../source-lock.js";import{defineTool}from"eve/tools";const inputSchema={type:`object`,additionalProperties:!1,properties:{path:{type:`string`,minLength:1,description:`Path to the file to edit (relative or absolute).`},edits:{type:`array`,minItems:1,items:{type:`object`,additionalProperties:!1,properties:{oldText:{type:`string`,minLength:1,description:`Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.`},newText:{type:`string`,description:`Replacement text for this targeted edit.`}},required:[`oldText`,`newText`]},description:`One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.`}},required:[`path`,`edits`]},outputSchema={type:`object`,additionalProperties:!1,properties:{path:{type:`string`},replacements:{type:`integer`,minimum:1}},required:[`path`,`replacements`]};function applyExactEdits(e,t){if(t.length===0)throw Error(`edits must contain at least one replacement.`);let n=[...t.map((t,n)=>{if(t.oldText.length===0)throw Error(`edits[${n}].oldText must not be empty.`);let r=e.indexOf(t.oldText);if(r===-1)throw Error(`edits[${n}].oldText was not found in the current file. Read the file and try again.`);if(e.indexOf(t.oldText,r+1)!==-1)throw Error(`edits[${n}].oldText occurs more than once. Include more surrounding text to make it unique.`);return{...t,end:r+t.oldText.length,index:n,start:r}})].sort((e,t)=>e.start-t.start);for(let e=1;e<n.length;e+=1){let t=n[e-1],r=n[e];if(t!==void 0&&r!==void 0&&r.start<t.end)throw Error(`edits[${t.index}] and edits[${r.index}] overlap. Merge them into one edit.`)}return n.toReversed().reduce((e,t)=>e.slice(0,t.start)+t.newText+e.slice(t.end),e)}var edit_file_default=defineTool({description:`Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.`,inputSchema,outputSchema,async execute(e,t){let{edits:n,path:r}=e;if(typeof r!=`string`||!Array.isArray(n)||n.some(e=>typeof e!=`object`||!e||typeof e.oldText!=`string`||typeof e.newText!=`string`))throw Error(`path must be a string and edits must contain oldText and newText strings.`);let i=await t.getSandbox();return await withAuthoredSourceLock(async()=>{let e=await i.readTextFile({path:r});if(e===null)throw Error(`File not found: ${r}.`);if(e.includes(`\0`))throw Error(`File "${r}" contains NUL bytes and appears to be binary.`);return await i.writeTextFile({content:applyExactEdits(e,n),path:r}),{path:i.resolvePath(r),replacements:n.length}})}});export{applyExactEdits,edit_file_default as default};
1
+ import{defineTool}from"eve/tools";const inputSchema={type:`object`,additionalProperties:!1,properties:{path:{type:`string`,minLength:1,description:`Absolute path below /source to edit.`},edits:{type:`array`,minItems:1,items:{type:`object`,additionalProperties:!1,properties:{oldText:{type:`string`,minLength:1,description:`Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.`},newText:{type:`string`,description:`Replacement text for this targeted edit.`}},required:[`oldText`,`newText`]},description:`One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.`}},required:[`path`,`edits`]},outputSchema={type:`object`,additionalProperties:!1,properties:{path:{type:`string`},replacements:{type:`integer`,minimum:1}},required:[`path`,`replacements`]};function applyExactEdits(e,t){if(t.length===0)throw Error(`edits must contain at least one replacement.`);let n=[...t.map((t,n)=>{if(t.oldText.length===0)throw Error(`edits[${n}].oldText must not be empty.`);let r=e.indexOf(t.oldText);if(r===-1)throw Error(`edits[${n}].oldText was not found in the current file. Read the file and try again.`);if(e.indexOf(t.oldText,r+1)!==-1)throw Error(`edits[${n}].oldText occurs more than once. Include more surrounding text to make it unique.`);return{...t,end:r+t.oldText.length,index:n,start:r}})].sort((e,t)=>e.start-t.start);for(let e=1;e<n.length;e+=1){let t=n[e-1],r=n[e];if(t!==void 0&&r!==void 0&&r.start<t.end)throw Error(`edits[${t.index}] and edits[${r.index}] overlap. Merge them into one edit.`)}return n.toReversed().reduce((e,t)=>e.slice(0,t.start)+t.newText+e.slice(t.end),e)}var edit_file_default=defineTool({description:`Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.`,inputSchema,outputSchema,async execute(e,t){let{edits:n,path:r}=e;if(typeof r!=`string`||!Array.isArray(n)||n.some(e=>typeof e!=`object`||!e||typeof e.oldText!=`string`||typeof e.newText!=`string`))throw Error(`path must be a string and edits must contain oldText and newText strings.`);let i=await t.getSandbox(),a=i.resolvePath(r);if(!a.startsWith(`/source/`)||a.split(`/`).some(e=>e===`..`))throw Error(`Self-modification file edits must stay below /source.`);let o=await i.readTextFile({path:a});if(o===null)throw Error(`File not found: ${r}.`);if(o.includes(`\0`))throw Error(`File "${r}" contains NUL bytes and appears to be binary.`);return await i.writeTextFile({content:applyExactEdits(o,n),path:a}),{path:a,replacements:n.length}}});export{applyExactEdits,edit_file_default as default};
@@ -0,0 +1,7 @@
1
+ import { type ToolContext } from "eve/tools";
2
+ /** Derives replay identity only from eve's verified delegation lineage. */
3
+ export declare function publicationOperationId(ctx: Pick<ToolContext, "session">): string;
4
+ declare const _default: import("eve/tools").DynamicSentinel<(import("eve/tools").ToolDefinition<Record<string, unknown>, import("../../github-publisher.js").PublishedSelfModificationProposal> & {
5
+ execute(input: Record<string, unknown>, ctx: ToolContext): Promise<import("../../github-publisher.js").PublishedSelfModificationProposal>;
6
+ }) | null>;
7
+ export default _default;
@@ -0,0 +1 @@
1
+ import{resolveSelfModificationConfig}from"../../config.js";import{createGitHubCredentialProvider}from"../../credentials.js";import{resolveSelfModificationMode}from"../../mode.js";import extension_default from"../extension.js";import{readPreparedSelfModificationWorkspace}from"../../git-workspace.js";import{publishGitHubDraftPullRequest}from"../../github-publisher.js";import{withSelfModificationWorkspaceLock}from"../../workspace-lock.js";import{defineDynamic,defineTool}from"eve/tools";const inputSchema={type:`object`,additionalProperties:!1,properties:{summary:{type:`string`,minLength:1,maxLength:1e4,description:`Concise description of the proposed agent source change.`},title:{type:`string`,minLength:1,maxLength:256,description:`Concise draft pull request title.`}},required:[`summary`,`title`]},outputSchema={type:`object`,additionalProperties:!1,properties:{branch:{type:`string`},changedPaths:{type:`array`,items:{type:`string`}},commitSha:{type:`string`},deployed:{type:`boolean`,const:!1},draft:{type:`boolean`,const:!0},merged:{type:`boolean`,const:!1},pullRequestUrl:{type:`string`},repository:{type:`string`},targetBranch:{type:`string`}},required:[`branch`,`changedPaths`,`commitSha`,`deployed`,`draft`,`merged`,`pullRequestUrl`,`repository`,`targetBranch`]};function resolveTool(){let e=resolveSelfModificationConfig(extension_default.config);return resolveSelfModificationMode(e)!==`deployed`||e.deployed===void 0?null:defineTool({description:`Publish the complete validated agent source change as one draft pull request. Merge and deployment do not occur.`,inputSchema,outputSchema,execute:publish})}async function publish(e,t){if(typeof e!=`object`||!e||!(`summary`in e)||typeof e.summary!=`string`||e.summary.trim().length===0||!(`title`in e)||typeof e.title!=`string`||e.title.trim().length===0)throw Error(`Production publication requires a valid title and summary.`);let n=resolveSelfModificationConfig(extension_default.config);if(resolveSelfModificationMode(n)!==`deployed`||n.deployed===void 0)throw Error(`Production publication requires deployed self-modification configuration.`);let r=n.deployed,i=e.summary,a=e.title,o=publicationOperationId(t),s=await t.getSandbox();return await withSelfModificationWorkspaceLock(`sandbox:${s.id}`,async()=>{let e=await readPreparedSelfModificationWorkspace({...r,sandbox:s});return await publishGitHubDraftPullRequest({credentialProvider:createGitHubCredentialProvider(r.credentials),description:i,operationId:o,sandbox:s,title:a,workspace:e})})}function publicationOperationId(e){let t=e.session.parent;if(t===void 0)throw Error(`Production publication requires a delegated child session.`);return`${t.rootSessionId}:${t.sessionId}:${t.turn.id}:${t.callId}:${e.session.id}`}var publish_default=defineDynamic({events:{"session.started":resolveTool}});export{publish_default as default,publicationOperationId};
@@ -1,12 +1,14 @@
1
1
  import { type LocalDevCapability } from "eve/local-dev";
2
+ import { type ToolContext } from "eve/tools";
3
+ import { type ResolvedSelfModificationConfig } from "../../config.js";
2
4
  import { type SpawnLike } from "../eve-add.js";
3
5
  import { type CatalogEntry } from "./search_registry.js";
4
6
  interface RegistryAddDependencies {
5
7
  readonly getCapability?: () => LocalDevCapability | undefined;
6
8
  readonly spawn?: SpawnLike;
7
9
  }
8
- /** What the tool reports back. Mirrors {@link outputSchema}. */
9
- export interface RegistryAddResult {
10
+ /** What local registry installation reports back. Mirrors {@link localOutputSchema}. */
11
+ export interface LocalRegistryAddResult {
10
12
  readonly address: string;
11
13
  /** `failed` carries an explicit mutation outcome instead of implying nothing changed. */
12
14
  readonly status: "installed" | "needs-terminal" | "failed";
@@ -17,6 +19,29 @@ export interface RegistryAddResult {
17
19
  readonly nextCommand?: string;
18
20
  readonly changed?: readonly string[];
19
21
  }
22
+ type ProductionRegistryAddResult = {
23
+ readonly address: string;
24
+ readonly status: "completed";
25
+ readonly completedItems: readonly string[];
26
+ readonly changedPaths: readonly string[];
27
+ readonly deploymentRequired: boolean;
28
+ } | {
29
+ readonly address: string;
30
+ readonly status: "input-required";
31
+ readonly installed: boolean;
32
+ readonly question: unknown;
33
+ } | {
34
+ readonly address: string;
35
+ readonly status: "external-action-required";
36
+ readonly installed: boolean;
37
+ readonly message: string;
38
+ readonly url: string;
39
+ readonly userCode?: string;
40
+ } | {
41
+ readonly address: string;
42
+ readonly status: "failed" | "cancelled";
43
+ readonly message: string;
44
+ };
20
45
  /**
21
46
  * Names the item's declared environment variables that are not set.
22
47
  *
@@ -43,10 +68,17 @@ export declare function handoffMessage(input: {
43
68
  readonly nextCommand?: string;
44
69
  };
45
70
  /** Exported for tests; the tool's `execute` delegates here. */
46
- export declare function addRegistryItem(address: string, options?: RegistryAddDependencies & {
71
+ export declare function addLocalRegistryItem(address: string, options?: RegistryAddDependencies & {
47
72
  readonly signal?: AbortSignal;
48
- }): Promise<RegistryAddResult>;
49
- declare const _default: import("eve/tools").ToolDefinition<Record<string, unknown>, RegistryAddResult> & {
50
- execute(input: Record<string, unknown>, ctx: import("eve/tools").ToolContext): Promise<RegistryAddResult>;
51
- };
73
+ }): Promise<LocalRegistryAddResult>;
74
+ export declare function resolveRegistryAddTool(config: ResolvedSelfModificationConfig): (import("eve/tools").ToolDefinition<Record<string, unknown>, LocalRegistryAddResult> & {
75
+ execute(input: Record<string, unknown>, ctx: ToolContext): Promise<LocalRegistryAddResult>;
76
+ }) | (import("eve/tools").ToolDefinition<Record<string, unknown>, ProductionRegistryAddResult> & {
77
+ execute(input: Record<string, unknown>, ctx: ToolContext): Promise<ProductionRegistryAddResult>;
78
+ }) | null;
79
+ declare const _default: import("eve/tools").DynamicSentinel<(import("eve/tools").ToolDefinition<Record<string, unknown>, LocalRegistryAddResult> & {
80
+ execute(input: Record<string, unknown>, ctx: ToolContext): Promise<LocalRegistryAddResult>;
81
+ }) | (import("eve/tools").ToolDefinition<Record<string, unknown>, ProductionRegistryAddResult> & {
82
+ execute(input: Record<string, unknown>, ctx: ToolContext): Promise<ProductionRegistryAddResult>;
83
+ }) | null>;
52
84
  export default _default;
@@ -1 +1 @@
1
- import{classifyCatalogEntry}from"../classify-registry-item.js";import{runEveAdd}from"../eve-add.js";import{withAuthoredSourceLock}from"../source-lock.js";import{loadRegistryIndex,resolveRegistryIndexUrl}from"./search_registry.js";import{defineTool}from"eve/tools";import{getLocalDevCapability}from"eve/local-dev";import{once}from"eve/tools/approval";const inputSchema={type:`object`,additionalProperties:!1,properties:{address:{type:`string`,minLength:1,maxLength:200,description:"Exact address of an item in the configured eve registry, for example `channel/slack` or `extension/browserbase`."}},required:[`address`]},outputSchema={type:`object`,additionalProperties:!1,properties:{status:{type:`string`,enum:[`installed`,`needs-terminal`,`failed`],description:"`installed` means the item is present. `needs-terminal` means nothing was installed. `failed` means installation stopped; read `message` and `changed` before retrying."},address:{type:`string`},title:{type:`string`},envVars:{type:`array`,items:{type:`string`},description:`Environment variables the item needs that are not set. The item is installed but will not work until the developer sets them. Never ask for or repeat their values.`},reason:{type:`string`,description:`Why the item was not installed here.`},changed:{type:`array`,items:{type:`string`},description:`Project-relative paths a failed install could not restore.`},nextCommand:{type:`string`,description:"The command that completes a `needs-terminal` item."},message:{type:`string`,description:`One-line summary to relay to the developer.`}},required:[`status`,`address`,`message`]};function unsetEnvVars(e,t=process.env){return(e.envVars??[]).filter(e=>{let n=t[e];return n===void 0||n===``})}function handoffMessage(e){if(e.interactiveClient)return{message:`${e.title} was not installed by this tool. ${e.reason} Continue in the setup panel that opens here; do not ask the developer to run another command.`};let t=`eve add ${e.address}`;return{message:`${e.title} was not installed. ${e.reason} Run \`${t}\` in a terminal to finish it.`,nextCommand:t}}async function addRegistryItem(e,t={}){let n=(t.getCapability??getLocalDevCapability)();if(n===void 0)throw Error("Registry items can only be installed while `eve dev` is running. Report the item address to the developer instead of installing it.");let r=(await loadRegistryIndex({nowMs:Date.now(),signal:t.signal,url:resolveRegistryIndexUrl()})).find(t=>t.address===e);if(r===void 0)throw Error(`No item in the configured eve registry is published at "${e}". Check the address before trying again.`);let i=classifyCatalogEntry(r);if(i.kind===`needs-terminal`){let t=handoffMessage({address:e,interactiveClient:n.interactiveClient,reason:i.reason,title:r.title});return{address:e,reason:i.reason,status:`needs-terminal`,title:r.title,...t}}let a=await withAuthoredSourceLock(()=>n.withSuspendedSource(()=>runEveAdd({address:e,appRoot:n.appRoot,signal:t.signal,spawn:t.spawn})));if(a.kind===`blocked`){let t=handoffMessage({address:e,interactiveClient:n.interactiveClient,reason:a.message,title:r.title});return{address:e,reason:a.message,status:`needs-terminal`,title:r.title,...t}}if(a.kind===`failed`)return a.changed===void 0?{address:e,status:`failed`,title:r.title,reason:a.message,message:a.message}:{address:e,status:`failed`,title:r.title,reason:a.message,message:a.message,changed:a.changed};let o=unsetEnvVars(r);return{address:e,envVars:[...o],message:o.length===0?`Installed ${r.title}.`:`Installed ${r.title}. It will not work until ${o.join(`, `)} ${o.length===1?`is`:`are`} set.`,status:`installed`,title:r.title}}var registry_add_default=defineTool({approval:once(),description:"Install an item from the configured eve registry into this project, for example `channel/slack` or `extension/browserbase`. Only items that need no setup are installed here; an item with a setup flow or multiple components is reported back with the command that completes it, and nothing is installed. Development only. Search first, then call this with the exact item address.",inputSchema,outputSchema,async execute(e,t){let{address:n}=e;if(typeof n!=`string`||n.length===0)throw Error(`address must be an exact item address from the configured eve registry.`);return await addRegistryItem(n,{signal:t.abortSignal})}});export{addRegistryItem,registry_add_default as default,handoffMessage,unsetEnvVars};
1
+ import{resolveSelfModificationConfig}from"../../config.js";import{resolveSelfModificationMode}from"../../mode.js";import{classifyCatalogEntry}from"../classify-registry-item.js";import{runEveAdd}from"../eve-add.js";import extension_default from"../extension.js";import{assertOfficialRegistryAddress,installProductionRegistryItem}from"../production-registry-add.js";import{readPreparedSelfModificationWorkspace}from"../../git-workspace.js";import{withSelfModificationWorkspaceLock}from"../../workspace-lock.js";import{loadRegistryIndex,officialRegistryIndexUrl,resolveRegistryIndexUrl}from"./search_registry.js";import{defineDynamic,defineTool}from"eve/tools";import{getLocalDevCapability}from"eve/local-dev";import{once}from"eve/tools/approval";const localInputSchema={type:`object`,additionalProperties:!1,properties:{address:{type:`string`,minLength:1,maxLength:200,description:"Exact address of an item in the configured eve registry, for example `channel/slack` or `extension/browserbase`."}},required:[`address`]},localOutputSchema={type:`object`,additionalProperties:!1,properties:{status:{type:`string`,enum:[`installed`,`needs-terminal`,`failed`]},address:{type:`string`},title:{type:`string`},envVars:{type:`array`,items:{type:`string`},description:`Environment variables the item needs that are not set. The item is installed but will not work until the developer sets them. Never ask for or repeat their values.`},reason:{type:`string`,description:`Why the item was not installed here.`},changed:{type:`array`,items:{type:`string`},description:`Project-relative paths a failed install could not restore.`},nextCommand:{type:`string`,description:"The command that completes a `needs-terminal` item."},message:{type:`string`,description:`One-line summary to relay to the developer.`}},required:[`status`,`address`,`message`]},productionInputSchema={type:`object`,additionalProperties:!1,properties:{address:{type:`string`,minLength:1,maxLength:200,description:"Exact official eve registry address, for example `channel/slack` or `extension/browserbase`."},answers:{type:`object`,additionalProperties:!0,description:`Non-secret answers to the setup question returned by the previous call.`},installed:{type:`boolean`,description:`Set to true with answers when the previous input-required result installed the source.`}},required:[`address`]},productionOutputSchema={type:`object`,additionalProperties:!1,properties:{status:{type:`string`,enum:[`completed`,`input-required`,`external-action-required`,`failed`,`cancelled`]},address:{type:`string`},changedPaths:{type:`array`,items:{type:`string`},description:`Repository-relative paths installed into the proposal.`},completedItems:{type:`array`,items:{type:`string`}},deploymentRequired:{type:`boolean`},installed:{type:`boolean`,description:`Whether source installation completed before setup paused.`},question:{type:`object`,additionalProperties:!0,description:`The current setup question. Supply only its non-secret answer on the next call.`},message:{type:`string`},url:{type:`string`,description:`External authorization URL the developer must open.`},userCode:{type:`string`}},required:[`status`,`address`]};function unsetEnvVars(e,t=process.env){return(e.envVars??[]).filter(e=>{let n=t[e];return n===void 0||n===``})}function handoffMessage(e){if(e.interactiveClient)return{message:`${e.title} was not installed by this tool. ${e.reason} Continue in the setup panel that opens here; do not ask the developer to run another command.`};let t=`eve add ${e.address}`;return{message:`${e.title} was not installed. ${e.reason} Run \`${t}\` in a terminal to finish it.`,nextCommand:t}}async function addLocalRegistryItem(e,t={}){let n=(t.getCapability??getLocalDevCapability)();if(n===void 0)throw Error("Registry items can only be installed while `eve dev` is running. Report the item address to the developer instead of installing it.");let r=(await loadRegistryIndex({nowMs:Date.now(),signal:t.signal,url:resolveRegistryIndexUrl()})).find(t=>t.address===e);if(r===void 0)throw Error(`No item in the configured eve registry is published at "${e}". Check the address before trying again.`);let i=classifyCatalogEntry(r);if(i.kind===`needs-terminal`){let t=handoffMessage({address:e,interactiveClient:n.interactiveClient,reason:i.reason,title:r.title});return{address:e,reason:i.reason,status:`needs-terminal`,title:r.title,...t}}let a=await withSelfModificationWorkspaceLock(`local:${n.appRoot}`,async()=>n.withSuspendedSource(()=>runEveAdd({address:e,appRoot:n.appRoot,signal:t.signal,spawn:t.spawn})));if(a.kind===`blocked`){let t=handoffMessage({address:e,interactiveClient:n.interactiveClient,reason:a.message,title:r.title});return{address:e,reason:a.message,status:`needs-terminal`,title:r.title,...t}}if(a.kind===`failed`)return a.changed===void 0?{address:e,status:`failed`,title:r.title,reason:a.message,message:a.message}:{address:e,status:`failed`,title:r.title,reason:a.message,message:a.message,changed:a.changed};let o=unsetEnvVars(r);return{address:e,envVars:[...o],message:o.length===0?`Installed ${r.title}.`:`Installed ${r.title}. It will not work until ${o.join(`, `)} ${o.length===1?`is`:`are`} set.`,status:`installed`,title:r.title}}async function addProductionRegistryItem(e,t,n,r){if(assertOfficialRegistryAddress(e),(await loadRegistryIndex({nowMs:Date.now(),signal:t.abortSignal,url:officialRegistryIndexUrl()})).find(t=>t.address===e)===void 0)throw Error(`No official eve registry item is published at "${e}".`);let i=await t.getSandbox(),a=await withSelfModificationWorkspaceLock(`sandbox:${i.id}`,async()=>{let a=await readPreparedSelfModificationWorkspace({...n,sandbox:i});return await installProductionRegistryItem({address:e,answers:r.answers,installed:r.installed,sandbox:i,signal:t.abortSignal,workspace:a})});return a.kind===`completed`?{address:e,...a,status:`completed`}:a.kind===`input-required`?{address:e,...a,status:`input-required`}:a.kind===`external-action-required`?{address:e,...a,status:`external-action-required`}:{address:e,...a,status:a.kind}}function localRegistryAddTool(){return defineTool({approval:once(),description:`Install an item from the configured eve registry into this project. Items that need setup are handed to the local setup flow instead. Search first, then call this with the exact item address.`,inputSchema:localInputSchema,outputSchema:localOutputSchema,async execute(e,t){let{address:n}=e;if(typeof n!=`string`||n.length===0)throw Error(`address must be an exact item address from the configured eve registry.`);return await addLocalRegistryItem(n,{signal:t.abortSignal})}})}function productionRegistryAddTool(e){return defineTool({approval:once(),description:`Install an exact item from the official eve registry into the current production change proposal. If setup pauses, call this tool again with the non-secret answers and the installed state from its result. External authorization and secret binding must be completed by the developer.`,inputSchema:productionInputSchema,outputSchema:productionOutputSchema,async execute(t,n){let{address:r}=t;if(typeof r!=`string`||r.length===0)throw Error(`address must be an exact item address from the official eve registry.`);return await addProductionRegistryItem(r,n,e,{answers:`answers`in t&&typeof t.answers==`object`&&t.answers!==null&&!Array.isArray(t.answers)?t.answers:void 0,installed:`installed`in t&&t.installed===!0})}})}function resolveRegistryAddTool(e){let t=resolveSelfModificationMode(e);return t===`local`?localRegistryAddTool():t===`deployed`&&e.deployed!==void 0?productionRegistryAddTool(e.deployed):null}var registry_add_default=defineDynamic({events:{"session.started":()=>resolveRegistryAddTool(resolveSelfModificationConfig(extension_default.config))}});export{addLocalRegistryItem,registry_add_default as default,handoffMessage,resolveRegistryAddTool,unsetEnvVars};
@@ -71,6 +71,7 @@ export declare function selectIntegrationPage(input: {
71
71
  * rather than imported because that module reaches the registry client, which
72
72
  * has no place in an agent runtime.
73
73
  */
74
+ export declare function officialRegistryIndexUrl(): string;
74
75
  export declare function resolveRegistryIndexUrl(configured?: string | undefined): string;
75
76
  /** Clears the module-level index cache. Test seam. */
76
77
  export declare function clearRegistryIndexCache(): void;
@@ -1 +1 @@
1
- import{defineTool}from"eve/tools";const CATEGORIES=[`channel`,`connection`,`extension`,`instrumentation`],INDEX_PATH=`/registry.json`,FETCH_TIMEOUT_MS=1e4,inputSchema={type:`object`,additionalProperties:!1,properties:{query:{type:`string`,maxLength:200,description:`Free-text match against integration names, titles, and descriptions.`},category:{type:`string`,enum:[...CATEGORIES],description:`Restrict results to one registry category.`},limit:{type:`integer`,minimum:1,maximum:25,description:`Maximum number of items to return (default 10, maximum 25).`},offset:{type:`integer`,minimum:0,description:`Number of matching items to skip. Use nextOffset from a prior result to retrieve the next page.`}}},outputSchema={type:`object`,additionalProperties:!1,properties:{items:{type:`array`,items:{type:`object`,additionalProperties:!1,properties:{address:{type:`string`},title:{type:`string`},description:{type:`string`},category:{type:`string`},components:{type:`array`,items:{type:`string`}},requires:{type:`string`},installed:{type:`boolean`}},required:[`address`,`title`]}},errors:{type:`array`,items:{type:`object`,additionalProperties:!1,properties:{registry:{type:`string`},message:{type:`string`}},required:[`registry`,`message`]}},total:{type:`integer`},hasMore:{type:`boolean`},nextOffset:{type:`integer`}},required:[`items`,`errors`,`total`,`hasMore`]};function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function optionalString(e){return typeof e==`string`&&e.length>0?e:void 0}function isCategory(e){return CATEGORIES.includes(e)}function categoryOf(e){let t=e.split(`/`)[0];return t!==void 0&&e.includes(`/`)&&isCategory(t)?t:void 0}function titleFromAddress(e){return(e.split(`/`).at(-1)??e).split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function eveMetadata(e){let t=e.meta;if(!isRecord(t))return{};let n=t.eve;return isRecord(n)?n:{}}function componentMetadata(e){let t=e.components;if(!Array.isArray(t))return;let n=[],r=[];for(let e of t){if(!isRecord(e))continue;let t=optionalString(e.item);if(t===void 0)continue;n.push(t),r.push(t);let i=optionalString(e.label);i!==void 0&&r.push(i);let a=optionalString(e.description);a!==void 0&&r.push(a)}return n.length>0?{addresses:n,searchTerms:r}:void 0}function authoredTargetOf(e){let t=e.files;if(Array.isArray(t))for(let e of t){if(!isRecord(e))continue;let t=optionalString(e.target);if(t?.startsWith(`agent/`)===!0)return t}}function declaredEnvVars(e){let t=e.envVars;return isRecord(t)?Object.keys(t):[]}function parseRegistryIndex(e){if(!isRecord(e)||!Array.isArray(e.items))return[];let t=[];for(let n of e.items){if(!isRecord(n))continue;let e=optionalString(n.name);if(e===void 0)continue;let r=eveMetadata(n),i={address:e,title:optionalString(n.title)??titleFromAddress(e)},a=categoryOf(e);a!==void 0&&(i.category=a);let o=optionalString(n.description);o!==void 0&&(i.description=o);let s=componentMetadata(r);s!==void 0&&(i.components=s.addresses,i.componentSearchTerms=s.searchTerms);let c=optionalString(r.requires);c!==void 0&&(i.requires=c);let l=authoredTargetOf(n);l!==void 0&&(i.authoredTarget=l),r.setup!==void 0&&r.setup!==null&&(i.declaresSetup=!0);let u=declaredEnvVars(n);u.length>0&&(i.envVars=u),t.push(i)}return t}function selectIntegrations(e){return selectIntegrationPage(e).items}function selectIntegrationPage(e){let t=Math.min(Math.max(e.limit??10,1),25),n=Math.max(e.offset??0,0),r=(e.query??``).toLowerCase().split(/\s+/u).filter(e=>e.length>0),i=e.entries.map((e,t)=>{let n=`${e.address} ${e.title}`.toLowerCase();return{entry:e,haystack:[n,e.description??``,...e.componentSearchTerms??e.components??[]].join(` `).toLowerCase(),index:t,primaryTerms:n}}),a=new Map(r.map(e=>{let t=i.filter(({haystack:t})=>t.includes(e)).length;return[e,Math.log((i.length+1)/(t+1))+1]})),o=i.map(({entry:t,haystack:n,index:i,primaryTerms:o})=>{if(e.category!==void 0&&!matchesCategory(t,e.category))return;if(r.length===0)return{entry:t,index:i,score:0};let s=r.reduce((e,t)=>{let r=a.get(t)??0;return o.includes(t)?e+2*r:n.includes(t)?e+r:e},0);return s>0?{entry:t,index:i,score:s}:void 0}).filter(e=>e!==void 0).sort((e,t)=>t.score-e.score||e.index-t.index),s=(o[0]?.score??0)*.4,c=o.filter(({score:e})=>e>=s),l=c.slice(n,n+t).map(({entry:e})=>{let t={address:e.address,title:e.title};return e.category!==void 0&&(t.category=e.category),e.components!==void 0&&(t.components=e.components),e.description!==void 0&&(t.description=e.description),e.requires!==void 0&&(t.requires=e.requires),t}),u=n+l.length,d={hasMore:u<c.length,items:l,total:c.length};return u<c.length&&(d.nextOffset=u),d}function matchesCategory(e,t){return e.category===t||e.components?.some(e=>categoryOf(e)===t)===!0}function resolveRegistryIndexUrl(e=process.env.EVE_DEV_OFFICIAL_REGISTRY_URL){if(e===void 0)return`https://eve.dev/r${INDEX_PATH}`;let t;try{t=new URL(e)}catch{throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`);if(t.username!==``||t.password!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include credentials.`);if(t.search!==``||t.hash!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include a query or fragment.`);return t.pathname=`${t.pathname.replace(/\/+$/u,``)}${INDEX_PATH}`,t.toString()}let cache;function clearRegistryIndexCache(){cache=void 0}async function loadRegistryIndex(e){if(cache!==void 0&&cache.url===e.url&&e.nowMs-cache.fetchedAtMs<3e5)return cache.entries;let t=await fetch(e.url,{headers:{accept:`application/json`},signal:AbortSignal.any(e.signal===void 0?[AbortSignal.timeout(FETCH_TIMEOUT_MS)]:[e.signal,AbortSignal.timeout(FETCH_TIMEOUT_MS)])});if(!t.ok)throw Error(`Could not read the eve registry (${t.status}).`);let n=parseRegistryIndex(await t.json());return cache={entries:n,fetchedAtMs:e.nowMs,url:e.url},n}async function annotateInstalled(e){let t=new Map(e.entries.flatMap(e=>e.authoredTarget===void 0?[]:[[e.address,e.authoredTarget]]));if(e.rows.every(e=>t.get(e.address)===void 0))return e.rows;let n;try{n=await e.ctx.getSandbox()}catch{return e.rows}return await Promise.all(e.rows.map(async e=>{let r=t.get(e.address);if(r===void 0)return e;let i=`/source/${r.slice(6)}`;try{let t=await n.readTextFile({path:i});return{...e,installed:t!==null}}catch{return e}}))}var search_registry_default=defineTool({description:"Search the eve registry for integrations this project can add: channels, MCP connections, extensions, and observability. Read-only — it installs nothing. Call it before writing an integration by hand, then pass an exact item address (for example `channel/slack`) to selfmod__registry_add.",inputSchema,outputSchema,async execute(e,t){let n=[],r;try{r=resolveRegistryIndexUrl()}catch(e){return{errors:[{message:errorMessage(e),registry:`eve`}],hasMore:!1,items:[],total:0}}let i=[];try{i=await loadRegistryIndex({nowMs:Date.now(),signal:t.abortSignal,url:r})}catch(e){n.push({message:errorMessage(e),registry:r})}let a={entries:i},o=typeof e.category==`string`?e.category:void 0;o!==void 0&&isCategory(o)&&(a.category=o),typeof e.limit==`number`&&(a.limit=e.limit),typeof e.offset==`number`&&(a.offset=e.offset),typeof e.query==`string`&&(a.query=e.query);let s=selectIntegrationPage(a),c={errors:n,hasMore:s.hasMore,items:await annotateInstalled({ctx:t,entries:i,rows:s.items}),total:s.total};return s.nextOffset!==void 0&&(c.nextOffset=s.nextOffset),c}});function errorMessage(e){return e instanceof Error?e.message:String(e)}export{clearRegistryIndexCache,search_registry_default as default,loadRegistryIndex,parseRegistryIndex,resolveRegistryIndexUrl,selectIntegrationPage,selectIntegrations};
1
+ import{defineTool}from"eve/tools";const CATEGORIES=[`channel`,`connection`,`extension`,`instrumentation`],INDEX_PATH=`/registry.json`,FETCH_TIMEOUT_MS=1e4,inputSchema={type:`object`,additionalProperties:!1,properties:{query:{type:`string`,maxLength:200,description:`Free-text match against integration names, titles, and descriptions.`},category:{type:`string`,enum:[...CATEGORIES],description:`Restrict results to one registry category.`},limit:{type:`integer`,minimum:1,maximum:25,description:`Maximum number of items to return (default 10, maximum 25).`},offset:{type:`integer`,minimum:0,description:`Number of matching items to skip. Use nextOffset from a prior result to retrieve the next page.`}}},outputSchema={type:`object`,additionalProperties:!1,properties:{items:{type:`array`,items:{type:`object`,additionalProperties:!1,properties:{address:{type:`string`},title:{type:`string`},description:{type:`string`},category:{type:`string`},components:{type:`array`,items:{type:`string`}},requires:{type:`string`},installed:{type:`boolean`}},required:[`address`,`title`]}},errors:{type:`array`,items:{type:`object`,additionalProperties:!1,properties:{registry:{type:`string`},message:{type:`string`}},required:[`registry`,`message`]}},total:{type:`integer`},hasMore:{type:`boolean`},nextOffset:{type:`integer`}},required:[`items`,`errors`,`total`,`hasMore`]};function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function optionalString(e){return typeof e==`string`&&e.length>0?e:void 0}function isCategory(e){return CATEGORIES.includes(e)}function categoryOf(e){let t=e.split(`/`)[0];return t!==void 0&&e.includes(`/`)&&isCategory(t)?t:void 0}function titleFromAddress(e){return(e.split(`/`).at(-1)??e).split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function eveMetadata(e){let t=e.meta;if(!isRecord(t))return{};let n=t.eve;return isRecord(n)?n:{}}function componentMetadata(e){let t=e.components;if(!Array.isArray(t))return;let n=[],r=[];for(let e of t){if(!isRecord(e))continue;let t=optionalString(e.item);if(t===void 0)continue;n.push(t),r.push(t);let i=optionalString(e.label);i!==void 0&&r.push(i);let a=optionalString(e.description);a!==void 0&&r.push(a)}return n.length>0?{addresses:n,searchTerms:r}:void 0}function authoredTargetOf(e){let t=e.files;if(Array.isArray(t))for(let e of t){if(!isRecord(e))continue;let t=optionalString(e.target);if(t?.startsWith(`agent/`)===!0)return t}}function declaredEnvVars(e){let t=e.envVars;return isRecord(t)?Object.keys(t):[]}function parseRegistryIndex(e){if(!isRecord(e)||!Array.isArray(e.items))return[];let t=[];for(let n of e.items){if(!isRecord(n))continue;let e=optionalString(n.name);if(e===void 0)continue;let r=eveMetadata(n);if(r.hidden===!0)continue;let i={address:e,title:optionalString(n.title)??titleFromAddress(e)},a=categoryOf(e);a!==void 0&&(i.category=a);let o=optionalString(n.description);o!==void 0&&(i.description=o);let s=componentMetadata(r);s!==void 0&&(i.components=s.addresses,i.componentSearchTerms=s.searchTerms);let c=optionalString(r.requires);c!==void 0&&(i.requires=c);let l=authoredTargetOf(n);l!==void 0&&(i.authoredTarget=l),r.setup!==void 0&&r.setup!==null&&(i.declaresSetup=!0);let u=declaredEnvVars(n);u.length>0&&(i.envVars=u),t.push(i)}return t}function selectIntegrations(e){return selectIntegrationPage(e).items}function selectIntegrationPage(e){let t=Math.min(Math.max(e.limit??10,1),25),n=Math.max(e.offset??0,0),r=(e.query??``).toLowerCase().split(/\s+/u).filter(e=>e.length>0),i=e.entries.map((e,t)=>{let n=`${e.address} ${e.title}`.toLowerCase();return{entry:e,haystack:[n,e.description??``,...e.componentSearchTerms??e.components??[]].join(` `).toLowerCase(),index:t,primaryTerms:n}}),a=new Map(r.map(e=>{let t=i.filter(({haystack:t})=>t.includes(e)).length;return[e,Math.log((i.length+1)/(t+1))+1]})),o=i.map(({entry:t,haystack:n,index:i,primaryTerms:o})=>{if(e.category!==void 0&&!matchesCategory(t,e.category))return;if(r.length===0)return{entry:t,index:i,score:0};let s=r.reduce((e,t)=>{let r=a.get(t)??0;return o.includes(t)?e+2*r:n.includes(t)?e+r:e},0);return s>0?{entry:t,index:i,score:s}:void 0}).filter(e=>e!==void 0).sort((e,t)=>t.score-e.score||e.index-t.index),s=(o[0]?.score??0)*.4,c=o.filter(({score:e})=>e>=s),l=c.slice(n,n+t).map(({entry:e})=>{let t={address:e.address,title:e.title};return e.category!==void 0&&(t.category=e.category),e.components!==void 0&&(t.components=e.components),e.description!==void 0&&(t.description=e.description),e.requires!==void 0&&(t.requires=e.requires),t}),u=n+l.length,d={hasMore:u<c.length,items:l,total:c.length};return u<c.length&&(d.nextOffset=u),d}function matchesCategory(e,t){return e.category===t||e.components?.some(e=>categoryOf(e)===t)===!0}function officialRegistryIndexUrl(){return`https://eve.dev/r${INDEX_PATH}`}function resolveRegistryIndexUrl(e=process.env.EVE_DEV_OFFICIAL_REGISTRY_URL){if(e===void 0)return officialRegistryIndexUrl();let t;try{t=new URL(e)}catch{throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`);if(t.username!==``||t.password!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include credentials.`);if(t.search!==``||t.hash!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include a query or fragment.`);return t.pathname=`${t.pathname.replace(/\/+$/u,``)}${INDEX_PATH}`,t.toString()}let cache;function clearRegistryIndexCache(){cache=void 0}async function loadRegistryIndex(e){if(cache!==void 0&&cache.url===e.url&&e.nowMs-cache.fetchedAtMs<3e5)return cache.entries;let t=await fetch(e.url,{headers:{accept:`application/json`},signal:AbortSignal.any(e.signal===void 0?[AbortSignal.timeout(FETCH_TIMEOUT_MS)]:[e.signal,AbortSignal.timeout(FETCH_TIMEOUT_MS)])});if(!t.ok)throw Error(`Could not read the eve registry (${t.status}).`);let n=parseRegistryIndex(await t.json());return cache={entries:n,fetchedAtMs:e.nowMs,url:e.url},n}async function annotateInstalled(e){let t=new Map(e.entries.flatMap(e=>e.authoredTarget===void 0?[]:[[e.address,e.authoredTarget]]));if(e.rows.every(e=>t.get(e.address)===void 0))return e.rows;let n;try{n=await e.ctx.getSandbox()}catch{return e.rows}return await Promise.all(e.rows.map(async e=>{let r=t.get(e.address);if(r===void 0)return e;let i=`/source/${r.slice(6)}`;try{let t=await n.readTextFile({path:i});return{...e,installed:t!==null}}catch{return e}}))}var search_registry_default=defineTool({description:"Search the eve registry for integrations this project can add: channels, MCP connections, extensions, and observability. Read-only — it installs nothing. Call it before writing an integration by hand, then pass an exact item address (for example `channel/slack`) to selfmod__registry_add.",inputSchema,outputSchema,async execute(e,t){let n=[],r;try{r=resolveRegistryIndexUrl()}catch(e){return{errors:[{message:errorMessage(e),registry:`eve`}],hasMore:!1,items:[],total:0}}let i=[];try{i=await loadRegistryIndex({nowMs:Date.now(),signal:t.abortSignal,url:r})}catch(e){n.push({message:errorMessage(e),registry:r})}let a={entries:i},o=typeof e.category==`string`?e.category:void 0;o!==void 0&&isCategory(o)&&(a.category=o),typeof e.limit==`number`&&(a.limit=e.limit),typeof e.offset==`number`&&(a.offset=e.offset),typeof e.query==`string`&&(a.query=e.query);let s=selectIntegrationPage(a),c={errors:n,hasMore:s.hasMore,items:await annotateInstalled({ctx:t,entries:i,rows:s.items}),total:s.total};return s.nextOffset!==void 0&&(c.nextOffset=s.nextOffset),c}});function errorMessage(e){return e instanceof Error?e.message:String(e)}export{clearRegistryIndexCache,search_registry_default as default,loadRegistryIndex,officialRegistryIndexUrl,parseRegistryIndex,resolveRegistryIndexUrl,selectIntegrationPage,selectIntegrations};
@@ -1 +1 @@
1
- import{mkdir}from"node:fs/promises";import{resolve}from"node:path";async function createSelfModificationFilesystem(e){let{MountableFs:t,OverlayFs:n,ReadWriteFs:r}=e.justBash,i=resolve(e.appRoot,`.eve/traces/v1`);return await Promise.all([e.defaultFilesystem.mkdir(`/source`,{recursive:!0}),mkdir(i,{recursive:!0})]),new t({base:e.defaultFilesystem,mounts:[{filesystem:new r({allowSymlinks:!1,maxFileReadSize:2**53-1,root:resolve(e.appRoot,`agent`)}),mountPoint:`/source`},{filesystem:new n({mountPoint:`/`,readOnly:!0,root:i}),mountPoint:`/traces`},{filesystem:new n({mountPoint:`/`,readOnly:!0,root:resolve(e.appRoot,`node_modules/eve/docs`)}),mountPoint:`/eve-docs`}]})}export{createSelfModificationFilesystem};
1
+ import{mkdir}from"node:fs/promises";import{resolve}from"node:path";async function createSelfModificationFilesystem(e){let{MountableFs:t,OverlayFs:n,ReadWriteFs:r}=e.justBash,i=resolve(e.appRoot,`.eve/traces/v1`),a=resolve(e.appRoot,`.eve/logs`);return await Promise.all([e.defaultFilesystem.mkdir(`/source`,{recursive:!0}),mkdir(i,{recursive:!0}),mkdir(a,{recursive:!0})]),new t({base:e.defaultFilesystem,mounts:[{filesystem:new r({allowSymlinks:!1,maxFileReadSize:2**53-1,root:resolve(e.appRoot,`agent`)}),mountPoint:`/source`},{filesystem:new n({mountPoint:`/`,readOnly:!0,root:i}),mountPoint:`/traces`},{filesystem:new n({mountPoint:`/`,readOnly:!0,root:a}),mountPoint:`/logs`},{filesystem:new n({mountPoint:`/`,readOnly:!0,root:resolve(e.appRoot,`node_modules/eve/docs`)}),mountPoint:`/eve-docs`}]})}export{createSelfModificationFilesystem};
@@ -0,0 +1,31 @@
1
+ import type { SandboxSession } from "eve/sandbox";
2
+ import type { GitHubRepository } from "./config.js";
3
+ export declare const SELF_MODIFICATION_CONFIG_PATH = "agent/subagents/self-modification/config.ts";
4
+ export declare const WORKSPACE_PATH = "/workspace";
5
+ export declare const REPOSITORY_PATH = "/workspace/repository";
6
+ export declare const BASE_REF = "refs/eve-self-modification/base";
7
+ export interface PreparedSelfModificationWorkspace {
8
+ readonly baseSha: string;
9
+ readonly directory: string;
10
+ readonly repository: GitHubRepository;
11
+ readonly repositoryPath: string;
12
+ readonly targetBranch: string;
13
+ }
14
+ type CheckoutSandbox = Pick<SandboxSession, "run" | "setNetworkPolicy">;
15
+ /** Prepares a token-free remote and immutable target-branch checkout for one child session. */
16
+ export declare function prepareSelfModificationWorkspace(input: {
17
+ readonly directory: string;
18
+ readonly repository: GitHubRepository;
19
+ readonly sandbox: CheckoutSandbox;
20
+ readonly targetBranch: string;
21
+ readonly token: string;
22
+ }): Promise<PreparedSelfModificationWorkspace>;
23
+ /** Reconstructs trusted workspace metadata after the session checkout preflight. */
24
+ export declare function readPreparedSelfModificationWorkspace(input: {
25
+ readonly directory: string;
26
+ readonly repository: GitHubRepository;
27
+ readonly sandbox: Pick<SandboxSession, "run">;
28
+ readonly targetBranch: string;
29
+ }): Promise<PreparedSelfModificationWorkspace>;
30
+ export declare function verifyApplicationRoot(sandbox: Pick<SandboxSession, "run">, directory: string): Promise<void>;
31
+ export {};
@@ -0,0 +1 @@
1
+ import{assertFullSha,assertGitRef}from"./identifiers.js";import{gitOutput,runGitCommand,withBrokeredGitHubCredential}from"./git.js";import{shellQuote}from"#shared/shell-quote.js";import{gitHubRemoteUrl}from"#shared/git.js";const SELF_MODIFICATION_CONFIG_PATH=`agent/subagents/self-modification/config.ts`,WORKSPACE_PATH=`/workspace`,REPOSITORY_PATH=`${WORKSPACE_PATH}/repository`,BASE_REF=`refs/eve-self-modification/base`;async function prepareSelfModificationWorkspace(e){assertGitRef(e.targetBranch,`target branch`);let t=gitHubRemoteUrl(e.repository);await withBrokeredGitHubCredential(e.sandbox,e.token,async()=>{await run(e.sandbox,`rm -rf ${quote(REPOSITORY_PATH)} && mkdir -p ${quote(REPOSITORY_PATH)}`),await run(e.sandbox,`git -C ${quote(REPOSITORY_PATH)} init`),await run(e.sandbox,`git -C ${quote(REPOSITORY_PATH)} remote add origin ${quote(t)}`),await run(e.sandbox,`GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null GIT_LFS_SKIP_SMUDGE=1 GIT_TERMINAL_PROMPT=0 git -C ${quote(REPOSITORY_PATH)} fetch --no-tags origin ${quote(`refs/heads/${e.targetBranch}`)}`),await run(e.sandbox,`git -C ${quote(REPOSITORY_PATH)} update-ref ${BASE_REF} FETCH_HEAD`),await run(e.sandbox,`git -C ${quote(REPOSITORY_PATH)} checkout --detach ${BASE_REF}`)});let n=await gitOutput(e.sandbox,`git -C ${quote(REPOSITORY_PATH)} rev-parse ${BASE_REF}`);return assertFullSha(n,`target branch revision`),await verifyApplicationRoot(e.sandbox,e.directory),{baseSha:n,directory:e.directory,repository:e.repository,repositoryPath:REPOSITORY_PATH,targetBranch:e.targetBranch}}async function readPreparedSelfModificationWorkspace(e){let t=await gitOutput(e.sandbox,`git -C ${quote(REPOSITORY_PATH)} rev-parse ${BASE_REF}`);return assertFullSha(t,`target branch revision`),await verifyApplicationRoot(e.sandbox,e.directory),{baseSha:t,directory:e.directory,repository:e.repository,repositoryPath:REPOSITORY_PATH,targetBranch:e.targetBranch}}async function verifyApplicationRoot(e,t){let n=t===`.`?REPOSITORY_PATH:`${REPOSITORY_PATH}/${t}`;if((await e.run({command:`test -d ${quote(`${n}/agent`)}`})).exitCode!==0)throw Error(`Self-modification source directory does not contain agent/: ${t}`)}function quote(e){return shellQuote(e)}async function run(e,t){await runGitCommand(e,t)}export{BASE_REF,REPOSITORY_PATH,SELF_MODIFICATION_CONFIG_PATH,WORKSPACE_PATH,prepareSelfModificationWorkspace,readPreparedSelfModificationWorkspace,verifyApplicationRoot};
@@ -0,0 +1,6 @@
1
+ import type { SandboxSession } from "eve/sandbox";
2
+ type CommandSandbox = Pick<SandboxSession, "run">;
3
+ export declare function withBrokeredGitHubCredential<T>(sandbox: Pick<SandboxSession, "setNetworkPolicy">, token: string, operation: () => Promise<T>): Promise<T>;
4
+ export declare function gitOutput(sandbox: CommandSandbox, command: string, trim?: boolean): Promise<string>;
5
+ export declare function runGitCommand(sandbox: CommandSandbox, command: string): Promise<void>;
6
+ export {};
@@ -0,0 +1 @@
1
+ import{SELF_MODIFICATION_BASELINE_NETWORK_POLICY}from"./network-policy.js";import{gitHubGitBrokerNetworkPolicy}from"#shared/git.js";const MAX_ERROR_OUTPUT=2e3;async function withBrokeredGitHubCredential(e,t,n){let r;try{await e.setNetworkPolicy(gitHubGitBrokerNetworkPolicy(t)),r={ok:!0,value:await n()}}catch(e){r={error:e,ok:!1}}try{await e.setNetworkPolicy(SELF_MODIFICATION_BASELINE_NETWORK_POLICY)}catch(e){throw Error(`Could not revoke the brokered GitHub credential from the sandbox.`,{cause:r.ok?e:AggregateError([r.error,e])})}if(!r.ok)throw r.error;return r.value}async function gitOutput(e,t,n=!0){let r=await e.run({command:t});if(r.exitCode!==0)throw gitCommandError(t,r);let i=String(r.stdout??``);return n?i.trim():i}async function runGitCommand(e,t){let n=await e.run({command:t});if(n.exitCode!==0)throw gitCommandError(t,n)}function gitCommandError(e,t){let n=truncate(String(t.stderr??``).trim()),r=truncate(String(t.stdout??``).trim());return Error([`Git command failed with exit ${t.exitCode}: ${e}`,n&&`stderr: ${n}`,r&&`stdout: ${r}`].filter(Boolean).join(`; `))}function truncate(e){return e.length<=MAX_ERROR_OUTPUT?e:`${e.slice(0,MAX_ERROR_OUTPUT)}…`}export{gitOutput,runGitCommand,withBrokeredGitHubCredential};
@@ -0,0 +1,27 @@
1
+ import type { GitHubCredentialProvider } from "./credentials.js";
2
+ import type { PreparedSelfModificationWorkspace } from "./git-workspace.js";
3
+ import { captureSelfModificationProposal } from "./proposal.js";
4
+ export interface PublishedSelfModificationProposal {
5
+ readonly changedPaths: readonly string[];
6
+ readonly commitSha: string;
7
+ readonly pullRequestUrl: string;
8
+ readonly repository: string;
9
+ readonly targetBranch: string;
10
+ readonly branch: string;
11
+ readonly draft: true;
12
+ readonly merged: false;
13
+ readonly deployed: false;
14
+ }
15
+ export interface GitHubDraftPublisherInput {
16
+ readonly credentialProvider: GitHubCredentialProvider;
17
+ readonly description: string;
18
+ readonly fetch?: typeof fetch;
19
+ /** Derived by the trusted parent/session lineage, never from model tool input. */
20
+ readonly operationId: string;
21
+ readonly sandbox: Parameters<typeof captureSelfModificationProposal>[0]["sandbox"];
22
+ readonly title: string;
23
+ readonly workspace: PreparedSelfModificationWorkspace;
24
+ }
25
+ /** Captures agent-only edits, then publishes one replay-safe draft pull request. */
26
+ export declare function publishGitHubDraftPullRequest(input: GitHubDraftPublisherInput): Promise<PublishedSelfModificationProposal>;
27
+ export declare function selfModificationBranchName(baseSha: string, operationId: string): string;
@@ -0,0 +1,2 @@
1
+ import{assertFullSha,assertGitRef,assertOperationId}from"./identifiers.js";import{captureSelfModificationProposal,readProposalBlob}from"./proposal.js";import{createHash}from"node:crypto";async function publishGitHubDraftPullRequest(e){assertOperationId(e.operationId),validateText(e.title,`title`,256,!1),validateText(e.description,`description`,65536,!0);let t=await captureSelfModificationProposal({sandbox:e.sandbox,workspace:e.workspace}),n=selfModificationBranchName(e.workspace.baseSha,e.operationId),r=await e.credentialProvider.resolve({capability:`publish`,repository:repository(e.workspace)});if(r.trim().length===0)throw Error(`Self-modification publication credential is empty.`);let i=new GitHubClient(e.fetch??fetch,r.trim());await assertTargetAtBase(i,repository(e.workspace),e.workspace.targetBranch,t.baseSha);let a=await i.ref(repository(e.workspace),n);if(a!==null)return await reconcile(i,e,t,n,a);let o=await upload(i,e,t);try{await i.createRef(repository(e.workspace),n,o)}catch(r){let a=await i.ref(repository(e.workspace),n);if(a===null)throw r;return await reconcile(i,e,t,n,a)}await assertTargetAtBase(i,repository(e.workspace),e.workspace.targetBranch,t.baseSha);let s=await i.createPullRequest(repository(e.workspace),n,e.workspace.targetBranch,e.title.trim(),body(e.description,t));return receipt(e.workspace,t,n,o,s)}function selfModificationBranchName(e,t){return assertFullSha(e,`proposal base revision`),assertOperationId(t),`eve-self-modification/${e.slice(0,12)}/${createHash(`sha256`).update(t).digest(`hex`).slice(0,24)}`}async function reconcile(e,t,n,r,i){let a=await e.commit(repository(t.workspace),i);if(a.parent!==n.baseSha)throw Error(`Self-modification operation conflict: existing branch has a different base.`);if(a.tree!==n.proposedTreeSha)throw Error(`Self-modification operation conflict: existing branch has different edits.`);let o=await e.pullRequest(repository(t.workspace),r,t.workspace.targetBranch);if(o===null)return await assertTargetAtBase(e,repository(t.workspace),t.workspace.targetBranch,n.baseSha),receipt(t.workspace,n,r,i,await e.createPullRequest(repository(t.workspace),r,t.workspace.targetBranch,t.title.trim(),body(t.description,n)));if(!o.draft)throw Error(`Self-modification operation conflict: its pull request is no longer a draft.`);return receipt(t.workspace,n,r,i,o)}async function upload(e,t,n){let r=await Promise.all(n.changes.map(async n=>n.objectId===null?{mode:`100644`,path:n.path,sha:null,type:`blob`}:{mode:n.mode,path:n.path,sha:await e.blob(repository(t.workspace),await readProposalBlob({change:n,sandbox:t.sandbox,workspace:t.workspace})),type:`blob`})),i=await e.tree(repository(t.workspace),n.baseTreeSha,r);if(i!==n.proposedTreeSha)throw Error(`GitHub did not reassemble the validated proposal tree.`);return await e.commitCreate(repository(t.workspace),n.baseSha,i,`eve self-modification proposal\n\nOperation: ${createHash(`sha256`).update(t.operationId).digest(`hex`).slice(0,24)}`)}async function assertTargetAtBase(e,t,n,r){assertGitRef(n);let i=await e.ref(t,n);if(i===null)throw Error(`Self-modification target branch ${JSON.stringify(n)} does not exist.`);if(i!==r.toLowerCase())throw Error(`Self-modification target branch changed while the proposal was being prepared.`)}function repository(e){return e.repository}function receipt(e,t,n,r,i){if(!i.draft)throw Error(`GitHub did not create a draft self-modification pull request.`);let a=repository(e);return{branch:n,changedPaths:t.changes.map(e=>e.path),commitSha:r,deployed:!1,draft:!0,merged:!1,pullRequestUrl:i.url,repository:`github.com/${a.owner}/${a.repo}`,targetBranch:e.targetBranch}}function body(e,t){return`${e}\n\n---\n\nThis is a draft proposal. Merge and deployment have not occurred.\n\n## Changed files\n${t.changes.map(e=>`- \`${e.path}\``).join(`
2
+ `)}`}function validateText(e,t,n,r){if(e.trim().length===0||e.length>n||!r&&/[\x00-\x1f\x7f]/u.test(e))throw Error(`Self-modification pull request ${t} is invalid.`)}var GitHubClient=class{requestFetch;token;constructor(e,t){this.requestFetch=e,this.token=t}async ref(e,t){let n=await this.request(e,`GET`,`/git/ref/heads/${t.split(`/`).map(encodeURIComponent).join(`/`)}`,void 0,!0);if(n===null||Array.isArray(n)||!record(n).object)return null;let r=record(record(n).object).sha;if(typeof r!=`string`)throw Error(`GitHub returned an invalid ref.`);return assertFullSha(r,`GitHub ref`),r.toLowerCase()}async commit(e,t){let n=record(await this.request(e,`GET`,`/git/commits/${t}`)),r=n.parents,i=record(n.tree).sha;if(!Array.isArray(r)||r.length!==1||typeof i!=`string`)throw Error(`GitHub returned an invalid commit.`);let a=record(r[0]).sha;if(typeof a!=`string`)throw Error(`GitHub returned an invalid commit.`);return assertFullSha(a,`GitHub parent`),assertFullSha(i,`GitHub tree`),{parent:a.toLowerCase(),tree:i.toLowerCase()}}async blob(e,t){return this.sha(await this.request(e,`POST`,`/git/blobs`,{content:t,encoding:`base64`}))}async tree(e,t,n){return this.sha(await this.request(e,`POST`,`/git/trees`,{base_tree:t,tree:n}))}async commitCreate(e,t,n,r){return this.sha(await this.request(e,`POST`,`/git/commits`,{message:r,parents:[t],tree:n}))}async createRef(e,t,n){await this.request(e,`POST`,`/git/refs`,{ref:`refs/heads/${t}`,sha:n})}async pullRequest(e,t,n){let r=new URLSearchParams({head:`${e.owner}:${t}`,state:`all`}),i=await this.request(e,`GET`,`/pulls?${r}`);if(!Array.isArray(i))throw Error(`GitHub returned an invalid pull request list.`);return i[0]===void 0?null:pullRequest(i[0],e,t,n)}async createPullRequest(e,t,n,r,i){return pullRequest(await this.request(e,`POST`,`/pulls`,{base:n,body:i,draft:!0,head:t,title:r}),e,t,n)}async sha(e){let t=record(e).sha;if(typeof t!=`string`)throw Error(`GitHub returned an invalid Git object.`);return assertFullSha(t,`GitHub object`),t.toLowerCase()}async request(e,t,n,r,i=!1){let a={accept:`application/vnd.github+json`,authorization:`Bearer ${this.token}`,"user-agent":`eve-self-modification`,"x-github-api-version":`2022-11-28`};r!==void 0&&(a[`content-type`]=`application/json`);let o=await this.requestFetch(`https://api.github.com/repos/${encodeURIComponent(e.owner)}/${encodeURIComponent(e.repo)}${n}`,{body:r===void 0?void 0:JSON.stringify(r),headers:a,method:t,signal:AbortSignal.timeout(3e4)});if(i&&o.status===404)return null;if(!o.ok)throw Error(`GitHub ${t} ${n} failed with HTTP ${o.status}.`);return await o.json()}};function record(e){if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`GitHub returned an invalid response.`);return e}function pullRequest(e,t,n,r){let i=record(e),a=i.draft,o=i.state,s=i.html_url;if(typeof a!=`boolean`||o!==`open`||typeof s!=`string`||record(i.head).ref!==n||record(i.base).ref!==r||!s.startsWith(`https://github.com/${t.owner}/${t.repo}/pull/`))throw Error(`GitHub returned an invalid pull request.`);return{draft:a,url:s}}export{publishGitHubDraftPullRequest,selfModificationBranchName};
@@ -0,0 +1,4 @@
1
+ export declare function assertFullSha(value: string, label: string): void;
2
+ export declare function assertRepositoryPart(value: string, label: string): void;
3
+ export declare function assertGitRef(value: string, label?: string): void;
4
+ export declare function assertOperationId(operationId: string): void;
@@ -0,0 +1 @@
1
+ import{isFullGitSha,isValidGitRef}from"#shared/git.js";function assertFullSha(e,t){if(!isFullGitSha(e))throw Error(`Self-modification ${t} must be a full Git SHA.`)}function assertRepositoryPart(e,t){if(!/^[A-Za-z0-9_.-]+$/u.test(e)||e===`.`||e===`..`||e.startsWith(`-`))throw Error(`Self-modification ${t} is invalid.`)}function assertGitRef(e,t=`target branch`){if(!isValidGitRef(e))throw Error(`Self-modification ${t} is not a valid Git ref.`)}function assertOperationId(e){if(e.length===0||e.length>512)throw Error(`Self-modification operation id must contain 1–512 characters.`)}export{assertFullSha,assertGitRef,assertOperationId,assertRepositoryPart};
@@ -0,0 +1,4 @@
1
+ import type { ResolvedSelfModificationConfig } from "./config.js";
2
+ export type SelfModificationMode = "local" | "disabled" | "deployed";
3
+ /** Resolves the mutually exclusive local or deployed editing mode. */
4
+ export declare function resolveSelfModificationMode(config: ResolvedSelfModificationConfig): SelfModificationMode;
@@ -0,0 +1 @@
1
+ function resolveSelfModificationMode(e){return process.env.EVE_DEV===`1`?e.localEnabled?`local`:`disabled`:e.deployed===void 0||e.deployed.credentials.kind===`vercel-connect`&&process.env.VERCEL_ENV!==`production`?`disabled`:`deployed`}export{resolveSelfModificationMode};
@@ -0,0 +1 @@
1
+ export declare const SELF_MODIFICATION_BASELINE_NETWORK_POLICY: "allow-all";
@@ -0,0 +1 @@
1
+ const SELF_MODIFICATION_BASELINE_NETWORK_POLICY=`allow-all`;export{SELF_MODIFICATION_BASELINE_NETWORK_POLICY};
@@ -0,0 +1,39 @@
1
+ import type { SandboxSession } from "eve/sandbox";
2
+ import type { PreparedSelfModificationWorkspace } from "./git-workspace.js";
3
+ export declare const MAX_PROPOSAL_CHANGED_BYTES = 1000000;
4
+ export declare const MAX_PROPOSAL_CHANGED_FILES = 100;
5
+ export interface ProposalChange {
6
+ readonly bytes: number;
7
+ readonly kind: "add" | "delete" | "modify";
8
+ readonly mode: "100644" | "100755" | null;
9
+ readonly objectId: string | null;
10
+ readonly path: string;
11
+ }
12
+ export interface SelfModificationProposal {
13
+ readonly baseSha: string;
14
+ readonly baseTreeSha: string;
15
+ readonly changedBytes: number;
16
+ readonly changes: readonly ProposalChange[];
17
+ readonly proposedTreeSha: string;
18
+ }
19
+ type ProposalSandbox = Pick<SandboxSession, "run">;
20
+ /** Captures and validates the worktree before any publication credential is resolved. */
21
+ export declare function captureSelfModificationProposal(input: {
22
+ readonly sandbox: ProposalSandbox;
23
+ readonly workspace: PreparedSelfModificationWorkspace;
24
+ }): Promise<SelfModificationProposal>;
25
+ /** Reads an already captured blob and verifies its Git object id before upload. */
26
+ export declare function readProposalBlob(input: {
27
+ readonly change: ProposalChange;
28
+ readonly sandbox: ProposalSandbox;
29
+ readonly workspace: PreparedSelfModificationWorkspace;
30
+ }): Promise<string>;
31
+ interface RawChange {
32
+ readonly newMode: string;
33
+ readonly newObjectId: string;
34
+ readonly path: string;
35
+ readonly status: "A" | "D" | "M";
36
+ }
37
+ export declare function parseRawDiff(raw: string): readonly RawChange[];
38
+ export declare function assertAllowedChange(change: Pick<ProposalChange, "mode" | "objectId" | "path">, directory: string): void;
39
+ export {};
@@ -0,0 +1,2 @@
1
+ import{assertFullSha}from"./identifiers.js";import{gitOutput,runGitCommand}from"./git.js";import{createHash}from"node:crypto";import{shellQuote}from"#shared/shell-quote.js";const MAX_PROPOSAL_CHANGED_BYTES=1e6,MAX_PROPOSAL_CHANGED_FILES=100;async function captureSelfModificationProposal(e){let t=quote(e.workspace.repositoryPath);assertFullSha(e.workspace.baseSha,`proposal base revision`),await runGitCommand(e.sandbox,`git -C ${t} add -A -- .`);let n=await gitOutput(e.sandbox,`git -C ${t} write-tree`),r=await gitOutput(e.sandbox,`git -C ${t} rev-parse ${quote(`${e.workspace.baseSha}^{tree}`)}`);assertFullSha(n,`proposal tree`),assertFullSha(r,`proposal base tree`);let i=parseRawDiff(await gitOutput(e.sandbox,`git -C ${t} diff-tree -r --no-commit-id --raw -z --no-renames ${quote(e.workspace.baseSha)} ${quote(n)}`,!1));if(i.length===0)throw Error(`Self-modification proposal contains no changes.`);if(i.length>100)throw Error(`Self-modification proposal changes ${i.length} files; limit is 100.`);let a=[],o=0;for(let t of i){let n=t.status===`D`?null:proposalMode(t.newMode,t.path),r=t.status===`D`?null:t.newObjectId;assertAllowedChange({mode:n,objectId:r,path:t.path},e.workspace.directory);let i=r===null?0:await blobSize(e.sandbox,e.workspace.repositoryPath,r);if(o+=i,o>1e6)throw Error(`Self-modification proposal changes more than ${MAX_PROPOSAL_CHANGED_BYTES} bytes.`);a.push({bytes:i,kind:t.status===`A`?`add`:t.status===`D`?`delete`:`modify`,mode:n,objectId:r,path:t.path})}return{baseSha:e.workspace.baseSha,baseTreeSha:r,changedBytes:o,changes:a,proposedTreeSha:n}}async function readProposalBlob(e){if(e.change.objectId===null)throw Error(`Cannot read a deleted proposal blob.`);let t=await gitOutput(e.sandbox,`git -C ${quote(e.workspace.repositoryPath)} cat-file blob ${quote(e.change.objectId)} | base64 | tr -d '\\n'`),n=Buffer.from(t,`base64`),r=createHash(`sha1`).update(`blob ${n.byteLength}\0`).update(n).digest(`hex`);if(n.byteLength!==e.change.bytes||r!==e.change.objectId.toLowerCase())throw Error(`Self-modification proposal blob changed after validation: ${JSON.stringify(e.change.path)}.`);return t}function parseRawDiff(e){if(e.length===0)return[];let t=e.split(`\0`);if(t.at(-1)===``&&t.pop(),t.length%2!=0)throw Error(`Git returned malformed raw diff output.`);let n=[];for(let e=0;e<t.length;e+=2){let r=t[e],i=t[e+1],a=r===void 0?null:/^:[0-7]{6} ([0-7]{6}) [a-f0-9]{40} ([a-f0-9]{40}) ([ADM])$/u.exec(r);if(a===null||i===void 0||!isSafePath(i))throw Error(`Git returned malformed raw diff output.`);n.push({newMode:a[1],newObjectId:a[2],path:i,status:a[3]})}return n}function assertAllowedChange(e,t){let n=e.path,r=t===`.`?``:`${t}/`,i=`${r}agent/`,a=n.split(`/`),o=a.at(-1)??``;if(!isSafePath(n)||a.includes(`.git`)||o===`.env`||o===`.envrc`||o.startsWith(`.env.`)||a.some(e=>[`node_modules`,`dist`,`build`,`.next`,`.output`,`.turbo`,`.vercel`,`coverage`,`out`].includes(e))||n.startsWith(`.github/workflows/`)||n.startsWith(`${i}subagents/self-modification/`)||n===`${r}agent/extensions/selfmod.ts`||n===`${r}agent/self-modification.config.ts`)throw Error(`Self-modification proposal changes a protected path: ${JSON.stringify(n)}.`)}function isSafePath(e){return e.length>0&&!e.startsWith(`/`)&&!e.includes(`\\`)&&!e.includes(`
2
+ `)&&!e.includes(`\r`)&&!e.split(`/`).some(e=>e===``||e===`.`||e===`..`)}function proposalMode(e,t){if(e===`100644`||e===`100755`)return e;throw Error(`Self-modification proposal uses unsafe Git mode ${e}: ${JSON.stringify(t)}.`)}async function blobSize(e,t,n){assertFullSha(n,`proposal blob`);let r=await gitOutput(e,`git -C ${quote(t)} cat-file -s ${quote(n)}`);if(!/^\d+$/u.test(r)||!Number.isSafeInteger(Number(r)))throw Error(`Git returned an invalid blob size.`);return Number(r)}function quote(e){return shellQuote(e)}export{MAX_PROPOSAL_CHANGED_BYTES,MAX_PROPOSAL_CHANGED_FILES,assertAllowedChange,captureSelfModificationProposal,parseRawDiff,readProposalBlob};