termify-agent 1.0.46 → 1.0.48

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 (62) hide show
  1. package/dist/agent.d.ts +1 -0
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +13 -0
  4. package/dist/agent.js.map +1 -1
  5. package/dist/bundle-sync.d.ts +74 -0
  6. package/dist/bundle-sync.d.ts.map +1 -0
  7. package/dist/bundle-sync.js +257 -0
  8. package/dist/bundle-sync.js.map +1 -0
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +25 -1
  11. package/dist/config.js.map +1 -1
  12. package/dist/config.test.d.ts +2 -0
  13. package/dist/config.test.d.ts.map +1 -0
  14. package/dist/config.test.js +63 -0
  15. package/dist/config.test.js.map +1 -0
  16. package/dist/index.js +24 -4
  17. package/dist/index.js.map +1 -1
  18. package/dist/personal-sync/api-client.d.ts +20 -0
  19. package/dist/personal-sync/api-client.d.ts.map +1 -0
  20. package/dist/personal-sync/api-client.js +101 -0
  21. package/dist/personal-sync/api-client.js.map +1 -0
  22. package/dist/personal-sync/applier.d.ts +6 -0
  23. package/dist/personal-sync/applier.d.ts.map +1 -0
  24. package/dist/personal-sync/applier.js +137 -0
  25. package/dist/personal-sync/applier.js.map +1 -0
  26. package/dist/personal-sync/collector.d.ts +9 -0
  27. package/dist/personal-sync/collector.d.ts.map +1 -0
  28. package/dist/personal-sync/collector.js +206 -0
  29. package/dist/personal-sync/collector.js.map +1 -0
  30. package/dist/personal-sync/engine.d.ts +28 -0
  31. package/dist/personal-sync/engine.d.ts.map +1 -0
  32. package/dist/personal-sync/engine.js +248 -0
  33. package/dist/personal-sync/engine.js.map +1 -0
  34. package/dist/personal-sync/managed-spec.d.ts +9 -0
  35. package/dist/personal-sync/managed-spec.d.ts.map +1 -0
  36. package/dist/personal-sync/managed-spec.js +52 -0
  37. package/dist/personal-sync/managed-spec.js.map +1 -0
  38. package/dist/personal-sync/types.d.ts +38 -0
  39. package/dist/personal-sync/types.d.ts.map +1 -0
  40. package/dist/personal-sync/types.js +18 -0
  41. package/dist/personal-sync/types.js.map +1 -0
  42. package/dist/personal-sync/watcher.d.ts +16 -0
  43. package/dist/personal-sync/watcher.d.ts.map +1 -0
  44. package/dist/personal-sync/watcher.js +88 -0
  45. package/dist/personal-sync/watcher.js.map +1 -0
  46. package/dist/setup.d.ts +20 -8
  47. package/dist/setup.d.ts.map +1 -1
  48. package/dist/setup.js +302 -128
  49. package/dist/setup.js.map +1 -1
  50. package/dist/ssh-manager.d.ts +6 -1
  51. package/dist/ssh-manager.d.ts.map +1 -1
  52. package/dist/ssh-manager.js +39 -3
  53. package/dist/ssh-manager.js.map +1 -1
  54. package/dist/ssh-manager.test.d.ts +2 -0
  55. package/dist/ssh-manager.test.d.ts.map +1 -0
  56. package/dist/ssh-manager.test.js +73 -0
  57. package/dist/ssh-manager.test.js.map +1 -0
  58. package/dist/ws-client.d.ts.map +1 -1
  59. package/dist/ws-client.js +5 -0
  60. package/dist/ws-client.js.map +1 -1
  61. package/package.json +3 -3
  62. package/scripts/publish-bundles.sh +121 -5
@@ -0,0 +1,206 @@
1
+ import { createHash } from 'crypto';
2
+ import { existsSync, readFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+ import { PersonalConfigDomain, REDACTED_PLACEHOLDER, EXCLUDED_FILES, } from './types.js';
6
+ const SECRET_KEYS = new Set([
7
+ 'token', 'apikey', 'api_key', 'apiKey', 'password', 'secret',
8
+ 'access_token', 'accessToken', 'refresh_token', 'refreshToken',
9
+ 'private_key', 'privateKey', 'authorization',
10
+ ]);
11
+ function redactSecrets(obj) {
12
+ if (typeof obj !== 'object' || obj === null)
13
+ return obj;
14
+ if (Array.isArray(obj))
15
+ return obj.map(redactSecrets);
16
+ const result = {};
17
+ for (const [key, value] of Object.entries(obj)) {
18
+ const lowerKey = key.toLowerCase();
19
+ if (SECRET_KEYS.has(lowerKey) || SECRET_KEYS.has(key)) {
20
+ if (typeof value === 'string' && value.length > 0) {
21
+ result[key] = REDACTED_PLACEHOLDER;
22
+ }
23
+ else {
24
+ result[key] = value;
25
+ }
26
+ }
27
+ else if (typeof value === 'object' && value !== null) {
28
+ result[key] = redactSecrets(value);
29
+ }
30
+ else {
31
+ result[key] = value;
32
+ }
33
+ }
34
+ return result;
35
+ }
36
+ function sha256(data) {
37
+ return createHash('sha256').update(data).digest('hex');
38
+ }
39
+ function logicalPath(relativePath) {
40
+ return '${HOME}/' + relativePath;
41
+ }
42
+ function isExcluded(relativePath) {
43
+ return EXCLUDED_FILES.has(relativePath);
44
+ }
45
+ function tryReadJson(filePath) {
46
+ try {
47
+ if (!existsSync(filePath))
48
+ return null;
49
+ return JSON.parse(readFileSync(filePath, 'utf8'));
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
55
+ function filterClaudeSettings(settings, spec) {
56
+ const filtered = { ...settings };
57
+ // Filter managed MCPs from mcpServers
58
+ if (filtered.mcpServers) {
59
+ const personal = {};
60
+ for (const [key, value] of Object.entries(filtered.mcpServers)) {
61
+ if (!spec.managedMcpKeys.has(key)) {
62
+ personal[key] = value;
63
+ }
64
+ }
65
+ filtered.mcpServers = personal;
66
+ }
67
+ // Filter managed hooks
68
+ if (filtered.hooks) {
69
+ const personalHooks = {};
70
+ for (const [event, handlers] of Object.entries(filtered.hooks)) {
71
+ if (Array.isArray(handlers)) {
72
+ const personalHandlers = handlers.filter((h) => {
73
+ const cmd = typeof h === 'string' ? h : h?.command ?? '';
74
+ return !spec.managedHookFiles.has(cmd);
75
+ });
76
+ if (personalHandlers.length > 0) {
77
+ personalHooks[event] = personalHandlers;
78
+ }
79
+ }
80
+ else {
81
+ personalHooks[event] = handlers;
82
+ }
83
+ }
84
+ filtered.hooks = personalHooks;
85
+ }
86
+ return filtered;
87
+ }
88
+ function filterInstalledPlugins(plugins, spec) {
89
+ if (!Array.isArray(plugins))
90
+ return plugins;
91
+ return plugins.filter((p) => !spec.managedPluginIds.has(p.id ?? p.pluginId ?? ''));
92
+ }
93
+ function filterKnownMarketplaces(marketplaces, spec) {
94
+ if (!Array.isArray(marketplaces))
95
+ return marketplaces;
96
+ return marketplaces.filter((m) => {
97
+ const key = `${m.source ?? ''}:${m.repo ?? ''}`;
98
+ return !spec.managedMarketplaceSources.has(key);
99
+ });
100
+ }
101
+ function filterEnabledPlugins(enabled, spec) {
102
+ if (typeof enabled !== 'object' || enabled === null)
103
+ return enabled;
104
+ const personal = {};
105
+ for (const [key, value] of Object.entries(enabled)) {
106
+ if (!spec.managedPluginIds.has(key)) {
107
+ personal[key] = value;
108
+ }
109
+ }
110
+ return personal;
111
+ }
112
+ function filterCodexSettings(settings, spec) {
113
+ // Codex config is TOML — stored as string. Filter managed MCP sections.
114
+ // For now, sync as-is (managed MCPs in codex are rare)
115
+ return settings;
116
+ }
117
+ export function collectPersonalConfig(spec) {
118
+ const home = homedir();
119
+ const entries = [];
120
+ const files = new Map();
121
+ const targets = [
122
+ {
123
+ relativePath: '.claude/settings.json',
124
+ domain: PersonalConfigDomain.CLAUDE_SETTINGS,
125
+ filter: filterClaudeSettings,
126
+ },
127
+ {
128
+ relativePath: '.claude/plugins/installed_plugins.json',
129
+ domain: PersonalConfigDomain.CLAUDE_PLUGINS,
130
+ filter: filterInstalledPlugins,
131
+ },
132
+ {
133
+ relativePath: '.claude/plugins/known_marketplaces.json',
134
+ domain: PersonalConfigDomain.CLAUDE_PLUGINS,
135
+ filter: filterKnownMarketplaces,
136
+ },
137
+ {
138
+ relativePath: '.codex/config.toml',
139
+ domain: PersonalConfigDomain.CODEX_SETTINGS,
140
+ filter: filterCodexSettings,
141
+ },
142
+ {
143
+ relativePath: '.gemini/settings.json',
144
+ domain: PersonalConfigDomain.GEMINI_SETTINGS,
145
+ },
146
+ {
147
+ relativePath: '.memsearch/config.toml',
148
+ domain: PersonalConfigDomain.MEMSEARCH_CONFIG,
149
+ },
150
+ ];
151
+ for (const target of targets) {
152
+ if (isExcluded(target.relativePath))
153
+ continue;
154
+ const filePath = join(home, target.relativePath);
155
+ if (!existsSync(filePath))
156
+ continue;
157
+ try {
158
+ let content;
159
+ const raw = readFileSync(filePath, 'utf8');
160
+ // JSON files: parse, filter, redact, re-serialize
161
+ if (target.relativePath.endsWith('.json')) {
162
+ content = JSON.parse(raw);
163
+ if (target.filter) {
164
+ content = target.filter(content, spec);
165
+ }
166
+ content = redactSecrets(content);
167
+ const serialized = Buffer.from(JSON.stringify(content, null, 2));
168
+ const hash = sha256(serialized);
169
+ entries.push({
170
+ logicalPath: logicalPath(target.relativePath),
171
+ domain: target.domain,
172
+ sha256: hash,
173
+ size: serialized.length,
174
+ });
175
+ files.set(hash, serialized);
176
+ }
177
+ else {
178
+ // TOML/text files: filter if needed, store as-is
179
+ let processed = raw;
180
+ if (target.filter) {
181
+ processed = target.filter(raw, spec);
182
+ }
183
+ const serialized = Buffer.from(processed);
184
+ const hash = sha256(serialized);
185
+ entries.push({
186
+ logicalPath: logicalPath(target.relativePath),
187
+ domain: target.domain,
188
+ sha256: hash,
189
+ size: serialized.length,
190
+ });
191
+ files.set(hash, serialized);
192
+ }
193
+ }
194
+ catch {
195
+ // Skip files that can't be read/parsed
196
+ }
197
+ }
198
+ return {
199
+ manifest: {
200
+ entries,
201
+ collectedAt: new Date().toISOString(),
202
+ },
203
+ files,
204
+ };
205
+ }
206
+ //# sourceMappingURL=collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/personal-sync/collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { EventEmitter } from 'events';
2
+ export declare class PersonalSyncEngine extends EventEmitter {
3
+ private api;
4
+ private watcher;
5
+ private spec;
6
+ private state;
7
+ private running;
8
+ private lastPushAt;
9
+ private pushPending;
10
+ constructor();
11
+ start(serverUrl: string, accessToken: string): void;
12
+ stop(): void;
13
+ /**
14
+ * Called when server sends `server.personal-config.updated` via WebSocket
15
+ */
16
+ onRemoteChange(version: number): void;
17
+ /**
18
+ * Update managed spec (call after bundle-sync completes)
19
+ */
20
+ refreshManagedSpec(): void;
21
+ private pull;
22
+ private push;
23
+ private onLocalChange;
24
+ private poll;
25
+ private loadState;
26
+ private saveState;
27
+ }
28
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/personal-sync/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAgBtC,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAO,CAAC,GAAG,CAAwC;IACnD,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAS;;IAS5B,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAmBnD,IAAI,IAAI,IAAI;IAYZ;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAUrC;;OAEG;IACH,kBAAkB,IAAI,IAAI;YAMZ,IAAI;YAyDJ,IAAI;IA2ElB,OAAO,CAAC,aAAa;YAyBP,IAAI;IAYlB,OAAO,CAAC,SAAS;IAgBjB,OAAO,CAAC,SAAS;CAQlB"}
@@ -0,0 +1,248 @@
1
+ import { EventEmitter } from 'events';
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+ import { logger } from '../utils/logger.js';
6
+ import { PersonalConfigApiClient } from './api-client.js';
7
+ import { PersonalConfigWatcher } from './watcher.js';
8
+ import { collectPersonalConfig } from './collector.js';
9
+ import { applyRemoteConfig } from './applier.js';
10
+ import { loadManagedSpec } from './managed-spec.js';
11
+ const STATE_FILE = join(homedir(), '.termify', 'personal-sync-state.json');
12
+ const PUSH_COOLDOWN_MS = 10_000; // 10s cooldown between pushes
13
+ const SUPPRESS_AFTER_APPLY_MS = 10_000; // 10s suppress watcher after apply
14
+ export class PersonalSyncEngine extends EventEmitter {
15
+ api = null;
16
+ watcher;
17
+ spec;
18
+ state;
19
+ running = false;
20
+ lastPushAt = 0;
21
+ pushPending = false;
22
+ constructor() {
23
+ super();
24
+ this.watcher = new PersonalConfigWatcher();
25
+ this.spec = loadManagedSpec();
26
+ this.state = this.loadState();
27
+ }
28
+ start(serverUrl, accessToken) {
29
+ if (this.running)
30
+ return;
31
+ this.running = true;
32
+ this.api = new PersonalConfigApiClient(serverUrl, accessToken);
33
+ // Wire watcher events
34
+ this.watcher.on('changed', () => this.onLocalChange());
35
+ this.watcher.on('poll', () => this.poll());
36
+ this.watcher.start();
37
+ // Initial pull (non-blocking)
38
+ this.pull().catch(err => {
39
+ logger.warn(`[PersonalSync] Initial pull failed: ${err.message}`);
40
+ });
41
+ logger.info('[PersonalSync] Engine started');
42
+ }
43
+ stop() {
44
+ if (!this.running)
45
+ return;
46
+ this.running = false;
47
+ this.watcher.stop();
48
+ this.watcher.removeAllListeners();
49
+ this.saveState();
50
+ this.api = null;
51
+ logger.info('[PersonalSync] Engine stopped');
52
+ }
53
+ /**
54
+ * Called when server sends `server.personal-config.updated` via WebSocket
55
+ */
56
+ onRemoteChange(version) {
57
+ if (!this.running)
58
+ return;
59
+ if (version <= this.state.lastPulledVersion)
60
+ return;
61
+ logger.info(`[PersonalSync] Remote change detected: v${version}`);
62
+ this.pull().catch(err => {
63
+ logger.warn(`[PersonalSync] Pull after remote change failed: ${err.message}`);
64
+ });
65
+ }
66
+ /**
67
+ * Update managed spec (call after bundle-sync completes)
68
+ */
69
+ refreshManagedSpec() {
70
+ this.spec = loadManagedSpec();
71
+ }
72
+ // ─── Pull ────────────────────────────────────────────────────────────────
73
+ async pull() {
74
+ if (!this.api)
75
+ return;
76
+ try {
77
+ const snapshot = await this.api.pull(this.state.lastPulledVersion);
78
+ if (!snapshot) {
79
+ logger.debug('[PersonalSync] No new version available');
80
+ return;
81
+ }
82
+ const manifest = snapshot.manifest;
83
+ if (!manifest?.entries?.length) {
84
+ logger.debug('[PersonalSync] Empty manifest, skipping');
85
+ this.state.lastPulledVersion = snapshot.version;
86
+ this.saveState();
87
+ return;
88
+ }
89
+ // Download missing blobs
90
+ const blobs = new Map();
91
+ for (const entry of manifest.entries) {
92
+ try {
93
+ const data = await this.api.downloadBlob(entry.sha256);
94
+ blobs.set(entry.sha256, data);
95
+ }
96
+ catch (err) {
97
+ logger.warn(`[PersonalSync] Failed to download blob ${entry.sha256}: ${err}`);
98
+ }
99
+ }
100
+ // Apply with watcher suppressed
101
+ this.watcher.suppressFor(SUPPRESS_AFTER_APPLY_MS);
102
+ const { applied, skipped } = applyRemoteConfig(manifest, blobs, this.state.hashCache);
103
+ // Update hash cache from applied entries
104
+ for (const entry of manifest.entries) {
105
+ if (applied.includes(entry.logicalPath)) {
106
+ this.state.hashCache[entry.logicalPath] = entry.sha256;
107
+ }
108
+ }
109
+ this.state.lastPulledVersion = snapshot.version;
110
+ this.state.lastSyncedAt = new Date().toISOString();
111
+ this.saveState();
112
+ // Ack version
113
+ await this.api.ack(snapshot.version).catch(() => { });
114
+ if (applied.length > 0) {
115
+ logger.info(`[PersonalSync] Pulled v${snapshot.version}: applied ${applied.length}, skipped ${skipped.length}`);
116
+ }
117
+ }
118
+ catch (err) {
119
+ logger.warn(`[PersonalSync] Pull error: ${err.message}`);
120
+ }
121
+ }
122
+ // ─── Push ────────────────────────────────────────────────────────────────
123
+ async push() {
124
+ if (!this.api)
125
+ return;
126
+ try {
127
+ const { manifest, files } = collectPersonalConfig(this.spec);
128
+ // Check if anything changed vs cache
129
+ let hasChanges = false;
130
+ for (const entry of manifest.entries) {
131
+ if (this.state.hashCache[entry.logicalPath] !== entry.sha256) {
132
+ hasChanges = true;
133
+ break;
134
+ }
135
+ }
136
+ // Also check if entries were removed
137
+ const currentPaths = new Set(manifest.entries.map(e => e.logicalPath));
138
+ for (const cachedPath of Object.keys(this.state.hashCache)) {
139
+ if (!currentPaths.has(cachedPath)) {
140
+ hasChanges = true;
141
+ break;
142
+ }
143
+ }
144
+ if (!hasChanges) {
145
+ logger.debug('[PersonalSync] No changes detected, skipping push');
146
+ return;
147
+ }
148
+ const blobSha256s = [...files.keys()];
149
+ const baseVersion = this.state.lastPushedVersion || this.state.lastPulledVersion;
150
+ // Init upload
151
+ const { uploadId, existingBlobs } = await this.api.initUpload(baseVersion, blobSha256s);
152
+ // Upload missing blobs
153
+ const existingSet = new Set(existingBlobs.map(b => b.toLowerCase()));
154
+ for (const [sha, data] of files) {
155
+ if (!existingSet.has(sha.toLowerCase())) {
156
+ await this.api.uploadBlob(uploadId, sha, data);
157
+ }
158
+ }
159
+ // Commit
160
+ const { version } = await this.api.commitUpload(uploadId, manifest);
161
+ // Update state
162
+ this.state.lastPushedVersion = version;
163
+ this.state.lastSyncedAt = new Date().toISOString();
164
+ for (const entry of manifest.entries) {
165
+ this.state.hashCache[entry.logicalPath] = entry.sha256;
166
+ }
167
+ // Clean removed entries from cache
168
+ for (const key of Object.keys(this.state.hashCache)) {
169
+ if (!currentPaths.has(key)) {
170
+ delete this.state.hashCache[key];
171
+ }
172
+ }
173
+ this.saveState();
174
+ logger.info(`[PersonalSync] Pushed v${version}: ${manifest.entries.length} entries`);
175
+ }
176
+ catch (err) {
177
+ if (err.code === 'CONFLICT') {
178
+ logger.info(`[PersonalSync] Conflict on push (server v${err.currentVersion}), pulling first`);
179
+ await this.pull();
180
+ // Re-push after pull
181
+ await this.push();
182
+ return;
183
+ }
184
+ logger.warn(`[PersonalSync] Push error: ${err.message}`);
185
+ }
186
+ }
187
+ // ─── Events ──────────────────────────────────────────────────────────────
188
+ onLocalChange() {
189
+ if (!this.running)
190
+ return;
191
+ const now = Date.now();
192
+ if (now - this.lastPushAt < PUSH_COOLDOWN_MS) {
193
+ // Cooldown active — schedule for later
194
+ if (!this.pushPending) {
195
+ this.pushPending = true;
196
+ setTimeout(() => {
197
+ this.pushPending = false;
198
+ this.lastPushAt = Date.now();
199
+ this.push().catch(err => {
200
+ logger.warn(`[PersonalSync] Deferred push failed: ${err.message}`);
201
+ });
202
+ }, PUSH_COOLDOWN_MS - (now - this.lastPushAt));
203
+ }
204
+ return;
205
+ }
206
+ this.lastPushAt = now;
207
+ this.push().catch(err => {
208
+ logger.warn(`[PersonalSync] Push failed: ${err.message}`);
209
+ });
210
+ }
211
+ async poll() {
212
+ if (!this.running)
213
+ return;
214
+ await this.pull().catch(err => {
215
+ logger.warn(`[PersonalSync] Poll pull failed: ${err.message}`);
216
+ });
217
+ await this.push().catch(err => {
218
+ logger.warn(`[PersonalSync] Poll push failed: ${err.message}`);
219
+ });
220
+ }
221
+ // ─── State persistence ───────────────────────────────────────────────────
222
+ loadState() {
223
+ try {
224
+ if (existsSync(STATE_FILE)) {
225
+ return JSON.parse(readFileSync(STATE_FILE, 'utf8'));
226
+ }
227
+ }
228
+ catch {
229
+ // Corrupted state file
230
+ }
231
+ return {
232
+ lastPulledVersion: 0,
233
+ lastPushedVersion: 0,
234
+ hashCache: {},
235
+ lastSyncedAt: null,
236
+ };
237
+ }
238
+ saveState() {
239
+ try {
240
+ mkdirSync(join(homedir(), '.termify'), { recursive: true });
241
+ writeFileSync(STATE_FILE, JSON.stringify(this.state, null, 2));
242
+ }
243
+ catch {
244
+ // Non-fatal
245
+ }
246
+ }
247
+ }
248
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/personal-sync/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface ManagedSpec {
2
+ managedMcpKeys: Set<string>;
3
+ managedHookFiles: Set<string>;
4
+ managedPluginIds: Set<string>;
5
+ managedPluginPaths: Set<string>;
6
+ managedMarketplaceSources: Set<string>;
7
+ }
8
+ export declare function loadManagedSpec(): ManagedSpec;
9
+ //# sourceMappingURL=managed-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-spec.d.ts","sourceRoot":"","sources":["../../src/personal-sync/managed-spec.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,yBAAyB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACxC;AAID,wBAAgB,eAAe,IAAI,WAAW,CAkD7C"}
@@ -0,0 +1,52 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+ const MANIFEST_PATH = join(homedir(), '.termify', 'bundles-manifest.json');
5
+ export function loadManagedSpec() {
6
+ const spec = {
7
+ managedMcpKeys: new Set(),
8
+ managedHookFiles: new Set(),
9
+ managedPluginIds: new Set(),
10
+ managedPluginPaths: new Set(),
11
+ managedMarketplaceSources: new Set(),
12
+ };
13
+ try {
14
+ if (!existsSync(MANIFEST_PATH))
15
+ return spec;
16
+ const raw = readFileSync(MANIFEST_PATH, 'utf8');
17
+ const manifest = JSON.parse(raw);
18
+ // MCPs managed by Termify
19
+ if (manifest.mcpRegistrations) {
20
+ for (const tool of Object.keys(manifest.mcpRegistrations)) {
21
+ for (const key of Object.keys(manifest.mcpRegistrations[tool])) {
22
+ spec.managedMcpKeys.add(key);
23
+ }
24
+ }
25
+ }
26
+ // Hooks managed by Termify
27
+ for (const hook of manifest.hooks ?? []) {
28
+ spec.managedHookFiles.add(hook.file);
29
+ }
30
+ // Plugins managed by Termify
31
+ if (manifest.plugins) {
32
+ for (const plugin of manifest.plugins) {
33
+ spec.managedPluginIds.add(plugin.pluginId);
34
+ spec.managedPluginPaths.add(plugin.installPath);
35
+ if (plugin.marketplaceSource) {
36
+ spec.managedMarketplaceSources.add(`${plugin.marketplaceSource.source}:${plugin.marketplaceSource.repo}`);
37
+ }
38
+ }
39
+ }
40
+ // Enabled plugins from bundle
41
+ if (manifest.enabledPlugins) {
42
+ for (const key of Object.keys(manifest.enabledPlugins)) {
43
+ spec.managedPluginIds.add(key);
44
+ }
45
+ }
46
+ }
47
+ catch {
48
+ // Invalid manifest — treat everything as personal
49
+ }
50
+ return spec;
51
+ }
52
+ //# sourceMappingURL=managed-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-spec.js","sourceRoot":"","sources":["../../src/personal-sync/managed-spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAW7B,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,uBAAuB,CAAC,CAAC;AAE3E,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,GAAgB;QACxB,cAAc,EAAE,IAAI,GAAG,EAAE;QACzB,gBAAgB,EAAE,IAAI,GAAG,EAAE;QAC3B,gBAAgB,EAAE,IAAI,GAAG,EAAE;QAC3B,kBAAkB,EAAE,IAAI,GAAG,EAAE;QAC7B,yBAAyB,EAAE,IAAI,GAAG,EAAE;KACrC,CAAC;IAEF,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;YAAE,OAAO,IAAI,CAAC;QAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;QAEnD,0BAA0B;QAC1B,IAAI,QAAQ,CAAC,gBAAgB,EAAE,CAAC;YAC9B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAC1D,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBAC/D,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;QAED,6BAA6B;QAC7B,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAwB,EAAE,CAAC;gBACvD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC3C,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBAChD,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;oBAC7B,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,IAAI,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC5G,CAAC;YACH,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;YAC5B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACvD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;IACpD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,38 @@
1
+ export declare enum PersonalConfigDomain {
2
+ CLAUDE_SETTINGS = "claude-settings",
3
+ CLAUDE_HOOKS = "claude-hooks",
4
+ CLAUDE_PLUGINS = "claude-plugins",
5
+ CLAUDE_ENABLED_PLUGINS = "claude-enabled-plugins",
6
+ CODEX_SETTINGS = "codex-settings",
7
+ GEMINI_SETTINGS = "gemini-settings",
8
+ MEMSEARCH_CONFIG = "memsearch-config"
9
+ }
10
+ export interface PersonalConfigEntry {
11
+ logicalPath: string;
12
+ domain: PersonalConfigDomain;
13
+ sha256: string;
14
+ size: number;
15
+ }
16
+ export interface PersonalConfigManifest {
17
+ entries: PersonalConfigEntry[];
18
+ collectedAt: string;
19
+ }
20
+ export interface PersonalSyncState {
21
+ lastPulledVersion: number;
22
+ lastPushedVersion: number;
23
+ hashCache: Record<string, string>;
24
+ lastSyncedAt: string | null;
25
+ }
26
+ export interface RemoteSnapshot {
27
+ version: number;
28
+ manifest: PersonalConfigManifest;
29
+ agentId: string;
30
+ message: string | null;
31
+ }
32
+ export interface InitUploadResponse {
33
+ uploadId: string;
34
+ existingBlobs: string[];
35
+ }
36
+ export declare const REDACTED_PLACEHOLDER = "***REDACTED***";
37
+ export declare const EXCLUDED_FILES: Set<string>;
38
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/personal-sync/types.ts"],"names":[],"mappings":"AAAA,oBAAY,oBAAoB;IAC9B,eAAe,oBAAoB;IACnC,YAAY,iBAAiB;IAC7B,cAAc,mBAAmB;IACjC,sBAAsB,2BAA2B;IACjD,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,gBAAgB,qBAAqB;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,sBAAsB,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AAGrD,eAAO,MAAM,cAAc,aAIzB,CAAC"}
@@ -0,0 +1,18 @@
1
+ export var PersonalConfigDomain;
2
+ (function (PersonalConfigDomain) {
3
+ PersonalConfigDomain["CLAUDE_SETTINGS"] = "claude-settings";
4
+ PersonalConfigDomain["CLAUDE_HOOKS"] = "claude-hooks";
5
+ PersonalConfigDomain["CLAUDE_PLUGINS"] = "claude-plugins";
6
+ PersonalConfigDomain["CLAUDE_ENABLED_PLUGINS"] = "claude-enabled-plugins";
7
+ PersonalConfigDomain["CODEX_SETTINGS"] = "codex-settings";
8
+ PersonalConfigDomain["GEMINI_SETTINGS"] = "gemini-settings";
9
+ PersonalConfigDomain["MEMSEARCH_CONFIG"] = "memsearch-config";
10
+ })(PersonalConfigDomain || (PersonalConfigDomain = {}));
11
+ export const REDACTED_PLACEHOLDER = '***REDACTED***';
12
+ // Files that are NEVER synced (contain auth credentials)
13
+ export const EXCLUDED_FILES = new Set([
14
+ '.codex/auth.json',
15
+ '.gemini/oauth_creds.json',
16
+ '.termify/config.json',
17
+ ]);
18
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/personal-sync/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,oBAQX;AARD,WAAY,oBAAoB;IAC9B,2DAAmC,CAAA;IACnC,qDAA6B,CAAA;IAC7B,yDAAiC,CAAA;IACjC,yEAAiD,CAAA;IACjD,yDAAiC,CAAA;IACjC,2DAAmC,CAAA;IACnC,6DAAqC,CAAA;AACvC,CAAC,EARW,oBAAoB,KAApB,oBAAoB,QAQ/B;AAiCD,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAErD,yDAAyD;AACzD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IACpC,kBAAkB;IAClB,0BAA0B;IAC1B,sBAAsB;CACvB,CAAC,CAAC"}