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
45 changes: 37 additions & 8 deletions .github/workflows/detect-changes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,24 +96,53 @@ jobs:
file.startsWith('.cargo/') ||
file.endsWith('.rs') ||
['Cargo.toml', 'Cargo.lock', 'Cross.toml', 'rust-toolchain', 'rust-toolchain.toml'].includes(file);
// Agent implementations and their tests are part of the Node test
// surface. Other AgentWorkforce records remain inert metadata.
const isAgentRuntime = (file) =>
file.startsWith('.agentworkforce/agents/');
// Files no build, test, or lint job consumes.
const isInert = (file) =>
file.startsWith('web/') ||
file.startsWith('docs/') ||
file.startsWith('specs/') ||
file.startsWith('.claude/') ||
file.startsWith('.agentworkforce/') ||
(file.startsWith('.agentworkforce/') && !isAgentRuntime(file)) ||
file.startsWith('.agents/') ||
file === 'LICENSE' ||
(/\.mdx?$/i.test(file) && !file.includes('/'));

const rustChanged =
unknownScope ||
files.some((file) => (isRust(file) && !isInert(file)) || isCi(file));
const nodeChanged =
unknownScope || files.some((file) => !isSwift(file) && !isInert(file));
const sdkSwiftChanged =
unknownScope || files.some((file) => isSwift(file) || isCi(file));
const classifyFiles = (changedFiles) => ({
rustChanged: changedFiles.some(
(file) => (isRust(file) && !isInert(file)) || isCi(file)
),
nodeChanged: changedFiles.some(
(file) => !isSwift(file) && !isInert(file)
),
sdkSwiftChanged: changedFiles.some(
(file) => isSwift(file) || isCi(file)
),
});

// Exercise the exact production classifier with an agent-only
// change so future broad inert-path rules fail visibly.
const agentRuntimeProbe = classifyFiles([
'.agentworkforce/agents/ci-scope-probe.ts',
]);
core.info(
`agent_runtime_probe rust_changed=${agentRuntimeProbe.rustChanged} node_changed=${agentRuntimeProbe.nodeChanged} sdk_swift_changed=${agentRuntimeProbe.sdkSwiftChanged}`
);
if (
agentRuntimeProbe.rustChanged ||
!agentRuntimeProbe.nodeChanged ||
agentRuntimeProbe.sdkSwiftChanged
) {
throw new Error('Agent-only scope probe must select only Node jobs');
}

const detectedScope = classifyFiles(files);
const rustChanged = unknownScope || detectedScope.rustChanged;
const nodeChanged = unknownScope || detectedScope.nodeChanged;
const sdkSwiftChanged = unknownScope || detectedScope.sdkSwiftChanged;

core.info(`Changed files (${files.length}): ${files.join(', ')}`);
core.info(
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/node-compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ on:
pull_request:
branches: [main]

# Reusable workflows cannot elevate the caller's token permissions.
# detect-changes.yml reads pull-request file lists and commit comparisons.
permissions:
contents: read
pull-requests: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/package-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ on:
pull_request:
branches: [main]

# Reusable workflows cannot elevate the caller's token permissions.
# detect-changes.yml reads pull-request file lists and commit comparisons.
permissions:
contents: read
pull-requests: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/rust-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ on:
push:
branches: [main]

# Reusable workflows cannot elevate the caller's token permissions.
# detect-changes.yml reads pull-request file lists and commit comparisons.
permissions:
contents: read
pull-requests: read

env:
CARGO_TERM_COLOR: always
AGENT_RELAY_TELEMETRY_DISABLED: 1
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ on:
# Run weekly on Sundays at midnight
- cron: '0 0 * * 0'

# Reusable workflows cannot elevate the caller's token permissions.
# detect-changes.yml reads pull-request file lists and commit comparisons.
permissions:
contents: read
pull-requests: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ on:
pull_request:
branches: [main]

# Reusable workflows cannot elevate the caller's token permissions.
# detect-changes.yml reads pull-request file lists and commit comparisons.
permissions:
contents: read
pull-requests: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- `agent-relay integration` now discovers relayfile control-plane capabilities before sending API v3 headers, fails fast with upgrade and restart guidance for incompatible daemons, and safely replaces stale daemons when a compatible binary is installed.
- `AgentRelaySDK` now maps Relaycast lifecycle states onto its existing Swift presence states, so root-package consumers compile with Relaycast 6.1 and later while package-local builds remain compatible with 6.0.5.

## [10.6.3] - 2026-07-17

Expand Down
8 changes: 0 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ extension RelayAgentType {

extension RelayAgentStatus {
init(_ status: Relaycast.AgentStatus) {
switch status {
case .online: self = .online
case .offline: self = .offline
case .away: self = .away
}
self.init(hosted: status.rawValue)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,18 @@ import Relaycast
// `Relay*` type built here.

extension RelayAgentStatus {
/// Map a hosted status string (`online`/`offline`/`away`) onto the enum.
/// Map hosted presence and lifecycle states onto the legacy public enum.
///
/// Relaycast 6.1 added lifecycle states while this SDK still supports
/// 6.0.5, so bridge by raw value instead of naming cases that older
/// Relaycast releases do not compile against.
init(hosted status: String) {
self = RelayAgentStatus(rawValue: status) ?? .unknown
switch status {
case "active", "online": self = .online
case "idle", "blocked", "waiting", "away": self = .away
case "offline": self = .offline
default: self = .unknown
}
}

var relaycastStatus: Relaycast.AgentStatus? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ final class HostedParticipantSDKTests: XCTestCase {
XCTAssertEqual(RelayAgentStatus(Relaycast.AgentStatus.online), .online)
XCTAssertEqual(RelayAgentStatus(Relaycast.AgentStatus.offline), .offline)
XCTAssertEqual(RelayAgentStatus(Relaycast.AgentStatus.away), .away)

let lifecycleStatuses: [(String, RelayAgentStatus)] = [
("active", .online),
("idle", .away),
("blocked", .away),
("waiting", .away),
]
for (rawValue, expected) in lifecycleStatuses {
XCTAssertEqual(RelayAgentStatus(hosted: rawValue), expected)
if let relaycastStatus = Relaycast.AgentStatus(rawValue: rawValue) {
XCTAssertEqual(RelayAgentStatus(relaycastStatus), expected)
}
}
XCTAssertEqual(RelayAgentStatus(hosted: "future-status"), .unknown)
}

func testJSONValueBridgingPreservesShape() {
Expand Down
17 changes: 0 additions & 17 deletions packages/workflow-types/package.json

This file was deleted.

Loading