agent-relay-server 0.60.1 → 0.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/openapi.json +361 -1
- package/package.json +3 -2
- package/public/assets/{MessageBubble-vzupFQD8.js → MessageBubble-CX63ZV4X.js} +2 -2
- package/public/assets/{MessageBubble-vzupFQD8.js.map → MessageBubble-CX63ZV4X.js.map} +1 -1
- package/public/assets/{PlanGraphPanel-DQvycBMW.js → PlanGraphPanel-Dby7wq9c.js} +2 -2
- package/public/assets/{PlanGraphPanel-DQvycBMW.js.map → PlanGraphPanel-Dby7wq9c.js.map} +1 -1
- package/public/assets/{activity-gmfkOBhQ.js → activity-2xPOScu_.js} +2 -2
- package/public/assets/{activity-gmfkOBhQ.js.map → activity-2xPOScu_.js.map} +1 -1
- package/public/assets/{agent-profiles-7X8gFuwj.js → agent-profiles-BfGTTbeY.js} +2 -2
- package/public/assets/{agent-profiles-7X8gFuwj.js.map → agent-profiles-BfGTTbeY.js.map} +1 -1
- package/public/assets/agents-Bg3WOBRV.js +2 -0
- package/public/assets/{agents-D201CuTR.js.map → agents-Bg3WOBRV.js.map} +1 -1
- package/public/assets/{analytics-CkOTrr5t.js → analytics-De0cEZGx.js} +3 -3
- package/public/assets/{analytics-CkOTrr5t.js.map → analytics-De0cEZGx.js.map} +1 -1
- package/public/assets/{automation-_5u-nVs8.js → automation-CHxhzq2t.js} +2 -2
- package/public/assets/{automation-_5u-nVs8.js.map → automation-CHxhzq2t.js.map} +1 -1
- package/public/assets/{badge-Cy6qO_Jz.js → badge-DhLyCPag.js} +2 -2
- package/public/assets/{badge-Cy6qO_Jz.js.map → badge-DhLyCPag.js.map} +1 -1
- package/public/assets/branch-state-badge-DSyWKluD.js +2 -0
- package/public/assets/{branch-state-badge-BPXXLpQG.js.map → branch-state-badge-DSyWKluD.js.map} +1 -1
- package/public/assets/{button-73wpRw65.js → button-K20wAZG1.js} +2 -2
- package/public/assets/{button-73wpRw65.js.map → button-K20wAZG1.js.map} +1 -1
- package/public/assets/card-CcZ9hLI7.js +2 -0
- package/public/assets/{card-BU6PvVHv.js.map → card-CcZ9hLI7.js.map} +1 -1
- package/public/assets/{channels-BsJu5TXR.js → channels-BG0Nib7y.js} +2 -2
- package/public/assets/{channels-BsJu5TXR.js.map → channels-BG0Nib7y.js.map} +1 -1
- package/public/assets/chat-CjP_crSl.js +2 -0
- package/public/assets/{chat-CHgPGHQD.js.map → chat-CjP_crSl.js.map} +1 -1
- package/public/assets/{connectors-arjfBQvc.js → connectors-DWh7MwV_.js} +2 -2
- package/public/assets/{connectors-arjfBQvc.js.map → connectors-DWh7MwV_.js.map} +1 -1
- package/public/assets/{copy-button-HRopUwui.js → copy-button-eF3cKp4Q.js} +2 -2
- package/public/assets/{copy-button-HRopUwui.js.map → copy-button-eF3cKp4Q.js.map} +1 -1
- package/public/assets/display-DzNvOu1j.js +3 -0
- package/public/assets/{display-CketawEF.js.map → display-DzNvOu1j.js.map} +1 -1
- package/public/assets/{dist-Kkpnjx_M.js → dist-1dhfdhm9.js} +2 -2
- package/public/assets/{dist-Kkpnjx_M.js.map → dist-1dhfdhm9.js.map} +1 -1
- package/public/assets/dist-BLBF7qqr.js +2 -0
- package/public/assets/{dist-De2oguBm.js.map → dist-BLBF7qqr.js.map} +1 -1
- package/public/assets/{dist-T7u7IZGJ.js → dist-BrQsqBbc.js} +2 -2
- package/public/assets/{dist-T7u7IZGJ.js.map → dist-BrQsqBbc.js.map} +1 -1
- package/public/assets/{dist-Cko2KPW8.js → dist-COQuunEv.js} +2 -2
- package/public/assets/{dist-Cko2KPW8.js.map → dist-COQuunEv.js.map} +1 -1
- package/public/assets/{dist-CLHMeXYi.js → dist-Ci5Y37nj.js} +2 -2
- package/public/assets/{dist-CLHMeXYi.js.map → dist-Ci5Y37nj.js.map} +1 -1
- package/public/assets/{dist-Ci1MM51P.js → dist-CoROafNg.js} +2 -2
- package/public/assets/{dist-Ci1MM51P.js.map → dist-CoROafNg.js.map} +1 -1
- package/public/assets/{dist-CC5f7oYw.js → dist-I-MFUv51.js} +2 -2
- package/public/assets/{dist-CC5f7oYw.js.map → dist-I-MFUv51.js.map} +1 -1
- package/public/assets/{dist-DFLciw0h.js → dist-UQGKwqZH.js} +2 -2
- package/public/assets/{dist-DFLciw0h.js.map → dist-UQGKwqZH.js.map} +1 -1
- package/public/assets/dist-YpHfnnIA.js +2 -0
- package/public/assets/{dist-DUoZnlB2.js.map → dist-YpHfnnIA.js.map} +1 -1
- package/public/assets/dist-qd198ib9.js +2 -0
- package/public/assets/{dist-D41tzJYg.js.map → dist-qd198ib9.js.map} +1 -1
- package/public/assets/{dist-DmN94rc8.js → dist-yGOq6sB3.js} +2 -2
- package/public/assets/{dist-DmN94rc8.js.map → dist-yGOq6sB3.js.map} +1 -1
- package/public/assets/{es2015-Df08Opjx.js → es2015-CRxz9lOj.js} +2 -2
- package/public/assets/{es2015-Df08Opjx.js.map → es2015-CRxz9lOj.js.map} +1 -1
- package/public/assets/{formatted-body-impl-DBt5tnS0.js → formatted-body-impl-u0W_hWYA.js} +2 -2
- package/public/assets/{formatted-body-impl-DBt5tnS0.js.map → formatted-body-impl-u0W_hWYA.js.map} +1 -1
- package/public/assets/index-BwfVOzUG.js +21 -0
- package/public/assets/{index-D7js3XlH.js.map → index-BwfVOzUG.js.map} +1 -1
- package/public/assets/index-Dn_GDXbi.css +2 -0
- package/public/assets/{input-B2EDz-BE.js → input-BHYNpXAG.js} +2 -2
- package/public/assets/{input-B2EDz-BE.js.map → input-BHYNpXAG.js.map} +1 -1
- package/public/assets/{insights-BvjkOXk9.js → insights-CAF9Hi5D.js} +2 -2
- package/public/assets/{insights-BvjkOXk9.js.map → insights-CAF9Hi5D.js.map} +1 -1
- package/public/assets/{integrations-7L1f3eIE.js → integrations-CG9qyHUf.js} +2 -2
- package/public/assets/{integrations-7L1f3eIE.js.map → integrations-CG9qyHUf.js.map} +1 -1
- package/public/assets/{lib-BZrjIp-o.js → lib-Df4aph5u.js} +2 -2
- package/public/assets/{lib-BZrjIp-o.js.map → lib-Df4aph5u.js.map} +1 -1
- package/public/assets/lucide-react-L2UxFDic.js +9 -0
- package/public/assets/lucide-react-L2UxFDic.js.map +1 -0
- package/public/assets/{maintenance-BBoL--vs.js → maintenance-DgHA35ve.js} +2 -2
- package/public/assets/{maintenance-BBoL--vs.js.map → maintenance-DgHA35ve.js.map} +1 -1
- package/public/assets/{managed-agents-BjYBzVZt.js → managed-agents-Rk6ghKR9.js} +2 -2
- package/public/assets/{managed-agents-BjYBzVZt.js.map → managed-agents-Rk6ghKR9.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-BnwjZsmO.js → markdown-preview-impl-NWMtJdYz.js} +2 -2
- package/public/assets/{markdown-preview-impl-BnwjZsmO.js.map → markdown-preview-impl-NWMtJdYz.js.map} +1 -1
- package/public/assets/memory-DamwWa9A.js +2 -0
- package/public/assets/{memory-SLycz2gC.js.map → memory-DamwWa9A.js.map} +1 -1
- package/public/assets/{messages-DfSCTe6N.js → messages--NU-YIL6.js} +2 -2
- package/public/assets/{messages-DfSCTe6N.js.map → messages--NU-YIL6.js.map} +1 -1
- package/public/assets/{orchestrators-BwxdTQm_.js → orchestrators-DQnIn6qx.js} +2 -2
- package/public/assets/{orchestrators-BwxdTQm_.js.map → orchestrators-DQnIn6qx.js.map} +1 -1
- package/public/assets/{overview-Djy3qkY5.js → overview-DCmNgXDf.js} +2 -2
- package/public/assets/{overview-Djy3qkY5.js.map → overview-DCmNgXDf.js.map} +1 -1
- package/public/assets/{pairs-9KNduLnC.js → pairs-DNELeC9P.js} +2 -2
- package/public/assets/{pairs-9KNduLnC.js.map → pairs-DNELeC9P.js.map} +1 -1
- package/public/assets/{react-dom-WI6TjVe7.js → react-dom-CrP_AtcL.js} +2 -2
- package/public/assets/{react-dom-WI6TjVe7.js.map → react-dom-CrP_AtcL.js.map} +1 -1
- package/public/assets/{security-tG3q7fFW.js → security-Dd3Kh0oC.js} +2 -2
- package/public/assets/{security-tG3q7fFW.js.map → security-Dd3Kh0oC.js.map} +1 -1
- package/public/assets/{select-CGUdMNOG.js → select-DQbeJZX0.js} +2 -2
- package/public/assets/{select-CGUdMNOG.js.map → select-DQbeJZX0.js.map} +1 -1
- package/public/assets/settings-BMAJrBIH.js +4 -0
- package/public/assets/settings-BMAJrBIH.js.map +1 -0
- package/public/assets/store-B8xP6z6T.js +9 -0
- package/public/assets/store-B8xP6z6T.js.map +1 -0
- package/public/assets/tasks-BYR4L9GP.js +2 -0
- package/public/assets/{tasks-DWlKg218.js.map → tasks-BYR4L9GP.js.map} +1 -1
- package/public/assets/teams-CoTifrq_.js +2 -0
- package/public/assets/{teams-DRchUP_p.js.map → teams-CoTifrq_.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-D_Sqe-vo.js → terminal-viewer-impl-B1YzfpE6.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D_Sqe-vo.js.map → terminal-viewer-impl-B1YzfpE6.js.map} +1 -1
- package/public/assets/{use-keyboard-viewport-fOL_3RHB.js → use-keyboard-viewport-DrRH_QzG.js} +2 -2
- package/public/assets/{use-keyboard-viewport-fOL_3RHB.js.map → use-keyboard-viewport-DrRH_QzG.js.map} +1 -1
- package/public/assets/{work-queue-HNcyjON9.js → work-queue-x57vlgyZ.js} +2 -2
- package/public/assets/{work-queue-HNcyjON9.js.map → work-queue-x57vlgyZ.js.map} +1 -1
- package/public/assets/{workspaces-CicYE2Ax.js → workspaces-CYm5bLg9.js} +3 -3
- package/public/assets/{workspaces-CicYE2Ax.js.map → workspaces-CYm5bLg9.js.map} +1 -1
- package/public/index.html +22 -22
- package/runner/src/config.ts +66 -2
- package/src/automations.ts +3 -4
- package/src/config-store.ts +5 -6
- package/src/connectors.ts +5 -0
- package/src/db/migrations.ts +6 -0
- package/src/db/schema.ts +1 -1
- package/src/index.ts +5 -2
- package/src/mcp-provider-catalog.ts +9 -0
- package/src/mcp.ts +4 -4
- package/src/provider-catalog-store.ts +33 -4
- package/src/provider-config-store.ts +216 -0
- package/src/recipe-runner.ts +2 -1
- package/src/recipe-validator.ts +4 -3
- package/src/routes/agents-spawn.ts +2 -2
- package/src/routes/index.ts +12 -2
- package/src/routes/insights.ts +4 -3
- package/src/routes/provider-config.ts +89 -41
- package/src/routes/settings.ts +127 -0
- package/src/routes/steward.ts +5 -5
- package/src/routes/tokens.ts +32 -1
- package/src/security.ts +34 -37
- package/src/settings/modules.ts +149 -0
- package/src/settings/registry.ts +397 -0
- package/src/spawn-command.ts +5 -1
- package/src/team-template-config.ts +2 -2
- package/src/token-db.ts +20 -0
- package/public/assets/agents-D201CuTR.js +0 -2
- package/public/assets/branch-state-badge-BPXXLpQG.js +0 -2
- package/public/assets/card-BU6PvVHv.js +0 -2
- package/public/assets/chat-CHgPGHQD.js +0 -2
- package/public/assets/display-CketawEF.js +0 -3
- package/public/assets/dist-D41tzJYg.js +0 -2
- package/public/assets/dist-DUoZnlB2.js +0 -2
- package/public/assets/dist-De2oguBm.js +0 -2
- package/public/assets/index-D7js3XlH.js +0 -21
- package/public/assets/index-DaNOQJci.css +0 -2
- package/public/assets/lucide-react-H_-8G79A.js +0 -9
- package/public/assets/lucide-react-H_-8G79A.js.map +0 -1
- package/public/assets/memory-SLycz2gC.js +0 -2
- package/public/assets/settings-CGcqyJ5L.js +0 -10
- package/public/assets/settings-CGcqyJ5L.js.map +0 -1
- package/public/assets/store-DXdfhiVf.js +0 -9
- package/public/assets/store-DXdfhiVf.js.map +0 -1
- package/public/assets/tasks-DWlKg218.js +0 -2
- package/public/assets/teams-DRchUP_p.js +0 -2
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SPAWN_PROVIDERS,
|
|
3
|
+
errMessage,
|
|
4
|
+
isRecord,
|
|
5
|
+
type ConnectorManifest,
|
|
6
|
+
type JSONSchema,
|
|
7
|
+
type SettingDescriptor,
|
|
8
|
+
type SettingDisplay,
|
|
9
|
+
type SettingScope,
|
|
10
|
+
type SettingTier,
|
|
11
|
+
} from "agent-relay-sdk";
|
|
12
|
+
import { ValidationError } from "../db";
|
|
13
|
+
import { cleanString } from "../validation";
|
|
14
|
+
import type { ProviderConfig } from "../../runner/src/adapter";
|
|
15
|
+
import { defaultProviderConfig } from "../../runner/src/config";
|
|
16
|
+
import { SETTING_ADMIN_SCOPE, getSettingDescriptor, registerProviderConfigSetting, registerSetting, validateSettingValue } from "./registry";
|
|
17
|
+
|
|
18
|
+
export const CONNECTOR_CONFIG_NAMESPACE = "connector-config";
|
|
19
|
+
export const CHANNEL_TYPE_CONFIG_NAMESPACE = "channel-type";
|
|
20
|
+
|
|
21
|
+
export function registerConnectorConfigSetting(
|
|
22
|
+
manifest: Pick<ConnectorManifest, "id" | "displayName" | "description" | "configSchema">,
|
|
23
|
+
opts: { defaults?: unknown } = {},
|
|
24
|
+
): SettingDescriptor | undefined {
|
|
25
|
+
if (!manifest.configSchema) return undefined;
|
|
26
|
+
const schema = schemaFromRecord(manifest.configSchema, `connector ${manifest.id} configSchema`);
|
|
27
|
+
return registerModuleSetting({
|
|
28
|
+
namespace: CONNECTOR_CONFIG_NAMESPACE,
|
|
29
|
+
key: manifest.id,
|
|
30
|
+
schema,
|
|
31
|
+
defaults: opts.defaults ?? schemaDefault(schema) ?? {},
|
|
32
|
+
scope: { read: "integration:read", write: SETTING_ADMIN_SCOPE },
|
|
33
|
+
tier: "server-runtime",
|
|
34
|
+
display: {
|
|
35
|
+
group: "Connectors",
|
|
36
|
+
label: manifest.displayName || manifest.id,
|
|
37
|
+
description: manifest.description ?? `Configuration for connector ${manifest.id}.`,
|
|
38
|
+
order: 100,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function validateConnectorConfig(manifest: ConnectorManifest, config: unknown): void {
|
|
44
|
+
const descriptor = getSettingDescriptor(CONNECTOR_CONFIG_NAMESPACE, manifest.id) ?? registerConnectorConfigSetting(manifest);
|
|
45
|
+
if (!descriptor) return;
|
|
46
|
+
const validation = validateSettingValue(descriptor.namespace, descriptor.key, config);
|
|
47
|
+
if (!validation.valid) throw new ValidationError(validation.errors.join("; "));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function registerChannelTypeSetting(input: {
|
|
51
|
+
type: string;
|
|
52
|
+
schema: JSONSchema;
|
|
53
|
+
defaults: unknown;
|
|
54
|
+
scope?: Partial<SettingScope>;
|
|
55
|
+
tier?: SettingTier;
|
|
56
|
+
display?: Partial<SettingDisplay>;
|
|
57
|
+
}): SettingDescriptor {
|
|
58
|
+
const type = cleanString(input.type, "channel type", { required: true, max: 80 })!;
|
|
59
|
+
return registerModuleSetting({
|
|
60
|
+
namespace: CHANNEL_TYPE_CONFIG_NAMESPACE,
|
|
61
|
+
key: type,
|
|
62
|
+
schema: input.schema,
|
|
63
|
+
defaults: input.defaults,
|
|
64
|
+
scope: { read: "integration:read", write: SETTING_ADMIN_SCOPE, ...input.scope },
|
|
65
|
+
tier: input.tier ?? "server-runtime",
|
|
66
|
+
display: {
|
|
67
|
+
group: "Channels",
|
|
68
|
+
label: `${type} channel`,
|
|
69
|
+
description: `Configuration for ${type} channel integrations.`,
|
|
70
|
+
order: 120,
|
|
71
|
+
...input.display,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ProviderSettingsDeclaration {
|
|
77
|
+
provider: string;
|
|
78
|
+
defaults: ProviderConfig;
|
|
79
|
+
display?: Partial<SettingDisplay>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const providerSettingsDeclarations = new Map<string, ProviderSettingsDeclaration>();
|
|
83
|
+
let builtInProvidersSeeded = false;
|
|
84
|
+
|
|
85
|
+
export function registerProviderSettingsDeclaration(input: {
|
|
86
|
+
provider: string;
|
|
87
|
+
defaults?: ProviderConfig;
|
|
88
|
+
display?: Partial<SettingDisplay>;
|
|
89
|
+
}): ProviderSettingsDeclaration {
|
|
90
|
+
const provider = cleanString(input.provider, "provider", { required: true, max: 80 })!;
|
|
91
|
+
const declaration: ProviderSettingsDeclaration = {
|
|
92
|
+
provider,
|
|
93
|
+
defaults: input.defaults ?? defaultProviderConfig(provider),
|
|
94
|
+
display: input.display,
|
|
95
|
+
};
|
|
96
|
+
providerSettingsDeclarations.set(provider, declaration);
|
|
97
|
+
return declaration;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function listProviderSettingsDeclarations(): ProviderSettingsDeclaration[] {
|
|
101
|
+
ensureBuiltInProviderSettingsDeclarations();
|
|
102
|
+
return [...providerSettingsDeclarations.values()];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getProviderSettingsDeclaration(provider: string): ProviderSettingsDeclaration | undefined {
|
|
106
|
+
ensureBuiltInProviderSettingsDeclarations();
|
|
107
|
+
return providerSettingsDeclarations.get(provider);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function providerConfigDefaults(provider: string): ProviderConfig {
|
|
111
|
+
return getProviderSettingsDeclaration(provider)?.defaults ?? defaultProviderConfig(provider);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function registerDeclaredProviderConfigSetting(input: { host: string; provider: string }): SettingDescriptor {
|
|
115
|
+
const declaration = getProviderSettingsDeclaration(input.provider);
|
|
116
|
+
if (!declaration) throw new ValidationError(`provider must be one of: ${listProviderSettingsDeclarations().map((d) => d.provider).join(", ")}`);
|
|
117
|
+
return registerProviderConfigSetting({
|
|
118
|
+
host: input.host,
|
|
119
|
+
provider: declaration.provider,
|
|
120
|
+
defaults: declaration.defaults,
|
|
121
|
+
display: declaration.display,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function ensureBuiltInProviderSettingsDeclarations(): void {
|
|
126
|
+
if (builtInProvidersSeeded) return;
|
|
127
|
+
builtInProvidersSeeded = true;
|
|
128
|
+
for (const provider of SPAWN_PROVIDERS) {
|
|
129
|
+
registerProviderSettingsDeclaration({ provider, defaults: defaultProviderConfig(provider) });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function registerModuleSetting(input: Parameters<typeof registerSetting>[0]): SettingDescriptor {
|
|
134
|
+
try {
|
|
135
|
+
return registerSetting(input);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (error instanceof ValidationError) throw error;
|
|
138
|
+
throw new ValidationError(errMessage(error));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function schemaFromRecord(value: Record<string, unknown>, field: string): JSONSchema {
|
|
143
|
+
if (!isRecord(value)) throw new ValidationError(`${field} must be an object`);
|
|
144
|
+
return value as JSONSchema;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function schemaDefault(schema: JSONSchema): unknown {
|
|
148
|
+
return Object.prototype.hasOwnProperty.call(schema, "default") ? schema.default : undefined;
|
|
149
|
+
}
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
// Settings descriptor registry (epic #380, #382) — the single server-side source
|
|
2
|
+
// of truth for which settings exist, their JSON Schema, defaults, required scope,
|
|
3
|
+
// tier, and display. This is the *declaration* layer over the existing `config`
|
|
4
|
+
// table (src/config-store.ts owns storage + history + the `config.changed` SSE) —
|
|
5
|
+
// it does NOT touch storage. The API (#383), scope enforcement (#385), module
|
|
6
|
+
// wiring (#386), and the Settings UI (#384) all build on this contract.
|
|
7
|
+
//
|
|
8
|
+
// DECISION LOCKED (#380 thread): validation is via `ajv`, descriptors carry full
|
|
9
|
+
// JSON Schema. Each descriptor's schema is ajv-compiled at registration, which
|
|
10
|
+
// validates it against the JSON Schema meta-schema and throws on a malformed
|
|
11
|
+
// schema — fail fast, never seed a broken descriptor.
|
|
12
|
+
//
|
|
13
|
+
// The `SettingDescriptor`/`JSONSchema` types live in `sdk/src/types.ts` (imported
|
|
14
|
+
// here, never re-declared — DRY rule). Keep this module under the ratchet ceiling;
|
|
15
|
+
// add per-surface seed helpers, don't inline a god-object.
|
|
16
|
+
|
|
17
|
+
import Ajv from "ajv";
|
|
18
|
+
import type { ValidateFunction } from "ajv";
|
|
19
|
+
import {
|
|
20
|
+
APPROVAL_MODES,
|
|
21
|
+
errMessage,
|
|
22
|
+
SPAWN_PROVIDERS,
|
|
23
|
+
VALID_EFFORTS,
|
|
24
|
+
type JSONSchema,
|
|
25
|
+
type SettingDescriptor,
|
|
26
|
+
type SettingScope,
|
|
27
|
+
} from "agent-relay-sdk";
|
|
28
|
+
|
|
29
|
+
/** Fail-closed default scope — a descriptor that omits scope requires admin to
|
|
30
|
+
* read and write (#385 owns the scope grammar; this layer only declares it). */
|
|
31
|
+
export const SETTING_ADMIN_SCOPE = "system:admin";
|
|
32
|
+
|
|
33
|
+
// One shared compiler. `strict: false` relaxes ajv's opinionated strict-mode
|
|
34
|
+
// warnings (unknown keywords/formats) so any reasonable JSON Schema compiles,
|
|
35
|
+
// while meta-schema validation (default on) still rejects a structurally broken
|
|
36
|
+
// schema. `allErrors` so value-validation reports every failure, not just the first.
|
|
37
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Registration input: a descriptor with an optional, possibly-partial `scope`.
|
|
41
|
+
* The registry resolves any omitted read/write scope to the fail-closed admin
|
|
42
|
+
* default and returns a fully-populated `SettingDescriptor`.
|
|
43
|
+
*/
|
|
44
|
+
export type SettingRegistration<T = unknown> = Omit<SettingDescriptor<T>, "scope"> & {
|
|
45
|
+
scope?: Partial<SettingScope>;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
interface RegisteredSetting {
|
|
49
|
+
descriptor: SettingDescriptor;
|
|
50
|
+
validate: ValidateFunction;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const registry = new Map<string, RegisteredSetting>();
|
|
54
|
+
|
|
55
|
+
function descriptorId(namespace: string, key: string): string {
|
|
56
|
+
return `${namespace}:${key}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resolveScope(scope: Partial<SettingScope> | undefined): SettingScope {
|
|
60
|
+
return {
|
|
61
|
+
read: scope?.read ?? SETTING_ADMIN_SCOPE,
|
|
62
|
+
write: scope?.write ?? SETTING_ADMIN_SCOPE,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Register (or replace) a setting descriptor. Compiles `schema` with ajv — a
|
|
68
|
+
* malformed JSON Schema throws here, at registration/seed time. The mechanism
|
|
69
|
+
* #386 modules call to contribute their own settings.
|
|
70
|
+
*/
|
|
71
|
+
export function registerSetting<T>(reg: SettingRegistration<T>): SettingDescriptor<T> {
|
|
72
|
+
if (!reg.namespace) throw new Error("setting descriptor requires a non-empty namespace");
|
|
73
|
+
if (!reg.key) throw new Error("setting descriptor requires a non-empty key");
|
|
74
|
+
const id = descriptorId(reg.namespace, reg.key);
|
|
75
|
+
|
|
76
|
+
let validate: ValidateFunction;
|
|
77
|
+
try {
|
|
78
|
+
validate = ajv.compile(reg.schema as object);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw new Error(`invalid JSON Schema for setting "${id}": ${errMessage(error)}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const descriptor: SettingDescriptor<T> = {
|
|
84
|
+
namespace: reg.namespace,
|
|
85
|
+
key: reg.key,
|
|
86
|
+
schema: reg.schema,
|
|
87
|
+
defaults: reg.defaults,
|
|
88
|
+
scope: resolveScope(reg.scope),
|
|
89
|
+
tier: reg.tier,
|
|
90
|
+
display: reg.display,
|
|
91
|
+
};
|
|
92
|
+
registry.set(id, { descriptor: descriptor as SettingDescriptor, validate });
|
|
93
|
+
return descriptor;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Look up a single descriptor by its (namespace, key) address. */
|
|
97
|
+
export function getSettingDescriptor(namespace: string, key: string): SettingDescriptor | undefined {
|
|
98
|
+
return registry.get(descriptorId(namespace, key))?.descriptor;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** All registered descriptors (built-ins + module contributions), seeded on first access. */
|
|
102
|
+
export function listSettingDescriptors(): SettingDescriptor[] {
|
|
103
|
+
ensureSeeded();
|
|
104
|
+
return [...registry.values()].map((entry) => entry.descriptor);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Distinct namespaces that have at least one registered descriptor. */
|
|
108
|
+
export function listSettingNamespaces(): string[] {
|
|
109
|
+
return [...new Set(listSettingDescriptors().map((d) => d.namespace))];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Validate a candidate value against a registered descriptor's compiled schema.
|
|
114
|
+
* The single validation seam — #383 calls this on writes so the schema is the one
|
|
115
|
+
* source of truth. Returns `valid:false` with a reason when no descriptor exists.
|
|
116
|
+
*/
|
|
117
|
+
export function validateSettingValue(
|
|
118
|
+
namespace: string,
|
|
119
|
+
key: string,
|
|
120
|
+
value: unknown,
|
|
121
|
+
): { valid: boolean; errors: string[] } {
|
|
122
|
+
ensureSeeded();
|
|
123
|
+
const entry = registry.get(descriptorId(namespace, key));
|
|
124
|
+
if (!entry) return { valid: false, errors: [`no descriptor registered for "${descriptorId(namespace, key)}"`] };
|
|
125
|
+
const valid = entry.validate(value) === true;
|
|
126
|
+
if (valid) return { valid: true, errors: [] };
|
|
127
|
+
const errors = (entry.validate.errors ?? []).map((e) => `${e.instancePath || "/"} ${e.message ?? "invalid"}`.trim());
|
|
128
|
+
return { valid: false, errors };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
132
|
+
// Built-in seeds — descriptors for today's `config`-table namespaces. Schemas
|
|
133
|
+
// mirror the validators in src/config-store.ts; defaults mirror its *_DEFAULTS.
|
|
134
|
+
// All current built-ins are `server-runtime` (config-table backed, runtime
|
|
135
|
+
// mutable). Scope is left default (admin) here; #385 refines read/write tokens.
|
|
136
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
137
|
+
|
|
138
|
+
const STEWARD_SCHEMA: JSONSchema = {
|
|
139
|
+
type: "object",
|
|
140
|
+
additionalProperties: false,
|
|
141
|
+
required: ["enabled", "provider", "permissionMode", "keepaliveSeconds"],
|
|
142
|
+
properties: {
|
|
143
|
+
enabled: { type: "boolean" },
|
|
144
|
+
provider: { type: "string", enum: [...SPAWN_PROVIDERS] },
|
|
145
|
+
model: { type: "string", maxLength: 120 },
|
|
146
|
+
effort: { type: "string", enum: [...VALID_EFFORTS] },
|
|
147
|
+
permissionMode: { type: "string", enum: [...APPROVAL_MODES] },
|
|
148
|
+
keepaliveSeconds: { type: "integer", minimum: 0, maximum: 2_592_000 },
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const INSIGHTS_SCHEMA: JSONSchema = {
|
|
153
|
+
type: "object",
|
|
154
|
+
additionalProperties: false,
|
|
155
|
+
required: ["enabled", "contextRatio", "introspection"],
|
|
156
|
+
properties: {
|
|
157
|
+
enabled: { type: "boolean" },
|
|
158
|
+
contextRatio: {
|
|
159
|
+
type: "object",
|
|
160
|
+
additionalProperties: false,
|
|
161
|
+
required: ["enabled"],
|
|
162
|
+
properties: { enabled: { type: "boolean" } },
|
|
163
|
+
},
|
|
164
|
+
introspection: {
|
|
165
|
+
type: "object",
|
|
166
|
+
additionalProperties: false,
|
|
167
|
+
required: ["enabled", "minTurns", "minContextRemaining"],
|
|
168
|
+
properties: {
|
|
169
|
+
enabled: { type: "boolean" },
|
|
170
|
+
minTurns: { type: "integer", minimum: 0, maximum: 1000 },
|
|
171
|
+
minContextRemaining: { type: "number", minimum: 0, maximum: 1 },
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const CONTEXT_THRESHOLD_SCHEMA: JSONSchema = {
|
|
178
|
+
type: "object",
|
|
179
|
+
additionalProperties: false,
|
|
180
|
+
required: ["enabled", "advisoryUtilization", "hardBackstopUtilization", "bandSize"],
|
|
181
|
+
properties: {
|
|
182
|
+
enabled: { type: "boolean" },
|
|
183
|
+
advisoryUtilization: { type: "number", minimum: 0, maximum: 1 },
|
|
184
|
+
hardBackstopUtilization: { type: "number", minimum: 0, maximum: 1 },
|
|
185
|
+
bandSize: { type: "number", minimum: 0, maximum: 1 },
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const NOTIFICATIONS_SCHEMA: JSONSchema = {
|
|
190
|
+
type: "object",
|
|
191
|
+
additionalProperties: false,
|
|
192
|
+
required: ["enabled", "branchLanded", "agentReady", "agentExited", "agentSpawnFailed", "contextThreshold"],
|
|
193
|
+
properties: {
|
|
194
|
+
enabled: { type: "boolean" },
|
|
195
|
+
branchLanded: { type: "boolean" },
|
|
196
|
+
agentReady: { type: "boolean" },
|
|
197
|
+
agentExited: { type: "boolean" },
|
|
198
|
+
agentSpawnFailed: { type: "boolean" },
|
|
199
|
+
contextThreshold: CONTEXT_THRESHOLD_SCHEMA,
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const WORKSPACE_SCHEMA: JSONSchema = {
|
|
204
|
+
type: "object",
|
|
205
|
+
additionalProperties: false,
|
|
206
|
+
required: ["symlinkPaths"],
|
|
207
|
+
properties: {
|
|
208
|
+
symlinkPaths: {
|
|
209
|
+
type: "array",
|
|
210
|
+
maxItems: 100,
|
|
211
|
+
items: { type: "string", maxLength: 120 },
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const LANDING_SCHEMA: JSONSchema = {
|
|
217
|
+
type: "object",
|
|
218
|
+
additionalProperties: false,
|
|
219
|
+
required: ["strategy"],
|
|
220
|
+
properties: {
|
|
221
|
+
strategy: { type: "string", enum: ["direct", "pr"] },
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// Provider chat/reasoning capture toggles (source: runner/src/adapter.ts ProviderConfig).
|
|
226
|
+
// NOTE (#383 coordination): provider config storage is being centralized in #383;
|
|
227
|
+
// these are seeded instance-global under namespace "provider". Per-provider
|
|
228
|
+
// (claude vs codex) host-addressing is #383's call — keep these minimal until then.
|
|
229
|
+
const PROVIDER_CHAT_CAPTURE_SCHEMA: JSONSchema = {
|
|
230
|
+
type: "string",
|
|
231
|
+
enum: ["final", "full"],
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const PROVIDER_REASONING_CAPTURE_SCHEMA: JSONSchema = {
|
|
235
|
+
type: "boolean",
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export const PROVIDER_CONFIG_NAMESPACE = "provider-config";
|
|
239
|
+
export const PROVIDER_CONFIG_SCHEMA: JSONSchema = {
|
|
240
|
+
type: "object",
|
|
241
|
+
additionalProperties: false,
|
|
242
|
+
required: [
|
|
243
|
+
"command",
|
|
244
|
+
"defaultArgs",
|
|
245
|
+
"env",
|
|
246
|
+
"pluginDirs",
|
|
247
|
+
"defaultCapabilities",
|
|
248
|
+
"defaultApprovalMode",
|
|
249
|
+
"defaultTags",
|
|
250
|
+
"chatCaptureMode",
|
|
251
|
+
"reasoningCapture",
|
|
252
|
+
"headless",
|
|
253
|
+
],
|
|
254
|
+
properties: {
|
|
255
|
+
command: { type: "string", minLength: 1, maxLength: 500 },
|
|
256
|
+
defaultArgs: { type: "array", maxItems: 50, items: { type: "string", maxLength: 80 } },
|
|
257
|
+
env: { type: "object", additionalProperties: { type: "string" } },
|
|
258
|
+
pluginDirs: { type: "array", maxItems: 50, items: { type: "string", maxLength: 80 } },
|
|
259
|
+
defaultCapabilities: { type: "array", maxItems: 50, items: { type: "string", maxLength: 80 } },
|
|
260
|
+
defaultApprovalMode: { type: "string", maxLength: 80 },
|
|
261
|
+
defaultTags: { type: "array", maxItems: 50, items: { type: "string", maxLength: 80 } },
|
|
262
|
+
chatCaptureMode: { type: "string", enum: ["final", "full"] },
|
|
263
|
+
reasoningCapture: { type: "boolean" },
|
|
264
|
+
headless: {
|
|
265
|
+
type: "object",
|
|
266
|
+
additionalProperties: false,
|
|
267
|
+
required: ["tmuxPrefix", "shutdownTimeoutMs"],
|
|
268
|
+
properties: {
|
|
269
|
+
tmuxPrefix: { type: "string", minLength: 1, maxLength: 120 },
|
|
270
|
+
shutdownTimeoutMs: { type: "integer", minimum: 1 },
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
let seeded = false;
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Register the built-in descriptors. Idempotent: safe to call repeatedly (and is
|
|
280
|
+
* called lazily by the read accessors). #386 adds module-contributed descriptors
|
|
281
|
+
* on top via `registerSetting`.
|
|
282
|
+
*/
|
|
283
|
+
export function seedBuiltInSettings(): void {
|
|
284
|
+
if (seeded) return;
|
|
285
|
+
seeded = true;
|
|
286
|
+
|
|
287
|
+
registerSetting({
|
|
288
|
+
namespace: "steward",
|
|
289
|
+
key: "default",
|
|
290
|
+
schema: STEWARD_SCHEMA,
|
|
291
|
+
defaults: { enabled: false, provider: "claude", permissionMode: "open", keepaliveSeconds: 300 },
|
|
292
|
+
scope: { read: "settings:read:steward", write: "settings:write:steward" },
|
|
293
|
+
tier: "server-runtime",
|
|
294
|
+
display: { group: "Agents", label: "Steward", description: "Auto-provisioned steward that reconciles merges and commands.", order: 10 },
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
registerSetting({
|
|
298
|
+
namespace: "insights",
|
|
299
|
+
key: "default",
|
|
300
|
+
schema: INSIGHTS_SCHEMA,
|
|
301
|
+
defaults: {
|
|
302
|
+
enabled: true,
|
|
303
|
+
contextRatio: { enabled: true },
|
|
304
|
+
introspection: { enabled: true, minTurns: 4, minContextRemaining: 0.15 },
|
|
305
|
+
},
|
|
306
|
+
scope: { read: "settings:read:insights", write: "settings:write:insights" },
|
|
307
|
+
tier: "server-runtime",
|
|
308
|
+
display: { group: "Insights", label: "Insights", description: "Continuous self-improvement instrumentation toggles.", order: 20 },
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
registerSetting({
|
|
312
|
+
namespace: "notifications",
|
|
313
|
+
key: "default",
|
|
314
|
+
schema: NOTIFICATIONS_SCHEMA,
|
|
315
|
+
defaults: {
|
|
316
|
+
enabled: true,
|
|
317
|
+
branchLanded: true,
|
|
318
|
+
agentReady: true,
|
|
319
|
+
agentExited: true,
|
|
320
|
+
agentSpawnFailed: true,
|
|
321
|
+
contextThreshold: { enabled: true, advisoryUtilization: 0.7, hardBackstopUtilization: 0.9, bandSize: 0.1 },
|
|
322
|
+
},
|
|
323
|
+
scope: { read: "settings:read:notifications", write: "settings:write:notifications" },
|
|
324
|
+
tier: "server-runtime",
|
|
325
|
+
display: { group: "Notifications", label: "Lifecycle notifications", description: "Relay-driven lifecycle push notifications (#239).", order: 30 },
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
registerSetting({
|
|
329
|
+
namespace: "workspace",
|
|
330
|
+
key: "default",
|
|
331
|
+
schema: WORKSPACE_SCHEMA,
|
|
332
|
+
defaults: { symlinkPaths: ["AGENTS.md", ".claude-rig"] },
|
|
333
|
+
scope: { read: "settings:read:workspace", write: "settings:write:workspace" },
|
|
334
|
+
tier: "server-runtime",
|
|
335
|
+
display: { group: "Workspace", label: "Workspace provisioning", description: "Untracked paths symlinked into isolated worktrees.", order: 40 },
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
registerSetting({
|
|
339
|
+
namespace: "landing",
|
|
340
|
+
key: "default",
|
|
341
|
+
schema: LANDING_SCHEMA,
|
|
342
|
+
defaults: { strategy: "direct" },
|
|
343
|
+
scope: { read: "settings:read:landing", write: "settings:write:landing" },
|
|
344
|
+
tier: "server-runtime",
|
|
345
|
+
display: { group: "Workspace", label: "Landing strategy", description: "Default land strategy for workspace branches.", order: 41 },
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
registerSetting({
|
|
349
|
+
namespace: "provider",
|
|
350
|
+
key: "chatCaptureMode",
|
|
351
|
+
schema: PROVIDER_CHAT_CAPTURE_SCHEMA,
|
|
352
|
+
defaults: "full",
|
|
353
|
+
scope: { read: "settings:read:provider", write: "settings:write:provider" },
|
|
354
|
+
tier: "server-runtime",
|
|
355
|
+
display: { group: "Providers", label: "Chat capture mode", description: "How much provider output is captured into chat.", order: 50 },
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
registerSetting({
|
|
359
|
+
namespace: "provider",
|
|
360
|
+
key: "reasoningCapture",
|
|
361
|
+
schema: PROVIDER_REASONING_CAPTURE_SCHEMA,
|
|
362
|
+
defaults: true,
|
|
363
|
+
scope: { read: "settings:read:provider", write: "settings:write:provider" },
|
|
364
|
+
tier: "server-runtime",
|
|
365
|
+
display: { group: "Providers", label: "Reasoning capture", description: "Stream reasoning/tool steps into chat.", order: 51 },
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export function registerProviderConfigSetting(input: {
|
|
370
|
+
host: string;
|
|
371
|
+
provider: string;
|
|
372
|
+
defaults: unknown;
|
|
373
|
+
display?: Partial<SettingDescriptor["display"]>;
|
|
374
|
+
}): SettingDescriptor {
|
|
375
|
+
return registerSetting({
|
|
376
|
+
namespace: PROVIDER_CONFIG_NAMESPACE,
|
|
377
|
+
key: `${input.host}/${input.provider}`,
|
|
378
|
+
schema: PROVIDER_CONFIG_SCHEMA,
|
|
379
|
+
defaults: input.defaults,
|
|
380
|
+
scope: { read: "agent:read", write: SETTING_ADMIN_SCOPE },
|
|
381
|
+
tier: "server-runtime",
|
|
382
|
+
display: {
|
|
383
|
+
group: "Providers",
|
|
384
|
+
label: `${input.host} ${input.provider}`,
|
|
385
|
+
description: `Provider runtime configuration for ${input.provider} on ${input.host}.`,
|
|
386
|
+
order: 60,
|
|
387
|
+
...input.display,
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function ensureSeeded(): void {
|
|
393
|
+
if (!seeded) seedBuiltInSettings();
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Seed on import so any consumer of the registry sees the built-ins.
|
|
397
|
+
seedBuiltInSettings();
|
package/src/spawn-command.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { errMessage } from "agent-relay-sdk";
|
|
|
4
4
|
import { resolveProviderSelection, type ProviderEffort } from "agent-relay-sdk/provider-catalog";
|
|
5
5
|
import { workspaceSpawnParams } from "./config-store";
|
|
6
6
|
import { ValidationError } from "./db";
|
|
7
|
+
import { effectiveProviderCatalogList } from "./provider-catalog-store";
|
|
7
8
|
|
|
8
9
|
/** Resolved provider/model/effort triple — the output shape of every model-resolution wrapper. */
|
|
9
10
|
export interface SpawnModelParams {
|
|
@@ -48,7 +49,10 @@ export function resolveSpawnModelParams(
|
|
|
48
49
|
): SpawnModelParams {
|
|
49
50
|
if (!model && !effort && opts.skipDefaultWhenEmpty) return {};
|
|
50
51
|
try {
|
|
51
|
-
const selection = resolveProviderSelection(
|
|
52
|
+
const selection = resolveProviderSelection(
|
|
53
|
+
{ provider: provider as SpawnProvider, model, effort: effort as ProviderEffort | undefined },
|
|
54
|
+
effectiveProviderCatalogList(),
|
|
55
|
+
);
|
|
52
56
|
return {
|
|
53
57
|
...(selection.modelAlias ? { model: selection.modelAlias } : {}),
|
|
54
58
|
...(selection.providerModel ? { providerModel: selection.providerModel } : {}),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRecord, SPAWN_PROVIDERS
|
|
1
|
+
import { isRecord, SPAWN_PROVIDERS } from "agent-relay-sdk";
|
|
2
2
|
import { ValidationError } from "./db";
|
|
3
3
|
import { cleanEnum, cleanString, cleanStringArray } from "./validation";
|
|
4
4
|
import type { PlanOwnerRef, SpawnProvider, TeamTemplate, TeamTemplateCompositionEntry, TeamTemplatePlanSkeleton } from "./types";
|
|
@@ -18,7 +18,7 @@ function cleanPositiveCount(value: unknown, field: string): number {
|
|
|
18
18
|
|
|
19
19
|
function optionalEffort(value: unknown, field: string): TeamTemplateCompositionEntry["effort"] {
|
|
20
20
|
if (value === undefined || value === null) return undefined;
|
|
21
|
-
return
|
|
21
|
+
return cleanString(value, field, { max: 120 }) as TeamTemplateCompositionEntry["effort"];
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function optionalStringProp<T extends string>(out: object, key: T, value: unknown, max: number): void {
|
package/src/token-db.ts
CHANGED
|
@@ -41,6 +41,26 @@ const BUILT_IN_PROFILES: Array<Omit<TokenProfile, "createdAt" | "updatedAt">> =
|
|
|
41
41
|
builtIn: true,
|
|
42
42
|
createdBy: "system",
|
|
43
43
|
},
|
|
44
|
+
{
|
|
45
|
+
id: "settings-reader",
|
|
46
|
+
name: "Settings Reader",
|
|
47
|
+
description: "Dashboard access for viewing schema-driven settings without mutation rights.",
|
|
48
|
+
role: "dashboard",
|
|
49
|
+
scope: ["settings:read"],
|
|
50
|
+
ttlSeconds: 7 * 24 * 60 * 60,
|
|
51
|
+
builtIn: true,
|
|
52
|
+
createdBy: "system",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "settings-operator",
|
|
56
|
+
name: "Settings Operator",
|
|
57
|
+
description: "Dashboard access for viewing settings and managing provider runtime catalog settings.",
|
|
58
|
+
role: "dashboard",
|
|
59
|
+
scope: ["settings:read", "settings:write:provider"],
|
|
60
|
+
ttlSeconds: 7 * 24 * 60 * 60,
|
|
61
|
+
builtIn: true,
|
|
62
|
+
createdBy: "system",
|
|
63
|
+
},
|
|
44
64
|
{
|
|
45
65
|
id: "orchestrator-host",
|
|
46
66
|
name: "Orchestrator Host",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{F as t,Fn as n,K as r,L as i,Nn as a,V as o,Y as s,ct as c,g as l,i as u,jt as d,kn as f,l as p,m,qn as h,wn as g,zt as _}from"./lucide-react-H_-8G79A.js";import{o as ee,t as v}from"./store-DXdfhiVf.js";import{G as y,K as b,U as x,V as S,a as C,d as w,i as te,n as ne}from"./display-CketawEF.js";import{o as T,r as E}from"./dist-Kkpnjx_M.js";import{t as D}from"./dist-DFLciw0h.js";import{i as O,n as k}from"./dist-Cko2KPW8.js";import{t as A}from"./dist-Ci1MM51P.js";import{t as j}from"./dist-DmN94rc8.js";import{a as M,i as N,n as re,o as ie,r as ae,s as oe,t as P}from"./es2015-Df08Opjx.js";import{a as F,i as se,n as I,r as L,t as R}from"./dist-T7u7IZGJ.js";import{t as z}from"./badge-Cy6qO_Jz.js";import{t as B}from"./button-73wpRw65.js";import{t as ce}from"./copy-button-HRopUwui.js";import{B as le,H as V,P as ue,S as H,U,V as W,d as de,g as fe,h as pe,l as me,m as he,p as ge,u as _e,x as G}from"./index-D7js3XlH.js";import{n as ve,t as ye}from"./card-BU6PvVHv.js";import{n as be,t as xe}from"./branch-state-badge-BPXXLpQG.js";var K=e(h(),1),q=n(),J=`Popover`,[Se,Ce]=O(J,[F]),Y=F(),[we,X]=Se(J),Te=e=>{let{__scopePopover:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!1}=e,s=Y(t),c=K.useRef(null),[l,u]=K.useState(!1),[d,f]=A({prop:r,defaultProp:i??!1,onChange:a,caller:J});return(0,q.jsx)(se,{...s,children:(0,q.jsx)(we,{scope:t,contentId:oe(),triggerRef:c,open:d,onOpenChange:f,onOpenToggle:K.useCallback(()=>f(e=>!e),[f]),hasCustomAnchor:l,onCustomAnchorAdd:K.useCallback(()=>u(!0),[]),onCustomAnchorRemove:K.useCallback(()=>u(!1),[]),modal:o,children:n})})};Te.displayName=J;var Ee=`PopoverAnchor`,De=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(Ee,n),a=Y(n),{onCustomAnchorAdd:o,onCustomAnchorRemove:s}=i;return K.useEffect(()=>(o(),()=>s()),[o,s]),(0,q.jsx)(R,{...a,...r,ref:t})});De.displayName=Ee;var Oe=`PopoverTrigger`,ke=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(Oe,n),a=Y(n),o=T(t,i.triggerRef),s=(0,q.jsx)(D.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.contentId,"data-state":Ve(i.open),...r,ref:o,onClick:k(e.onClick,i.onOpenToggle)});return i.hasCustomAnchor?s:(0,q.jsx)(R,{asChild:!0,...a,children:s})});ke.displayName=Oe;var Z=`PopoverPortal`,[Ae,je]=Se(Z,{forceMount:void 0}),Me=e=>{let{__scopePopover:t,forceMount:n,children:r,container:i}=e,a=X(Z,t);return(0,q.jsx)(Ae,{scope:t,forceMount:n,children:(0,q.jsx)(j,{present:n||a.open,children:(0,q.jsx)(N,{asChild:!0,container:i,children:r})})})};Me.displayName=Z;var Q=`PopoverContent`,Ne=K.forwardRef((e,t)=>{let n=je(Q,e.__scopePopover),{forceMount:r=n.forceMount,...i}=e,a=X(Q,e.__scopePopover);return(0,q.jsx)(j,{present:r||a.open,children:a.modal?(0,q.jsx)(Fe,{...i,ref:t}):(0,q.jsx)(Ie,{...i,ref:t})})});Ne.displayName=Q;var Pe=E(`PopoverContent.RemoveScroll`),Fe=K.forwardRef((e,t)=>{let n=X(Q,e.__scopePopover),r=K.useRef(null),i=T(t,r),a=K.useRef(!1);return K.useEffect(()=>{let e=r.current;if(e)return P(e)},[]),(0,q.jsx)(re,{as:Pe,allowPinchZoom:!0,children:(0,q.jsx)(Le,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:k(e.onCloseAutoFocus,e=>{e.preventDefault(),a.current||n.triggerRef.current?.focus()}),onPointerDownOutside:k(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;a.current=t.button===2||n},{checkForDefaultPrevented:!1}),onFocusOutside:k(e.onFocusOutside,e=>e.preventDefault(),{checkForDefaultPrevented:!1})})})}),Ie=K.forwardRef((e,t)=>{let n=X(Q,e.__scopePopover),r=K.useRef(!1),i=K.useRef(!1);return(0,q.jsx)(Le,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),Le=K.forwardRef((e,t)=>{let{__scopePopover:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,disableOutsidePointerEvents:o,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onInteractOutside:u,...d}=e,f=X(Q,n),p=Y(n);return ae(),(0,q.jsx)(M,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,q.jsx)(ie,{asChild:!0,disableOutsidePointerEvents:o,onInteractOutside:u,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onDismiss:()=>f.onOpenChange(!1),children:(0,q.jsx)(L,{"data-state":Ve(f.open),role:`dialog`,id:f.contentId,...p,...d,ref:t,style:{...d.style,"--radix-popover-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-popover-content-available-width":`var(--radix-popper-available-width)`,"--radix-popover-content-available-height":`var(--radix-popper-available-height)`,"--radix-popover-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-popover-trigger-height":`var(--radix-popper-anchor-height)`}})})})}),$=`PopoverClose`,Re=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X($,n);return(0,q.jsx)(D.button,{type:`button`,...r,ref:t,onClick:k(e.onClick,()=>i.onOpenChange(!1))})});Re.displayName=$;var ze=`PopoverArrow`,Be=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Y(n);return(0,q.jsx)(I,{...i,...r,ref:t})});Be.displayName=ze;function Ve(e){return e?`open`:`closed`}var He=Te,Ue=ke,We=Me,Ge=Ne;function Ke({...e}){return(0,q.jsx)(He,{"data-slot":`popover`,...e})}function qe({...e}){return(0,q.jsx)(Ue,{"data-slot":`popover-trigger`,...e})}function Je({className:e,align:t=`center`,sideOffset:n=4,...r}){return(0,q.jsx)(We,{children:(0,q.jsx)(Ge,{"data-slot":`popover-content`,align:t,sideOffset:n,className:a(`z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95`,e),...r})})}function Ye({className:e,...t}){return(0,q.jsx)(`div`,{"data-slot":`popover-header`,className:a(`flex flex-col gap-0.5 text-sm`,e),...t})}function Xe({className:e,...t}){return(0,q.jsx)(`div`,{"data-slot":`popover-title`,className:a(`font-medium`,e),...t})}function Ze({agent:e,childAgents:n=[],parentAgent:i}){let a=ee();v(e=>e.set);let u=v(e=>e.switchView),f=v(e=>e.openInboxThread),h=v(e=>e.openAgentDetail),g=v(e=>e.openPairInvite),T=v(e=>e.openRename),E=v(e=>e.openConfirm),D=v(e=>e.doAgentAction),O=v(e=>e.doDeleteAgent),k=v(e=>e.openFilesForAgent),A=v(e=>e.workspaceAction),j=v(e=>e.openWorkspaceFocus),{terminalOpen:M,terminalTarget:N,terminalOpening:re,openTerminal:ie,closeTerminal:ae}=be(e.id),oe=le(),P=te(a,e,ue(e),oe[e.id]||null),F=C(e,`shutdown`),se=C(e,`compact`),I=C(e,`clearContext`),L=!!(e.providerCapabilities?.terminal?.live?.read||e.providerCapabilities?.terminal?.attach?.create),R=!!(e.providerCapabilities?.terminal?.live?.write||e.providerCapabilities?.model?.provider===`claude`),V=ne(e),U=i?w(i):e.spawnedBy,W=n.length>0;return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(ye,{className:`group hover:border-zinc-600 transition-colors cursor-pointer`,onClick:()=>h(e),children:(0,q.jsxs)(ve,{className:`p-4`,children:[(0,q.jsxs)(`div`,{className:`flex items-start gap-2.5 mb-2.5`,children:[(0,q.jsx)(H,{agent:e,now:a,className:`mt-0.5`}),(0,q.jsx)(G,{agent:e}),(0,q.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,q.jsx)(`div`,{className:`text-sm font-medium truncate`,children:w(e)}),(0,q.jsx)(`div`,{className:`text-xs mt-0.5 ${y(P.tone)}`,children:P.label}),typeof e.meta?.cwd==`string`&&e.meta.cwd&&(0,q.jsx)(`button`,{type:`button`,className:`mt-0.5 block max-w-full truncate font-mono text-[10px] text-muted-foreground hover:text-foreground`,title:`Open ${e.meta.cwd} in Files`,onClick:t=>{t.stopPropagation(),k(e)},children:S(e.meta.cwd)})]}),e.branchState&&e.branchWorkspaceId&&(0,q.jsx)(xe,{state:e.branchState,className:`mt-0.5 shrink-0`,onClick:t=>{t.stopPropagation(),j(e.branchWorkspaceId)}})]}),P.badges.length>0&&(0,q.jsx)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:P.badges.map(e=>(0,q.jsx)(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium ${e.className}`,children:e.label},e.label))}),(W||e.spawnedBy&&U)&&(0,q.jsxs)(`div`,{className:`mb-2 flex flex-wrap gap-1.5`,onClick:e=>e.stopPropagation(),children:[W&&(0,q.jsxs)(Ke,{children:[(0,q.jsx)(qe,{asChild:!0,children:(0,q.jsxs)(`button`,{type:`button`,className:`inline-flex h-6 max-w-full items-center gap-1.5 rounded-full border border-sky-500/30 bg-sky-500/10 px-2 text-[10px] font-medium text-sky-300 transition-colors hover:bg-sky-500/15`,title:`${n.length} live child ${n.length===1?`agent`:`agents`}`,children:[(0,q.jsx)(p,{className:`h-3 w-3`}),(0,q.jsx)(`span`,{children:n.length}),(0,q.jsx)(`span`,{className:`flex -space-x-1`,children:n.slice(0,4).map(e=>(0,q.jsx)(H,{agent:e,now:a,className:`h-2 w-2 ring-1 ring-background`},e.id))})]})}),(0,q.jsxs)(Je,{align:`start`,className:`w-80`,onClick:e=>e.stopPropagation(),children:[(0,q.jsx)(Ye,{children:(0,q.jsx)(Xe,{children:`Team`})}),(0,q.jsx)(`div`,{className:`space-y-1.5`,children:n.map(e=>(0,q.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-2`,children:[(0,q.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,q.jsx)(H,{agent:e,now:a,className:`mt-1`}),(0,q.jsx)(G,{agent:e}),(0,q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,q.jsx)(`div`,{className:`truncate text-xs font-medium`,children:w(e)}),(0,q.jsx)(`div`,{className:`truncate text-[10px] text-muted-foreground`,children:e.providerCapabilities?.model?.alias||e.providerCapabilities?.model?.id||e.providerCapabilities?.model?.provider||e.status})]}),(0,q.jsx)(z,{variant:`outline`,className:`h-4 px-1.5 text-[9px]`,children:e.status})]}),(0,q.jsxs)(`div`,{className:`mt-2 flex gap-1`,children:[(0,q.jsx)(B,{size:`xs`,variant:`outline`,onClick:()=>h(e),children:`Open`}),(0,q.jsxs)(B,{size:`xs`,variant:`ghost`,onClick:()=>{f(e.id),u(`chat`)},children:[(0,q.jsx)(s,{className:`h-3 w-3`}),`Chat`]})]})]},e.id))})]})]}),e.spawnedBy&&U&&(0,q.jsx)(z,{variant:`outline`,className:`max-w-full text-[10px] text-muted-foreground`,children:(0,q.jsxs)(`span`,{className:`truncate`,children:[`spawned by `,U]})})]}),(e.tags.length>0||b(e.capabilities).length>0)&&(0,q.jsxs)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:[e.tags.slice(0,3).map(e=>(0,q.jsx)(z,{variant:`outline`,className:`text-[9px] px-1 py-0 h-4`,children:e},e)),b(e.capabilities).slice(0,2).map(e=>(0,q.jsx)(z,{variant:`secondary`,className:`text-[9px] px-1 py-0 h-4`,children:e},e))]}),(0,q.jsxs)(`div`,{className:`space-y-2 mb-2`,children:[(0,q.jsx)(pe,{agent:e}),(0,q.jsx)(he,{agent:e,compact:!0}),(0,q.jsx)(fe,{agent:e})]}),(0,q.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.id!==`user`&&e.id!==`system`&&x(a,e.lastSeen)}),(0,q.jsxs)(`div`,{className:`flex gap-1 mt-2.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity`,onClick:e=>e.stopPropagation(),children:[(0,q.jsx)(ce,{value:e.id,label:`Copy agent ID`,size:`icon`,className:`h-7 w-7`,iconClassName:`w-3 h-3`}),(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Chat`,onClick:()=>{f(e.id),u(`chat`)},children:(0,q.jsx)(s,{className:`w-3 h-3`})}),(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Pair`,onClick:()=>g(e.id),children:(0,q.jsx)(c,{className:`w-3 h-3`})}),(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Rename`,onClick:()=>T(e),children:(0,q.jsx)(o,{className:`w-3 h-3`})}),L&&(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Terminal`,disabled:re,onClick:()=>void ie(),children:(0,q.jsx)(l,{className:`w-3 h-3`})}),(e.branchState===`changes`||e.branchState===`idle`)&&e.branchWorkspaceId&&(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-amber-400 hover:text-amber-300`,title:`Mark workspace ready — hand off to the auto-merge`,onClick:()=>E(`Mark Workspace Ready`,`Mark ${w(e)}'s branch ready to land? The relay auto-merge will rebase and land it.`,()=>A(e.branchWorkspaceId,`ready`)),children:(0,q.jsx)(d,{className:`w-3 h-3`})}),se&&(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Compact`,onClick:()=>E(`Compact Agent`,`Compact context for ${w(e)}?`,()=>D(e,`compact`,`agents-grid`)),children:(0,q.jsx)(r,{className:`w-3 h-3`})}),I&&(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Clear Context`,onClick:()=>E(`Clear Context`,`Clear context for ${w(e)}?`,()=>D(e,`clearContext`,`agents-grid`)),children:(0,q.jsx)(_,{className:`w-3 h-3`})}),F&&(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Shutdown`,onClick:()=>E(`Shutdown Agent`,`Shutdown ${w(e)}?`,()=>D(e,`shutdown`,`agents-grid`)),children:(0,q.jsx)(t,{className:`w-3 h-3`})}),V&&(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Forget stale agent`,onClick:()=>E(`Forget Agent`,`Forget ${w(e)}?`,()=>O(e.id)),children:(0,q.jsx)(m,{className:`w-3 h-3`})})]})]})}),N&&(0,q.jsx)(ge,{open:M,onOpenChange:ae,orchestratorId:N.orchestratorId,session:N.session,interactive:N.interactive||R})]})}function Qe(){let e=v(e=>e.agentPresetFilter),t=v(e=>e.agentStatusFilter),n=v(e=>e.agentTagFilter),r=v(e=>e.agentHostFilter),a=v(e=>e.agentSort),o=v(e=>e.agentSortDir),s=v(e=>e.showOffline),c=v(e=>e.set),l=v(e=>e.openAgentSpawn),d=v(e=>e.agentsById),p=ee(),m=W(),h=U(),_=V(),y=me(m,p),b=de(m,p),x=e||t||n||r;function S(){c({agentPresetFilter:``,agentStatusFilter:``,agentTagFilter:``,agentHostFilter:``})}function C(){c({agentSortDir:o===`asc`?`desc`:`asc`})}return(0,q.jsxs)(`div`,{className:`space-y-4`,children:[(0,q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,q.jsxs)(`select`,{value:e,onChange:e=>c({agentPresetFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:``,children:`All agents`}),(0,q.jsx)(`option`,{value:`active`,children:`Active`}),(0,q.jsx)(`option`,{value:`claude`,children:`Claude`}),(0,q.jsx)(`option`,{value:`codex`,children:`Codex`}),(0,q.jsx)(`option`,{value:`paired`,children:`Paired`}),(0,q.jsx)(`option`,{value:`unpaired`,children:`Unpaired`}),(0,q.jsx)(`option`,{value:`offline_stale`,children:`Offline / Stale`})]}),(0,q.jsxs)(`select`,{value:t,onChange:e=>c({agentStatusFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:``,children:`Any status`}),(0,q.jsx)(`option`,{value:`online`,children:`Online`}),(0,q.jsx)(`option`,{value:`idle`,children:`Idle`}),(0,q.jsx)(`option`,{value:`busy`,children:`Busy`}),(0,q.jsx)(`option`,{value:`offline`,children:`Offline`}),(0,q.jsx)(`option`,{value:`starting`,children:`Starting`})]}),h.length>0&&(0,q.jsxs)(`select`,{value:n,onChange:e=>c({agentTagFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:``,children:`Any tag`}),h.map(e=>(0,q.jsx)(`option`,{value:e,children:e},e))]}),_.length>1&&(0,q.jsxs)(`select`,{value:r,onChange:e=>c({agentHostFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:``,children:`Any host`}),_.map(e=>(0,q.jsx)(`option`,{value:e,children:e},e))]}),(0,q.jsxs)(`select`,{value:a,onChange:e=>c({agentSort:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:`status`,children:`Sort: Status`}),(0,q.jsx)(`option`,{value:`name`,children:`Sort: Name`}),(0,q.jsx)(`option`,{value:`lastSeen`,children:`Sort: Last seen`}),(0,q.jsx)(`option`,{value:`created`,children:`Sort: Created`})]}),(0,q.jsx)(B,{size:`icon`,variant:`outline`,className:`h-8 w-8`,title:`Toggle sort direction`,onClick:C,children:o===`asc`?(0,q.jsx)(g,{className:`w-3.5 h-3.5`}):(0,q.jsx)(f,{className:`w-3.5 h-3.5`})}),(0,q.jsxs)(`label`,{className:`flex items-center gap-1.5 text-sm text-muted-foreground cursor-pointer select-none`,children:[(0,q.jsx)(`input`,{type:`checkbox`,checked:s,onChange:e=>c({showOffline:e.target.checked}),className:`rounded`}),`Show offline`]}),x&&(0,q.jsxs)(B,{size:`sm`,variant:`ghost`,className:`h-8 text-muted-foreground hover:text-foreground gap-1`,onClick:S,children:[(0,q.jsx)(u,{className:`w-3 h-3`}),`Clear filters`]}),(0,q.jsx)(`div`,{className:`ml-auto`,children:(0,q.jsxs)(B,{size:`sm`,onClick:l,className:`gap-1`,children:[(0,q.jsx)(i,{className:`w-3.5 h-3.5`}),`Spawn`]})})]}),b.length===0?(0,q.jsx)(`div`,{className:`text-center py-16 text-muted-foreground text-sm`,children:`No agents match the current filters.`}):(0,q.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-3`,children:b.map(e=>(0,q.jsx)(Ze,{agent:e,parentAgent:e.spawnedBy?d[e.spawnedBy]??null:null,childAgents:_e(y.get(e.id)??[])},e.id))})]})}export{Qe as AgentsView};
|
|
2
|
-
//# sourceMappingURL=agents-D201CuTR.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{Ct as t,Fn as n,In as r,Nn as i,Qt as a,a as o,p as s,qn as c,rn as l}from"./lucide-react-H_-8G79A.js";import{t as u}from"./store-DXdfhiVf.js";var d=e(c(),1);function f(e){let t=u(e=>e.showError),[n,i]=(0,d.useState)(!1),[a,o]=(0,d.useState)(null),[s,c]=(0,d.useState)(!1);async function l(){if(!(!e||s)){c(!0);try{o(await r(`POST`,`/agents/`+encodeURIComponent(e)+`/terminal-session`)),i(!0)}catch(e){t(`Terminal Failed`,e.message)}finally{c(!1)}}}function f(t){if(t){i(!0);return}i(!1);let n=a;o(null),e&&n?.mode===`guest`&&r(`DELETE`,`/agents/`+encodeURIComponent(e)+`/terminal-session/`+encodeURIComponent(n.session)).catch(()=>{})}return{terminalOpen:n,terminalTarget:a,terminalOpening:s,openTerminal:l,closeTerminal:f}}var p=n(),m={idle:{label:`idle`,tip:`Branch worktree — nothing to land yet.`,className:`bg-zinc-500/10 text-zinc-400 border-zinc-500/20`,Icon:a},changes:{label:`changes`,tip:`Unlanded work in this branch — use "Mark workspace ready" to land it.`,className:`bg-amber-500/10 text-amber-400 border-amber-500/20`,Icon:t},ready:{label:`ready`,tip:`Handed off — the relay auto-merge will land it (~2 min sweep).`,className:`bg-blue-500/10 text-blue-400 border-blue-500/20`,Icon:l},steward:{label:`steward`,tip:`Under reconciliation — a steward is landing it. No action needed.`,className:`bg-orange-500/10 text-orange-400 border-orange-500/20`,Icon:o},blocked:{label:`blocked`,tip:`Escalated — the auto-merge/steward path is stuck. Needs human attention.`,className:`bg-red-500/10 text-red-400 border-red-500/20`,Icon:s}};function h({state:e,onClick:t,iconOnly:n=!1,className:r}){let a=m[e],{Icon:o}=a,s=!!t,c=s?`${a.tip} Click to open this workspace.`:a.tip;return(0,p.jsxs)(`span`,{role:s?`button`:void 0,tabIndex:s?0:void 0,title:c,onClick:t,onKeyDown:s?e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),t?.(e))}:void 0,className:i(`inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium leading-none`,a.className,s&&`cursor-pointer hover:brightness-125 focus:outline-none focus:ring-1 focus:ring-current`,r),children:[(0,p.jsx)(o,{className:`h-2.5 w-2.5 shrink-0`}),!n&&(0,p.jsx)(`span`,{children:a.label})]})}export{f as n,h as t};
|
|
2
|
-
//# sourceMappingURL=branch-state-badge-BPXXLpQG.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import"./chunk-CilyBKbf.js";import{Fn as e,Nn as t,qn as n}from"./lucide-react-H_-8G79A.js";n();var r=e();function i({className:e,size:n=`default`,...i}){return(0,r.jsx)(`div`,{"data-slot":`card`,"data-size":n,className:t(`group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl`,e),...i})}function a({className:e,...n}){return(0,r.jsx)(`div`,{"data-slot":`card-header`,className:t(`group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3`,e),...n})}function o({className:e,...n}){return(0,r.jsx)(`div`,{"data-slot":`card-title`,className:t(`font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm`,e),...n})}function s({className:e,...n}){return(0,r.jsx)(`div`,{"data-slot":`card-content`,className:t(`px-4 group-data-[size=sm]/card:px-3`,e),...n})}export{o as i,s as n,a as r,i as t};
|
|
2
|
-
//# sourceMappingURL=card-BU6PvVHv.js.map
|