agent-device runs as an optional module on workers
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 8/100
- Loại issue
- Tái cấu trúc
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
Hướng nghiên cứu
Start with src/daemon/main.ts, where agent-device is wired by static import on the worker path (lines 329-645), and src/core/config.ts, which holds its config type, validator and gateway warning. The change moves this into a new src/agent-device/definition.ts and worker.ts behind the module host from #595. Done means a worker with the module off never calls loadWorker, the old agentDevice key is rejected as unknown, and the listed tests pass under the new capabilities key.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Part of #591.
Scope
Moves agent-device's worker side onto the module host from #595. After
this PR, agent-device is the registry's first module:
- It is turned on with
capabilities.agent-device.enabled. The top-level
agentDevicekey goes. - A worker with it turned off never loads its code.
src/daemon/main.tsno longer wires it on a worker.
Its behaviour is otherwise unchanged, with three exceptions:
- With agent-device off, simlock no longer stops an agent-device daemon
left by a crash (ADR 0030 §2). - On
daemon stop, agent-device's two stop steps are now bounded by the
Hook deadline;
today they have no limit. Its slowest stop is about 22 s: a running
--versioncheck or reap (ps5 s, SIGTERM 10 s, SIGKILL 2 s,
F18). Past 30 s the drivers are disposed with agent-device still
stopping, and the warning names it. - A gateway's warning for
commanduses the generic text (below).
The gateway side stays hand-wired in main.ts until #598. In this PR it
loads agent-device with a dynamic import(), only when it is turned on.
That way no daemon loads agent-device's code through a static import.
Test fixtures that build a whole Config lose their agentDevice line.
That edit is mechanical and is not counted in this task's size. Setup
lines that turn agent-device on (edge.test.ts, gateway-front.test.ts,
main.test.ts, worker-capabilities.e2e.test.ts,
lease-requires.e2e.test.ts) move to capabilities["agent-device"]
instead. The slow-lane files are rewritten (F14).
In short
An operator turns agent-device on under capabilities:
{ "capabilities": { "agent-device": { "enabled": true, "command": "agent-device", "leaseTtlCapMs": 60000 } } }
A config that still says { "agentDevice": { "enabled": true } } gets
Unknown config key: "agentDevice", and agent-device stays off. The
integration is unreleased, so nothing migrates the old key.
flowchart LR
R["module-registry: agent-device *"] --> H[module host]
H -->|on| L["loadWorker() → createWorker *"]
H -->|off| O["agent-device: off<br/>no code loaded, no reap *"]
If this goes wrong: agent-device does not start on a worker that turns it
on, or simlock daemon stop leaves its process behind.
Technical spec
Facts
| # | Fact | Source |
|---|---|---|
| F1 | main.ts statically imports 15 names from ../agent-device/index.js. |
src/daemon/main.ts:5-21 |
| F2 | On a worker, main.ts builds agent-device's supervisor, edge parts, lease-end participant, capability source (with an off stub when disabled), relay target, HTTP front, stop steps and start. |
src/daemon/main.ts:329-357, :372, :484-488, :522-527, :548-551, :571-575, :592-596, :630-645 |
| F3 | agentDevice.stop() runs in dispose before the drivers, because the Android driver stops the adb server agent-device uses. |
src/daemon/main.ts:548-551 |
| F4 | stopAuxiliary disposes the edge and cancels waiting allocates through leasing.cancelPending. |
src/daemon/main.ts:571-575 |
| F5 | onSocketClaimed starts the supervisor, not awaited, unless a test passed agentDeviceUpstream. |
src/daemon/main.ts:592-596 |
| F6 | With config.enabled false, the supervisor starts in off; start() reaps a recorded daemon, then stays off. |
src/agent-device/host/agent-device-supervisor.ts:163, :255-286 |
| F7 | Two supervisor tests pin the off path. | src/agent-device/host/agent-device-supervisor.test.ts:346, :1161 |
| F8 | The agent-device config is { enabled, command, leaseTtlCapMs? }, default { enabled: false, command: "agent-device" }, leaseTtlCapMs from 5000 to lease.maxTtlMs; command is worker-only. The core holds its type, the cap check and its call, its gateway key, its gateway warning, its default and its validator. The validators come from src/core/validation.ts, which src/core/index.ts does not export; invalidValue words an error Invalid config value for "<path>": expected <what>. |
src/core/config.ts:253-257, :410, :452-459, :485, :494, :522-530, :763, :916-920; src/core/validation.ts:17-19, :17-118 |
| F9 | Config tests for agent-device: one describe block of 8 tests, plus a gateway test. | src/core/config.test.ts:1961-2036, :1776 |
| F10 | configSchema names agentDevice. |
src/contract/schemas.ts:902-906 |
| F11 | Tests pass agentDeviceUpstream or agentDeviceHealth to startDaemon. |
src/agent-device/edge.test.ts:165; src/agent-device/gateway-front.test.ts:270; src/daemon/main.test.ts:2430; src/daemon/worker-capabilities.e2e.test.ts:66; src/daemon/lease-requires.e2e.test.ts:89 |
| F12 | Five assertions name the old key: three in those suites, two in the supervisor's tests. | src/agent-device/gateway-front.test.ts:703, :709-711; src/agent-device/edge.test.ts:2098-2105; src/agent-device/host/agent-device-supervisor.test.ts:421, :480 |
| F13 | The supervisor's remedies tell the user to set agentDevice.command. |
src/agent-device/host/agent-device-supervisor.ts:228-230 |
| F14 | The slow-lane tests write and delete agentDevice in a config. |
e2e/slow-agent-device.test.ts; e2e/slow-agent-device-gateway.test.ts:160, :173, :264, :280 |
| F15 | docs/CONFIGURATION.md documents the agentDevice.* keys, the gateway slice, and "A daemon a killed Simlock left behind is stopped at the next start". |
docs/CONFIGURATION.md:38-40, :162-169 |
| F16 | The gateway path reads config.agentDevice for enabled and leaseTtlCapMs. |
src/daemon/main.ts:827, :958-960 |
| F17 | dependency-cruiser records import() as dynamic-import, import type as type-only, and import("x").T as type-import. |
node_modules/dependency-cruiser/src/extract/tsc/extract-typescript-deps.mjs:82, :424, :436 (18.4.0) |
| F18 | The supervisor's waits: ps 5 s, --version 10 s, SIGTERM grace 10 s, SIGKILL grace 2 s. |
src/agent-device/host/agent-device-supervisor.ts:76-80 |
| F19 | agent-device's front imports src/http's helpers and types. |
src/agent-device/front/front.ts:1; src/agent-device/front/allocate.ts:4-6; src/agent-device/host/host.ts:3 |
| F20 | Today a gateway warns Ignoring "agentDevice.command": it names the program a worker runs, and this daemon runs in gateway mode. |
src/core/config.ts:528 |
Modules touched
flowchart LR
main["daemon/main.ts *"] --> host["modules host"]
main --> reg["module-registry *"]
reg --> def["agent-device/definition *new*"]
def -. loadWorker .-> w["agent-device/worker *new*"]
main -. "dynamic import (gateway, until #598)" .-> idx["agent-device/index *"]
w --> sup["agent-device supervisor *"]
cfg["core/config.ts, core/index.ts *"]
contract["contract/schemas.ts, protocol.ts *"]
Surface and extension points
src/agent-device/definition.ts exports agentDeviceModule, an
OptionalModuleDefinition:
name: "agent-device".config:- F8's validator without
enabled, which the core owns (#595), built
from validators thatsrc/core/index.tsnow exports
(objectValidator,nonEmptyString,integerInRange,
invalidValue); - F8's defaults without
enabled; gatewayKeys: ["leaseTtlCapMs"];- a
checkthatleaseTtlCapMsis at mostlease.maxTtlMs, failing
withinvalidValue's text,
Invalid config value for "capabilities.agent-device.leaseTtlCapMs": expected at most lease.maxTtlMs.
- F8's validator without
- Every agent-device piece F8 lists leaves
src/core/config.ts. loadWorker: () => import("./worker.js"). NoloadGatewayuntil #598.
src/agent-device/worker.ts exports createWorker(ctx). It builds the
supervisor and the edge parts from ctx (F2), and returns:
capability, from today's capability source;relayTarget, from today's relay target;mount, the HTTP front's handler (the front keeps usingsrc/http's
helpers, F19; ADR 0030 §6), withctx.config.leaseTtlCapMsand
maxRunMs = ctx.daemonConfig.lease.maxTtlMs;findings, today'sagentDeviceFindingsreturning
{ message, remedy }; the host now stampsmodule(#596's line moves
here);hooks.afterSocketClaimed:void supervisor.start()(F5);hooks.beforeDeviceReclaim: the lease-end participant;hooks.beforeDrain: dispose the edge, then cancel waiting allocates
throughctx.cancelPending(F4);hooks.beforeDriversDispose:supervisor.stop()(F3).
src/agent-device/testing.ts exports
agentDeviceModuleWith({ upstream?, health? }), a definition whose
createWorker uses the given fakes. With upstream, the supervisor is
never started, as F5 does today.
Other changes:
src/agent-device/index.tskeeps only what the gateway path uses
(F16).main.ts's gateway path loads it withawait import(...)only
whencapabilities.agent-device.enabledistrue. It reads the section
through the typedefinition.tsexports, and a missing section counts
as off. Every other name F1 lists leavesmain.ts.StartDaemonOptionsdropsagentDeviceUpstreamandagentDeviceHealth.- The supervisor drops its
enabledbranch (F6). It is built only for a
turned-on module. - The supervisor's remedies say
capabilities.agent-device.command(F13). - A gateway warns
Ignoring "capabilities.agent-device.command": it configures a worker, and this daemon runs in gateway mode.,
#595's generic text, in place of F20's. - New dependency-cruiser rule
main-loads-modules-lazily:main.ts
importssrc/agent-deviceonly asdynamic-import,type-onlyor
type-import(F17). #598 tightens it to no import at all.
Contract and event changes
configSchema drops agentDevice (F10); agent-device's section travels in
capabilities. This PR bumps the protocol by one. No event changes.
Other code on the same state
- The gateway path in
main.ts(F16) reads agent-device's config. It
switches toconfig.capabilities["agent-device"], with the same
behaviour. - #595's host tests pin agent-device's hand-wired entry first in the
capability list, and its stop steps before the hooks. With the hand
wiring gone, those tests assert the registry order only, with
agent-device as a registered module. - The core doctor gets only
host.findings()atmain.ts:329. - A leftover agent-device daemon while off: nothing acts on it any
more. The next start with agent-device on reaps it, as today (F6).
Rules in play
architecture.mdrules 18 and 21:main.tsnames no module on the
worker path.safety.md: the reap's ownership proof is unchanged.testing.md: delete only F7's two tests, whose path is gone. F9's tests
move, they are not deleted.documentation.md: F15, plusCLI.md,HTTP-API.mdandCLIENT.md
wherever they writeagentDevice.
Tests
Seam:
startDaemon({ optionalModules: [agentDeviceModuleWith({ upstream: fake })], configOverrides: { capabilities: { "agent-device": … } } })
in place of agentDeviceUpstream in the suites F11 names, modelled on
src/agent-device/edge.test.ts. Those suites still pass, with their setup
changed and F12's three assertions renamed to the new key.
- a worker with no
capabilities["agent-device"]section answers status.get with{ name: agent-device, state: off }, and so does one withenabled: false - a worker with agent-device off never calls agent-device's
loadWorker(a spying definition that wrapsagentDeviceModule) - a gateway with agent-device off, or with no section for it, mounts no
/v1/agent-device(as today) - a worker whose config has only the old
agentDevicekey warnsUnknown config key: "agentDevice"and reports agent-deviceoff - a worker with agent-device off starts no supervisor: no
psruns and no signal is sent, even with a recorded daemon on disk - F9's tests move to
src/agent-device/definition.test.ts, undercapabilities.agent-device(as today):- the defaults, and an explicit section kept as written;
commandrefused when empty, and when a number;leaseTtlCapMsaccepted at 5000 and atlease.maxTtlMs, refused as a fraction, refused below 5000, and refused abovelease.maxTtlMswithinvalidValue's text namingcapabilities.agent-device.leaseTtlCapMs;- a loaded config parsed through
configSchemakeeps the section; - on a gateway,
enabledandleaseTtlCapMsread without a warning, andcommandwarned about with the generic text
startDaemonwith agent-device on stops the agent-device child before the drivers are disposed (as today,main.test.ts:2449)- with agent-device on, a release still waits for agent-device's lease end before the device is reclaimed (as today)
daemon stopcancels an agent-device allocate waiting in the queue before leasing settles (as today)doctor.runreports{ kind: "module-unavailable", module: "agent-device" }, with the module stamped by the host- the supervisor's not-found and not-agent-device remedies name
capabilities.agent-device.command(F12's two supervisor assertions) config.getshows agent-device's section undercapabilities["agent-device"]and noagentDevicekey- the conformance suite runs over agent-device as a registered module
- dependency-cruiser fails a value import of
src/agent-devicefrommain.ts(a lint-harness case);pnpm lintpassing on this PR'smain.ts, with its dynamic and type imports, shows the allowed kinds pass - the protocol version is one above the base branch's
Done when
- Every Tests line passes, and every other test in the suites F11 names
passes with only its setup changed and F12's assertions renamed. - F7's two supervisor tests are deleted. No other agent-device test is
deleted. docs/CONFIGURATION.mddocumentscapabilities.agent-device.*. Its
leftover-daemon line says it applies with
capabilities.agent-device.enabledtrue.- F14's config writes and deletes use
capabilities["agent-device"]. On a
Mac with an iOS runtime:scripts/slow-e2e.sh e2e/slow-agent-device.test.ts
andscripts/slow-e2e.sh e2e/slow-agent-device-gateway.test.tspass.
Out of scope
- The gateway side moving onto the host (#598).
- The doctor finding's shape (#596).
Depends on
- #595
Written by an agent.
- Ngôn ngữ chính
- TypeScript
- Star
- 19
- Fork
- 1
- Merge trung bình
- 7 giờ 57 phút
- Pull request đã merge (30 ngày)
- 213
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của callstackincubator/simlock
-
Lint does not enforce index.ts boundaries for cleanup/, routing/, warm-pool/ and contract/ helpersĐang mởbug:new
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
callstackincubator/simlock#445 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug:new
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
callstackincubator/simlock#424 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
daemon-lifecycle e2e: the it.fails status test passes for the wrong reasonCó thể đã có người làm @V3RON đã nhận 7 ngày trước. Đang mởbug:triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
callstackincubator/simlock#422 · 1 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
feature:spec
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 8/100
callstackincubator/simlock#602 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agent-device's gateway side runs as an optional moduleCó thể đã có người làm @V3RON đã nhận hôm nay. Đang mởtask:ready
callstackincubator/simlock#598 · 2 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của callstackincubator/simlock
Issue tương tự
-
test: make the #3408 Claude OAuth token fixture obviously fake so secret scanners stop flagging itĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
code-yeongyu/senpi#3436 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 78/100
lingdojo/kana-dojo#32505 · 1 bình luận · 5 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
code-quality refactoring
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
github/gh-aw-firewall#10040 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
review-followup
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
griffinwork40/agent-afk#3868 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area: import-export bug status: needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
amatya-aditya/obsidian-rss-dashboard#1191 ·
Maintainer thường phản hồi trong vòng 1 ngày