@autohq/cli 0.1.477 → 0.1.479
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/dist/agent-bridge.js +20 -2
- package/dist/index.js +351 -68
- package/package.json +1 -1
package/dist/agent-bridge.js
CHANGED
|
@@ -30866,7 +30866,7 @@ Object.assign(lookup, {
|
|
|
30866
30866
|
// package.json
|
|
30867
30867
|
var package_default = {
|
|
30868
30868
|
name: "@autohq/cli",
|
|
30869
|
-
version: "0.1.
|
|
30869
|
+
version: "0.1.479",
|
|
30870
30870
|
license: "SEE LICENSE IN README.md",
|
|
30871
30871
|
publishConfig: {
|
|
30872
30872
|
access: "public"
|
|
@@ -38169,8 +38169,10 @@ var SpendCapRuntimeErrorResponseSchema = external_exports.object({
|
|
|
38169
38169
|
issues: external_exports.array(external_exports.unknown()).optional()
|
|
38170
38170
|
});
|
|
38171
38171
|
|
|
38172
|
-
// ../../packages/schemas/src/templates/
|
|
38172
|
+
// ../../packages/schemas/src/templates/variable-contract.ts
|
|
38173
38173
|
var import_yaml = __toESM(require_dist(), 1);
|
|
38174
|
+
|
|
38175
|
+
// ../../packages/schemas/src/templates/public-source.ts
|
|
38174
38176
|
var MANAGED_TEMPLATE_PUBLIC_SOURCE_ORIGIN = "https://www.auto.sh";
|
|
38175
38177
|
var MANAGED_TEMPLATE_PUBLIC_SOURCE_PATH = "/api/v1/templates";
|
|
38176
38178
|
var SOURCE_COMMENT_PREFIX = `# Source: ${MANAGED_TEMPLATE_PUBLIC_SOURCE_ORIGIN}${MANAGED_TEMPLATE_PUBLIC_SOURCE_PATH}/`;
|
|
@@ -49762,6 +49764,21 @@ triggers:
|
|
|
49762
49764
|
]
|
|
49763
49765
|
}
|
|
49764
49766
|
],
|
|
49767
|
+
"@auto/herald": [
|
|
49768
|
+
{
|
|
49769
|
+
version: "1.0.0",
|
|
49770
|
+
files: [
|
|
49771
|
+
{
|
|
49772
|
+
path: "agents/herald.yaml",
|
|
49773
|
+
content: '# Source: https://www.auto.sh/api/v1/templates/%40auto/herald/1.0.0/agents/herald.yaml\n# Required variables: branchPrefix, changelogPath, githubConnection, heartbeatCron, heartbeatTimezone, repoFullName, scanWindowDays, slackChannel, slackConnection, trustedApprovalMentionIds, validationCommandSet\nname: herald\nlabels:\n purpose: changelog-curator\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsession:\n archiveAfterInactive:\n seconds: 86400\nharness: codex\nmodel:\n provider: openai\n id: gpt-5.6-sol\nreasoningEffort: high\nconcurrency: 1\nidentity:\n displayName: Herald\n username: herald\n avatar:\n asset: .auto/assets/herald.png\n sha256: 50395a53249a96be9ca1eb160bde02c8ceb681bf08b589c8472ed493efceeb64\n description:\n Curates scheduled public changelogs from merged work judged user-facing and\n valuable, for human wording and merge review.\ndisplayTitle: "Herald changelog: {{heartbeat.scheduledAt}}"\nsystemPrompt: |\n You are Herald, the changelog curator for {{ $repoFullName }}. You prepare\n human-reviewed changelog pull requests and never merge them.\n\n Source of truth and public contract:\n - `{{ $changelogPath }}` is the maintained changelog file and the sole state\n for changelog idempotency and deduplication. Read the complete file before\n planning an edit. Never create a parallel changelog source or depend on a\n repository-specific changelog helper or generated data model.\n - Preserve the file\'s existing format, ordering, headings, release grouping,\n and editorial conventions. If the repository renders or publishes the file\n elsewhere, preserve that presentation too. When an existing convention\n exposes a lead entry as a teaser, the newest included entry must read well\n standing alone.\n - Internal source PR identifiers and merge timestamps are provenance. Never\n put PR numbers, GitHub links, merge timestamps, provenance labels, or\n PR-oriented wording in a headline, bullet, public changelog, rendered\n page, or PR screenshot. This provenance ban applies to public changelog\n content and rendering. The operational Slack approval message is not public\n changelog content: it must include Herald\'s own changelog PR link, window,\n counts, and validation summary, but never candidate PR links, candidate\n provenance, or raw private content.\n - Do not use labels or prewritten maintainer copy as eligibility authority;\n Herald owns the bounded editorial judgment described below.\n\n Editorial voice:\n - Write every bullet as one complete, benefit-led sentence in present tense:\n name the surface a user recognizes and state the outcome, not the\n implementation. Concrete user impact is the register; vague reassurance is\n not.\n - Headlines are specific and thematic when the existing changelog format uses\n them. Keep every headline distinct and write it in outcome language.\n - Prefer substantive updates of roughly three to five entries. Never pad\n with ineligible or trivial work to reach a count; a thin window ships a\n short update or none at all.\n - When the repository\'s changelog house style requires it, avoid digits,\n apostrophes, and quotation marks in headlines and bullets. Treat this as\n editorial guidance, not a claim that provenance validation rejects all such\n characters.\n - Avoid internal codenames and engineering jargon. If a change cannot be\n described without internal context, it is not ready for the public\n changelog.\n\n Scan and selection:\n - The scan window is exactly {{ $scanWindowDays }} days ending at the\n heartbeat\'s `scheduledAt` timestamp. Use explicit inclusive ISO boundaries\n and retain the overlap on every run so late merges are discovered.\n - Search all merged PRs in that window, follow pagination to completion, and\n fetch enough PR, file, diff, merge, review, and comment data to evaluate\n every PR. If any page or required field is missing, truncated, stale, or\n ambiguous, fail the run closed: do not edit, push, open a PR, or post raw\n content. Report the incomplete surface and counts in the session output.\n - Evaluate every merged PR in the window. No label or maintainer-supplied\n public copy is required. Include a PR when the evidence supports a concrete,\n externally observable outcome that is valuable to users: a new or improved\n capability, a meaningful user-facing fix, better reliability, performance,\n or accessibility, or materially less workflow friction.\n - Exclude internal agent/process work, CI- or test-only changes, refactors,\n dependency or maintenance work, and any change with no evidenced\n user-visible outcome. Do not infer value from the PR title, files touched,\n diff size, or author alone. For mixed PRs, include only the evidence-backed\n user-facing outcome.\n - Exclude private tenant details. Include a security-related change only when\n a high-level user benefit is directly verifiable and can be stated without\n vulnerability, exploit, tenant, or internal-defense details. When truth or\n safety is uncertain, exclude the candidate and record the private reason;\n never infer or publish a sensitive claim.\n - Human wording or inclusion feedback in the Herald Slack thread or PR review\n is steering input, not an eligibility prerequisite. Requests for more\n inclusion mean re-evaluate excluded PRs against the same evidence and safety\n rubric; requests for less inclusion mean remove or defer candidates. Human\n steering never overrides completeness, provenance, or sensitive-content\n safeguards.\n - Count every scanned, included, and excluded PR. Keep exclusion reasons in\n the private session summary, not in public copy or Slack.\n\n Changelog update:\n - Treat the complete existing contents of `{{ $changelogPath }}` as the\n idempotency and deduplication state. Before writing, compare every proposed\n user-facing outcome with every existing entry. If the file already describes\n the same outcome, do not add it again. An overlapping rerun with no new or\n corrected outcome is a no-op.\n - A human-requested correction in PR review or the Herald Slack thread updates\n the matching existing changelog entry; it never appends a duplicate. If the\n intended entry cannot be identified confidently from the file contents and\n review context, fail closed and ask for clarification.\n - Add at most one new changelog section or release group per run when the\n existing file format uses groups. Follow the file\'s established ordering and\n date/version conventions. Group newly included outcomes together; corrections\n may update older entries in the same focused PR.\n - If there are no additions or corrections, open nothing. Report the exact\n window, scanned count, included count, excluded count, and validation\n result in the session output, then archive the session.\n\n Pull-request workflow:\n - Work from current `main` on `{{ $branchPrefix }}<YYYY-MM-DD>`. Search for an\n existing open Herald changelog PR before creating one. Update that one\n focused PR when it exists; otherwise create exactly one. Never create a\n second PR for the same run and never enable auto-merge.\n - Change only `{{ $changelogPath }}` and directly related tests or rendering\n code unless a minimal\n compatibility fix is required. Preserve the public presentation.\n - Run the configured validation command set exactly as provided:\n {{ $validationCommandSet }}\n - Inspect the full literal diff and any rendered public output. Verify no\n internal provenance appears in the changelog or rendered markup.\n - After opening or updating the PR, confirm its attributed held\n `github.pull_request` binding exists. Keep the branch and PR current,\n address CI/review feedback with normal follow-up commits, repair merge\n conflicts, and wait for green aggregate CI plus an exact-head `pr-review`\n thumbs-up. Never merge.\n - Post exactly one concise Slack message in `{{ $slackChannel }}` after the\n PR exists. Tag {{ $trustedApprovalMentionIds }} for explicit public-copy\n wording and merge approval. Include the PR link, inclusive\n {{ $scanWindowDays }}-day window, included and excluded counts, and\n validation summary. Invite replies in that thread to request more or less\n inclusion. Do not include raw candidate, private, tenant, security, or\n provenance content.\n - While a PR is open, do not archive the session. On PR close, report the\n final status and end the turn without self-archiving. The event router\n releases the held binding only after the close delivery settles; the\n configured inactivity policy may archive the unbound session later.\n\ninitialPrompt: |\n Run the scheduled Herald changelog curation at {{heartbeat.scheduledAt}}.\n Scan the inclusive {{ $scanWindowDays }}-day merged-PR window, apply the\n fail-closed selection and changelog-file idempotency and deduplication\n contract, and either prepare one human-reviewed PR or report an empty run\n without opening anything.\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: main\n auth:\n kind: githubApp\n commitAuthor:\n name: auto-dot-sh[bot]\n email: 292914954+auto-dot-sh[bot]@users.noreply.github.com\n capabilities:\n contents: write\n pullRequests: write\n issues: read\n checks: read\n actions: read\n workflows: none\n secrets: none\n merge: none\nworkingDirectory: /workspace/repo\nbindings:\n github.pull_request:\n lifecycle: held\n bind: onAttributedEvent\n continuity: agent\n context:\n role: implementer\n workflow: herald\n phase: implementation\ntools:\n auto:\n kind: local\n implementation: auto\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: "{{ $slackConnection }}"\n github:\n kind: github\n tools:\n - search_pull_requests\n - pull_request_read\n - get_file_contents\n - list_commits\n - actions_list\n - actions_get\n - get_job_logs\n - create_pull_request\n - update_pull_request\n - upsert_issue_comment\n - add_reply_to_pull_request_comment\n - pull_request_review_write\ntriggers:\n - name: changelog-heartbeat\n kind: heartbeat\n cron: "{{ $heartbeatCron }}"\n timezone: "{{ $heartbeatTimezone }}"\n message: |\n Herald run scheduled at {{heartbeat.scheduledAt}}. Scan the inclusive\n {{ $scanWindowDays }}-day window, then prepare one focused changelog PR\n or report an empty run without opening anything.\n routing:\n kind: spawn\n - name: check-failed\n event: github.check_run.completed\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.checkRun.conclusion: failure\n $.github.checkRun.name:\n notIn:\n - All checks\n $.github.checkRun.headIsCurrent:\n notIn:\n - false\n message: |\n Check {{github.checkRun.name}} failed on Herald PR\n #{{github.pullRequest.number}}. Confirm it belongs to the current head,\n diagnose it, and push a normal focused fix without enabling auto-merge.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n - name: aggregate-ci-passed\n event: github.check_run.completed\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.checkRun.conclusion: success\n $.github.checkRun.name: All checks\n $.github.checkRun.headIsCurrent:\n notIn:\n - false\n message: |\n Aggregate CI passed on Herald PR #{{github.pullRequest.number}}. Inspect\n the exact-head pr-review result and address any remaining feedback before\n reporting the PR ready for human wording and merge review.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n - name: pr-conversation\n events:\n - github.issue_comment.created\n - github.issue_comment.edited\n - github.pull_request_review.submitted\n - github.pull_request_review.edited\n - github.pull_request_review_comment.created\n - github.pull_request_review_comment.edited\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.auto.externalBot: false\n message: |\n A review or conversation update arrived on Herald PR\n #{{github.pullRequest.number}}. Address wording or correctness feedback\n on the existing branch, preserving the public/provenance boundary.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n - name: slack-inclusion-steering\n event: chat.message.subscribed\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.auto.authored: false\n message: |\n {{message.author.userName}} replied in Herald\'s changelog approval thread:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Treat this as human steering on wording or inclusion. A request for more\n inclusion means re-evaluate excluded PRs against the same evidence and\n safety rubric; a request for less inclusion means remove or defer the\n named candidates. Never relax scan completeness, private/tenant/security\n safeguards, or the public provenance ban. Update the same focused PR,\n rerun validation, and reply concisely in the thread with the outcome.\n routing:\n kind: deliver\n routeBy:\n kind: attributedSessions\n onUnmatched: drop\n - name: merge-conflict\n event: github.pull_request.merge_conflict\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n message: |\n Herald PR #{{github.pullRequest.number}} has a merge conflict. Fetch the\n latest main, resolve it minimally, and rerun affected validation.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n - name: pr-closed\n event: github.pull_request.closed\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n message: |\n Herald PR #{{github.pullRequest.number}} closed\n (merged={{github.pullRequest.merged}}). Report final status and end the\n turn without self-archiving. This trigger releases the held binding only\n after delivery settles; inactivity archival can happen later.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n release: true\n'
|
|
49774
|
+
},
|
|
49775
|
+
{
|
|
49776
|
+
path: "fragments/environments/agent-runtime.yaml",
|
|
49777
|
+
content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/herald/1.0.0/fragments/environments/agent-runtime.yaml\nharness: codex\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
|
|
49778
|
+
}
|
|
49779
|
+
]
|
|
49780
|
+
}
|
|
49781
|
+
],
|
|
49765
49782
|
"@auto/incident-response": [
|
|
49766
49783
|
{
|
|
49767
49784
|
version: "1.0.0",
|
|
@@ -68564,6 +68581,7 @@ var TEMPLATE_DESCRIPTIONS = {
|
|
|
68564
68581
|
"@auto/default": "Auto's minimum general-purpose runtime contract, implicitly imported by the permanent Default agent in every project.",
|
|
68565
68582
|
"@auto/engineering-tier": "An engineering-tier fleet: senior and junior engineers with PR ownership, a live-iteration designer, and a session introspector.",
|
|
68566
68583
|
"@auto/handoff": "A handoff coder that takes ownership of delegated PRs or coding tasks and reports back when ready.",
|
|
68584
|
+
"@auto/herald": "A scheduled changelog curator that judges merged work for user-facing value and prepares one provenance-free, human-reviewed public changelog PR per run.",
|
|
68567
68585
|
"@auto/incident-response": "A first responder for production alerts: investigates, delivers an evidence-based triage report, and opens a draft fix PR when the cause is clear; -slack entrypoint for channel triage.",
|
|
68568
68586
|
"@auto/inspector": "A root-cause investigator that reproduces unusual behavior, bisects it, and produces a case file before anyone changes the code.",
|
|
68569
68587
|
"@auto/intern": "A low-cost GLM 5.2 generalist for quick questions and bounded fixes, with calibrated escalation when work exceeds the intern lane.",
|
package/dist/index.js
CHANGED
|
@@ -22590,12 +22590,70 @@ var init_content_source = __esm({
|
|
|
22590
22590
|
}
|
|
22591
22591
|
});
|
|
22592
22592
|
|
|
22593
|
-
// ../../packages/schemas/src/templates/
|
|
22593
|
+
// ../../packages/schemas/src/templates/variable-contract.ts
|
|
22594
22594
|
import { parseAllDocuments } from "yaml";
|
|
22595
|
+
function readTemplateVariableContract(document, path2) {
|
|
22596
|
+
const value = document.templateVariables;
|
|
22597
|
+
if (value === void 0) {
|
|
22598
|
+
return { declared: false, required: /* @__PURE__ */ new Set(), optional: /* @__PURE__ */ new Set() };
|
|
22599
|
+
}
|
|
22600
|
+
if (!isRecord(value)) {
|
|
22601
|
+
throw new Error(
|
|
22602
|
+
`Invalid templateVariables in ${path2}: expected a map with required and optional lists`
|
|
22603
|
+
);
|
|
22604
|
+
}
|
|
22605
|
+
const required2 = readVariableNames(value.required, "required", path2);
|
|
22606
|
+
const optional2 = readVariableNames(value.optional, "optional", path2);
|
|
22607
|
+
const overlap = [...required2].filter((name) => optional2.has(name)).sort();
|
|
22608
|
+
if (overlap.length > 0) {
|
|
22609
|
+
throw new Error(
|
|
22610
|
+
`Invalid templateVariables in ${path2}: variables cannot be both required and optional (${overlap.join(", ")})`
|
|
22611
|
+
);
|
|
22612
|
+
}
|
|
22613
|
+
return { declared: true, required: required2, optional: optional2 };
|
|
22614
|
+
}
|
|
22615
|
+
function readVariableNames(value, kind, path2) {
|
|
22616
|
+
if (value === void 0) {
|
|
22617
|
+
return /* @__PURE__ */ new Set();
|
|
22618
|
+
}
|
|
22619
|
+
if (!Array.isArray(value)) {
|
|
22620
|
+
throw new Error(
|
|
22621
|
+
`Invalid templateVariables.${kind} in ${path2}: expected a list of variable names`
|
|
22622
|
+
);
|
|
22623
|
+
}
|
|
22624
|
+
const names = /* @__PURE__ */ new Set();
|
|
22625
|
+
for (const name of value) {
|
|
22626
|
+
if (typeof name !== "string" || !VARIABLE_NAME_PATTERN.test(name)) {
|
|
22627
|
+
throw new Error(
|
|
22628
|
+
`Invalid templateVariables.${kind} in ${path2}: names must match [A-Za-z_][A-Za-z0-9_]*`
|
|
22629
|
+
);
|
|
22630
|
+
}
|
|
22631
|
+
if (names.has(name)) {
|
|
22632
|
+
throw new Error(
|
|
22633
|
+
`Invalid templateVariables.${kind} in ${path2}: duplicate variable ${name}`
|
|
22634
|
+
);
|
|
22635
|
+
}
|
|
22636
|
+
names.add(name);
|
|
22637
|
+
}
|
|
22638
|
+
return names;
|
|
22639
|
+
}
|
|
22640
|
+
function isRecord(value) {
|
|
22641
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22642
|
+
}
|
|
22643
|
+
var VARIABLE_NAME_PATTERN;
|
|
22644
|
+
var init_variable_contract = __esm({
|
|
22645
|
+
"../../packages/schemas/src/templates/variable-contract.ts"() {
|
|
22646
|
+
"use strict";
|
|
22647
|
+
VARIABLE_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
22648
|
+
}
|
|
22649
|
+
});
|
|
22650
|
+
|
|
22651
|
+
// ../../packages/schemas/src/templates/public-source.ts
|
|
22595
22652
|
var MANAGED_TEMPLATE_PUBLIC_SOURCE_ORIGIN, MANAGED_TEMPLATE_PUBLIC_SOURCE_PATH, SOURCE_COMMENT_PREFIX;
|
|
22596
22653
|
var init_public_source = __esm({
|
|
22597
22654
|
"../../packages/schemas/src/templates/public-source.ts"() {
|
|
22598
22655
|
"use strict";
|
|
22656
|
+
init_variable_contract();
|
|
22599
22657
|
MANAGED_TEMPLATE_PUBLIC_SOURCE_ORIGIN = "https://www.auto.sh";
|
|
22600
22658
|
MANAGED_TEMPLATE_PUBLIC_SOURCE_PATH = "/api/v1/templates";
|
|
22601
22659
|
SOURCE_COMMENT_PREFIX = `# Source: ${MANAGED_TEMPLATE_PUBLIC_SOURCE_ORIGIN}${MANAGED_TEMPLATE_PUBLIC_SOURCE_PATH}/`;
|
|
@@ -34198,6 +34256,21 @@ triggers:
|
|
|
34198
34256
|
]
|
|
34199
34257
|
}
|
|
34200
34258
|
],
|
|
34259
|
+
"@auto/herald": [
|
|
34260
|
+
{
|
|
34261
|
+
version: "1.0.0",
|
|
34262
|
+
files: [
|
|
34263
|
+
{
|
|
34264
|
+
path: "agents/herald.yaml",
|
|
34265
|
+
content: '# Source: https://www.auto.sh/api/v1/templates/%40auto/herald/1.0.0/agents/herald.yaml\n# Required variables: branchPrefix, changelogPath, githubConnection, heartbeatCron, heartbeatTimezone, repoFullName, scanWindowDays, slackChannel, slackConnection, trustedApprovalMentionIds, validationCommandSet\nname: herald\nlabels:\n purpose: changelog-curator\nimports:\n - ../fragments/environments/agent-runtime.yaml\nsession:\n archiveAfterInactive:\n seconds: 86400\nharness: codex\nmodel:\n provider: openai\n id: gpt-5.6-sol\nreasoningEffort: high\nconcurrency: 1\nidentity:\n displayName: Herald\n username: herald\n avatar:\n asset: .auto/assets/herald.png\n sha256: 50395a53249a96be9ca1eb160bde02c8ceb681bf08b589c8472ed493efceeb64\n description:\n Curates scheduled public changelogs from merged work judged user-facing and\n valuable, for human wording and merge review.\ndisplayTitle: "Herald changelog: {{heartbeat.scheduledAt}}"\nsystemPrompt: |\n You are Herald, the changelog curator for {{ $repoFullName }}. You prepare\n human-reviewed changelog pull requests and never merge them.\n\n Source of truth and public contract:\n - `{{ $changelogPath }}` is the maintained changelog file and the sole state\n for changelog idempotency and deduplication. Read the complete file before\n planning an edit. Never create a parallel changelog source or depend on a\n repository-specific changelog helper or generated data model.\n - Preserve the file\'s existing format, ordering, headings, release grouping,\n and editorial conventions. If the repository renders or publishes the file\n elsewhere, preserve that presentation too. When an existing convention\n exposes a lead entry as a teaser, the newest included entry must read well\n standing alone.\n - Internal source PR identifiers and merge timestamps are provenance. Never\n put PR numbers, GitHub links, merge timestamps, provenance labels, or\n PR-oriented wording in a headline, bullet, public changelog, rendered\n page, or PR screenshot. This provenance ban applies to public changelog\n content and rendering. The operational Slack approval message is not public\n changelog content: it must include Herald\'s own changelog PR link, window,\n counts, and validation summary, but never candidate PR links, candidate\n provenance, or raw private content.\n - Do not use labels or prewritten maintainer copy as eligibility authority;\n Herald owns the bounded editorial judgment described below.\n\n Editorial voice:\n - Write every bullet as one complete, benefit-led sentence in present tense:\n name the surface a user recognizes and state the outcome, not the\n implementation. Concrete user impact is the register; vague reassurance is\n not.\n - Headlines are specific and thematic when the existing changelog format uses\n them. Keep every headline distinct and write it in outcome language.\n - Prefer substantive updates of roughly three to five entries. Never pad\n with ineligible or trivial work to reach a count; a thin window ships a\n short update or none at all.\n - When the repository\'s changelog house style requires it, avoid digits,\n apostrophes, and quotation marks in headlines and bullets. Treat this as\n editorial guidance, not a claim that provenance validation rejects all such\n characters.\n - Avoid internal codenames and engineering jargon. If a change cannot be\n described without internal context, it is not ready for the public\n changelog.\n\n Scan and selection:\n - The scan window is exactly {{ $scanWindowDays }} days ending at the\n heartbeat\'s `scheduledAt` timestamp. Use explicit inclusive ISO boundaries\n and retain the overlap on every run so late merges are discovered.\n - Search all merged PRs in that window, follow pagination to completion, and\n fetch enough PR, file, diff, merge, review, and comment data to evaluate\n every PR. If any page or required field is missing, truncated, stale, or\n ambiguous, fail the run closed: do not edit, push, open a PR, or post raw\n content. Report the incomplete surface and counts in the session output.\n - Evaluate every merged PR in the window. No label or maintainer-supplied\n public copy is required. Include a PR when the evidence supports a concrete,\n externally observable outcome that is valuable to users: a new or improved\n capability, a meaningful user-facing fix, better reliability, performance,\n or accessibility, or materially less workflow friction.\n - Exclude internal agent/process work, CI- or test-only changes, refactors,\n dependency or maintenance work, and any change with no evidenced\n user-visible outcome. Do not infer value from the PR title, files touched,\n diff size, or author alone. For mixed PRs, include only the evidence-backed\n user-facing outcome.\n - Exclude private tenant details. Include a security-related change only when\n a high-level user benefit is directly verifiable and can be stated without\n vulnerability, exploit, tenant, or internal-defense details. When truth or\n safety is uncertain, exclude the candidate and record the private reason;\n never infer or publish a sensitive claim.\n - Human wording or inclusion feedback in the Herald Slack thread or PR review\n is steering input, not an eligibility prerequisite. Requests for more\n inclusion mean re-evaluate excluded PRs against the same evidence and safety\n rubric; requests for less inclusion mean remove or defer candidates. Human\n steering never overrides completeness, provenance, or sensitive-content\n safeguards.\n - Count every scanned, included, and excluded PR. Keep exclusion reasons in\n the private session summary, not in public copy or Slack.\n\n Changelog update:\n - Treat the complete existing contents of `{{ $changelogPath }}` as the\n idempotency and deduplication state. Before writing, compare every proposed\n user-facing outcome with every existing entry. If the file already describes\n the same outcome, do not add it again. An overlapping rerun with no new or\n corrected outcome is a no-op.\n - A human-requested correction in PR review or the Herald Slack thread updates\n the matching existing changelog entry; it never appends a duplicate. If the\n intended entry cannot be identified confidently from the file contents and\n review context, fail closed and ask for clarification.\n - Add at most one new changelog section or release group per run when the\n existing file format uses groups. Follow the file\'s established ordering and\n date/version conventions. Group newly included outcomes together; corrections\n may update older entries in the same focused PR.\n - If there are no additions or corrections, open nothing. Report the exact\n window, scanned count, included count, excluded count, and validation\n result in the session output, then archive the session.\n\n Pull-request workflow:\n - Work from current `main` on `{{ $branchPrefix }}<YYYY-MM-DD>`. Search for an\n existing open Herald changelog PR before creating one. Update that one\n focused PR when it exists; otherwise create exactly one. Never create a\n second PR for the same run and never enable auto-merge.\n - Change only `{{ $changelogPath }}` and directly related tests or rendering\n code unless a minimal\n compatibility fix is required. Preserve the public presentation.\n - Run the configured validation command set exactly as provided:\n {{ $validationCommandSet }}\n - Inspect the full literal diff and any rendered public output. Verify no\n internal provenance appears in the changelog or rendered markup.\n - After opening or updating the PR, confirm its attributed held\n `github.pull_request` binding exists. Keep the branch and PR current,\n address CI/review feedback with normal follow-up commits, repair merge\n conflicts, and wait for green aggregate CI plus an exact-head `pr-review`\n thumbs-up. Never merge.\n - Post exactly one concise Slack message in `{{ $slackChannel }}` after the\n PR exists. Tag {{ $trustedApprovalMentionIds }} for explicit public-copy\n wording and merge approval. Include the PR link, inclusive\n {{ $scanWindowDays }}-day window, included and excluded counts, and\n validation summary. Invite replies in that thread to request more or less\n inclusion. Do not include raw candidate, private, tenant, security, or\n provenance content.\n - While a PR is open, do not archive the session. On PR close, report the\n final status and end the turn without self-archiving. The event router\n releases the held binding only after the close delivery settles; the\n configured inactivity policy may archive the unbound session later.\n\ninitialPrompt: |\n Run the scheduled Herald changelog curation at {{heartbeat.scheduledAt}}.\n Scan the inclusive {{ $scanWindowDays }}-day merged-PR window, apply the\n fail-closed selection and changelog-file idempotency and deduplication\n contract, and either prepare one human-reviewed PR or report an empty run\n without opening anything.\nmounts:\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/repo\n ref: main\n auth:\n kind: githubApp\n commitAuthor:\n name: auto-dot-sh[bot]\n email: 292914954+auto-dot-sh[bot]@users.noreply.github.com\n capabilities:\n contents: write\n pullRequests: write\n issues: read\n checks: read\n actions: read\n workflows: none\n secrets: none\n merge: none\nworkingDirectory: /workspace/repo\nbindings:\n github.pull_request:\n lifecycle: held\n bind: onAttributedEvent\n continuity: agent\n context:\n role: implementer\n workflow: herald\n phase: implementation\ntools:\n auto:\n kind: local\n implementation: auto\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: "{{ $slackConnection }}"\n github:\n kind: github\n tools:\n - search_pull_requests\n - pull_request_read\n - get_file_contents\n - list_commits\n - actions_list\n - actions_get\n - get_job_logs\n - create_pull_request\n - update_pull_request\n - upsert_issue_comment\n - add_reply_to_pull_request_comment\n - pull_request_review_write\ntriggers:\n - name: changelog-heartbeat\n kind: heartbeat\n cron: "{{ $heartbeatCron }}"\n timezone: "{{ $heartbeatTimezone }}"\n message: |\n Herald run scheduled at {{heartbeat.scheduledAt}}. Scan the inclusive\n {{ $scanWindowDays }}-day window, then prepare one focused changelog PR\n or report an empty run without opening anything.\n routing:\n kind: spawn\n - name: check-failed\n event: github.check_run.completed\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.checkRun.conclusion: failure\n $.github.checkRun.name:\n notIn:\n - All checks\n $.github.checkRun.headIsCurrent:\n notIn:\n - false\n message: |\n Check {{github.checkRun.name}} failed on Herald PR\n #{{github.pullRequest.number}}. Confirm it belongs to the current head,\n diagnose it, and push a normal focused fix without enabling auto-merge.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n - name: aggregate-ci-passed\n event: github.check_run.completed\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.checkRun.conclusion: success\n $.github.checkRun.name: All checks\n $.github.checkRun.headIsCurrent:\n notIn:\n - false\n message: |\n Aggregate CI passed on Herald PR #{{github.pullRequest.number}}. Inspect\n the exact-head pr-review result and address any remaining feedback before\n reporting the PR ready for human wording and merge review.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n - name: pr-conversation\n events:\n - github.issue_comment.created\n - github.issue_comment.edited\n - github.pull_request_review.submitted\n - github.pull_request_review.edited\n - github.pull_request_review_comment.created\n - github.pull_request_review_comment.edited\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n $.github.auto.externalBot: false\n message: |\n A review or conversation update arrived on Herald PR\n #{{github.pullRequest.number}}. Address wording or correctness feedback\n on the existing branch, preserving the public/provenance boundary.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n - name: slack-inclusion-steering\n event: chat.message.subscribed\n connection: "{{ $slackConnection }}"\n where:\n $.chat.provider: slack\n $.auto.authored: false\n message: |\n {{message.author.userName}} replied in Herald\'s changelog approval thread:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Treat this as human steering on wording or inclusion. A request for more\n inclusion means re-evaluate excluded PRs against the same evidence and\n safety rubric; a request for less inclusion means remove or defer the\n named candidates. Never relax scan completeness, private/tenant/security\n safeguards, or the public provenance ban. Update the same focused PR,\n rerun validation, and reply concisely in the thread with the outcome.\n routing:\n kind: deliver\n routeBy:\n kind: attributedSessions\n onUnmatched: drop\n - name: merge-conflict\n event: github.pull_request.merge_conflict\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n message: |\n Herald PR #{{github.pullRequest.number}} has a merge conflict. Fetch the\n latest main, resolve it minimally, and rerun affected validation.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n - name: pr-closed\n event: github.pull_request.closed\n connection: "{{ $githubConnection }}"\n where:\n $.github.repository.fullName: "{{ $repoFullName }}"\n message: |\n Herald PR #{{github.pullRequest.number}} closed\n (merged={{github.pullRequest.merged}}). Report final status and end the\n turn without self-archiving. This trigger releases the held binding only\n after delivery settles; inactivity archival can happen later.\n routing:\n kind: bind\n target: github.pull_request\n onUnmatched: drop\n release: true\n'
|
|
34266
|
+
},
|
|
34267
|
+
{
|
|
34268
|
+
path: "fragments/environments/agent-runtime.yaml",
|
|
34269
|
+
content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/herald/1.0.0/fragments/environments/agent-runtime.yaml\nharness: codex\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
|
|
34270
|
+
}
|
|
34271
|
+
]
|
|
34272
|
+
}
|
|
34273
|
+
],
|
|
34201
34274
|
"@auto/incident-response": [
|
|
34202
34275
|
{
|
|
34203
34276
|
version: "1.0.0",
|
|
@@ -53031,6 +53104,7 @@ var init_hardcoded = __esm({
|
|
|
53031
53104
|
"@auto/default": "Auto's minimum general-purpose runtime contract, implicitly imported by the permanent Default agent in every project.",
|
|
53032
53105
|
"@auto/engineering-tier": "An engineering-tier fleet: senior and junior engineers with PR ownership, a live-iteration designer, and a session introspector.",
|
|
53033
53106
|
"@auto/handoff": "A handoff coder that takes ownership of delegated PRs or coding tasks and reports back when ready.",
|
|
53107
|
+
"@auto/herald": "A scheduled changelog curator that judges merged work for user-facing value and prepares one provenance-free, human-reviewed public changelog PR per run.",
|
|
53034
53108
|
"@auto/incident-response": "A first responder for production alerts: investigates, delivers an evidence-based triage report, and opens a draft fix PR when the cause is clear; -slack entrypoint for channel triage.",
|
|
53035
53109
|
"@auto/inspector": "A root-cause investigator that reproduces unusual behavior, bisects it, and produces a case file before anyone changes the code.",
|
|
53036
53110
|
"@auto/intern": "A low-cost GLM 5.2 generalist for quick questions and bounded fixes, with calibrated escalation when work exceeds the intern lane.",
|
|
@@ -54686,6 +54760,7 @@ var init_templates = __esm({
|
|
|
54686
54760
|
init_hardcoded();
|
|
54687
54761
|
init_subscription();
|
|
54688
54762
|
init_catalog();
|
|
54763
|
+
init_variable_contract();
|
|
54689
54764
|
}
|
|
54690
54765
|
});
|
|
54691
54766
|
|
|
@@ -57684,7 +57759,7 @@ var init_package = __esm({
|
|
|
57684
57759
|
"package.json"() {
|
|
57685
57760
|
package_default = {
|
|
57686
57761
|
name: "@autohq/cli",
|
|
57687
|
-
version: "0.1.
|
|
57762
|
+
version: "0.1.479",
|
|
57688
57763
|
license: "SEE LICENSE IN README.md",
|
|
57689
57764
|
publishConfig: {
|
|
57690
57765
|
access: "public"
|
|
@@ -57945,7 +58020,7 @@ function compileAgentDocument(document, path2, stack, context) {
|
|
|
57945
58020
|
`Agent import cycle detected: ${[...stack, resolvedPath].join(" -> ")}`
|
|
57946
58021
|
);
|
|
57947
58022
|
}
|
|
57948
|
-
if (!
|
|
58023
|
+
if (!isRecord3(document)) {
|
|
57949
58024
|
throw new Error(`Invalid agent authoring file ${path2}: expected object`);
|
|
57950
58025
|
}
|
|
57951
58026
|
const imports = importPaths(document).map(
|
|
@@ -58070,25 +58145,25 @@ function authoringDocumentApplyShape(document, path2) {
|
|
|
58070
58145
|
};
|
|
58071
58146
|
}
|
|
58072
58147
|
function finalizeAgentApplyShape(document, path2) {
|
|
58073
|
-
if (!
|
|
58148
|
+
if (!isRecord3(document) || !isRecord3(document.spec)) {
|
|
58074
58149
|
return { resource: document, resources: [] };
|
|
58075
58150
|
}
|
|
58076
58151
|
const next = structuredClone(document);
|
|
58077
58152
|
const spec = next.spec;
|
|
58078
58153
|
const resources = [];
|
|
58079
|
-
if (
|
|
58154
|
+
if (isRecord3(spec.environment)) {
|
|
58080
58155
|
const environment = inlineEnvironmentResource(spec.environment, path2);
|
|
58081
58156
|
spec.environment = environment.metadata.name;
|
|
58082
58157
|
resources.push(environment);
|
|
58083
58158
|
}
|
|
58084
|
-
if (
|
|
58159
|
+
if (isRecord3(spec.identity)) {
|
|
58085
58160
|
const identity2 = inlineIdentityResource(spec.identity, next, path2);
|
|
58086
58161
|
spec.identity = identity2.metadata.name;
|
|
58087
58162
|
resources.push(identity2);
|
|
58088
58163
|
}
|
|
58089
58164
|
if (Array.isArray(spec.triggers)) {
|
|
58090
58165
|
spec.triggers = spec.triggers.map((trigger) => {
|
|
58091
|
-
if (!
|
|
58166
|
+
if (!isRecord3(trigger) || !("name" in trigger)) {
|
|
58092
58167
|
return trigger;
|
|
58093
58168
|
}
|
|
58094
58169
|
const compiledTrigger = { ...trigger };
|
|
@@ -58136,7 +58211,7 @@ function inlineIdentityResource(document, agentDocument, path2) {
|
|
|
58136
58211
|
}
|
|
58137
58212
|
spec[key] = value;
|
|
58138
58213
|
}
|
|
58139
|
-
if (metadata.name === void 0 &&
|
|
58214
|
+
if (metadata.name === void 0 && isRecord3(agentDocument.metadata) && typeof agentDocument.metadata.name === "string") {
|
|
58140
58215
|
metadata.name = agentDocument.metadata.name;
|
|
58141
58216
|
}
|
|
58142
58217
|
const parsed = IdentityApplyRequestSchema.safeParse({ metadata, spec });
|
|
@@ -58172,7 +58247,7 @@ function resolveFileBackedFields(spec, path2) {
|
|
|
58172
58247
|
};
|
|
58173
58248
|
}
|
|
58174
58249
|
function resolveFileBackedString(value, input) {
|
|
58175
|
-
if (!
|
|
58250
|
+
if (!isRecord3(value) || !("file" in value)) {
|
|
58176
58251
|
return value;
|
|
58177
58252
|
}
|
|
58178
58253
|
const file2 = value.file;
|
|
@@ -58190,8 +58265,8 @@ function resolveFileBackedString(value, input) {
|
|
|
58190
58265
|
return readFileSync8(resolve3(dirname8(input.path), filePath), "utf8");
|
|
58191
58266
|
}
|
|
58192
58267
|
function removalDirectives(document, path2) {
|
|
58193
|
-
const raw =
|
|
58194
|
-
if (!
|
|
58268
|
+
const raw = isRecord3(document.remove) ? document.remove : {};
|
|
58269
|
+
if (!isRecord3(raw)) {
|
|
58195
58270
|
return [];
|
|
58196
58271
|
}
|
|
58197
58272
|
const directives = [];
|
|
@@ -58213,18 +58288,18 @@ function stringList(value, label) {
|
|
|
58213
58288
|
});
|
|
58214
58289
|
}
|
|
58215
58290
|
function applyRemoval(value, removal) {
|
|
58216
|
-
if (!
|
|
58291
|
+
if (!isRecord3(value)) {
|
|
58217
58292
|
return value;
|
|
58218
58293
|
}
|
|
58219
58294
|
const next = structuredClone(value);
|
|
58220
|
-
if (!
|
|
58295
|
+
if (!isRecord3(next.spec)) {
|
|
58221
58296
|
return next;
|
|
58222
58297
|
}
|
|
58223
58298
|
const spec = { ...next.spec };
|
|
58224
58299
|
next.spec = spec;
|
|
58225
58300
|
switch (removal.target) {
|
|
58226
58301
|
case "tools": {
|
|
58227
|
-
if (!
|
|
58302
|
+
if (!isRecord3(spec[removal.target])) {
|
|
58228
58303
|
return next;
|
|
58229
58304
|
}
|
|
58230
58305
|
const collection = {
|
|
@@ -58268,7 +58343,7 @@ function mergeValues2(base, override, path2) {
|
|
|
58268
58343
|
if (Array.isArray(base) && Array.isArray(override)) {
|
|
58269
58344
|
return mergeArrays(base, override, path2);
|
|
58270
58345
|
}
|
|
58271
|
-
if (
|
|
58346
|
+
if (isRecord3(base) && isRecord3(override)) {
|
|
58272
58347
|
const merged = { ...base };
|
|
58273
58348
|
for (const [key, value] of Object.entries(override)) {
|
|
58274
58349
|
merged[key] = mergeValues2(merged[key], value, [...path2, key]);
|
|
@@ -58311,7 +58386,7 @@ function isNamedArrayMergePath(path2) {
|
|
|
58311
58386
|
return path2 === "spec.mounts" || path2 === "spec.triggers";
|
|
58312
58387
|
}
|
|
58313
58388
|
function collectionItemKey(collection, item) {
|
|
58314
|
-
if (!
|
|
58389
|
+
if (!isRecord3(item)) {
|
|
58315
58390
|
return void 0;
|
|
58316
58391
|
}
|
|
58317
58392
|
if (typeof item.name === "string") {
|
|
@@ -58343,7 +58418,7 @@ function isAgentFile(path2) {
|
|
|
58343
58418
|
return false;
|
|
58344
58419
|
}
|
|
58345
58420
|
}
|
|
58346
|
-
function
|
|
58421
|
+
function isRecord3(value) {
|
|
58347
58422
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
58348
58423
|
}
|
|
58349
58424
|
var AGENT_FILE_EXTENSIONS, AGENT_SPEC_FIELDS, AGENT_METADATA_FIELDS;
|
|
@@ -58752,7 +58827,7 @@ function sourceFileIndex(files) {
|
|
|
58752
58827
|
function isAbsoluteSourcePath(path2) {
|
|
58753
58828
|
return path2.startsWith("/");
|
|
58754
58829
|
}
|
|
58755
|
-
function
|
|
58830
|
+
function isRecord4(value) {
|
|
58756
58831
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
58757
58832
|
}
|
|
58758
58833
|
var APPLY_DIRECTORIES, PROJECT_APPLY_RESOURCE_DIRECTORIES;
|
|
@@ -58831,7 +58906,7 @@ function resolveTemplateImportPath(importPath, fileIndex) {
|
|
|
58831
58906
|
return key;
|
|
58832
58907
|
}
|
|
58833
58908
|
function removalDirectives2(document, path2) {
|
|
58834
|
-
const raw =
|
|
58909
|
+
const raw = isRecord4(document.remove) ? document.remove : {};
|
|
58835
58910
|
const directives = [];
|
|
58836
58911
|
for (const [target, value] of Object.entries(raw)) {
|
|
58837
58912
|
const names = stringList2(value, `remove.${target}`);
|
|
@@ -58976,7 +59051,7 @@ function mergeValues3(base, override) {
|
|
|
58976
59051
|
if (override === void 0) {
|
|
58977
59052
|
return base;
|
|
58978
59053
|
}
|
|
58979
|
-
if (
|
|
59054
|
+
if (isRecord4(base) && isRecord4(override)) {
|
|
58980
59055
|
const merged = { ...base };
|
|
58981
59056
|
for (const [key, value] of Object.entries(override)) {
|
|
58982
59057
|
merged[key] = mergeValues3(merged[key], value);
|
|
@@ -58996,7 +59071,7 @@ function sortJson(value) {
|
|
|
58996
59071
|
if (Array.isArray(value)) {
|
|
58997
59072
|
return value.map(sortJson);
|
|
58998
59073
|
}
|
|
58999
|
-
if (
|
|
59074
|
+
if (isRecord4(value)) {
|
|
59000
59075
|
return Object.fromEntries(
|
|
59001
59076
|
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortJson(nested)])
|
|
59002
59077
|
);
|
|
@@ -59012,7 +59087,9 @@ var init_helpers = __esm({
|
|
|
59012
59087
|
"import",
|
|
59013
59088
|
"imports",
|
|
59014
59089
|
"remove",
|
|
59015
|
-
"
|
|
59090
|
+
"templateVariables",
|
|
59091
|
+
"variables",
|
|
59092
|
+
"when"
|
|
59016
59093
|
]);
|
|
59017
59094
|
AGENT_METADATA_FIELD_KEYS = ["name", "labels", "annotations"];
|
|
59018
59095
|
}
|
|
@@ -59032,7 +59109,7 @@ function fileBackedStringField() {
|
|
|
59032
59109
|
};
|
|
59033
59110
|
}
|
|
59034
59111
|
function rejectDirectiveObject(value, input) {
|
|
59035
|
-
if (
|
|
59112
|
+
if (isRecord4(value) && "append" in value) {
|
|
59036
59113
|
throw new Error(
|
|
59037
59114
|
`Invalid agent authoring file ${input.path}: ${input.field} does not support directive objects; append is supported on ${APPEND_CAPABLE_FIELDS}`
|
|
59038
59115
|
);
|
|
@@ -59040,7 +59117,7 @@ function rejectDirectiveObject(value, input) {
|
|
|
59040
59117
|
return value;
|
|
59041
59118
|
}
|
|
59042
59119
|
function resolveFileBackedString2(value, input) {
|
|
59043
|
-
if (!
|
|
59120
|
+
if (!isRecord4(value)) {
|
|
59044
59121
|
return value;
|
|
59045
59122
|
}
|
|
59046
59123
|
if ("file" in value && !("append" in value)) {
|
|
@@ -59138,11 +59215,11 @@ function rejectUnresolvedAppendDirective(value) {
|
|
|
59138
59215
|
);
|
|
59139
59216
|
}
|
|
59140
59217
|
function appendDirectiveFromMarker(value) {
|
|
59141
|
-
if (!
|
|
59218
|
+
if (!isRecord4(value)) {
|
|
59142
59219
|
return void 0;
|
|
59143
59220
|
}
|
|
59144
59221
|
const marker = value[APPEND_DIRECTIVE_MARKER_KEY];
|
|
59145
|
-
if (!
|
|
59222
|
+
if (!isRecord4(marker)) {
|
|
59146
59223
|
return void 0;
|
|
59147
59224
|
}
|
|
59148
59225
|
return marker;
|
|
@@ -59164,7 +59241,7 @@ function inlineEnvironmentField() {
|
|
|
59164
59241
|
target: "spec",
|
|
59165
59242
|
merge: (base, override) => mergeValues3(base, override),
|
|
59166
59243
|
compile: (value, context) => {
|
|
59167
|
-
if (!
|
|
59244
|
+
if (!isRecord4(value)) {
|
|
59168
59245
|
return { resources: [], value };
|
|
59169
59246
|
}
|
|
59170
59247
|
const resource = inlineEnvironmentResource2(value, context.path);
|
|
@@ -59177,7 +59254,7 @@ function inlineIdentityField() {
|
|
|
59177
59254
|
target: "spec",
|
|
59178
59255
|
merge: (base, override) => mergeValues3(base, override),
|
|
59179
59256
|
compile: (value, context) => {
|
|
59180
|
-
if (!
|
|
59257
|
+
if (!isRecord4(value)) {
|
|
59181
59258
|
return { resources: [], value };
|
|
59182
59259
|
}
|
|
59183
59260
|
const resource = inlineIdentityResource2(
|
|
@@ -59190,7 +59267,7 @@ function inlineIdentityField() {
|
|
|
59190
59267
|
};
|
|
59191
59268
|
}
|
|
59192
59269
|
function assertAgentAuthoringDocument(document, path2) {
|
|
59193
|
-
if (!
|
|
59270
|
+
if (!isRecord4(document) || !("kind" in document)) {
|
|
59194
59271
|
return;
|
|
59195
59272
|
}
|
|
59196
59273
|
if (document.kind === "session") {
|
|
@@ -59343,12 +59420,12 @@ function compileRoutingInlineBindings(input) {
|
|
|
59343
59420
|
const bindings = input.bindings ? cloneBindings(input.bindings) : {};
|
|
59344
59421
|
const compiledTriggers = [];
|
|
59345
59422
|
for (const trigger of input.triggers) {
|
|
59346
|
-
if (!
|
|
59423
|
+
if (!isRecord4(trigger) || trigger.kind === "heartbeat") {
|
|
59347
59424
|
compiledTriggers.push(trigger);
|
|
59348
59425
|
continue;
|
|
59349
59426
|
}
|
|
59350
59427
|
const routing = trigger.routing;
|
|
59351
|
-
if (!
|
|
59428
|
+
if (!isRecord4(routing)) {
|
|
59352
59429
|
compiledTriggers.push(trigger);
|
|
59353
59430
|
continue;
|
|
59354
59431
|
}
|
|
@@ -59379,7 +59456,7 @@ function extractDeliverContribution(routing, path2) {
|
|
|
59379
59456
|
if (bindBlock === void 0) {
|
|
59380
59457
|
return void 0;
|
|
59381
59458
|
}
|
|
59382
|
-
if (!
|
|
59459
|
+
if (!isRecord4(bindBlock)) {
|
|
59383
59460
|
throw inlineShapeError(
|
|
59384
59461
|
path2,
|
|
59385
59462
|
"deliver",
|
|
@@ -59409,7 +59486,7 @@ function extractBindArmContribution(routing, path2) {
|
|
|
59409
59486
|
}
|
|
59410
59487
|
function extractSpawnArmContribution(routing, path2) {
|
|
59411
59488
|
const bindBlock = routing.bind;
|
|
59412
|
-
if (!
|
|
59489
|
+
if (!isRecord4(bindBlock)) {
|
|
59413
59490
|
return void 0;
|
|
59414
59491
|
}
|
|
59415
59492
|
if (bindBlock.lifecycle === void 0 && bindBlock.continuity === void 0) {
|
|
@@ -59447,7 +59524,7 @@ function mergeContributionIntoBindings(bindings, contribution, path2) {
|
|
|
59447
59524
|
}
|
|
59448
59525
|
function ensureEntry(bindings, target) {
|
|
59449
59526
|
const existing = bindings[target];
|
|
59450
|
-
if (
|
|
59527
|
+
if (isRecord4(existing)) {
|
|
59451
59528
|
return existing;
|
|
59452
59529
|
}
|
|
59453
59530
|
const entry = {};
|
|
@@ -59469,7 +59546,7 @@ function stripInlineRoutingFields(trigger, routing) {
|
|
|
59469
59546
|
return { ...trigger, routing: rest };
|
|
59470
59547
|
}
|
|
59471
59548
|
case "spawn": {
|
|
59472
|
-
if (!
|
|
59549
|
+
if (!isRecord4(routing.bind)) {
|
|
59473
59550
|
return trigger;
|
|
59474
59551
|
}
|
|
59475
59552
|
const {
|
|
@@ -59534,7 +59611,7 @@ function rejectSingletonTarget(target, path2, arm) {
|
|
|
59534
59611
|
function cloneBindings(bindings) {
|
|
59535
59612
|
const clone2 = {};
|
|
59536
59613
|
for (const [key, value] of Object.entries(bindings)) {
|
|
59537
|
-
clone2[key] =
|
|
59614
|
+
clone2[key] = isRecord4(value) ? { ...value } : value;
|
|
59538
59615
|
}
|
|
59539
59616
|
return clone2;
|
|
59540
59617
|
}
|
|
@@ -59584,7 +59661,7 @@ function triggersField() {
|
|
|
59584
59661
|
const withNamesStripped = removeAuthoringTriggerNames(value);
|
|
59585
59662
|
const { triggers, bindings } = compileRoutingInlineBindings({
|
|
59586
59663
|
triggers: withNamesStripped,
|
|
59587
|
-
bindings:
|
|
59664
|
+
bindings: isRecord4(context.draft.spec.bindings) ? context.draft.spec.bindings : void 0,
|
|
59588
59665
|
path: context.path
|
|
59589
59666
|
});
|
|
59590
59667
|
context.draft.spec.bindings = bindings;
|
|
@@ -59593,7 +59670,7 @@ function triggersField() {
|
|
|
59593
59670
|
};
|
|
59594
59671
|
}
|
|
59595
59672
|
function mountItemKey(item) {
|
|
59596
|
-
if (!
|
|
59673
|
+
if (!isRecord4(item)) {
|
|
59597
59674
|
return void 0;
|
|
59598
59675
|
}
|
|
59599
59676
|
if (typeof item.name === "string") {
|
|
@@ -59605,7 +59682,7 @@ function mountItemKey(item) {
|
|
|
59605
59682
|
return void 0;
|
|
59606
59683
|
}
|
|
59607
59684
|
function triggerItemKey(item) {
|
|
59608
|
-
if (!
|
|
59685
|
+
if (!isRecord4(item)) {
|
|
59609
59686
|
return void 0;
|
|
59610
59687
|
}
|
|
59611
59688
|
if (typeof item.name === "string") {
|
|
@@ -59658,7 +59735,7 @@ function removeAuthoringTriggerNames(value) {
|
|
|
59658
59735
|
return value;
|
|
59659
59736
|
}
|
|
59660
59737
|
return value.map((trigger) => {
|
|
59661
|
-
if (!
|
|
59738
|
+
if (!isRecord4(trigger) || !("name" in trigger)) {
|
|
59662
59739
|
return trigger;
|
|
59663
59740
|
}
|
|
59664
59741
|
const next = { ...trigger };
|
|
@@ -59681,7 +59758,7 @@ function namedMapField() {
|
|
|
59681
59758
|
target: "spec",
|
|
59682
59759
|
merge: (base, override) => mergeValues3(base, override),
|
|
59683
59760
|
remove: (value, names) => {
|
|
59684
|
-
if (!
|
|
59761
|
+
if (!isRecord4(value)) {
|
|
59685
59762
|
return value;
|
|
59686
59763
|
}
|
|
59687
59764
|
const next = { ...value };
|
|
@@ -59780,7 +59857,7 @@ function mergeSourceLocations(base, override) {
|
|
|
59780
59857
|
continue;
|
|
59781
59858
|
}
|
|
59782
59859
|
const prefix = `${target}.${key}`;
|
|
59783
|
-
if (!
|
|
59860
|
+
if (!isRecord4(value)) {
|
|
59784
59861
|
merged = Object.fromEntries(
|
|
59785
59862
|
Object.entries(merged).filter(
|
|
59786
59863
|
([path2]) => path2 !== prefix && !path2.startsWith(`${prefix}.`)
|
|
@@ -59907,14 +59984,14 @@ function readVariableScope(document, path2) {
|
|
|
59907
59984
|
if (declared === void 0) {
|
|
59908
59985
|
return /* @__PURE__ */ new Map();
|
|
59909
59986
|
}
|
|
59910
|
-
if (!
|
|
59987
|
+
if (!isRecord4(declared)) {
|
|
59911
59988
|
throw new Error(
|
|
59912
59989
|
`Invalid variables in ${path2}: variables must be a map of name to value`
|
|
59913
59990
|
);
|
|
59914
59991
|
}
|
|
59915
59992
|
const scope = /* @__PURE__ */ new Map();
|
|
59916
59993
|
for (const [name, value] of Object.entries(declared)) {
|
|
59917
|
-
if (!
|
|
59994
|
+
if (!VARIABLE_NAME_PATTERN2.test(name)) {
|
|
59918
59995
|
throw new Error(
|
|
59919
59996
|
`Invalid variable name "${name}" in ${path2}: names must match [A-Za-z_][A-Za-z0-9_]*`
|
|
59920
59997
|
);
|
|
@@ -59923,6 +60000,66 @@ function readVariableScope(document, path2) {
|
|
|
59923
60000
|
}
|
|
59924
60001
|
return scope;
|
|
59925
60002
|
}
|
|
60003
|
+
function registerTemplateVariableContract(declarations, contract, path2) {
|
|
60004
|
+
for (const [kind, names] of [
|
|
60005
|
+
["required", contract.required],
|
|
60006
|
+
["optional", contract.optional]
|
|
60007
|
+
]) {
|
|
60008
|
+
for (const name of names) {
|
|
60009
|
+
const existing = declarations.get(name);
|
|
60010
|
+
if (existing && existing.kind !== kind) {
|
|
60011
|
+
throw new Error(
|
|
60012
|
+
`Conflicting template variable declaration for "${name}": ${existing.kind} in ${existing.path}, ${kind} in ${path2}`
|
|
60013
|
+
);
|
|
60014
|
+
}
|
|
60015
|
+
declarations.set(name, existing ?? { kind, path: path2 });
|
|
60016
|
+
}
|
|
60017
|
+
}
|
|
60018
|
+
}
|
|
60019
|
+
function assertRequiredTemplateVariables(required2, variables, path2) {
|
|
60020
|
+
for (const name of [...required2].sort()) {
|
|
60021
|
+
if (!variables.has(name)) {
|
|
60022
|
+
throw new Error(
|
|
60023
|
+
`Required template variable "${name}" is missing for imported ${path2}`
|
|
60024
|
+
);
|
|
60025
|
+
}
|
|
60026
|
+
}
|
|
60027
|
+
}
|
|
60028
|
+
function includeConditionalTemplateDocument(input) {
|
|
60029
|
+
const optional2 = new Set(
|
|
60030
|
+
[...input.declarations.entries()].filter(([, declaration]) => declaration.kind === "optional").map(([name]) => name)
|
|
60031
|
+
);
|
|
60032
|
+
const referencedOptional = optionalVariableReferences(
|
|
60033
|
+
input.document,
|
|
60034
|
+
optional2
|
|
60035
|
+
);
|
|
60036
|
+
const condition = readVariableCondition(input.document.when, input.path);
|
|
60037
|
+
if (referencedOptional.size > 0) {
|
|
60038
|
+
if (!condition || referencedOptional.size !== 1 || !referencedOptional.has(condition)) {
|
|
60039
|
+
throw new Error(
|
|
60040
|
+
`Optional template variables in ${input.path} must be referenced only inside a document gated by matching when.variable`
|
|
60041
|
+
);
|
|
60042
|
+
}
|
|
60043
|
+
}
|
|
60044
|
+
if (!condition) {
|
|
60045
|
+
return true;
|
|
60046
|
+
}
|
|
60047
|
+
if (!optional2.has(condition)) {
|
|
60048
|
+
throw new Error(
|
|
60049
|
+
`Invalid when.variable in ${input.path}: "${condition}" must be declared in templateVariables.optional`
|
|
60050
|
+
);
|
|
60051
|
+
}
|
|
60052
|
+
const value = input.variables.get(condition);
|
|
60053
|
+
if (value === void 0) {
|
|
60054
|
+
return false;
|
|
60055
|
+
}
|
|
60056
|
+
if (value.trim().length === 0) {
|
|
60057
|
+
throw new Error(
|
|
60058
|
+
`Optional template variable "${condition}" in ${input.path} must be non-empty when supplied`
|
|
60059
|
+
);
|
|
60060
|
+
}
|
|
60061
|
+
return true;
|
|
60062
|
+
}
|
|
59926
60063
|
function substituteVariables(document, scope, site) {
|
|
59927
60064
|
if (scope.size === 0) {
|
|
59928
60065
|
return document;
|
|
@@ -59936,7 +60073,7 @@ function substituteValue(value, scope, site) {
|
|
|
59936
60073
|
if (Array.isArray(value)) {
|
|
59937
60074
|
return value.map((item) => substituteValue(item, scope, site));
|
|
59938
60075
|
}
|
|
59939
|
-
if (
|
|
60076
|
+
if (isRecord4(value)) {
|
|
59940
60077
|
return Object.fromEntries(
|
|
59941
60078
|
Object.entries(value).map(([key, nested]) => [
|
|
59942
60079
|
key,
|
|
@@ -59971,13 +60108,49 @@ function coerceVariableValue(name, value, path2) {
|
|
|
59971
60108
|
function availableNames(scope) {
|
|
59972
60109
|
return [...scope.keys()].sort().map((name) => `{{ $${name} }}`).join(", ");
|
|
59973
60110
|
}
|
|
59974
|
-
|
|
60111
|
+
function readVariableCondition(value, path2) {
|
|
60112
|
+
if (value === void 0) return void 0;
|
|
60113
|
+
if (!isRecord4(value) || typeof value.variable !== "string" || value.variable.length === 0 || Object.keys(value).some((key) => key !== "variable")) {
|
|
60114
|
+
throw new Error(
|
|
60115
|
+
`Invalid when in ${path2}: expected exactly { variable: <optional variable name> }`
|
|
60116
|
+
);
|
|
60117
|
+
}
|
|
60118
|
+
return value.variable;
|
|
60119
|
+
}
|
|
60120
|
+
function optionalVariableReferences(value, optional2) {
|
|
60121
|
+
const found = /* @__PURE__ */ new Set();
|
|
60122
|
+
collectOptionalVariableReferences(value, optional2, found);
|
|
60123
|
+
return found;
|
|
60124
|
+
}
|
|
60125
|
+
function collectOptionalVariableReferences(value, optional2, found) {
|
|
60126
|
+
if (typeof value === "string") {
|
|
60127
|
+
for (const match of value.matchAll(VARIABLE_REFERENCE_PATTERN)) {
|
|
60128
|
+
if (match[1] && optional2.has(match[1])) found.add(match[1]);
|
|
60129
|
+
}
|
|
60130
|
+
return;
|
|
60131
|
+
}
|
|
60132
|
+
if (Array.isArray(value)) {
|
|
60133
|
+
for (const item of value) {
|
|
60134
|
+
collectOptionalVariableReferences(item, optional2, found);
|
|
60135
|
+
}
|
|
60136
|
+
return;
|
|
60137
|
+
}
|
|
60138
|
+
if (isRecord4(value)) {
|
|
60139
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
60140
|
+
if (key !== "templateVariables" && key !== "when") {
|
|
60141
|
+
collectOptionalVariableReferences(nested, optional2, found);
|
|
60142
|
+
}
|
|
60143
|
+
}
|
|
60144
|
+
}
|
|
60145
|
+
}
|
|
60146
|
+
var VARIABLE_DECLARATIONS_FIELD, VARIABLE_NAME_PATTERN2, VARIABLE_REFERENCE_PATTERN;
|
|
59975
60147
|
var init_template_variables = __esm({
|
|
59976
60148
|
"../../packages/schemas/src/project-apply-files/template-variables.ts"() {
|
|
59977
60149
|
"use strict";
|
|
60150
|
+
init_templates();
|
|
59978
60151
|
init_source();
|
|
59979
60152
|
VARIABLE_DECLARATIONS_FIELD = "variables";
|
|
59980
|
-
|
|
60153
|
+
VARIABLE_NAME_PATTERN2 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
59981
60154
|
VARIABLE_REFERENCE_PATTERN = /\{\{\s*\$([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
|
|
59982
60155
|
}
|
|
59983
60156
|
});
|
|
@@ -60064,7 +60237,7 @@ function projectCompiledTriggerSourceLocations(locations, authoredTriggers) {
|
|
|
60064
60237
|
);
|
|
60065
60238
|
let compiledIndex = 0;
|
|
60066
60239
|
for (const [authoredIndex, trigger] of authoredTriggers.entries()) {
|
|
60067
|
-
if (!
|
|
60240
|
+
if (!isRecord4(trigger)) {
|
|
60068
60241
|
continue;
|
|
60069
60242
|
}
|
|
60070
60243
|
const events = authoredTriggerEvents(trigger);
|
|
@@ -60132,9 +60305,24 @@ function validateAgentFragmentDocument(document, path2, context) {
|
|
|
60132
60305
|
`Agent import cycle detected: ${[...context.stack, normalizedPath].join(" -> ")}`
|
|
60133
60306
|
);
|
|
60134
60307
|
}
|
|
60135
|
-
if (!
|
|
60308
|
+
if (!isRecord4(document)) {
|
|
60136
60309
|
throw new Error(`Invalid agent fragment file ${path2}: expected object`);
|
|
60137
60310
|
}
|
|
60311
|
+
const variableContract = readTemplateVariableContract(
|
|
60312
|
+
document,
|
|
60313
|
+
normalizedPath
|
|
60314
|
+
);
|
|
60315
|
+
registerTemplateVariableContract(
|
|
60316
|
+
context.templateVariableKinds,
|
|
60317
|
+
variableContract,
|
|
60318
|
+
normalizedPath
|
|
60319
|
+
);
|
|
60320
|
+
includeConditionalTemplateDocument({
|
|
60321
|
+
document,
|
|
60322
|
+
declarations: context.templateVariableKinds,
|
|
60323
|
+
variables: context.variables,
|
|
60324
|
+
path: normalizedPath
|
|
60325
|
+
});
|
|
60138
60326
|
for (const imported of importPaths2(document).map(
|
|
60139
60327
|
(importPath) => resolveImportPath2(importPath, normalizedPath, context.fileIndex)
|
|
60140
60328
|
)) {
|
|
@@ -60144,6 +60332,7 @@ function validateAgentFragmentDocument(document, path2, context) {
|
|
|
60144
60332
|
{
|
|
60145
60333
|
fileIndex: context.fileIndex,
|
|
60146
60334
|
stack: [...context.stack, normalizedPath],
|
|
60335
|
+
templateVariableKinds: context.templateVariableKinds,
|
|
60147
60336
|
variables: context.variables
|
|
60148
60337
|
}
|
|
60149
60338
|
);
|
|
@@ -60182,20 +60371,59 @@ function conflictingGeneratedResourceMessage(key, existing, record2) {
|
|
|
60182
60371
|
return `Conflicting generated resource "${key}" from agent authoring: ${location}. Inline generated resources must be identical when they share a name.`;
|
|
60183
60372
|
}
|
|
60184
60373
|
function compileAgentDocumentValue(document, path2, fileIndex, contextVariables) {
|
|
60374
|
+
const templateVariableKinds = /* @__PURE__ */ new Map();
|
|
60375
|
+
collectTemplateVariableContracts(
|
|
60376
|
+
document,
|
|
60377
|
+
path2,
|
|
60378
|
+
fileIndex,
|
|
60379
|
+
[],
|
|
60380
|
+
templateVariableKinds
|
|
60381
|
+
);
|
|
60185
60382
|
const draft = compileAgentDocument2(document, path2, {
|
|
60186
60383
|
fileIndex,
|
|
60187
60384
|
stack: [],
|
|
60385
|
+
templateVariableKinds,
|
|
60188
60386
|
variables: /* @__PURE__ */ new Map(),
|
|
60189
60387
|
...contextVariables && Object.keys(contextVariables).length > 0 ? { contextVariables: new Map(Object.entries(contextVariables)) } : {}
|
|
60190
60388
|
});
|
|
60191
60389
|
const authoredTriggers = structuredClone(draft.spec.triggers);
|
|
60192
|
-
const removals =
|
|
60390
|
+
const removals = isRecord4(document) ? removalDirectives2(document, normalizeSourcePath(path2)) : [];
|
|
60193
60391
|
return {
|
|
60194
60392
|
...compileAgentDraftResources(draft, path2, removals),
|
|
60195
60393
|
sourceLocations: draft.sourceLocations,
|
|
60196
60394
|
authoredTriggers
|
|
60197
60395
|
};
|
|
60198
60396
|
}
|
|
60397
|
+
function collectTemplateVariableContracts(document, path2, fileIndex, stack, declarations) {
|
|
60398
|
+
const normalizedPath = normalizeSourcePath(path2);
|
|
60399
|
+
if (stack.includes(normalizedPath)) {
|
|
60400
|
+
throw new Error(
|
|
60401
|
+
`Agent import cycle detected: ${[...stack, normalizedPath].join(" -> ")}`
|
|
60402
|
+
);
|
|
60403
|
+
}
|
|
60404
|
+
if (!isRecord4(document)) {
|
|
60405
|
+
throw new Error(`Invalid agent authoring file ${path2}: expected object`);
|
|
60406
|
+
}
|
|
60407
|
+
registerTemplateVariableContract(
|
|
60408
|
+
declarations,
|
|
60409
|
+
readTemplateVariableContract(document, normalizedPath),
|
|
60410
|
+
normalizedPath
|
|
60411
|
+
);
|
|
60412
|
+
const imports = [
|
|
60413
|
+
...stack.length === 0 && document.name === BUILT_IN_DEFAULT_AGENT_NAME ? [BUILT_IN_DEFAULT_AGENT_TEMPLATE_IMPORT] : [],
|
|
60414
|
+
...importPaths2(document)
|
|
60415
|
+
];
|
|
60416
|
+
for (const importPath of imports) {
|
|
60417
|
+
const imported = resolveImportPath2(importPath, normalizedPath, fileIndex);
|
|
60418
|
+
collectTemplateVariableContracts(
|
|
60419
|
+
readSingleDocument2(imported, fileIndex),
|
|
60420
|
+
imported,
|
|
60421
|
+
fileIndex,
|
|
60422
|
+
[...stack, normalizedPath],
|
|
60423
|
+
declarations
|
|
60424
|
+
);
|
|
60425
|
+
}
|
|
60426
|
+
}
|
|
60199
60427
|
function compileAgentDocument2(document, path2, context) {
|
|
60200
60428
|
const normalizedPath = normalizeSourcePath(path2);
|
|
60201
60429
|
if (context.stack.includes(normalizedPath)) {
|
|
@@ -60203,13 +60431,35 @@ function compileAgentDocument2(document, path2, context) {
|
|
|
60203
60431
|
`Agent import cycle detected: ${[...context.stack, normalizedPath].join(" -> ")}`
|
|
60204
60432
|
);
|
|
60205
60433
|
}
|
|
60206
|
-
if (!
|
|
60434
|
+
if (!isRecord4(document)) {
|
|
60207
60435
|
throw new Error(`Invalid agent authoring file ${path2}: expected object`);
|
|
60208
60436
|
}
|
|
60437
|
+
const variableContract = readTemplateVariableContract(
|
|
60438
|
+
document,
|
|
60439
|
+
normalizedPath
|
|
60440
|
+
);
|
|
60441
|
+
registerTemplateVariableContract(
|
|
60442
|
+
context.templateVariableKinds,
|
|
60443
|
+
variableContract,
|
|
60444
|
+
normalizedPath
|
|
60445
|
+
);
|
|
60209
60446
|
const variables = context.stack.length === 0 ? new Map([
|
|
60210
60447
|
...context.contextVariables ?? /* @__PURE__ */ new Map(),
|
|
60211
60448
|
...readVariableScope(document, normalizedPath)
|
|
60212
60449
|
]) : context.variables;
|
|
60450
|
+
assertRequiredTemplateVariables(
|
|
60451
|
+
variableContract.required,
|
|
60452
|
+
variables,
|
|
60453
|
+
normalizedPath
|
|
60454
|
+
);
|
|
60455
|
+
if (context.stack.length > 0 && !includeConditionalTemplateDocument({
|
|
60456
|
+
document,
|
|
60457
|
+
declarations: context.templateVariableKinds,
|
|
60458
|
+
variables,
|
|
60459
|
+
path: normalizedPath
|
|
60460
|
+
})) {
|
|
60461
|
+
return emptyAgentDraft();
|
|
60462
|
+
}
|
|
60213
60463
|
let merged = emptyAgentDraft();
|
|
60214
60464
|
const imports = [
|
|
60215
60465
|
...context.stack.length === 0 && document.name === BUILT_IN_DEFAULT_AGENT_NAME ? [BUILT_IN_DEFAULT_AGENT_TEMPLATE_IMPORT] : [],
|
|
@@ -60221,16 +60471,47 @@ function compileAgentDocument2(document, path2, context) {
|
|
|
60221
60471
|
normalizedPath,
|
|
60222
60472
|
context.fileIndex
|
|
60223
60473
|
);
|
|
60474
|
+
const rawImportedDocument = readSingleDocument2(imported, context.fileIndex);
|
|
60475
|
+
if (!isRecord4(rawImportedDocument)) {
|
|
60476
|
+
throw new Error(
|
|
60477
|
+
`Invalid agent authoring file ${imported}: expected object`
|
|
60478
|
+
);
|
|
60479
|
+
}
|
|
60480
|
+
const importedContract = readTemplateVariableContract(
|
|
60481
|
+
rawImportedDocument,
|
|
60482
|
+
imported
|
|
60483
|
+
);
|
|
60484
|
+
registerTemplateVariableContract(
|
|
60485
|
+
context.templateVariableKinds,
|
|
60486
|
+
importedContract,
|
|
60487
|
+
imported
|
|
60488
|
+
);
|
|
60489
|
+
assertRequiredTemplateVariables(
|
|
60490
|
+
importedContract.required,
|
|
60491
|
+
variables,
|
|
60492
|
+
imported
|
|
60493
|
+
);
|
|
60494
|
+
if (!includeConditionalTemplateDocument({
|
|
60495
|
+
document: rawImportedDocument,
|
|
60496
|
+
declarations: context.templateVariableKinds,
|
|
60497
|
+
variables,
|
|
60498
|
+
path: imported
|
|
60499
|
+
})) {
|
|
60500
|
+
continue;
|
|
60501
|
+
}
|
|
60224
60502
|
const importedDocument = substituteVariables(
|
|
60225
|
-
|
|
60503
|
+
rawImportedDocument,
|
|
60226
60504
|
variables,
|
|
60227
|
-
{
|
|
60505
|
+
{
|
|
60506
|
+
importPath
|
|
60507
|
+
}
|
|
60228
60508
|
);
|
|
60229
60509
|
merged = mergeAgentDrafts(
|
|
60230
60510
|
merged,
|
|
60231
60511
|
compileAgentDocument2(importedDocument, imported, {
|
|
60232
60512
|
fileIndex: context.fileIndex,
|
|
60233
60513
|
stack: [...context.stack, normalizedPath],
|
|
60514
|
+
templateVariableKinds: context.templateVariableKinds,
|
|
60234
60515
|
variables
|
|
60235
60516
|
})
|
|
60236
60517
|
);
|
|
@@ -60247,6 +60528,7 @@ var init_agent_authoring = __esm({
|
|
|
60247
60528
|
"../../packages/schemas/src/project-apply-files/agent-authoring.ts"() {
|
|
60248
60529
|
"use strict";
|
|
60249
60530
|
init_default_agent();
|
|
60531
|
+
init_templates();
|
|
60250
60532
|
init_agent_document_merge();
|
|
60251
60533
|
init_agent_fields();
|
|
60252
60534
|
init_source();
|
|
@@ -60492,7 +60774,7 @@ function hasBuiltInDefaultAgentDocument(files) {
|
|
|
60492
60774
|
return files.some((file2) => {
|
|
60493
60775
|
try {
|
|
60494
60776
|
return readDocumentsFromSource(file2).some(
|
|
60495
|
-
(document) =>
|
|
60777
|
+
(document) => isRecord4(document) && document.name === BUILT_IN_DEFAULT_AGENT_NAME
|
|
60496
60778
|
);
|
|
60497
60779
|
} catch {
|
|
60498
60780
|
return false;
|
|
@@ -60503,7 +60785,7 @@ function templateImportsInFile(file2) {
|
|
|
60503
60785
|
try {
|
|
60504
60786
|
const specifiers = [];
|
|
60505
60787
|
for (const document of readDocumentsFromSource(file2)) {
|
|
60506
|
-
if (!
|
|
60788
|
+
if (!isRecord4(document)) {
|
|
60507
60789
|
continue;
|
|
60508
60790
|
}
|
|
60509
60791
|
for (const importPath of importPaths2(document)) {
|
|
@@ -60752,6 +61034,7 @@ function assertValidFragmentSourceFiles(files, resourceRoot, fileIndex) {
|
|
|
60752
61034
|
validateAgentFragmentDocument(documents[0], file2.path, {
|
|
60753
61035
|
fileIndex,
|
|
60754
61036
|
stack: [],
|
|
61037
|
+
templateVariableKinds: /* @__PURE__ */ new Map(),
|
|
60755
61038
|
variables: /* @__PURE__ */ new Map()
|
|
60756
61039
|
});
|
|
60757
61040
|
} catch (error51) {
|
|
@@ -69444,7 +69727,7 @@ var AgentFacingAutoMcpShim = class {
|
|
|
69444
69727
|
}
|
|
69445
69728
|
};
|
|
69446
69729
|
function agentFacingDryRunTool(tool) {
|
|
69447
|
-
if (!
|
|
69730
|
+
if (!isRecord2(tool) || tool.name !== DRY_RUN_TOOL_NAME) {
|
|
69448
69731
|
return tool;
|
|
69449
69732
|
}
|
|
69450
69733
|
if (typeof tool.description !== "string" || !tool.description.includes(AUTO_RESOURCES_DRY_RUN_PATHS_PROTOCOL_MARKER)) {
|
|
@@ -69473,7 +69756,7 @@ function agentFacingDryRunTool(tool) {
|
|
|
69473
69756
|
};
|
|
69474
69757
|
}
|
|
69475
69758
|
function resolveAgentFacingDryRun(input) {
|
|
69476
|
-
if (!
|
|
69759
|
+
if (!isRecord2(input.arguments)) {
|
|
69477
69760
|
throw new Error(`Dry-run arguments must be an object. ${correctedCall}`);
|
|
69478
69761
|
}
|
|
69479
69762
|
const argumentsValue = input.arguments;
|
|
@@ -69633,7 +69916,7 @@ function localImportPaths(content, importerPath) {
|
|
|
69633
69916
|
const imports = [];
|
|
69634
69917
|
for (const document of parseAllDocuments2(content)) {
|
|
69635
69918
|
const value = document.toJS();
|
|
69636
|
-
if (!
|
|
69919
|
+
if (!isRecord2(value) || !Array.isArray(value.imports)) {
|
|
69637
69920
|
continue;
|
|
69638
69921
|
}
|
|
69639
69922
|
for (const importPath of value.imports) {
|
|
@@ -69784,8 +70067,8 @@ async function startAutoMcpProxy(input) {
|
|
|
69784
70067
|
return { server, url: `http://127.0.0.1:${address.port}/mcp` };
|
|
69785
70068
|
}
|
|
69786
70069
|
function prepareDryRunToolCall(input) {
|
|
69787
|
-
const params =
|
|
69788
|
-
const argumentsValue =
|
|
70070
|
+
const params = isRecord2(input.message.params) ? input.message.params : {};
|
|
70071
|
+
const argumentsValue = isRecord2(params.arguments) ? params.arguments : {};
|
|
69789
70072
|
const hasLegacyDialect = ["files", "resources"].some(
|
|
69790
70073
|
(key) => Object.hasOwn(argumentsValue, key)
|
|
69791
70074
|
);
|
|
@@ -69830,7 +70113,7 @@ function transformToolsListResponse(body) {
|
|
|
69830
70113
|
const parsed = JSON.parse(body);
|
|
69831
70114
|
let compatible = false;
|
|
69832
70115
|
const transformed = transformJsonRpcMessages(parsed, (message) => {
|
|
69833
|
-
if (!
|
|
70116
|
+
if (!isRecord2(message.result) || !Array.isArray(message.result.tools)) {
|
|
69834
70117
|
return message;
|
|
69835
70118
|
}
|
|
69836
70119
|
const tools = message.result.tools.map((tool) => {
|
|
@@ -69847,16 +70130,16 @@ function transformToolsListResponse(body) {
|
|
|
69847
70130
|
function transformJsonRpcMessages(value, transform2) {
|
|
69848
70131
|
if (Array.isArray(value)) {
|
|
69849
70132
|
return value.map(
|
|
69850
|
-
(message) =>
|
|
70133
|
+
(message) => isRecord2(message) ? transform2(message) : message
|
|
69851
70134
|
);
|
|
69852
70135
|
}
|
|
69853
|
-
return
|
|
70136
|
+
return isRecord2(value) ? transform2(value) : value;
|
|
69854
70137
|
}
|
|
69855
70138
|
function isToolsListRequest(value) {
|
|
69856
|
-
return
|
|
70139
|
+
return isRecord2(value) && value.method === "tools/list";
|
|
69857
70140
|
}
|
|
69858
70141
|
function isDryRunToolCall(value) {
|
|
69859
|
-
if (!
|
|
70142
|
+
if (!isRecord2(value) || value.method !== "tools/call" || !isRecord2(value.params)) {
|
|
69860
70143
|
return false;
|
|
69861
70144
|
}
|
|
69862
70145
|
return value.params.name === DRY_RUN_TOOL_NAME;
|
|
@@ -69921,7 +70204,7 @@ function writeResponse(response, status, headers, body) {
|
|
|
69921
70204
|
}
|
|
69922
70205
|
response.end(body);
|
|
69923
70206
|
}
|
|
69924
|
-
function
|
|
70207
|
+
function isRecord2(value) {
|
|
69925
70208
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
69926
70209
|
}
|
|
69927
70210
|
|
|
@@ -80449,7 +80732,7 @@ async function selectRepository(context, github, explicitRepo) {
|
|
|
80449
80732
|
const selection = github.grant.providerResourceSelection;
|
|
80450
80733
|
if (selection.kind === "selected") {
|
|
80451
80734
|
const repos = selection.resources.map(
|
|
80452
|
-
(resource) =>
|
|
80735
|
+
(resource) => isRecord5(resource) && typeof resource.fullName === "string" ? resource.fullName : void 0
|
|
80453
80736
|
).filter(isDefined);
|
|
80454
80737
|
if (repos.length === 1) {
|
|
80455
80738
|
context.writeOutput(`Using GitHub repository ${repos[0]}.`);
|
|
@@ -80779,7 +81062,7 @@ function slackWorkspaceUrl(slack) {
|
|
|
80779
81062
|
function organizationLabel(organization) {
|
|
80780
81063
|
return `${organization.organizationName} (${organization.organizationSlug})`;
|
|
80781
81064
|
}
|
|
80782
|
-
function
|
|
81065
|
+
function isRecord5(value) {
|
|
80783
81066
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
80784
81067
|
}
|
|
80785
81068
|
function isDefined(value) {
|