fix(node-sdk): bind --agent/--agent-file profile on interactive session create (v2) - #2832
fix(node-sdk): bind --agent/--agent-file profile on interactive session create (v2)#2832SnowingFox wants to merge 3 commits into
Conversation
…on create (v2) Fixes MoonshotAI#2765
🦋 Changeset detectedLatest commit: 1c8e2d1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7adf7e4aea
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| input.permission !== undefined | ||
| ) { | ||
| const agent = await this.materializeMainAgent(handle, { | ||
| profile: agentProfileName, |
There was a problem hiding this comment.
Register --agent-file profiles before binding
When the TUI passes only agentFiles, this binds the parsed profile name, but SDKRpcClientV2 never registers those files with the v2 engine; the explicit profile loader reads only IBootstrapService.args.agentFiles, while this client bootstraps only skillDirs. In that context an arbitrary --agent-file profile is absent from the session catalog, so profile.bind rejects as an unknown profile and interactive --agent-file remains unusable unless the same profile is also discoverable from user/project agent dirs.
Useful? React with 👍 / 👎.
| // materialized — the same binding print mode applies via `mainAgentBinding` | ||
| // — so a profile's `tools` / `disallowedTools` policy is enforced in | ||
| // interactive sessions too, not just `-p`. | ||
| const agentProfileName = await this.resolveStartupAgentProfile(input, workDir); |
There was a problem hiding this comment.
Clean up failed startup profile binds
When a newly selected startup profile is invalid or missing, the rejection now happens after ISessionLifecycleService.create() has already returned and indexed the session, because the profile is resolved/bound in the SDK instead of inside the lifecycle create call. In that scenario createSession({ id, agentProfile: 'missing-agent' }) returns an error but leaves a live/persisted session behind, so listSessions shows a failed create and the same id cannot be reused; either validate/bind before indexing via mainAgentBinding or close/remove the handle on failure.
Useful? React with 👍 / 👎.
…binding The interactive --agent-file path resolved the profile name but never registered the file with the v2 engine, so an agentfile supplied solely through agentFiles was absent from the session catalog and profile.bind rejected it as an unknown profile (chatgpt-codex-connector P1). Seed input.agentFiles through the explicit agent loader channel (IBootstrapService.args.agentFiles) and re-arm the workspace explicit loader before binding, matching run-v2-print. Adds a regression test for an agent-file-only profile that binds as the interactive main agent. Signed-off-by: snowingfox <1503401882@qq.com>
Fixes #2765
Problem
Agent profile frontmatter
tools(allowlist) anddisallowedTools(denylist)are enforced in
-pprint mode but completely ignored in interactive TUIsessions. The interactive session is created through the SDK's agent-core-v2
client, and its
createSessionnever bound the requested startup profile —the main agent fell back to the default profile, so the model saw the full,
unrestricted tool set regardless of the profile's tool policy.
The profile's system prompt appeared to be applied because profile text can
still influence prompt rendering, but the tool policy (activation fold +
execution guard) is driven by the bound profile's
tools/disallowedTools,which were never applied in interactive mode.
Root cause
SDKRpcClientV2.createSession(the v2 engine client used by the interactiveTUI,
run-shell.ts→createKimiHarnessV2) droppedCreateSessionOptions.agentProfile/agentFilesentirely: it created thesession with no
mainAgentBindingandmaterializeMainAgentalways boundDEFAULT_AGENT_PROFILE_NAME. Print mode (run-v2-print.ts), by contrast,resolves the profile name and passes it into the session's
mainAgentBinding,so the tool policy is enforced there.
Fix
packages/node-sdk/src/sdk-rpc-client-v2.ts:createSessionnow resolves the startup profile (--agentname, or the--agent-file's frontmattername, mirroringrun-v2-print.ts) and passesit to main-agent materialization, so the interactive session binds the same
profile (and its tool policy) as print mode.
materializeMainAgentaccepts the optionalprofileand binds it insteadof unconditionally binding the default profile; an already-bound agent is
left alone so the explicit binding is never overwritten.
Verification
packages/node-sdk/test/session-agent-profile.test.tscreates a v2 session with
agentProfilepointing at a restricted profileand asserts the interactive main agent binds that profile (
profileName+activeToolNames). It fails on the previous code (main agent bound thedefault profile) and passes with the fix.
pnpm -C packages/node-sdk exec vitest run test/session-agent-profile.test.tsNote: unrelated to the earlier open PR #2822 (hooks index rebuild), which
touches the hooks domain of agent-core-v2.