Skip to content

feat(daemon): daemon status lists the registered provider plugins - #3768

Merged
thymikee merged 4 commits into
feat/plugin-registry-v2from
feat/plugin-registry-v2-status
Oct 17, 2026
Merged

thymikee merged 4 commits into
feat/plugin-registry-v2from
feat/plugin-registry-v2-status

Conversation

@thymikee

@thymikee thymikee commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Summary

Part 2 of 4 of #3755 (umbrella #3747), stacked on #3767. Blocked by #3748: do not merge before it.

  • agent-device daemon status [--state-dir <path>] [--json] reads daemon.json without contacting the daemon and lists every provider it registered (builtin/store/embedder, active/failed, typed error.reason). A record whose pid/start time no longer names a live process reports running: false.
  • plugins list --json still works without a daemon (it lists store selections), and when a daemon runs for the same --state-dir it also returns that daemon's inventory under daemon.
  • daemon and plugins schema, usage and help updated; daemon stays out of MCP (mcpExposed: false).
agent-device daemon status --json
agent-device plugins list --json

Not in this PR: the failed inventory entry inside the provider-not-registered error. #3748 owns that error, so I'll add the entry after rebasing onto it.

9 files.

Validation

pnpm check:affected --run --head a304bb7f40 (the stack top, which contains this layer): passed (exactCommit). CI owns integration, coverage and device lanes.

🤖 Generated with Claude Code

View guided diff Turn on auto-fix

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://callstack.github.io/agent-device/pr-preview/pr-3768/

Built to branch gh-pages at 2026-10-17 11:51 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.37 MB 5.37 MB +2.7 kB
Package (unpacked) 5.37 MB 5.37 MB +2.7 kB
Package (download) 1.62 MB 1.62 MB +889 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 26.2 ms 27.2 ms +1.0 ms
CLI --help 76.6 ms 76.3 ms -0.3 ms

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 9 files

You’re at about 93% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread src/commands/schema/command-overrides.ts Outdated
Comment thread src/commands/schema/command-overrides.ts Outdated
Comment thread packages/daemon-contracts/src/daemon-status.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files (changes from recent commits).

You’re at about 93% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread packages/daemon-contracts/src/daemon-status.ts Outdated
Comment thread src/commands/schema/command-overrides.ts Outdated
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from 2e08f8f to 8566cee Compare October 16, 2026 23:02
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from 8566cee to 5645905 Compare October 16, 2026 23:17
@thymikee

Copy link
Copy Markdown
Member Author

The code has one problem to fix before merge, and CI is green: 18 checks, 0 failing at 5645905. There are no conflicts.

readRecord and isTransport in daemon-status.ts add a third parser of daemon.json. The other two are readRegistration in daemon-registration.ts and readDaemonInfo in daemon-client-metadata.ts. isTransport copies readDaemonInfoTransport word for word, so the field schema (transport, version, plugins) now lives in two places and can drift. readRecord also catches every error and returns {}, which drops the absent/unreadable split that readRegistration keeps. If daemon.json exists but cannot be read (EACCES, I/O fault), daemon status prints "No running daemon for

." and plugins list leaves out the daemon inventory, even while a daemon serves that state dir. The rule: one owner in daemon-contracts parses daemon.json, and every reader uses it. Please move readDaemonInfo and its field readers into daemon-contracts next to readRegistration, or extend readRegistration to return the parsed record. Then build readDaemonStatus from that record and its registered, absent or unreadable status, delete readRecord and isTransport, and report "unreadable" instead of running: false. A test with an unreadable daemon.json should show that case.

Could readDaemonStatus become a small projection of registration status, the ownership check and readPluginInventory(record.plugins)? That would remove readRecord, the isTransport copy and the swallowed read error, and the CLI rendering and schema changes could stay as they are. The one thing that has to change first is a single daemon.json record reader in daemon-contracts, which daemon-client-metadata.ts then imports.

Not blocking, take or leave: plugins.md does not yet mention the daemon inventory that plugins list --json now returns (and line 20 still says an incompatible plugin stops the daemon from starting), so add one sentence or confirm a later stack PR owns it; and the em dash to hyphen change in the doc comment at daemon.ts:87 is unrelated and can be dropped.

Of the open inline threads, none still apply. All five are fixed at 5645905, so please resolve them: --clean only on stop, plugins flags per action, null start time, start-time JSDoc and plugins usage text.

No test here proves that a real daemon writes plugins into daemon.json; that write belongs to #3767, and every test here hand-writes the record. I did not rerun pnpm check:affected on the stack top, and I did not check whether a later stack PR owns the website page update and the changeset.

Before merge, one daemon-contracts reader must own daemon.json parsing for status, registration and client metadata. Merge also waits on #3748, as the PR body says.

@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from 5645905 to 8e5814d Compare October 17, 2026 05:06
@thymikee

Copy link
Copy Markdown
Member Author

Thanks. Fixed in 8e5814d (stack top 7f449c5 passed pnpm check:affected --run).

  • One daemon.json reader. readRegistration in daemon-registration.ts now also returns the parsed record. readDaemonStatus is a projection of it, next to the ownership check; daemon-status.ts, readRecord and isTransport are deleted. The transport reader is one function in daemon-resolution.ts that both readDaemonInfo and the status code use.
  • Unreadable record. A record that exists but cannot be read is state: "unreadable" (daemon status says whether a daemon runs there is unknown, and plugins list notes it), no longer "No running daemon". DaemonStatus.state is running | stopped | unreadable; test added with an unreadable file.
  • The inventory is carried raw in the status and validated with readPluginInventory where it is shown, which keeps the daemon-contracts closure within its budget.
  • Dropped the unrelated em dash change.

On the docs sentence: plugins.md is owned by the stacked docs PR (#3769), which now covers plugins list inventory and the removed "incompatible plugin stops the daemon" line. A real daemon writing plugins is covered in #3767 (daemon-composition-credentials.test.ts asserts the composed inventory lands in daemon.json), and I saw it in a live run.

@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from 8e5814d to e886ff7 Compare October 17, 2026 05:23
@thymikee

Copy link
Copy Markdown
Member Author

The PR is ready at e886ff7. The earlier findings from #3768 (comment) are fixed, and I have no new blocking findings.

Not blocking: readDaemonInfo in https://github.com/callstack/agent-device/blob/e886ff7/src/daemon-client/daemon-client-metadata.ts#L110 still parses daemon.json with its own JSON.parse, so two parsers read one file, and later it could take the record from readRegistration; the unreadable state is tested only at readDaemonStatus, so one CLI test with a chmod-000 daemon.json could check the daemon status text and the daemonRecord:"unreadable" field from plugins list. You can take or leave both.

The five open cubic-dev-ai threads are fixed at this head, so you can resolve them: the daemon usage and flags (#3768 (comment)), the plugins flags (#3768 (comment)), the unreadable start-time case (#3768 (comment)), the readDaemonStatus JSDoc (#3768 (comment)), and the plugins usage text (#3768 (comment)).

All 15 checks pass at e886ff7, and there are no conflicts. This was a read-only review: I did not rerun pnpm check:affected or the tests, and I did not check that #3767 writes real daemon plugins into daemon.json or that #3769 updates plugins.md. Cubic has not reviewed this head. Merge now waits only on the stack order (#3767 as the base, and #3748 as the PR body says), and nothing in this change holds it up.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 17, 2026
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from e886ff7 to 377404f Compare October 17, 2026 07:32
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from 377404f to 7fa7572 Compare October 17, 2026 08:01
@thymikee

Copy link
Copy Markdown
Member Author

On the non-blocking readDaemonInfo note: it still has its own JSON.parse because it reads the client-only fields (token, ports, code signature, policy digest) that the status reader never needs, and the eager-closure budget keeps the client path from importing the registration module. The record's transport reader is shared, and status/registration have a single reader. Folding readDaemonInfo into the registration reader is a fair follow-up for the client-metadata owner; I left it out here.

@thymikee
thymikee added this pull request to stack #3779 October 17, 2026 08:16
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from 7fa7572 to ae9ce10 Compare October 17, 2026 08:41
@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from ae9ce10 to 7a789be Compare October 17, 2026 09:32
@thymikee

Copy link
Copy Markdown
Member Author

Rebased onto main and the new #3767. daemon.json now has one reader, readDaemonRecord in daemon-resolution, with absent, unreadable and invalid states. readDaemonInfo (client) and readDaemonStatus project from it, so there is no third parser. daemon status reports running, stopped, unreadable or invalid, and only an absent file reads as stopped. check:affected --run --head c09dbc6c4f passes.

@thymikee

Copy link
Copy Markdown
Member Author

Fixed the failed Coverage check (CRAP 30.0 at 0% coverage on the plugins list text renderer in src/cli/commands/plugins.ts). Two text-mode tests now cover a plugin the running daemon did not register and an unreadable/invalid daemon record (b4b381fe58). The docs and testmu PRs are rebased onto it. check:affected --run --head 1c548fb7ba passes.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

You’re at about 97% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread src/cli/commands/__tests__/plugins.test.ts Outdated
@thymikee

Copy link
Copy Markdown
Member Author

This PR is ready at b4b381f. The earlier clean review at 7fa7572 (#3768 (comment)) still holds, and nothing new needs fixing.

Not blocking: state === 'unreadable' || state === 'invalid' is tested in three places (plugins.ts:39, plugins.ts:57 and daemon.ts:143), so you could export one predicate next to DaemonStatus in daemon-registration.ts and use it at all three, or leave it as is.

Cubic's P3 thread on the plugins.test.ts:178 assertion still applies (#3768 (comment)). {not json always yields invalid, so pinning invalid there would close it. daemon-registration-status.test.ts already pins the classification, so this is optional.

The two Smoke Tests jobs are still queued, and nothing is failing. This PR only changes how the CLI and daemon-contracts read records (daemon status, plugins list, readDaemonInfo). Smoke does reach readDaemonInfo on its daemon-connect route, but the read behavior is unchanged. I did not run tests or lint locally, and I could not check the Smoke outcome. There are no conflicts. The queued Smoke Tests need to pass before merge.

This review covers b4b381f. The newer head bddb30f only pins the invalid state in plugins.test.ts, which addresses the Cubic P3 thread above.

thymikee and others added 4 commits October 17, 2026 12:53
`daemon status [--json]` reads the daemon record without contacting the
daemon and reports every provider it registered, with the reason any plugin
failed. `plugins list --json` reports the running daemon's inventory next
to the store selections.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… daemon records

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ecord

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@thymikee

Copy link
Copy Markdown
Member Author

This PR is ready: the code is clean at bddb30f, and the earlier clean review at 7fa7572 (#3768 (comment)) still holds. The rebase onto the new base changed nothing in behavior, and the new test commits now pin the "unknown providers" wording that the open test thread asked for.

Not blocking: the check state === 'unreadable' || state === 'invalid' appears at plugins.ts:39, plugins.ts:57 and daemon.ts:143, and the wording differs between "not a valid record" and "is invalid", so you could export one predicate such as isDaemonRecordUnknown(status) next to DaemonStatus in daemon-registration.ts and use one phrase; take it or leave it.

The cubic-dev-ai P3 thread on plugins.test.ts no longer applies, because the test at bddb30f asserts the "providers are unknown" text, so please resolve it: #3768 (comment)

All 20 checks pass, and I know of no conflicts. I reviewed only the logical patch from the range-diff (7a789be, b4b381f and bddb30f), not the roughly 220 files of rebase churn from the base moving. I did not re-trace the daemon-side writer of the daemon.json plugins list in this round, and I ran no tests. The only step left before merge is that the base branch feat/plugin-registry-v2 must be ready.

@thymikee
thymikee force-pushed the feat/plugin-registry-v2-status branch from bddb30f to 0c81506 Compare October 17, 2026 11:50
@thymikee

Copy link
Copy Markdown
Member Author

Pushed 0c81506f84 (rebased onto the new #3767). Applied: one isUnusableRecord predicate next to DaemonStatus replaces the three unreadable || invalid checks (daemon.ts, two in plugins.ts), and plugins.test.ts pins the invalid state (cubic's P3, thread resolved). The Coverage check that failed on the plugins list text renderer is fixed by two text-mode tests. check:affected --run --head a304bb7f40 passes on the stack top.

@thymikee

Copy link
Copy Markdown
Member Author

This PR is ready. Since the earlier review at bddb30f, the rebased head 0c81506 extracts the unusable-record check into one predicate shared by the daemon status and plugins list renderers, and the '{not json' test in plugins.test.ts now asserts 'is invalid'. I read the diff and found the extraction preserves behavior. I did not run the tests, and I did not review the #3767 content that came in with the rebase, since it belongs to the base.

Not blocking: the 'unreadable' state of the unusable-record check has no CLI-level test, and the render branch at daemon.ts:144 is never exercised for either unusable state. You could add one case in daemon.test.ts that stubs readDaemonStatus as { state: 'unreadable', stateDir } and asserts the output contains 'is unreadable, so whether a daemon runs there is unknown', and optionally a matching 'invalid' case for 'not a valid record'. You can take or leave this.

The cubic-dev-ai thread on the plugins.test.ts '{not json' assertion no longer applies, because that test now asserts 'is invalid'. Please resolve it: #3768 (comment)

There are no conflicts. Smoke Tests is still running, not failed, and this change touches no device or smoke route. Once CI is green, the PR waits for the base PR #3767 to land.

@thymikee
thymikee merged commit 232c676 into main Oct 17, 2026
19 of 21 checks passed
@thymikee
thymikee deleted the feat/plugin-registry-v2-status branch October 17, 2026 12:46
thymikee added a commit that referenced this pull request Oct 17, 2026
…ment

* origin/main:
  feat(provider-testmu): publish @agent-device/testmu on plugin contract v2 (#3770)
  docs(plugins): document plugin contract v2, the inventory and ADR 0034 (#3769)
  feat(daemon): daemon status lists the registered provider plugins (#3768)
  feat(plugins): plugin contract v2 and one provider registry (#3767)

# Conflicts:
#	packages/daemon/src/sessions/handlers/lease.ts
#	src/__tests__/cloud-connect-testmu.test.ts
#	src/cli/commands/connection.ts
#	src/cli/commands/daemon.ts
#	src/daemon-client/daemon-client-metadata.ts
#	src/daemon-client/daemon-client.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant