@coralai/nps-cli 0.1.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.
Files changed (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +459 -0
  3. package/dist/audit-log.d.ts +26 -0
  4. package/dist/audit-log.d.ts.map +1 -0
  5. package/dist/audit-log.js +120 -0
  6. package/dist/audit-log.js.map +1 -0
  7. package/dist/bindings/bindings-loader.d.ts +19 -0
  8. package/dist/bindings/bindings-loader.d.ts.map +1 -0
  9. package/dist/bindings/bindings-loader.js +84 -0
  10. package/dist/bindings/bindings-loader.js.map +1 -0
  11. package/dist/cli/agent-cmd.d.ts +2 -0
  12. package/dist/cli/agent-cmd.d.ts.map +1 -0
  13. package/dist/cli/agent-cmd.js +125 -0
  14. package/dist/cli/agent-cmd.js.map +1 -0
  15. package/dist/cli/bind-cmd.d.ts +2 -0
  16. package/dist/cli/bind-cmd.d.ts.map +1 -0
  17. package/dist/cli/bind-cmd.js +127 -0
  18. package/dist/cli/bind-cmd.js.map +1 -0
  19. package/dist/cli/daemon-cmd.d.ts +4 -0
  20. package/dist/cli/daemon-cmd.d.ts.map +1 -0
  21. package/dist/cli/daemon-cmd.js +137 -0
  22. package/dist/cli/daemon-cmd.js.map +1 -0
  23. package/dist/cli/index.d.ts +2 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +62 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/config/loader.d.ts +5 -0
  28. package/dist/config/loader.d.ts.map +1 -0
  29. package/dist/config/loader.js +54 -0
  30. package/dist/config/loader.js.map +1 -0
  31. package/dist/config/paths.d.ts +14 -0
  32. package/dist/config/paths.d.ts.map +1 -0
  33. package/dist/config/paths.js +27 -0
  34. package/dist/config/paths.js.map +1 -0
  35. package/dist/config/schema.d.ts +48 -0
  36. package/dist/config/schema.d.ts.map +1 -0
  37. package/dist/config/schema.js +52 -0
  38. package/dist/config/schema.js.map +1 -0
  39. package/dist/daemon/control-client.d.ts +2 -0
  40. package/dist/daemon/control-client.d.ts.map +1 -0
  41. package/dist/daemon/control-client.js +51 -0
  42. package/dist/daemon/control-client.js.map +1 -0
  43. package/dist/daemon/control-socket.d.ts +19 -0
  44. package/dist/daemon/control-socket.d.ts.map +1 -0
  45. package/dist/daemon/control-socket.js +192 -0
  46. package/dist/daemon/control-socket.js.map +1 -0
  47. package/dist/daemon/daemon.d.ts +20 -0
  48. package/dist/daemon/daemon.d.ts.map +1 -0
  49. package/dist/daemon/daemon.js +166 -0
  50. package/dist/daemon/daemon.js.map +1 -0
  51. package/dist/dispatch/dispatch-pipeline.d.ts +39 -0
  52. package/dist/dispatch/dispatch-pipeline.d.ts.map +1 -0
  53. package/dist/dispatch/dispatch-pipeline.js +219 -0
  54. package/dist/dispatch/dispatch-pipeline.js.map +1 -0
  55. package/dist/dispatch/slash-commands.d.ts +35 -0
  56. package/dist/dispatch/slash-commands.d.ts.map +1 -0
  57. package/dist/dispatch/slash-commands.js +67 -0
  58. package/dist/dispatch/slash-commands.js.map +1 -0
  59. package/dist/errors.d.ts +22 -0
  60. package/dist/errors.d.ts.map +1 -0
  61. package/dist/errors.js +17 -0
  62. package/dist/errors.js.map +1 -0
  63. package/dist/gateway/matrix-gateway.d.ts +24 -0
  64. package/dist/gateway/matrix-gateway.d.ts.map +1 -0
  65. package/dist/gateway/matrix-gateway.js +166 -0
  66. package/dist/gateway/matrix-gateway.js.map +1 -0
  67. package/dist/logger.d.ts +13 -0
  68. package/dist/logger.d.ts.map +1 -0
  69. package/dist/logger.js +19 -0
  70. package/dist/logger.js.map +1 -0
  71. package/dist/main.d.ts +3 -0
  72. package/dist/main.d.ts.map +1 -0
  73. package/dist/main.js +7 -0
  74. package/dist/main.js.map +1 -0
  75. package/dist/profile/profile-registry.d.ts +24 -0
  76. package/dist/profile/profile-registry.d.ts.map +1 -0
  77. package/dist/profile/profile-registry.js +114 -0
  78. package/dist/profile/profile-registry.js.map +1 -0
  79. package/dist/runtime-check.d.ts +18 -0
  80. package/dist/runtime-check.d.ts.map +1 -0
  81. package/dist/runtime-check.js +62 -0
  82. package/dist/runtime-check.js.map +1 -0
  83. package/dist/session/compat-hash.d.ts +21 -0
  84. package/dist/session/compat-hash.d.ts.map +1 -0
  85. package/dist/session/compat-hash.js +115 -0
  86. package/dist/session/compat-hash.js.map +1 -0
  87. package/dist/session/session-store.d.ts +29 -0
  88. package/dist/session/session-store.d.ts.map +1 -0
  89. package/dist/session/session-store.js +123 -0
  90. package/dist/session/session-store.js.map +1 -0
  91. package/dist/version.d.ts +2 -0
  92. package/dist/version.d.ts.map +1 -0
  93. package/dist/version.js +2 -0
  94. package/dist/version.js.map +1 -0
  95. package/package.json +59 -0
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Daemon — wires all the modules together. Entrypoint for `nps daemon start`.
3
+ */
4
+ import { mkdirSync, existsSync } from 'node:fs';
5
+ import { getLogger } from '../logger.js';
6
+ import { PATHS } from '../config/paths.js';
7
+ import { loadGlobalConfig } from '../config/loader.js';
8
+ import { assertRuntime } from '../runtime-check.js';
9
+ import { AuditLog } from '../audit-log.js';
10
+ import { ProfileRegistry } from '../profile/profile-registry.js';
11
+ import { BindingsLoader } from '../bindings/bindings-loader.js';
12
+ import { SessionStore } from '../session/session-store.js';
13
+ import { ControlSocket } from './control-socket.js';
14
+ import { DispatchPipeline } from '../dispatch/dispatch-pipeline.js';
15
+ import { MatrixGateway } from '../gateway/matrix-gateway.js';
16
+ import { cacheRuntimeVersions } from '../session/compat-hash.js';
17
+ import { NPS_VERSION } from '../version.js';
18
+ import { readFileSync } from 'node:fs';
19
+ import { join } from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+ import { dirname } from 'node:path';
22
+ let activeDaemon;
23
+ function readAgentPkgVersion() {
24
+ // Locate node_modules relative to this file when bundled.
25
+ try {
26
+ const here = dirname(fileURLToPath(import.meta.url));
27
+ // dist/daemon/daemon.js → up to nps-cli root → node_modules/@coralai/claude-code-agent/package.json
28
+ for (const up of ['../..', '../../..', '../../../..']) {
29
+ const candidate = join(here, up, 'node_modules', '@coralai', 'claude-code-agent', 'package.json');
30
+ if (existsSync(candidate)) {
31
+ return JSON.parse(readFileSync(candidate, 'utf8')).version;
32
+ }
33
+ }
34
+ }
35
+ catch { /* fall through */ }
36
+ return 'unknown';
37
+ }
38
+ export async function startDaemon() {
39
+ if (activeDaemon) {
40
+ throw new Error('daemon already running in this process');
41
+ }
42
+ const logger = getLogger('daemon');
43
+ // 1. ensure ~/.nps/ exists
44
+ mkdirSync(PATHS.home, { recursive: true });
45
+ mkdirSync(PATHS.stateDir, { recursive: true });
46
+ mkdirSync(PATHS.agentsDir, { recursive: true });
47
+ // 2. boot runtime check
48
+ assertRuntime(logger);
49
+ // 3. load global config
50
+ if (!existsSync(PATHS.configFile)) {
51
+ throw new Error(`config not found at ${PATHS.configFile}. Run \`nps daemon init\` or create it manually.`);
52
+ }
53
+ const config = loadGlobalConfig(PATHS.configFile);
54
+ // 4. audit log
55
+ const audit = new AuditLog(PATHS.auditFile);
56
+ // 5. registries
57
+ const registry = new ProfileRegistry(PATHS.agentsDir);
58
+ await registry.start();
59
+ const bindings = new BindingsLoader(PATHS.bindingsFile);
60
+ await bindings.start();
61
+ const sessions = new SessionStore(PATHS.stateDir);
62
+ // 6. runtime version cache (for compatHash stability across a daemon run)
63
+ const runtimeVersions = cacheRuntimeVersions();
64
+ const agentPkgVersion = readAgentPkgVersion();
65
+ logger.info({ ...runtimeVersions, agentPkgVersion }, 'cached runtime versions for compatHash');
66
+ // 7. pipeline
67
+ const adminSet = new Set(config.daemon.adminUserIds);
68
+ const pipeline = new DispatchPipeline({
69
+ registry,
70
+ bindings,
71
+ sessions,
72
+ audit,
73
+ adminUserIds: adminSet,
74
+ runtime: { ...runtimeVersions, agentPkgVersion },
75
+ });
76
+ // 8. control socket + RPC methods
77
+ const controlSocket = new ControlSocket(PATHS.daemonSocket, PATHS.daemonPid);
78
+ controlSocket.register('health', async () => ({
79
+ status: 'ok',
80
+ pid: process.pid,
81
+ uptimeSec: Math.round((Date.now() - state.startedAt) / 1000),
82
+ profileCount: registry.list().length,
83
+ bindingCount: Object.keys(bindings.snapshot().matrix).length,
84
+ npsVersion: NPS_VERSION,
85
+ matrixConnected: !!state.matrix,
86
+ }));
87
+ controlSocket.register('stop', async () => {
88
+ // schedule shutdown on next tick so we can ack first
89
+ setTimeout(() => { void stopDaemon().then(() => process.exit(0)); }, 50);
90
+ return { ack: true };
91
+ });
92
+ controlSocket.register('bindings.list', async () => bindings.snapshot());
93
+ controlSocket.register('profile.list', async () => registry.list().map(p => ({ name: p.name, workspace: p.config.workspace })));
94
+ controlSocket.register('version', async () => ({
95
+ nps: NPS_VERSION,
96
+ agentPkg: agentPkgVersion,
97
+ claude: runtimeVersions.claudeVersion,
98
+ shim: runtimeVersions.shimVersion,
99
+ }));
100
+ await controlSocket.start();
101
+ const state = {
102
+ logger,
103
+ audit,
104
+ registry,
105
+ bindings,
106
+ sessions,
107
+ controlSocket,
108
+ startedAt: Date.now(),
109
+ };
110
+ // 9. Matrix gateway (if configured)
111
+ if (config.im.matrix) {
112
+ const matrix = new MatrixGateway({
113
+ homeserver: config.im.matrix.homeserver,
114
+ userId: config.im.matrix.user,
115
+ accessToken: config.im.matrix.accessToken,
116
+ }, pipeline);
117
+ await matrix.start();
118
+ state.matrix = matrix;
119
+ }
120
+ else {
121
+ logger.warn('no matrix config in ~/.nps/config.yaml — daemon running but no IM transport active');
122
+ }
123
+ activeDaemon = state;
124
+ process.on('SIGINT', () => { void stopDaemon().then(() => process.exit(0)); });
125
+ process.on('SIGTERM', () => { void stopDaemon().then(() => process.exit(0)); });
126
+ logger.info({ version: NPS_VERSION, pid: process.pid }, 'nps daemon started');
127
+ return state;
128
+ }
129
+ export async function stopDaemon() {
130
+ if (!activeDaemon)
131
+ return;
132
+ const s = activeDaemon;
133
+ activeDaemon = undefined;
134
+ try {
135
+ await s.matrix?.stop();
136
+ }
137
+ catch (e) {
138
+ s.logger.warn({ err: e instanceof Error ? e.message : e }, 'matrix stop');
139
+ }
140
+ try {
141
+ await s.bindings.stop();
142
+ }
143
+ catch (e) {
144
+ s.logger.warn({ err: e instanceof Error ? e.message : e }, 'bindings stop');
145
+ }
146
+ try {
147
+ await s.registry.stop();
148
+ }
149
+ catch (e) {
150
+ s.logger.warn({ err: e instanceof Error ? e.message : e }, 'registry stop');
151
+ }
152
+ try {
153
+ await s.controlSocket.stop();
154
+ }
155
+ catch (e) {
156
+ s.logger.warn({ err: e instanceof Error ? e.message : e }, 'control socket stop');
157
+ }
158
+ try {
159
+ s.audit.close();
160
+ }
161
+ catch (e) {
162
+ s.logger.warn({ err: e instanceof Error ? e.message : e }, 'audit close');
163
+ }
164
+ s.logger.info('nps daemon stopped cleanly');
165
+ }
166
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/daemon/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { Logger } from 'pino';
2
+ import type { SessionStore } from '../session/session-store.js';
3
+ import type { ProfileRegistry } from '../profile/profile-registry.js';
4
+ import type { BindingsLoader } from '../bindings/bindings-loader.js';
5
+ import type { AuditLog } from '../audit-log.js';
6
+ export interface IncomingMessage {
7
+ channelId: string;
8
+ eventId: string;
9
+ text: string;
10
+ sender: string;
11
+ transport: 'matrix';
12
+ }
13
+ export interface ReplyTarget {
14
+ /** Called BEFORE start() (long latency) so user sees a typing indicator. */
15
+ startTyping?: () => Promise<void>;
16
+ /** Called when stop() finishes (or on error). */
17
+ stopTyping?: () => Promise<void>;
18
+ /** Final reply text. */
19
+ send: (text: string) => Promise<void>;
20
+ }
21
+ export interface PipelineDeps {
22
+ registry: ProfileRegistry;
23
+ bindings: BindingsLoader;
24
+ sessions: SessionStore;
25
+ audit?: AuditLog;
26
+ adminUserIds: ReadonlySet<string>;
27
+ runtime: {
28
+ claudeVersion: string;
29
+ shimVersion: string;
30
+ agentPkgVersion: string;
31
+ };
32
+ }
33
+ export declare class DispatchPipeline {
34
+ private readonly deps;
35
+ private logger;
36
+ constructor(deps: PipelineDeps, logger?: Logger);
37
+ dispatch(msg: IncomingMessage, reply: ReplyTarget): Promise<void>;
38
+ }
39
+ //# sourceMappingURL=dispatch-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch-pipeline.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatch-pipeline.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,wBAAwB;IACxB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;CAClF;AAED,qBAAa,gBAAgB;IAEf,OAAO,CAAC,QAAQ,CAAC,IAAI;IADjC,OAAO,CAAC,MAAM,CAAS;gBACM,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM;IAI1D,QAAQ,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CA6LxE"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * M4 — DispatchPipeline.
3
+ *
4
+ * Per CEO plan rev 5 §6.2 corrected order:
5
+ *
6
+ * 1. event-id dedupe → silent drop on duplicate
7
+ * 2. binding lookup → /help reply on miss
8
+ * 3. compute currentCompatHash
9
+ * 4. compat check BEFORE resume ← codex F1: not after
10
+ * 5. spawn ClaudeCodeAgent (cwd=profile, env, permissionMode)
11
+ * 6. agent.start({ resumeSession }) (or fresh if hash mismatch / no stored)
12
+ * 7. agent.prompt(text)
13
+ * 8. persist sessionId + compatHash + lastEventId BEFORE send ← codex F11
14
+ * 9. agent.stop()
15
+ * 10. gateway.sendReply()
16
+ */
17
+ import { ClaudeCodeAgent, isAgentError } from '@coralai/claude-code-agent';
18
+ import { getLogger } from '../logger.js';
19
+ import { computeCompatHash } from '../session/compat-hash.js';
20
+ import { isSlashCommand, handleSlash, defaultHelpText } from './slash-commands.js';
21
+ export class DispatchPipeline {
22
+ deps;
23
+ logger;
24
+ constructor(deps, logger) {
25
+ this.deps = deps;
26
+ this.logger = logger ?? getLogger('dispatch');
27
+ }
28
+ async dispatch(msg, reply) {
29
+ // 1. event-id dedupe
30
+ if (this.deps.sessions.hasSeenEvent(msg.channelId, msg.eventId)) {
31
+ this.logger.debug({ eventId: msg.eventId }, 'duplicate event — silent drop');
32
+ this.deps.audit?.append({
33
+ sender: msg.sender,
34
+ transport: msg.transport,
35
+ channel: msg.channelId,
36
+ command_or_event: 'message',
37
+ decision: 'dropped',
38
+ detail: 'duplicate event id',
39
+ });
40
+ return;
41
+ }
42
+ // Slash command path: short-circuit before agent dispatch
43
+ const binding = this.deps.bindings.lookupMatrix(msg.channelId);
44
+ if (isSlashCommand(msg.text)) {
45
+ const ctx = {
46
+ channelId: msg.channelId,
47
+ sender: msg.sender,
48
+ transport: msg.transport,
49
+ adminUserIds: this.deps.adminUserIds,
50
+ ...(binding ? { binding: { profile: binding } } : {}),
51
+ };
52
+ const handlers = {
53
+ help: async (c) => {
54
+ const stored = this.deps.sessions.get(c.channelId);
55
+ if (binding) {
56
+ return `Bound to profile: ${binding}\nSession active: ${stored ? 'yes' : 'no'}\n\n${defaultHelpText(true)}`;
57
+ }
58
+ return defaultHelpText(c.adminUserIds.has(c.sender));
59
+ },
60
+ status: async (c) => {
61
+ const stored = this.deps.sessions.get(c.channelId);
62
+ if (!binding)
63
+ return 'status: unbound. Run `nps bind add` on the host.';
64
+ return [
65
+ `status: bound to '${binding}'`,
66
+ `session: ${stored ? `present (id ${stored.sessionId.slice(0, 8)}...)` : 'fresh'}`,
67
+ `lastSeen: ${stored?.lastSeenAt ?? '—'}`,
68
+ ].join('\n');
69
+ },
70
+ };
71
+ const result = await handleSlash(msg.text, ctx, handlers, this.deps.audit);
72
+ if (result.text)
73
+ await reply.send(result.text);
74
+ return;
75
+ }
76
+ // 2. binding lookup
77
+ if (!binding) {
78
+ this.deps.audit?.append({
79
+ sender: msg.sender,
80
+ transport: msg.transport,
81
+ channel: msg.channelId,
82
+ command_or_event: 'message',
83
+ decision: 'dropped',
84
+ detail: 'no binding',
85
+ });
86
+ await reply.send(defaultHelpText(this.deps.adminUserIds.has(msg.sender)));
87
+ return;
88
+ }
89
+ // Sender auth check (single-user v0.1 — non-admin messages refused)
90
+ if (!this.deps.adminUserIds.has(msg.sender)) {
91
+ this.deps.audit?.append({
92
+ sender: msg.sender,
93
+ transport: msg.transport,
94
+ channel: msg.channelId,
95
+ command_or_event: 'message',
96
+ decision: 'denied',
97
+ detail: 'non-admin sender',
98
+ });
99
+ await reply.send('denied: nps v0.1 is single-user; only the daemon admin may chat.');
100
+ return;
101
+ }
102
+ const profile = this.deps.registry.get(binding);
103
+ if (!profile) {
104
+ this.logger.error({ profile: binding, channelId: msg.channelId }, 'binding points to unknown profile');
105
+ this.deps.audit?.append({
106
+ sender: msg.sender,
107
+ transport: msg.transport,
108
+ channel: msg.channelId,
109
+ command_or_event: 'message',
110
+ decision: 'error',
111
+ detail: `unknown profile '${binding}'`,
112
+ });
113
+ await reply.send(`error: profile '${binding}' not found. Check \`nps agent list\` on the host.`);
114
+ return;
115
+ }
116
+ // 3. compute currentCompatHash
117
+ let currentHash;
118
+ try {
119
+ currentHash = computeCompatHash({
120
+ profileDir: profile.dir,
121
+ claudeVersion: this.deps.runtime.claudeVersion,
122
+ shimVersion: this.deps.runtime.shimVersion,
123
+ agentPkgVersion: this.deps.runtime.agentPkgVersion,
124
+ });
125
+ }
126
+ catch (e) {
127
+ this.logger.error({ err: e instanceof Error ? e.message : e, profile: binding }, 'compatHash compute failed');
128
+ await reply.send('error: failed to verify session integrity. Run `nps daemon status` for details.');
129
+ return;
130
+ }
131
+ // 4. compat check BEFORE resume (codex F1)
132
+ const stored = this.deps.sessions.get(msg.channelId);
133
+ let resumeId;
134
+ let resumedHint = false;
135
+ if (stored && stored.compatHash === currentHash && stored.profile === binding) {
136
+ resumeId = stored.sessionId;
137
+ }
138
+ else if (stored) {
139
+ // Hash mismatch — drop stale session
140
+ resumedHint = true;
141
+ this.logger.info({ channelId: msg.channelId, oldHash: stored.compatHash.slice(0, 8), newHash: currentHash.slice(0, 8) }, 'compatHash mismatch — fresh start');
142
+ this.deps.sessions.delete(msg.channelId);
143
+ }
144
+ // 5-6. Spawn + start
145
+ await reply.startTyping?.();
146
+ const agent = new ClaudeCodeAgent({
147
+ cwd: profile.dir,
148
+ env: profile.config.env,
149
+ permissionMode: profile.config.permissionMode,
150
+ ...(profile.config.recording ? { recording: profile.config.recording } : {}),
151
+ });
152
+ let resultText;
153
+ let newSessionId;
154
+ try {
155
+ await agent.start(resumeId ? { resumeSession: resumeId } : {});
156
+ // Augment user text with workspace pointer (M-WS strategy: workspace in prompt)
157
+ const promptText = profile.config.workspace
158
+ ? `[Your task workspace is at: ${profile.config.workspace}]\n\n${msg.text}`
159
+ : msg.text;
160
+ const handle = agent.prompt(promptText);
161
+ const result = await handle.result;
162
+ resultText = result.text;
163
+ newSessionId = agent.sessionId ?? '';
164
+ }
165
+ catch (e) {
166
+ try {
167
+ await agent.stop();
168
+ }
169
+ catch { /* ignore */ }
170
+ await reply.stopTyping?.();
171
+ const msgText = e instanceof Error ? e.message : String(e);
172
+ this.logger.error({ err: msgText, channelId: msg.channelId }, 'agent dispatch failed');
173
+ this.deps.audit?.append({
174
+ sender: msg.sender,
175
+ transport: msg.transport,
176
+ channel: msg.channelId,
177
+ command_or_event: 'message',
178
+ decision: 'error',
179
+ detail: isAgentError(e) ? e.code : 'agent error',
180
+ });
181
+ await reply.send(`error: agent failed (${isAgentError(e) ? e.code : 'unknown'}). Check daemon logs.`);
182
+ return;
183
+ }
184
+ // 8. persist BEFORE send (codex F11)
185
+ try {
186
+ this.deps.sessions.put(msg.channelId, {
187
+ sessionId: newSessionId,
188
+ compatHash: currentHash,
189
+ profile: binding,
190
+ lastEventId: msg.eventId,
191
+ });
192
+ }
193
+ catch (e) {
194
+ this.logger.error({ err: e instanceof Error ? e.message : e }, 'session persist failed — message handled but state may be lost on restart');
195
+ }
196
+ // 9. stop
197
+ try {
198
+ await agent.stop();
199
+ }
200
+ catch (e) {
201
+ this.logger.warn({ err: e instanceof Error ? e.message : e }, 'agent.stop failed (best-effort)');
202
+ }
203
+ await reply.stopTyping?.();
204
+ // 10. send reply
205
+ const finalText = resumedHint
206
+ ? `[session reset: profile or skills changed since last turn]\n\n${resultText}`
207
+ : resultText;
208
+ await reply.send(finalText);
209
+ this.deps.audit?.append({
210
+ sender: msg.sender,
211
+ transport: msg.transport,
212
+ channel: msg.channelId,
213
+ command_or_event: 'message',
214
+ decision: 'accepted',
215
+ profile: binding,
216
+ });
217
+ }
218
+ }
219
+ //# sourceMappingURL=dispatch-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch-pipeline.js","sourceRoot":"","sources":["../../src/dispatch/dispatch-pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * M8 — slash command parser + dispatcher.
3
+ *
4
+ * v0.1 minimal contract per CEO plan rev 5 D6=A:
5
+ * /help — open to any sender (DM-friendly; lets a new admin discover the bot)
6
+ * /status — admin only
7
+ * /unknown → reply with /help (open)
8
+ * denied → audit-logged + reply "denied"
9
+ *
10
+ * The actual binding mgmt (/bind /unbind /reset /persona) is CLI-only in v0.1.
11
+ */
12
+ import type { AuditLog } from '../audit-log.js';
13
+ export interface SlashContext {
14
+ channelId: string;
15
+ sender: string;
16
+ transport: 'matrix';
17
+ adminUserIds: ReadonlySet<string>;
18
+ binding?: {
19
+ profile: string;
20
+ lastEventId?: string;
21
+ };
22
+ }
23
+ export interface SlashResult {
24
+ /** If true: gateway should reply with `text` and skip agent dispatch. */
25
+ handled: boolean;
26
+ text?: string;
27
+ }
28
+ export interface SlashHandlers {
29
+ status: (ctx: SlashContext) => Promise<string>;
30
+ help: (ctx: SlashContext) => Promise<string>;
31
+ }
32
+ export declare function isSlashCommand(text: string): boolean;
33
+ export declare function handleSlash(text: string, ctx: SlashContext, handlers: SlashHandlers, audit?: AuditLog): Promise<SlashResult>;
34
+ export declare function defaultHelpText(adminMode: boolean): string;
35
+ //# sourceMappingURL=slash-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../src/dispatch/slash-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,CAAC;IACpB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,YAAY,EACjB,QAAQ,EAAE,aAAa,EACvB,KAAK,CAAC,EAAE,QAAQ,GACf,OAAO,CAAC,WAAW,CAAC,CAmDtB;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAU1D"}
@@ -0,0 +1,67 @@
1
+ export function isSlashCommand(text) {
2
+ return text.startsWith('/');
3
+ }
4
+ export async function handleSlash(text, ctx, handlers, audit) {
5
+ const trimmed = text.trim();
6
+ const [cmd] = trimmed.split(/\s+/);
7
+ switch (cmd) {
8
+ case '/help': {
9
+ // Open to any sender — codex F12 fix
10
+ const reply = await handlers.help(ctx);
11
+ audit?.append({
12
+ sender: ctx.sender,
13
+ transport: ctx.transport,
14
+ channel: ctx.channelId,
15
+ command_or_event: '/help',
16
+ decision: 'accepted',
17
+ });
18
+ return { handled: true, text: reply };
19
+ }
20
+ case '/status': {
21
+ if (!ctx.adminUserIds.has(ctx.sender)) {
22
+ audit?.append({
23
+ sender: ctx.sender,
24
+ transport: ctx.transport,
25
+ channel: ctx.channelId,
26
+ command_or_event: '/status',
27
+ decision: 'denied',
28
+ });
29
+ return { handled: true, text: 'denied: /status requires admin privileges' };
30
+ }
31
+ const reply = await handlers.status(ctx);
32
+ audit?.append({
33
+ sender: ctx.sender,
34
+ transport: ctx.transport,
35
+ channel: ctx.channelId,
36
+ command_or_event: '/status',
37
+ decision: 'accepted',
38
+ });
39
+ return { handled: true, text: reply };
40
+ }
41
+ default: {
42
+ audit?.append({
43
+ sender: ctx.sender,
44
+ transport: ctx.transport,
45
+ channel: ctx.channelId,
46
+ command_or_event: cmd ?? '/(empty)',
47
+ decision: 'dropped',
48
+ detail: 'unknown command',
49
+ });
50
+ // Show help to anyone — open
51
+ const reply = await handlers.help(ctx);
52
+ return { handled: true, text: `Unknown command: ${cmd ?? '?'}\n\n${reply}` };
53
+ }
54
+ }
55
+ }
56
+ export function defaultHelpText(adminMode) {
57
+ const base = [
58
+ 'nps DM commands:',
59
+ ' /help show this message (open)',
60
+ ' /status show current binding (admin only)',
61
+ ].join('\n');
62
+ if (adminMode) {
63
+ return base + '\n\nManage bindings via host CLI:\n nps bind add <channel-id> <profile>\n nps bind list';
64
+ }
65
+ return base + '\n\nDM is not yet bound. The admin must run `nps bind add` on the host.';
66
+ }
67
+ //# sourceMappingURL=slash-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../src/dispatch/slash-commands.ts"],"names":[],"mappings":"AAgCA,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,GAAiB,EACjB,QAAuB,EACvB,KAAgB;IAEhB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnC,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,qCAAqC;YACrC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,KAAK,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,OAAO,EAAE,GAAG,CAAC,SAAS;gBACtB,gBAAgB,EAAE,OAAO;gBACzB,QAAQ,EAAE,UAAU;aACrB,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACxC,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtC,KAAK,EAAE,MAAM,CAAC;oBACZ,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,SAAS,EAAE,GAAG,CAAC,SAAS;oBACxB,OAAO,EAAE,GAAG,CAAC,SAAS;oBACtB,gBAAgB,EAAE,SAAS;oBAC3B,QAAQ,EAAE,QAAQ;iBACnB,CAAC,CAAC;gBACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,2CAA2C,EAAE,CAAC;YAC9E,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzC,KAAK,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,OAAO,EAAE,GAAG,CAAC,SAAS;gBACtB,gBAAgB,EAAE,SAAS;gBAC3B,QAAQ,EAAE,UAAU;aACrB,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACxC,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,KAAK,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,OAAO,EAAE,GAAG,CAAC,SAAS;gBACtB,gBAAgB,EAAE,GAAG,IAAI,UAAU;gBACnC,QAAQ,EAAE,SAAS;gBACnB,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;YACH,6BAA6B;YAC7B,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,oBAAoB,GAAG,IAAI,GAAG,OAAO,KAAK,EAAE,EAAE,CAAC;QAC/E,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAAkB;IAChD,MAAM,IAAI,GAAG;QACX,kBAAkB;QAClB,sCAAsC;QACtC,+CAA+C;KAChD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,IAAI,GAAG,2FAA2F,CAAC;IAC5G,CAAC;IACD,OAAO,IAAI,GAAG,yEAAyE,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * NpsError — typed errors for nps-cli operations.
3
+ *
4
+ * Codes are grouped by concern:
5
+ * - Profile / workspace: PROFILE_NOT_FOUND, WORKSPACE_INVALID, NPS_YAML_INVALID
6
+ * - Bindings: BINDING_NOT_FOUND, BINDING_WRITE_FAILED
7
+ * - Session: COMPAT_HASH_MISMATCH, SESSION_STORE_CORRUPT
8
+ * - Gateway: GATEWAY_AUTH_FAILED, ROOM_ENCRYPTED, ROOM_NOT_DM
9
+ * - Runtime: CLAUDE_BIN_MISSING, ACP_SHIM_MISSING, SHIM_UNHEALTHY
10
+ * - Daemon: SOCKET_BUSY, DAEMON_ALREADY_RUNNING, STALE_SOCKET
11
+ */
12
+ export type NpsErrorCode = 'PROFILE_NOT_FOUND' | 'WORKSPACE_INVALID' | 'NPS_YAML_INVALID' | 'BINDING_NOT_FOUND' | 'BINDING_WRITE_FAILED' | 'COMPAT_HASH_MISMATCH' | 'COMPAT_HASH_FAILED' | 'SESSION_STORE_CORRUPT' | 'GATEWAY_AUTH_FAILED' | 'ROOM_ENCRYPTED' | 'ROOM_NOT_DM' | 'CLAUDE_BIN_MISSING' | 'ACP_SHIM_MISSING' | 'SHIM_UNHEALTHY' | 'SOCKET_BUSY' | 'DAEMON_ALREADY_RUNNING' | 'STALE_SOCKET' | 'UNAUTHORIZED' | 'EVENT_DUPLICATE';
13
+ export declare class NpsError extends Error {
14
+ readonly code: NpsErrorCode;
15
+ readonly context?: Record<string, unknown>;
16
+ constructor(code: NpsErrorCode, message: string, opts?: {
17
+ cause?: Error;
18
+ context?: Record<string, unknown>;
19
+ });
20
+ }
21
+ export declare function isNpsError(e: unknown): e is NpsError;
22
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY,GACpB,mBAAmB,GACnB,mBAAmB,GACnB,kBAAkB,GAClB,mBAAmB,GACnB,sBAAsB,GACtB,sBAAsB,GACtB,oBAAoB,GACpB,uBAAuB,GACvB,qBAAqB,GACrB,gBAAgB,GAChB,aAAa,GACb,oBAAoB,GACpB,kBAAkB,GAClB,gBAAgB,GAChB,aAAa,GACb,wBAAwB,GACxB,cAAc,GACd,cAAc,GACd,iBAAiB,CAAC;AAEtB,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGzC,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,KAAK,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;CAQ9D;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,QAAQ,CAEpD"}
package/dist/errors.js ADDED
@@ -0,0 +1,17 @@
1
+ export class NpsError extends Error {
2
+ code;
3
+ context;
4
+ constructor(code, message, opts) {
5
+ super(message);
6
+ this.name = 'NpsError';
7
+ this.code = code;
8
+ if (opts?.cause !== undefined)
9
+ this.cause = opts.cause;
10
+ if (opts?.context !== undefined)
11
+ this.context = opts.context;
12
+ }
13
+ }
14
+ export function isNpsError(e) {
15
+ return e instanceof NpsError;
16
+ }
17
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAgCA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAe;IACnB,OAAO,CAA2B;IAE3C,YACE,IAAkB,EAClB,OAAe,EACf,IAA2D;QAE3D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,IAAI,EAAE,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACvD,IAAI,IAAI,EAAE,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC/D,CAAC;CACF;AAED,MAAM,UAAU,UAAU,CAAC,CAAU;IACnC,OAAO,CAAC,YAAY,QAAQ,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { Logger } from 'pino';
2
+ import type { DispatchPipeline } from '../dispatch/dispatch-pipeline.js';
3
+ export interface MatrixGatewayConfig {
4
+ homeserver: string;
5
+ userId: string;
6
+ accessToken: string;
7
+ /** Type indicator timeout (ms) shown while agent runs. matrix-js-sdk default is OK. */
8
+ typingTimeoutMs?: number;
9
+ }
10
+ export declare class MatrixGateway {
11
+ private readonly config;
12
+ private readonly pipeline;
13
+ private logger;
14
+ private client;
15
+ private dispatching;
16
+ private stopRequested;
17
+ constructor(config: MatrixGatewayConfig, pipeline: DispatchPipeline, logger?: Logger);
18
+ start(): Promise<void>;
19
+ stop(): Promise<void>;
20
+ private onTimeline;
21
+ private handleMessage;
22
+ private makeReplyTarget;
23
+ }
24
+ //# sourceMappingURL=matrix-gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix-gateway.d.ts","sourceRoot":"","sources":["../../src/gateway/matrix-gateway.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,gBAAgB,EAAgC,MAAM,kCAAkC,CAAC;AAEvG,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,aAAa;IAOtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAP3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAS;gBAGX,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,EAAE,gBAAgB,EAC3C,MAAM,CAAC,EAAE,MAAM;IAKX,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,OAAO,CAAC,UAAU;YAcJ,aAAa;IAuD3B,OAAO,CAAC,eAAe;CAsBxB"}