Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VENDORED.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Pinned to [faremeter/interchange](https://github.com/faremeter/interchange)
| `vendor/intx/hub-common` | `@intx/hub-common` at a newer commit than npm has published | maintainers | 2026-11-03 |
| `vendor/intx/workflow` | `@intx/workflow`, with one local step-timeout-budget delta | maintainers | 2026-11-03 |
| `vendor/intx/workflow-deploy` | `@intx/workflow-deploy` at a newer commit than npm has published | maintainers | 2026-11-03 |
| `vendor/intx/workflow-host` | `@intx/workflow-host`, with one local step-grants-collapse delta | maintainers | 2026-11-03 |
| `vendor/intx/workflow-host` | `@intx/workflow-host`, with a local step-grants-collapse delta and a temporary delta omitting an empty inbound `Subject` header instead of passing it through empty (kill condition: upstream tolerates an empty Subject, INTR-577) | maintainers | 2026-11-03 |

npm's published `0.3.0` predates this pin for every row above, so each is
re-vendored at the same commit rather than mixed pins; the root
Expand Down
2 changes: 1 addition & 1 deletion vendor/intx/workflow-host/VENDORED-FROM
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Source: https://github.com/faremeter/interchange (packages/workflow-host)
Commit: 692c31068cbb636ebb19c6d179ec6fe126a2d4e6 (origin/main, 2026-09-03)
License: LGPL-2.1-only (see vendor/intx/LICENSE)
Local modifications: exports map repointed from the upstream intx-src condition to direct TypeScript source resolution (types/default -> ./src/...); dist references removed. Upstream test files are not vendored (they import the unvendored @intx/inference-testing and @intx/test-harness test packages); only the tests covering a workbench delta are kept. CL-6448: the suspendable-child (onTrigger body) spawn seam threads the parent child's credentials-backed authorize and MailPartReader: RunSuspendableChild's input and createInMemorySpawnSuspendableChild's opts gain the two optional fields (adapters/spawn-child.ts), and child/run-child.ts hoists `authorize` above the body resolver and passes both when building it, so a tool-bearing body agent gates its tool calls through the same per-step grant snapshot a top-level step does and reads an attachments-only inbound mail's parts instead of throwing. Upstream runs bodies toolless and has no analog. child/run-child.ts also resolves a step's grants entry through findStepGrantsEntry (head collapse: a body step whose own id is absent from a single-step deployment's snapshot resolves to the sole entry). CL-6396: the event-channel envelope, sender, and receiver carry an optional childRunId; run-child stamps spawnInput.childRunId onto body-child events so overlapping turns HMAC-bind the occurrence they belong to. Retired at this pin: the CL-6448 credentialWiring thread (upstream now passes the run's live credential-material cell into every body spawn natively as `credentialMaterial`). Retired at earlier pins: the empty-mail drop (CL-6164) and the action/loop runtime bind (CL-6325).
Local modifications: exports map repointed from the upstream intx-src condition to direct TypeScript source resolution (types/default -> ./src/...); dist references removed. Upstream test files are not vendored (they import the unvendored @intx/inference-testing and @intx/test-harness test packages); only the tests covering a workbench delta are kept. CL-6448: the suspendable-child (onTrigger body) spawn seam threads the parent child's credentials-backed authorize and MailPartReader: RunSuspendableChild's input and createInMemorySpawnSuspendableChild's opts gain the two optional fields (adapters/spawn-child.ts), and child/run-child.ts hoists `authorize` above the body resolver and passes both when building it, so a tool-bearing body agent gates its tool calls through the same per-step grant snapshot a top-level step does and reads an attachments-only inbound mail's parts instead of throwing. Upstream runs bodies toolless and has no analog. child/run-child.ts also resolves a step's grants entry through findStepGrantsEntry (head collapse: a body step whose own id is absent from a single-step deployment's snapshot resolves to the sole entry). CL-6396: the event-channel envelope, sender, and receiver carry an optional childRunId; run-child stamps spawnInput.childRunId onto body-child events so overlapping turns HMAC-bind the occurrence they belong to. Retired at this pin: the CL-6448 credentialWiring thread (upstream now passes the run's live credential-material cell into every body spawn natively as `credentialMaterial`). Retired at earlier pins: the empty-mail drop (CL-6164) and the action/loop runtime bind (CL-6325). Temporary delta: buildInboundMessageFromMail omits `subject` when the decoded header is empty (a present-but-textless Subject header), since createInboundMessage rejects an empty subject and fails the step; see VENDORED.md's kill condition.
28 changes: 28 additions & 0 deletions vendor/intx/workflow-host/src/adapters/step-invoker.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describe, expect, test } from "bun:test";

import type { Mail } from "@intx/types/runtime";

import { buildInboundMessageFromMail } from "./step-invoker";

function mailWithSubject(subject: string | undefined): Mail {
return {
headers: {
from: "sender@example.com",
to: ["agent@local"],
...(subject !== undefined ? { subject } : {}),
},
rawHeaders: {},
parts: [{ contentType: "text/plain", ref: "part_1", text: "hi" }],
} as Mail;
}

describe("buildInboundMessageFromMail", () => {
test("an empty Subject header is treated as absent", async () => {
const message = await buildInboundMessageFromMail(
mailWithSubject(""),
undefined,
);

expect(message.headers.subject).toBeUndefined();
});
});
8 changes: 6 additions & 2 deletions vendor/intx/workflow-host/src/adapters/step-invoker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ function safeAddr(raw: string | undefined, fallback: string): string {
* which is not wired with a reader -- still delivers; a part that needs bytes
* with no reader is refused loudly rather than silently dropped.
*/
async function buildInboundMessageFromMail(
export async function buildInboundMessageFromMail(
mail: Mail,
mailPartReader: MailPartReader | undefined,
): Promise<InboundMessage> {
Expand Down Expand Up @@ -819,7 +819,11 @@ async function buildInboundMessageFromMail(
return createInboundMessage({
from: safeAddr(mail.headers.from, "trigger@local"),
to: safeAddr(mail.headers.to[0], "agent@local"),
...(mail.headers.subject !== undefined
// A present-but-empty Subject header (e.g. "Subject:" with no text)
// decodes to "" and createInboundMessage rejects an empty subject,
// failing the step -- so treat it like an absent header.
...(mail.headers.subject !== undefined &&
mail.headers.subject.trim().length > 0
? { subject: mail.headers.subject }
: {}),
...(isMessageId(mail.headers.messageId)
Expand Down
Loading