@openacp/cli 2026.331.1 → 2026.331.3
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 +2 -1
- package/dist/cli.js +24987 -270
- package/dist/cli.js.map +1 -1
- package/dist/data/registry-snapshot.json +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +17669 -406
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/adapter-ELG3VRZ3.js +0 -14
- package/dist/adapter-ELG3VRZ3.js.map +0 -1
- package/dist/agent-catalog-UYD26QDK.js +0 -10
- package/dist/agent-catalog-UYD26QDK.js.map +0 -1
- package/dist/agent-dependencies-ED2ZTUHG.js +0 -23
- package/dist/agent-dependencies-ED2ZTUHG.js.map +0 -1
- package/dist/agent-registry-YOGP656W.js +0 -8
- package/dist/agent-registry-YOGP656W.js.map +0 -1
- package/dist/agent-store-5UHZH2XI.js +0 -8
- package/dist/agent-store-5UHZH2XI.js.map +0 -1
- package/dist/api-client-PEMHYL5U.js +0 -13
- package/dist/api-client-PEMHYL5U.js.map +0 -1
- package/dist/api-server-DATG2KBR.js +0 -10
- package/dist/api-server-DATG2KBR.js.map +0 -1
- package/dist/api-server-L5Z7XACW.js +0 -7
- package/dist/api-server-L5Z7XACW.js.map +0 -1
- package/dist/autostart-CUPZMKKC.js +0 -22
- package/dist/autostart-CUPZMKKC.js.map +0 -1
- package/dist/chunk-23SRIVG4.js +0 -50
- package/dist/chunk-23SRIVG4.js.map +0 -1
- package/dist/chunk-2KT6TROD.js +0 -129
- package/dist/chunk-2KT6TROD.js.map +0 -1
- package/dist/chunk-2R5XM3ES.js +0 -154
- package/dist/chunk-2R5XM3ES.js.map +0 -1
- package/dist/chunk-3EWTPOF7.js +0 -51
- package/dist/chunk-3EWTPOF7.js.map +0 -1
- package/dist/chunk-566W6INH.js +0 -83
- package/dist/chunk-566W6INH.js.map +0 -1
- package/dist/chunk-5WGVYX3C.js +0 -55
- package/dist/chunk-5WGVYX3C.js.map +0 -1
- package/dist/chunk-7GXEMMEV.js +0 -44
- package/dist/chunk-7GXEMMEV.js.map +0 -1
- package/dist/chunk-7U6IZIJP.js +0 -186
- package/dist/chunk-7U6IZIJP.js.map +0 -1
- package/dist/chunk-7YIKTRSM.js +0 -105
- package/dist/chunk-7YIKTRSM.js.map +0 -1
- package/dist/chunk-7ZCQF6QM.js +0 -27
- package/dist/chunk-7ZCQF6QM.js.map +0 -1
- package/dist/chunk-AFKX424Q.js +0 -92
- package/dist/chunk-AFKX424Q.js.map +0 -1
- package/dist/chunk-BYCJQPMN.js +0 -543
- package/dist/chunk-BYCJQPMN.js.map +0 -1
- package/dist/chunk-CDAUYTVP.js +0 -41
- package/dist/chunk-CDAUYTVP.js.map +0 -1
- package/dist/chunk-EWVXSTQK.js +0 -6544
- package/dist/chunk-EWVXSTQK.js.map +0 -1
- package/dist/chunk-FNRSWA2K.js +0 -1
- package/dist/chunk-FNRSWA2K.js.map +0 -1
- package/dist/chunk-FPKQYCQS.js +0 -776
- package/dist/chunk-FPKQYCQS.js.map +0 -1
- package/dist/chunk-IZ5UEZF7.js +0 -138
- package/dist/chunk-IZ5UEZF7.js.map +0 -1
- package/dist/chunk-K6UY5M75.js +0 -653
- package/dist/chunk-K6UY5M75.js.map +0 -1
- package/dist/chunk-KGAQW6F4.js +0 -106
- package/dist/chunk-KGAQW6F4.js.map +0 -1
- package/dist/chunk-LGFWH3AE.js +0 -26
- package/dist/chunk-LGFWH3AE.js.map +0 -1
- package/dist/chunk-LRV56K2M.js +0 -4106
- package/dist/chunk-LRV56K2M.js.map +0 -1
- package/dist/chunk-MDJHCCFS.js +0 -485
- package/dist/chunk-MDJHCCFS.js.map +0 -1
- package/dist/chunk-MLF4W5R6.js +0 -101
- package/dist/chunk-MLF4W5R6.js.map +0 -1
- package/dist/chunk-NHD5XDD2.js +0 -686
- package/dist/chunk-NHD5XDD2.js.map +0 -1
- package/dist/chunk-NJX75BLK.js +0 -259
- package/dist/chunk-NJX75BLK.js.map +0 -1
- package/dist/chunk-NOEAJNTK.js +0 -156
- package/dist/chunk-NOEAJNTK.js.map +0 -1
- package/dist/chunk-ON7HB5O7.js +0 -58
- package/dist/chunk-ON7HB5O7.js.map +0 -1
- package/dist/chunk-OSBZXY2W.js +0 -126
- package/dist/chunk-OSBZXY2W.js.map +0 -1
- package/dist/chunk-OYSAN7UX.js +0 -15
- package/dist/chunk-OYSAN7UX.js.map +0 -1
- package/dist/chunk-P3HHJANC.js +0 -209
- package/dist/chunk-P3HHJANC.js.map +0 -1
- package/dist/chunk-R2YLDQLI.js +0 -1115
- package/dist/chunk-R2YLDQLI.js.map +0 -1
- package/dist/chunk-R6KZYF7D.js +0 -231
- package/dist/chunk-R6KZYF7D.js.map +0 -1
- package/dist/chunk-S64CB6J3.js +0 -98
- package/dist/chunk-S64CB6J3.js.map +0 -1
- package/dist/chunk-SSLVNCEA.js +0 -236
- package/dist/chunk-SSLVNCEA.js.map +0 -1
- package/dist/chunk-TGP34LQN.js +0 -681
- package/dist/chunk-TGP34LQN.js.map +0 -1
- package/dist/chunk-VUSCVRJL.js +0 -229
- package/dist/chunk-VUSCVRJL.js.map +0 -1
- package/dist/chunk-W26AUH5B.js +0 -61
- package/dist/chunk-W26AUH5B.js.map +0 -1
- package/dist/chunk-WQCJTU2C.js +0 -84
- package/dist/chunk-WQCJTU2C.js.map +0 -1
- package/dist/chunk-XRJUS6FE.js +0 -53
- package/dist/chunk-XRJUS6FE.js.map +0 -1
- package/dist/chunk-YZCKSNRN.js +0 -453
- package/dist/chunk-YZCKSNRN.js.map +0 -1
- package/dist/chunk-ZIRH6QWW.js +0 -69
- package/dist/chunk-ZIRH6QWW.js.map +0 -1
- package/dist/chunk-ZSLHHQPQ.js +0 -282
- package/dist/chunk-ZSLHHQPQ.js.map +0 -1
- package/dist/config-X4UP7H6R.js +0 -13
- package/dist/config-X4UP7H6R.js.map +0 -1
- package/dist/config-editor-7BENRVG5.js +0 -11
- package/dist/config-editor-7BENRVG5.js.map +0 -1
- package/dist/config-registry-M3FFWEVM.js +0 -18
- package/dist/config-registry-M3FFWEVM.js.map +0 -1
- package/dist/context-FVGCU5TI.js +0 -9
- package/dist/context-FVGCU5TI.js.map +0 -1
- package/dist/core-plugins-JSY2I44L.js +0 -25
- package/dist/core-plugins-JSY2I44L.js.map +0 -1
- package/dist/daemon-UOSRDEXW.js +0 -34
- package/dist/daemon-UOSRDEXW.js.map +0 -1
- package/dist/dev-loader-7P3HZCIA.js +0 -37
- package/dist/dev-loader-7P3HZCIA.js.map +0 -1
- package/dist/doctor-6DLACBR4.js +0 -10
- package/dist/doctor-6DLACBR4.js.map +0 -1
- package/dist/file-service-FQQYME7M.js +0 -8
- package/dist/file-service-FQQYME7M.js.map +0 -1
- package/dist/install-cloudflared-LNS5L5FR.js +0 -33
- package/dist/install-cloudflared-LNS5L5FR.js.map +0 -1
- package/dist/install-context-KZO5FR4D.js +0 -78
- package/dist/install-context-KZO5FR4D.js.map +0 -1
- package/dist/install-jq-SN4IA5K4.js +0 -31
- package/dist/install-jq-SN4IA5K4.js.map +0 -1
- package/dist/instance-context-FLCE7VZ4.js +0 -13
- package/dist/instance-context-FLCE7VZ4.js.map +0 -1
- package/dist/instance-registry-SW5FWKHO.js +0 -7
- package/dist/instance-registry-SW5FWKHO.js.map +0 -1
- package/dist/integrate-JIEZYDOR.js +0 -371
- package/dist/integrate-JIEZYDOR.js.map +0 -1
- package/dist/log-YZ243M5G.js +0 -25
- package/dist/log-YZ243M5G.js.map +0 -1
- package/dist/main-D7M2AKRM.js +0 -697
- package/dist/main-D7M2AKRM.js.map +0 -1
- package/dist/menu-ALFN37IR.js +0 -15
- package/dist/menu-ALFN37IR.js.map +0 -1
- package/dist/notifications-MO23S7S3.js +0 -8
- package/dist/notifications-MO23S7S3.js.map +0 -1
- package/dist/plugin-create-HFKS23JY.js +0 -968
- package/dist/plugin-create-HFKS23JY.js.map +0 -1
- package/dist/plugin-installer-VSTYZSXC.js +0 -9
- package/dist/plugin-installer-VSTYZSXC.js.map +0 -1
- package/dist/plugin-registry-6J3YSFHF.js +0 -7
- package/dist/plugin-registry-6J3YSFHF.js.map +0 -1
- package/dist/plugin-search-MGKAL5JM.js +0 -39
- package/dist/plugin-search-MGKAL5JM.js.map +0 -1
- package/dist/post-upgrade-F4YPMTUT.js +0 -79
- package/dist/post-upgrade-F4YPMTUT.js.map +0 -1
- package/dist/read-text-file-DJBTITIB.js +0 -7
- package/dist/read-text-file-DJBTITIB.js.map +0 -1
- package/dist/registry-client-GTBWLXYU.js +0 -7
- package/dist/registry-client-GTBWLXYU.js.map +0 -1
- package/dist/security-O4XGN2CM.js +0 -8
- package/dist/security-O4XGN2CM.js.map +0 -1
- package/dist/settings-manager-B4UN2LAC.js +0 -7
- package/dist/settings-manager-B4UN2LAC.js.map +0 -1
- package/dist/setup-44WLBIOT.js +0 -989
- package/dist/setup-44WLBIOT.js.map +0 -1
- package/dist/speech-GHTSWDAN.js +0 -9
- package/dist/speech-GHTSWDAN.js.map +0 -1
- package/dist/suggest-RST5VOHB.js +0 -36
- package/dist/suggest-RST5VOHB.js.map +0 -1
- package/dist/telegram-D7ASLVEB.js +0 -7
- package/dist/telegram-D7ASLVEB.js.map +0 -1
- package/dist/tunnel-ALJDPFDQ.js +0 -10
- package/dist/tunnel-ALJDPFDQ.js.map +0 -1
- package/dist/tunnel-service-TBAHDXMF.js +0 -755
- package/dist/tunnel-service-TBAHDXMF.js.map +0 -1
- package/dist/validators-GITLOFXC.js +0 -11
- package/dist/validators-GITLOFXC.js.map +0 -1
- package/dist/version-AXXV6IV2.js +0 -15
- package/dist/version-AXXV6IV2.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/tunnel/tunnel-registry.ts","../../src/plugins/tunnel/providers/cloudflare.ts","../../src/plugins/tunnel/providers/ngrok.ts","../../src/plugins/tunnel/providers/bore.ts","../../src/plugins/tunnel/providers/tailscale.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { createChildLogger } from '../../core/utils/log.js'\nimport type { TunnelProvider } from './provider.js'\nimport { CloudflareTunnelProvider } from './providers/cloudflare.js'\nimport { NgrokTunnelProvider } from './providers/ngrok.js'\nimport { BoreTunnelProvider } from './providers/bore.js'\nimport { TailscaleTunnelProvider } from './providers/tailscale.js'\n\nconst log = createChildLogger({ module: 'tunnel-registry' })\n\nexport const MAX_RETRIES = 5\nconst BASE_RETRY_DELAY_MS = 2_000\n\nexport interface TunnelEntry {\n port: number\n type: 'system' | 'user'\n provider: string\n label?: string\n publicUrl?: string\n sessionId?: string\n status: 'stopped' | 'starting' | 'active' | 'failed'\n retryCount: number\n createdAt: string\n}\n\ninterface PersistedEntry {\n port: number\n type: 'system' | 'user'\n provider: string\n label?: string\n sessionId?: string\n createdAt: string\n}\n\ninterface LiveEntry {\n entry: TunnelEntry\n process: TunnelProvider | null\n spawnPromise: Promise<string> | null\n retryTimer: ReturnType<typeof setTimeout> | null\n}\n\nexport class TunnelRegistry {\n private entries: Map<number, LiveEntry> = new Map()\n private saveTimeout: ReturnType<typeof setTimeout> | null = null\n private maxUserTunnels: number\n private providerOptions: Record<string, unknown>\n private registryPath: string\n private shuttingDown = false\n\n constructor(opts: { maxUserTunnels?: number; providerOptions?: Record<string, unknown>; registryPath?: string } = {}) {\n this.maxUserTunnels = opts.maxUserTunnels ?? 5\n this.providerOptions = opts.providerOptions ?? {}\n this.registryPath = opts.registryPath ?? path.join(os.homedir(), '.openacp', 'tunnels.json')\n }\n\n async add(port: number, opts: {\n type: 'system' | 'user'\n provider: string\n label?: string\n sessionId?: string\n }): Promise<TunnelEntry> {\n // Check if port already registered\n if (this.entries.has(port)) {\n const existing = this.entries.get(port)!\n if (existing.entry.status === 'active' || existing.entry.status === 'starting') {\n throw new Error(`Port ${port} is already tunneled → ${existing.entry.publicUrl || 'starting...'}`)\n }\n // Stopped/failed entry — clean up retry timer and re-add\n if (existing.retryTimer) clearTimeout(existing.retryTimer)\n this.entries.delete(port)\n }\n\n // Check max user tunnels\n if (opts.type === 'user') {\n const userCount = this.list(false).filter(e => e.status === 'active' || e.status === 'starting').length\n if (userCount >= this.maxUserTunnels) {\n throw new Error(`Max user tunnels (${this.maxUserTunnels}) reached. Stop a tunnel first.`)\n }\n }\n\n const entry: TunnelEntry = {\n port,\n type: opts.type,\n provider: opts.provider,\n label: opts.label,\n sessionId: opts.sessionId,\n status: 'starting',\n retryCount: 0,\n createdAt: new Date().toISOString(),\n }\n\n const provider = this.createProvider(opts.provider)\n\n // Wire up post-establishment crash detection with auto-retry\n provider.onExit((code) => {\n if (this.shuttingDown) return\n const live = this.entries.get(port)\n if (!live) return\n\n live.entry.status = 'failed'\n live.process = null\n this.scheduleSave()\n\n if (live.entry.retryCount < MAX_RETRIES) {\n const delay = BASE_RETRY_DELAY_MS * Math.pow(2, live.entry.retryCount)\n log.warn({ port, code, retry: live.entry.retryCount + 1, maxRetries: MAX_RETRIES, delayMs: delay },\n 'Tunnel crashed, scheduling retry')\n live.retryTimer = setTimeout(() => this.retry(port, opts), delay)\n } else {\n log.error({ port, code }, `Tunnel crashed and exhausted all ${MAX_RETRIES} retries`)\n }\n })\n\n const spawnPromise = provider.start(port).then(url => {\n entry.publicUrl = url\n entry.status = 'active'\n log.info({ port, url, label: opts.label }, 'Tunnel active')\n this.scheduleSave()\n return url\n }).catch(err => {\n entry.status = 'failed'\n log.error({ port, err: (err as Error).message }, 'Tunnel failed to start')\n this.scheduleSave()\n throw err\n })\n\n this.entries.set(port, { entry, process: provider, spawnPromise, retryTimer: null })\n this.scheduleSave()\n\n // Await spawn — caller gets the URL or error\n await spawnPromise\n return entry\n }\n\n private async retry(port: number, opts: {\n type: 'system' | 'user'\n provider: string\n label?: string\n sessionId?: string\n }): Promise<void> {\n if (this.shuttingDown) return\n const live = this.entries.get(port)\n if (!live) return\n\n const retryCount = live.entry.retryCount + 1\n log.info({ port, retry: retryCount, maxRetries: MAX_RETRIES }, 'Retrying tunnel')\n\n // Remove old entry so add() doesn't reject\n if (live.retryTimer) clearTimeout(live.retryTimer)\n this.entries.delete(port)\n\n try {\n const entry = await this.add(port, opts)\n entry.retryCount = retryCount\n } catch (err) {\n log.error({ port, err: (err as Error).message, retry: retryCount }, 'Tunnel retry failed')\n\n // Re-insert as failed with incremented retry count for next onExit cycle\n const failedEntry: TunnelEntry = {\n port,\n type: opts.type,\n provider: opts.provider,\n label: opts.label,\n sessionId: opts.sessionId,\n status: 'failed',\n retryCount,\n createdAt: live.entry.createdAt,\n }\n\n if (retryCount < MAX_RETRIES) {\n const delay = BASE_RETRY_DELAY_MS * Math.pow(2, retryCount)\n const retryTimer = setTimeout(() => this.retry(port, opts), delay)\n this.entries.set(port, { entry: failedEntry, process: null, spawnPromise: null, retryTimer })\n log.warn({ port, retry: retryCount + 1, delayMs: delay }, 'Scheduling next retry')\n } else {\n this.entries.set(port, { entry: failedEntry, process: null, spawnPromise: null, retryTimer: null })\n log.error({ port }, `Tunnel exhausted all ${MAX_RETRIES} retries`)\n }\n this.scheduleSave()\n }\n }\n\n async stop(port: number): Promise<void> {\n const live = this.entries.get(port)\n if (!live) return\n\n if (live.entry.type === 'system') {\n throw new Error('Cannot stop system tunnel')\n }\n\n // Cancel any pending retry\n if (live.retryTimer) clearTimeout(live.retryTimer)\n\n // Wait for spawn to finish if still starting\n if (live.spawnPromise) {\n try { await live.spawnPromise } catch { /* ignore spawn error */ }\n }\n\n if (live.process) {\n await live.process.stop()\n }\n\n this.entries.delete(port)\n this.scheduleSave()\n log.info({ port, label: live.entry.label }, 'Tunnel stopped')\n }\n\n async stopBySession(sessionId: string): Promise<TunnelEntry[]> {\n const stopped: TunnelEntry[] = []\n const toStop = this.getBySession(sessionId)\n for (const entry of toStop) {\n try {\n await this.stop(entry.port)\n stopped.push(entry)\n } catch { /* ignore */ }\n }\n return stopped\n }\n\n async stopAllUser(): Promise<void> {\n const userEntries = this.list(false)\n for (const entry of userEntries) {\n try { await this.stop(entry.port) } catch { /* ignore */ }\n }\n }\n\n async shutdown(): Promise<void> {\n this.shuttingDown = true\n\n for (const [, live] of this.entries) {\n if (live.retryTimer) clearTimeout(live.retryTimer)\n if (live.spawnPromise) {\n try { await live.spawnPromise } catch { /* ignore */ }\n }\n if (live.process) {\n await live.process.stop()\n }\n }\n this.entries.clear()\n this.scheduleSave()\n }\n\n list(includeSystem = false): TunnelEntry[] {\n const entries = Array.from(this.entries.values()).map(l => l.entry)\n if (includeSystem) return entries\n return entries.filter(e => e.type === 'user')\n }\n\n get(port: number): TunnelEntry | null {\n return this.entries.get(port)?.entry ?? null\n }\n\n getBySession(sessionId: string): TunnelEntry[] {\n return this.list(false).filter(e => e.sessionId === sessionId)\n }\n\n getSystemEntry(): TunnelEntry | null {\n for (const live of this.entries.values()) {\n if (live.entry.type === 'system') return live.entry\n }\n return null\n }\n\n async restore(): Promise<void> {\n if (!fs.existsSync(this.registryPath)) return\n\n try {\n const raw = JSON.parse(fs.readFileSync(this.registryPath, 'utf-8')) as PersistedEntry[]\n log.info({ count: raw.length }, 'Restoring tunnels')\n\n // Only restore user tunnels — system tunnel is registered separately by TunnelService.start()\n const userEntries = raw.filter(e => e.type === 'user')\n for (const persisted of userEntries) {\n try {\n await this.add(persisted.port, {\n type: persisted.type,\n provider: persisted.provider,\n label: persisted.label,\n sessionId: persisted.sessionId,\n })\n } catch (err) {\n log.warn({ port: persisted.port, err: (err as Error).message }, 'Failed to restore tunnel')\n }\n }\n } catch (err) {\n log.warn({ err: (err as Error).message }, 'Failed to read tunnels.json')\n }\n }\n\n private createProvider(name: string): TunnelProvider {\n switch (name) {\n case 'cloudflare':\n return new CloudflareTunnelProvider(this.providerOptions)\n case 'ngrok':\n return new NgrokTunnelProvider(this.providerOptions)\n case 'bore':\n return new BoreTunnelProvider(this.providerOptions)\n case 'tailscale':\n return new TailscaleTunnelProvider(this.providerOptions)\n default:\n log.warn({ provider: name }, 'Unknown provider, falling back to cloudflare')\n return new CloudflareTunnelProvider(this.providerOptions)\n }\n }\n\n private scheduleSave(): void {\n if (this.saveTimeout) clearTimeout(this.saveTimeout)\n this.saveTimeout = setTimeout(() => this.save(), 2000)\n }\n\n private save(): void {\n const data: PersistedEntry[] = Array.from(this.entries.values()).map(l => ({\n port: l.entry.port,\n type: l.entry.type,\n provider: l.entry.provider,\n label: l.entry.label,\n sessionId: l.entry.sessionId,\n createdAt: l.entry.createdAt,\n }))\n\n try {\n const dir = path.dirname(this.registryPath)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(this.registryPath, JSON.stringify(data, null, 2))\n } catch (err) {\n log.error({ err: (err as Error).message }, 'Failed to save tunnels.json')\n }\n }\n\n flush(): void {\n if (this.saveTimeout) {\n clearTimeout(this.saveTimeout)\n this.saveTimeout = null\n }\n this.save()\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { createChildLogger } from '../../../core/utils/log.js'\nimport { commandExists } from '../../../core/agents/agent-dependencies.js'\nimport type { TunnelProvider } from '../provider.js'\n\nconst log = createChildLogger({ module: 'cloudflare-tunnel' })\n\nconst SIGKILL_TIMEOUT_MS = 5_000\n\nexport class CloudflareTunnelProvider implements TunnelProvider {\n private child: ChildProcess | null = null\n private publicUrl = ''\n private options: Record<string, unknown>\n private binDir: string\n private exitCallback: ((code: number | null) => void) | null = null\n\n constructor(options: Record<string, unknown> = {}, binDir?: string) {\n this.options = options\n this.binDir = binDir ?? path.join(os.homedir(), '.openacp', 'bin')\n }\n\n onExit(callback: (code: number | null) => void): void {\n this.exitCallback = callback\n }\n\n async start(localPort: number): Promise<string> {\n // Find binary — post-upgrade should have installed it, but fallback to ensureCloudflared() as safety net\n let binaryPath = this.findBinary()\n if (!binaryPath) {\n log.warn('cloudflared not found locally, attempting auto-install as fallback...')\n try {\n const { ensureCloudflared } = await import('./install-cloudflared.js')\n binaryPath = await ensureCloudflared()\n } catch (err) {\n throw new Error(`cloudflared is not installed and auto-install failed: ${(err as Error).message}`)\n }\n }\n\n const args = ['tunnel', '--url', `http://localhost:${localPort}`]\n if (this.options.domain) {\n args.push('--hostname', String(this.options.domain))\n }\n\n return new Promise<string>((resolve, reject) => {\n let settled = false\n const settle = (fn: () => void) => { if (!settled) { settled = true; fn() } }\n\n const timeout = setTimeout(() => {\n this.stop()\n settle(() => reject(new Error('Cloudflare tunnel timed out after 30s')))\n }, 30_000)\n\n try {\n this.child = spawn(binaryPath, args, { stdio: ['ignore', 'pipe', 'pipe'] })\n } catch {\n clearTimeout(timeout)\n settle(() => reject(new Error(`Failed to start cloudflared at ${binaryPath}`)))\n return\n }\n\n const urlPattern = /https:\\/\\/[a-zA-Z0-9-]+\\.trycloudflare\\.com/\n\n const onData = (data: Buffer) => {\n const line = data.toString()\n log.debug(line.trim())\n const match = line.match(urlPattern)\n if (match) {\n clearTimeout(timeout)\n this.publicUrl = match[0]\n log.info({ url: this.publicUrl }, 'Cloudflare tunnel ready')\n settle(() => resolve(this.publicUrl))\n }\n }\n\n this.child.stdout?.on('data', onData)\n this.child.stderr?.on('data', onData)\n\n this.child.on('error', (err) => {\n clearTimeout(timeout)\n settle(() => reject(new Error(`cloudflared failed to start: ${err.message}`)))\n })\n\n this.child.on('exit', (code) => {\n if (!this.publicUrl) {\n clearTimeout(timeout)\n settle(() => reject(new Error(`cloudflared exited with code ${code} before establishing tunnel`)))\n } else {\n // Post-establishment crash\n log.error({ code }, 'cloudflared exited unexpectedly after establishment')\n this.child = null\n this.exitCallback?.(code)\n }\n })\n })\n }\n\n async stop(): Promise<void> {\n const child = this.child\n if (!child) return\n this.child = null\n\n child.kill('SIGTERM')\n\n // Wait for graceful exit, then SIGKILL if still alive\n const exited = await Promise.race([\n new Promise<boolean>((resolve) => child.on('exit', () => resolve(true))),\n new Promise<boolean>((resolve) => setTimeout(() => resolve(false), SIGKILL_TIMEOUT_MS)),\n ])\n\n if (!exited) {\n log.warn('cloudflared did not exit after SIGTERM, sending SIGKILL')\n child.kill('SIGKILL')\n }\n\n log.info('Cloudflare tunnel stopped')\n }\n\n getPublicUrl(): string {\n return this.publicUrl\n }\n\n private findBinary(): string | null {\n // 1. Check PATH first (respects user's system install)\n if (commandExists('cloudflared')) return 'cloudflared'\n\n // 2. Check binDir (installed by post-upgrade)\n const binPath = path.join(this.binDir, 'cloudflared')\n if (fs.existsSync(binPath)) return binPath\n\n // 3. Not found\n return null\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport { createChildLogger } from '../../../core/utils/log.js'\nimport type { TunnelProvider } from '../provider.js'\n\nconst log = createChildLogger({ module: 'ngrok-tunnel' })\n\nconst SIGKILL_TIMEOUT_MS = 5_000\n\nexport class NgrokTunnelProvider implements TunnelProvider {\n private child: ChildProcess | null = null\n private publicUrl = ''\n private options: Record<string, unknown>\n private exitCallback: ((code: number | null) => void) | null = null\n\n constructor(options: Record<string, unknown> = {}) {\n this.options = options\n }\n\n onExit(callback: (code: number | null) => void): void {\n this.exitCallback = callback\n }\n\n async start(localPort: number): Promise<string> {\n const args = ['http', String(localPort), '--log', 'stdout', '--log-format', 'json']\n if (this.options.authtoken) {\n args.push('--authtoken', String(this.options.authtoken))\n }\n if (this.options.domain) {\n args.push('--domain', String(this.options.domain))\n }\n if (this.options.region) {\n args.push('--region', String(this.options.region))\n }\n\n return new Promise<string>((resolve, reject) => {\n let settled = false\n const settle = (fn: () => void) => { if (!settled) { settled = true; fn() } }\n\n const timeout = setTimeout(() => {\n this.stop()\n settle(() => reject(new Error('ngrok tunnel timed out after 30s. Is ngrok installed?')))\n }, 30_000)\n\n try {\n this.child = spawn('ngrok', args, { stdio: ['ignore', 'pipe', 'pipe'] })\n } catch {\n clearTimeout(timeout)\n settle(() => reject(new Error(\n 'Failed to start ngrok. Install it from https://ngrok.com/download'\n )))\n return\n }\n\n // Match both v2 (*.ngrok.io) and v3 (*.ngrok-free.app, *.ngrok.app) domains\n const urlPattern = /https:\\/\\/[a-zA-Z0-9-]+\\.(?:ngrok(?:-free)?\\.app|ngrok\\.io)/\n\n const onData = (data: Buffer) => {\n const line = data.toString()\n log.debug(line.trim())\n const match = line.match(urlPattern)\n if (match) {\n clearTimeout(timeout)\n this.publicUrl = match[0]\n log.info({ url: this.publicUrl }, 'ngrok tunnel ready')\n settle(() => resolve(this.publicUrl))\n }\n }\n\n this.child.stdout?.on('data', onData)\n this.child.stderr?.on('data', onData)\n\n this.child.on('error', (err) => {\n clearTimeout(timeout)\n settle(() => reject(new Error(\n `ngrok failed to start: ${err.message}. Install it from https://ngrok.com/download`\n )))\n })\n\n this.child.on('exit', (code) => {\n if (!this.publicUrl) {\n clearTimeout(timeout)\n settle(() => reject(new Error(`ngrok exited with code ${code} before establishing tunnel`)))\n } else {\n log.error({ code }, 'ngrok exited unexpectedly after establishment')\n this.child = null\n this.exitCallback?.(code)\n }\n })\n })\n }\n\n async stop(): Promise<void> {\n const child = this.child\n if (!child) return\n this.child = null\n\n child.kill('SIGTERM')\n\n const exited = await Promise.race([\n new Promise<boolean>((resolve) => child.on('exit', () => resolve(true))),\n new Promise<boolean>((resolve) => setTimeout(() => resolve(false), SIGKILL_TIMEOUT_MS)),\n ])\n\n if (!exited) {\n log.warn('ngrok did not exit after SIGTERM, sending SIGKILL')\n child.kill('SIGKILL')\n }\n\n log.info('ngrok tunnel stopped')\n }\n\n getPublicUrl(): string {\n return this.publicUrl\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport { createChildLogger } from '../../../core/utils/log.js'\nimport type { TunnelProvider } from '../provider.js'\n\nconst log = createChildLogger({ module: 'bore-tunnel' })\n\nconst SIGKILL_TIMEOUT_MS = 5_000\n\nexport class BoreTunnelProvider implements TunnelProvider {\n private child: ChildProcess | null = null\n private publicUrl = ''\n private options: Record<string, unknown>\n private exitCallback: ((code: number | null) => void) | null = null\n\n constructor(options: Record<string, unknown> = {}) {\n this.options = options\n }\n\n onExit(callback: (code: number | null) => void): void {\n this.exitCallback = callback\n }\n\n async start(localPort: number): Promise<string> {\n const server = String(this.options.server || 'bore.pub')\n const args = ['local', String(localPort), '--to', server]\n if (this.options.port) {\n args.push('--port', String(this.options.port))\n }\n if (this.options.secret) {\n args.push('--secret', String(this.options.secret))\n }\n\n return new Promise<string>((resolve, reject) => {\n let settled = false\n const settle = (fn: () => void) => { if (!settled) { settled = true; fn() } }\n\n const timeout = setTimeout(() => {\n this.stop()\n settle(() => reject(new Error('Bore tunnel timed out after 30s. Is bore installed?')))\n }, 30_000)\n\n try {\n this.child = spawn('bore', args, { stdio: ['ignore', 'pipe', 'pipe'] })\n } catch {\n clearTimeout(timeout)\n settle(() => reject(new Error(\n 'Failed to start bore. Install it from https://github.com/ekzhang/bore'\n )))\n return\n }\n\n const urlPattern = /listening at ([^\\s]+):(\\d+)/\n\n const onData = (data: Buffer) => {\n const line = data.toString()\n log.debug(line.trim())\n const match = line.match(urlPattern)\n if (match) {\n clearTimeout(timeout)\n this.publicUrl = `http://${match[1]}:${match[2]}`\n log.info({ url: this.publicUrl }, 'Bore tunnel ready')\n settle(() => resolve(this.publicUrl))\n }\n }\n\n this.child.stdout?.on('data', onData)\n this.child.stderr?.on('data', onData)\n\n this.child.on('error', (err) => {\n clearTimeout(timeout)\n settle(() => reject(new Error(\n `bore failed to start: ${err.message}. Install it from https://github.com/ekzhang/bore`\n )))\n })\n\n this.child.on('exit', (code) => {\n if (!this.publicUrl) {\n clearTimeout(timeout)\n settle(() => reject(new Error(`bore exited with code ${code} before establishing tunnel`)))\n } else {\n log.error({ code }, 'bore exited unexpectedly after establishment')\n this.child = null\n this.exitCallback?.(code)\n }\n })\n })\n }\n\n async stop(): Promise<void> {\n const child = this.child\n if (!child) return\n this.child = null\n\n child.kill('SIGTERM')\n\n const exited = await Promise.race([\n new Promise<boolean>((resolve) => child.on('exit', () => resolve(true))),\n new Promise<boolean>((resolve) => setTimeout(() => resolve(false), SIGKILL_TIMEOUT_MS)),\n ])\n\n if (!exited) {\n log.warn('bore did not exit after SIGTERM, sending SIGKILL')\n child.kill('SIGKILL')\n }\n\n log.info('Bore tunnel stopped')\n }\n\n getPublicUrl(): string {\n return this.publicUrl\n }\n}\n","import { spawn, execSync, type ChildProcess } from 'node:child_process'\nimport { createChildLogger } from '../../../core/utils/log.js'\nimport type { TunnelProvider } from '../provider.js'\n\nconst log = createChildLogger({ module: 'tailscale-tunnel' })\n\nconst SIGKILL_TIMEOUT_MS = 5_000\n\nexport class TailscaleTunnelProvider implements TunnelProvider {\n private child: ChildProcess | null = null\n private publicUrl = ''\n private options: Record<string, unknown>\n private exitCallback: ((code: number | null) => void) | null = null\n\n constructor(options: Record<string, unknown> = {}) {\n this.options = options\n }\n\n onExit(callback: (code: number | null) => void): void {\n this.exitCallback = callback\n }\n\n async start(localPort: number): Promise<string> {\n let hostname = ''\n try {\n const statusJson = execSync('tailscale status --json', { encoding: 'utf-8', timeout: 10_000 })\n const status = JSON.parse(statusJson)\n hostname = String(status.Self.DNSName).replace(/\\.$/, '')\n log.debug({ hostname }, 'Resolved Tailscale hostname')\n } catch (err) {\n log.warn('Failed to resolve Tailscale hostname via status --json')\n }\n\n const args = ['funnel', String(localPort)]\n if (this.options.bg) {\n args.push('--bg')\n }\n\n return new Promise<string>((resolve, reject) => {\n let settled = false\n const settle = (fn: () => void) => { if (!settled) { settled = true; fn() } }\n\n const timeout = setTimeout(() => {\n this.stop()\n settle(() => reject(new Error('Tailscale funnel timed out after 30s. Is tailscale installed?')))\n }, 30_000)\n\n try {\n this.child = spawn('tailscale', args, { stdio: ['ignore', 'pipe', 'pipe'] })\n } catch {\n clearTimeout(timeout)\n settle(() => reject(new Error(\n 'Failed to start tailscale. Install it from https://tailscale.com/download'\n )))\n return\n }\n\n // Match only Tailscale funnel URLs (*.ts.net pattern)\n const urlPattern = /https:\\/\\/[a-zA-Z0-9-]+\\.[a-zA-Z0-9-]+\\.ts\\.net/\n\n const onData = (data: Buffer) => {\n const line = data.toString()\n log.debug(line.trim())\n const match = line.match(urlPattern)\n if (match) {\n clearTimeout(timeout)\n this.publicUrl = match[0]\n log.info({ url: this.publicUrl }, 'Tailscale funnel ready')\n settle(() => resolve(this.publicUrl))\n }\n }\n\n this.child.stdout?.on('data', onData)\n this.child.stderr?.on('data', onData)\n\n this.child.on('error', (err) => {\n clearTimeout(timeout)\n settle(() => reject(new Error(\n `tailscale failed to start: ${err.message}. Install it from https://tailscale.com/download`\n )))\n })\n\n this.child.on('exit', (code) => {\n if (!this.publicUrl) {\n clearTimeout(timeout)\n if (hostname) {\n // Tailscale funnel may exit immediately after configuring — construct URL with port\n this.publicUrl = `https://${hostname}:${localPort}`\n this.child = null // process is done; prevent stop() from sending SIGTERM to dead process\n log.info({ url: this.publicUrl }, 'Tailscale funnel ready (constructed from hostname)')\n settle(() => resolve(this.publicUrl))\n } else {\n settle(() => reject(new Error(`tailscale exited with code ${code} before establishing funnel`)))\n }\n } else {\n log.error({ code }, 'tailscale exited unexpectedly after establishment')\n this.child = null\n this.exitCallback?.(code)\n }\n })\n })\n }\n\n async stop(): Promise<void> {\n const child = this.child\n if (!child) return\n this.child = null\n\n child.kill('SIGTERM')\n\n const exited = await Promise.race([\n new Promise<boolean>((resolve) => child.on('exit', () => resolve(true))),\n new Promise<boolean>((resolve) => setTimeout(() => resolve(false), SIGKILL_TIMEOUT_MS)),\n ])\n\n if (!exited) {\n log.warn('tailscale did not exit after SIGTERM, sending SIGKILL')\n child.kill('SIGKILL')\n }\n\n log.info('Tailscale funnel stopped')\n }\n\n getPublicUrl(): string {\n return this.publicUrl\n }\n}\n"],"mappings":"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","names":["fs","path","os","spawn","log","SIGKILL_TIMEOUT_MS","spawn","spawn","log","SIGKILL_TIMEOUT_MS","spawn","spawn","log","SIGKILL_TIMEOUT_MS","spawn","log","path","os","fs"]}
|
package/dist/chunk-NJX75BLK.js
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
// src/plugins/context/context-provider.ts
|
|
2
|
-
var DEFAULT_MAX_TOKENS = 3e4;
|
|
3
|
-
var TOKENS_PER_TURN_ESTIMATE = 400;
|
|
4
|
-
|
|
5
|
-
// src/plugins/context/entire/checkpoint-reader.ts
|
|
6
|
-
import { execFileSync } from "child_process";
|
|
7
|
-
var ENTIRE_BRANCH = "origin/entire/checkpoints/v1";
|
|
8
|
-
var CHECKPOINT_ID_RE = /^[0-9a-f]{12}$/;
|
|
9
|
-
var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
10
|
-
var CheckpointReader = class _CheckpointReader {
|
|
11
|
-
constructor(repoPath) {
|
|
12
|
-
this.repoPath = repoPath;
|
|
13
|
-
}
|
|
14
|
-
// ─── Git execution ───────────────────────────────────────────────────────────
|
|
15
|
-
/**
|
|
16
|
-
* Run a git command in the repo directory.
|
|
17
|
-
* Returns trimmed stdout on success, empty string on failure.
|
|
18
|
-
*/
|
|
19
|
-
git(...args) {
|
|
20
|
-
try {
|
|
21
|
-
return execFileSync("git", ["-C", this.repoPath, ...args], {
|
|
22
|
-
encoding: "utf-8"
|
|
23
|
-
}).trim();
|
|
24
|
-
} catch {
|
|
25
|
-
return "";
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
// ─── Static helpers ──────────────────────────────────────────────────────────
|
|
29
|
-
/**
|
|
30
|
-
* Convert a 12-char checkpoint ID to its shard path: "f634acf05138" → "f6/34acf05138"
|
|
31
|
-
*/
|
|
32
|
-
static shardPath(cpId) {
|
|
33
|
-
return `${cpId.slice(0, 2)}/${cpId.slice(2)}`;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Returns true when value looks like a 12-char lowercase hex checkpoint ID.
|
|
37
|
-
*/
|
|
38
|
-
static isCheckpointId(value) {
|
|
39
|
-
return CHECKPOINT_ID_RE.test(value);
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Returns true when value looks like a UUID (session ID).
|
|
43
|
-
*/
|
|
44
|
-
static isSessionId(value) {
|
|
45
|
-
return SESSION_ID_RE.test(value);
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Parse checkpoint-level metadata JSON. Returns null on error.
|
|
49
|
-
*/
|
|
50
|
-
static parseCheckpointMeta(json) {
|
|
51
|
-
try {
|
|
52
|
-
const parsed = JSON.parse(json);
|
|
53
|
-
if (!parsed || typeof parsed !== "object") return null;
|
|
54
|
-
if (!Array.isArray(parsed.sessions)) return null;
|
|
55
|
-
return parsed;
|
|
56
|
-
} catch {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Extract Entire-Checkpoint trailer IDs from `git log --format="%H|%(trailers:...)"` output.
|
|
62
|
-
* Each line is: `<hash>|<trailer_value_or_empty>`. Returns only non-empty trailer values.
|
|
63
|
-
* Uses the last pipe on each line to locate the trailer value, to be robust against
|
|
64
|
-
* subject lines that contain pipes.
|
|
65
|
-
*/
|
|
66
|
-
static parseCheckpointTrailers(output) {
|
|
67
|
-
const ids = [];
|
|
68
|
-
for (const line of output.split("\n")) {
|
|
69
|
-
const pipe = line.lastIndexOf("|");
|
|
70
|
-
if (pipe === -1) continue;
|
|
71
|
-
const trailerId = line.slice(pipe + 1).trim();
|
|
72
|
-
if (trailerId) ids.push(trailerId);
|
|
73
|
-
}
|
|
74
|
-
return ids;
|
|
75
|
-
}
|
|
76
|
-
// ─── Branch check ────────────────────────────────────────────────────────────
|
|
77
|
-
async hasEntireBranch() {
|
|
78
|
-
const out = this.git("branch", "-r");
|
|
79
|
-
return out.includes("entire/checkpoints/v1");
|
|
80
|
-
}
|
|
81
|
-
// ─── Core session fetching ───────────────────────────────────────────────────
|
|
82
|
-
listAllCheckpointIds() {
|
|
83
|
-
const out = this.git(
|
|
84
|
-
"ls-tree",
|
|
85
|
-
"-r",
|
|
86
|
-
ENTIRE_BRANCH,
|
|
87
|
-
"--name-only"
|
|
88
|
-
);
|
|
89
|
-
if (!out) return [];
|
|
90
|
-
const ids = /* @__PURE__ */ new Set();
|
|
91
|
-
for (const file of out.split("\n")) {
|
|
92
|
-
const parts = file.split("/");
|
|
93
|
-
if (parts.length === 3 && parts[2] === "metadata.json") {
|
|
94
|
-
ids.add(parts[0] + parts[1]);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return [...ids];
|
|
98
|
-
}
|
|
99
|
-
fetchCheckpointMeta(cpId) {
|
|
100
|
-
const shard = _CheckpointReader.shardPath(cpId);
|
|
101
|
-
const raw = this.git("show", `${ENTIRE_BRANCH}:${shard}/metadata.json`);
|
|
102
|
-
if (!raw) return null;
|
|
103
|
-
return _CheckpointReader.parseCheckpointMeta(raw);
|
|
104
|
-
}
|
|
105
|
-
fetchSessionMeta(metaPath) {
|
|
106
|
-
const normalized = metaPath.startsWith("/") ? metaPath.slice(1) : metaPath;
|
|
107
|
-
const raw = this.git("show", `${ENTIRE_BRANCH}:${normalized}`);
|
|
108
|
-
if (!raw) return {};
|
|
109
|
-
try {
|
|
110
|
-
return JSON.parse(raw);
|
|
111
|
-
} catch {
|
|
112
|
-
return {};
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Build SessionInfo[] from a single checkpoint's metadata.
|
|
117
|
-
*/
|
|
118
|
-
buildSessionsForCheckpoint(cpId, cpMeta) {
|
|
119
|
-
const sessions = [];
|
|
120
|
-
for (let idx = 0; idx < cpMeta.sessions.length; idx++) {
|
|
121
|
-
const sess = cpMeta.sessions[idx];
|
|
122
|
-
const transcriptPath = (sess.transcript ?? "").replace(/^\//, "");
|
|
123
|
-
const metaPath = sess.metadata ?? "";
|
|
124
|
-
const smeta = this.fetchSessionMeta(metaPath);
|
|
125
|
-
const createdAt = smeta.created_at ?? "";
|
|
126
|
-
sessions.push({
|
|
127
|
-
checkpointId: cpId,
|
|
128
|
-
sessionIndex: String(idx),
|
|
129
|
-
transcriptPath,
|
|
130
|
-
createdAt,
|
|
131
|
-
endedAt: createdAt,
|
|
132
|
-
// will be filled from JSONL by conversation builder
|
|
133
|
-
branch: smeta.branch ?? cpMeta.branch ?? "",
|
|
134
|
-
agent: smeta.agent ?? "",
|
|
135
|
-
turnCount: smeta.session_metrics?.turn_count ?? 0,
|
|
136
|
-
filesTouched: smeta.files_touched ?? cpMeta.files_touched ?? [],
|
|
137
|
-
sessionId: smeta.session_id ?? ""
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
return sessions;
|
|
141
|
-
}
|
|
142
|
-
getSessionsForCheckpoint(cpId) {
|
|
143
|
-
const meta = this.fetchCheckpointMeta(cpId);
|
|
144
|
-
if (!meta) return [];
|
|
145
|
-
return this.buildSessionsForCheckpoint(cpId, meta);
|
|
146
|
-
}
|
|
147
|
-
// ─── Public resolvers ────────────────────────────────────────────────────────
|
|
148
|
-
/**
|
|
149
|
-
* All sessions recorded on a given branch, sorted by createdAt ascending.
|
|
150
|
-
*/
|
|
151
|
-
async resolveByBranch(branchName) {
|
|
152
|
-
const cpIds = this.listAllCheckpointIds();
|
|
153
|
-
const sessions = [];
|
|
154
|
-
for (const cpId of cpIds) {
|
|
155
|
-
const meta = this.fetchCheckpointMeta(cpId);
|
|
156
|
-
if (!meta) continue;
|
|
157
|
-
if (meta.branch !== branchName) continue;
|
|
158
|
-
sessions.push(...this.buildSessionsForCheckpoint(cpId, meta));
|
|
159
|
-
}
|
|
160
|
-
sessions.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
161
|
-
return sessions;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Sessions linked to a specific commit via the Entire-Checkpoint git trailer.
|
|
165
|
-
*/
|
|
166
|
-
async resolveByCommit(commitHash) {
|
|
167
|
-
const fullHash = this.git("rev-parse", commitHash);
|
|
168
|
-
if (!fullHash) return [];
|
|
169
|
-
const cpId = this.git(
|
|
170
|
-
"log",
|
|
171
|
-
"-1",
|
|
172
|
-
"--format=%(trailers:key=Entire-Checkpoint,valueonly)",
|
|
173
|
-
fullHash
|
|
174
|
-
);
|
|
175
|
-
if (!cpId) return [];
|
|
176
|
-
return this.getSessionsForCheckpoint(cpId.trim());
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* All sessions from a merged PR (by number or GitHub URL).
|
|
180
|
-
*/
|
|
181
|
-
async resolveByPr(prInput) {
|
|
182
|
-
let prNumber;
|
|
183
|
-
if (/^\d+$/.test(prInput)) {
|
|
184
|
-
prNumber = prInput;
|
|
185
|
-
} else {
|
|
186
|
-
const m = /\/pull\/(\d+)/.exec(prInput);
|
|
187
|
-
if (!m) return [];
|
|
188
|
-
prNumber = m[1];
|
|
189
|
-
}
|
|
190
|
-
const mergeOut = this.git(
|
|
191
|
-
"log",
|
|
192
|
-
"--all",
|
|
193
|
-
"--oneline",
|
|
194
|
-
"--grep",
|
|
195
|
-
`Merge pull request #${prNumber}`
|
|
196
|
-
);
|
|
197
|
-
if (!mergeOut) return [];
|
|
198
|
-
const mergeCommit = mergeOut.split("\n")[0].split(" ")[0];
|
|
199
|
-
const logOut = this.git(
|
|
200
|
-
"log",
|
|
201
|
-
"--format=%H|%(trailers:key=Entire-Checkpoint,valueonly)",
|
|
202
|
-
`${mergeCommit}^2`,
|
|
203
|
-
"--not",
|
|
204
|
-
`${mergeCommit}^1`
|
|
205
|
-
);
|
|
206
|
-
if (!logOut) return [];
|
|
207
|
-
const cpIds = _CheckpointReader.parseCheckpointTrailers(logOut);
|
|
208
|
-
const sessions = [];
|
|
209
|
-
for (const cpId of cpIds) {
|
|
210
|
-
sessions.push(...this.getSessionsForCheckpoint(cpId));
|
|
211
|
-
}
|
|
212
|
-
sessions.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
213
|
-
return sessions;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Sessions matching a specific checkpoint ID.
|
|
217
|
-
*/
|
|
218
|
-
async resolveByCheckpoint(checkpointId) {
|
|
219
|
-
return this.getSessionsForCheckpoint(checkpointId);
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Find a session by its UUID.
|
|
223
|
-
*/
|
|
224
|
-
async resolveBySessionId(sessionId) {
|
|
225
|
-
const cpIds = this.listAllCheckpointIds();
|
|
226
|
-
for (const cpId of cpIds) {
|
|
227
|
-
const sessions = this.getSessionsForCheckpoint(cpId);
|
|
228
|
-
const match = sessions.find((s) => s.sessionId === sessionId);
|
|
229
|
-
if (match) return [match];
|
|
230
|
-
}
|
|
231
|
-
return [];
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Latest N sessions across all checkpoints, sorted by createdAt descending.
|
|
235
|
-
*/
|
|
236
|
-
async resolveLatest(count) {
|
|
237
|
-
const cpIds = this.listAllCheckpointIds();
|
|
238
|
-
const all = [];
|
|
239
|
-
for (const cpId of cpIds) {
|
|
240
|
-
all.push(...this.getSessionsForCheckpoint(cpId));
|
|
241
|
-
}
|
|
242
|
-
all.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
243
|
-
return all.slice(0, count);
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Read the full JSONL transcript content from the entire branch.
|
|
247
|
-
*/
|
|
248
|
-
getTranscript(transcriptPath) {
|
|
249
|
-
const normalized = transcriptPath.startsWith("/") ? transcriptPath.slice(1) : transcriptPath;
|
|
250
|
-
return this.git("show", `${ENTIRE_BRANCH}:${normalized}`);
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
export {
|
|
255
|
-
DEFAULT_MAX_TOKENS,
|
|
256
|
-
TOKENS_PER_TURN_ESTIMATE,
|
|
257
|
-
CheckpointReader
|
|
258
|
-
};
|
|
259
|
-
//# sourceMappingURL=chunk-NJX75BLK.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/context/context-provider.ts","../../src/plugins/context/entire/checkpoint-reader.ts"],"sourcesContent":["// NOTE: This interface is designed around Entire as the first provider.\n// It may evolve when additional providers (Cursor history, Zed, etc.) are added.\n// Providers may only support a subset of query types and should return empty results\n// for unsupported types rather than throwing.\n\nexport interface ContextProvider {\n readonly name: string;\n isAvailable(repoPath: string): Promise<boolean>;\n listSessions(query: ContextQuery): Promise<SessionListResult>;\n buildContext(query: ContextQuery, options?: ContextOptions): Promise<ContextResult>;\n}\n\nexport interface ContextQuery {\n repoPath: string;\n type: \"branch\" | \"commit\" | \"pr\" | \"latest\" | \"checkpoint\" | \"session\";\n value: string;\n}\n\nexport interface ContextOptions {\n maxTokens?: number;\n limit?: number;\n /** When true, insert `## [agentName]` headers at agent boundaries in merged history */\n labelAgent?: boolean;\n}\n\nexport interface SessionInfo {\n checkpointId: string;\n sessionIndex: string;\n transcriptPath: string;\n createdAt: string;\n endedAt: string;\n branch: string;\n agent: string;\n turnCount: number;\n filesTouched: string[];\n sessionId: string;\n}\n\nexport interface SessionListResult {\n sessions: SessionInfo[];\n estimatedTokens: number;\n}\n\nexport type ContextMode = \"full\" | \"balanced\" | \"compact\";\n\nexport interface ContextResult {\n markdown: string;\n tokenEstimate: number;\n sessionCount: number;\n totalTurns: number;\n mode: ContextMode;\n truncated: boolean;\n timeRange: { start: string; end: string };\n}\n\nexport const DEFAULT_MAX_TOKENS = 30_000;\nexport const TOKENS_PER_TURN_ESTIMATE = 400;\n","import { execFileSync } from \"child_process\";\nimport type { SessionInfo } from \"../context-provider.js\";\n\n// ─── Internal types ────────────────────────────────────────────────────────────\n\ninterface CheckpointMeta {\n checkpoint_id?: string;\n branch?: string;\n files_touched?: string[];\n sessions: Array<{\n metadata: string;\n transcript: string;\n }>;\n}\n\ninterface SessionMeta {\n session_id?: string;\n created_at?: string;\n branch?: string;\n agent?: string;\n files_touched?: string[];\n session_metrics?: {\n turn_count?: number;\n };\n}\n\n// ─── CheckpointReader ─────────────────────────────────────────────────────────\n\nconst ENTIRE_BRANCH = \"origin/entire/checkpoints/v1\";\nconst CHECKPOINT_ID_RE = /^[0-9a-f]{12}$/;\nconst SESSION_ID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\n\nexport class CheckpointReader {\n constructor(private readonly repoPath: string) {}\n\n // ─── Git execution ───────────────────────────────────────────────────────────\n\n /**\n * Run a git command in the repo directory.\n * Returns trimmed stdout on success, empty string on failure.\n */\n private git(...args: string[]): string {\n try {\n return execFileSync(\"git\", [\"-C\", this.repoPath, ...args], {\n encoding: \"utf-8\",\n }).trim();\n } catch {\n return \"\";\n }\n }\n\n // ─── Static helpers ──────────────────────────────────────────────────────────\n\n /**\n * Convert a 12-char checkpoint ID to its shard path: \"f634acf05138\" → \"f6/34acf05138\"\n */\n static shardPath(cpId: string): string {\n return `${cpId.slice(0, 2)}/${cpId.slice(2)}`;\n }\n\n /**\n * Returns true when value looks like a 12-char lowercase hex checkpoint ID.\n */\n static isCheckpointId(value: string): boolean {\n return CHECKPOINT_ID_RE.test(value);\n }\n\n /**\n * Returns true when value looks like a UUID (session ID).\n */\n static isSessionId(value: string): boolean {\n return SESSION_ID_RE.test(value);\n }\n\n /**\n * Parse checkpoint-level metadata JSON. Returns null on error.\n */\n static parseCheckpointMeta(json: string): CheckpointMeta | null {\n try {\n const parsed = JSON.parse(json) as CheckpointMeta;\n if (!parsed || typeof parsed !== \"object\") return null;\n if (!Array.isArray(parsed.sessions)) return null;\n return parsed;\n } catch {\n return null;\n }\n }\n\n /**\n * Extract Entire-Checkpoint trailer IDs from `git log --format=\"%H|%(trailers:...)\"` output.\n * Each line is: `<hash>|<trailer_value_or_empty>`. Returns only non-empty trailer values.\n * Uses the last pipe on each line to locate the trailer value, to be robust against\n * subject lines that contain pipes.\n */\n static parseCheckpointTrailers(output: string): string[] {\n const ids: string[] = [];\n for (const line of output.split(\"\\n\")) {\n const pipe = line.lastIndexOf(\"|\");\n if (pipe === -1) continue;\n const trailerId = line.slice(pipe + 1).trim();\n if (trailerId) ids.push(trailerId);\n }\n return ids;\n }\n\n // ─── Branch check ────────────────────────────────────────────────────────────\n\n async hasEntireBranch(): Promise<boolean> {\n const out = this.git(\"branch\", \"-r\");\n return out.includes(\"entire/checkpoints/v1\");\n }\n\n // ─── Core session fetching ───────────────────────────────────────────────────\n\n private listAllCheckpointIds(): string[] {\n const out = this.git(\n \"ls-tree\",\n \"-r\",\n ENTIRE_BRANCH,\n \"--name-only\"\n );\n if (!out) return [];\n\n const ids = new Set<string>();\n for (const file of out.split(\"\\n\")) {\n const parts = file.split(\"/\");\n // Checkpoint-level metadata: XX/YYYYYYYYYY/metadata.json (3 parts)\n if (parts.length === 3 && parts[2] === \"metadata.json\") {\n ids.add(parts[0] + parts[1]);\n }\n }\n return [...ids];\n }\n\n private fetchCheckpointMeta(cpId: string): CheckpointMeta | null {\n const shard = CheckpointReader.shardPath(cpId);\n const raw = this.git(\"show\", `${ENTIRE_BRANCH}:${shard}/metadata.json`);\n if (!raw) return null;\n return CheckpointReader.parseCheckpointMeta(raw);\n }\n\n private fetchSessionMeta(metaPath: string): SessionMeta {\n const normalized = metaPath.startsWith(\"/\") ? metaPath.slice(1) : metaPath;\n const raw = this.git(\"show\", `${ENTIRE_BRANCH}:${normalized}`);\n if (!raw) return {};\n try {\n return JSON.parse(raw) as SessionMeta;\n } catch {\n return {};\n }\n }\n\n /**\n * Build SessionInfo[] from a single checkpoint's metadata.\n */\n private buildSessionsForCheckpoint(\n cpId: string,\n cpMeta: CheckpointMeta\n ): SessionInfo[] {\n const sessions: SessionInfo[] = [];\n\n for (let idx = 0; idx < cpMeta.sessions.length; idx++) {\n const sess = cpMeta.sessions[idx];\n const transcriptPath = (sess.transcript ?? \"\").replace(/^\\//, \"\");\n const metaPath = sess.metadata ?? \"\";\n\n const smeta = this.fetchSessionMeta(metaPath);\n const createdAt = smeta.created_at ?? \"\";\n\n sessions.push({\n checkpointId: cpId,\n sessionIndex: String(idx),\n transcriptPath,\n createdAt,\n endedAt: createdAt, // will be filled from JSONL by conversation builder\n branch: smeta.branch ?? cpMeta.branch ?? \"\",\n agent: smeta.agent ?? \"\",\n turnCount: smeta.session_metrics?.turn_count ?? 0,\n filesTouched: smeta.files_touched ?? cpMeta.files_touched ?? [],\n sessionId: smeta.session_id ?? \"\",\n });\n }\n\n return sessions;\n }\n\n private getSessionsForCheckpoint(cpId: string): SessionInfo[] {\n const meta = this.fetchCheckpointMeta(cpId);\n if (!meta) return [];\n return this.buildSessionsForCheckpoint(cpId, meta);\n }\n\n // ─── Public resolvers ────────────────────────────────────────────────────────\n\n /**\n * All sessions recorded on a given branch, sorted by createdAt ascending.\n */\n async resolveByBranch(branchName: string): Promise<SessionInfo[]> {\n const cpIds = this.listAllCheckpointIds();\n const sessions: SessionInfo[] = [];\n\n for (const cpId of cpIds) {\n const meta = this.fetchCheckpointMeta(cpId);\n if (!meta) continue;\n if (meta.branch !== branchName) continue;\n sessions.push(...this.buildSessionsForCheckpoint(cpId, meta));\n }\n\n sessions.sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n return sessions;\n }\n\n /**\n * Sessions linked to a specific commit via the Entire-Checkpoint git trailer.\n */\n async resolveByCommit(commitHash: string): Promise<SessionInfo[]> {\n const fullHash = this.git(\"rev-parse\", commitHash);\n if (!fullHash) return [];\n\n const cpId = this.git(\n \"log\",\n \"-1\",\n \"--format=%(trailers:key=Entire-Checkpoint,valueonly)\",\n fullHash\n );\n if (!cpId) return [];\n\n return this.getSessionsForCheckpoint(cpId.trim());\n }\n\n /**\n * All sessions from a merged PR (by number or GitHub URL).\n */\n async resolveByPr(prInput: string): Promise<SessionInfo[]> {\n let prNumber: string;\n\n if (/^\\d+$/.test(prInput)) {\n prNumber = prInput;\n } else {\n const m = /\\/pull\\/(\\d+)/.exec(prInput);\n if (!m) return [];\n prNumber = m[1];\n }\n\n const mergeOut = this.git(\n \"log\",\n \"--all\",\n \"--oneline\",\n \"--grep\",\n `Merge pull request #${prNumber}`\n );\n if (!mergeOut) return [];\n\n const mergeCommit = mergeOut.split(\"\\n\")[0].split(\" \")[0];\n\n const logOut = this.git(\n \"log\",\n \"--format=%H|%(trailers:key=Entire-Checkpoint,valueonly)\",\n `${mergeCommit}^2`,\n \"--not\",\n `${mergeCommit}^1`\n );\n if (!logOut) return [];\n\n const cpIds = CheckpointReader.parseCheckpointTrailers(logOut);\n const sessions: SessionInfo[] = [];\n\n for (const cpId of cpIds) {\n sessions.push(...this.getSessionsForCheckpoint(cpId));\n }\n\n sessions.sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n return sessions;\n }\n\n /**\n * Sessions matching a specific checkpoint ID.\n */\n async resolveByCheckpoint(checkpointId: string): Promise<SessionInfo[]> {\n return this.getSessionsForCheckpoint(checkpointId);\n }\n\n /**\n * Find a session by its UUID.\n */\n async resolveBySessionId(sessionId: string): Promise<SessionInfo[]> {\n const cpIds = this.listAllCheckpointIds();\n\n for (const cpId of cpIds) {\n const sessions = this.getSessionsForCheckpoint(cpId);\n const match = sessions.find((s) => s.sessionId === sessionId);\n if (match) return [match];\n }\n\n return [];\n }\n\n /**\n * Latest N sessions across all checkpoints, sorted by createdAt descending.\n */\n async resolveLatest(count: number): Promise<SessionInfo[]> {\n const cpIds = this.listAllCheckpointIds();\n const all: SessionInfo[] = [];\n\n for (const cpId of cpIds) {\n all.push(...this.getSessionsForCheckpoint(cpId));\n }\n\n all.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n return all.slice(0, count);\n }\n\n /**\n * Read the full JSONL transcript content from the entire branch.\n */\n getTranscript(transcriptPath: string): string {\n const normalized = transcriptPath.startsWith(\"/\")\n ? transcriptPath.slice(1)\n : transcriptPath;\n return this.git(\"show\", `${ENTIRE_BRANCH}:${normalized}`);\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-NOEAJNTK.js
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getGlobalRoot
|
|
3
|
-
} from "./chunk-ON7HB5O7.js";
|
|
4
|
-
|
|
5
|
-
// src/core/config/config-registry.ts
|
|
6
|
-
import * as fs from "fs";
|
|
7
|
-
import * as path from "path";
|
|
8
|
-
var CONFIG_REGISTRY = [
|
|
9
|
-
{
|
|
10
|
-
path: "defaultAgent",
|
|
11
|
-
displayName: "Default Agent",
|
|
12
|
-
group: "agent",
|
|
13
|
-
type: "select",
|
|
14
|
-
options: (config) => {
|
|
15
|
-
try {
|
|
16
|
-
const agentsPath = path.join(getGlobalRoot(), "agents.json");
|
|
17
|
-
if (fs.existsSync(agentsPath)) {
|
|
18
|
-
const data = JSON.parse(fs.readFileSync(agentsPath, "utf-8"));
|
|
19
|
-
return Object.keys(data.installed ?? {});
|
|
20
|
-
}
|
|
21
|
-
} catch {
|
|
22
|
-
}
|
|
23
|
-
return Object.keys(config.agents ?? {});
|
|
24
|
-
},
|
|
25
|
-
scope: "safe",
|
|
26
|
-
hotReload: true
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
path: "channels.telegram.displayVerbosity",
|
|
30
|
-
displayName: "Telegram Verbosity",
|
|
31
|
-
group: "display",
|
|
32
|
-
type: "select",
|
|
33
|
-
options: ["low", "medium", "high"],
|
|
34
|
-
scope: "safe",
|
|
35
|
-
hotReload: true
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
path: "channels.discord.displayVerbosity",
|
|
39
|
-
displayName: "Discord Verbosity",
|
|
40
|
-
group: "display",
|
|
41
|
-
type: "select",
|
|
42
|
-
options: ["low", "medium", "high"],
|
|
43
|
-
scope: "safe",
|
|
44
|
-
hotReload: true
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
path: "logging.level",
|
|
48
|
-
displayName: "Log Level",
|
|
49
|
-
group: "logging",
|
|
50
|
-
type: "select",
|
|
51
|
-
options: ["silent", "debug", "info", "warn", "error", "fatal"],
|
|
52
|
-
scope: "safe",
|
|
53
|
-
hotReload: true
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
path: "tunnel.enabled",
|
|
57
|
-
displayName: "Tunnel",
|
|
58
|
-
group: "tunnel",
|
|
59
|
-
type: "toggle",
|
|
60
|
-
scope: "safe",
|
|
61
|
-
hotReload: false
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
path: "security.maxConcurrentSessions",
|
|
65
|
-
displayName: "Max Concurrent Sessions",
|
|
66
|
-
group: "security",
|
|
67
|
-
type: "number",
|
|
68
|
-
scope: "safe",
|
|
69
|
-
hotReload: true
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
path: "security.sessionTimeoutMinutes",
|
|
73
|
-
displayName: "Session Timeout (min)",
|
|
74
|
-
group: "security",
|
|
75
|
-
type: "number",
|
|
76
|
-
scope: "safe",
|
|
77
|
-
hotReload: true
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
path: "workspace.baseDir",
|
|
81
|
-
displayName: "Workspace Directory",
|
|
82
|
-
group: "workspace",
|
|
83
|
-
type: "string",
|
|
84
|
-
scope: "safe",
|
|
85
|
-
hotReload: true
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
path: "sessionStore.ttlDays",
|
|
89
|
-
displayName: "Session Store TTL (days)",
|
|
90
|
-
group: "storage",
|
|
91
|
-
type: "number",
|
|
92
|
-
scope: "safe",
|
|
93
|
-
hotReload: true
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
path: "speech.stt.provider",
|
|
97
|
-
displayName: "Speech to Text",
|
|
98
|
-
group: "speech",
|
|
99
|
-
type: "select",
|
|
100
|
-
options: ["groq"],
|
|
101
|
-
scope: "safe",
|
|
102
|
-
hotReload: true
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
path: "speech.stt.apiKey",
|
|
106
|
-
displayName: "STT API Key",
|
|
107
|
-
group: "speech",
|
|
108
|
-
type: "string",
|
|
109
|
-
scope: "sensitive",
|
|
110
|
-
hotReload: true
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
path: "agentSwitch.labelHistory",
|
|
114
|
-
displayName: "Label Agent in History",
|
|
115
|
-
group: "agent",
|
|
116
|
-
type: "toggle",
|
|
117
|
-
scope: "safe",
|
|
118
|
-
hotReload: true
|
|
119
|
-
}
|
|
120
|
-
];
|
|
121
|
-
function getFieldDef(path2) {
|
|
122
|
-
return CONFIG_REGISTRY.find((f) => f.path === path2);
|
|
123
|
-
}
|
|
124
|
-
function getSafeFields() {
|
|
125
|
-
return CONFIG_REGISTRY.filter((f) => f.scope === "safe");
|
|
126
|
-
}
|
|
127
|
-
function isHotReloadable(path2) {
|
|
128
|
-
const def = getFieldDef(path2);
|
|
129
|
-
return def?.hotReload ?? false;
|
|
130
|
-
}
|
|
131
|
-
function resolveOptions(def, config) {
|
|
132
|
-
if (!def.options) return void 0;
|
|
133
|
-
return typeof def.options === "function" ? def.options(config) : def.options;
|
|
134
|
-
}
|
|
135
|
-
function getConfigValue(config, path2) {
|
|
136
|
-
const parts = path2.split(".");
|
|
137
|
-
let current = config;
|
|
138
|
-
for (const part of parts) {
|
|
139
|
-
if (current && typeof current === "object" && part in current) {
|
|
140
|
-
current = current[part];
|
|
141
|
-
} else {
|
|
142
|
-
return void 0;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return current;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export {
|
|
149
|
-
CONFIG_REGISTRY,
|
|
150
|
-
getFieldDef,
|
|
151
|
-
getSafeFields,
|
|
152
|
-
isHotReloadable,
|
|
153
|
-
resolveOptions,
|
|
154
|
-
getConfigValue
|
|
155
|
-
};
|
|
156
|
-
//# sourceMappingURL=chunk-NOEAJNTK.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/config/config-registry.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Config } from \"./config.js\";\nimport { getGlobalRoot } from \"../instance-context.js\";\n\nexport interface ConfigFieldDef {\n path: string;\n displayName: string;\n group: string;\n type: \"toggle\" | \"select\" | \"number\" | \"string\";\n options?: string[] | ((config: Config) => string[]);\n scope: \"safe\" | \"sensitive\";\n hotReload: boolean;\n}\n\nexport const CONFIG_REGISTRY: ConfigFieldDef[] = [\n {\n path: \"defaultAgent\",\n displayName: \"Default Agent\",\n group: \"agent\",\n type: \"select\",\n options: (config) => {\n try {\n const agentsPath = path.join(getGlobalRoot(), \"agents.json\");\n if (fs.existsSync(agentsPath)) {\n const data = JSON.parse(fs.readFileSync(agentsPath, \"utf-8\"));\n return Object.keys(data.installed ?? {});\n }\n } catch {\n /* fallback */\n }\n return Object.keys(config.agents ?? {});\n },\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"channels.telegram.displayVerbosity\",\n displayName: \"Telegram Verbosity\",\n group: \"display\",\n type: \"select\",\n options: [\"low\", \"medium\", \"high\"],\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"channels.discord.displayVerbosity\",\n displayName: \"Discord Verbosity\",\n group: \"display\",\n type: \"select\",\n options: [\"low\", \"medium\", \"high\"],\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"logging.level\",\n displayName: \"Log Level\",\n group: \"logging\",\n type: \"select\",\n options: [\"silent\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"],\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"tunnel.enabled\",\n displayName: \"Tunnel\",\n group: \"tunnel\",\n type: \"toggle\",\n scope: \"safe\",\n hotReload: false,\n },\n {\n path: \"security.maxConcurrentSessions\",\n displayName: \"Max Concurrent Sessions\",\n group: \"security\",\n type: \"number\",\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"security.sessionTimeoutMinutes\",\n displayName: \"Session Timeout (min)\",\n group: \"security\",\n type: \"number\",\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"workspace.baseDir\",\n displayName: \"Workspace Directory\",\n group: \"workspace\",\n type: \"string\",\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"sessionStore.ttlDays\",\n displayName: \"Session Store TTL (days)\",\n group: \"storage\",\n type: \"number\",\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"speech.stt.provider\",\n displayName: \"Speech to Text\",\n group: \"speech\",\n type: \"select\",\n options: [\"groq\"],\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"speech.stt.apiKey\",\n displayName: \"STT API Key\",\n group: \"speech\",\n type: \"string\",\n scope: \"sensitive\",\n hotReload: true,\n },\n {\n path: \"agentSwitch.labelHistory\",\n displayName: \"Label Agent in History\",\n group: \"agent\",\n type: \"toggle\",\n scope: \"safe\",\n hotReload: true,\n },\n];\n\nexport function getFieldDef(path: string): ConfigFieldDef | undefined {\n return CONFIG_REGISTRY.find((f) => f.path === path);\n}\n\nexport function getSafeFields(): ConfigFieldDef[] {\n return CONFIG_REGISTRY.filter((f) => f.scope === \"safe\");\n}\n\nexport function isHotReloadable(path: string): boolean {\n const def = getFieldDef(path);\n return def?.hotReload ?? false;\n}\n\nexport function resolveOptions(\n def: ConfigFieldDef,\n config: Config,\n): string[] | undefined {\n if (!def.options) return undefined;\n return typeof def.options === \"function\" ? def.options(config) : def.options;\n}\n\nexport function getConfigValue(config: Config, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = config;\n for (const part of parts) {\n if (current && typeof current === \"object\" && part in current) {\n current = (current as Record<string, unknown>)[part];\n } else {\n return undefined;\n }\n }\n return current;\n}\n"],"mappings":"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","names":["path"]}
|
package/dist/chunk-ON7HB5O7.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// src/core/instance-context.ts
|
|
2
|
-
import path from "path";
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import os from "os";
|
|
5
|
-
function createInstanceContext(opts) {
|
|
6
|
-
const { id, root, isGlobal } = opts;
|
|
7
|
-
return {
|
|
8
|
-
id,
|
|
9
|
-
root,
|
|
10
|
-
isGlobal,
|
|
11
|
-
paths: {
|
|
12
|
-
config: path.join(root, "config.json"),
|
|
13
|
-
sessions: path.join(root, "sessions.json"),
|
|
14
|
-
agents: path.join(root, "agents.json"),
|
|
15
|
-
registryCache: path.join(root, "registry-cache.json"),
|
|
16
|
-
plugins: path.join(root, "plugins"),
|
|
17
|
-
pluginsData: path.join(root, "plugins", "data"),
|
|
18
|
-
pluginRegistry: path.join(root, "plugins.json"),
|
|
19
|
-
logs: path.join(root, "logs"),
|
|
20
|
-
pid: path.join(root, "openacp.pid"),
|
|
21
|
-
running: path.join(root, "running"),
|
|
22
|
-
apiPort: path.join(root, "api.port"),
|
|
23
|
-
apiSecret: path.join(root, "api-secret"),
|
|
24
|
-
bin: path.join(root, "bin"),
|
|
25
|
-
cache: path.join(root, "cache"),
|
|
26
|
-
tunnels: path.join(root, "tunnels.json"),
|
|
27
|
-
agentsDir: path.join(root, "agents")
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function generateSlug(name) {
|
|
32
|
-
const slug = name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
33
|
-
return slug || "openacp";
|
|
34
|
-
}
|
|
35
|
-
function expandHome(p) {
|
|
36
|
-
if (p.startsWith("~")) return path.join(os.homedir(), p.slice(1));
|
|
37
|
-
return p;
|
|
38
|
-
}
|
|
39
|
-
function resolveInstanceRoot(opts) {
|
|
40
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
41
|
-
if (opts.dir) return path.join(expandHome(opts.dir), ".openacp");
|
|
42
|
-
if (opts.local) return path.join(cwd, ".openacp");
|
|
43
|
-
if (opts.global) return path.join(os.homedir(), ".openacp");
|
|
44
|
-
const localRoot = path.join(cwd, ".openacp");
|
|
45
|
-
if (fs.existsSync(localRoot)) return localRoot;
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
function getGlobalRoot() {
|
|
49
|
-
return path.join(os.homedir(), ".openacp");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export {
|
|
53
|
-
createInstanceContext,
|
|
54
|
-
generateSlug,
|
|
55
|
-
resolveInstanceRoot,
|
|
56
|
-
getGlobalRoot
|
|
57
|
-
};
|
|
58
|
-
//# sourceMappingURL=chunk-ON7HB5O7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/instance-context.ts"],"sourcesContent":["import path from 'node:path'\nimport fs from 'node:fs'\nimport os from 'node:os'\n\nexport interface InstanceContext {\n id: string\n root: string\n isGlobal: boolean\n paths: {\n config: string\n sessions: string\n agents: string\n registryCache: string\n plugins: string\n pluginsData: string\n pluginRegistry: string\n logs: string\n pid: string\n running: string\n apiPort: string\n apiSecret: string\n bin: string\n cache: string\n tunnels: string\n agentsDir: string\n }\n}\n\nexport interface CreateInstanceContextOpts {\n id: string\n root: string\n isGlobal: boolean\n}\n\nexport function createInstanceContext(opts: CreateInstanceContextOpts): InstanceContext {\n const { id, root, isGlobal } = opts\n return {\n id, root, isGlobal,\n paths: {\n config: path.join(root, 'config.json'),\n sessions: path.join(root, 'sessions.json'),\n agents: path.join(root, 'agents.json'),\n registryCache: path.join(root, 'registry-cache.json'),\n plugins: path.join(root, 'plugins'),\n pluginsData: path.join(root, 'plugins', 'data'),\n pluginRegistry: path.join(root, 'plugins.json'),\n logs: path.join(root, 'logs'),\n pid: path.join(root, 'openacp.pid'),\n running: path.join(root, 'running'),\n apiPort: path.join(root, 'api.port'),\n apiSecret: path.join(root, 'api-secret'),\n bin: path.join(root, 'bin'),\n cache: path.join(root, 'cache'),\n tunnels: path.join(root, 'tunnels.json'),\n agentsDir: path.join(root, 'agents'),\n },\n }\n}\n\nexport function generateSlug(name: string): string {\n const slug = name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '')\n return slug || 'openacp'\n}\n\nfunction expandHome(p: string): string {\n if (p.startsWith('~')) return path.join(os.homedir(), p.slice(1))\n return p\n}\n\nexport interface ResolveOpts {\n dir?: string\n local?: boolean\n global?: boolean\n cwd?: string\n}\n\nexport function resolveInstanceRoot(opts: ResolveOpts): string | null {\n const cwd = opts.cwd ?? process.cwd()\n if (opts.dir) return path.join(expandHome(opts.dir), '.openacp')\n if (opts.local) return path.join(cwd, '.openacp')\n if (opts.global) return path.join(os.homedir(), '.openacp')\n const localRoot = path.join(cwd, '.openacp')\n if (fs.existsSync(localRoot)) return localRoot\n return null\n}\n\nexport function getGlobalRoot(): string {\n return path.join(os.homedir(), '.openacp')\n}\n"],"mappings":";AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,OAAO,QAAQ;AAgCR,SAAS,sBAAsB,MAAkD;AACtF,QAAM,EAAE,IAAI,MAAM,SAAS,IAAI;AAC/B,SAAO;AAAA,IACL;AAAA,IAAI;AAAA,IAAM;AAAA,IACV,OAAO;AAAA,MACL,QAAQ,KAAK,KAAK,MAAM,aAAa;AAAA,MACrC,UAAU,KAAK,KAAK,MAAM,eAAe;AAAA,MACzC,QAAQ,KAAK,KAAK,MAAM,aAAa;AAAA,MACrC,eAAe,KAAK,KAAK,MAAM,qBAAqB;AAAA,MACpD,SAAS,KAAK,KAAK,MAAM,SAAS;AAAA,MAClC,aAAa,KAAK,KAAK,MAAM,WAAW,MAAM;AAAA,MAC9C,gBAAgB,KAAK,KAAK,MAAM,cAAc;AAAA,MAC9C,MAAM,KAAK,KAAK,MAAM,MAAM;AAAA,MAC5B,KAAK,KAAK,KAAK,MAAM,aAAa;AAAA,MAClC,SAAS,KAAK,KAAK,MAAM,SAAS;AAAA,MAClC,SAAS,KAAK,KAAK,MAAM,UAAU;AAAA,MACnC,WAAW,KAAK,KAAK,MAAM,YAAY;AAAA,MACvC,KAAK,KAAK,KAAK,MAAM,KAAK;AAAA,MAC1B,OAAO,KAAK,KAAK,MAAM,OAAO;AAAA,MAC9B,SAAS,KAAK,KAAK,MAAM,cAAc;AAAA,MACvC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAAA,IACrC;AAAA,EACF;AACF;AAEO,SAAS,aAAa,MAAsB;AACjD,QAAM,OAAO,KAAK,YAAY,EAAE,QAAQ,eAAe,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,UAAU,EAAE;AACpG,SAAO,QAAQ;AACjB;AAEA,SAAS,WAAW,GAAmB;AACrC,MAAI,EAAE,WAAW,GAAG,EAAG,QAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,EAAE,MAAM,CAAC,CAAC;AAChE,SAAO;AACT;AASO,SAAS,oBAAoB,MAAkC;AACpE,QAAM,MAAM,KAAK,OAAO,QAAQ,IAAI;AACpC,MAAI,KAAK,IAAK,QAAO,KAAK,KAAK,WAAW,KAAK,GAAG,GAAG,UAAU;AAC/D,MAAI,KAAK,MAAO,QAAO,KAAK,KAAK,KAAK,UAAU;AAChD,MAAI,KAAK,OAAQ,QAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,UAAU;AAC1D,QAAM,YAAY,KAAK,KAAK,KAAK,UAAU;AAC3C,MAAI,GAAG,WAAW,SAAS,EAAG,QAAO;AACrC,SAAO;AACT;AAEO,SAAS,gBAAwB;AACtC,SAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,UAAU;AAC3C;","names":[]}
|