experimental-ash 0.55.3 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/LICENSE +202 -0
- package/dist/docs/internals/compiler-and-artifacts.md +1 -1
- package/dist/docs/internals/context.md +3 -3
- package/dist/docs/public/advanced/typescript-api.md +19 -0
- package/dist/docs/public/advanced/vercel-deployment.md +2 -1
- package/dist/docs/public/channels/github.md +145 -0
- package/dist/docs/public/channels/index.md +23 -2
- package/dist/docs/public/meta.json +1 -0
- package/dist/docs/public/onboarding.md +7 -5
- package/dist/docs/public/sandbox.md +18 -3
- package/dist/docs/public/subagents.mdx +7 -2
- package/dist/docs/public/tools.mdx +10 -2
- package/dist/skills/agent/SKILL.md +169 -0
- package/dist/skills/agent/references/deployment.md +35 -0
- package/dist/skills/agent/references/getting-started.md +58 -0
- package/dist/skills/agent/references/project-layout.md +35 -0
- package/dist/skills/agent/references/runtime-model.md +24 -0
- package/dist/skills/agent/references/skills.md +26 -0
- package/dist/skills/agent/scripts/add-to-existing-project.sh +12 -0
- package/dist/skills/agent/scripts/bootstrap-from-npm.sh +9 -0
- package/dist/skills/agent/scripts/verify-local-agent.sh +16 -0
- package/dist/skills/ash-add-agent/SKILL.md +166 -0
- package/dist/skills/ash-add-next/SKILL.md +137 -0
- package/dist/skills/framework/SKILL.md +93 -0
- package/dist/skills/framework/references/architecture.md +14 -0
- package/dist/skills/framework/references/discovery-and-compilation.md +15 -0
- package/dist/skills/framework/references/quality-gates.md +13 -0
- package/dist/skills/framework/references/runtime-model.md +12 -0
- package/dist/skills/framework/references/workspace-and-sandbox.md +25 -0
- package/dist/skills/framework/scripts/framework-review-checklist.sh +13 -0
- package/dist/skills/framework/scripts/run-framework-gates.sh +8 -0
- package/dist/src/client/output-schema.js +1 -1
- package/dist/src/compiler/compile-from-memory.d.ts +2 -0
- package/dist/src/compiler/compile-from-memory.js +1 -1
- package/dist/src/compiler/manifest.d.ts +10 -2
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/compiler/normalize-sandbox.js +1 -1
- package/dist/src/compiler/normalize-subagent.js +1 -1
- package/dist/src/compiler/normalize-tool.js +1 -1
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +1 -0
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/remote-agent-dispatch.js +1 -1
- package/dist/src/execution/session.js +1 -1
- package/dist/src/execution/subagent-tool.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/harness/code-mode.js +1 -1
- package/dist/src/harness/execute-tool.d.ts +1 -0
- package/dist/src/harness/provider-tools.d.ts +7 -1
- package/dist/src/harness/provider-tools.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tools.d.ts +2 -0
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/sandbox.d.ts +2 -1
- package/dist/src/internal/authored-definition/sandbox.js +1 -1
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/packages/ash-scaffold/src/channels.js +2 -2
- package/dist/src/packages/ash-scaffold/src/steps/run-add-to-agent.js +1 -1
- package/dist/src/packages/ash-scaffold/src/web-template.js +2 -2
- package/dist/src/public/channels/github/api.d.ts +166 -0
- package/dist/src/public/channels/github/api.js +1 -0
- package/dist/src/public/channels/github/auth.d.ts +83 -0
- package/dist/src/public/channels/github/auth.js +2 -0
- package/dist/src/public/channels/github/binding.d.ts +49 -0
- package/dist/src/public/channels/github/binding.js +1 -0
- package/dist/src/public/channels/github/checkout.d.ts +48 -0
- package/dist/src/public/channels/github/checkout.js +1 -0
- package/dist/src/public/channels/github/constants.d.ts +2 -0
- package/dist/src/public/channels/github/constants.js +1 -0
- package/dist/src/public/channels/github/defaults.d.ts +21 -0
- package/dist/src/public/channels/github/defaults.js +3 -0
- package/dist/src/public/channels/github/dispatch.d.ts +34 -0
- package/dist/src/public/channels/github/dispatch.js +1 -0
- package/dist/src/public/channels/github/githubChannel.d.ts +109 -0
- package/dist/src/public/channels/github/githubChannel.js +1 -0
- package/dist/src/public/channels/github/inbound.d.ts +183 -0
- package/dist/src/public/channels/github/inbound.js +2 -0
- package/dist/src/public/channels/github/index.d.ts +9 -0
- package/dist/src/public/channels/github/index.js +1 -0
- package/dist/src/public/channels/github/limits.d.ts +4 -0
- package/dist/src/public/channels/github/limits.js +2 -0
- package/dist/src/public/channels/github/pr-context.d.ts +45 -0
- package/dist/src/public/channels/github/pr-context.js +5 -0
- package/dist/src/public/channels/github/state.d.ts +48 -0
- package/dist/src/public/channels/github/state.js +1 -0
- package/dist/src/public/channels/github/verify.d.ts +35 -0
- package/dist/src/public/channels/github/verify.js +1 -0
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/definitions/sandbox.d.ts +3 -3
- package/dist/src/public/definitions/tool.d.ts +21 -1
- package/dist/src/public/sandbox/index.d.ts +1 -1
- package/dist/src/public/tools/define-bash-tool.js +1 -1
- package/dist/src/public/tools/define-glob-tool.js +1 -1
- package/dist/src/public/tools/define-grep-tool.js +1 -1
- package/dist/src/public/tools/define-read-file-tool.js +1 -1
- package/dist/src/public/tools/define-write-file-tool.js +1 -1
- package/dist/src/public/tools/internal.js +1 -1
- package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
- package/dist/src/runtime/connections/authorization-tokens.d.ts +8 -0
- package/dist/src/runtime/connections/authorization-tokens.js +1 -1
- package/dist/src/runtime/connections/mcp-client.d.ts +14 -0
- package/dist/src/runtime/connections/mcp-client.js +1 -1
- package/dist/src/runtime/connections/types.d.ts +1 -0
- package/dist/src/runtime/framework-tools/ask-question.d.ts +4 -0
- package/dist/src/runtime/framework-tools/ask-question.js +1 -1
- package/dist/src/runtime/framework-tools/bash.d.ts +5 -0
- package/dist/src/runtime/framework-tools/bash.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +1 -0
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
- package/dist/src/runtime/framework-tools/final-output.js +1 -1
- package/dist/src/runtime/framework-tools/glob.d.ts +5 -0
- package/dist/src/runtime/framework-tools/glob.js +2 -2
- package/dist/src/runtime/framework-tools/grep.d.ts +5 -0
- package/dist/src/runtime/framework-tools/grep.js +2 -2
- package/dist/src/runtime/framework-tools/read-file.d.ts +5 -0
- package/dist/src/runtime/framework-tools/read-file.js +2 -2
- package/dist/src/runtime/framework-tools/skill.d.ts +2 -0
- package/dist/src/runtime/framework-tools/skill.js +1 -1
- package/dist/src/runtime/framework-tools/todo.d.ts +2 -0
- package/dist/src/runtime/framework-tools/todo.js +2 -2
- package/dist/src/runtime/framework-tools/web-fetch.d.ts +3 -0
- package/dist/src/runtime/framework-tools/web-fetch.js +2 -2
- package/dist/src/runtime/framework-tools/web-search.d.ts +17 -0
- package/dist/src/runtime/framework-tools/web-search.js +1 -1
- package/dist/src/runtime/framework-tools/write-file.d.ts +5 -0
- package/dist/src/runtime/framework-tools/write-file.js +2 -2
- package/dist/src/runtime/resolve-sandbox.js +1 -1
- package/dist/src/runtime/resolve-tool.js +1 -1
- package/dist/src/runtime/sandbox/keys.js +1 -1
- package/dist/src/runtime/sandbox/template-plan.d.ts +5 -0
- package/dist/src/runtime/sandbox/template-plan.js +1 -1
- package/dist/src/runtime/subagents/registry.js +1 -1
- package/dist/src/runtime/tools/registry.js +1 -1
- package/dist/src/runtime/types.d.ts +11 -2
- package/dist/src/shared/dynamic-tool-definition.d.ts +2 -1
- package/dist/src/shared/json-schema.d.ts +3 -1
- package/dist/src/shared/json-schema.js +1 -1
- package/dist/src/shared/sandbox-definition.d.ts +22 -2
- package/dist/src/shared/tool-definition.d.ts +10 -2
- package/package.json +25 -1
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Maximum body length accepted by GitHub issue and pull-request comments. */
|
|
2
|
+
export declare const GITHUB_COMMENT_BODY_MAX_LENGTH = 65536;
|
|
3
|
+
/** Splits a long comment body into GitHub-sized comment bodies. */
|
|
4
|
+
export declare function splitGitHubCommentBody(body: string, maxLength?: number): readonly string[];
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const GITHUB_COMMENT_BODY_MAX_LENGTH=65536;function splitGitHubCommentBody(t,n=GITHUB_COMMENT_BODY_MAX_LENGTH){if(t.length<=n)return[t];let r=[],i=t;for(;i.length>n;){let e=findCommentSplitIndex(i,n);r.push(i.slice(0,e).trimEnd()),i=i.slice(e).trimStart()}return i.length>0&&r.push(i),r}function findCommentSplitIndex(e,t){let n=e.lastIndexOf(`
|
|
2
|
+
`,t);if(n>t*.5)return n;let r=e.lastIndexOf(` `,t);return r>t*.5?r:t}export{GITHUB_COMMENT_BODY_MAX_LENGTH,splitGitHubCommentBody};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type GitHubApiOptions } from "#public/channels/github/api.js";
|
|
2
|
+
import type { GitHubChannelCredentials } from "#public/channels/github/auth.js";
|
|
3
|
+
/**
|
|
4
|
+
* Built-in glob patterns excluded from the diff loaded into model context.
|
|
5
|
+
*
|
|
6
|
+
* These files are large and generated; their patch text rarely helps the model
|
|
7
|
+
* and burns context budget. They are still listed with their stats so the agent
|
|
8
|
+
* knows they changed, and the full file is always available from the checkout.
|
|
9
|
+
*/
|
|
10
|
+
export declare const GITHUB_DEFAULT_EXCLUDED_DIFF_FILES: readonly string[];
|
|
11
|
+
/** Controls the pull-request diff injected into GitHub-triggered turns. */
|
|
12
|
+
export interface GitHubPullRequestContextConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Additional glob patterns excluded from the diff loaded into model context.
|
|
15
|
+
* Extends the built-in {@link GITHUB_DEFAULT_EXCLUDED_DIFF_FILES} list — it
|
|
16
|
+
* does not replace it. Excluded files are still listed with their stats; only
|
|
17
|
+
* the patch body is omitted.
|
|
18
|
+
*/
|
|
19
|
+
readonly excludedFiles?: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
/** Input for building one-shot model context for a pull request. */
|
|
22
|
+
export interface GitHubPullRequestContextInput {
|
|
23
|
+
readonly api?: GitHubApiOptions;
|
|
24
|
+
readonly config?: GitHubPullRequestContextConfig;
|
|
25
|
+
readonly credentials?: GitHubChannelCredentials;
|
|
26
|
+
readonly installationId?: number;
|
|
27
|
+
readonly owner: string;
|
|
28
|
+
readonly pullRequestNumber: number | null;
|
|
29
|
+
readonly repo: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Builds bounded, one-shot pull-request background for a GitHub turn: PR
|
|
33
|
+
* metadata plus the changed-file diff (noisy files excluded from the patch).
|
|
34
|
+
*
|
|
35
|
+
* The returned strings are intended for `SendPayload.context`; each is appended
|
|
36
|
+
* as a `role: "user"` message to session history before the delivery message.
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildGitHubPullRequestContext(input: GitHubPullRequestContextInput): Promise<readonly string[] | undefined>;
|
|
39
|
+
/** Merges channel-generated PR context before hook-provided context. */
|
|
40
|
+
export declare function mergeGitHubContext(input: {
|
|
41
|
+
readonly github?: readonly string[];
|
|
42
|
+
readonly hook?: readonly string[];
|
|
43
|
+
}): readonly string[] | undefined;
|
|
44
|
+
/** Returns true when a file path matches any of the provided glob patterns. */
|
|
45
|
+
export declare function fileMatchesAnyGlob(filename: string, patterns: readonly string[]): boolean;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{getGitHubPullRequest,listGitHubPullRequestFiles}from"#public/channels/github/api.js";const MAX_PATCH_BYTES=2e4,GITHUB_DEFAULT_EXCLUDED_DIFF_FILES=[`**/pnpm-lock.yaml`,`**/package-lock.json`,`**/npm-shrinkwrap.json`,`**/yarn.lock`,`**/bun.lockb`,`**/Cargo.lock`,`**/go.sum`,`**/poetry.lock`,`**/Pipfile.lock`,`**/uv.lock`,`**/composer.lock`,`**/Gemfile.lock`,`**/*.min.js`,`**/*.min.css`,`**/*.map`,`**/*.snap`];async function buildGitHubPullRequestContext(n){if(n.pullRequestNumber===null)return;let i=renderPullRequestMetadata(await getGitHubPullRequest({api:n.api,credentials:n.credentials,installationId:n.installationId,owner:n.owner,pullRequestNumber:n.pullRequestNumber,repo:n.repo})),a=await listGitHubPullRequestFiles({api:n.api,credentials:n.credentials,installationId:n.installationId,owner:n.owner,perPage:50,pullRequestNumber:n.pullRequestNumber,repo:n.repo}),o=[...GITHUB_DEFAULT_EXCLUDED_DIFF_FILES,...n.config?.excludedFiles??[]];return i.push(``,...renderPullRequestFiles(a,o)),[[`GitHub pull request context for the current turn. `,`Use this as background for the user's GitHub comment.`,``,i.join(`
|
|
2
|
+
`)].join(`
|
|
3
|
+
`)]}function mergeGitHubContext(e){let t=e.github??[],n=e.hook??[];if(!(t.length===0&&n.length===0))return[...t,...n]}function renderPullRequestMetadata(e){return[`<github_pull_request>`,`number: ${e.number}`,`title: ${e.title}`,`state: ${e.state??`unknown`}`,`draft: ${e.draft?`true`:`false`}`,...e.author?.login?[`author: ${e.author.login}`]:[],...e.htmlUrl?[`url: ${e.htmlUrl}`]:[],...e.base.ref?[`base_ref: ${e.base.ref}`]:[],...e.base.sha?[`base_sha: ${e.base.sha}`]:[],...e.head.ref?[`head_ref: ${e.head.ref}`]:[],...e.head.sha?[`head_sha: ${e.head.sha}`]:[],...e.mergeable===null||e.mergeable===void 0?[]:[`mergeable: ${e.mergeable?`true`:`false`}`],...e.changedFiles===void 0?[]:[`changed_files: ${e.changedFiles}`],...e.additions===void 0?[]:[`additions: ${e.additions}`],...e.deletions===void 0?[]:[`deletions: ${e.deletions}`],...e.body?[``,`body:`,indent(truncateText(e.body,4e3))]:[],`</github_pull_request>`]}function renderPullRequestFiles(e,t){if(e.length===0)return[`<github_pull_request_files>`,`none`,`</github_pull_request_files>`];let r=[`<github_pull_request_files>`],i=MAX_PATCH_BYTES,a=!1;for(let n of e){if(r.push(renderFileSummary(n)),fileMatchesAnyGlob(n.filename,t)){r.push(` patch omitted (excluded)`);continue}if(n.patch===void 0)continue;if(i<=0){a=!0;continue}let e=truncateByBytes(n.patch,i);r.push(`patch:`,indent(e.text)),i-=e.bytes,e.truncated&&(a=!0,i=0)}return a&&r.push(``,`patches_truncated: true`,`max_patch_bytes: ${MAX_PATCH_BYTES}`),r.push(`</github_pull_request_files>`),r}function renderFileSummary(e){let t=[e.status??`modified`,e.additions===void 0?void 0:`+${e.additions}`,e.deletions===void 0?void 0:`-${e.deletions}`].filter(e=>e!==void 0);return`- ${e.filename}${t.length>0?` (${t.join(`, `)})`:``}`}function fileMatchesAnyGlob(e,t){return t.some(t=>globToRegExp(t).test(e))}function globToRegExp(e){let t=``;for(let n=0;n<e.length;n+=1){let r=e.charAt(n);r===`*`?e[n+1]===`*`?(t+=`.*`,n+=1,e[n+1]===`/`&&(n+=1)):t+=`[^/]*`:`\\^$.|?+()[]{}`.includes(r)?t+=`\\${r}`:t+=r}return RegExp(`^${t}$`,`u`)}function truncateByBytes(e,t){let n=new TextEncoder().encode(e);return n.byteLength<=t?{bytes:n.byteLength,text:e,truncated:!1}:{bytes:t,text:`${new TextDecoder().decode(n.slice(0,t))}\n[truncated]`,truncated:!0}}function truncateText(e,t){return e.length<=t?e:`${e.slice(0,t)}\n[truncated]`}function indent(e){return e.split(`
|
|
4
|
+
`).map(e=>` ${e}`).join(`
|
|
5
|
+
`)}export{GITHUB_DEFAULT_EXCLUDED_DIFF_FILES,buildGitHubPullRequestContext,fileMatchesAnyGlob,mergeGitHubContext};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type GitHubConversationKind, type GitHubConversationRef, type GitHubIssueCommentEvent, type GitHubIssueWebhookEvent, type GitHubPullRequestReviewCommentEvent, type GitHubPullRequestWebhookEvent } from "#public/channels/github/inbound.js";
|
|
2
|
+
/** JSON-serializable GitHub channel state. */
|
|
3
|
+
export interface GitHubChannelState {
|
|
4
|
+
baseRef: string | null;
|
|
5
|
+
baseSha: string | null;
|
|
6
|
+
checkoutPath: string | null;
|
|
7
|
+
conversationKind: GitHubConversationKind;
|
|
8
|
+
defaultBranch: string | null;
|
|
9
|
+
headRef: string | null;
|
|
10
|
+
headSha: string | null;
|
|
11
|
+
installationId: number | null;
|
|
12
|
+
issueNumber: number | null;
|
|
13
|
+
owner: string;
|
|
14
|
+
pullRequestNumber: number | null;
|
|
15
|
+
repo: string;
|
|
16
|
+
repositoryId: number;
|
|
17
|
+
reviewCommentId: number | null;
|
|
18
|
+
reviewThreadRootCommentId: number | null;
|
|
19
|
+
triggeringCommentId: number | null;
|
|
20
|
+
triggeringUserLogin: string | null;
|
|
21
|
+
}
|
|
22
|
+
/** Minimal receive target needed to seed GitHub channel state. */
|
|
23
|
+
export interface GitHubReceiveStateTarget {
|
|
24
|
+
readonly installationId?: number;
|
|
25
|
+
readonly issueNumber?: number;
|
|
26
|
+
readonly pullRequestNumber?: number;
|
|
27
|
+
}
|
|
28
|
+
/** Initial empty GitHub channel state. */
|
|
29
|
+
export declare function initialGitHubState(): GitHubChannelState;
|
|
30
|
+
/** Builds state for an issue or PR timeline comment. */
|
|
31
|
+
export declare function stateFromIssueCommentEvent(event: GitHubIssueCommentEvent): GitHubChannelState;
|
|
32
|
+
/** Builds state for an inline pull-request review comment. */
|
|
33
|
+
export declare function stateFromPullRequestReviewCommentEvent(event: GitHubPullRequestReviewCommentEvent): GitHubChannelState;
|
|
34
|
+
/** Builds state for an issue event hook dispatch. */
|
|
35
|
+
export declare function stateFromIssueEvent(event: GitHubIssueWebhookEvent): GitHubChannelState;
|
|
36
|
+
/** Builds state for a pull-request event hook dispatch. */
|
|
37
|
+
export declare function stateFromPullRequestEvent(event: GitHubPullRequestWebhookEvent): GitHubChannelState;
|
|
38
|
+
/** Builds state for proactive `receive()` calls. */
|
|
39
|
+
export declare function stateFromReceiveTarget(input: {
|
|
40
|
+
readonly target: GitHubReceiveStateTarget;
|
|
41
|
+
readonly owner: string;
|
|
42
|
+
readonly repo: string;
|
|
43
|
+
readonly repositoryId: number;
|
|
44
|
+
}): GitHubChannelState;
|
|
45
|
+
/** Reconstructs the channel-local GitHub conversation reference from state. */
|
|
46
|
+
export declare function conversationFromState(state: GitHubChannelState): GitHubConversationRef;
|
|
47
|
+
/** Builds the channel-local continuation token from durable state. */
|
|
48
|
+
export declare function continuationTokenFromState(state: GitHubChannelState): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{githubContinuationToken}from"#public/channels/github/inbound.js";function initialGitHubState(){return{baseRef:null,baseSha:null,checkoutPath:null,conversationKind:`issue`,defaultBranch:null,headRef:null,headSha:null,installationId:null,issueNumber:null,owner:``,pullRequestNumber:null,repo:``,repositoryId:0,reviewCommentId:null,reviewThreadRootCommentId:null,triggeringCommentId:null,triggeringUserLogin:null}}function stateFromIssueCommentEvent(e){return{...initialGitHubState(),baseRef:e.baseRef,baseSha:e.baseSha,conversationKind:e.conversation.kind,defaultBranch:e.defaultBranch,headRef:e.headRef,headSha:e.headSha,installationId:e.installationId??null,issueNumber:e.comment.issueNumber,owner:e.repository.owner,pullRequestNumber:e.comment.pullRequestNumber,repo:e.repository.name,repositoryId:e.repository.id,triggeringCommentId:e.comment.id,triggeringUserLogin:e.sender.login}}function stateFromPullRequestReviewCommentEvent(e){return{...initialGitHubState(),baseRef:e.baseRef,baseSha:e.baseSha,conversationKind:`review_thread`,defaultBranch:e.defaultBranch,headRef:e.headRef,headSha:e.headSha,installationId:e.installationId??null,owner:e.repository.owner,pullRequestNumber:e.comment.pullRequestNumber,repo:e.repository.name,repositoryId:e.repository.id,reviewCommentId:e.comment.id,reviewThreadRootCommentId:e.comment.reviewThreadRootCommentId,triggeringCommentId:e.comment.id,triggeringUserLogin:e.sender.login}}function stateFromIssueEvent(e){return{...initialGitHubState(),conversationKind:`issue`,installationId:e.installationId??null,issueNumber:e.issue.issueNumber,owner:e.repository.owner,repo:e.repository.name,repositoryId:e.repository.id,triggeringUserLogin:e.sender.login}}function stateFromPullRequestEvent(e){return{...initialGitHubState(),baseRef:e.baseRef,baseSha:e.baseSha,conversationKind:`pull_request`,defaultBranch:e.defaultBranch,headRef:e.headRef,headSha:e.headSha,installationId:e.installationId??null,issueNumber:e.pullRequest.pullRequestNumber,owner:e.repository.owner,pullRequestNumber:e.pullRequest.pullRequestNumber,repo:e.repository.name,repositoryId:e.repository.id,triggeringUserLogin:e.sender.login}}function stateFromReceiveTarget(e){let{target:t}=e,n=t.pullRequestNumber===void 0?`issue`:`pull_request`;return{...initialGitHubState(),conversationKind:n,installationId:t.installationId??null,issueNumber:n===`issue`?t.issueNumber??null:t.pullRequestNumber??null,owner:e.owner,pullRequestNumber:t.pullRequestNumber??null,repo:e.repo,repositoryId:e.repositoryId}}function conversationFromState(e){return{issueNumber:e.issueNumber,kind:e.conversationKind,pullRequestNumber:e.pullRequestNumber}}function continuationTokenFromState(t){return githubContinuationToken({conversationKind:t.conversationKind,issueNumber:t.issueNumber,pullRequestNumber:t.pullRequestNumber,repositoryId:t.repositoryId,reviewThreadRootCommentId:t.reviewThreadRootCommentId})}export{continuationTokenFromState,conversationFromState,initialGitHubState,stateFromIssueCommentEvent,stateFromIssueEvent,stateFromPullRequestEvent,stateFromPullRequestReviewCommentEvent,stateFromReceiveTarget};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type GitHubWebhookSecret } from "#public/channels/github/auth.js";
|
|
2
|
+
/**
|
|
3
|
+
* Caller-supplied inbound webhook verifier. Used as an alternative to
|
|
4
|
+
* HMAC verification — e.g. Connect supplies a verifier that authenticates
|
|
5
|
+
* Connect-forwarded webhooks with Vercel OIDC instead of GitHub's webhook
|
|
6
|
+
* secret.
|
|
7
|
+
*
|
|
8
|
+
* Contract (matches the other channels' `webhookVerifier`):
|
|
9
|
+
*
|
|
10
|
+
* - **Throw / reject** → the channel responds 401 to GitHub.
|
|
11
|
+
* - **Return a falsy value** (`null` / `undefined` / `false` / `""` / `0`)
|
|
12
|
+
* → the channel responds 401 to GitHub. This lets verifiers signal
|
|
13
|
+
* rejection without throwing — e.g. Connect's `vercelOidc()` returns
|
|
14
|
+
* `null` on a failed OIDC check.
|
|
15
|
+
* - **Return a truthy non-string value** → verification accepted.
|
|
16
|
+
* - **Return a string** → verification accepted, and the string replaces
|
|
17
|
+
* the raw body for downstream parsing.
|
|
18
|
+
*/
|
|
19
|
+
export type GitHubWebhookVerifier = (request: Request, body: string) => unknown | Promise<unknown>;
|
|
20
|
+
/** Options for {@link verifyGitHubRequest}. */
|
|
21
|
+
export interface GitHubVerifyOptions {
|
|
22
|
+
readonly webhookSecret?: GitHubWebhookSecret;
|
|
23
|
+
readonly webhookVerifier?: GitHubWebhookVerifier;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Verifies a GitHub webhook request and returns its raw body. The raw body is
|
|
27
|
+
* required because GitHub signs the exact bytes it delivered.
|
|
28
|
+
*
|
|
29
|
+
* When a {@link GitHubWebhookVerifier} is supplied, it replaces the built-in
|
|
30
|
+
* HMAC check: GitHub's webhook secret is never read and the verifier owns the
|
|
31
|
+
* accept/reject decision.
|
|
32
|
+
*/
|
|
33
|
+
export declare function verifyGitHubRequest(request: Request, options: GitHubVerifyOptions): Promise<string>;
|
|
34
|
+
/** Signs a raw GitHub webhook body for tests and local fixtures. */
|
|
35
|
+
export declare function signGitHubWebhookBody(body: string, secret: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{createHmac,timingSafeEqual}from"node:crypto";import{resolveGitHubWebhookSecret}from"#public/channels/github/auth.js";const log=createLogger(`github.verify`);async function verifyGitHubRequest(e,t){let n=await e.text();if(t.webhookVerifier!==void 0){let r=await t.webhookVerifier(e,n);if(!r)throw Error(`githubChannel: inbound webhook verifier rejected the request.`);return typeof r==`string`?r:n}let i=await resolveGitHubWebhookSecret(t.webhookSecret),a=e.headers.get(`x-hub-signature-256`)??``;if(!a)throw Error(`githubChannel: inbound request missing X-Hub-Signature-256.`);if(!constantTimeCompare(signGitHubWebhookBody(n,i),a))throw Error(`githubChannel: inbound request signature mismatch.`);return n}function signGitHubWebhookBody(e,n){return`sha256=${createHmac(`sha256`,n).update(e).digest(`hex`)}`}function constantTimeCompare(e,t){if(e.length!==t.length)return!1;try{return timingSafeEqual(Buffer.from(e),Buffer.from(t))}catch(e){return log.debug(`timingSafeEqual threw`,{error:e}),!1}}export{signGitHubWebhookBody,verifyGitHubRequest};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{buildSlackBinding,slackContinuationToken}from"#public/channels/slack/api.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{formatSlackContextBlock,parseAppMentionEvent,parseDirectMessageEvent}from"#public/channels/slack/inbound.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.setContinuationToken(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),l=createSlackFetchFile({botToken:e.credentials?.botToken}),u=e.onAppMention??defaultOnAppMention,d=e.onDirectMessage??defaultOnDirectMessage,f={...defaultEvents,...e.events,"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler()};return defineChannel({kindHint:`slack`,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,pendingAuthMessageTs:{}},fetchFile:l,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,{send:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials);return a===null?new Response(`unauthorized`,{status:401}):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(a,{send:r,waitUntil:i},{config:e}):handleEventPost({body:a,send:r,waitUntil:i,onAppMention:u,onDirectMessage:d,uploadPolicy:t,credentials:e.credentials})})],async receive(t,{send:n}){let r=t.target,i=r.channelId;if(!i||typeof i!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let o=typeof r.threadTs==`string`?r.threadTs:``,s=r.initialMessage;if(s&&o.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let c=o;if(s){let{thread:t}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:i,threadTs:``,teamId:void 0}),n={card:s.card};s.fallbackText!==void 0&&(n.fallbackText=s.fallbackText),c=(await t.post(n)).id}return n(t.message,{auth:t.auth,continuationToken:slackContinuationToken(i,c),state:{channelId:i,threadTs:c||null,teamId:null,triggeringUserId:null}})},events:f})}async function handleEventPost(e){let t;try{t=JSON.parse(e.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(typeof t.challenge==`string`)return new Response(t.challenge,{status:200,headers:{"content-type":`text/plain`}});let n=parseAppMentionEvent(t);if(n)return e.waitUntil(dispatchInboundMessage({kind:`app_mention`,message:n,handler:e.onAppMention,send:e.send,uploadPolicy:e.uploadPolicy,credentials:e.credentials})),new Response(`ok`);let r=parseDirectMessageEvent(t);return r&&e.waitUntil(dispatchInboundMessage({kind:`direct_message`,message:r,handler:e.onDirectMessage,send:e.send,uploadPolicy:e.uploadPolicy,credentials:e.credentials})),new Response(`ok`)}async function verifyInbound(e,t){try{return await verifySlackRequest(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function dispatchInboundMessage(e){let{message:n,kind:r}=e,{thread:i,slack:o}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:n.channelId,threadTs:n.threadTs,teamId:n.teamId}),s={thread:i,slack:o},c;try{c=await e.handler(s,n)}catch(e){logError(log,`${r} handler failed`,e,{channelId:n.channelId});return}if(c!=null)try{let t=await collectInboundFileParts({mention:n,thread:i,policy:e.uploadPolicy}),r=buildSlackTurnMessage(n.markdown,t),a={channelId:n.channelId,fullName:n.author?.fullName,teamId:n.teamId,threadTs:n.threadTs,userId:n.author?.userId??``,userName:n.author?.userName},o=c.context??[];await e.send({message:r,context:[formatSlackContextBlock(a),...o]},{auth:c.auth,continuationToken:slackContinuationToken(n.channelId,n.threadTs),state:{channelId:n.channelId,threadTs:n.threadTs,teamId:n.teamId??null,triggeringUserId:a.userId||null}})}catch(e){logError(log,`${r} delivery failed`,e,{channelId:n.channelId})}}export{slackChannel};
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{mergeUploadPolicy}from"#public/channels/upload-policy.js";import{POST,defineChannel}from"#public/definitions/defineChannel.js";import{buildSlackBinding,slackContinuationToken}from"#public/channels/slack/api.js";import{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage}from"#public/channels/slack/defaults.js";import{buildSlackTurnMessage,collectInboundFileParts,createSlackFetchFile}from"#public/channels/slack/attachments.js";import{formatSlackContextBlock,parseAppMentionEvent,parseDirectMessageEvent}from"#public/channels/slack/inbound.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#public/channels/slack/constants.js";import{handleInteractionPost}from"#public/channels/slack/interactions.js";import{verifySlackRequest}from"#public/channels/slack/verify.js";const log=createLogger(`slack.channel`);function rebuildSlackContext(e,t,n){let{thread:r,slack:i}=buildSlackBinding({botToken:n?.botToken,channelId:e.channelId??``,threadTs:e.threadTs??``,teamId:e.teamId??void 0,onThreadTsChanged(n){e.threadTs=n,e.channelId&&t.setContinuationToken(slackContinuationToken(e.channelId,n))}});return{thread:r,slack:i,state:e}}function slackChannel(e={}){let t=mergeUploadPolicy(e.uploadPolicy),l=createSlackFetchFile({botToken:e.credentials?.botToken}),u=e.onAppMention??defaultOnAppMention,d=e.onDirectMessage??defaultOnDirectMessage,f={...defaultEvents,...e.events,"input.requested":e.events?.[`input.requested`]??defaultInputRequestedHandler()};return defineChannel({kindHint:`slack`,state:{channelId:null,threadTs:null,teamId:null,triggeringUserId:null,pendingToolCallMessage:null,pendingAuthMessageTs:{}},fetchFile:l,metadata(e){return{channelId:e.channelId,teamId:e.teamId,threadTs:e.threadTs,triggeringUserId:e.triggeringUserId??null}},context(t,n){return rebuildSlackContext(t,n,e.credentials)},routes:[POST(e.route??SLACK_CHANNEL_DEFAULT_ROUTE,async(n,{send:r,waitUntil:i})=>{let a=await verifyInbound(n,e.credentials);return a===null?new Response(`unauthorized`,{status:401}):shouldDropSlackHttpTimeoutRetry(n.headers)?new Response(`ok`):(n.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`)?handleInteractionPost(a,{send:r,waitUntil:i},{config:e}):handleEventPost({body:a,send:r,waitUntil:i,onAppMention:u,onDirectMessage:d,uploadPolicy:t,credentials:e.credentials})})],async receive(t,{send:n}){let r=t.target,i=r.channelId;if(!i||typeof i!=`string`)throw Error(`slackChannel().receive requires target.channelId.`);let o=typeof r.threadTs==`string`?r.threadTs:``,s=r.initialMessage;if(s&&o.length>0)throw Error("slackChannel().receive: `threadTs` and `initialMessage` are mutually exclusive.");let c=o;if(s){let{thread:t}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:i,threadTs:``,teamId:void 0}),n={card:s.card};s.fallbackText!==void 0&&(n.fallbackText=s.fallbackText),c=(await t.post(n)).id}return n(t.message,{auth:t.auth,continuationToken:slackContinuationToken(i,c),state:{channelId:i,threadTs:c||null,teamId:null,triggeringUserId:null}})},events:f})}function shouldDropSlackHttpTimeoutRetry(e){return Number(e.get(`x-slack-retry-num`)??``)>=1&&e.get(`x-slack-retry-reason`)===`http_timeout`}async function handleEventPost(e){let t;try{t=JSON.parse(e.body)}catch(e){return log.warn(`inbound webhook body is not valid JSON`,{error:e}),new Response(`ok`)}if(typeof t.challenge==`string`)return new Response(t.challenge,{status:200,headers:{"content-type":`text/plain`}});let n=parseAppMentionEvent(t);if(n)return e.waitUntil(dispatchInboundMessage({kind:`app_mention`,message:n,handler:e.onAppMention,send:e.send,uploadPolicy:e.uploadPolicy,credentials:e.credentials})),new Response(`ok`);let r=parseDirectMessageEvent(t);return r&&e.waitUntil(dispatchInboundMessage({kind:`direct_message`,message:r,handler:e.onDirectMessage,send:e.send,uploadPolicy:e.uploadPolicy,credentials:e.credentials})),new Response(`ok`)}async function verifyInbound(e,t){try{return await verifySlackRequest(e,{signingSecret:t?.signingSecret??(t?.webhookVerifier?void 0:process.env.SLACK_SIGNING_SECRET),webhookVerifier:t?.webhookVerifier})}catch(e){return log.warn(`slack inbound verification failed`,{error:e}),null}}async function dispatchInboundMessage(e){let{message:n,kind:r}=e,{thread:i,slack:o}=buildSlackBinding({botToken:e.credentials?.botToken,channelId:n.channelId,threadTs:n.threadTs,teamId:n.teamId}),s={thread:i,slack:o},c;try{c=await e.handler(s,n)}catch(e){logError(log,`${r} handler failed`,e,{channelId:n.channelId});return}if(c!=null)try{let t=await collectInboundFileParts({mention:n,thread:i,policy:e.uploadPolicy}),r=buildSlackTurnMessage(n.markdown,t),a={channelId:n.channelId,fullName:n.author?.fullName,teamId:n.teamId,threadTs:n.threadTs,userId:n.author?.userId??``,userName:n.author?.userName},o=c.context??[];await e.send({message:r,context:[formatSlackContextBlock(a),...o]},{auth:c.auth,continuationToken:slackContinuationToken(n.channelId,n.threadTs),state:{channelId:n.channelId,threadTs:n.threadTs,teamId:n.teamId??null,triggeringUserId:a.userId||null}})}catch(e){logError(log,`${r} delivery failed`,e,{channelId:n.channelId})}}export{slackChannel};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Optional } from "#shared/optional.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { SandboxDefinitionWithBootstrap as SharedSandboxDefinitionWithBootstrap, SandboxDefinitionWithoutBootstrap as SharedSandboxDefinitionWithoutBootstrap } from "#shared/sandbox-definition.js";
|
|
3
3
|
export type { SandboxCommandResult, SandboxProcess, SandboxReadBinaryFileOptions, SandboxReadFileOptions, SandboxRemovePathOptions, SandboxReadTextFileOptions, SandboxRunOptions, SandboxSession, SandboxSpawnOptions, SandboxWriteBinaryFileOptions, SandboxWriteFileOptions, SandboxWriteTextFileOptions, } from "#shared/sandbox-session.js";
|
|
4
|
-
export type { SandboxBootstrapUseFn, SandboxSessionUseFn, SandboxBootstrapContext, SandboxSessionContext, } from "#shared/sandbox-definition.js";
|
|
5
|
-
export type SandboxDefinition<BO = Record<string, never>, SO = Record<string, never>> = Optional<
|
|
4
|
+
export type { SandboxBootstrapUseFn, SandboxRevalidationKeyFn, SandboxSessionUseFn, SandboxBootstrapContext, SandboxSessionContext, } from "#shared/sandbox-definition.js";
|
|
5
|
+
export type SandboxDefinition<BO = Record<string, never>, SO = Record<string, never>> = Optional<SharedSandboxDefinitionWithBootstrap<BO, SO>, "backend"> | Optional<SharedSandboxDefinitionWithoutBootstrap<BO, SO>, "backend">;
|
|
6
6
|
/**
|
|
7
7
|
* Defines a sandbox configuration.
|
|
8
8
|
*/
|
|
@@ -55,7 +55,7 @@ export type ToolContext = SessionContext;
|
|
|
55
55
|
* `get-weather`. Authored definitions do not carry a `name` field —
|
|
56
56
|
* identity is path-derived.
|
|
57
57
|
*/
|
|
58
|
-
export type ToolDefinition<TInput = unknown, TOutput = unknown> = PublicToolDefinition<TInput> & {
|
|
58
|
+
export type ToolDefinition<TInput = unknown, TOutput = unknown> = PublicToolDefinition<TInput, TOutput> & {
|
|
59
59
|
execute(input: TInput, ctx: ToolContext): Promise<TOutput> | TOutput;
|
|
60
60
|
/**
|
|
61
61
|
* Optional per-tool approval gate. When set, the function's return value
|
|
@@ -98,17 +98,37 @@ export type ToolDefinition<TInput = unknown, TOutput = unknown> = PublicToolDefi
|
|
|
98
98
|
* For dynamic entries, `defineTool` stamps a brand that the
|
|
99
99
|
* lifecycle code validates — raw object literals are rejected.
|
|
100
100
|
*/
|
|
101
|
+
export declare function defineTool<TInputSchema extends StandardJSONSchemaV1<unknown, unknown>, TOutputSchema extends StandardJSONSchemaV1<unknown, unknown>>(definition: {
|
|
102
|
+
description: ToolDefinition<unknown, unknown>["description"];
|
|
103
|
+
inputSchema: TInputSchema;
|
|
104
|
+
outputSchema: TOutputSchema;
|
|
105
|
+
execute(input: StandardJSONSchemaV1.InferOutput<TInputSchema>, ctx: ToolContext): Promise<StandardJSONSchemaV1.InferOutput<TOutputSchema>> | StandardJSONSchemaV1.InferOutput<TOutputSchema>;
|
|
106
|
+
needsApproval?: ToolDefinition<StandardJSONSchemaV1.InferOutput<TInputSchema>, unknown>["needsApproval"];
|
|
107
|
+
toModelOutput?: ToolDefinition<unknown, StandardJSONSchemaV1.InferOutput<TOutputSchema>>["toModelOutput"];
|
|
108
|
+
onCompact?: ToolDefinition<unknown, unknown>["onCompact"];
|
|
109
|
+
}): ToolDefinition<StandardJSONSchemaV1.InferOutput<TInputSchema>, StandardJSONSchemaV1.InferOutput<TOutputSchema>>;
|
|
101
110
|
export declare function defineTool<TSchema extends StandardJSONSchemaV1<unknown, unknown>, TOutput>(definition: {
|
|
102
111
|
description: ToolDefinition<unknown, unknown>["description"];
|
|
103
112
|
inputSchema: TSchema;
|
|
113
|
+
outputSchema?: JsonObject;
|
|
104
114
|
execute(input: StandardJSONSchemaV1.InferOutput<TSchema>, ctx: ToolContext): Promise<TOutput> | TOutput;
|
|
105
115
|
needsApproval?: ToolDefinition<StandardJSONSchemaV1.InferOutput<TSchema>, unknown>["needsApproval"];
|
|
106
116
|
toModelOutput?: ToolDefinition<unknown, TOutput>["toModelOutput"];
|
|
107
117
|
onCompact?: ToolDefinition<unknown, unknown>["onCompact"];
|
|
108
118
|
}): ToolDefinition<StandardJSONSchemaV1.InferOutput<TSchema>, TOutput>;
|
|
119
|
+
export declare function defineTool<TOutputSchema extends StandardJSONSchemaV1<unknown, unknown>>(definition: {
|
|
120
|
+
description: ToolDefinition<unknown, unknown>["description"];
|
|
121
|
+
inputSchema: JsonObject;
|
|
122
|
+
outputSchema: TOutputSchema;
|
|
123
|
+
execute(input: Record<string, unknown>, ctx: ToolContext): Promise<StandardJSONSchemaV1.InferOutput<TOutputSchema>> | StandardJSONSchemaV1.InferOutput<TOutputSchema>;
|
|
124
|
+
needsApproval?: ToolDefinition<Record<string, unknown>, unknown>["needsApproval"];
|
|
125
|
+
toModelOutput?: ToolDefinition<unknown, StandardJSONSchemaV1.InferOutput<TOutputSchema>>["toModelOutput"];
|
|
126
|
+
onCompact?: ToolDefinition<unknown, unknown>["onCompact"];
|
|
127
|
+
}): ToolDefinition<Record<string, unknown>, StandardJSONSchemaV1.InferOutput<TOutputSchema>>;
|
|
109
128
|
export declare function defineTool<TOutput>(definition: {
|
|
110
129
|
description: ToolDefinition<unknown, unknown>["description"];
|
|
111
130
|
inputSchema: JsonObject;
|
|
131
|
+
outputSchema?: JsonObject;
|
|
112
132
|
execute(input: Record<string, unknown>, ctx: ToolContext): Promise<TOutput> | TOutput;
|
|
113
133
|
needsApproval?: ToolDefinition<Record<string, unknown>, unknown>["needsApproval"];
|
|
114
134
|
toModelOutput?: ToolDefinition<unknown, TOutput>["toModelOutput"];
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Sandbox authoring helpers for `agent/sandbox.ts` (or
|
|
3
3
|
* `agent/sandbox/sandbox.ts` when paired with a `workspace/` folder).
|
|
4
4
|
*/
|
|
5
|
-
export { defineSandbox, type SandboxBootstrapContext, type SandboxBootstrapUseFn, type SandboxCommandResult, type SandboxDefinition, type SandboxProcess, type SandboxReadBinaryFileOptions, type SandboxReadFileOptions, type SandboxReadTextFileOptions, type SandboxRunOptions, type SandboxSession, type SandboxSpawnOptions, type SandboxSessionContext, type SandboxSessionUseFn, type SandboxWriteBinaryFileOptions, type SandboxWriteFileOptions, type SandboxWriteTextFileOptions, } from "#public/definitions/sandbox.js";
|
|
5
|
+
export { defineSandbox, type SandboxBootstrapContext, type SandboxBootstrapUseFn, type SandboxCommandResult, type SandboxDefinition, type SandboxProcess, type SandboxReadBinaryFileOptions, type SandboxReadFileOptions, type SandboxReadTextFileOptions, type SandboxRevalidationKeyFn, type SandboxRunOptions, type SandboxSession, type SandboxSpawnOptions, type SandboxSessionContext, type SandboxSessionUseFn, type SandboxWriteBinaryFileOptions, type SandboxWriteFileOptions, type SandboxWriteTextFileOptions, } from "#public/definitions/sandbox.js";
|
|
6
6
|
export type { SandboxBackend, SandboxBackendCreateInput, SandboxBackendHandle, SandboxBackendPrewarmInput, SandboxBackendRuntimeContext, SandboxBackendSessionState, SandboxSeedFile, } from "#public/definitions/sandbox-backend.js";
|
|
7
7
|
export type { SandboxNetworkPolicy } from "#shared/sandbox-network-policy.js";
|
|
8
8
|
export { SandboxTemplateNotProvisionedError } from "#public/definitions/sandbox-backend.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{BASH_INPUT_SCHEMA}from"#runtime/framework-tools/bash.js";import{executeBashOnSandbox}from"#execution/sandbox/bash-tool.js";function defineBashTool(
|
|
1
|
+
import{BASH_INPUT_SCHEMA,BASH_OUTPUT_SCHEMA}from"#runtime/framework-tools/bash.js";import{executeBashOnSandbox}from"#execution/sandbox/bash-tool.js";function defineBashTool(n={}){return{description:n.description??`Execute a shell command in the workspace sandbox.`,async execute(e,t){return executeBashOnSandbox(await t.getSandbox(),e)},inputSchema:BASH_INPUT_SCHEMA,outputSchema:BASH_OUTPUT_SCHEMA}}export{defineBashTool};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{GLOB_INPUT_SCHEMA}from"#runtime/framework-tools/glob.js";import{executeGlobOnSandbox}from"#execution/sandbox/glob-tool.js";function defineGlobTool(
|
|
1
|
+
import{GLOB_INPUT_SCHEMA,GLOB_OUTPUT_SCHEMA}from"#runtime/framework-tools/glob.js";import{executeGlobOnSandbox}from"#execution/sandbox/glob-tool.js";function defineGlobTool(n={}){return{description:n.description??`Search for files by glob pattern in the workspace sandbox.`,async execute(e,t){return executeGlobOnSandbox(await t.getSandbox(),e)},inputSchema:GLOB_INPUT_SCHEMA,outputSchema:GLOB_OUTPUT_SCHEMA}}export{defineGlobTool};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{GREP_INPUT_SCHEMA}from"#runtime/framework-tools/grep.js";import{executeGrepOnSandbox}from"#execution/sandbox/grep-tool.js";function defineGrepTool(
|
|
1
|
+
import{GREP_INPUT_SCHEMA,GREP_OUTPUT_SCHEMA}from"#runtime/framework-tools/grep.js";import{executeGrepOnSandbox}from"#execution/sandbox/grep-tool.js";function defineGrepTool(n={}){return{description:n.description??`Search file contents by pattern in the workspace sandbox.`,async execute(e,t){return executeGrepOnSandbox(await t.getSandbox(),e)},inputSchema:GREP_INPUT_SCHEMA,outputSchema:GREP_OUTPUT_SCHEMA}}export{defineGrepTool};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{clearReadFileState}from"#runtime/framework-tools/file-state.js";import{READ_FILE_INPUT_SCHEMA}from"#runtime/framework-tools/read-file.js";import{executeReadFileOnSandbox}from"#execution/sandbox/read-file-tool.js";function defineReadFileTool(n={}){let r=n.onCompact??(()=>(clearReadFileState(),{}));return{description:n.description??`Read a file from the workspace sandbox.`,async execute(e,t){return executeReadFileOnSandbox(await t.getSandbox(),e)},inputSchema:READ_FILE_INPUT_SCHEMA,onCompact:r}}export{defineReadFileTool};
|
|
1
|
+
import{clearReadFileState}from"#runtime/framework-tools/file-state.js";import{READ_FILE_INPUT_SCHEMA,READ_FILE_OUTPUT_SCHEMA}from"#runtime/framework-tools/read-file.js";import{executeReadFileOnSandbox}from"#execution/sandbox/read-file-tool.js";function defineReadFileTool(n={}){let r=n.onCompact??(()=>(clearReadFileState(),{}));return{description:n.description??`Read a file from the workspace sandbox.`,async execute(e,t){return executeReadFileOnSandbox(await t.getSandbox(),e)},inputSchema:READ_FILE_INPUT_SCHEMA,onCompact:r,outputSchema:READ_FILE_OUTPUT_SCHEMA}}export{defineReadFileTool};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{WRITE_FILE_INPUT_SCHEMA}from"#runtime/framework-tools/write-file.js";import{executeWriteFileOnSandbox}from"#execution/sandbox/write-file-tool.js";function defineWriteFileTool(
|
|
1
|
+
import{WRITE_FILE_INPUT_SCHEMA,WRITE_FILE_OUTPUT_SCHEMA}from"#runtime/framework-tools/write-file.js";import{executeWriteFileOnSandbox}from"#execution/sandbox/write-file-tool.js";function defineWriteFileTool(n={}){return{description:n.description??`Write a file to the workspace sandbox.`,async execute(e,t){return executeWriteFileOnSandbox(await t.getSandbox(),e)},inputSchema:WRITE_FILE_INPUT_SCHEMA,outputSchema:WRITE_FILE_OUTPUT_SCHEMA}}export{defineWriteFileTool};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function toPublicToolDefinition(e){if(!e.execute)throw Error(`Tool "${e.name}" is client-side and cannot be re-exported publicly.`);let t=e.execute,n=e.inputSchema,r={description:e.description,execute:e=>t(e),inputSchema:n??{}};return e.needsApproval!==void 0&&(r.needsApproval=e.needsApproval),e.onCompact!==void 0&&(r.onCompact=e.onCompact),r}export{toPublicToolDefinition};
|
|
1
|
+
function toPublicToolDefinition(e){if(!e.execute)throw Error(`Tool "${e.name}" is client-side and cannot be re-exported publicly.`);let t=e.execute,n=e.inputSchema,r={description:e.description,execute:e=>t(e),inputSchema:n??{},outputSchema:e.outputSchema};return e.needsApproval!==void 0&&(r.needsApproval=e.needsApproval),e.onCompact!==void 0&&(r.onCompact=e.onCompact),r}export{toPublicToolDefinition};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{MockLanguageModelV3}from"ai/test";import{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT}from"#runtime/agent/bootstrap.js";import{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText}from"#runtime/agent/bootstrap-model-utils.js";import{findRelevantSkill,getActivatedSkillIds,getAvailableSkills}from"#runtime/agent/mock-model-skill-selection.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";const authoredRuntimeModelMocks=new Map,bootstrapWeatherPayloadSchema=z.object({city:z.string(),condition:z.string(),summary:z.string(),temperatureF:z.number().finite()}).strict(),ASH_MOCK_AUTHORED_MODELS_ENV=`ASH_MOCK_AUTHORED_MODELS`;function shouldMockAuthoredRuntimeModels(){return process.env.ASH_MOCK_AUTHORED_MODELS===`1`||process.env.NODE_ENV===`test`}function createMockAuthoredRuntimeModel(e){let t=authoredRuntimeModelMocks.get(e.id);if(t!==void 0)return t;let n=new MockLanguageModelV3({modelId:e.id,provider:`ash-runtime-mock`,doGenerate:async t=>createMockModelResult(t,e.id),doStream:async t=>createBootstrapStreamResult(createMockModelResult(t,e.id))});return authoredRuntimeModelMocks.set(e.id,n),n}function createMockModelResult(e,t){let n=getLastAuthoredToolResult(e.prompt);if(n!==null){let r=createFollowUpToolCallResult({modelId:t,options:e,result:n});if(r!==null)return r}else{let n=createSkillLoadResult(e.prompt,t)??createAuthoredToolCallResult(e,t);if(n!==null)return n}let r=createFinalOutputResult(e,t);if(r!==null)return r;let i=n===null?createAssistantMessage(e.prompt):formatToolResultReply(n,e.prompt);return createBootstrapGenerateResult({inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i),text:i})}function createFinalOutputResult(e,t){let r=getAvailableTools(e).find(e=>e.name===FINAL_OUTPUT_TOOL_NAME);if(r===void 0)return null;let i=createJsonSchemaSample(r.inputSchema);return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(JSON.stringify(i)),toolCallId:createToolCallId(FINAL_OUTPUT_TOOL_NAME),toolName:FINAL_OUTPUT_TOOL_NAME})}function resolveMockAuthoredRuntimeModel(e){return!shouldMockAuthoredRuntimeModels()||e.id===BOOTSTRAP_RUNTIME_MODEL_ID?null:createMockAuthoredRuntimeModel(e)}function createSkillLoadResult(e,t){let n=getLastUserPromptText(e);if(n===null||getActivatedSkillIds(e).length>0)return null;let r=findRelevantSkill(getAvailableSkills(e),n);return r===null?null:createToolCallGenerateResult({input:{skill:r.name},inputTokens:estimateTokenCount(getPromptText(e)),modelId:t,outputTokens:estimateTokenCount(r.name),toolCallId:`call_load_skill`,toolName:LOAD_SKILL_TOOL_NAME})}function createAuthoredToolCallResult(e,n){let r=getLastUserPromptText(e.prompt);if(r===null)return null;let i=findRelevantTool(getAvailableTools(e),r);if(i===null)return null;let a=resolveWeatherCity(r),o=createAuthoredToolInput(i,r,a);if(i.name===CODE_MODE_TOOL_NAME){let t=findRelevantCodeModeHostTool(i.description,r);if(t===null)return null;let o=`return await tools${formatCodeModeToolAccess(t)}({ city: ${JSON.stringify(a)} });`;return createToolCallGenerateResult({input:{js:o},inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:n,outputTokens:estimateTokenCount(o),toolCallId:createToolCallId(i.name),toolName:i.name})}return createToolCallGenerateResult({input:o,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:n,outputTokens:estimateTokenCount(Object.values(o).join(` `)),toolCallId:createToolCallId(i.name),toolName:i.name})}function createFollowUpToolCallResult(e){let t=findNextExplicitToolAfterResult({previousToolName:e.result.toolName,prompt:e.options.prompt,tools:getAvailableTools(e.options)});if(t===null)return null;let n=createFollowUpToolInput(e.result.output);return n===null?null:createToolCallGenerateResult({input:n,inputTokens:estimateTokenCount(getPromptText(e.options.prompt)),modelId:e.modelId,outputTokens:estimateTokenCount(Object.values(n).join(` `)),toolCallId:createToolCallId(t.name),toolName:t.name})}function createAuthoredToolInput(e,t,n){let r=getToolInputPropertyNames(e.inputSchema);return r.includes(`topic`)||/\btopic\b/u.test(normalizeText(t))?{topic:resolveLookupTopic(t)}:r.length===1&&r[0]===`message`?{message:t}:{city:n}}function createAssistantMessage(e){let t=getLastUserPromptText(e)??`Hello from Ash`,n=getSystemPromptLabels(e),r=resolveSystemProbe(e);return n.length>0?r===null?`Bootstrap reply [${n.join(`, `)}]: ${t}`:`Bootstrap reply [${n.join(`, `)}; probe=${r}]: ${t}`:r===null?`Bootstrap reply: ${t}`:`Bootstrap reply [probe=${r}]: ${t}`}function formatToolResultReply(e,t){if(e.isError)return`Local weather tool failed: ${formatToolOutput(e.output)}`;if(isWeatherPayload(e.output))return`Used local weather tool for ${e.output.city}: ${e.output.condition}, ${e.output.temperatureF}F. ${e.output.summary}`;let n=getLastUserPromptText(t)??`Hello from Ash`;return`Used ${e.toolName} for "${n}": ${formatToolOutput(e.output)}`}function createToolCallGenerateResult(e){return{content:[{input:JSON.stringify(e.input),toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-call`}],finishReason:{raw:void 0,unified:`tool-calls`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:new Date(`2026-03-16T00:00:00.000Z`)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function getAvailableTools(e){return(e.tools??[]).flatMap(e=>e.type===`function`?[{description:e.description,inputSchema:`inputSchema`in e?e.inputSchema:void 0,name:e.name}]:[])}function getLastAuthoredToolResult(e){for(let t of[...e].reverse()){if(t.role===`user`)return null;if(!(t.role!==`tool`&&t.role!==`assistant`)){for(let e of[...t.content].reverse())if(!(typeof e==`string`||e.type!==`tool-result`)&&e.toolName!==LOAD_SKILL_TOOL_NAME)return{isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,output:e.output.type===`execution-denied`?{reason:e.output.reason??null,type:e.output.type}:e.output.value,toolCallId:e.toolCallId,toolName:e.toolName}}}return null}function findNextExplicitToolAfterResult(e){let t=getLastUserPromptText(e.prompt);if(t===null)return null;let n=normalizeText(t),r=n.indexOf(normalizeText(e.previousToolName));return r<0?null:e.tools.filter(t=>t.name!==e.previousToolName).flatMap(e=>{let t=n.indexOf(normalizeText(e.name),r+1);return t<0?[]:[{index:t,tool:e}]}).sort((e,t)=>e.index-t.index)[0]?.tool??null}function createFollowUpToolInput(e){return isRecord(e)&&typeof e.stepKey==`string`?{stepKey:e.stepKey}:null}function getSystemPromptLabels(e){let t=e.filter(e=>e.role===`system`);if(t.length===0)return[];let n=t.flatMap(e=>{let t=getPromptContentText(e.content);if(t.startsWith(`Available skills
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{MockLanguageModelV3}from"ai/test";import{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT}from"#runtime/agent/bootstrap.js";import{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText}from"#runtime/agent/bootstrap-model-utils.js";import{findRelevantSkill,getActivatedSkillIds,getAvailableSkills}from"#runtime/agent/mock-model-skill-selection.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";const authoredRuntimeModelMocks=new Map,bootstrapWeatherPayloadSchema=z.object({city:z.string(),condition:z.string(),summary:z.string(),temperatureF:z.number().finite()}).strict(),ASH_MOCK_AUTHORED_MODELS_ENV=`ASH_MOCK_AUTHORED_MODELS`;function shouldMockAuthoredRuntimeModels(){return process.env.ASH_MOCK_AUTHORED_MODELS===`1`||process.env.NODE_ENV===`test`}function createMockAuthoredRuntimeModel(e){let t=authoredRuntimeModelMocks.get(e.id);if(t!==void 0)return t;let n=new MockLanguageModelV3({modelId:e.id,provider:`ash-runtime-mock`,doGenerate:async t=>createMockModelResult(t,e.id),doStream:async t=>createBootstrapStreamResult(createMockModelResult(t,e.id))});return authoredRuntimeModelMocks.set(e.id,n),n}function createMockModelResult(e,t){let n=getLastAuthoredToolResult(e.prompt);if(n!==null){let r=createFollowUpToolCallResult({modelId:t,options:e,result:n});if(r!==null)return r}else{let n=createSkillLoadResult(e.prompt,t)??createAuthoredToolCallResult(e,t);if(n!==null)return n}let r=createFinalOutputResult(e,t);if(r!==null)return r;let i=n===null?createAssistantMessage(e.prompt):formatToolResultReply(n,e.prompt);return createBootstrapGenerateResult({inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i),text:i})}function createFinalOutputResult(e,t){let r=getAvailableTools(e).find(e=>e.name===FINAL_OUTPUT_TOOL_NAME);if(r===void 0)return null;let i=createJsonSchemaSample(r.inputSchema);return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(JSON.stringify(i)),toolCallId:createToolCallId(FINAL_OUTPUT_TOOL_NAME),toolName:FINAL_OUTPUT_TOOL_NAME})}function resolveMockAuthoredRuntimeModel(e){return!shouldMockAuthoredRuntimeModels()||e.id===BOOTSTRAP_RUNTIME_MODEL_ID?null:createMockAuthoredRuntimeModel(e)}function createSkillLoadResult(e,t){let n=getLastUserPromptText(e);if(n===null||getActivatedSkillIds(e).length>0)return null;let r=findRelevantSkill(getAvailableSkills(e),n);return r===null?null:createToolCallGenerateResult({input:{skill:r.name},inputTokens:estimateTokenCount(getPromptText(e)),modelId:t,outputTokens:estimateTokenCount(r.name),toolCallId:`call_load_skill`,toolName:LOAD_SKILL_TOOL_NAME})}function createAuthoredToolCallResult(e,n){let r=getLastUserPromptText(e.prompt);if(r===null)return null;let i=findRelevantTool(getAvailableTools(e),r);if(i===null)return null;let a=resolveWeatherCity(r),o=createAuthoredToolInput(i,r,a);if(i.name===CODE_MODE_TOOL_NAME){let t=findRelevantCodeModeHostTool(i.description,r);if(t===null)return null;let o=`return await tools${formatCodeModeToolAccess(t)}({ city: ${JSON.stringify(a)} });`;return createToolCallGenerateResult({input:{js:o},inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:n,outputTokens:estimateTokenCount(o),toolCallId:createToolCallId(i.name),toolName:i.name})}return createToolCallGenerateResult({input:o,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:n,outputTokens:estimateTokenCount(Object.values(o).join(` `)),toolCallId:createToolCallId(i.name),toolName:i.name})}function createFollowUpToolCallResult(e){let t=findNextExplicitToolAfterResult({previousToolName:e.result.toolName,prompt:e.options.prompt,tools:getAvailableTools(e.options)});if(t===null)return null;let n=createFollowUpToolInput(e.result.output);return n===null?null:createToolCallGenerateResult({input:n,inputTokens:estimateTokenCount(getPromptText(e.options.prompt)),modelId:e.modelId,outputTokens:estimateTokenCount(Object.values(n).join(` `)),toolCallId:createToolCallId(t.name),toolName:t.name})}function createAuthoredToolInput(e,t,n){let r=getToolInputPropertyNames(e.inputSchema);return r.includes(`topic`)||/\btopic\b/u.test(normalizeText(t))?{topic:resolveLookupTopic(t)}:r.length===1&&r[0]===`message`?{message:t}:{city:n}}function createAssistantMessage(e){let t=getLastUserPromptText(e)??`Hello from Ash`,n=getSystemPromptLabels(e),r=resolveSystemProbe(e);return n.length>0?r===null?`Bootstrap reply [${n.join(`, `)}]: ${t}`:`Bootstrap reply [${n.join(`, `)}; probe=${r}]: ${t}`:r===null?`Bootstrap reply: ${t}`:`Bootstrap reply [probe=${r}]: ${t}`}function formatToolResultReply(e,t){if(e.isError)return`Local weather tool failed: ${formatToolOutput(e.output)}`;if(isWeatherPayload(e.output))return`Used local weather tool for ${e.output.city}: ${e.output.condition}, ${e.output.temperatureF}F. ${e.output.summary}`;let n=getLastUserPromptText(t)??`Hello from Ash`;return`Used ${e.toolName} for "${n}": ${formatToolOutput(e.output)}`}function createToolCallGenerateResult(e){return{content:[{input:JSON.stringify(e.input),toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-call`}],finishReason:{raw:void 0,unified:`tool-calls`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:new Date(`2026-03-16T00:00:00.000Z`)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function getAvailableTools(e){return(e.tools??[]).flatMap(e=>e.type===`function`?[{description:e.description,inputSchema:`inputSchema`in e?e.inputSchema:void 0,name:e.name,outputSchema:`outputSchema`in e?e.outputSchema:void 0}]:[])}function getLastAuthoredToolResult(e){for(let t of[...e].reverse()){if(t.role===`user`)return null;if(!(t.role!==`tool`&&t.role!==`assistant`)){for(let e of[...t.content].reverse())if(!(typeof e==`string`||e.type!==`tool-result`)&&e.toolName!==LOAD_SKILL_TOOL_NAME)return{isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,output:e.output.type===`execution-denied`?{reason:e.output.reason??null,type:e.output.type}:e.output.value,toolCallId:e.toolCallId,toolName:e.toolName}}}return null}function findNextExplicitToolAfterResult(e){let t=getLastUserPromptText(e.prompt);if(t===null)return null;let n=normalizeText(t),r=n.indexOf(normalizeText(e.previousToolName));return r<0?null:e.tools.filter(t=>t.name!==e.previousToolName).flatMap(e=>{let t=n.indexOf(normalizeText(e.name),r+1);return t<0?[]:[{index:t,tool:e}]}).sort((e,t)=>e.index-t.index)[0]?.tool??null}function createFollowUpToolInput(e){return isRecord(e)&&typeof e.stepKey==`string`?{stepKey:e.stepKey}:null}function getSystemPromptLabels(e){let t=e.filter(e=>e.role===`system`);if(t.length===0)return[];let n=t.flatMap(e=>{let t=getPromptContentText(e.content);if(t.startsWith(`Available skills
|
|
2
2
|
`))return[];let n=t.split(`
|
|
3
3
|
`).map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of n){if(e===BOOTSTRAP_RUNTIME_SYSTEM_PROMPT||e===`Available skills`)continue;let t=/^System \((.+)\)$/.exec(e);if(t?.[1]){r.push(t[1]);continue}let n=/^Skill \((.+)\)$/.exec(e);n?.[1]&&r.push(n[1])}if(r.length>0)return r;let i=n.find(e=>e!==BOOTSTRAP_RUNTIME_SYSTEM_PROMPT&&e!==`Available skills`);return i===void 0?[]:[i]});return[...new Set(n)]}function getToolInputPropertyNames(e){return!isRecord(e)||!isRecord(e.properties)?[]:Object.keys(e.properties)}function findRelevantTool(e,t){let n=normalizeText(t),r=e.find(e=>n.includes(normalizeText(e.name)));return r===void 0?/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(n)?e.find(e=>/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(normalizeText(`${e.name} ${e.description??``}`)))??null:null:r}function findRelevantCodeModeHostTool(e,t){return e===void 0?null:findRelevantTool(parseCodeModeHostTools(e),t)?.name??null}function parseCodeModeHostTools(e){let t=[],n;for(let r of e.split(`
|
|
4
4
|
`)){let e=/^\s*\/\*\*\s*(.*?)\s*\*\/\s*$/u.exec(r);if(e?.[1]!==void 0){n=e[1];continue}let i=/^\s*(?:([$A-Z_a-z][$\w]*)|(["'])(.*?)\2)\s*:\s*\(input:/u.exec(r),a=i?.[1]??i?.[3];a!==void 0&&(t.push({description:n,name:a}),n=void 0)}return t}function formatCodeModeToolAccess(e){return/^[$A-Z_a-z][$\w]*$/u.test(e)?`.${e}`:`[${JSON.stringify(e)}]`}function normalizeText(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,` `).trim()}function createToolCallId(e){return`call_${e.toLowerCase().replace(/[^a-z0-9]+/gu,`_`).replace(/^_+|_+$/gu,``)||`tool`}`}function resolveSystemProbe(e){let t=e.filter(e=>e.role===`system`).map(e=>getPromptContentText(e.content)).join(`
|
|
@@ -41,3 +41,11 @@ export declare function readCachedToken(ctx: AlsContext, connectionName: string,
|
|
|
41
41
|
* into the durable step payload. See the module docblock.
|
|
42
42
|
*/
|
|
43
43
|
export declare function writeCachedToken(ctx: AlsContext, connectionName: string, principalKey: string, token: TokenResult): void;
|
|
44
|
+
/**
|
|
45
|
+
* Drops the cached {@link TokenResult} for `(connectionName, principalKey)`,
|
|
46
|
+
* if present. Used when the remote server rejects an already-resolved
|
|
47
|
+
* bearer (HTTP 401) so the subsequent re-authorization attempt does not
|
|
48
|
+
* re-read the stale token from the per-step cache. No-op when nothing is
|
|
49
|
+
* cached for the principal.
|
|
50
|
+
*/
|
|
51
|
+
export declare function evictCachedToken(ctx: AlsContext, connectionName: string, principalKey: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ContextKey}from"#context/key.js";const ConnectionAuthorizationTokensKey=new ContextKey(`ash.connectionAuthorizationTokens`);function readCachedToken(e,t,n){let r=e.get(ConnectionAuthorizationTokensKey)?.[t]?.[n];if(r!==void 0&&!(r.expiresAt!==void 0&&r.expiresAt<=Date.now()))return r}function writeCachedToken(e,t,n,r){let i=e.get(ConnectionAuthorizationTokensKey)??{},a=i[t]??{};asContainer(e).setVirtualContext(ConnectionAuthorizationTokensKey,{...i,[t]:{...a,[n]:r}})}function asContainer(e){return e}export{ConnectionAuthorizationTokensKey,readCachedToken,writeCachedToken};
|
|
1
|
+
import{ContextKey}from"#context/key.js";const ConnectionAuthorizationTokensKey=new ContextKey(`ash.connectionAuthorizationTokens`);function readCachedToken(e,t,n){let r=e.get(ConnectionAuthorizationTokensKey)?.[t]?.[n];if(r!==void 0&&!(r.expiresAt!==void 0&&r.expiresAt<=Date.now()))return r}function writeCachedToken(e,t,n,r){let i=e.get(ConnectionAuthorizationTokensKey)??{},a=i[t]??{};asContainer(e).setVirtualContext(ConnectionAuthorizationTokensKey,{...i,[t]:{...a,[n]:r}})}function evictCachedToken(e,t,n){let r=e.get(ConnectionAuthorizationTokensKey),i=r?.[t];if(r===void 0||i===void 0||i[n]===void 0)return;let{[n]:a,...o}=i;asContainer(e).setVirtualContext(ConnectionAuthorizationTokensKey,{...r,[t]:o})}function asContainer(e){return e}export{ConnectionAuthorizationTokensKey,evictCachedToken,readCachedToken,writeCachedToken};
|
|
@@ -38,10 +38,24 @@ export declare class McpConnectionClient implements ConnectionClient {
|
|
|
38
38
|
/**
|
|
39
39
|
* Executes a named tool through the AI SDK's tool executor, which
|
|
40
40
|
* handles the JSON-RPC `tools/call` internally.
|
|
41
|
+
*
|
|
42
|
+
* A `401`/`invalid_token` from the remote server is translated into
|
|
43
|
+
* {@link ConnectionAuthorizationRequiredError} via {@link #rethrowClassified}
|
|
44
|
+
* so callers re-enter the authorization flow instead of surfacing an
|
|
45
|
+
* opaque transport error.
|
|
41
46
|
*/
|
|
42
47
|
executeTool(toolName: string, args: unknown): Promise<unknown>;
|
|
43
48
|
close(): Promise<void>;
|
|
44
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Returns `true` when an error from the MCP transport indicates the
|
|
52
|
+
* bearer was rejected by the remote server — an HTTP `401`. Per
|
|
53
|
+
* RFC 6750 a `401` means the access token is missing, expired, or
|
|
54
|
+
* revoked, all of which are recoverable by re-authorizing. (A `403`
|
|
55
|
+
* is an insufficient-scope / permission problem and is intentionally
|
|
56
|
+
* left to propagate, since re-running the same grant would not help.)
|
|
57
|
+
*/
|
|
58
|
+
export declare function isMcpAuthRequiredError(error: unknown): boolean;
|
|
45
59
|
/**
|
|
46
60
|
* Returns `true` when a tool name passes the configured filter.
|
|
47
61
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{contextStorage}from"#context/container.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{readCachedToken,writeCachedToken}from"#runtime/connections/authorization-tokens.js";import{principalKey,resolveConnectionPrincipal}from"#runtime/connections/principal.js";var McpConnectionClient=class{#e;#t;#n;#r;#i;constructor(e){this.#i=e}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#a();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#a(){let e=await resolveHeaders(this.#i),t=this.#i.url;try{return await createMCPClient({transport:{type:`http`,url:t,headers:e}})}catch(
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{contextStorage}from"#context/container.js";import{ConnectionAuthorizationRequiredError}from"#public/connections/errors.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{evictCachedToken,readCachedToken,writeCachedToken}from"#runtime/connections/authorization-tokens.js";import{principalKey,resolveConnectionPrincipal}from"#runtime/connections/principal.js";var McpConnectionClient=class{#e;#t;#n;#r;#i;constructor(e){this.#i=e}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#a();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#a(){let e=await resolveHeaders(this.#i),t=this.#i.url;try{return await createMCPClient({transport:{type:`http`,url:t,headers:e}})}catch(n){if(!isMcpHttpFallbackRetryableError(n))throw n;return await createMCPClient({transport:{type:`sse`,url:t,headers:e}})}}async getToolMetadata(){return(await this.#o()).metadata}async getTools(){return(await this.#o()).tools}async executeTool(e,t){try{let{tools:n}=await this.#o(),r=n[e];if(r?.execute===void 0)throw Error(`Tool "${e}" not found in connection "${this.#i.connectionName}".`);return await r.execute(t,{})}catch(e){return await this.#l(e)}}async#o(){if(this.#r!==void 0)return this.#r;if(this.#n!==void 0)return this.#n;this.#n=this.#s();try{return this.#r=await this.#n,this.#r}catch(e){throw this.#n=void 0,e}}async#s(){try{return await this.#c()}catch(e){return await this.#l(e)}}async#c(){let e=await this.connect(),t=await e.listTools(),n=this.#i.tools,r=n===void 0?t.tools:t.tools.filter(e=>passesToolFilter(e.name,n)),i=e.toolsFromDefinitions({tools:r});return{metadata:r.map(e=>({annotations:e.annotations,description:e.description??``,inputSchema:e.inputSchema??{},name:e.name,outputSchema:`outputSchema`in e&&e.outputSchema!==void 0?e.outputSchema:void 0})),tools:i}}async close(){this.#t!==void 0&&(await this.#t.close(),this.#t=void 0),this.#e=void 0,this.#n=void 0,this.#r=void 0}async#l(e){throw isMcpAuthRequiredError(e)?(this.#u(),await this.close(),new ConnectionAuthorizationRequiredError(this.#i.connectionName,{message:`Connection "${this.#i.connectionName}" requires authorization (the server rejected the token).`})):e}#u(){let e=this.#i.authorization;if(e===void 0)return;let n=contextStorage.getStore();if(n!==void 0)try{let t=resolveConnectionPrincipal(this.#i.connectionName,e,n);evictCachedToken(n,this.#i.connectionName,principalKey(t))}catch{}}};function isMcpAuthRequiredError(e){return readHttpStatus(e)===401}function isMcpHttpFallbackRetryableError(e){let t=readHttpStatus(e);return t===400||t===404||t===405}function readHttpStatus(t){for(let n of walkErrorChain(t)){if(!isObject(n))continue;let t=readStatusField(n);if(t!==void 0)return t;let r=n.response;if(isObject(r)){let e=readStatusField(r);if(e!==void 0)return e}if(typeof n.message==`string`){let e=/\bHTTP\s+(\d{3})\b/u.exec(n.message);if(e?.[1]!==void 0)return Number(e[1])}}}function readStatusField(e){if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode}function*walkErrorChain(t){let n=t,r=new Set;for(;n!=null&&!r.has(n);){if(r.add(n),yield n,!isObject(n)||!(`cause`in n))return;n=n.cause}}function passesToolFilter(e,t){return t===void 0?!0:`allow`in t?t.allow.includes(e):!t.block.includes(e)}async function resolveHeaders(e){let t={};if(e.authorization!==void 0&&(t.Authorization=`Bearer ${(await resolveToken(e)).token}`),e.headers!==void 0){let n=await resolveHeadersDefinition(e.headers);for(let[r,i]of Object.entries(n)){if(e.authorization!==void 0&&r.toLowerCase()===`authorization`)throw Error(`Connection "${e.connectionName}" headers must not include an "Authorization" key when "authorization" is also provided.`);t[r]=i}}return t}async function resolveToken(e){if(e.authorization===void 0)throw Error(`Connection "${e.connectionName}" does not define authorization.`);let n=contextStorage.getStore(),r=resolveConnectionPrincipal(e.connectionName,e.authorization,n),i={url:e.url};if(n===void 0)return await e.authorization.getToken({principal:r,connection:i});let a=principalKey(r),o=readCachedToken(n,e.connectionName,a);if(o!==void 0)return o;let s=await e.authorization.getToken({principal:r,connection:i});return writeCachedToken(n,e.connectionName,a,s),s}async function resolveHeadersDefinition(e){if(typeof e==`function`)return await e();let t={},n=Object.entries(e);for(let[e,r]of n)t[e]=await resolveHeaderValue(r);return t}async function resolveHeaderValue(e){return typeof e==`function`?await e():await e}export{McpConnectionClient,isMcpAuthRequiredError,passesToolFilter,resolveHeaders};
|
|
@@ -290,6 +290,7 @@ export interface ConnectionToolMetadata {
|
|
|
290
290
|
readonly description: string;
|
|
291
291
|
readonly inputSchema: Record<string, unknown>;
|
|
292
292
|
readonly name: string;
|
|
293
|
+
readonly outputSchema?: Record<string, unknown>;
|
|
293
294
|
}
|
|
294
295
|
/** A live client for a single connection. */
|
|
295
296
|
export interface ConnectionClient {
|
|
@@ -8,6 +8,10 @@ export declare const ASK_QUESTION_TOOL_NAME = "ask_question";
|
|
|
8
8
|
* Shared input schema used by the framework `ask_question` tool.
|
|
9
9
|
*/
|
|
10
10
|
export declare const ASK_QUESTION_INPUT_SCHEMA: JsonObject;
|
|
11
|
+
/**
|
|
12
|
+
* Shared output schema used by the framework `ask_question` tool.
|
|
13
|
+
*/
|
|
14
|
+
export declare const ASK_QUESTION_OUTPUT_SCHEMA: JsonObject;
|
|
11
15
|
/**
|
|
12
16
|
* Root-only framework tool that lets the agent request structured user input.
|
|
13
17
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{inputRequestSchema}from"#runtime/input/types.js";const ASK_QUESTION_TOOL_NAME=`ask_question`,askQuestionToolInputSchema=inputRequestSchema.omit({action:!0,display:!0,requestId:!0}),{$schema:_jsonSchemaVersion,...askQuestionInputSchema}=z.toJSONSchema(askQuestionToolInputSchema),ASK_QUESTION_INPUT_SCHEMA=askQuestionInputSchema,ASK_QUESTION_TOOL_DEFINITION={description:`Ask the user a question and wait for their response before continuing. Use this when you need clarification or a choice from the user.`,inputSchema:ASK_QUESTION_INPUT_SCHEMA,logicalPath:`ash:framework/ask-question`,name:ASK_QUESTION_TOOL_NAME,sourceId:`ash:ask-question-tool`,sourceKind:`module`};export{ASK_QUESTION_INPUT_SCHEMA,ASK_QUESTION_TOOL_DEFINITION,ASK_QUESTION_TOOL_NAME};
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{inputRequestSchema}from"#runtime/input/types.js";const ASK_QUESTION_TOOL_NAME=`ask_question`,askQuestionToolInputSchema=inputRequestSchema.omit({action:!0,display:!0,requestId:!0}),{$schema:_jsonSchemaVersion,...askQuestionInputSchema}=z.toJSONSchema(askQuestionToolInputSchema),askQuestionToolOutputSchema=z.object({optionId:z.string().optional(),status:z.enum([`answered`,`ignored`]),text:z.string().optional()}).strict(),{$schema:_outputJsonSchemaVersion,...askQuestionOutputSchema}=z.toJSONSchema(askQuestionToolOutputSchema),ASK_QUESTION_INPUT_SCHEMA=askQuestionInputSchema,ASK_QUESTION_OUTPUT_SCHEMA=askQuestionOutputSchema,ASK_QUESTION_TOOL_DEFINITION={description:`Ask the user a question and wait for their response before continuing. Use this when you need clarification or a choice from the user.`,inputSchema:ASK_QUESTION_INPUT_SCHEMA,logicalPath:`ash:framework/ask-question`,name:ASK_QUESTION_TOOL_NAME,outputSchema:ASK_QUESTION_OUTPUT_SCHEMA,sourceId:`ash:ask-question-tool`,sourceKind:`module`};export{ASK_QUESTION_INPUT_SCHEMA,ASK_QUESTION_OUTPUT_SCHEMA,ASK_QUESTION_TOOL_DEFINITION,ASK_QUESTION_TOOL_NAME};
|
|
@@ -9,4 +9,9 @@ import type { ResolvedToolDefinition } from "#runtime/types.js";
|
|
|
9
9
|
* input contracts in sync without duplication.
|
|
10
10
|
*/
|
|
11
11
|
export declare const BASH_INPUT_SCHEMA: JsonObject;
|
|
12
|
+
/**
|
|
13
|
+
* Shared output schema used by the framework `bash` tool and any author tool
|
|
14
|
+
* constructed via {@link defineBashTool}.
|
|
15
|
+
*/
|
|
16
|
+
export declare const BASH_OUTPUT_SCHEMA: JsonObject;
|
|
12
17
|
export declare const BASH_TOOL_DEFINITION: ResolvedToolDefinition;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeBashOnSandbox}from"#execution/sandbox/bash-tool.js";const BASH_INPUT_SCHEMA={additionalProperties:!1,properties:{command:{description:`The shell command to execute.`,type:`string`}},required:[`command`],type:`object`};async function executeBash(e){return executeBashOnSandbox(await requireSandboxSession(),e)}const BASH_TOOL_DEFINITION={description:`Execute a shell command in the shared workspace environment.`,execute:executeBash,inputSchema:BASH_INPUT_SCHEMA,logicalPath:`ash:framework/bash`,name:`bash`,sourceId:`ash:bash-tool`,sourceKind:`module`};export{BASH_INPUT_SCHEMA,BASH_TOOL_DEFINITION};
|
|
1
|
+
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeBashOnSandbox}from"#execution/sandbox/bash-tool.js";const BASH_INPUT_SCHEMA={additionalProperties:!1,properties:{command:{description:`The shell command to execute.`,type:`string`}},required:[`command`],type:`object`},BASH_OUTPUT_SCHEMA={additionalProperties:!1,properties:{exitCode:{type:`number`},stderr:{type:`string`},stdout:{type:`string`},truncated:{type:`boolean`}},required:[`exitCode`,`stderr`,`stdout`,`truncated`],type:`object`};async function executeBash(e){return executeBashOnSandbox(await requireSandboxSession(),e)}const BASH_TOOL_DEFINITION={description:`Execute a shell command in the shared workspace environment.`,execute:executeBash,inputSchema:BASH_INPUT_SCHEMA,logicalPath:`ash:framework/bash`,name:`bash`,outputSchema:BASH_OUTPUT_SCHEMA,sourceId:`ash:bash-tool`,sourceKind:`module`};export{BASH_INPUT_SCHEMA,BASH_OUTPUT_SCHEMA,BASH_TOOL_DEFINITION};
|
|
@@ -7,6 +7,7 @@ interface ConnectionSearchResultItem {
|
|
|
7
7
|
readonly error?: string;
|
|
8
8
|
readonly inputSchema?: Record<string, unknown>;
|
|
9
9
|
readonly needsAuthorization?: boolean;
|
|
10
|
+
readonly outputSchema?: Record<string, unknown>;
|
|
10
11
|
readonly tool?: string;
|
|
11
12
|
readonly qualifiedName?: string;
|
|
12
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";import{ConnectionRegistryKey}from"#context/providers/connection.js";import{getAuthorizationResult,getHookUrl,requestAuthorization}from"#harness/authorization.js";import{supportsInteractiveAuthorization}from"#runtime/connections/types.js";import{isConnectionAuthorizationFailedError,isConnectionAuthorizationRequiredError}from"#public/connections/errors.js";import{writeCachedToken}from"#runtime/connections/authorization-tokens.js";import{principalKey,resolveConnectionPrincipal}from"#runtime/connections/principal.js";const logger=createLogger(`framework.connection-search-dynamic`),ConnectionSearchResultsKey=new ContextKey(`ash.connectionSearchResults`);function qualifiedConnectionToolName(e,t){return`${e}__${t}`}function tokenize(e){return e.toLowerCase().split(/[\s_\-./]+/).filter(e=>e.length>1)}function scoreMatch(e,t){let n=tokenize(t.name),r=tokenize(t.description),i=0;for(let t of e){for(let e of n)(e.includes(t)||t.includes(e))&&(i+=3);for(let e of r)(e.includes(t)||t.includes(e))&&(i+=1)}return i}function resolveInteractiveAuth(e,t){let n=e.getConnections().find(e=>e.connectionName===t);if(n?.authorization&&supportsInteractiveAuthorization(n.authorization))return n.authorization}async function completePendingAuthorizations(e){let n=loadContext();for(let t of e.getConnections()){let
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";import{ConnectionRegistryKey}from"#context/providers/connection.js";import{getAuthorizationResult,getHookUrl,requestAuthorization}from"#harness/authorization.js";import{supportsInteractiveAuthorization}from"#runtime/connections/types.js";import{ConnectionAuthorizationFailedError,isConnectionAuthorizationFailedError,isConnectionAuthorizationRequiredError}from"#public/connections/errors.js";import{writeCachedToken}from"#runtime/connections/authorization-tokens.js";import{principalKey,resolveConnectionPrincipal}from"#runtime/connections/principal.js";const logger=createLogger(`framework.connection-search-dynamic`),CONNECTION_SEARCH_OUTPUT_SCHEMA={items:{additionalProperties:!1,properties:{connection:{type:`string`},description:{type:`string`},error:{type:`string`},inputSchema:{type:`object`},needsAuthorization:{type:`boolean`},outputSchema:{type:`object`},qualifiedName:{type:`string`},tool:{type:`string`}},required:[`connection`,`description`],type:`object`},type:`array`},ConnectionSearchResultsKey=new ContextKey(`ash.connectionSearchResults`);function qualifiedConnectionToolName(e,t){return`${e}__${t}`}function tokenize(e){return e.toLowerCase().split(/[\s_\-./]+/).filter(e=>e.length>1)}function scoreMatch(e,t){let n=tokenize(t.name),r=tokenize(t.description),i=0;for(let t of e){for(let e of n)(e.includes(t)||t.includes(e))&&(i+=3);for(let e of r)(e.includes(t)||t.includes(e))&&(i+=1)}return i}function resolveInteractiveAuth(e,t){let n=e.getConnections().find(e=>e.connectionName===t);if(n?.authorization&&supportsInteractiveAuthorization(n.authorization))return n.authorization}async function completePendingAuthorizations(e){let n=loadContext(),r=new Set;for(let t of e.getConnections()){let a=getAuthorizationResult(t.connectionName);if(!a)continue;let o=resolveInteractiveAuth(e,t.connectionName);if(!o)continue;let s=resolveConnectionPrincipal(t.connectionName,o),c=await o.completeAuthorization({callbackUrl:a.hookUrl,connection:{url:t.url??``},principal:s,request:a.callback,state:a.state});writeCachedToken(n,t.connectionName,principalKey(s),c),r.add(t.connectionName)}return r}async function executeConnectionSearch(e){let n=loadContext(),i=n.get(ConnectionRegistryKey);if(i===void 0)return[];let s=await completePendingAuthorizations(i),c=e.limit??10,u=tokenize(e.keywords),d=[],p=[],h=e.connection!==void 0&&e.connection!==``?i.getConnections().filter(t=>t.connectionName===e.connection):i.getConnections(),g=[];for(let e of h){let t;try{t=await i.getClient(e.connectionName).getToolMetadata()}catch(t){if(isConnectionAuthorizationRequiredError(t)){if(s.has(e.connectionName)){logger.warn(`connection still unauthorized after authorization`,{connection:e.connectionName}),p.push({connection:e.connectionName,description:e.description,error:`Authorization for "${e.connectionName}" did not take effect; the token was rejected after sign-in.`});continue}let t=resolveInteractiveAuth(i,e.connectionName);if(t){let n=getHookUrl(e.connectionName);if(n){let r=resolveConnectionPrincipal(e.connectionName,t);try{let{challenge:i,state:a}=await t.startAuthorization({callbackUrl:n,connection:{url:e.url??``},principal:r});g.push({name:e.connectionName,challenge:i,hookUrl:n,state:a})}catch(t){logger.warn(`startAuthorization failed`,{connection:e.connectionName,error:t instanceof Error?t:Error(String(t))})}}}p.push({connection:e.connectionName,description:e.description,needsAuthorization:!0});continue}if(isConnectionAuthorizationFailedError(t)){logger.warn(`connection authorization failed`,{connection:e.connectionName,reason:t.reason,retryable:t.retryable,error:t}),p.push({connection:e.connectionName,description:e.description,error:`Authorization failed for ${e.connectionName}: ${t.message}`});continue}let n=t instanceof Error?t.message:`unknown error`;logger.warn(`failed to load connection tools`,{connection:e.connectionName,error:t instanceof Error?t:Error(n)}),p.push({connection:e.connectionName,description:e.description,error:`Failed to load tools for "${e.connectionName}": ${n}`});continue}for(let n of t){let t=scoreMatch(u,n);t>0&&d.push({item:{connection:e.connectionName,description:n.description,inputSchema:n.inputSchema,outputSchema:n.outputSchema,qualifiedName:`connection__${qualifiedConnectionToolName(e.connectionName,n.name)}`,tool:n.name},score:t})}}if(g.length>0)return requestAuthorization(g);d.sort((e,t)=>t.score-e.score);let _=d.slice(0,c).map(e=>e.item);if(_.length>0){let e=[..._,...p],t=n.get(ConnectionSearchResultsKey)??[],r=new Map(t.map(e=>[e.qualifiedName,e]));for(let e of _)e.qualifiedName&&r.set(e.qualifiedName,e);return n.set(ConnectionSearchResultsKey,[...r.values()]),e}return h.map(e=>p.find(t=>t.connection===e.connectionName)||{connection:e.connectionName,description:e.description})}function extractDiscoveredTools(e){let t=new Map;for(let n of e){if(n.role!==`tool`)continue;let e=n.content;for(let n of e){if(n.type!==`tool-result`||n.toolName!==`connection__search`)continue;let e=n.output;if(e==null)continue;let r=typeof e==`object`&&`type`in e&&`value`in e?e.value:e;if(Array.isArray(r))for(let e of r)e.tool&&e.qualifiedName&&t.set(e.qualifiedName,e)}}return[...t.values()]}function createConnectionSearchEvents(){return{"step.started":async(e,n)=>{let l=loadContext().get(ConnectionRegistryKey);if(!l||l.getConnections().length===0)return null;let f=l.getConnections().map(e=>e.connectionName),h=extractDiscoveredTools(n.messages),g=loadContext().get(ConnectionSearchResultsKey)??[],_=new Map;for(let e of g)e.qualifiedName&&_.set(e.qualifiedName,e);for(let e of h)e.qualifiedName&&_.set(e.qualifiedName,e);let v=[..._.values()],y={};y.search={description:`Search for tools across your connections. Discovered tools become directly callable by their qualified name (e.g. \`connection__linear__list_issues\`) in your next response. Available connections: ${f.join(`, `)}.`,inputSchema:{type:`object`,additionalProperties:!1,properties:{keywords:{description:`Search keywords and expanded aliases. Distill intent into keywords; avoid stop words like 'a', 'the', 'in'.`,type:`string`},connection:{description:`Optional: limit search to a specific connection name.`,type:`string`},limit:{description:`Max results to return. Default 10.`,type:`number`}},required:[`keywords`]},async execute(e){return executeConnectionSearch(e)},outputSchema:CONNECTION_SEARCH_OUTPUT_SCHEMA};for(let e of v){let n=e.connection,f=e.tool,p=l.getConnectionApproval(n);y[qualifiedConnectionToolName(n,f)]={description:e.description,inputSchema:e.inputSchema??{type:`object`},needsApproval:p,outputSchema:e.outputSchema,async execute(e){let l=loadContext().get(ConnectionRegistryKey),p=l.getConnections().find(e=>e.connectionName===n),m=p?.authorization&&supportsInteractiveAuthorization(p.authorization)?p.authorization:void 0,h=!1;if(m){let e=getAuthorizationResult(n);if(e){h=!0;let r=loadContext(),i=resolveConnectionPrincipal(n,m),a=await m.completeAuthorization({callbackUrl:e.hookUrl,connection:{url:p?.url??``},principal:i,request:e.callback,state:e.state});writeCachedToken(r,n,principalKey(i),a)}}try{return await l.getClient(n).executeTool(f,e)}catch(e){if(!isConnectionAuthorizationRequiredError(e)||!m)throw e;if(h)throw new ConnectionAuthorizationFailedError(n,{retryable:!1,reason:`token_rejected_after_authorization`,message:`Connection "${n}" rejected the token immediately after authorization.`});let t=getHookUrl(n);if(!t)throw e;let r=resolveConnectionPrincipal(n,m),{challenge:i,state:s}=await m.startAuthorization({callbackUrl:t,connection:{url:p?.url??``},principal:r});return requestAuthorization([{name:n,challenge:i,hookUrl:t,state:s}])}}}}return y}}}function createConnectionSearchResolver(){let e=createConnectionSearchEvents();return{slug:`connection`,eventNames:Object.keys(e),events:e,sourceId:`ash:connection-search-dynamic`,sourceKind:`module`,logicalPath:`ash:framework/connection-search-dynamic`}}export{createConnectionSearchEvents,createConnectionSearchResolver,extractDiscoveredTools};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsonSchema}from"ai";const FINAL_OUTPUT_TOOL_NAME=`final_output`;function buildFinalOutputTool(e){return{description:`Deliver your final answer in the required structure by calling this tool. Call it exactly once, when you are done; do not answer in prose.`,inputSchema:jsonSchema(e)}}export{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool};
|
|
1
|
+
import{jsonSchema}from"ai";const FINAL_OUTPUT_TOOL_NAME=`final_output`;function buildFinalOutputTool(e){return{description:`Deliver your final answer in the required structure by calling this tool. Call it exactly once, when you are done; do not answer in prose.`,inputSchema:jsonSchema(e),outputSchema:jsonSchema(e)}}export{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool};
|
|
@@ -9,4 +9,9 @@ import type { ResolvedToolDefinition } from "#runtime/types.js";
|
|
|
9
9
|
* input contracts in sync without duplication.
|
|
10
10
|
*/
|
|
11
11
|
export declare const GLOB_INPUT_SCHEMA: JsonObject;
|
|
12
|
+
/**
|
|
13
|
+
* Shared output schema used by the framework `glob` tool and any author tool
|
|
14
|
+
* constructed via {@link defineGlobTool}.
|
|
15
|
+
*/
|
|
16
|
+
export declare const GLOB_OUTPUT_SCHEMA: JsonObject;
|
|
12
17
|
export declare const GLOB_TOOL_DEFINITION: ResolvedToolDefinition;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeGlobOnSandbox}from"#execution/sandbox/glob-tool.js";const GLOB_INPUT_SCHEMA={additionalProperties:!1,properties:{limit:{description:`Maximum number of results to return. Defaults to 100.`,maximum:1e3,minimum:1,type:`integer`},path:{description:`The directory to search in. Defaults to /workspace. Must be an absolute path. Omit to use the default.`,type:`string`},pattern:{description:`The glob pattern to match files against (e.g. "**/*.ts", "src/**/*.js").`,type:`string`}},required:[`pattern`],type:`object`};async function executeGlob(e){return executeGlobOnSandbox(await requireSandboxSession(),e)}const GLOB_TOOL_DEFINITION={description:[`Fast file pattern matching tool that works with any codebase size.`,``,`Usage:`,`- Supports glob patterns like "**/*.js" or "src/**/*.ts".`,`- Returns matching file paths.`,`- Use this tool when you need to find files by name patterns.`,`- If you are unsure of the correct file path, use the glob tool to look up filenames by glob pattern.`,`- Use the grep tool instead if you need to search file contents.`,`- Call this tool in parallel when you know there are multiple patterns to search for.`].join(`
|
|
2
|
-
`),execute:executeGlob,inputSchema:GLOB_INPUT_SCHEMA,logicalPath:`ash:framework/glob`,name:`glob`,sourceId:`ash:glob-tool`,sourceKind:`module`};export{GLOB_INPUT_SCHEMA,GLOB_TOOL_DEFINITION};
|
|
1
|
+
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeGlobOnSandbox}from"#execution/sandbox/glob-tool.js";const GLOB_INPUT_SCHEMA={additionalProperties:!1,properties:{limit:{description:`Maximum number of results to return. Defaults to 100.`,maximum:1e3,minimum:1,type:`integer`},path:{description:`The directory to search in. Defaults to /workspace. Must be an absolute path. Omit to use the default.`,type:`string`},pattern:{description:`The glob pattern to match files against (e.g. "**/*.ts", "src/**/*.js").`,type:`string`}},required:[`pattern`],type:`object`},GLOB_OUTPUT_SCHEMA={additionalProperties:!1,properties:{content:{type:`string`},count:{type:`integer`},path:{type:`string`},truncated:{type:`boolean`}},required:[`content`,`count`,`path`,`truncated`],type:`object`};async function executeGlob(e){return executeGlobOnSandbox(await requireSandboxSession(),e)}const GLOB_TOOL_DEFINITION={description:[`Fast file pattern matching tool that works with any codebase size.`,``,`Usage:`,`- Supports glob patterns like "**/*.js" or "src/**/*.ts".`,`- Returns matching file paths.`,`- Use this tool when you need to find files by name patterns.`,`- If you are unsure of the correct file path, use the glob tool to look up filenames by glob pattern.`,`- Use the grep tool instead if you need to search file contents.`,`- Call this tool in parallel when you know there are multiple patterns to search for.`].join(`
|
|
2
|
+
`),execute:executeGlob,inputSchema:GLOB_INPUT_SCHEMA,logicalPath:`ash:framework/glob`,name:`glob`,outputSchema:GLOB_OUTPUT_SCHEMA,sourceId:`ash:glob-tool`,sourceKind:`module`};export{GLOB_INPUT_SCHEMA,GLOB_OUTPUT_SCHEMA,GLOB_TOOL_DEFINITION};
|
|
@@ -9,4 +9,9 @@ import type { ResolvedToolDefinition } from "#runtime/types.js";
|
|
|
9
9
|
* input contracts in sync without duplication.
|
|
10
10
|
*/
|
|
11
11
|
export declare const GREP_INPUT_SCHEMA: JsonObject;
|
|
12
|
+
/**
|
|
13
|
+
* Shared output schema used by the framework `grep` tool and any author tool
|
|
14
|
+
* constructed via {@link defineGrepTool}.
|
|
15
|
+
*/
|
|
16
|
+
export declare const GREP_OUTPUT_SCHEMA: JsonObject;
|
|
12
17
|
export declare const GREP_TOOL_DEFINITION: ResolvedToolDefinition;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeGrepOnSandbox}from"#execution/sandbox/grep-tool.js";const GREP_INPUT_SCHEMA={additionalProperties:!1,properties:{context:{description:`Number of surrounding context lines to include before and after each match. Defaults to 0.`,minimum:0,type:`integer`},glob:{description:`Filter files by glob pattern (e.g. "*.ts", "*.{ts,tsx}").`,type:`string`},ignoreCase:{description:`Perform case-insensitive search. Defaults to false.`,type:`boolean`},limit:{description:`Maximum number of matches to return per file. Defaults to 100.`,maximum:1e3,minimum:1,type:`integer`},literal:{description:`Treat the pattern as a literal string instead of a regular expression. Defaults to false.`,type:`boolean`},path:{description:`The directory or file to search in. Defaults to /workspace. Must be an absolute path. Omit to use the default.`,type:`string`},pattern:{description:`The regex pattern to search for in file contents (e.g. "log.*Error", "function\\s+\\w+").`,type:`string`}},required:[`pattern`],type:`object`};async function executeGrep(e){return executeGrepOnSandbox(await requireSandboxSession(),e)}const GREP_TOOL_DEFINITION={description:[`Fast content search tool that works with any codebase size.`,``,`Usage:`,`- Searches file contents using regular expressions.`,`- Supports full regex syntax (e.g. "log.*Error", "function\\s+\\w+").`,`- Filter files by pattern with the glob parameter (e.g. "*.js", "*.{ts,tsx}").`,`- Returns matching lines with file paths and line numbers.`,`- Use this tool when you need to find files containing specific patterns.`,`- Use the glob tool instead if you only need to find files by name.`,`- Call this tool in parallel when you have multiple independent searches.`,`- Any line longer than 2000 characters is truncated.`].join(`
|
|
2
|
-
`),execute:executeGrep,inputSchema:GREP_INPUT_SCHEMA,logicalPath:`ash:framework/grep`,name:`grep`,sourceId:`ash:grep-tool`,sourceKind:`module`};export{GREP_INPUT_SCHEMA,GREP_TOOL_DEFINITION};
|
|
1
|
+
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeGrepOnSandbox}from"#execution/sandbox/grep-tool.js";const GREP_INPUT_SCHEMA={additionalProperties:!1,properties:{context:{description:`Number of surrounding context lines to include before and after each match. Defaults to 0.`,minimum:0,type:`integer`},glob:{description:`Filter files by glob pattern (e.g. "*.ts", "*.{ts,tsx}").`,type:`string`},ignoreCase:{description:`Perform case-insensitive search. Defaults to false.`,type:`boolean`},limit:{description:`Maximum number of matches to return per file. Defaults to 100.`,maximum:1e3,minimum:1,type:`integer`},literal:{description:`Treat the pattern as a literal string instead of a regular expression. Defaults to false.`,type:`boolean`},path:{description:`The directory or file to search in. Defaults to /workspace. Must be an absolute path. Omit to use the default.`,type:`string`},pattern:{description:`The regex pattern to search for in file contents (e.g. "log.*Error", "function\\s+\\w+").`,type:`string`}},required:[`pattern`],type:`object`},GREP_OUTPUT_SCHEMA={additionalProperties:!1,properties:{content:{type:`string`},matchCount:{type:`integer`},path:{type:`string`},truncated:{type:`boolean`}},required:[`content`,`matchCount`,`path`,`truncated`],type:`object`};async function executeGrep(e){return executeGrepOnSandbox(await requireSandboxSession(),e)}const GREP_TOOL_DEFINITION={description:[`Fast content search tool that works with any codebase size.`,``,`Usage:`,`- Searches file contents using regular expressions.`,`- Supports full regex syntax (e.g. "log.*Error", "function\\s+\\w+").`,`- Filter files by pattern with the glob parameter (e.g. "*.js", "*.{ts,tsx}").`,`- Returns matching lines with file paths and line numbers.`,`- Use this tool when you need to find files containing specific patterns.`,`- Use the glob tool instead if you only need to find files by name.`,`- Call this tool in parallel when you have multiple independent searches.`,`- Any line longer than 2000 characters is truncated.`].join(`
|
|
2
|
+
`),execute:executeGrep,inputSchema:GREP_INPUT_SCHEMA,logicalPath:`ash:framework/grep`,name:`grep`,outputSchema:GREP_OUTPUT_SCHEMA,sourceId:`ash:grep-tool`,sourceKind:`module`};export{GREP_INPUT_SCHEMA,GREP_OUTPUT_SCHEMA,GREP_TOOL_DEFINITION};
|
|
@@ -9,4 +9,9 @@ import type { ResolvedToolDefinition } from "#runtime/types.js";
|
|
|
9
9
|
* model input contracts in sync without duplication.
|
|
10
10
|
*/
|
|
11
11
|
export declare const READ_FILE_INPUT_SCHEMA: JsonObject;
|
|
12
|
+
/**
|
|
13
|
+
* Shared output schema used by the framework `read_file` tool and any author
|
|
14
|
+
* tool constructed via {@link defineReadFileTool}.
|
|
15
|
+
*/
|
|
16
|
+
export declare const READ_FILE_OUTPUT_SCHEMA: JsonObject;
|
|
12
17
|
export declare const READ_FILE_TOOL_DEFINITION: ResolvedToolDefinition;
|