@ekkos/cli 1.3.2 → 1.3.6

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 (123) hide show
  1. package/dist/capture/jsonl-rewriter.d.ts +1 -1
  2. package/dist/capture/jsonl-rewriter.js +3 -3
  3. package/dist/capture/transcript-repair.d.ts +2 -2
  4. package/dist/capture/transcript-repair.js +2 -2
  5. package/dist/commands/claw.d.ts +13 -0
  6. package/dist/commands/claw.js +253 -0
  7. package/dist/commands/dashboard.js +617 -83
  8. package/dist/commands/doctor.d.ts +3 -3
  9. package/dist/commands/doctor.js +6 -79
  10. package/dist/commands/gemini.d.ts +19 -0
  11. package/dist/commands/gemini.js +193 -0
  12. package/dist/commands/init.js +2 -25
  13. package/dist/commands/run.d.ts +0 -1
  14. package/dist/commands/run.js +147 -241
  15. package/dist/commands/scan.d.ts +21 -0
  16. package/dist/commands/scan.js +386 -0
  17. package/dist/commands/swarm-dashboard.js +156 -28
  18. package/dist/commands/swarm.d.ts +1 -1
  19. package/dist/commands/swarm.js +1 -1
  20. package/dist/commands/test-claude.d.ts +2 -2
  21. package/dist/commands/test-claude.js +3 -3
  22. package/dist/deploy/index.d.ts +0 -2
  23. package/dist/deploy/index.js +0 -2
  24. package/dist/deploy/settings.d.ts +2 -2
  25. package/dist/deploy/settings.js +42 -4
  26. package/dist/deploy/skills.js +1 -2
  27. package/dist/index.js +79 -19
  28. package/dist/lib/usage-parser.js +5 -4
  29. package/dist/utils/proxy-url.d.ts +12 -1
  30. package/dist/utils/proxy-url.js +16 -1
  31. package/dist/utils/templates.js +1 -1
  32. package/package.json +4 -6
  33. package/templates/CLAUDE.md +49 -107
  34. package/dist/agent/daemon.d.ts +0 -130
  35. package/dist/agent/daemon.js +0 -606
  36. package/dist/agent/health-check.d.ts +0 -35
  37. package/dist/agent/health-check.js +0 -243
  38. package/dist/agent/pty-runner.d.ts +0 -53
  39. package/dist/agent/pty-runner.js +0 -190
  40. package/dist/commands/agent.d.ts +0 -50
  41. package/dist/commands/agent.js +0 -544
  42. package/dist/commands/setup-remote.d.ts +0 -20
  43. package/dist/commands/setup-remote.js +0 -582
  44. package/dist/commands/synk.d.ts +0 -7
  45. package/dist/commands/synk.js +0 -339
  46. package/dist/cron/index.d.ts +0 -7
  47. package/dist/cron/index.js +0 -13
  48. package/dist/cron/promoter.d.ts +0 -70
  49. package/dist/cron/promoter.js +0 -403
  50. package/dist/synk/api.d.ts +0 -22
  51. package/dist/synk/api.js +0 -133
  52. package/dist/synk/auth.d.ts +0 -7
  53. package/dist/synk/auth.js +0 -30
  54. package/dist/synk/config.d.ts +0 -18
  55. package/dist/synk/config.js +0 -37
  56. package/dist/synk/daemon/control-client.d.ts +0 -11
  57. package/dist/synk/daemon/control-client.js +0 -101
  58. package/dist/synk/daemon/control-server.d.ts +0 -24
  59. package/dist/synk/daemon/control-server.js +0 -91
  60. package/dist/synk/daemon/run.d.ts +0 -14
  61. package/dist/synk/daemon/run.js +0 -338
  62. package/dist/synk/encryption.d.ts +0 -17
  63. package/dist/synk/encryption.js +0 -133
  64. package/dist/synk/index.d.ts +0 -13
  65. package/dist/synk/index.js +0 -36
  66. package/dist/synk/machine-client.d.ts +0 -42
  67. package/dist/synk/machine-client.js +0 -218
  68. package/dist/synk/persistence.d.ts +0 -51
  69. package/dist/synk/persistence.js +0 -211
  70. package/dist/synk/qr.d.ts +0 -5
  71. package/dist/synk/qr.js +0 -33
  72. package/dist/synk/session-bridge.d.ts +0 -58
  73. package/dist/synk/session-bridge.js +0 -171
  74. package/dist/synk/session-client.d.ts +0 -46
  75. package/dist/synk/session-client.js +0 -240
  76. package/dist/synk/types.d.ts +0 -574
  77. package/dist/synk/types.js +0 -74
  78. package/dist/utils/verify-remote-terminal.d.ts +0 -10
  79. package/dist/utils/verify-remote-terminal.js +0 -415
  80. package/templates/README.md +0 -378
  81. package/templates/claude-plugins/PHASE2_COMPLETION.md +0 -346
  82. package/templates/claude-plugins/PLUGIN_PROPOSALS.md +0 -1776
  83. package/templates/claude-plugins/README.md +0 -587
  84. package/templates/claude-plugins/agents/code-reviewer.json +0 -14
  85. package/templates/claude-plugins/agents/debug-detective.json +0 -15
  86. package/templates/claude-plugins/agents/git-companion.json +0 -14
  87. package/templates/claude-plugins/blog-manager/.claude-plugin/plugin.json +0 -8
  88. package/templates/claude-plugins/blog-manager/commands/blog.md +0 -691
  89. package/templates/claude-plugins/golden-loop-monitor/.claude-plugin/plugin.json +0 -8
  90. package/templates/claude-plugins/golden-loop-monitor/commands/loop-status.md +0 -434
  91. package/templates/claude-plugins/learning-tracker/.claude-plugin/plugin.json +0 -8
  92. package/templates/claude-plugins/learning-tracker/commands/my-patterns.md +0 -282
  93. package/templates/claude-plugins/memory-lens/.claude-plugin/plugin.json +0 -8
  94. package/templates/claude-plugins/memory-lens/commands/memory-search.md +0 -181
  95. package/templates/claude-plugins/pattern-coach/.claude-plugin/plugin.json +0 -8
  96. package/templates/claude-plugins/pattern-coach/commands/forge.md +0 -365
  97. package/templates/claude-plugins/project-schema-validator/.claude-plugin/plugin.json +0 -8
  98. package/templates/claude-plugins/project-schema-validator/commands/validate-schema.md +0 -582
  99. package/templates/commands/continue.md +0 -47
  100. package/templates/cursor-rules/ekkos-memory.md +0 -127
  101. package/templates/ekkos-manifest.json +0 -223
  102. package/templates/helpers/json-parse.cjs +0 -101
  103. package/templates/plan-template.md +0 -306
  104. package/templates/shared/hooks-enabled.json +0 -22
  105. package/templates/shared/session-words.json +0 -45
  106. package/templates/skills/ekkOS_Deep_Recall/Skill.md +0 -282
  107. package/templates/skills/ekkOS_Learn/Skill.md +0 -265
  108. package/templates/skills/ekkOS_Memory_First/Skill.md +0 -206
  109. package/templates/skills/ekkOS_Plan_Assist/Skill.md +0 -302
  110. package/templates/skills/ekkOS_Preferences/Skill.md +0 -247
  111. package/templates/skills/ekkOS_Reflect/Skill.md +0 -257
  112. package/templates/skills/ekkOS_Safety/Skill.md +0 -265
  113. package/templates/skills/ekkOS_Schema/Skill.md +0 -251
  114. package/templates/skills/ekkOS_Summary/Skill.md +0 -257
  115. package/templates/spec-template.md +0 -159
  116. package/templates/windsurf-rules/ekkos-memory.md +0 -127
  117. package/templates/windsurf-skills/README.md +0 -58
  118. package/templates/windsurf-skills/ekkos-continue/SKILL.md +0 -81
  119. package/templates/windsurf-skills/ekkos-golden-loop/SKILL.md +0 -225
  120. package/templates/windsurf-skills/ekkos-insights/SKILL.md +0 -138
  121. package/templates/windsurf-skills/ekkos-recall/SKILL.md +0 -96
  122. package/templates/windsurf-skills/ekkos-safety/SKILL.md +0 -89
  123. package/templates/windsurf-skills/ekkos-vault/SKILL.md +0 -86
@@ -1,211 +0,0 @@
1
- "use strict";
2
- /**
3
- * Persistence for ekkOS_synk — credentials, settings, daemon state
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.readCredentials = readCredentials;
7
- exports.writeCredentialsLegacy = writeCredentialsLegacy;
8
- exports.writeCredentialsDataKey = writeCredentialsDataKey;
9
- exports.clearCredentials = clearCredentials;
10
- exports.readSettings = readSettings;
11
- exports.writeSettings = writeSettings;
12
- exports.updateSettings = updateSettings;
13
- exports.readDaemonState = readDaemonState;
14
- exports.writeDaemonState = writeDaemonState;
15
- exports.clearDaemonState = clearDaemonState;
16
- exports.acquireDaemonLock = acquireDaemonLock;
17
- exports.releaseDaemonLock = releaseDaemonLock;
18
- const promises_1 = require("node:fs/promises");
19
- const node_fs_1 = require("node:fs");
20
- const node_fs_2 = require("node:fs");
21
- const zod_1 = require("zod");
22
- const config_1 = require("./config");
23
- const encryption_1 = require("./encryption");
24
- const defaultSettings = {
25
- schemaVersion: 1,
26
- onboardingCompleted: false,
27
- };
28
- // Credentials
29
- const credentialsSchema = zod_1.z.object({
30
- token: zod_1.z.string(),
31
- secret: zod_1.z.string().base64().nullish(),
32
- encryption: zod_1.z.object({
33
- publicKey: zod_1.z.string().base64(),
34
- machineKey: zod_1.z.string().base64(),
35
- }).nullish(),
36
- });
37
- async function readCredentials() {
38
- if (!(0, node_fs_1.existsSync)(config_1.synkConfig.credentialsFile))
39
- return null;
40
- try {
41
- const raw = JSON.parse(await (0, promises_1.readFile)(config_1.synkConfig.credentialsFile, 'utf8'));
42
- const credentials = credentialsSchema.parse(raw);
43
- if (credentials.secret) {
44
- return {
45
- token: credentials.token,
46
- encryption: { type: 'legacy', secret: new Uint8Array(Buffer.from(credentials.secret, 'base64')) },
47
- };
48
- }
49
- else if (credentials.encryption) {
50
- return {
51
- token: credentials.token,
52
- encryption: {
53
- type: 'dataKey',
54
- publicKey: new Uint8Array(Buffer.from(credentials.encryption.publicKey, 'base64')),
55
- machineKey: new Uint8Array(Buffer.from(credentials.encryption.machineKey, 'base64')),
56
- },
57
- };
58
- }
59
- }
60
- catch {
61
- return null;
62
- }
63
- return null;
64
- }
65
- async function writeCredentialsLegacy(credentials) {
66
- config_1.synkConfig.ensureDirectories();
67
- await (0, promises_1.writeFile)(config_1.synkConfig.credentialsFile, JSON.stringify({
68
- secret: (0, encryption_1.encodeBase64)(credentials.secret),
69
- token: credentials.token,
70
- }, null, 2));
71
- }
72
- async function writeCredentialsDataKey(credentials) {
73
- config_1.synkConfig.ensureDirectories();
74
- await (0, promises_1.writeFile)(config_1.synkConfig.credentialsFile, JSON.stringify({
75
- encryption: {
76
- publicKey: (0, encryption_1.encodeBase64)(credentials.publicKey),
77
- machineKey: (0, encryption_1.encodeBase64)(credentials.machineKey),
78
- },
79
- token: credentials.token,
80
- }, null, 2));
81
- }
82
- async function clearCredentials() {
83
- if ((0, node_fs_1.existsSync)(config_1.synkConfig.credentialsFile)) {
84
- await (0, promises_1.unlink)(config_1.synkConfig.credentialsFile);
85
- }
86
- }
87
- // Settings
88
- async function readSettings() {
89
- if (!(0, node_fs_1.existsSync)(config_1.synkConfig.settingsFile))
90
- return { ...defaultSettings };
91
- try {
92
- const raw = JSON.parse(await (0, promises_1.readFile)(config_1.synkConfig.settingsFile, 'utf8'));
93
- return { ...defaultSettings, ...raw };
94
- }
95
- catch {
96
- return { ...defaultSettings };
97
- }
98
- }
99
- async function writeSettings(settings) {
100
- config_1.synkConfig.ensureDirectories();
101
- await (0, promises_1.writeFile)(config_1.synkConfig.settingsFile, JSON.stringify(settings, null, 2));
102
- }
103
- async function updateSettings(updater) {
104
- const lockFile = config_1.synkConfig.settingsFile + '.lock';
105
- const tmpFile = config_1.synkConfig.settingsFile + '.tmp';
106
- let fileHandle;
107
- let attempts = 0;
108
- while (attempts < 50) {
109
- try {
110
- fileHandle = await (0, promises_1.open)(lockFile, node_fs_2.constants.O_CREAT | node_fs_2.constants.O_EXCL | node_fs_2.constants.O_WRONLY);
111
- break;
112
- }
113
- catch (err) {
114
- if (err.code === 'EEXIST') {
115
- attempts++;
116
- await new Promise(resolve => setTimeout(resolve, 100));
117
- try {
118
- const stats = await (0, promises_1.stat)(lockFile);
119
- if (Date.now() - stats.mtimeMs > 10000) {
120
- await (0, promises_1.unlink)(lockFile).catch(() => { });
121
- }
122
- }
123
- catch { }
124
- }
125
- else {
126
- throw err;
127
- }
128
- }
129
- }
130
- if (!fileHandle) {
131
- throw new Error('Failed to acquire settings lock after 5 seconds');
132
- }
133
- try {
134
- const current = await readSettings();
135
- const updated = await updater(current);
136
- config_1.synkConfig.ensureDirectories();
137
- await (0, promises_1.writeFile)(tmpFile, JSON.stringify(updated, null, 2));
138
- await (0, promises_1.rename)(tmpFile, config_1.synkConfig.settingsFile);
139
- return updated;
140
- }
141
- finally {
142
- await fileHandle.close();
143
- await (0, promises_1.unlink)(lockFile).catch(() => { });
144
- }
145
- }
146
- // Daemon state
147
- async function readDaemonState() {
148
- try {
149
- if (!(0, node_fs_1.existsSync)(config_1.synkConfig.daemonStateFile))
150
- return null;
151
- return JSON.parse(await (0, promises_1.readFile)(config_1.synkConfig.daemonStateFile, 'utf-8'));
152
- }
153
- catch {
154
- return null;
155
- }
156
- }
157
- function writeDaemonState(state) {
158
- (0, node_fs_1.writeFileSync)(config_1.synkConfig.daemonStateFile, JSON.stringify(state, null, 2), 'utf-8');
159
- }
160
- async function clearDaemonState() {
161
- if ((0, node_fs_1.existsSync)(config_1.synkConfig.daemonStateFile)) {
162
- await (0, promises_1.unlink)(config_1.synkConfig.daemonStateFile);
163
- }
164
- if ((0, node_fs_1.existsSync)(config_1.synkConfig.daemonLockFile)) {
165
- try {
166
- await (0, promises_1.unlink)(config_1.synkConfig.daemonLockFile);
167
- }
168
- catch { }
169
- }
170
- }
171
- async function acquireDaemonLock(maxAttempts = 5, delayIncrementMs = 200) {
172
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
173
- try {
174
- const fileHandle = await (0, promises_1.open)(config_1.synkConfig.daemonLockFile, node_fs_2.constants.O_CREAT | node_fs_2.constants.O_EXCL | node_fs_2.constants.O_WRONLY);
175
- await fileHandle.writeFile(String(process.pid));
176
- return fileHandle;
177
- }
178
- catch (error) {
179
- if (error.code === 'EEXIST') {
180
- try {
181
- const lockPid = (0, node_fs_1.readFileSync)(config_1.synkConfig.daemonLockFile, 'utf-8').trim();
182
- if (lockPid && !isNaN(Number(lockPid))) {
183
- try {
184
- process.kill(Number(lockPid), 0);
185
- }
186
- catch {
187
- (0, node_fs_1.unlinkSync)(config_1.synkConfig.daemonLockFile);
188
- continue;
189
- }
190
- }
191
- }
192
- catch { }
193
- }
194
- if (attempt === maxAttempts)
195
- return null;
196
- await new Promise(resolve => setTimeout(resolve, attempt * delayIncrementMs));
197
- }
198
- }
199
- return null;
200
- }
201
- async function releaseDaemonLock(lockHandle) {
202
- try {
203
- await lockHandle.close();
204
- }
205
- catch { }
206
- try {
207
- if ((0, node_fs_1.existsSync)(config_1.synkConfig.daemonLockFile))
208
- (0, node_fs_1.unlinkSync)(config_1.synkConfig.daemonLockFile);
209
- }
210
- catch { }
211
- }
package/dist/synk/qr.d.ts DELETED
@@ -1,5 +0,0 @@
1
- /**
2
- * QR code display for ekkOS_synk mobile pairing
3
- */
4
- /** Display a QR code in the terminal for mobile device pairing */
5
- export declare function displayQRCode(url: string): void;
package/dist/synk/qr.js DELETED
@@ -1,33 +0,0 @@
1
- "use strict";
2
- /**
3
- * QR code display for ekkOS_synk mobile pairing
4
- */
5
- var __importDefault = (this && this.__importDefault) || function (mod) {
6
- return (mod && mod.__esModule) ? mod : { "default": mod };
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.displayQRCode = displayQRCode;
10
- const chalk_1 = __importDefault(require("chalk"));
11
- /** Display a QR code in the terminal for mobile device pairing */
12
- function displayQRCode(url) {
13
- let qrcode;
14
- try {
15
- qrcode = require('qrcode-terminal');
16
- }
17
- catch {
18
- console.log(chalk_1.default.yellow(' qrcode-terminal not installed. Install it for QR code display.'));
19
- console.log(chalk_1.default.gray(` Pairing URL: ${url}`));
20
- return;
21
- }
22
- console.log('');
23
- console.log(chalk_1.default.cyan('═'.repeat(60)));
24
- console.log(chalk_1.default.cyan.bold(' ekkOS_synk') + chalk_1.default.gray(' — Scan to pair your mobile device'));
25
- console.log(chalk_1.default.cyan('═'.repeat(60)));
26
- qrcode.generate(url, { small: true }, (qr) => {
27
- for (const line of qr.split('\n')) {
28
- console.log(' '.repeat(8) + line);
29
- }
30
- });
31
- console.log(chalk_1.default.cyan('═'.repeat(60)));
32
- console.log('');
33
- }
@@ -1,58 +0,0 @@
1
- /**
2
- * SynkSessionBridge — links `ekkos run` to synk real-time sync
3
- *
4
- * Lifecycle:
5
- * create() → reads creds, returns null if synk disabled
6
- * onSessionEstablished → creates synk session + WS client
7
- * onAgentOutput → batched forwarding of PTY output
8
- * onIdleChange → keepalive / thinking state
9
- * onTurnEnd → flush output buffer
10
- * shutdown → graceful close
11
- */
12
- import { EventEmitter } from 'node:events';
13
- export interface SynkBridgeOptions {
14
- cwd: string;
15
- verbose?: boolean;
16
- }
17
- export declare class SynkSessionBridge extends EventEmitter {
18
- private readonly credential;
19
- private readonly apiClient;
20
- private readonly cwd;
21
- private readonly verbose;
22
- private sessionClient;
23
- private synkSession;
24
- private outputBuffer;
25
- private flushTimer;
26
- private established;
27
- private closed;
28
- private constructor();
29
- /**
30
- * Factory — returns null when synk is not configured (zero-cost path).
31
- */
32
- static create(opts: SynkBridgeOptions): Promise<SynkSessionBridge | null>;
33
- /**
34
- * Called once after Claude Code's session name is detected from the status line.
35
- * Creates the synk session via REST, then opens a SessionClient WebSocket.
36
- */
37
- onSessionEstablished(sessionName: string, sessionId: string, extra?: {
38
- hostPid?: number;
39
- }): Promise<void>;
40
- /**
41
- * Called on every PTY data chunk. Buffers and flushes every 200ms.
42
- */
43
- onAgentOutput(data: string): void;
44
- /**
45
- * Called when Claude transitions between idle <-> active.
46
- */
47
- onIdleChange(idle: boolean): void;
48
- /**
49
- * Called at turn boundaries — flush any pending output immediately.
50
- */
51
- onTurnEnd(): void;
52
- /**
53
- * Graceful shutdown — send death event, flush, close socket.
54
- */
55
- shutdown(): Promise<void>;
56
- private flushOutputBuffer;
57
- private log;
58
- }
@@ -1,171 +0,0 @@
1
- "use strict";
2
- /**
3
- * SynkSessionBridge — links `ekkos run` to synk real-time sync
4
- *
5
- * Lifecycle:
6
- * create() → reads creds, returns null if synk disabled
7
- * onSessionEstablished → creates synk session + WS client
8
- * onAgentOutput → batched forwarding of PTY output
9
- * onIdleChange → keepalive / thinking state
10
- * onTurnEnd → flush output buffer
11
- * shutdown → graceful close
12
- */
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.SynkSessionBridge = void 0;
18
- const node_events_1 = require("node:events");
19
- const node_os_1 = __importDefault(require("node:os"));
20
- const persistence_1 = require("./persistence");
21
- const api_1 = require("./api");
22
- const session_client_1 = require("./session-client");
23
- const config_1 = require("./config");
24
- const control_client_1 = require("./daemon/control-client");
25
- class SynkSessionBridge extends node_events_1.EventEmitter {
26
- constructor(credential, apiClient, opts) {
27
- super();
28
- this.sessionClient = null;
29
- this.synkSession = null;
30
- this.outputBuffer = '';
31
- this.flushTimer = null;
32
- this.established = false;
33
- this.closed = false;
34
- this.credential = credential;
35
- this.apiClient = apiClient;
36
- this.cwd = opts.cwd;
37
- this.verbose = opts.verbose ?? false;
38
- }
39
- /**
40
- * Factory — returns null when synk is not configured (zero-cost path).
41
- */
42
- static async create(opts) {
43
- try {
44
- const credential = await (0, persistence_1.readCredentials)();
45
- if (!credential)
46
- return null;
47
- const apiClient = await api_1.ApiClient.create(credential);
48
- return new SynkSessionBridge(credential, apiClient, opts);
49
- }
50
- catch {
51
- return null;
52
- }
53
- }
54
- /**
55
- * Called once after Claude Code's session name is detected from the status line.
56
- * Creates the synk session via REST, then opens a SessionClient WebSocket.
57
- */
58
- async onSessionEstablished(sessionName, sessionId, extra) {
59
- if (this.established || this.closed)
60
- return;
61
- this.established = true;
62
- try {
63
- const settings = await (0, persistence_1.readSettings)();
64
- const metadata = {
65
- path: this.cwd,
66
- host: node_os_1.default.hostname(),
67
- name: sessionName,
68
- os: node_os_1.default.platform(),
69
- homeDir: node_os_1.default.homedir(),
70
- synkHomeDir: config_1.synkConfig.synkHomeDir,
71
- machineId: settings.machineId,
72
- claudeSessionId: sessionId,
73
- hostPid: extra?.hostPid ?? process.pid,
74
- startedBy: 'terminal',
75
- lifecycleState: 'running',
76
- lifecycleStateSince: Date.now(),
77
- };
78
- const session = await this.apiClient.getOrCreateSession({
79
- tag: sessionId,
80
- metadata,
81
- state: null,
82
- });
83
- if (!session) {
84
- this.log('synk session creation failed (server unreachable)');
85
- return;
86
- }
87
- this.synkSession = session;
88
- this.sessionClient = new session_client_1.SessionClient(this.credential.token, session);
89
- // Pipe incoming user messages to run.ts via EventEmitter
90
- this.sessionClient.onUserMessage((msg) => {
91
- this.emit('remote-message', { text: msg.content.text, meta: msg.meta });
92
- });
93
- this.sessionClient.on('connected', () => this.log('synk WS connected'));
94
- this.sessionClient.on('disconnected', (reason) => this.log(`synk WS disconnected: ${reason}`));
95
- this.sessionClient.on('error', (err) => this.log(`synk WS error: ${err.message}`));
96
- // Notify daemon (best-effort, fire-and-forget)
97
- (0, control_client_1.notifyDaemonSessionStarted)(session.id, metadata).catch(() => { });
98
- this.log(`synk session established: ${session.id}`);
99
- }
100
- catch (err) {
101
- this.log(`synk session establish error: ${err instanceof Error ? err.message : err}`);
102
- }
103
- }
104
- /**
105
- * Called on every PTY data chunk. Buffers and flushes every 200ms.
106
- */
107
- onAgentOutput(data) {
108
- if (!this.sessionClient || this.closed)
109
- return;
110
- this.outputBuffer += data;
111
- if (!this.flushTimer) {
112
- this.flushTimer = setTimeout(() => {
113
- this.flushTimer = null;
114
- this.flushOutputBuffer();
115
- }, 200);
116
- }
117
- }
118
- /**
119
- * Called when Claude transitions between idle <-> active.
120
- */
121
- onIdleChange(idle) {
122
- if (!this.sessionClient || this.closed)
123
- return;
124
- this.sessionClient.keepAlive(!idle, 'local');
125
- }
126
- /**
127
- * Called at turn boundaries — flush any pending output immediately.
128
- */
129
- onTurnEnd() {
130
- this.flushOutputBuffer();
131
- }
132
- /**
133
- * Graceful shutdown — send death event, flush, close socket.
134
- */
135
- async shutdown() {
136
- if (this.closed)
137
- return;
138
- this.closed = true;
139
- if (this.flushTimer) {
140
- clearTimeout(this.flushTimer);
141
- this.flushTimer = null;
142
- }
143
- this.flushOutputBuffer();
144
- if (this.sessionClient) {
145
- try {
146
- this.sessionClient.sendSessionDeath();
147
- await Promise.race([
148
- this.sessionClient.flush(),
149
- new Promise(resolve => setTimeout(resolve, 3000)),
150
- ]);
151
- }
152
- catch { }
153
- await this.sessionClient.close().catch(() => { });
154
- this.sessionClient = null;
155
- }
156
- }
157
- // ── internals ──
158
- flushOutputBuffer() {
159
- if (!this.sessionClient || this.outputBuffer.length === 0)
160
- return;
161
- const chunk = this.outputBuffer;
162
- this.outputBuffer = '';
163
- this.sessionClient.sendAgentMessage(chunk);
164
- }
165
- log(msg) {
166
- if (this.verbose) {
167
- process.stderr.write(`[synk-bridge] ${msg}\n`);
168
- }
169
- }
170
- }
171
- exports.SynkSessionBridge = SynkSessionBridge;
@@ -1,46 +0,0 @@
1
- /**
2
- * Real-time session client for ekkOS_synk
3
- * Manages Socket.IO connection and message sync with synk-server
4
- */
5
- import { EventEmitter } from 'node:events';
6
- import type { Session, Metadata, UserMessage } from './types';
7
- export declare class SessionClient extends EventEmitter {
8
- private readonly token;
9
- readonly sessionId: string;
10
- private metadata;
11
- private metadataVersion;
12
- private agentState;
13
- private agentStateVersion;
14
- private socket;
15
- private pendingMessages;
16
- private pendingMessageCallback;
17
- private encryptionKey;
18
- private encryptionVariant;
19
- private lastSeq;
20
- private pendingOutbox;
21
- private flushTimer;
22
- constructor(token: string, session: Session);
23
- onUserMessage(callback: (data: UserMessage) => void): void;
24
- private routeIncomingMessage;
25
- private fetchMessages;
26
- private scheduleFlush;
27
- private flushOutbox;
28
- /** Send encrypted message to session */
29
- sendMessage(content: unknown): void;
30
- /** Send agent output message */
31
- sendAgentMessage(data: any): void;
32
- /** Send session event */
33
- sendSessionEvent(event: {
34
- type: string;
35
- [key: string]: any;
36
- }): void;
37
- /** Send keepalive ping */
38
- keepAlive(thinking: boolean, mode: 'local' | 'remote'): void;
39
- /** Notify server of session end */
40
- sendSessionDeath(): void;
41
- /** Update session metadata on server */
42
- updateMetadata(handler: (metadata: Metadata) => Metadata): void;
43
- /** Wait for pending messages to flush */
44
- flush(): Promise<void>;
45
- close(): Promise<void>;
46
- }