@borgee/agents-host 0.2.2 → 0.2.28
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/README.md +184 -21
- package/dist/agents-host-supervisor.d.ts +7 -5
- package/dist/agents-host-supervisor.js +24 -4
- package/dist/agents-host.d.ts +114 -15
- package/dist/agents-host.js +2712 -141
- package/dist/chat/chat-control-plane.d.ts +13 -2
- package/dist/chat/sdk-chat-control-plane.d.ts +14 -3
- package/dist/chat/sdk-chat-control-plane.js +54 -2
- package/dist/cli-args.d.ts +46 -5
- package/dist/cli-args.js +313 -32
- package/dist/cli.d.ts +9 -0
- package/dist/cli.js +112 -5
- package/dist/compatibility-gates.d.ts +39 -0
- package/dist/compatibility-gates.js +131 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +23 -5
- package/dist/connections-state-store.d.ts +81 -0
- package/dist/connections-state-store.js +228 -0
- package/dist/context/attention.d.ts +12 -0
- package/dist/context/attention.js +137 -0
- package/dist/context/collaboration-capabilities-diagnostics.d.ts +3 -0
- package/dist/context/collaboration-capabilities-diagnostics.js +18 -0
- package/dist/context/collaboration-outcome.d.ts +2 -0
- package/dist/context/collaboration-outcome.js +26 -0
- package/dist/context/injection.d.ts +134 -0
- package/dist/context/injection.js +355 -0
- package/dist/context/prompt.d.ts +4 -1
- package/dist/context/prompt.js +231 -1
- package/dist/context/task-thread-collaboration.d.ts +6 -0
- package/dist/context/task-thread-collaboration.js +31 -0
- package/dist/context/turn-preparation.d.ts +9 -0
- package/dist/context/turn-preparation.js +135 -0
- package/dist/debug.d.ts +44 -0
- package/dist/debug.js +135 -0
- package/dist/gateway/localhost-gateway.d.ts +52 -0
- package/dist/gateway/localhost-gateway.js +857 -0
- package/dist/index.js +7 -5
- package/dist/local-config.d.ts +4 -1
- package/dist/local-config.js +24 -7
- package/dist/managed-daemon-log.d.ts +34 -0
- package/dist/managed-daemon-log.js +261 -0
- package/dist/managed-daemon.d.ts +220 -0
- package/dist/managed-daemon.js +1601 -0
- package/dist/policy/authorization-audit.d.ts +63 -0
- package/dist/policy/authorization-audit.js +94 -0
- package/dist/policy/copilot-permission.d.ts +15 -0
- package/dist/policy/copilot-permission.js +193 -0
- package/dist/policy/gateway-authorization.d.ts +42 -0
- package/dist/policy/gateway-authorization.js +162 -0
- package/dist/providers/awaiting-user.d.ts +12 -0
- package/dist/providers/awaiting-user.js +192 -0
- package/dist/providers/claude/adapter.d.ts +3 -1
- package/dist/providers/claude/adapter.js +8 -12
- package/dist/providers/claude/cli-client.d.ts +12 -5
- package/dist/providers/claude/cli-client.js +184 -37
- package/dist/providers/claude/session-store.d.ts +1 -0
- package/dist/providers/codex/adapter.d.ts +11 -0
- package/dist/providers/codex/adapter.js +19 -0
- package/dist/providers/codex/cli-client.d.ts +103 -0
- package/dist/providers/codex/cli-client.js +1133 -0
- package/dist/providers/codex/project-doc.d.ts +3 -0
- package/dist/providers/codex/project-doc.js +90 -0
- package/dist/providers/codex/session-store.d.ts +38 -0
- package/dist/providers/codex/session-store.js +150 -0
- package/dist/providers/copilot/adapter.d.ts +3 -1
- package/dist/providers/copilot/adapter.js +8 -12
- package/dist/providers/copilot/cli-client.d.ts +20 -2
- package/dist/providers/copilot/cli-client.js +251 -71
- package/dist/providers/copilot/session-store.d.ts +1 -0
- package/dist/providers/create-provider.d.ts +11 -2
- package/dist/providers/create-provider.js +131 -12
- package/dist/run.d.ts +1 -0
- package/dist/run.js +5 -2
- package/dist/state-paths.d.ts +14 -1
- package/dist/state-paths.js +87 -3
- package/dist/task-thread-resolution.d.ts +10 -0
- package/dist/task-thread-resolution.js +48 -0
- package/dist/types.d.ts +267 -1
- package/dist/visible-mentions.d.ts +3 -0
- package/dist/visible-mentions.js +15 -0
- package/package.json +19 -17
- package/skills/borgee-agent/SKILL.md +33 -0
- package/skills/borgee-agent/borgee-agent.mjs +473 -0
- package/skills/borgee-agent/borgee-agent.py +409 -0
|
@@ -1,25 +1,144 @@
|
|
|
1
|
+
import { FileChannelContextStore } from '../context/injection.js';
|
|
2
|
+
import { createProviderConnectionsSessionStore } from '../connections-state-store.js';
|
|
3
|
+
import { ProviderTurnPreparer } from '../context/turn-preparation.js';
|
|
4
|
+
import { CLAUDE_PROVIDER_V2_COMPATIBILITY_GATE, CONNECTIONS_STATE_LAYER_COMPATIBILITY_GATE, CONTEXT_INJECTION_COMPATIBILITY_GATE, CODEX_PROVIDER_COMPATIBILITY_GATE, COPILOT_PROVIDER_V2_COMPATIBILITY_GATE, INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV, LOCALHOST_GATEWAY_COMPATIBILITY_GATE, parseInternalProviderImplementationOverrides, POLICY_AUDIT_ENFORCEMENT_COMPATIBILITY_GATE, resolveInternalPolicyMode, resolveInternalCompatibilityGates, SKILL_RUNTIME_COMPATIBILITY_GATE, } from '../compatibility-gates.js';
|
|
1
5
|
import { ClaudeCliClient } from './claude/cli-client.js';
|
|
2
6
|
import { ClaudeProviderAdapter } from './claude/adapter.js';
|
|
3
7
|
import { FileClaudeChannelSessionStore } from './claude/session-store.js';
|
|
8
|
+
import { CodexCliClient } from './codex/cli-client.js';
|
|
9
|
+
import { CodexProviderAdapter } from './codex/adapter.js';
|
|
10
|
+
import { FileCodexChannelSessionStore } from './codex/session-store.js';
|
|
4
11
|
import { CopilotCliClient } from './copilot/cli-client.js';
|
|
5
12
|
import { CopilotProviderAdapter } from './copilot/adapter.js';
|
|
6
13
|
import { FileCopilotChannelSessionStore } from './copilot/session-store.js';
|
|
7
|
-
import { resolveClaudeSessionMapPath, resolveCopilotSessionMapPath } from '../state-paths.js';
|
|
8
|
-
|
|
14
|
+
import { resolveClaudeSessionMapPath, resolveCodexSessionMapPath, resolveCopilotSessionMapPath, } from '../state-paths.js';
|
|
15
|
+
import { createAwaitingUserProgressHandler, parseProviderReply } from './awaiting-user.js';
|
|
16
|
+
class ProviderV2CompatibilityAdapter {
|
|
17
|
+
provider;
|
|
18
|
+
turnPreparer;
|
|
19
|
+
constructor(provider, turnPreparer) {
|
|
20
|
+
this.provider = provider;
|
|
21
|
+
this.turnPreparer = turnPreparer;
|
|
22
|
+
}
|
|
23
|
+
async generateReply(input, options) {
|
|
24
|
+
const preparedTurn = await this.turnPreparer.prepare(input);
|
|
25
|
+
return this.provider.generateReply({
|
|
26
|
+
turn: preparedTurn,
|
|
27
|
+
}, options);
|
|
28
|
+
}
|
|
29
|
+
async dispose() {
|
|
30
|
+
await this.provider.shutdown?.();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
class CliBackedProviderV2 {
|
|
34
|
+
cli;
|
|
35
|
+
constructor(cli) {
|
|
36
|
+
this.cli = cli;
|
|
37
|
+
}
|
|
38
|
+
async generateReply(input, options) {
|
|
39
|
+
const text = await this.cli.generateReply(input.turn, {
|
|
40
|
+
onProgress: createAwaitingUserProgressHandler(options?.onProgress),
|
|
41
|
+
});
|
|
42
|
+
return parseProviderReply(text);
|
|
43
|
+
}
|
|
44
|
+
async shutdown() {
|
|
45
|
+
await this.cli.dispose();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
class ClaudeProviderV2 extends CliBackedProviderV2 {
|
|
49
|
+
}
|
|
50
|
+
class CopilotProviderV2 extends CliBackedProviderV2 {
|
|
51
|
+
}
|
|
52
|
+
const TASK_WORKSPACE_ROOT_DIR_ENV = 'AGENTS_HOST_INTERNAL_TASK_WORKSPACE_ROOT_DIR';
|
|
53
|
+
const PROVIDER_V2_COMPATIBILITY_GATES = {
|
|
54
|
+
claude: CLAUDE_PROVIDER_V2_COMPATIBILITY_GATE,
|
|
55
|
+
copilot: COPILOT_PROVIDER_V2_COMPATIBILITY_GATE,
|
|
56
|
+
};
|
|
57
|
+
function resolveProviderImplementation(provider, routingConfig) {
|
|
58
|
+
if (!routingConfig.compatibilityGates.has(PROVIDER_V2_COMPATIBILITY_GATES[provider])) {
|
|
59
|
+
return 'v1';
|
|
60
|
+
}
|
|
61
|
+
return routingConfig.implementationOverrides[provider] ?? 'v2';
|
|
62
|
+
}
|
|
63
|
+
function createClaudeProvider(config, debugLogger, connectionsStateGateEnabled, implementation, turnPreparer) {
|
|
64
|
+
const cli = new ClaudeCliClient(config.claudeCommand, config.claudeArgs, {}, createProviderConnectionsSessionStore({
|
|
65
|
+
provider: 'claude',
|
|
66
|
+
legacyStore: new FileClaudeChannelSessionStore({
|
|
67
|
+
resolvePath: (agentId) => resolveClaudeSessionMapPath(config.stateRootDir, agentId),
|
|
68
|
+
}),
|
|
69
|
+
stateRootDir: config.stateRootDir,
|
|
70
|
+
gateEnabled: connectionsStateGateEnabled,
|
|
71
|
+
logger: debugLogger,
|
|
72
|
+
}), config.resolveStableAgentId, debugLogger);
|
|
73
|
+
return implementation === 'v2'
|
|
74
|
+
? new ProviderV2CompatibilityAdapter(new ClaudeProviderV2(cli), turnPreparer)
|
|
75
|
+
: new ClaudeProviderAdapter(cli, turnPreparer);
|
|
76
|
+
}
|
|
77
|
+
function createCopilotProvider(config, debugLogger, connectionsStateGateEnabled, implementation, turnPreparer, policyAuditGateEnabled, authorizationAuditSink) {
|
|
78
|
+
const policyMode = resolveInternalPolicyMode(policyAuditGateEnabled);
|
|
79
|
+
const cli = new CopilotCliClient(config.copilotCommand, config.copilotArgs, {
|
|
80
|
+
idleSessionTtlMs: config.copilotSessionTtlMinutes * 60 * 1000,
|
|
81
|
+
}, createProviderConnectionsSessionStore({
|
|
82
|
+
provider: 'copilot',
|
|
83
|
+
legacyStore: new FileCopilotChannelSessionStore({
|
|
84
|
+
resolvePath: (agentId) => resolveCopilotSessionMapPath(config.stateRootDir, agentId),
|
|
85
|
+
}),
|
|
86
|
+
stateRootDir: config.stateRootDir,
|
|
87
|
+
gateEnabled: connectionsStateGateEnabled,
|
|
88
|
+
logger: debugLogger,
|
|
89
|
+
}), config.resolveStableAgentId, debugLogger, {
|
|
90
|
+
gateEnabled: policyAuditGateEnabled,
|
|
91
|
+
policyMode,
|
|
92
|
+
auditSink: authorizationAuditSink,
|
|
93
|
+
});
|
|
94
|
+
return implementation === 'v2'
|
|
95
|
+
? new ProviderV2CompatibilityAdapter(new CopilotProviderV2(cli), turnPreparer)
|
|
96
|
+
: new CopilotProviderAdapter(cli, turnPreparer);
|
|
97
|
+
}
|
|
98
|
+
function createCodexProvider(config, debugLogger, connectionsStateGateEnabled, turnPreparer) {
|
|
99
|
+
const cli = new CodexCliClient(config.codexCommand, config.codexArgs, {}, createProviderConnectionsSessionStore({
|
|
100
|
+
provider: 'codex',
|
|
101
|
+
legacyStore: new FileCodexChannelSessionStore({
|
|
102
|
+
resolvePath: (agentId) => resolveCodexSessionMapPath(config.stateRootDir, agentId),
|
|
103
|
+
}),
|
|
104
|
+
stateRootDir: config.stateRootDir,
|
|
105
|
+
gateEnabled: connectionsStateGateEnabled,
|
|
106
|
+
logger: debugLogger,
|
|
107
|
+
}), config.resolveStableAgentId, debugLogger);
|
|
108
|
+
return new CodexProviderAdapter(cli, turnPreparer);
|
|
109
|
+
}
|
|
110
|
+
export function createProvider(config, debugLogger, options = {}) {
|
|
111
|
+
const routingConfig = {
|
|
112
|
+
compatibilityGates: options.compatibilityGates ?? resolveInternalCompatibilityGates(),
|
|
113
|
+
implementationOverrides: parseInternalProviderImplementationOverrides(process.env[INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV]),
|
|
114
|
+
};
|
|
115
|
+
const connectionsStateGateEnabled = routingConfig.compatibilityGates.has(CONNECTIONS_STATE_LAYER_COMPATIBILITY_GATE);
|
|
116
|
+
const contextInjectionGateEnabled = routingConfig.compatibilityGates.has(CONTEXT_INJECTION_COMPATIBILITY_GATE);
|
|
117
|
+
const skillRuntimeGateEnabled = routingConfig.compatibilityGates.has(SKILL_RUNTIME_COMPATIBILITY_GATE);
|
|
118
|
+
const localhostGatewayGateEnabled = routingConfig.compatibilityGates.has(LOCALHOST_GATEWAY_COMPATIBILITY_GATE);
|
|
119
|
+
const policyAuditGateEnabled = routingConfig.compatibilityGates.has(POLICY_AUDIT_ENFORCEMENT_COMPATIBILITY_GATE);
|
|
120
|
+
const channelContextStore = contextInjectionGateEnabled
|
|
121
|
+
? new FileChannelContextStore(config.stateRootDir, {
|
|
122
|
+
skillRuntimeEnabled: skillRuntimeGateEnabled,
|
|
123
|
+
taskWorkspaceRootDir: process.env[TASK_WORKSPACE_ROOT_DIR_ENV],
|
|
124
|
+
localhostGateway: skillRuntimeGateEnabled && localhostGatewayGateEnabled
|
|
125
|
+
? options.localhostGateway
|
|
126
|
+
: undefined,
|
|
127
|
+
})
|
|
128
|
+
: undefined;
|
|
129
|
+
const turnPreparer = new ProviderTurnPreparer(channelContextStore, debugLogger);
|
|
9
130
|
switch (config.provider) {
|
|
10
131
|
case 'claude': {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
132
|
+
return createClaudeProvider(config, debugLogger, connectionsStateGateEnabled, resolveProviderImplementation('claude', routingConfig), turnPreparer);
|
|
133
|
+
}
|
|
134
|
+
case 'codex': {
|
|
135
|
+
if (!routingConfig.compatibilityGates.has(CODEX_PROVIDER_COMPATIBILITY_GATE)) {
|
|
136
|
+
throw new Error(`Unsupported provider: ${String(config.provider)} (enable ${CODEX_PROVIDER_COMPATIBILITY_GATE})`);
|
|
137
|
+
}
|
|
138
|
+
return createCodexProvider(config, debugLogger, connectionsStateGateEnabled, turnPreparer);
|
|
15
139
|
}
|
|
16
140
|
case 'copilot': {
|
|
17
|
-
|
|
18
|
-
idleSessionTtlMs: config.copilotSessionTtlMinutes * 60 * 1000,
|
|
19
|
-
}, new FileCopilotChannelSessionStore({
|
|
20
|
-
resolvePath: (agentId) => resolveCopilotSessionMapPath(config.stateRootDir, agentId),
|
|
21
|
-
}), config.resolveStableAgentId);
|
|
22
|
-
return new CopilotProviderAdapter(cli);
|
|
141
|
+
return createCopilotProvider(config, debugLogger, connectionsStateGateEnabled, resolveProviderImplementation('copilot', routingConfig), turnPreparer, policyAuditGateEnabled, options.authorizationAuditSink);
|
|
23
142
|
}
|
|
24
143
|
default:
|
|
25
144
|
throw new Error(`Unsupported provider: ${String(config.provider)}`);
|
package/dist/run.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { parseGenerateConfigSpec, resolveLocalConfigLayout } from './local-confi
|
|
|
2
2
|
import type { LocalConfigGenerateResult, LocalConfigGenerateSpec, LocalConfigSnapshot } from './types.js';
|
|
3
3
|
export interface RunMainOptions {
|
|
4
4
|
configPath?: string;
|
|
5
|
+
debug?: boolean;
|
|
5
6
|
}
|
|
6
7
|
export interface ValidateLocalConfigDeps {
|
|
7
8
|
loadSnapshot?: (configPath: string) => Promise<LocalConfigSnapshot>;
|
package/dist/run.js
CHANGED
|
@@ -43,9 +43,12 @@ export async function generateLocalConfig(rootPath, specJson, sourceLabelOrDeps
|
|
|
43
43
|
writer.log(JSON.stringify(result, null, 2));
|
|
44
44
|
}
|
|
45
45
|
export async function runMain(options = {}) {
|
|
46
|
+
const runtimeOptions = {
|
|
47
|
+
debug: options.debug,
|
|
48
|
+
};
|
|
46
49
|
const host = options.configPath
|
|
47
|
-
? new AgentsHostSupervisor(options.configPath)
|
|
48
|
-
: new AgentsHost(loadConfigFromEnv());
|
|
50
|
+
? new AgentsHostSupervisor(options.configPath, runtimeOptions)
|
|
51
|
+
: new AgentsHost(loadConfigFromEnv(), { runtimeOptions });
|
|
49
52
|
const shutdown = (signal) => {
|
|
50
53
|
console.log(`[agents-host] received ${signal}, shutting down`);
|
|
51
54
|
host
|
package/dist/state-paths.d.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
export declare function
|
|
1
|
+
export declare function normalizeManagedRuntimeKey(serverUrl: string): string;
|
|
2
|
+
export declare function resolveSingleAgentStateRoot(env?: NodeJS.ProcessEnv, resolvedHomeDir?: string, agentKey?: string): string;
|
|
3
|
+
export declare function resolveManagedRuntimeRoot(serverUrl: string, env?: NodeJS.ProcessEnv, resolvedHomeDir?: string): string;
|
|
2
4
|
export declare function resolveManagedStateRoot(rootPath: string): string;
|
|
5
|
+
export declare function resolveManagedDaemonSocketPath(rootPath: string): string;
|
|
6
|
+
export declare function resolveManagedDaemonLogPath(rootPath: string): string;
|
|
7
|
+
export declare function resolveManagedRuntimeSettingsPath(rootPath: string): string;
|
|
8
|
+
export declare function resolveManagedBootstrapLockPath(rootPath: string): string;
|
|
3
9
|
export declare function resolveLocalConfigAgentStateRoot(rootPath: string, agentKey: string): string;
|
|
4
10
|
export declare function resolveAgentCursorPath(stateRootDir: string, agentId: string): string;
|
|
11
|
+
export declare function resolveSharedProtocolKickoffDecisionPath(stateRootDir: string, channelId: string, anchorMessageId: string): string;
|
|
12
|
+
export declare function resolveSharedProtocolStatusPath(stateRootDir: string, channelId: string, anchorMessageId: string): string;
|
|
13
|
+
export declare function resolveConnectionsStatePath(stateRootDir: string): string;
|
|
14
|
+
export declare function resolveAttentionStatePath(stateRootDir: string, channelId: string): string;
|
|
15
|
+
export declare function resolveAuthorizationAuditPath(stateRootDir: string): string;
|
|
16
|
+
export declare function resolvePreviousAuthorizationAuditPath(stateRootDir: string): string;
|
|
5
17
|
export declare function resolveClaudeSessionMapPath(stateRootDir: string, agentId: string): string;
|
|
18
|
+
export declare function resolveCodexSessionMapPath(stateRootDir: string, agentId: string): string;
|
|
6
19
|
export declare function resolveCopilotSessionMapPath(stateRootDir: string, agentId: string): string;
|
package/dist/state-paths.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
|
-
import { join, resolve } from 'node:path';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
const SINGLE_AGENT_HOME_ROOT = '.borgee';
|
|
5
5
|
const AGENTS_HOST_ROOT = 'agents-host';
|
|
6
6
|
const SINGLE_AGENT_NAMESPACE = 'single-agent';
|
|
7
|
+
const MANAGED_RUNTIME_NAMESPACE = 'managed';
|
|
7
8
|
const MANAGED_STATE_DIRNAME = '.state';
|
|
9
|
+
const MANAGED_DAEMON_SOCKET_FILENAME = 'ctl.sock';
|
|
10
|
+
const MANAGED_DAEMON_LOG_FILENAME = 'daemon.log';
|
|
11
|
+
const MANAGED_RUNTIME_SETTINGS_FILENAME = 'managed-runtime-settings.json';
|
|
12
|
+
const MANAGED_BOOTSTRAP_LOCK_DIRNAME = '.bootstrap.lock';
|
|
8
13
|
const STATE_ROOT_LABEL_MAX_LENGTH = 48;
|
|
14
|
+
const MANAGED_RUNTIME_LABEL_MAX_LENGTH = 24;
|
|
9
15
|
function encodeSegment(value) {
|
|
10
16
|
return encodeURIComponent(value);
|
|
11
17
|
}
|
|
@@ -22,25 +28,103 @@ function sanitizeStateRootLabel(agentKey) {
|
|
|
22
28
|
function hashStateRootKey(agentKey) {
|
|
23
29
|
return createHash('sha256').update(agentKey).digest('hex').slice(0, 12);
|
|
24
30
|
}
|
|
25
|
-
export function
|
|
31
|
+
export function normalizeManagedRuntimeKey(serverUrl) {
|
|
32
|
+
const trimmed = serverUrl.trim();
|
|
33
|
+
try {
|
|
34
|
+
const parsed = new URL(trimmed);
|
|
35
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/u, '') || '/';
|
|
36
|
+
return parsed.toString();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return trimmed.replace(/\/+$/u, '');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function sanitizeManagedRuntimeLabel(serverUrl) {
|
|
43
|
+
const normalized = normalizeManagedRuntimeKey(serverUrl);
|
|
44
|
+
let labelSource = normalized;
|
|
45
|
+
try {
|
|
46
|
+
const parsed = new URL(normalized);
|
|
47
|
+
labelSource = `${parsed.hostname}${parsed.pathname === '/' ? '' : parsed.pathname}`;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
labelSource = normalized;
|
|
51
|
+
}
|
|
52
|
+
const sanitized = encodeSegment(labelSource)
|
|
53
|
+
.toLowerCase()
|
|
54
|
+
.replace(/%/g, '-')
|
|
55
|
+
.replace(/[^a-z0-9._-]+/g, '-')
|
|
56
|
+
.replace(/-+/g, '-')
|
|
57
|
+
.replace(/^-|-$/g, '')
|
|
58
|
+
.slice(0, MANAGED_RUNTIME_LABEL_MAX_LENGTH);
|
|
59
|
+
return sanitized.length > 0 ? sanitized : 'server';
|
|
60
|
+
}
|
|
61
|
+
function hashManagedRuntimeKey(serverUrl) {
|
|
62
|
+
return createHash('sha256').update(normalizeManagedRuntimeKey(serverUrl)).digest('hex').slice(0, 12);
|
|
63
|
+
}
|
|
64
|
+
export function resolveSingleAgentStateRoot(env = process.env, resolvedHomeDir = homedir(), agentKey) {
|
|
26
65
|
const home = env.HOME?.trim() || resolvedHomeDir.trim();
|
|
27
66
|
if (!home) {
|
|
28
67
|
throw new Error('Unable to resolve a user home directory for agents-host state');
|
|
29
68
|
}
|
|
30
|
-
|
|
69
|
+
const baseRoot = join(home, SINGLE_AGENT_HOME_ROOT, AGENTS_HOST_ROOT, SINGLE_AGENT_NAMESPACE);
|
|
70
|
+
const normalizedAgentKey = agentKey?.trim();
|
|
71
|
+
if (!normalizedAgentKey) {
|
|
72
|
+
return baseRoot;
|
|
73
|
+
}
|
|
74
|
+
return join(baseRoot, `agent-${hashStateRootKey(normalizedAgentKey)}`);
|
|
75
|
+
}
|
|
76
|
+
export function resolveManagedRuntimeRoot(serverUrl, env = process.env, resolvedHomeDir = homedir()) {
|
|
77
|
+
const home = env.HOME?.trim() || resolvedHomeDir.trim();
|
|
78
|
+
if (!home) {
|
|
79
|
+
throw new Error('Unable to resolve a user home directory for agents-host state');
|
|
80
|
+
}
|
|
81
|
+
return join(home, SINGLE_AGENT_HOME_ROOT, AGENTS_HOST_ROOT, MANAGED_RUNTIME_NAMESPACE, `${sanitizeManagedRuntimeLabel(serverUrl)}-${hashManagedRuntimeKey(serverUrl)}`);
|
|
31
82
|
}
|
|
32
83
|
export function resolveManagedStateRoot(rootPath) {
|
|
33
84
|
return join(resolve(rootPath), MANAGED_STATE_DIRNAME);
|
|
34
85
|
}
|
|
86
|
+
export function resolveManagedDaemonSocketPath(rootPath) {
|
|
87
|
+
return join(resolve(rootPath), MANAGED_DAEMON_SOCKET_FILENAME);
|
|
88
|
+
}
|
|
89
|
+
export function resolveManagedDaemonLogPath(rootPath) {
|
|
90
|
+
return join(resolve(rootPath), MANAGED_DAEMON_LOG_FILENAME);
|
|
91
|
+
}
|
|
92
|
+
export function resolveManagedRuntimeSettingsPath(rootPath) {
|
|
93
|
+
return join(resolve(rootPath), MANAGED_RUNTIME_SETTINGS_FILENAME);
|
|
94
|
+
}
|
|
95
|
+
export function resolveManagedBootstrapLockPath(rootPath) {
|
|
96
|
+
return join(resolve(rootPath), MANAGED_BOOTSTRAP_LOCK_DIRNAME);
|
|
97
|
+
}
|
|
35
98
|
export function resolveLocalConfigAgentStateRoot(rootPath, agentKey) {
|
|
36
99
|
return join(resolveManagedStateRoot(rootPath), `${sanitizeStateRootLabel(agentKey)}-${hashStateRootKey(agentKey)}`);
|
|
37
100
|
}
|
|
38
101
|
export function resolveAgentCursorPath(stateRootDir, agentId) {
|
|
39
102
|
return join(stateRootDir, `bpp-cursor-${encodeSegment(agentId)}.json`);
|
|
40
103
|
}
|
|
104
|
+
export function resolveSharedProtocolKickoffDecisionPath(stateRootDir, channelId, anchorMessageId) {
|
|
105
|
+
return join(dirname(resolve(stateRootDir)), 'protocol-kickoff-decisions', `${encodeSegment(channelId)}--${encodeSegment(anchorMessageId)}.json`);
|
|
106
|
+
}
|
|
107
|
+
export function resolveSharedProtocolStatusPath(stateRootDir, channelId, anchorMessageId) {
|
|
108
|
+
return join(dirname(resolve(stateRootDir)), 'protocol-status', `${encodeSegment(channelId)}--${encodeSegment(anchorMessageId)}.json`);
|
|
109
|
+
}
|
|
110
|
+
export function resolveConnectionsStatePath(stateRootDir) {
|
|
111
|
+
return join(stateRootDir, 'connections-state.sqlite');
|
|
112
|
+
}
|
|
113
|
+
export function resolveAttentionStatePath(stateRootDir, channelId) {
|
|
114
|
+
return join(stateRootDir, 'attention-state', `${encodeSegment(channelId)}.json`);
|
|
115
|
+
}
|
|
116
|
+
export function resolveAuthorizationAuditPath(stateRootDir) {
|
|
117
|
+
return join(stateRootDir, 'authorization-audit.jsonl');
|
|
118
|
+
}
|
|
119
|
+
export function resolvePreviousAuthorizationAuditPath(stateRootDir) {
|
|
120
|
+
return join(stateRootDir, 'authorization-audit.previous.jsonl');
|
|
121
|
+
}
|
|
41
122
|
export function resolveClaudeSessionMapPath(stateRootDir, agentId) {
|
|
42
123
|
return join(stateRootDir, `claude-channel-sessions-${encodeSegment(agentId)}.json`);
|
|
43
124
|
}
|
|
125
|
+
export function resolveCodexSessionMapPath(stateRootDir, agentId) {
|
|
126
|
+
return join(stateRootDir, `codex-channel-sessions-${encodeSegment(agentId)}.json`);
|
|
127
|
+
}
|
|
44
128
|
export function resolveCopilotSessionMapPath(stateRootDir, agentId) {
|
|
45
129
|
return join(stateRootDir, `copilot-channel-sessions-${encodeSegment(agentId)}.json`);
|
|
46
130
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatControlPlane } from './chat/chat-control-plane.js';
|
|
2
|
+
import type { Task } from './types.js';
|
|
3
|
+
interface WaitForTaskForThreadOptions {
|
|
4
|
+
preferredTaskId?: string;
|
|
5
|
+
attempts?: number;
|
|
6
|
+
delayMs?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function findTaskForThread(controlPlane: ChatControlPlane, threadId: string, preferredTaskId?: string): Promise<Task | null>;
|
|
9
|
+
export declare function waitForTaskForThread(controlPlane: ChatControlPlane, threadId: string, options?: WaitForTaskForThreadOptions): Promise<Task | null>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export async function findTaskForThread(controlPlane, threadId, preferredTaskId) {
|
|
2
|
+
if (preferredTaskId) {
|
|
3
|
+
try {
|
|
4
|
+
const task = await controlPlane.getTask({ taskId: preferredTaskId });
|
|
5
|
+
if (task.threadId === threadId) {
|
|
6
|
+
return task;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
// Fall through to the visibility-based compatibility scan.
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const channels = await controlPlane.listChannels();
|
|
14
|
+
let matchedTask = null;
|
|
15
|
+
for (const channel of channels) {
|
|
16
|
+
let tasks;
|
|
17
|
+
try {
|
|
18
|
+
tasks = await controlPlane.listTasks({ channelId: channel.id });
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
for (const task of tasks) {
|
|
24
|
+
if (task.threadId !== threadId) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (matchedTask && matchedTask.id !== task.id) {
|
|
28
|
+
throw new Error(`multiple tasks matched thread ${threadId}`);
|
|
29
|
+
}
|
|
30
|
+
matchedTask = task;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return matchedTask;
|
|
34
|
+
}
|
|
35
|
+
export async function waitForTaskForThread(controlPlane, threadId, options = {}) {
|
|
36
|
+
const attempts = Math.max(1, options.attempts ?? 1);
|
|
37
|
+
const delayMs = Math.max(0, options.delayMs ?? 0);
|
|
38
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
39
|
+
const task = await findTaskForThread(controlPlane, threadId, options.preferredTaskId);
|
|
40
|
+
if (task) {
|
|
41
|
+
return task;
|
|
42
|
+
}
|
|
43
|
+
if (attempt < attempts - 1 && delayMs > 0) {
|
|
44
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|