Merge remote-tracking branch 'origin/master' into feature/subagent-policy-inheritance

# Conflicts:
#	.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml
#	docs/cordis-catalog/services.md
#	docs/persistence-catalog.md
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	packages/core/session/README.i18n.yaml
#	packages/subagent/subagent-inprocess/README.i18n.yaml
#	packages/ui/user-approval/src/index.ts
This commit is contained in:
kingwl
2026-07-28 11:19:46 +08:00
1141 changed files with 36230 additions and 16667 deletions

View File

@@ -273,8 +273,8 @@ export class ApprovalService extends Service {
})
})
// Visibility layer 2: the boundary narrator. pre-step runs after prompt
// assembly but before the request history is derived, so the notice is
// Visibility layer 2: the boundary narrator. agent/step runs before the
// request history is derived, so the notice is
// seen by THIS step's request: idle-time flip-flops coalesce at the
// turn's first step (net-zero → nothing), and a mid-turn switch is
// narrated no later than the next step. What each session was last told
@@ -287,7 +287,7 @@ export class ApprovalService extends Service {
// baseline came from the delegating session; otherwise the configured
// default moved under the session (operator/config).
const narrated = new WeakMap<Agent['session'], ApprovalPolicy>()
ctx.on('agent/pre-step', (agent) => {
ctx.on('agent/step', (agent) => {
const session = agent.session
const events = session.events
const seedStart = Math.min(session.header.seedLength ?? 0, events.length)
@@ -315,10 +315,10 @@ export class ApprovalService extends Service {
: overrideIndex < 0 && session.header.approvalPolicy === current
? 'inherited from the delegating session'
: 'changed by the operator/config'
agent.inject(
[{ type: 'text', text: `The approval policy changed from "${told}" to "${current}" (${cause}).` }],
{ source: { kind: 'plugin', plugin: 'user-approval' } },
)
agent.inject({
content: [{ type: 'text', text: `The approval policy changed from "${told}" to "${current}" (${cause}).` }],
source: { kind: 'plugin', plugin: 'user-approval' },
})
})
}

View File

@@ -368,13 +368,15 @@ describe('approval policy (the approval/policy fold)', () => {
const agent = {
id,
session,
inject: (content: { type: string; text: string }[]) => { injected.push(content[0]?.text ?? '') },
inject: (input: { content: Array<{ type: string; text: string }> }) => {
injected.push(input.content[0]?.text ?? '')
},
} as unknown as Agent
return { agent, session, injected }
}
const preStep = (ctx: Context, agent: Agent): Promise<void> =>
agentEvents(ctx, agent).serial('agent/pre-step', 1, 1, new AbortController().signal)
agentEvents(ctx, agent).serial('agent/step', 1, 1, new AbortController().signal)
/** Append a `request/header` snapshot whose system text is exactly `system`. */
function appendHeader(session: Session, system: string): void {
@@ -540,7 +542,9 @@ describe('approval policy (the approval/policy fold)', () => {
const agent = {
id,
session,
inject: (content: { type: string; text: string }[]) => { injected.push(content[0]?.text ?? '') },
inject: (input: { content: Array<{ type: string; text: string }> }) => {
injected.push(input.content[0]?.text ?? '')
},
} as unknown as Agent
await preStep(ctx, agent)