@jc_stack/ez-agents 0.1.0-beta.12
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/.dockerignore +24 -0
- package/.env.example +26 -0
- package/AGENTS.md +84 -0
- package/CHANGELOG.md +39 -0
- package/CONTRIBUTING.md +73 -0
- package/Dockerfile +16 -0
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/SECURITY.md +26 -0
- package/THIRD_PARTY_NOTICES.md +14 -0
- package/bin/ezenciel-agents +2 -0
- package/bin/ezenciel-agents-ai +2 -0
- package/bin/ezenciel-agents-ai.mjs +5 -0
- package/bin/ezenciel-agents-approval +2 -0
- package/bin/ezenciel-agents-approval.mjs +16 -0
- package/bin/ezenciel-agents-create +12 -0
- package/bin/ezenciel-agents-docker +6 -0
- package/bin/ezenciel-agents-host +5 -0
- package/bin/ezenciel-agents-install +2 -0
- package/bin/ezenciel-agents-message +2 -0
- package/bin/ezenciel-agents-message.mjs +16 -0
- package/bin/ezenciel-agents-owner +2 -0
- package/bin/ezenciel-agents-owner.mjs +18 -0
- package/bin/ezenciel-agents-react +2 -0
- package/bin/ezenciel-agents-react.mjs +16 -0
- package/bin/ezenciel-agents-setup.mjs +18 -0
- package/bin/ezenciel-agents-source +2 -0
- package/bin/ezenciel-agents-source.mjs +16 -0
- package/bin/ezenciel-agents-tools.mjs +3 -0
- package/bin/ezenciel-agents.mjs +37 -0
- package/compose.whatsapp.yaml +12 -0
- package/compose.yaml +40 -0
- package/default-plugins.json +1 -0
- package/docker/entrypoint.sh +15 -0
- package/docker/healthcheck.mjs +8 -0
- package/docker/plugin-smoke.mjs +48 -0
- package/docker/pnpm-lock.yaml +415 -0
- package/docker/recovery.ts +11 -0
- package/docker/run.ts +52 -0
- package/docker/smoke.mjs +47 -0
- package/docker/status-smoke.mjs +30 -0
- package/docker/upgrade-smoke.mjs +58 -0
- package/docs/architecture/ai-selection.md +37 -0
- package/docs/architecture/authority-boundaries.md +14 -0
- package/docs/architecture/event-sources.md +34 -0
- package/docs/architecture/telegram-intake.md +29 -0
- package/docs/development-and-testing.md +18 -0
- package/docs/docker-runtime.md +118 -0
- package/docs/host-service.md +80 -0
- package/docs/plugin-contributions.md +34 -0
- package/docs/plugins.md +181 -0
- package/docs/releasing.md +71 -0
- package/docs/setup.md +234 -0
- package/docs/upgrades.md +193 -0
- package/package.json +106 -0
- package/scripts/assert-local-registry.mjs +22 -0
- package/scripts/release-check.mjs +14 -0
- package/scripts/smoke.ts +102 -0
- package/src/agent-install.ts +96 -0
- package/src/ai-cli.ts +22 -0
- package/src/ai.ts +88 -0
- package/src/approval-cli.ts +59 -0
- package/src/approval.ts +119 -0
- package/src/audio.ts +184 -0
- package/src/client-defaults.ts +101 -0
- package/src/config.ts +48 -0
- package/src/control-state.ts +350 -0
- package/src/desktop-bridge.ts +284 -0
- package/src/event-sources.ts +112 -0
- package/src/executor.ts +335 -0
- package/src/files.ts +75 -0
- package/src/format.ts +57 -0
- package/src/host-executor-client.ts +46 -0
- package/src/host-executor-protocol.ts +2 -0
- package/src/host-executor.ts +129 -0
- package/src/identity.ts +17 -0
- package/src/inbox.ts +171 -0
- package/src/index.ts +812 -0
- package/src/install-config.ts +56 -0
- package/src/install-tools.mjs +98 -0
- package/src/menu.ts +123 -0
- package/src/message-send.ts +57 -0
- package/src/message.ts +68 -0
- package/src/owner-args.ts +4 -0
- package/src/owner.ts +30 -0
- package/src/plugins/manager.mjs +272 -0
- package/src/react.ts +33 -0
- package/src/reaction.ts +32 -0
- package/src/read-request.ts +72 -0
- package/src/reply.ts +13 -0
- package/src/runs.ts +445 -0
- package/src/service.ts +28 -0
- package/src/setup.ts +180 -0
- package/src/software-status.ts +23 -0
- package/src/source-cli.ts +18 -0
- package/src/update-attention.ts +18 -0
- package/src/updates/artifact.mjs +83 -0
- package/src/updates/binding.mjs +27 -0
- package/src/updates/control.mjs +131 -0
- package/src/updates/launch.mjs +13 -0
- package/src/updates/runtime.mjs +140 -0
- package/src/updates/status.mjs +49 -0
- package/src/updates/supervisor.mjs +102 -0
- package/src/version.ts +4 -0
- package/src/workspace.ts +32 -0
- package/templates/agent/AGENTS.md +49 -0
- package/templates/agent/SOUL.md +11 -0
- package/templates/agent/TOOLS.md +46 -0
- package/templates/agent/USER.md +5 -0
- package/templates/updates.md +45 -0
- package/test/agent-install.test.ts +48 -0
- package/test/ai-cli.test.ts +28 -0
- package/test/ai.test.ts +105 -0
- package/test/approval.test.ts +40 -0
- package/test/audio.test.ts +77 -0
- package/test/client-defaults.test.ts +64 -0
- package/test/codex-context.test.ts +33 -0
- package/test/config.test.ts +32 -0
- package/test/control-state.test.ts +58 -0
- package/test/desktop-bridge.test.ts +159 -0
- package/test/docker-runtime.test.ts +23 -0
- package/test/event-sources.test.ts +113 -0
- package/test/executor.test.ts +135 -0
- package/test/files.test.ts +50 -0
- package/test/format.test.ts +41 -0
- package/test/host-executor.test.ts +149 -0
- package/test/inbox-burst.test.ts +66 -0
- package/test/inbox.test.ts +102 -0
- package/test/install-config.test.ts +75 -0
- package/test/install-tools.test.mjs +59 -0
- package/test/intake-relay.test.ts +337 -0
- package/test/owner-help.test.mjs +10 -0
- package/test/plugin-manager.test.mjs +157 -0
- package/test/publish-guard.test.ts +21 -0
- package/test/reaction.test.ts +122 -0
- package/test/read-request.test.ts +134 -0
- package/test/relay.test.ts +254 -0
- package/test/release-entrypoints.test.mjs +26 -0
- package/test/runs.test.ts +116 -0
- package/test/security.test.ts +85 -0
- package/test/setup.test.ts +68 -0
- package/test/software-status.test.ts +31 -0
- package/test/update-attention.test.ts +21 -0
- package/test/updates.test.mjs +282 -0
- package/test/upgrade-pause.test.ts +70 -0
- package/test/workspace.test.ts +80 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { dirname, join } from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const require = createRequire(import.meta.url)
|
|
9
|
+
const tsx = require.resolve('tsx')
|
|
10
|
+
const entry = join(here, '..', 'src', 'source-cli.ts')
|
|
11
|
+
const forwarded = process.argv.slice(2).filter((arg) => arg !== '--')
|
|
12
|
+
const child = spawn(process.execPath, ['--import', tsx, entry, ...forwarded], { stdio: 'inherit' })
|
|
13
|
+
child.on('exit', (code, signal) => {
|
|
14
|
+
if (signal) process.kill(process.pid, signal)
|
|
15
|
+
process.exit(code ?? 1)
|
|
16
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { dirname, join } from 'node:path'
|
|
6
|
+
import { fileURLToPath } from 'node:url'
|
|
7
|
+
|
|
8
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const require = createRequire(import.meta.url)
|
|
10
|
+
const entry = join(here, '..', 'src', 'index.ts')
|
|
11
|
+
const forwarded = process.argv.slice(2).filter((arg) => arg !== '--')
|
|
12
|
+
if (forwarded.length === 1 && forwarded[0] === '--version') {
|
|
13
|
+
console.log(require('../package.json').version)
|
|
14
|
+
process.exit(0)
|
|
15
|
+
}
|
|
16
|
+
if (forwarded.length === 1 && ['--help', '-h'].includes(forwarded[0])) {
|
|
17
|
+
console.log('Usage: ezenciel-agents [start]\nStarts the Docker relay bound by EZ_DEPLOYMENT_DIR/docker.env.\nInitialize the mind: ezenciel-agents-setup init\nSetup instructions: docs/setup.md in the installed package.')
|
|
18
|
+
process.exit(0)
|
|
19
|
+
}
|
|
20
|
+
if (forwarded.length && (forwarded.length !== 1 || forwarded[0] !== 'start')) {
|
|
21
|
+
console.error('Usage: ezenciel-agents [start] (or --help)')
|
|
22
|
+
process.exit(1)
|
|
23
|
+
}
|
|
24
|
+
if (!existsSync('/.dockerenv') && process.env.EZ_DEVELOPMENT !== '1') {
|
|
25
|
+
const docker = spawn(join(here, 'ezenciel-agents-docker'), ['up', '-d', '--wait', 'relay'], { stdio: 'inherit' })
|
|
26
|
+
docker.on('error', () => { console.error('Docker launcher could not start'); process.exitCode = 1 })
|
|
27
|
+
docker.on('exit', code => { process.exitCode = code ?? 1 })
|
|
28
|
+
} else {
|
|
29
|
+
const tsx = require.resolve('tsx')
|
|
30
|
+
const args = existsSync('.env') ? ['--env-file=.env', entry] : [entry]
|
|
31
|
+
const child = spawn(process.execPath, ['--import', tsx, ...args, ...forwarded], { stdio: 'inherit' })
|
|
32
|
+
child.on('exit', (code, signal) => {
|
|
33
|
+
if (signal) process.kill(process.pid, signal)
|
|
34
|
+
process.exit(code ?? 1)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
services:
|
|
2
|
+
relay:
|
|
3
|
+
volumes:
|
|
4
|
+
- whatsapp-ipc:/plugins/whatsapp:ro
|
|
5
|
+
- whatsapp-client:/opt/plugins/whatsapp:ro
|
|
6
|
+
volumes:
|
|
7
|
+
whatsapp-ipc:
|
|
8
|
+
external: true
|
|
9
|
+
name: ${EZ_WHATSAPP_IPC_VOLUME:?Set the registered WhatsApp IPC volume}
|
|
10
|
+
whatsapp-client:
|
|
11
|
+
external: true
|
|
12
|
+
name: ${EZ_WHATSAPP_CLIENT_VOLUME:?Set the registered WhatsApp client volume}
|
package/compose.yaml
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
services:
|
|
2
|
+
relay:
|
|
3
|
+
image: ${EZ_RELAY_IMAGE:-ezenciel-agents:local}
|
|
4
|
+
build:
|
|
5
|
+
context: .
|
|
6
|
+
target: runtime
|
|
7
|
+
init: true
|
|
8
|
+
restart: unless-stopped
|
|
9
|
+
stop_grace_period: 30s
|
|
10
|
+
cap_drop: [ALL]
|
|
11
|
+
cap_add: [CHOWN, DAC_OVERRIDE, FOWNER, SETUID, SETGID, SETPCAP]
|
|
12
|
+
environment:
|
|
13
|
+
EZ_AGENT_PURPOSE_FILE: /run/agent-purpose.md
|
|
14
|
+
EZ_EXECUTOR_TRANSPORT: host
|
|
15
|
+
EZ_AGENT_WORKSPACE: ${EZ_AGENT_WORKSPACE:?Set this agent workspace}
|
|
16
|
+
EZ_CONTROL_DIR: ${EZ_CONTROL_DIR:?Set this agent control directory}
|
|
17
|
+
EZ_EXECUTOR_CLI: ${EZ_EXECUTOR_CLI:?Set the host installation CLI}
|
|
18
|
+
EZ_EXECUTOR_TIMEOUT_SECONDS: ${EZ_EXECUTOR_TIMEOUT_SECONDS:-300}
|
|
19
|
+
secrets: [relay_env]
|
|
20
|
+
configs:
|
|
21
|
+
- source: agent_purpose
|
|
22
|
+
target: /run/agent-purpose.md
|
|
23
|
+
volumes:
|
|
24
|
+
- ${EZ_AGENT_WORKSPACE}:/workspace
|
|
25
|
+
- ${EZ_AGENT_WORKSPACE}:${EZ_AGENT_WORKSPACE}
|
|
26
|
+
- ${EZ_CONTROL_DIR}:/state/control
|
|
27
|
+
- ${EZ_CONTROL_DIR}:${EZ_CONTROL_DIR}
|
|
28
|
+
tmpfs: [/tmp]
|
|
29
|
+
healthcheck:
|
|
30
|
+
test: [CMD, node, /app/docker/healthcheck.mjs]
|
|
31
|
+
interval: 10s
|
|
32
|
+
timeout: 5s
|
|
33
|
+
start_period: 30s
|
|
34
|
+
retries: 3
|
|
35
|
+
configs:
|
|
36
|
+
agent_purpose:
|
|
37
|
+
file: ${EZ_AGENT_PURPOSE_FILE:-./templates/agent/SOUL.md}
|
|
38
|
+
secrets:
|
|
39
|
+
relay_env:
|
|
40
|
+
file: ${EZ_RELAY_ENV_FILE:?Set EZ_RELAY_ENV_FILE to the private relay env file}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/sh -p
|
|
2
|
+
set -eu
|
|
3
|
+
umask 077
|
|
4
|
+
if [ "$(id -u)" = 0 ]; then
|
|
5
|
+
mkdir -p /state/control /state/home /workspace /run/secrets
|
|
6
|
+
chmod 700 /run/secrets
|
|
7
|
+
chown 1000:1000 /state/control /state/home /workspace
|
|
8
|
+
if [ -f /run/secrets/relay_env ]; then exec 3</run/secrets/relay_env; else exec 3</dev/null; fi
|
|
9
|
+
exec setpriv --ruid=1001 --euid=1000 --regid=1000 --clear-groups --bounding-set=-all --no-new-privs /app/docker/entrypoint.sh "$@"
|
|
10
|
+
fi
|
|
11
|
+
case "${1:-start}" in
|
|
12
|
+
start|smoke|exec|setup)
|
|
13
|
+
exec flock --no-fork -n -E 73 /state/control/relay.lock node --import /app/node_modules/tsx/dist/loader.mjs /app/docker/run.ts "$@" ;;
|
|
14
|
+
*) exec node --import /app/node_modules/tsx/dist/loader.mjs /app/docker/run.ts "$@" ;;
|
|
15
|
+
esac
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
const value = JSON.parse(readFileSync('/state/control/heartbeat.json', 'utf8'));
|
|
3
|
+
if (!value.polling || Date.now() - value.at > 20000) process.exit(1);
|
|
4
|
+
|
|
5
|
+
if (process.env.EZ_EXECUTOR_TRANSPORT === 'host') {
|
|
6
|
+
const host = JSON.parse(readFileSync(process.env.EZ_CONTROL_DIR + '/host-executor/heartbeat.json', 'utf8'));
|
|
7
|
+
if (Date.now() - host.at > 15000) process.exit(1);
|
|
8
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Explicit opt-in: node docker/plugin-smoke.mjs. Only synthetic provider data.
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import * as fs from 'node:fs/promises';
|
|
4
|
+
import {tmpdir} from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import {execFile,spawn} from 'node:child_process';
|
|
7
|
+
import {promisify} from 'node:util';
|
|
8
|
+
import {snapshot,init} from '../src/plugins/manager.mjs';
|
|
9
|
+
const exec=promisify(execFile),bin=new URL('../bin/ezenciel-agents-tools.mjs',import.meta.url).pathname;
|
|
10
|
+
const root=await fs.mkdtemp(path.join(tmpdir(),'ez-plugin-docker-'));
|
|
11
|
+
const source=path.join(root,'source'),home=path.join(root,'tools'),mind=path.join(root,'mind');
|
|
12
|
+
const whatsappSource=path.resolve(process.env.EZ_WHATSAPP_SOURCE || new URL('../../ez_whatsapp',import.meta.url).pathname);
|
|
13
|
+
let record;
|
|
14
|
+
const call=async(...args)=>(await exec(process.execPath,[bin,'--home',home,...args],{maxBuffer:4*1024*1024})).stdout;
|
|
15
|
+
try {
|
|
16
|
+
await fs.mkdir(source);await fs.mkdir(mind);
|
|
17
|
+
const original=await snapshot(whatsappSource);
|
|
18
|
+
for(const [name,f]of original.files) {await fs.mkdir(path.dirname(path.join(source,name)),{recursive:true});await fs.writeFile(path.join(source,name),f.data,{mode:f.mode});}
|
|
19
|
+
await fs.copyFile(path.join(whatsappSource,'docker/fixture.mjs'),path.join(source,'src/transport.mjs'));
|
|
20
|
+
const m=JSON.parse(await fs.readFile(path.join(source,'ez-plugin.json')));m.commands.probe={executable:'bin/ez-whatsapp.mjs',args:[]};await fs.writeFile(path.join(source,'ez-plugin.json'),JSON.stringify(m));
|
|
21
|
+
const d=JSON.parse(await fs.readFile(path.join(source,'ez-deployment.json')));d.commands.probe={service:'whatsapp',argv:['node','-e',"console.log('ready');setInterval(()=>{},1000)"]};await fs.writeFile(path.join(source,'ez-deployment.json'),JSON.stringify(d));
|
|
22
|
+
const p=await snapshot(source);await init(home,mind);
|
|
23
|
+
console.log('Installing isolated WhatsApp snapshot with synthetic transport…');
|
|
24
|
+
const installed=JSON.parse(await call('plugins','install','whatsapp','--source',source,'--revision',p.revision));assert.equal(installed.started,false);
|
|
25
|
+
record=JSON.parse(await fs.readFile(path.join(home,'registry.json'))).plugins.whatsapp;
|
|
26
|
+
await call('plugins','start','whatsapp');
|
|
27
|
+
assert.equal(JSON.parse(await call('whatsapp','doctor','--json')).data.connected,true);
|
|
28
|
+
const first=JSON.parse(await call('whatsapp','inbox')).data;
|
|
29
|
+
assert.equal(first.messages.length,1);
|
|
30
|
+
const text=path.join(await fs.realpath(mind),'literal $(no execution) message.txt');await fs.writeFile(text,'Synthetic registry test');
|
|
31
|
+
const send=JSON.parse(await call('whatsapp','send','--to','+15551230000','--text-file',text,'--idempotency-key','registry:qa')).data;
|
|
32
|
+
assert.equal(send.state,'accepted');
|
|
33
|
+
const duplicate=JSON.parse(await call('whatsapp','send','--to','+15551230000','--text-file',text,'--idempotency-key','registry:qa')).data;assert.equal(duplicate.providerMessageId,send.providerMessageId);
|
|
34
|
+
await call('plugins','stop','whatsapp');await call('plugins','start','whatsapp');
|
|
35
|
+
assert.equal(JSON.parse(await call('whatsapp','operation','--idempotency-key','registry:qa')).data.providerMessageId,send.providerMessageId);
|
|
36
|
+
assert.equal(JSON.parse(await call('whatsapp','inbox')).data.nextCursor,first.nextCursor);
|
|
37
|
+
const probe=spawn(process.execPath,[bin,'--home',home,'probe'],{stdio:['ignore','pipe','pipe']});
|
|
38
|
+
await new Promise((resolve,reject)=>{const timeout=setTimeout(()=>reject(Error('Probe never started')),20000);probe.stdout.once('data',()=>{clearTimeout(timeout);resolve();});});
|
|
39
|
+
const closed=new Promise(resolve=>probe.once('close',resolve));probe.kill('SIGTERM');assert.equal(await closed,130);
|
|
40
|
+
const clients=(await exec('docker',['ps','-a','--filter',`name=${record.project}-call-`,'--format','{{.Names}}'])).stdout.trim();assert.equal(clients,'');
|
|
41
|
+
assert.equal(JSON.parse(await call('whatsapp','doctor')).data.connected,true);
|
|
42
|
+
await call('plugins','uninstall','whatsapp');
|
|
43
|
+
const volumes=(await exec('docker',['volume','ls','--filter',`label=com.docker.compose.project=${record.project}`,'--format','{{.Name}}'])).stdout.trim();assert(volumes);
|
|
44
|
+
console.log('PASS: install without startup; registered CLI; synthetic account/read/send; literal file path; idempotency; stop/start persistence; data-preserving uninstall. No real provider calls.');
|
|
45
|
+
} catch(error) { if(record)console.error((await exec('docker',['compose','-p',record.project,'-f',record.compose,'logs','--tail','30']).catch(()=>({stdout:''}))).stdout);throw error; } finally {
|
|
46
|
+
if(record){await exec('docker',['compose','-p',record.project,'-f',record.compose,'down','--volumes']).catch(()=>{});await exec('docker',['image','rm',`${record.project}-whatsapp:${record.revision.slice(7,23)}`]).catch(()=>{});}
|
|
47
|
+
await fs.rm(root,{recursive:true,force:true});
|
|
48
|
+
}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
lockfileVersion: '9.0'
|
|
2
|
+
|
|
3
|
+
settings:
|
|
4
|
+
autoInstallPeers: true
|
|
5
|
+
excludeLinksFromLockfile: false
|
|
6
|
+
|
|
7
|
+
importers:
|
|
8
|
+
|
|
9
|
+
.:
|
|
10
|
+
dependencies:
|
|
11
|
+
grammy:
|
|
12
|
+
specifier: ^1.39.3
|
|
13
|
+
version: 1.46.0
|
|
14
|
+
tsx:
|
|
15
|
+
specifier: ^4.21.0
|
|
16
|
+
version: 4.23.13
|
|
17
|
+
devDependencies:
|
|
18
|
+
'@types/node':
|
|
19
|
+
specifier: ^24.10.1
|
|
20
|
+
version: 24.13.3
|
|
21
|
+
typescript:
|
|
22
|
+
specifier: ^5.9.3
|
|
23
|
+
version: 5.9.3
|
|
24
|
+
|
|
25
|
+
packages:
|
|
26
|
+
|
|
27
|
+
'@esbuild/aix-ppc64@0.28.2':
|
|
28
|
+
resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==}
|
|
29
|
+
engines: {node: '>=18'}
|
|
30
|
+
cpu: [ppc64]
|
|
31
|
+
os: [aix]
|
|
32
|
+
|
|
33
|
+
'@esbuild/android-arm64@0.28.2':
|
|
34
|
+
resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==}
|
|
35
|
+
engines: {node: '>=18'}
|
|
36
|
+
cpu: [arm64]
|
|
37
|
+
os: [android]
|
|
38
|
+
|
|
39
|
+
'@esbuild/android-arm@0.28.2':
|
|
40
|
+
resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==}
|
|
41
|
+
engines: {node: '>=18'}
|
|
42
|
+
cpu: [arm]
|
|
43
|
+
os: [android]
|
|
44
|
+
|
|
45
|
+
'@esbuild/android-x64@0.28.2':
|
|
46
|
+
resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==}
|
|
47
|
+
engines: {node: '>=18'}
|
|
48
|
+
cpu: [x64]
|
|
49
|
+
os: [android]
|
|
50
|
+
|
|
51
|
+
'@esbuild/darwin-arm64@0.28.2':
|
|
52
|
+
resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==}
|
|
53
|
+
engines: {node: '>=18'}
|
|
54
|
+
cpu: [arm64]
|
|
55
|
+
os: [darwin]
|
|
56
|
+
|
|
57
|
+
'@esbuild/darwin-x64@0.28.2':
|
|
58
|
+
resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==}
|
|
59
|
+
engines: {node: '>=18'}
|
|
60
|
+
cpu: [x64]
|
|
61
|
+
os: [darwin]
|
|
62
|
+
|
|
63
|
+
'@esbuild/freebsd-arm64@0.28.2':
|
|
64
|
+
resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==}
|
|
65
|
+
engines: {node: '>=18'}
|
|
66
|
+
cpu: [arm64]
|
|
67
|
+
os: [freebsd]
|
|
68
|
+
|
|
69
|
+
'@esbuild/freebsd-x64@0.28.2':
|
|
70
|
+
resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==}
|
|
71
|
+
engines: {node: '>=18'}
|
|
72
|
+
cpu: [x64]
|
|
73
|
+
os: [freebsd]
|
|
74
|
+
|
|
75
|
+
'@esbuild/linux-arm64@0.28.2':
|
|
76
|
+
resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==}
|
|
77
|
+
engines: {node: '>=18'}
|
|
78
|
+
cpu: [arm64]
|
|
79
|
+
os: [linux]
|
|
80
|
+
|
|
81
|
+
'@esbuild/linux-arm@0.28.2':
|
|
82
|
+
resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==}
|
|
83
|
+
engines: {node: '>=18'}
|
|
84
|
+
cpu: [arm]
|
|
85
|
+
os: [linux]
|
|
86
|
+
|
|
87
|
+
'@esbuild/linux-ia32@0.28.2':
|
|
88
|
+
resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==}
|
|
89
|
+
engines: {node: '>=18'}
|
|
90
|
+
cpu: [ia32]
|
|
91
|
+
os: [linux]
|
|
92
|
+
|
|
93
|
+
'@esbuild/linux-loong64@0.28.2':
|
|
94
|
+
resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==}
|
|
95
|
+
engines: {node: '>=18'}
|
|
96
|
+
cpu: [loong64]
|
|
97
|
+
os: [linux]
|
|
98
|
+
|
|
99
|
+
'@esbuild/linux-mips64el@0.28.2':
|
|
100
|
+
resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==}
|
|
101
|
+
engines: {node: '>=18'}
|
|
102
|
+
cpu: [mips64el]
|
|
103
|
+
os: [linux]
|
|
104
|
+
|
|
105
|
+
'@esbuild/linux-ppc64@0.28.2':
|
|
106
|
+
resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==}
|
|
107
|
+
engines: {node: '>=18'}
|
|
108
|
+
cpu: [ppc64]
|
|
109
|
+
os: [linux]
|
|
110
|
+
|
|
111
|
+
'@esbuild/linux-riscv64@0.28.2':
|
|
112
|
+
resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==}
|
|
113
|
+
engines: {node: '>=18'}
|
|
114
|
+
cpu: [riscv64]
|
|
115
|
+
os: [linux]
|
|
116
|
+
|
|
117
|
+
'@esbuild/linux-s390x@0.28.2':
|
|
118
|
+
resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==}
|
|
119
|
+
engines: {node: '>=18'}
|
|
120
|
+
cpu: [s390x]
|
|
121
|
+
os: [linux]
|
|
122
|
+
|
|
123
|
+
'@esbuild/linux-x64@0.28.2':
|
|
124
|
+
resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==}
|
|
125
|
+
engines: {node: '>=18'}
|
|
126
|
+
cpu: [x64]
|
|
127
|
+
os: [linux]
|
|
128
|
+
|
|
129
|
+
'@esbuild/netbsd-arm64@0.28.2':
|
|
130
|
+
resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==}
|
|
131
|
+
engines: {node: '>=18'}
|
|
132
|
+
cpu: [arm64]
|
|
133
|
+
os: [netbsd]
|
|
134
|
+
|
|
135
|
+
'@esbuild/netbsd-x64@0.28.2':
|
|
136
|
+
resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==}
|
|
137
|
+
engines: {node: '>=18'}
|
|
138
|
+
cpu: [x64]
|
|
139
|
+
os: [netbsd]
|
|
140
|
+
|
|
141
|
+
'@esbuild/openbsd-arm64@0.28.2':
|
|
142
|
+
resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==}
|
|
143
|
+
engines: {node: '>=18'}
|
|
144
|
+
cpu: [arm64]
|
|
145
|
+
os: [openbsd]
|
|
146
|
+
|
|
147
|
+
'@esbuild/openbsd-x64@0.28.2':
|
|
148
|
+
resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==}
|
|
149
|
+
engines: {node: '>=18'}
|
|
150
|
+
cpu: [x64]
|
|
151
|
+
os: [openbsd]
|
|
152
|
+
|
|
153
|
+
'@esbuild/openharmony-arm64@0.28.2':
|
|
154
|
+
resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==}
|
|
155
|
+
engines: {node: '>=18'}
|
|
156
|
+
cpu: [arm64]
|
|
157
|
+
os: [openharmony]
|
|
158
|
+
|
|
159
|
+
'@esbuild/sunos-x64@0.28.2':
|
|
160
|
+
resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==}
|
|
161
|
+
engines: {node: '>=18'}
|
|
162
|
+
cpu: [x64]
|
|
163
|
+
os: [sunos]
|
|
164
|
+
|
|
165
|
+
'@esbuild/win32-arm64@0.28.2':
|
|
166
|
+
resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==}
|
|
167
|
+
engines: {node: '>=18'}
|
|
168
|
+
cpu: [arm64]
|
|
169
|
+
os: [win32]
|
|
170
|
+
|
|
171
|
+
'@esbuild/win32-ia32@0.28.2':
|
|
172
|
+
resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==}
|
|
173
|
+
engines: {node: '>=18'}
|
|
174
|
+
cpu: [ia32]
|
|
175
|
+
os: [win32]
|
|
176
|
+
|
|
177
|
+
'@esbuild/win32-x64@0.28.2':
|
|
178
|
+
resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==}
|
|
179
|
+
engines: {node: '>=18'}
|
|
180
|
+
cpu: [x64]
|
|
181
|
+
os: [win32]
|
|
182
|
+
|
|
183
|
+
'@grammyjs/types@5.0.0':
|
|
184
|
+
resolution: {integrity: sha512-iq1Qrq1iPKkB8yAa0qSuIURMZOCuqTY5pWy5gHpCeL1oQ+GPadGhw/cDTVE8waJwuCzacUzuIjRv1sESvk7u7A==}
|
|
185
|
+
|
|
186
|
+
'@types/node@24.13.3':
|
|
187
|
+
resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==}
|
|
188
|
+
|
|
189
|
+
abort-controller@3.0.0:
|
|
190
|
+
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
|
191
|
+
engines: {node: '>=6.5'}
|
|
192
|
+
|
|
193
|
+
debug@4.4.3:
|
|
194
|
+
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
|
195
|
+
engines: {node: '>=6.0'}
|
|
196
|
+
peerDependencies:
|
|
197
|
+
supports-color: '*'
|
|
198
|
+
peerDependenciesMeta:
|
|
199
|
+
supports-color:
|
|
200
|
+
optional: true
|
|
201
|
+
|
|
202
|
+
esbuild@0.28.2:
|
|
203
|
+
resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==}
|
|
204
|
+
engines: {node: '>=18'}
|
|
205
|
+
hasBin: true
|
|
206
|
+
|
|
207
|
+
event-target-shim@5.0.1:
|
|
208
|
+
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
|
|
209
|
+
engines: {node: '>=6'}
|
|
210
|
+
|
|
211
|
+
fsevents@2.3.3:
|
|
212
|
+
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
|
213
|
+
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
|
214
|
+
os: [darwin]
|
|
215
|
+
|
|
216
|
+
grammy@1.46.0:
|
|
217
|
+
resolution: {integrity: sha512-/8Qw+iisrUdOMk+p2mjEHouMm/BBdBEN1DHh16wiTpRUZkxDG3PxexdjCvR+wvK3LWPdrEvnQbdrwpU954sPhg==}
|
|
218
|
+
engines: {node: ^12.20.0 || >=14.13.1}
|
|
219
|
+
|
|
220
|
+
ms@2.1.3:
|
|
221
|
+
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
|
222
|
+
|
|
223
|
+
node-fetch@2.7.0:
|
|
224
|
+
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
|
225
|
+
engines: {node: 4.x || >=6.0.0}
|
|
226
|
+
peerDependencies:
|
|
227
|
+
encoding: ^0.1.0
|
|
228
|
+
peerDependenciesMeta:
|
|
229
|
+
encoding:
|
|
230
|
+
optional: true
|
|
231
|
+
|
|
232
|
+
tr46@0.0.3:
|
|
233
|
+
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
|
234
|
+
|
|
235
|
+
tsx@4.23.13:
|
|
236
|
+
resolution: {integrity: sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==}
|
|
237
|
+
engines: {node: '>=18.0.0'}
|
|
238
|
+
hasBin: true
|
|
239
|
+
|
|
240
|
+
typescript@5.9.3:
|
|
241
|
+
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
|
242
|
+
engines: {node: '>=14.17'}
|
|
243
|
+
hasBin: true
|
|
244
|
+
|
|
245
|
+
undici-types@7.18.2:
|
|
246
|
+
resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
|
|
247
|
+
|
|
248
|
+
webidl-conversions@3.0.1:
|
|
249
|
+
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
|
250
|
+
|
|
251
|
+
whatwg-url@5.0.0:
|
|
252
|
+
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
|
253
|
+
|
|
254
|
+
snapshots:
|
|
255
|
+
|
|
256
|
+
'@esbuild/aix-ppc64@0.28.2':
|
|
257
|
+
optional: true
|
|
258
|
+
|
|
259
|
+
'@esbuild/android-arm64@0.28.2':
|
|
260
|
+
optional: true
|
|
261
|
+
|
|
262
|
+
'@esbuild/android-arm@0.28.2':
|
|
263
|
+
optional: true
|
|
264
|
+
|
|
265
|
+
'@esbuild/android-x64@0.28.2':
|
|
266
|
+
optional: true
|
|
267
|
+
|
|
268
|
+
'@esbuild/darwin-arm64@0.28.2':
|
|
269
|
+
optional: true
|
|
270
|
+
|
|
271
|
+
'@esbuild/darwin-x64@0.28.2':
|
|
272
|
+
optional: true
|
|
273
|
+
|
|
274
|
+
'@esbuild/freebsd-arm64@0.28.2':
|
|
275
|
+
optional: true
|
|
276
|
+
|
|
277
|
+
'@esbuild/freebsd-x64@0.28.2':
|
|
278
|
+
optional: true
|
|
279
|
+
|
|
280
|
+
'@esbuild/linux-arm64@0.28.2':
|
|
281
|
+
optional: true
|
|
282
|
+
|
|
283
|
+
'@esbuild/linux-arm@0.28.2':
|
|
284
|
+
optional: true
|
|
285
|
+
|
|
286
|
+
'@esbuild/linux-ia32@0.28.2':
|
|
287
|
+
optional: true
|
|
288
|
+
|
|
289
|
+
'@esbuild/linux-loong64@0.28.2':
|
|
290
|
+
optional: true
|
|
291
|
+
|
|
292
|
+
'@esbuild/linux-mips64el@0.28.2':
|
|
293
|
+
optional: true
|
|
294
|
+
|
|
295
|
+
'@esbuild/linux-ppc64@0.28.2':
|
|
296
|
+
optional: true
|
|
297
|
+
|
|
298
|
+
'@esbuild/linux-riscv64@0.28.2':
|
|
299
|
+
optional: true
|
|
300
|
+
|
|
301
|
+
'@esbuild/linux-s390x@0.28.2':
|
|
302
|
+
optional: true
|
|
303
|
+
|
|
304
|
+
'@esbuild/linux-x64@0.28.2':
|
|
305
|
+
optional: true
|
|
306
|
+
|
|
307
|
+
'@esbuild/netbsd-arm64@0.28.2':
|
|
308
|
+
optional: true
|
|
309
|
+
|
|
310
|
+
'@esbuild/netbsd-x64@0.28.2':
|
|
311
|
+
optional: true
|
|
312
|
+
|
|
313
|
+
'@esbuild/openbsd-arm64@0.28.2':
|
|
314
|
+
optional: true
|
|
315
|
+
|
|
316
|
+
'@esbuild/openbsd-x64@0.28.2':
|
|
317
|
+
optional: true
|
|
318
|
+
|
|
319
|
+
'@esbuild/openharmony-arm64@0.28.2':
|
|
320
|
+
optional: true
|
|
321
|
+
|
|
322
|
+
'@esbuild/sunos-x64@0.28.2':
|
|
323
|
+
optional: true
|
|
324
|
+
|
|
325
|
+
'@esbuild/win32-arm64@0.28.2':
|
|
326
|
+
optional: true
|
|
327
|
+
|
|
328
|
+
'@esbuild/win32-ia32@0.28.2':
|
|
329
|
+
optional: true
|
|
330
|
+
|
|
331
|
+
'@esbuild/win32-x64@0.28.2':
|
|
332
|
+
optional: true
|
|
333
|
+
|
|
334
|
+
'@grammyjs/types@5.0.0': {}
|
|
335
|
+
|
|
336
|
+
'@types/node@24.13.3':
|
|
337
|
+
dependencies:
|
|
338
|
+
undici-types: 7.18.2
|
|
339
|
+
|
|
340
|
+
abort-controller@3.0.0:
|
|
341
|
+
dependencies:
|
|
342
|
+
event-target-shim: 5.0.1
|
|
343
|
+
|
|
344
|
+
debug@4.4.3:
|
|
345
|
+
dependencies:
|
|
346
|
+
ms: 2.1.3
|
|
347
|
+
|
|
348
|
+
esbuild@0.28.2:
|
|
349
|
+
optionalDependencies:
|
|
350
|
+
'@esbuild/aix-ppc64': 0.28.2
|
|
351
|
+
'@esbuild/android-arm': 0.28.2
|
|
352
|
+
'@esbuild/android-arm64': 0.28.2
|
|
353
|
+
'@esbuild/android-x64': 0.28.2
|
|
354
|
+
'@esbuild/darwin-arm64': 0.28.2
|
|
355
|
+
'@esbuild/darwin-x64': 0.28.2
|
|
356
|
+
'@esbuild/freebsd-arm64': 0.28.2
|
|
357
|
+
'@esbuild/freebsd-x64': 0.28.2
|
|
358
|
+
'@esbuild/linux-arm': 0.28.2
|
|
359
|
+
'@esbuild/linux-arm64': 0.28.2
|
|
360
|
+
'@esbuild/linux-ia32': 0.28.2
|
|
361
|
+
'@esbuild/linux-loong64': 0.28.2
|
|
362
|
+
'@esbuild/linux-mips64el': 0.28.2
|
|
363
|
+
'@esbuild/linux-ppc64': 0.28.2
|
|
364
|
+
'@esbuild/linux-riscv64': 0.28.2
|
|
365
|
+
'@esbuild/linux-s390x': 0.28.2
|
|
366
|
+
'@esbuild/linux-x64': 0.28.2
|
|
367
|
+
'@esbuild/netbsd-arm64': 0.28.2
|
|
368
|
+
'@esbuild/netbsd-x64': 0.28.2
|
|
369
|
+
'@esbuild/openbsd-arm64': 0.28.2
|
|
370
|
+
'@esbuild/openbsd-x64': 0.28.2
|
|
371
|
+
'@esbuild/openharmony-arm64': 0.28.2
|
|
372
|
+
'@esbuild/sunos-x64': 0.28.2
|
|
373
|
+
'@esbuild/win32-arm64': 0.28.2
|
|
374
|
+
'@esbuild/win32-ia32': 0.28.2
|
|
375
|
+
'@esbuild/win32-x64': 0.28.2
|
|
376
|
+
|
|
377
|
+
event-target-shim@5.0.1: {}
|
|
378
|
+
|
|
379
|
+
fsevents@2.3.3:
|
|
380
|
+
optional: true
|
|
381
|
+
|
|
382
|
+
grammy@1.46.0:
|
|
383
|
+
dependencies:
|
|
384
|
+
'@grammyjs/types': 5.0.0
|
|
385
|
+
abort-controller: 3.0.0
|
|
386
|
+
debug: 4.4.3
|
|
387
|
+
node-fetch: 2.7.0
|
|
388
|
+
transitivePeerDependencies:
|
|
389
|
+
- encoding
|
|
390
|
+
- supports-color
|
|
391
|
+
|
|
392
|
+
ms@2.1.3: {}
|
|
393
|
+
|
|
394
|
+
node-fetch@2.7.0:
|
|
395
|
+
dependencies:
|
|
396
|
+
whatwg-url: 5.0.0
|
|
397
|
+
|
|
398
|
+
tr46@0.0.3: {}
|
|
399
|
+
|
|
400
|
+
tsx@4.23.13:
|
|
401
|
+
dependencies:
|
|
402
|
+
esbuild: 0.28.2
|
|
403
|
+
optionalDependencies:
|
|
404
|
+
fsevents: 2.3.3
|
|
405
|
+
|
|
406
|
+
typescript@5.9.3: {}
|
|
407
|
+
|
|
408
|
+
undici-types@7.18.2: {}
|
|
409
|
+
|
|
410
|
+
webidl-conversions@3.0.1: {}
|
|
411
|
+
|
|
412
|
+
whatwg-url@5.0.0:
|
|
413
|
+
dependencies:
|
|
414
|
+
tr46: 0.0.3
|
|
415
|
+
webidl-conversions: 3.0.1
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RunStore } from '../src/runs.js'
|
|
2
|
+
|
|
3
|
+
// Called only after the deployment's kernel writer lock is held. No worker
|
|
4
|
+
// from a previous container can still own this deployment; PIDs may be reused.
|
|
5
|
+
export const recoverInterruptedRuns = async (controlDir: string) => {
|
|
6
|
+
const store = new RunStore(controlDir)
|
|
7
|
+
for (const run of await store.list()) {
|
|
8
|
+
if (run.status === 'running')
|
|
9
|
+
await store.patch(run.id, { status: 'failed', endedAt: new Date().toISOString() })
|
|
10
|
+
}
|
|
11
|
+
}
|
package/docker/run.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readFileSync, closeSync } from 'node:fs'
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { executorEnvironment, executorInvocation } from '../src/executor.js'
|
|
4
|
+
import { parseEnv } from 'node:util'
|
|
5
|
+
import { writeFile, rm } from 'node:fs/promises'
|
|
6
|
+
import { loadConfig } from '../src/config.js'
|
|
7
|
+
import { recoverInterruptedRuns } from './recovery.js'
|
|
8
|
+
import { createRelay } from '../src/index.js'
|
|
9
|
+
import { packageVersion } from '../src/version.js'
|
|
10
|
+
|
|
11
|
+
// Provider errors can contain credential-bearing URLs; never dump error causes.
|
|
12
|
+
process.on('uncaughtException', (error) => {
|
|
13
|
+
console.error(error.name + ': ' + error.message.replace(/bot\d+:[A-Za-z0-9_-]+/g, 'bot[redacted]'))
|
|
14
|
+
process.exit(1)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// Read and close the root-opened descriptor before any executor can start.
|
|
18
|
+
// Secrets never enter the initial process environment or a readable mount.
|
|
19
|
+
let privateEnv: NodeJS.ProcessEnv = {}
|
|
20
|
+
try { privateEnv = parseEnv(readFileSync(3, 'utf8')) } catch (error) {
|
|
21
|
+
if ((error as NodeJS.ErrnoException).code !== 'EINVAL' && (error as NodeJS.ErrnoException).code !== 'EBADF') throw error
|
|
22
|
+
} finally { try { closeSync(3) } catch {} }
|
|
23
|
+
for (const [key, value] of Object.entries(privateEnv)) {
|
|
24
|
+
if (value !== undefined && ['TELEGRAM_BOT_TOKEN', 'GEMINI_API_KEY', 'OPENAI_API_KEY'].includes(key)) process.env[key] = value
|
|
25
|
+
}
|
|
26
|
+
privateEnv = {}
|
|
27
|
+
const [command = 'start', ...args] = process.argv.slice(2)
|
|
28
|
+
process.argv = [process.argv[0], '', ...args]
|
|
29
|
+
if (['start', 'smoke'].includes(command)) await recoverInterruptedRuns(loadConfig().controlDir)
|
|
30
|
+
if (command === 'start') {
|
|
31
|
+
const relay = createRelay(loadConfig())
|
|
32
|
+
const heartbeat = '/state/control/heartbeat.json'
|
|
33
|
+
await rm(heartbeat, { force: true })
|
|
34
|
+
const timer = setInterval(() => {
|
|
35
|
+
if (relay.bot.isRunning()) void writeFile(heartbeat, JSON.stringify({ at: Date.now(), polling: true, version: packageVersion }), { mode: 0o600 })
|
|
36
|
+
}, 5000)
|
|
37
|
+
for (const signal of ['SIGINT', 'SIGTERM'] as const) process.once(signal, () => { clearInterval(timer); void relay.stop() })
|
|
38
|
+
try { await relay.start() } finally { clearInterval(timer); await rm(heartbeat, { force: true }) }
|
|
39
|
+
} else if (command === 'smoke') {
|
|
40
|
+
await import('../scripts/smoke.js')
|
|
41
|
+
} else if (command === 'exec') {
|
|
42
|
+
if (!args.length) throw new Error('exec requires a command')
|
|
43
|
+
const invocation = executorInvocation(args[0], args.slice(1))
|
|
44
|
+
const child = spawn(invocation.command, invocation.args, { stdio: 'inherit', env: executorEnvironment() })
|
|
45
|
+
child.on('error', () => { console.error('Command could not start'); process.exitCode = 1 })
|
|
46
|
+
for (const signal of ['SIGINT', 'SIGTERM'] as const) process.once(signal, () => child.kill(signal))
|
|
47
|
+
child.on('exit', (code) => { process.exitCode = code ?? 1 })
|
|
48
|
+
} else if (command === 'setup') {
|
|
49
|
+
await (await import('../src/setup.js')).runCli()
|
|
50
|
+
} else if (['owner', 'source', 'message', 'react'].includes(command)) {
|
|
51
|
+
await import(`../src/${command === 'source' ? 'source-cli' : command}.js`)
|
|
52
|
+
} else throw new Error('Use start, smoke, exec, setup, owner, source, message or react')
|