@provos/ironcurtain 0.4.1 → 0.5.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/README.md +219 -248
- package/dist/cli.js +10 -0
- package/dist/cli.js.map +1 -1
- package/dist/config/config-command.js +144 -6
- package/dist/config/config-command.js.map +1 -1
- package/dist/config/constitution-user-base.md +2 -0
- package/dist/config/first-start.js +77 -12
- package/dist/config/first-start.js.map +1 -1
- package/dist/config/generated/compiled-policy.json +199 -72
- package/dist/config/generated/tool-annotations.json +1018 -36
- package/dist/config/mcp-servers.json +10 -0
- package/dist/config/paths.d.ts +31 -0
- package/dist/config/paths.js +52 -2
- package/dist/config/paths.js.map +1 -1
- package/dist/config/types.d.ts +8 -0
- package/dist/config/user-config.d.ts +21 -3
- package/dist/config/user-config.js +34 -3
- package/dist/config/user-config.js.map +1 -1
- package/dist/docker/adapters/claude-code.js +64 -8
- package/dist/docker/adapters/claude-code.js.map +1 -1
- package/dist/docker/agent-adapter.d.ts +18 -1
- package/dist/docker/docker-agent-session.d.ts +15 -8
- package/dist/docker/docker-agent-session.js +61 -88
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +51 -0
- package/dist/docker/docker-infrastructure.js +261 -0
- package/dist/docker/docker-infrastructure.js.map +1 -0
- package/dist/docker/docker-manager.js +3 -0
- package/dist/docker/docker-manager.js.map +1 -1
- package/dist/docker/mitm-proxy.js +4 -0
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/oauth-credentials.d.ts +81 -0
- package/dist/docker/oauth-credentials.js +178 -0
- package/dist/docker/oauth-credentials.js.map +1 -0
- package/dist/docker/orientation.js +1 -1
- package/dist/docker/orientation.js.map +1 -1
- package/dist/docker/provider-config.d.ts +3 -0
- package/dist/docker/provider-config.js +28 -0
- package/dist/docker/provider-config.js.map +1 -1
- package/dist/docker/pty-session.d.ts +27 -0
- package/dist/docker/pty-session.js +420 -0
- package/dist/docker/pty-session.js.map +1 -0
- package/dist/docker/pty-types.d.ts +24 -0
- package/dist/docker/pty-types.js +12 -0
- package/dist/docker/pty-types.js.map +1 -0
- package/dist/docker/types.d.ts +6 -0
- package/dist/escalation/escalation-watcher.d.ts +44 -0
- package/dist/escalation/escalation-watcher.js +92 -0
- package/dist/escalation/escalation-watcher.js.map +1 -0
- package/dist/escalation/listener-command.d.ts +10 -0
- package/dist/escalation/listener-command.js +407 -0
- package/dist/escalation/listener-command.js.map +1 -0
- package/dist/escalation/listener-state.d.ts +49 -0
- package/dist/escalation/listener-state.js +104 -0
- package/dist/escalation/listener-state.js.map +1 -0
- package/dist/escalation/session-registry.d.ts +17 -0
- package/dist/escalation/session-registry.js +98 -0
- package/dist/escalation/session-registry.js.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.js +2 -3
- package/dist/logger.js.map +1 -1
- package/dist/pipeline/annotate.js +35 -15
- package/dist/pipeline/annotate.js.map +1 -1
- package/dist/pipeline/constitution-customizer.d.ts +2 -1
- package/dist/pipeline/constitution-customizer.js +36 -3
- package/dist/pipeline/constitution-customizer.js.map +1 -1
- package/dist/pipeline/github-identity.d.ts +38 -0
- package/dist/pipeline/github-identity.js +64 -0
- package/dist/pipeline/github-identity.js.map +1 -0
- package/dist/pipeline/handwritten-scenarios.js +34 -0
- package/dist/pipeline/handwritten-scenarios.js.map +1 -1
- package/dist/sandbox/index.js +12 -3
- package/dist/sandbox/index.js.map +1 -1
- package/dist/servers/fetch-server.js +2 -2
- package/dist/session/base-transport.d.ts +19 -0
- package/dist/session/base-transport.js +36 -0
- package/dist/session/base-transport.js.map +1 -0
- package/dist/session/cli-transport.d.ts +3 -3
- package/dist/session/cli-transport.js +7 -4
- package/dist/session/cli-transport.js.map +1 -1
- package/dist/session/index.js +24 -78
- package/dist/session/index.js.map +1 -1
- package/dist/session/interaction-log.d.ts +13 -0
- package/dist/session/interaction-log.js +28 -0
- package/dist/session/interaction-log.js.map +1 -0
- package/dist/session/preflight.d.ts +3 -0
- package/dist/session/preflight.js +39 -18
- package/dist/session/preflight.js.map +1 -1
- package/dist/session/types.d.ts +2 -0
- package/dist/signal/bot-command.js +5 -0
- package/dist/signal/bot-command.js.map +1 -1
- package/dist/signal/format.d.ts +21 -1
- package/dist/signal/format.js +41 -3
- package/dist/signal/format.js.map +1 -1
- package/dist/signal/signal-bot-daemon.d.ts +53 -18
- package/dist/signal/signal-bot-daemon.js +344 -106
- package/dist/signal/signal-bot-daemon.js.map +1 -1
- package/dist/signal/signal-config.d.ts +4 -0
- package/dist/signal/signal-config.js +2 -0
- package/dist/signal/signal-config.js.map +1 -1
- package/dist/signal/signal-transport.d.ts +13 -7
- package/dist/signal/signal-transport.js +36 -12
- package/dist/signal/signal-transport.js.map +1 -1
- package/dist/trusted-process/audit-log.d.ts +6 -1
- package/dist/trusted-process/audit-log.js +22 -2
- package/dist/trusted-process/audit-log.js.map +1 -1
- package/dist/trusted-process/audit-redactor.d.ts +25 -0
- package/dist/trusted-process/audit-redactor.js +121 -0
- package/dist/trusted-process/audit-redactor.js.map +1 -0
- package/dist/trusted-process/escalation.d.ts +1 -1
- package/dist/trusted-process/escalation.js +6 -1
- package/dist/trusted-process/escalation.js.map +1 -1
- package/dist/trusted-process/index.d.ts +2 -1
- package/dist/trusted-process/index.js +24 -6
- package/dist/trusted-process/index.js.map +1 -1
- package/dist/trusted-process/mcp-client-manager.js +14 -2
- package/dist/trusted-process/mcp-client-manager.js.map +1 -1
- package/dist/trusted-process/mcp-error-utils.d.ts +11 -0
- package/dist/trusted-process/mcp-error-utils.js +50 -0
- package/dist/trusted-process/mcp-error-utils.js.map +1 -0
- package/dist/trusted-process/mcp-proxy-server.d.ts +4 -0
- package/dist/trusted-process/mcp-proxy-server.js +14 -4
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
- package/dist/trusted-process/sandbox-integration.d.ts +5 -0
- package/dist/trusted-process/sandbox-integration.js +1 -1
- package/dist/trusted-process/sandbox-integration.js.map +1 -1
- package/dist/trusted-process/server-context.d.ts +21 -0
- package/dist/trusted-process/server-context.js +42 -0
- package/dist/trusted-process/server-context.js.map +1 -0
- package/dist/types/argument-roles.d.ts +5 -2
- package/dist/types/argument-roles.js +25 -2
- package/dist/types/argument-roles.js.map +1 -1
- package/docker/Dockerfile.claude-code +8 -3
- package/docker/entrypoint-claude-code.sh +64 -4
- package/package.json +16 -8
- package/src/config/constitution-user-base.md +2 -0
- package/src/config/generated/compiled-policy.json +199 -72
- package/src/config/generated/tool-annotations.json +1018 -36
- package/src/config/mcp-servers.json +10 -0
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { execFile as execFileCb } from 'node:child_process';
|
|
9
9
|
import { promisify } from 'node:util';
|
|
10
|
+
import { detectAuthMethod, loadOAuthCredentials } from '../docker/oauth-credentials.js';
|
|
10
11
|
const execFile = promisify(execFileCb);
|
|
11
12
|
const DOCKER_TIMEOUT_MS = 5_000;
|
|
12
13
|
const DEFAULT_DOCKER_AGENT = 'claude-code';
|
|
@@ -34,11 +35,30 @@ export async function checkDockerAvailable() {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
38
|
+
* Sources that skip macOS Keychain to keep preflight fast and non-interactive.
|
|
39
|
+
* Full Keychain detection happens in prepareDockerInfrastructure().
|
|
40
|
+
*
|
|
41
|
+
* Limitation: macOS users whose OAuth credentials exist only in the Keychain
|
|
42
|
+
* (no ~/.claude/.credentials.json and no API key) will fall back to builtin
|
|
43
|
+
* in auto-detect mode, or get a PreflightError with explicit --agent.
|
|
44
|
+
* In practice this is rare: Claude Code always writes the credentials file.
|
|
45
|
+
*/
|
|
46
|
+
const preflightSources = {
|
|
47
|
+
loadFromFile: loadOAuthCredentials,
|
|
48
|
+
loadFromKeychain: () => null,
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Checks whether credentials (OAuth or API key) are available for the given agent.
|
|
52
|
+
* Returns the auth kind if available, or null if no credentials found.
|
|
53
|
+
*
|
|
54
|
+
* Skips macOS Keychain to avoid interactive prompts during preflight.
|
|
55
|
+
* Full detection including Keychain happens in prepareDockerInfrastructure().
|
|
39
56
|
*/
|
|
40
|
-
function
|
|
41
|
-
|
|
57
|
+
function detectCredentials(_agentId, config, sources) {
|
|
58
|
+
const auth = detectAuthMethod(config, sources ?? preflightSources);
|
|
59
|
+
if (auth.kind === 'none')
|
|
60
|
+
return null;
|
|
61
|
+
return auth.kind === 'oauth' ? 'oauth' : 'apikey';
|
|
42
62
|
}
|
|
43
63
|
/**
|
|
44
64
|
* Resolves the session mode based on explicit --agent flag or auto-detection.
|
|
@@ -47,14 +67,14 @@ function hasApiKeyForAgent(_agentId, config) {
|
|
|
47
67
|
* - Auto-detect: prefers Docker when available; silently falls back to builtin. Never throws.
|
|
48
68
|
*/
|
|
49
69
|
export async function resolveSessionMode(options) {
|
|
50
|
-
const { config, requestedAgent } = options;
|
|
70
|
+
const { config, requestedAgent, credentialSources } = options;
|
|
51
71
|
const isDockerAvailable = options.isDockerAvailable ?? checkDockerAvailable;
|
|
52
72
|
if (requestedAgent !== undefined) {
|
|
53
|
-
return resolveExplicit(requestedAgent, config, isDockerAvailable);
|
|
73
|
+
return resolveExplicit(requestedAgent, config, isDockerAvailable, credentialSources);
|
|
54
74
|
}
|
|
55
|
-
return resolveAutoDetect(config, isDockerAvailable);
|
|
75
|
+
return resolveAutoDetect(config, isDockerAvailable, credentialSources);
|
|
56
76
|
}
|
|
57
|
-
async function resolveExplicit(agent, config, isDockerAvailable) {
|
|
77
|
+
async function resolveExplicit(agent, config, isDockerAvailable, credentialSources) {
|
|
58
78
|
if (agent === 'builtin') {
|
|
59
79
|
return {
|
|
60
80
|
mode: { kind: 'builtin' },
|
|
@@ -65,16 +85,16 @@ async function resolveExplicit(agent, config, isDockerAvailable) {
|
|
|
65
85
|
if (!dockerOk) {
|
|
66
86
|
throw new PreflightError(`--agent ${agent} requires Docker, but the Docker daemon is not available. ` + 'Is Docker installed and running?');
|
|
67
87
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
88
|
+
const credKind = detectCredentials(agent, config, credentialSources);
|
|
89
|
+
if (credKind === null) {
|
|
90
|
+
throw new PreflightError(`--agent ${agent} requires authentication. ` + 'Log in with `claude login` (OAuth) or set ANTHROPIC_API_KEY.');
|
|
71
91
|
}
|
|
72
92
|
return {
|
|
73
|
-
mode: { kind: 'docker', agent },
|
|
74
|
-
reason:
|
|
93
|
+
mode: { kind: 'docker', agent, authKind: credKind },
|
|
94
|
+
reason: `Explicit --agent selection (${credKind === 'oauth' ? 'OAuth' : 'API key'})`,
|
|
75
95
|
};
|
|
76
96
|
}
|
|
77
|
-
async function resolveAutoDetect(config, isDockerAvailable) {
|
|
97
|
+
async function resolveAutoDetect(config, isDockerAvailable, credentialSources) {
|
|
78
98
|
const dockerOk = await isDockerAvailable();
|
|
79
99
|
if (!dockerOk) {
|
|
80
100
|
return {
|
|
@@ -82,15 +102,16 @@ async function resolveAutoDetect(config, isDockerAvailable) {
|
|
|
82
102
|
reason: 'Docker not available',
|
|
83
103
|
};
|
|
84
104
|
}
|
|
85
|
-
|
|
105
|
+
const credKind = detectCredentials(DEFAULT_DOCKER_AGENT, config, credentialSources);
|
|
106
|
+
if (credKind === null) {
|
|
86
107
|
return {
|
|
87
108
|
mode: { kind: 'builtin' },
|
|
88
|
-
reason: '
|
|
109
|
+
reason: 'No credentials (OAuth or API key)',
|
|
89
110
|
};
|
|
90
111
|
}
|
|
91
112
|
return {
|
|
92
|
-
mode: { kind: 'docker', agent: DEFAULT_DOCKER_AGENT },
|
|
93
|
-
reason:
|
|
113
|
+
mode: { kind: 'docker', agent: DEFAULT_DOCKER_AGENT, authKind: credKind },
|
|
114
|
+
reason: `Docker available, ${credKind === 'oauth' ? 'OAuth' : 'ANTHROPIC_API_KEY'} detected`,
|
|
94
115
|
};
|
|
95
116
|
}
|
|
96
117
|
//# sourceMappingURL=preflight.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/session/preflight.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/session/preflight.ts"],"names":[],"mappings":"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"}
|
package/dist/session/types.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export type SessionMode = {
|
|
|
34
34
|
} | {
|
|
35
35
|
readonly kind: 'docker';
|
|
36
36
|
readonly agent: AgentId;
|
|
37
|
+
readonly authKind?: 'oauth' | 'apikey';
|
|
37
38
|
};
|
|
38
39
|
/**
|
|
39
40
|
* A single turn in the conversation. Captures what the user said,
|
|
@@ -139,6 +140,7 @@ export interface EscalationRequest {
|
|
|
139
140
|
readonly serverName: string;
|
|
140
141
|
readonly arguments: Record<string, unknown>;
|
|
141
142
|
readonly reason: string;
|
|
143
|
+
readonly context?: Readonly<Record<string, string>>;
|
|
142
144
|
}
|
|
143
145
|
/**
|
|
144
146
|
* Options for creating a session. Extends the base config with
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { loadConfig } from '../config/index.js';
|
|
10
10
|
import { loadUserConfig } from '../config/user-config.js';
|
|
11
|
+
import { getDaemonLogPath } from '../config/paths.js';
|
|
11
12
|
import { createDockerManager } from '../docker/docker-manager.js';
|
|
12
13
|
import { resolveSessionMode } from '../session/preflight.js';
|
|
13
14
|
import { SignalBotDaemon } from './signal-bot-daemon.js';
|
|
@@ -21,6 +22,10 @@ export async function runBot(options = {}) {
|
|
|
21
22
|
process.stderr.write('Signal is not configured. Run: ironcurtain setup-signal\n');
|
|
22
23
|
process.exit(1);
|
|
23
24
|
}
|
|
25
|
+
// Set up daemon-wide logger before creating sessions.
|
|
26
|
+
// Individual session creations will call logger.setup() too,
|
|
27
|
+
// but it's now idempotent — subsequent calls are no-ops.
|
|
28
|
+
logger.setup({ logFilePath: getDaemonLogPath('signal-bot') });
|
|
24
29
|
const config = loadConfig();
|
|
25
30
|
// Resolve session mode (same logic as `ironcurtain start`)
|
|
26
31
|
const preflight = await resolveSessionMode({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot-command.js","sourceRoot":"","sources":["../../src/signal/bot-command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAQvC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,UAAsB,EAAE;IACnD,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAErD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,2DAA2D;IAC3D,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC;QACzC,MAAM;QACN,cAAc,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAE,OAAO,CAAC,KAAiB,CAAC,CAAC,CAAC,SAAS;KACvE,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;IAE5B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,MAAM,gBAAgB,GAAG,4BAA4B,CAAC,MAAM,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAEtF,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,MAAM,EAAE,YAAY;QACpB,gBAAgB;QAChB,IAAI;KACL,CAAC,CAAC;IAEH,gDAAgD;IAChD,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,IAAI,YAAY;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,4BAA4B;QAC/D,YAAY,GAAG,IAAI,CAAC;QACpB,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,MAAM,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;IAE7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,IAAI,CAAC,IAAI,QAAQ,CAAC,CAAC;IAC3E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAEhD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC"}
|
|
1
|
+
{"version":3,"file":"bot-command.js","sourceRoot":"","sources":["../../src/signal/bot-command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAQvC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,UAAsB,EAAE;IACnD,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAErD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,sDAAsD;IACtD,6DAA6D;IAC7D,yDAAyD;IACzD,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAE9D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,2DAA2D;IAC3D,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC;QACzC,MAAM;QACN,cAAc,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAE,OAAO,CAAC,KAAiB,CAAC,CAAC,CAAC,SAAS;KACvE,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;IAE5B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,MAAM,gBAAgB,GAAG,4BAA4B,CAAC,MAAM,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAEtF,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,MAAM,EAAE,YAAY;QACpB,gBAAgB;QAChB,IAAI;KACL,CAAC,CAAC;IAEH,gDAAgD;IAChD,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,IAAI,YAAY;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,4BAA4B;QAC/D,YAAY,GAAG,IAAI,CAAC;QACpB,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,MAAM,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;IAE7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,IAAI,CAAC,IAAI,QAAQ,CAAC,CAAC;IAC3E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAEhD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC"}
|
package/dist/signal/format.d.ts
CHANGED
|
@@ -12,8 +12,11 @@ export declare const SIGNAL_MAX_MESSAGE_LENGTH = 2000;
|
|
|
12
12
|
* Formats an escalation request as a styled text banner.
|
|
13
13
|
* Includes tool name, arguments, reason, and instructions
|
|
14
14
|
* for the user to reply "approve" or "deny".
|
|
15
|
+
*
|
|
16
|
+
* When sessionLabel is provided, includes `[#N]` in the header
|
|
17
|
+
* so the user knows which session is escalating.
|
|
15
18
|
*/
|
|
16
|
-
export declare function formatEscalationBanner(request: EscalationRequest): string;
|
|
19
|
+
export declare function formatEscalationBanner(request: EscalationRequest, sessionLabel?: number): string;
|
|
17
20
|
/**
|
|
18
21
|
* Formats budget status for the /budget command.
|
|
19
22
|
* Shows current turn consumption and session totals.
|
|
@@ -29,3 +32,20 @@ export declare function formatBudgetSummary(status: BudgetStatus): string;
|
|
|
29
32
|
* then single newlines, then at the hard limit.
|
|
30
33
|
*/
|
|
31
34
|
export declare function splitMessage(text: string, maxLength: number): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Information about a managed session for display purposes.
|
|
37
|
+
*/
|
|
38
|
+
export interface SessionListEntry {
|
|
39
|
+
readonly label: number;
|
|
40
|
+
readonly turnCount: number;
|
|
41
|
+
readonly budgetPercent: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Formats the /sessions command output.
|
|
45
|
+
* Marks the current session with `>`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function formatSessionList(sessions: SessionListEntry[], currentLabel: number | null): string;
|
|
48
|
+
/**
|
|
49
|
+
* Prefixes a message with `[#N]` when multiple sessions are active.
|
|
50
|
+
*/
|
|
51
|
+
export declare function prefixWithLabel(text: string, label: number, sessionCount: number): string;
|
package/dist/signal/format.js
CHANGED
|
@@ -11,15 +11,31 @@ export const SIGNAL_MAX_MESSAGE_LENGTH = 2000;
|
|
|
11
11
|
* Formats an escalation request as a styled text banner.
|
|
12
12
|
* Includes tool name, arguments, reason, and instructions
|
|
13
13
|
* for the user to reply "approve" or "deny".
|
|
14
|
+
*
|
|
15
|
+
* When sessionLabel is provided, includes `[#N]` in the header
|
|
16
|
+
* so the user knows which session is escalating.
|
|
14
17
|
*/
|
|
15
|
-
export function formatEscalationBanner(request) {
|
|
18
|
+
export function formatEscalationBanner(request, sessionLabel) {
|
|
16
19
|
const separator = '\u2501'.repeat(30); // box drawing heavy horizontal
|
|
17
|
-
const
|
|
20
|
+
const labelTag = sessionLabel != null ? ` [#${sessionLabel}]` : '';
|
|
21
|
+
const header = `**ESCALATION${labelTag}: Human approval required**`;
|
|
18
22
|
const toolLine = `Tool: \`${request.serverName}/${request.toolName}\``;
|
|
19
23
|
const argsLine = `Arguments: \`${JSON.stringify(request.arguments)}\``;
|
|
24
|
+
const contextLines = request.context ? Object.entries(request.context).map(([k, v]) => `${k}: \`${v}\``) : [];
|
|
20
25
|
const reasonLine = `Reason: *${request.reason}*`;
|
|
21
26
|
const instructions = '**Reply "approve" or "deny"**';
|
|
22
|
-
return [
|
|
27
|
+
return [
|
|
28
|
+
separator,
|
|
29
|
+
header,
|
|
30
|
+
separator,
|
|
31
|
+
toolLine,
|
|
32
|
+
argsLine,
|
|
33
|
+
...contextLines,
|
|
34
|
+
reasonLine,
|
|
35
|
+
separator,
|
|
36
|
+
instructions,
|
|
37
|
+
separator,
|
|
38
|
+
].join('\n');
|
|
23
39
|
}
|
|
24
40
|
/**
|
|
25
41
|
* Formats budget status for the /budget command.
|
|
@@ -90,6 +106,28 @@ export function splitMessage(text, maxLength) {
|
|
|
90
106
|
}
|
|
91
107
|
return chunks;
|
|
92
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Formats the /sessions command output.
|
|
111
|
+
* Marks the current session with `>`.
|
|
112
|
+
*/
|
|
113
|
+
export function formatSessionList(sessions, currentLabel) {
|
|
114
|
+
if (sessions.length === 0)
|
|
115
|
+
return 'No active sessions.';
|
|
116
|
+
const lines = ['**Active sessions:**'];
|
|
117
|
+
for (const s of sessions) {
|
|
118
|
+
const marker = s.label === currentLabel ? '>' : ' ';
|
|
119
|
+
lines.push(`${marker} #${s.label} turns: ${s.turnCount} budget: ${s.budgetPercent}%`);
|
|
120
|
+
}
|
|
121
|
+
return lines.join('\n');
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Prefixes a message with `[#N]` when multiple sessions are active.
|
|
125
|
+
*/
|
|
126
|
+
export function prefixWithLabel(text, label, sessionCount) {
|
|
127
|
+
if (sessionCount <= 1)
|
|
128
|
+
return text;
|
|
129
|
+
return `[#${label}] ${text}`;
|
|
130
|
+
}
|
|
93
131
|
// --- Private helpers ---
|
|
94
132
|
function formatBudgetLine(label, current, limit, format) {
|
|
95
133
|
const currentStr = format(current);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/signal/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,kDAAkD;AAClD,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/signal/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* - WebSocket connection to signal-cli-rest-api with reconnect + exponential backoff
|
|
6
6
|
* - Message routing: authorization, identity verification, escalation replies,
|
|
7
7
|
* control commands, and session forwarding
|
|
8
|
-
* -
|
|
8
|
+
* - Multi-session lifecycle: creates transport+session on demand, cleans up on end
|
|
9
9
|
* - Identity verification with TTL cache (5 min), fail-closed
|
|
10
|
-
* - Escalation state with race prevention
|
|
10
|
+
* - Escalation state with race prevention (per-session)
|
|
11
11
|
* - Message sending via POST /v2/send with text_mode: "styled"
|
|
12
12
|
*/
|
|
13
13
|
import { type ResolvedSignalConfig } from './signal-config.js';
|
|
@@ -57,23 +57,29 @@ export declare class SignalBotDaemon {
|
|
|
57
57
|
private reconnectAttempts;
|
|
58
58
|
private static readonly MAX_RECONNECT_DELAY_MS;
|
|
59
59
|
private static readonly BASE_RECONNECT_DELAY_MS;
|
|
60
|
-
private
|
|
61
|
-
private
|
|
62
|
-
private
|
|
63
|
-
private
|
|
64
|
-
private escalationResolving;
|
|
60
|
+
private sessions;
|
|
61
|
+
private currentLabel;
|
|
62
|
+
private nextLabel;
|
|
63
|
+
private readonly maxConcurrentSessions;
|
|
65
64
|
private identityLocked;
|
|
66
65
|
private lastIdentityCheckMs;
|
|
67
66
|
private recentTimestamps;
|
|
67
|
+
private sessionOpInProgress;
|
|
68
68
|
private exitResolve;
|
|
69
69
|
constructor(options: SignalBotDaemonOptions);
|
|
70
|
+
/**
|
|
71
|
+
* Schedules a session-mutating operation (/new, /quit) so that
|
|
72
|
+
* concurrent routeToSession() calls wait for it to complete.
|
|
73
|
+
* Operations are chained to prevent interleaving.
|
|
74
|
+
*/
|
|
75
|
+
private scheduleSessionOp;
|
|
70
76
|
/**
|
|
71
77
|
* Starts the daemon. Returns a promise that resolves when
|
|
72
78
|
* shutdown() is called (e.g., SIGTERM/SIGINT).
|
|
73
79
|
*/
|
|
74
80
|
start(): Promise<void>;
|
|
75
81
|
/**
|
|
76
|
-
* Initiates graceful shutdown. Ends
|
|
82
|
+
* Initiates graceful shutdown. Ends all active sessions,
|
|
77
83
|
* closes the WebSocket, and unblocks start().
|
|
78
84
|
*/
|
|
79
85
|
shutdown(): Promise<void>;
|
|
@@ -87,36 +93,54 @@ export declare class SignalBotDaemon {
|
|
|
87
93
|
private scheduleReconnect;
|
|
88
94
|
private handleIncomingMessage;
|
|
89
95
|
/**
|
|
90
|
-
* Routes a user message to the
|
|
96
|
+
* Routes a user message to the current session. Creates a new
|
|
91
97
|
* session if none exists. Handles BudgetExhaustedError by ending
|
|
92
98
|
* the exhausted session and notifying the user.
|
|
99
|
+
*
|
|
100
|
+
* Supports one-shot `#N` prefix routing: `#2 do something` routes
|
|
101
|
+
* "do something" to session #2 without changing currentLabel.
|
|
93
102
|
*/
|
|
94
103
|
private routeToSession;
|
|
104
|
+
/**
|
|
105
|
+
* Forwards a message to a specific managed session. Handles
|
|
106
|
+
* in-flight guards, BudgetExhaustedError, and response formatting.
|
|
107
|
+
*/
|
|
108
|
+
private forwardToSession;
|
|
95
109
|
/**
|
|
96
110
|
* Creates a new session with a fresh SignalSessionTransport.
|
|
97
111
|
* Follows the same pattern as index.ts: create transport,
|
|
98
112
|
* wire callbacks, create session, start transport.
|
|
113
|
+
* Returns the label of the new session.
|
|
99
114
|
*/
|
|
100
115
|
private startNewSession;
|
|
101
116
|
/**
|
|
102
|
-
* Ends
|
|
103
|
-
*
|
|
104
|
-
|
|
117
|
+
* Ends a specific session by label and cleans up.
|
|
118
|
+
* If it was the current session, auto-switches to the most recent remaining.
|
|
119
|
+
*/
|
|
120
|
+
endSession(label: number): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Convenience method: ends the current session (if any).
|
|
105
123
|
*/
|
|
106
124
|
endCurrentSession(): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Auto-switches currentLabel to the highest remaining label (most recent),
|
|
127
|
+
* or null if no sessions remain.
|
|
128
|
+
*/
|
|
129
|
+
private autoSwitchCurrent;
|
|
107
130
|
/**
|
|
108
131
|
* Checks if the message is an escalation reply.
|
|
109
132
|
* Accepts: approve, deny, /approve, /deny (case-insensitive).
|
|
133
|
+
* Optionally with a session label: "approve #2", "/approve 2".
|
|
110
134
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
135
|
+
* Routes to the session with a pending escalation. If multiple
|
|
136
|
+
* sessions have pending escalations and no label is specified,
|
|
137
|
+
* asks for disambiguation.
|
|
114
138
|
*/
|
|
115
139
|
private handleEscalationReply;
|
|
116
140
|
/** Called by SignalSessionTransport when the session surfaces an escalation. */
|
|
117
|
-
setPendingEscalation(escalationId: string): void;
|
|
141
|
+
setPendingEscalation(label: number, escalationId: string): void;
|
|
118
142
|
/** Called by SignalSessionTransport when an escalation expires. */
|
|
119
|
-
clearPendingEscalation(): void;
|
|
143
|
+
clearPendingEscalation(label: number): void;
|
|
120
144
|
private handleControlCommand;
|
|
121
145
|
/**
|
|
122
146
|
* Checks whether the sender's Signal identity key has changed.
|
|
@@ -137,6 +161,17 @@ export declare class SignalBotDaemon {
|
|
|
137
161
|
private postMessage;
|
|
138
162
|
}
|
|
139
163
|
export declare function parseSignalEnvelope(data: string): SignalEnvelope | null;
|
|
140
|
-
/** Normalize a phone number by stripping spaces. */
|
|
141
164
|
export declare function normalizePhoneNumber(number: string): string;
|
|
142
165
|
export declare function isAuthorizedSender(envelope: SignalEnvelope, recipientNumber: string): boolean;
|
|
166
|
+
export interface HashPrefixResult {
|
|
167
|
+
/** The session label from the #N prefix, or null if no prefix was found. */
|
|
168
|
+
targetLabel: number | null;
|
|
169
|
+
/** The message text with the #N prefix stripped (or the original text if no prefix). */
|
|
170
|
+
messageText: string;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Parses an optional `#N` prefix from a message for one-shot session routing.
|
|
174
|
+
* Pattern: `#N ` at the start, where N is one or more digits, followed by a space.
|
|
175
|
+
* E.g., `#2 do something` -> { targetLabel: 2, messageText: 'do something' }
|
|
176
|
+
*/
|
|
177
|
+
export declare function parseHashPrefix(text: string): HashPrefixResult;
|