agent-relay-server 0.62.3 → 0.63.1
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/docs/openapi.json +1 -1
- package/package.json +4 -2
- package/public/assets/{MessageBubble-DRrxfjyT.js → MessageBubble-Cl6ufPHw.js} +2 -2
- package/public/assets/MessageBubble-Cl6ufPHw.js.map +1 -0
- package/public/assets/{PlanGraphPanel-Dp2eYazz.js → PlanGraphPanel-BnfjmkQ8.js} +2 -2
- package/public/assets/{PlanGraphPanel-Dp2eYazz.js.map → PlanGraphPanel-BnfjmkQ8.js.map} +1 -1
- package/public/assets/{activity--t0U2yzq.js → activity-aFxvGLtd.js} +2 -2
- package/public/assets/{activity--t0U2yzq.js.map → activity-aFxvGLtd.js.map} +1 -1
- package/public/assets/{agent-profiles-BMtJYzxn.js → agent-profiles-B4mleUDz.js} +2 -2
- package/public/assets/{agent-profiles-BMtJYzxn.js.map → agent-profiles-B4mleUDz.js.map} +1 -1
- package/public/assets/{agents-Ck9AePlc.js → agents-DW5djToQ.js} +2 -2
- package/public/assets/{agents-Ck9AePlc.js.map → agents-DW5djToQ.js.map} +1 -1
- package/public/assets/{analytics-CzfK387L.js → analytics-CRi6thtg.js} +2 -2
- package/public/assets/{analytics-CzfK387L.js.map → analytics-CRi6thtg.js.map} +1 -1
- package/public/assets/{automation-Cgw8vtE8.js → automation-Do4OpauI.js} +2 -2
- package/public/assets/{automation-Cgw8vtE8.js.map → automation-Do4OpauI.js.map} +1 -1
- package/public/assets/{branch-state-badge-DnEEPtOP.js → branch-state-badge-D3W3w7zz.js} +2 -2
- package/public/assets/{branch-state-badge-DnEEPtOP.js.map → branch-state-badge-D3W3w7zz.js.map} +1 -1
- package/public/assets/{channels-Dc3L2MQs.js → channels-BytdR9NS.js} +2 -2
- package/public/assets/{channels-Dc3L2MQs.js.map → channels-BytdR9NS.js.map} +1 -1
- package/public/assets/{chat-Fc6iJ7sa.js → chat-CvaQ2czL.js} +2 -2
- package/public/assets/{chat-Fc6iJ7sa.js.map → chat-CvaQ2czL.js.map} +1 -1
- package/public/assets/{connectors-Dc2ttGWs.js → connectors-BLQDp8Bc.js} +2 -2
- package/public/assets/{connectors-Dc2ttGWs.js.map → connectors-BLQDp8Bc.js.map} +1 -1
- package/public/assets/{display-DzNvOu1j.js → display-B06I5sqa.js} +3 -3
- package/public/assets/display-B06I5sqa.js.map +1 -0
- package/public/assets/{formatted-body-impl-Bg-gx7rG.js → formatted-body-impl-0Lf8e1Ic.js} +2 -2
- package/public/assets/{formatted-body-impl-Bg-gx7rG.js.map → formatted-body-impl-0Lf8e1Ic.js.map} +1 -1
- package/public/assets/{index-BeDncjN4.js → index-C3su8ezq.js} +6 -6
- package/public/assets/{index-BeDncjN4.js.map → index-C3su8ezq.js.map} +1 -1
- package/public/assets/{insights-c08aW-7n.js → insights-64uExH1E.js} +2 -2
- package/public/assets/{insights-c08aW-7n.js.map → insights-64uExH1E.js.map} +1 -1
- package/public/assets/{integrations-BwpgcqnF.js → integrations-HyC1EaIp.js} +2 -2
- package/public/assets/{integrations-BwpgcqnF.js.map → integrations-HyC1EaIp.js.map} +1 -1
- package/public/assets/{maintenance-CTKP0kWB.js → maintenance-EVBpKH07.js} +2 -2
- package/public/assets/{maintenance-CTKP0kWB.js.map → maintenance-EVBpKH07.js.map} +1 -1
- package/public/assets/{managed-agents-BofCxo8d.js → managed-agents-BLZPxGuw.js} +2 -2
- package/public/assets/{managed-agents-BofCxo8d.js.map → managed-agents-BLZPxGuw.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-CQ-6BIb8.js → markdown-preview-impl-Bg6rCWYN.js} +2 -2
- package/public/assets/{markdown-preview-impl-CQ-6BIb8.js.map → markdown-preview-impl-Bg6rCWYN.js.map} +1 -1
- package/public/assets/{memory-DvfXjMoi.js → memory-Bjr8bgjj.js} +2 -2
- package/public/assets/{memory-DvfXjMoi.js.map → memory-Bjr8bgjj.js.map} +1 -1
- package/public/assets/{messages-C9VsPzZ_.js → messages-CRYw1F4z.js} +2 -2
- package/public/assets/{messages-C9VsPzZ_.js.map → messages-CRYw1F4z.js.map} +1 -1
- package/public/assets/{orchestrators-MffVueeE.js → orchestrators-D-co1vdp.js} +2 -2
- package/public/assets/{orchestrators-MffVueeE.js.map → orchestrators-D-co1vdp.js.map} +1 -1
- package/public/assets/{overview-BSVajefM.js → overview-Ddy5czri.js} +2 -2
- package/public/assets/{overview-BSVajefM.js.map → overview-Ddy5czri.js.map} +1 -1
- package/public/assets/{pairs-B5711-Cs.js → pairs-CFVM8uHL.js} +2 -2
- package/public/assets/{pairs-B5711-Cs.js.map → pairs-CFVM8uHL.js.map} +1 -1
- package/public/assets/{security-DkUwK9Vj.js → security-Df4_76bh.js} +2 -2
- package/public/assets/{security-DkUwK9Vj.js.map → security-Df4_76bh.js.map} +1 -1
- package/public/assets/{select-DrM2RRiT.js → select-Cq3BBnL9.js} +2 -2
- package/public/assets/{select-DrM2RRiT.js.map → select-Cq3BBnL9.js.map} +1 -1
- package/public/assets/{settings-DdKCb-vy.js → settings-DOLEYXZL.js} +2 -2
- package/public/assets/{settings-DdKCb-vy.js.map → settings-DOLEYXZL.js.map} +1 -1
- package/public/assets/{store-iTiheuTD.js → store-C1E8jmNE.js} +4 -4
- package/public/assets/store-C1E8jmNE.js.map +1 -0
- package/public/assets/{tasks-e1y1PFfO.js → tasks-BcsmPi9_.js} +2 -2
- package/public/assets/{tasks-e1y1PFfO.js.map → tasks-BcsmPi9_.js.map} +1 -1
- package/public/assets/{teams-BUcxoGC_.js → teams-BQrV3eKI.js} +2 -2
- package/public/assets/{teams-BUcxoGC_.js.map → teams-BQrV3eKI.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-CmZjQOB2.js → terminal-viewer-impl-Dle04qpH.js} +2 -2
- package/public/assets/{terminal-viewer-impl-CmZjQOB2.js.map → terminal-viewer-impl-Dle04qpH.js.map} +1 -1
- package/public/assets/{work-queue-CXBQx43n.js → work-queue-BLhTLg4o.js} +2 -2
- package/public/assets/{work-queue-CXBQx43n.js.map → work-queue-BLhTLg4o.js.map} +1 -1
- package/public/assets/{workspaces-D2EfZh9a.js → workspaces-4NCNTmRQ.js} +3 -3
- package/public/assets/{workspaces-D2EfZh9a.js.map → workspaces-4NCNTmRQ.js.map} +1 -1
- package/public/index.html +3 -3
- package/runner/src/adapter.ts +2 -1
- package/runner/src/config.ts +143 -5
- package/src/agent-ref.ts +8 -6
- package/src/artifact-storage.ts +3 -5
- package/src/automations/constants.ts +12 -0
- package/src/automations/cron.ts +129 -0
- package/src/automations/crud.ts +84 -0
- package/src/automations/dispatch.ts +275 -0
- package/src/automations/index.ts +5 -0
- package/src/automations/reconcile.ts +245 -0
- package/src/automations/storage.ts +181 -0
- package/src/automations/types.ts +16 -0
- package/src/automations/validation.ts +140 -0
- package/src/automations.ts +1 -1045
- package/src/bus.ts +3 -4
- package/src/cli/_shared.ts +5 -4
- package/src/cli/agent-detect.ts +6 -4
- package/src/cli/introspect.ts +3 -2
- package/src/cli/token.ts +2 -1
- package/src/cli/workspace.ts +2 -1
- package/src/config.ts +176 -1
- package/src/connectors.ts +3 -3
- package/src/db/activity.ts +1 -1
- package/src/db/agent-predicates.ts +9 -0
- package/src/db/agent-search.ts +2 -2
- package/src/db/agents.ts +13 -41
- package/src/db/artifacts.ts +8 -8
- package/src/db/channel-identity.ts +38 -0
- package/src/db/channels.ts +37 -61
- package/src/db/connection.ts +2 -1
- package/src/db/continuation-archives.ts +7 -7
- package/src/db/delivery.ts +7 -12
- package/src/db/inbox.ts +1 -1
- package/src/db/integrations.ts +4 -4
- package/src/db/issue-lifecycle.ts +6 -6
- package/src/db/mappers.ts +1 -2
- package/src/db/merge-lease.ts +3 -3
- package/src/db/message-claims.ts +16 -0
- package/src/db/message-queries.ts +8 -0
- package/src/db/message-reads.ts +26 -9
- package/src/db/messages.ts +17 -41
- package/src/db/notification-subscriptions.ts +2 -2
- package/src/db/orchestrators.ts +4 -4
- package/src/db/pair-maintenance.ts +9 -0
- package/src/db/pairs.ts +10 -18
- package/src/db/plans.ts +1 -1
- package/src/db/policy-runtime.ts +14 -0
- package/src/db/project-entries.ts +1 -1
- package/src/db/projects.ts +2 -2
- package/src/db/shared.ts +7 -0
- package/src/db/stats.ts +2 -2
- package/src/db/task-core.ts +18 -0
- package/src/db/task-maintenance.ts +24 -0
- package/src/db/tasks.ts +5 -17
- package/src/db/teams.ts +3 -3
- package/src/db/workspaces.ts +6 -6
- package/src/index.ts +6 -5
- package/src/issue-tracker/github.ts +3 -3
- package/src/maintenance/constants.ts +52 -0
- package/src/maintenance/events.ts +32 -0
- package/src/maintenance/index.ts +7 -0
- package/src/maintenance/jobs.ts +340 -0
- package/src/maintenance/orphaned-sessions.ts +86 -0
- package/src/maintenance/scheduler.ts +231 -0
- package/src/maintenance/teams.ts +65 -0
- package/src/maintenance/types.ts +31 -0
- package/src/maintenance/workspaces.ts +251 -0
- package/src/maintenance.ts +1 -1099
- package/src/mcp/identity.ts +131 -0
- package/src/mcp/index.ts +208 -0
- package/src/mcp/tools-messaging.ts +459 -0
- package/src/mcp/tools-spawn.ts +145 -0
- package/src/mcp/tools-workspace.ts +227 -0
- package/src/mcp/types.ts +24 -0
- package/src/mcp/validation.ts +104 -0
- package/src/mcp.ts +1 -1319
- package/src/notification-router.ts +2 -2
- package/src/notification-rules.ts +2 -2
- package/src/project-ingest.ts +3 -3
- package/src/project-instructions.ts +1 -1
- package/src/provider-config-store.ts +5 -4
- package/src/provider-state.ts +2 -4
- package/src/reviewer-pipeline.ts +1 -1
- package/src/routes/agent-sessions.ts +5 -4
- package/src/routes/orchestrator-proxy.ts +5 -4
- package/src/routes/workspaces.ts +5 -4
- package/src/security.ts +13 -7
- package/src/self-resume.ts +3 -7
- package/src/services/agent-action.ts +2 -2
- package/src/services/issue-activity.ts +0 -4
- package/src/services/issue-associations.ts +2 -2
- package/src/services/issue-lifecycle.ts +8 -11
- package/src/services/managed-running.ts +1 -1
- package/src/services/parity-harness.ts +3 -3
- package/src/services/plan-graph.ts +4 -7
- package/src/services/send-message.ts +16 -12
- package/src/services/shutdown-agent.ts +2 -2
- package/src/services/team-templates.ts +2 -2
- package/src/services/team.ts +2 -2
- package/src/settings/modules.ts +1 -1
- package/src/settings/registry.ts +3 -3
- package/src/spawn-command.ts +1 -1
- package/src/sse.ts +0 -4
- package/src/upgrade.ts +7 -9
- package/src/workspace-actions.ts +1 -1
- package/src/workspace-auto-merge.ts +4 -5
- package/src/workspace-claim.ts +1 -2
- package/src/workspace-orphans.ts +2 -7
- package/src/workspace-probe.ts +5 -8
- package/public/assets/MessageBubble-DRrxfjyT.js.map +0 -1
- package/public/assets/display-DzNvOu1j.js.map +0 -1
- package/public/assets/store-iTiheuTD.js.map +0 -1
|
@@ -57,7 +57,7 @@ export interface NotificationScope {
|
|
|
57
57
|
paths?: string[];
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
interface NotificationMessage {
|
|
61
61
|
subject?: string;
|
|
62
62
|
body: string;
|
|
63
63
|
payload?: Record<string, unknown>;
|
|
@@ -67,7 +67,7 @@ export interface NotificationMessage {
|
|
|
67
67
|
replyExpected?: boolean;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
interface RouteNotificationInput {
|
|
71
71
|
type: NotificationType;
|
|
72
72
|
scope: NotificationScope;
|
|
73
73
|
/**
|
|
@@ -33,7 +33,7 @@ export interface NotificationRule {
|
|
|
33
33
|
evaluate(agent: AgentCard, ctx: NotificationRuleContext): RuleDecision;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
interface AudienceMember {
|
|
37
37
|
agentId: string;
|
|
38
38
|
/** The rule whose decision was decisive (last non-abstain wins) — carried for explainability (#446). */
|
|
39
39
|
matchedRule: string;
|
|
@@ -161,7 +161,7 @@ export function setSubscriptionRules(rules: NotificationRule[]): void {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
/** The effective ordered rule list for a type: its registered defaults, then subscription overrides. */
|
|
164
|
-
|
|
164
|
+
function audienceRulesFor(type: NotificationType): NotificationRule[] {
|
|
165
165
|
const defaults = audienceRegistry.get(type);
|
|
166
166
|
if (!defaults) return [];
|
|
167
167
|
return subscriptionRules.length === 0 ? defaults : [...defaults, ...subscriptionRules];
|
package/src/project-ingest.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type { ProjectEntry } from "./types";
|
|
|
16
16
|
|
|
17
17
|
const INGEST_FILENAME = "CLAUDE.md";
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
interface ParsedSection {
|
|
20
20
|
/** Heading text (the entry title). For pre-heading preamble content: "(preamble)". */
|
|
21
21
|
title: string;
|
|
22
22
|
/** Section body — lines under the heading up to the next heading, trimmed. May be "". */
|
|
@@ -25,14 +25,14 @@ export interface ParsedSection {
|
|
|
25
25
|
anchor: string;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
interface IngestRootResult {
|
|
29
29
|
rootPath: string;
|
|
30
30
|
filePath: string;
|
|
31
31
|
found: boolean;
|
|
32
32
|
sections: number;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
interface IngestResult {
|
|
36
36
|
projectId: string;
|
|
37
37
|
created: number;
|
|
38
38
|
updated: number;
|
|
@@ -31,7 +31,7 @@ export interface ProjectInstructionPolicy {
|
|
|
31
31
|
policy?: ProjectInstructionPolicyName;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
interface ComposeProjectInstructionsOptions {
|
|
35
35
|
/** Named policy selecting the included source set. Default `all`. */
|
|
36
36
|
policy?: ProjectInstructionPolicyName;
|
|
37
37
|
/** Explicit source set; overrides `policy` when given (the low-level lever). */
|
|
@@ -3,6 +3,7 @@ import { hostname } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { ValidationError, listOrchestrators } from "./db";
|
|
5
5
|
import { getConfig, listConfig, setConfig } from "./config-store";
|
|
6
|
+
import { providerConfigHomeFromEnv } from "./config";
|
|
6
7
|
import { cleanString, cleanStringArray, optionalEnum } from "./validation";
|
|
7
8
|
import { emitConfigChanged } from "./sse";
|
|
8
9
|
import {
|
|
@@ -24,15 +25,15 @@ export const VALID_PROVIDER_CONFIGS = SPAWN_PROVIDERS;
|
|
|
24
25
|
type ProviderConfigProvider = string;
|
|
25
26
|
type ProviderConfigEntry = ConfigEntry<ProviderConfig>;
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
function defaultProviderConfigHost(): string {
|
|
28
29
|
return hostname();
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
function providerConfigKey(host: string, provider: string): string {
|
|
32
33
|
return `${normalizeProviderConfigHost(host)}/${normalizeProviderConfigProvider(provider)}`;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
function parseProviderConfigKey(key: string): { host: string; provider: ProviderConfigProvider } | null {
|
|
36
37
|
const slash = key.lastIndexOf("/");
|
|
37
38
|
if (slash <= 0 || slash === key.length - 1) return null;
|
|
38
39
|
const host = cleanString(key.slice(0, slash), "host", { required: true, max: 120 })!;
|
|
@@ -234,5 +235,5 @@ function maskEnv(env: Record<string, string>): Record<string, string> {
|
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
function agentRelayHome(): string {
|
|
237
|
-
return
|
|
238
|
+
return providerConfigHomeFromEnv();
|
|
238
239
|
}
|
package/src/provider-state.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isRecord } from "agent-relay-sdk";
|
|
2
|
+
import { rateLimitFallbackMs } from "./config";
|
|
2
3
|
|
|
3
4
|
// One server-side home for reading an agent's provider runtime state (the
|
|
4
5
|
// `meta.providerState` that both Claude and Codex ride for blocked/approval
|
|
@@ -6,7 +7,7 @@ import { isRecord } from "agent-relay-sdk";
|
|
|
6
7
|
// the transient-agent reaper (don't reap a held agent), and the rate-limit
|
|
7
8
|
// resume sweep. The dashboard has its own client-side copy in display.ts.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
interface ProviderStateView {
|
|
10
11
|
state: string;
|
|
11
12
|
reason?: string;
|
|
12
13
|
label?: string;
|
|
@@ -48,9 +49,6 @@ export function isRateLimitHold(agent: HasMeta | null | undefined): boolean {
|
|
|
48
49
|
// rather than waiting the full (unknown) limit window. Re-entering the hold on a
|
|
49
50
|
// still-limited retry is cheap, and a subscription limit almost always carries a
|
|
50
51
|
// reset time. Read at call-time so operators/tests can tune it.
|
|
51
|
-
const rateLimitFallbackMs = (): number =>
|
|
52
|
-
Number(process.env.AGENT_RELAY_RATE_LIMIT_FALLBACK_MS) || 60 * 60 * 1000;
|
|
53
|
-
|
|
54
52
|
/**
|
|
55
53
|
* When a rate-limit hold should be lifted. The provider's `resetAt` is
|
|
56
54
|
* authoritative; otherwise fall back to `enteredAt + fallback window`. Null only
|
package/src/reviewer-pipeline.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { Command, WorkspaceMergePreview, WorkspaceRecord } from "./types";
|
|
|
9
9
|
|
|
10
10
|
type ReviewDecision = "APPROVED" | "CHANGES_REQUESTED" | "REVIEW_REQUIRED";
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
function parsePrNumber(prUrl: string | undefined): number | undefined {
|
|
13
13
|
if (!prUrl) return undefined;
|
|
14
14
|
const match = prUrl.match(/\/pull\/(\d+)(?:\D|$)/);
|
|
15
15
|
if (!match) return undefined;
|
|
@@ -14,6 +14,7 @@ import { authContextFromRequest } from "../services/auth-context";
|
|
|
14
14
|
import { ShutdownAuthError, ShutdownTargetError, shutdownAgent } from "../services/shutdown-agent";
|
|
15
15
|
import { type AgentCard, type SpawnApprovalMode } from "../types";
|
|
16
16
|
import { type ProviderEffort } from "agent-relay-sdk/provider-catalog";
|
|
17
|
+
import { relayToken } from "../config";
|
|
17
18
|
|
|
18
19
|
const CLAUDE_RESUME_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
19
20
|
|
|
@@ -486,8 +487,8 @@ async function proxyOrchestratorDelete(req: Request, orchestratorId: string, pat
|
|
|
486
487
|
const incoming = new URL(req.url);
|
|
487
488
|
const proxyUrl = `${orch.apiUrl}${path}${incoming.search}`;
|
|
488
489
|
const headers: Record<string, string> = {};
|
|
489
|
-
const
|
|
490
|
-
if (
|
|
490
|
+
const token = relayToken();
|
|
491
|
+
if (token) headers[RELAY_TOKEN_HEADER] = token;
|
|
491
492
|
try {
|
|
492
493
|
const res = await fetch(proxyUrl, {
|
|
493
494
|
method: "DELETE",
|
|
@@ -507,8 +508,8 @@ async function proxyOrchestratorJson(orchestratorId: string, path: string, metho
|
|
|
507
508
|
if (!orch.apiUrl) return error("orchestrator does not expose an API", 422);
|
|
508
509
|
if (orch.status !== "online") return error("orchestrator is offline", 422);
|
|
509
510
|
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
510
|
-
const
|
|
511
|
-
if (
|
|
511
|
+
const token = relayToken();
|
|
512
|
+
if (token) headers[RELAY_TOKEN_HEADER] = token;
|
|
512
513
|
try {
|
|
513
514
|
const res = await fetch(`${orch.apiUrl}${path}`, {
|
|
514
515
|
method,
|
|
@@ -5,6 +5,7 @@ import { authorizeRoute, cleanJsonArray, error, json, type Handler } from "./_sh
|
|
|
5
5
|
import { cleanStringArray } from "../validation";
|
|
6
6
|
import { emitOrchestratorStatus } from "../sse";
|
|
7
7
|
import { type OrchestratorRuntimeInput, type SpawnProvider } from "../types";
|
|
8
|
+
import { relayToken } from "../config";
|
|
8
9
|
|
|
9
10
|
export const getOrchestratorDirectories: Handler = async (req, params) => {
|
|
10
11
|
const orch = getOrchestrator(params.id!);
|
|
@@ -63,8 +64,8 @@ async function proxyOrchestratorGet(req: Request, orchestratorId: string, path:
|
|
|
63
64
|
const incoming = new URL(req.url);
|
|
64
65
|
const proxyUrl = `${orch.apiUrl}${path}${incoming.search}`;
|
|
65
66
|
const headers: Record<string, string> = {};
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
67
|
+
const token = relayToken();
|
|
68
|
+
if (token) headers[RELAY_TOKEN_HEADER] = token;
|
|
68
69
|
try {
|
|
69
70
|
const res = await fetch(proxyUrl, { headers, signal: AbortSignal.timeout(10_000) });
|
|
70
71
|
const contentType = res.headers.get("content-type") ?? "";
|
|
@@ -88,8 +89,8 @@ async function proxyOrchestratorPost(req: Request, orchestratorId: string, path:
|
|
|
88
89
|
const headers: Record<string, string> = {
|
|
89
90
|
"Content-Type": req.headers.get("content-type") ?? "application/json",
|
|
90
91
|
};
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
92
|
+
const token = relayToken();
|
|
93
|
+
if (token) headers[RELAY_TOKEN_HEADER] = token;
|
|
93
94
|
try {
|
|
94
95
|
const body = await req.text();
|
|
95
96
|
const res = await fetch(proxyUrl, {
|
package/src/routes/workspaces.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { resolve } from "node:path";
|
|
|
13
13
|
import { type WorkspaceAutoMergePolicy, type WorkspaceDiagnostics, type WorkspaceGitState, type WorkspaceMergeStrategy, type WorkspaceRecord, type WorkspaceStatus } from "../types";
|
|
14
14
|
import { AUTO_MERGE_POLICIES } from "../workspace-merge";
|
|
15
15
|
import { workspaceActiveClaim } from "../workspace-claim";
|
|
16
|
+
import { relayToken } from "../config";
|
|
16
17
|
|
|
17
18
|
export const getWorkspaces: Handler = (req) => {
|
|
18
19
|
try {
|
|
@@ -50,8 +51,8 @@ async function proxyWorkspaceHostGet(workspaceId: string, hostPath: string, extr
|
|
|
50
51
|
if (workspace.baseSha) query.set("baseSha", workspace.baseSha);
|
|
51
52
|
for (const [key, value] of Object.entries(extraQuery ?? {})) query.set(key, value);
|
|
52
53
|
const headers: Record<string, string> = {};
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
54
|
+
const token = relayToken();
|
|
55
|
+
if (token) headers[RELAY_TOKEN_HEADER] = token;
|
|
55
56
|
try {
|
|
56
57
|
const res = await fetch(`${orch.apiUrl}${hostPath}?${query.toString()}`, {
|
|
57
58
|
headers,
|
|
@@ -145,8 +146,8 @@ async function fetchWorkspaceGitState(workspace: WorkspaceRecord): Promise<{ sta
|
|
|
145
146
|
if (workspace.baseRef) query.set("baseRef", workspace.baseRef);
|
|
146
147
|
if (workspace.baseSha) query.set("baseSha", workspace.baseSha);
|
|
147
148
|
const headers: Record<string, string> = {};
|
|
148
|
-
const
|
|
149
|
-
if (
|
|
149
|
+
const token = relayToken();
|
|
150
|
+
if (token) headers[RELAY_TOKEN_HEADER] = token;
|
|
150
151
|
try {
|
|
151
152
|
const res = await fetch(`${orch.apiUrl}/api/workspace/state?${query.toString()}`, { headers, signal: AbortSignal.timeout(10_000) });
|
|
152
153
|
if (!res.ok) return { unavailable: `host returned ${res.status}` };
|
package/src/security.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
CORS_ORIGINS,
|
|
3
|
+
allowUnauthenticated,
|
|
4
|
+
corsOriginsFromEnv,
|
|
5
|
+
getIntegrationTokens,
|
|
6
|
+
relayToken,
|
|
7
|
+
tokenSecretFromEnv,
|
|
8
|
+
type IntegrationTokenConfig,
|
|
9
|
+
} from "./config";
|
|
2
10
|
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
3
11
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
12
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -14,7 +22,7 @@ export function isLoopbackHost(hostname: string): boolean {
|
|
|
14
22
|
}
|
|
15
23
|
|
|
16
24
|
export function assertSafeNetworkConfig(host: string): void {
|
|
17
|
-
if (authToken() ||
|
|
25
|
+
if (authToken() || allowUnauthenticated()) return;
|
|
18
26
|
if (isLoopbackHost(host)) return;
|
|
19
27
|
throw new Error(
|
|
20
28
|
`Refusing to bind unauthenticated relay on ${host}. Set AGENT_RELAY_TOKEN or AGENT_RELAY_ALLOW_UNAUTH=1.`,
|
|
@@ -407,7 +415,7 @@ export function unauthorized(req: Request): Response {
|
|
|
407
415
|
}
|
|
408
416
|
|
|
409
417
|
function authToken(): string {
|
|
410
|
-
return
|
|
418
|
+
return relayToken();
|
|
411
419
|
}
|
|
412
420
|
|
|
413
421
|
function extractToken(req: Request): string | null {
|
|
@@ -417,7 +425,7 @@ function extractToken(req: Request): string | null {
|
|
|
417
425
|
}
|
|
418
426
|
|
|
419
427
|
function tokenSecret(): string {
|
|
420
|
-
const env =
|
|
428
|
+
const env = tokenSecretFromEnv();
|
|
421
429
|
if (env) return env;
|
|
422
430
|
const path = join(process.env.HOME || ".", ".agent-relay", "token-secret");
|
|
423
431
|
if (existsSync(path)) return readFileSync(path, "utf8").trim();
|
|
@@ -542,7 +550,5 @@ function isTokenRevoked(jti: string): boolean {
|
|
|
542
550
|
}
|
|
543
551
|
|
|
544
552
|
function corsOrigins(): string[] {
|
|
545
|
-
|
|
546
|
-
if (raw === undefined) return CORS_ORIGINS;
|
|
547
|
-
return raw.split(",").map((origin) => origin.trim()).filter(Boolean);
|
|
553
|
+
return corsOriginsFromEnv() ?? CORS_ORIGINS;
|
|
548
554
|
}
|
package/src/self-resume.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { emitRelayEvent } from "./events";
|
|
|
14
14
|
import { routeNotification } from "./notification-router";
|
|
15
15
|
import type { AgentCard, Command, ContinuationEnvelope, ContinuationLedgerEntry, SelfResumeMode } from "./types";
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
interface CompactAndResumeInput {
|
|
18
18
|
agentId: string;
|
|
19
19
|
workingState: string;
|
|
20
20
|
ruledOut?: unknown;
|
|
@@ -22,7 +22,7 @@ export interface CompactAndResumeInput {
|
|
|
22
22
|
objective?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
interface CompactAndResumeResult {
|
|
26
26
|
ok: boolean;
|
|
27
27
|
mode: SelfResumeMode;
|
|
28
28
|
envelope: ContinuationEnvelope;
|
|
@@ -110,7 +110,7 @@ export function enqueueContinuationInjectionAfterClear(command: Command): Comman
|
|
|
110
110
|
return inject;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
function renderContinuation(envelope: ContinuationEnvelope): string {
|
|
114
114
|
const ledger = envelope.ledger.length
|
|
115
115
|
? envelope.ledger.map((entry) => `- gen ${entry.gen} @ ${new Date(entry.at).toISOString()}: ${entry.ruledOut}${entry.why ? `; why: ${entry.why}` : ""}`).join("\n")
|
|
116
116
|
: "- none";
|
|
@@ -231,7 +231,3 @@ function ledgerEntry(ruledOut: string, why: string, generation: number, now: num
|
|
|
231
231
|
if (!cleaned) throw new ValidationError("ruledOut entries cannot be blank");
|
|
232
232
|
return { gen: generation, ruledOut: cleaned, why, at: now };
|
|
233
233
|
}
|
|
234
|
-
|
|
235
|
-
export function continuationForAgent(agentId: string): ContinuationEnvelope | null {
|
|
236
|
-
return getContinuationEnvelope(agentId);
|
|
237
|
-
}
|
|
@@ -8,7 +8,7 @@ import type { AgentCard, Command } from "../types";
|
|
|
8
8
|
|
|
9
9
|
export type AgentAction = "compact" | "clearContext" | "inject";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
interface AgentActionInput {
|
|
12
12
|
agentId: string;
|
|
13
13
|
action: AgentAction;
|
|
14
14
|
message?: string;
|
|
@@ -16,7 +16,7 @@ export interface AgentActionInput {
|
|
|
16
16
|
requestedBy?: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
interface AgentActionResult {
|
|
20
20
|
action: AgentAction;
|
|
21
21
|
command: Command;
|
|
22
22
|
}
|
|
@@ -24,7 +24,3 @@ export function recordAndEmitIssueActivity(input: RecordIssueActivityInput) {
|
|
|
24
24
|
emitActivityEvent(event);
|
|
25
25
|
return event;
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
export function resolveIssueActivityMapping(input: { issueRefId?: string; issueRef?: string; defaultRepo?: string; provider?: IssueProvider }) {
|
|
29
|
-
return resolveIssueActivityRef(input);
|
|
30
|
-
}
|
|
@@ -8,7 +8,7 @@ import { getIssueRef, resolveIssueRefByExternalKey, resolveIssueRefFromString }
|
|
|
8
8
|
import type { IssueAssociationEntityType, IssueAssociationIssue, IssueProvider } from "../types";
|
|
9
9
|
import { ValidationError } from "../db/connection";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
interface ResolveAssociationIssueInput {
|
|
12
12
|
issueRefId?: string;
|
|
13
13
|
ref?: string;
|
|
14
14
|
defaultRepo?: string;
|
|
@@ -19,7 +19,7 @@ export interface ResolveAssociationIssueInput {
|
|
|
19
19
|
title?: string;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
interface AssociateIssueInput extends ResolveAssociationIssueInput {
|
|
23
23
|
entityType: IssueAssociationEntityType;
|
|
24
24
|
entityId: string;
|
|
25
25
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { getIssueRef, resolveIssueRefByExternalKey, resolveIssueRefFromString, updateIssueRef } from "../db/issue-refs";
|
|
10
10
|
import { associateIssue } from "../db/issue-associations";
|
|
11
11
|
import { resolveIssueTrackerAdapter } from "../issue-tracker";
|
|
12
|
+
import { defaultIssueRepo } from "../config";
|
|
12
13
|
import type { IssueTrackerAdapter } from "../issue-tracker";
|
|
13
14
|
import { recordAndEmitIssueActivity } from "./issue-activity";
|
|
14
15
|
import type { IssueAssociationEntityType, IssueProvider, IssueRef, WorkspaceRecord } from "../types";
|
|
@@ -17,7 +18,7 @@ type LifecycleWorkspace = Pick<WorkspaceRecord, "id" | "repoRoot" | "branch" | "
|
|
|
17
18
|
type AdapterResolver = (ref: IssueRef) => IssueTrackerAdapter;
|
|
18
19
|
type LogFn = (message: string) => void;
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
interface LandedIssueLifecycleInput {
|
|
21
22
|
workspace: LifecycleWorkspace;
|
|
22
23
|
mergedSha?: string;
|
|
23
24
|
subject?: string;
|
|
@@ -31,7 +32,7 @@ export interface LandedIssueLifecycleInput {
|
|
|
31
32
|
prLand?: boolean;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
interface ReopenIssueLifecycleInput {
|
|
35
36
|
issueRefId?: string;
|
|
36
37
|
ref?: string;
|
|
37
38
|
defaultRepo?: string;
|
|
@@ -46,19 +47,19 @@ export interface ReopenIssueLifecycleInput {
|
|
|
46
47
|
entityId?: string;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
interface IssueLifecycleOptions {
|
|
50
51
|
adapterResolver?: AdapterResolver;
|
|
51
52
|
log?: LogFn;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
type LandIssueRefSource = "association" | "commit" | "backlink";
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
type CloseIssueLifecycleResult =
|
|
57
58
|
| { issueRef: IssueRef; action: "closed"; source: LandIssueRefSource; landKey: string }
|
|
58
59
|
| { issueRef: IssueRef; action: "skipped"; reason: "already-closed" | "already-processed"; landKey: string }
|
|
59
60
|
| { issueRef: IssueRef; action: "failed"; error: string; landKey: string };
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
type ReopenIssueLifecycleResult =
|
|
62
63
|
| { issueRef: IssueRef; action: "reopened"; landKey: string }
|
|
63
64
|
| { issueRef: IssueRef; action: "skipped"; reason: "already-open"; landKey: string }
|
|
64
65
|
| { issueRef: IssueRef; action: "failed"; error: string; landKey: string };
|
|
@@ -78,10 +79,6 @@ function logFailure(opts: IssueLifecycleOptions, message: string): void {
|
|
|
78
79
|
else console.warn(message);
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
function defaultIssueRepo(): string | undefined {
|
|
82
|
-
return process.env.AGENT_RELAY_DEFAULT_ISSUE_REPO || process.env.GITHUB_REPOSITORY || undefined;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
82
|
/**
|
|
86
83
|
* `owner/repo` out of any git remote URL form: `git@github.com:owner/repo.git`,
|
|
87
84
|
* `https://github.com/owner/repo.git`, `ssh://git@host/owner/repo`, trailing slash/`.git`
|
|
@@ -210,7 +207,7 @@ export function parseBacklinkIssueRefs(text: string | undefined, fallbackDefault
|
|
|
210
207
|
return issueRefMap(refs);
|
|
211
208
|
}
|
|
212
209
|
|
|
213
|
-
|
|
210
|
+
function resolveIssueRefsForLand(input: LandedIssueLifecycleInput): { source: LandIssueRefSource; refs: IssueRef[] } {
|
|
214
211
|
const associated = associatedIssueRefs(input.workspace);
|
|
215
212
|
if (associated.length > 0) return { source: "association", refs: associated };
|
|
216
213
|
const fallbackDefaultRepo = landDefaultRepo(input.workspace);
|
|
@@ -19,7 +19,7 @@ import { emitMessageAvailable, emitMessageDeliveryUpdated, emitNewMessage } from
|
|
|
19
19
|
import type { AuthContext } from "./auth-context";
|
|
20
20
|
import type { ManagedAgentState } from "../types";
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
interface ManagedRunningInput {
|
|
23
23
|
policyName?: string;
|
|
24
24
|
spawnRequestId?: string;
|
|
25
25
|
agentId: string;
|
|
@@ -15,7 +15,7 @@ import { subscribeRelayEvents } from "../events";
|
|
|
15
15
|
/** An emitted relay event, normalized to the fields parity compares — volatile
|
|
16
16
|
* `seq`/`timestamp` are deliberately dropped so only behavior, not ordering noise,
|
|
17
17
|
* is asserted. */
|
|
18
|
-
|
|
18
|
+
interface CapturedEvent {
|
|
19
19
|
type: string;
|
|
20
20
|
source: string;
|
|
21
21
|
subject?: string;
|
|
@@ -36,7 +36,7 @@ export interface Capture<S> {
|
|
|
36
36
|
* settled so the harness can snapshot. Keep the abstraction swappable: a later slice
|
|
37
37
|
* can replace a direct-call transport with an end-to-end HTTP one without reshaping
|
|
38
38
|
* the harness. */
|
|
39
|
-
|
|
39
|
+
interface ParityTransport<C> {
|
|
40
40
|
id: string;
|
|
41
41
|
invoke(ctx: C): Promise<void>;
|
|
42
42
|
}
|
|
@@ -57,7 +57,7 @@ export interface ParityOp<C, S> {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/** Drive one transport in isolation and capture everything it produced. */
|
|
60
|
-
|
|
60
|
+
async function captureTransport<C, S>(
|
|
61
61
|
op: ParityOp<C, S>,
|
|
62
62
|
transportId: string,
|
|
63
63
|
ctx: C,
|
|
@@ -4,12 +4,13 @@ import { associateIssue, planNodeIssueEntityId, removeAssociation } from "../db/
|
|
|
4
4
|
import { resolveIssueRefFromString } from "../db/issue-refs";
|
|
5
5
|
import { emitRelayEvent } from "../events";
|
|
6
6
|
import { cleanString, cleanStringArray, optionalEnum } from "../validation";
|
|
7
|
+
import { defaultIssueRepo } from "../config";
|
|
7
8
|
import type { AuthContext } from "./auth-context";
|
|
8
9
|
import type { AgentCard, Plan, PlanEdge, PlanNode, PlanOwnerRef, PlanStatus } from "../types";
|
|
9
10
|
|
|
10
11
|
export const PLAN_STATUSES = ["pending", "in-progress", "landed", "blocked"] as const;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
interface PlanNodeInput {
|
|
13
14
|
id?: unknown;
|
|
14
15
|
label?: unknown;
|
|
15
16
|
scopeBlurb?: unknown;
|
|
@@ -21,7 +22,7 @@ export interface PlanNodeInput {
|
|
|
21
22
|
blackboardRefs?: unknown;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
interface PlanNodePatch {
|
|
25
26
|
label?: unknown;
|
|
26
27
|
scopeBlurb?: unknown;
|
|
27
28
|
ownerRef?: unknown;
|
|
@@ -32,7 +33,7 @@ export interface PlanNodePatch {
|
|
|
32
33
|
blackboardRefs?: unknown;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
interface PlanCreateInput {
|
|
36
37
|
threadId: unknown;
|
|
37
38
|
teamId?: unknown;
|
|
38
39
|
channel?: unknown;
|
|
@@ -86,10 +87,6 @@ function cleanRefs(value: unknown): PlanNode["refs"] | undefined {
|
|
|
86
87
|
return Object.keys(out).length ? out : undefined;
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
function defaultIssueRepo(): string | undefined {
|
|
90
|
-
return process.env.AGENT_RELAY_DEFAULT_ISSUE_REPO || process.env.GITHUB_REPOSITORY || undefined;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
90
|
function syncPlanNodeIssueAssociation(planId: string, node: PlanNode): void {
|
|
94
91
|
if (!node.refs?.issueId) return;
|
|
95
92
|
associateIssue(node.refs.issueId, "plan-node", planNodeIssueEntityId(planId, node.id));
|
|
@@ -22,7 +22,14 @@
|
|
|
22
22
|
// OUT OF SCOPE (transport-edge, excluded from the parity facet): automatic memory injection
|
|
23
23
|
// (needs request-derived context) and per-transport audit (HTTP domain row vs MCP tool-call row).
|
|
24
24
|
import { isMechanicalMessageKind, isRecord, isReservedAgentId } from "agent-relay-sdk";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
ValidationError,
|
|
27
|
+
getMessage,
|
|
28
|
+
listAgents,
|
|
29
|
+
sendMessageWithResult,
|
|
30
|
+
channelObligationAnsweredBy,
|
|
31
|
+
spawnObligationAnsweredBy,
|
|
32
|
+
} from "../db";
|
|
26
33
|
import { planSend, type DeliveryReceipt } from "../agent-ref";
|
|
27
34
|
import { emitMessageQueued, emitNewMessage } from "../sse";
|
|
28
35
|
import { getLifecycleManager } from "../lifecycle-manager";
|
|
@@ -32,14 +39,14 @@ import type { AuthContext } from "./auth-context";
|
|
|
32
39
|
import type { IntegrationTokenConfig } from "../config";
|
|
33
40
|
import type { Message, SendMessageInput } from "../types";
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
interface SendMessageResult {
|
|
36
43
|
message: Message;
|
|
37
44
|
created: boolean;
|
|
38
45
|
/** Synchronous delivery receipt (live recipients / queued / store-ahead). */
|
|
39
46
|
receipt: DeliveryReceipt;
|
|
40
47
|
}
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
interface SendMessageOptions {
|
|
43
50
|
/** The integration token when the MCP caller authenticated with one. AuthContext stays lean
|
|
44
51
|
* (foundation contract) — the integration-specific target policy rides here, not on the ctx. */
|
|
45
52
|
integration?: IntegrationTokenConfig | null;
|
|
@@ -159,16 +166,13 @@ export function sendMessageService(
|
|
|
159
166
|
// Resolve BEFORE authorize so both run against the canonical id (kills the HTTP-authorizes-raw
|
|
160
167
|
// vs MCP-authorizes-resolved drift).
|
|
161
168
|
const receipt = resolveSendTarget(input, input.from);
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
// exactly ONE open obligation on that channel this send is unambiguously the answer — link it here,
|
|
167
|
-
// at send time, so the obligation clears with no extra message. (`channelObligationAnsweredBy` is a
|
|
168
|
-
// no-op unless `to` resolved to a channel agent with a single open obligation; deciding at send time
|
|
169
|
-
// — not query time — keeps a later sibling conversation from retroactively mis-attributing it.)
|
|
169
|
+
// Reply-obligation linking: some real answers are ordinary sends without replyTo/thread linkage.
|
|
170
|
+
// Channel bridge replies and spawn report-backs both have a single unambiguous open obligation case;
|
|
171
|
+
// link those at send time so the obligation clears with one message and the Stop hook does not nag
|
|
172
|
+
// the agent into a redundant `/reply`.
|
|
170
173
|
if (!input.replyTo && !isMechanicalMessageKind(input.kind)) {
|
|
171
|
-
const answered = channelObligationAnsweredBy(input.from, input.to)
|
|
174
|
+
const answered = channelObligationAnsweredBy(input.from, input.to)
|
|
175
|
+
?? spawnObligationAnsweredBy(input.from, input.to);
|
|
172
176
|
if (answered !== null) input.replyTo = answered;
|
|
173
177
|
}
|
|
174
178
|
authorizeSend(input, ctx, opts, reservedSink);
|
|
@@ -50,7 +50,7 @@ export class ShutdownTargetError extends Error {}
|
|
|
50
50
|
|
|
51
51
|
type OnlineOrchestrator = NonNullable<ReturnType<typeof getOrchestrator>>;
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
interface ShutdownAgentInput {
|
|
54
54
|
agentId?: string;
|
|
55
55
|
policyName?: string;
|
|
56
56
|
spawnRequestId?: string;
|
|
@@ -69,7 +69,7 @@ export interface ShutdownAgentInput {
|
|
|
69
69
|
auditMetadata?: Record<string, unknown>;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
interface ShutdownAgentResult {
|
|
73
73
|
command: Command;
|
|
74
74
|
orchestratorId: string;
|
|
75
75
|
agent: AgentCard | null;
|
|
@@ -8,7 +8,7 @@ import { setCallerTeamBrief } from "./team";
|
|
|
8
8
|
import { spawnAgent, type SpawnAgentInput, type SpawnAgentResult } from "./spawn-agent";
|
|
9
9
|
import type { AgentLifecycle, SpawnApprovalMode, SpawnProvider, TeamTemplate, TeamTemplateCompositionEntry, WorkspaceMode } from "../types";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
interface TeamTemplateInstantiateInput {
|
|
12
12
|
slug: string;
|
|
13
13
|
orchestratorId?: unknown;
|
|
14
14
|
cwd?: unknown;
|
|
@@ -19,7 +19,7 @@ export interface TeamTemplateInstantiateInput {
|
|
|
19
19
|
waitForRegistrationMs?: unknown;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
interface TeamTemplateInstantiateResult {
|
|
23
23
|
template: TeamTemplate;
|
|
24
24
|
team: ReturnType<typeof setCallerTeamBrief>["team"];
|
|
25
25
|
spawned: SpawnAgentResult[];
|
package/src/services/team.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { Team } from "../types";
|
|
|
7
7
|
export class TeamAuthError extends Error {}
|
|
8
8
|
export class TeamNotFoundError extends Error {}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface TeamPayload {
|
|
11
11
|
team: Team;
|
|
12
12
|
roster: ReturnType<typeof getTeamRoster>;
|
|
13
13
|
brief: string | null;
|
|
@@ -16,7 +16,7 @@ export interface TeamPayload {
|
|
|
16
16
|
issues: ReturnType<typeof listIssueRefsForEntity>;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
interface TeamBriefInput {
|
|
20
20
|
title?: string;
|
|
21
21
|
brief?: string;
|
|
22
22
|
definitionOfDone?: string;
|
package/src/settings/modules.ts
CHANGED