@namzu/sdk 61.4.0 → 62.0.0
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/CHANGELOG.md +55 -0
- package/dist/agents/QueryAgent.d.ts.map +1 -1
- package/dist/agents/QueryAgent.js +2 -0
- package/dist/agents/QueryAgent.js.map +1 -1
- package/dist/bridge/acp/permission.d.ts +8 -0
- package/dist/bridge/acp/permission.d.ts.map +1 -1
- package/dist/bridge/acp/permission.js.map +1 -1
- package/dist/bridge/acp/server.d.ts.map +1 -1
- package/dist/bridge/acp/server.js +8 -1
- package/dist/bridge/acp/server.js.map +1 -1
- package/dist/constants/tools/index.d.ts +2 -0
- package/dist/constants/tools/index.d.ts.map +1 -1
- package/dist/constants/tools/index.js +23 -0
- package/dist/constants/tools/index.js.map +1 -1
- package/dist/eval/harness-protection.js +1 -1
- package/dist/eval/harness-protection.js.map +1 -1
- package/dist/learning/cycle.d.ts +5 -3
- package/dist/learning/cycle.d.ts.map +1 -1
- package/dist/learning/cycle.js +11 -13
- package/dist/learning/cycle.js.map +1 -1
- package/dist/learning/guidance.d.ts +74 -0
- package/dist/learning/guidance.d.ts.map +1 -0
- package/dist/learning/guidance.js +259 -0
- package/dist/learning/guidance.js.map +1 -0
- package/dist/learning/skill.d.ts +2 -2
- package/dist/learning/skill.d.ts.map +1 -1
- package/dist/learning/skill.js +6 -6
- package/dist/learning/skill.js.map +1 -1
- package/dist/learning/store.d.ts.map +1 -1
- package/dist/learning/store.js +6 -6
- package/dist/learning/store.js.map +1 -1
- package/dist/pals/communication/ingress-schema.d.ts +8 -8
- package/dist/pals/communication/schema.d.ts +2 -2
- package/dist/peers/client.d.ts +2 -3
- package/dist/peers/client.d.ts.map +1 -1
- package/dist/peers/client.js +2 -3
- package/dist/peers/client.js.map +1 -1
- package/dist/peers/endpoint.d.ts +1 -2
- package/dist/peers/endpoint.d.ts.map +1 -1
- package/dist/peers/endpoint.js +1 -2
- package/dist/peers/endpoint.js.map +1 -1
- package/dist/peers/protocol.d.ts.map +1 -1
- package/dist/peers/protocol.js +1 -0
- package/dist/peers/protocol.js.map +1 -1
- package/dist/prompt/coding-agent-doctrine.d.ts +4 -4
- package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
- package/dist/prompt/coding-agent-doctrine.js +5 -3
- package/dist/prompt/coding-agent-doctrine.js.map +1 -1
- package/dist/prompt/index.d.ts +0 -4
- package/dist/prompt/index.d.ts.map +1 -1
- package/dist/prompt/index.js +0 -2
- package/dist/prompt/index.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +3 -0
- package/dist/provider/fallback.js.map +1 -1
- package/dist/provider/idle-timeout.d.ts.map +1 -1
- package/dist/provider/idle-timeout.js +5 -0
- package/dist/provider/idle-timeout.js.map +1 -1
- package/dist/provider/model-window-suffix.d.ts.map +1 -1
- package/dist/provider/model-window-suffix.js +1 -0
- package/dist/provider/model-window-suffix.js.map +1 -1
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +5 -0
- package/dist/provider/retry.js.map +1 -1
- package/dist/provider/step-stopped.d.ts +19 -0
- package/dist/provider/step-stopped.d.ts.map +1 -0
- package/dist/provider/step-stopped.js +25 -0
- package/dist/provider/step-stopped.js.map +1 -0
- package/dist/provider/token-budget.d.ts.map +1 -1
- package/dist/provider/token-budget.js +6 -1
- package/dist/provider/token-budget.js.map +1 -1
- package/dist/public-runtime.d.ts +3 -14
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +3 -14
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +0 -2
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +0 -2
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +3 -21
- package/dist/public-types.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +17 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +168 -5
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/per-call-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/per-call-review.js +4 -5
- package/dist/runtime/query/iteration/phases/per-call-review.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +6 -3
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts +9 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +48 -2
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +7 -4
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +40 -8
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +139 -24
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/turn/completion-audit.d.ts +32 -0
- package/dist/runtime/query/turn/completion-audit.d.ts.map +1 -0
- package/dist/runtime/query/turn/completion-audit.js +56 -0
- package/dist/runtime/query/turn/completion-audit.js.map +1 -0
- package/dist/runtime/query/turn/stall-monitor.d.ts +78 -0
- package/dist/runtime/query/turn/stall-monitor.d.ts.map +1 -0
- package/dist/runtime/query/turn/stall-monitor.js +101 -0
- package/dist/runtime/query/turn/stall-monitor.js.map +1 -0
- package/dist/session/paths.d.ts +1 -2
- package/dist/session/paths.d.ts.map +1 -1
- package/dist/session/paths.js +1 -4
- package/dist/session/paths.js.map +1 -1
- package/dist/tools/builtins/bash.d.ts +2 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +5 -2
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/content-fingerprint.d.ts +13 -0
- package/dist/tools/builtins/content-fingerprint.d.ts.map +1 -1
- package/dist/tools/builtins/content-fingerprint.js +25 -0
- package/dist/tools/builtins/content-fingerprint.js.map +1 -1
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +7 -2
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/shell-read-credit.d.ts +15 -0
- package/dist/tools/builtins/shell-read-credit.d.ts.map +1 -0
- package/dist/tools/builtins/shell-read-credit.js +161 -0
- package/dist/tools/builtins/shell-read-credit.js.map +1 -0
- package/dist/tools/paths.d.ts +15 -2
- package/dist/tools/paths.d.ts.map +1 -1
- package/dist/tools/paths.js +17 -2
- package/dist/tools/paths.js.map +1 -1
- package/dist/turn/evidence-recall.d.ts +1 -1
- package/dist/turn/evidence-recall.d.ts.map +1 -1
- package/dist/turn/evidence-recall.js +5 -14
- package/dist/turn/evidence-recall.js.map +1 -1
- package/dist/types/acp/index.d.ts +6 -0
- package/dist/types/acp/index.d.ts.map +1 -1
- package/dist/types/agent/base.d.ts +4 -0
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/hitl/index.d.ts +8 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/ids/index.d.ts +1 -1
- package/dist/types/message/index.d.ts +1 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +1 -0
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/provider/interface.d.ts +12 -0
- package/dist/types/provider/interface.d.ts.map +1 -1
- package/dist/types/session/config.d.ts +25 -0
- package/dist/types/session/config.d.ts.map +1 -1
- package/dist/types/session/records.d.ts.map +1 -1
- package/dist/types/session/records.js +2 -0
- package/dist/types/session/records.js.map +1 -1
- package/dist/types/session/turn.d.ts +1 -1
- package/dist/types/session/turn.d.ts.map +1 -1
- package/dist/types/session/turn.js.map +1 -1
- package/package.json +1 -1
- package/src/agents/QueryAgent.ts +2 -0
- package/src/bridge/acp/permission.ts +8 -0
- package/src/bridge/acp/server.ts +7 -1
- package/src/constants/tools/index.ts +27 -0
- package/src/eval/harness-protection.ts +1 -1
- package/src/learning/cycle.ts +15 -16
- package/src/learning/guidance.ts +339 -0
- package/src/learning/skill.ts +7 -7
- package/src/learning/store.ts +5 -6
- package/src/peers/client.ts +2 -3
- package/src/peers/endpoint.ts +1 -2
- package/src/peers/protocol.ts +1 -0
- package/src/prompt/coding-agent-doctrine.ts +5 -3
- package/src/prompt/index.ts +0 -4
- package/src/provider/fallback.ts +7 -0
- package/src/provider/idle-timeout.ts +8 -0
- package/src/provider/model-window-suffix.ts +1 -0
- package/src/provider/retry.ts +8 -0
- package/src/provider/step-stopped.ts +27 -0
- package/src/provider/token-budget.ts +6 -1
- package/src/public-runtime.ts +6 -28
- package/src/public-tools.ts +0 -3
- package/src/public-types.ts +5 -137
- package/src/runtime/query/iteration/index.ts +207 -5
- package/src/runtime/query/iteration/phases/per-call-review.ts +7 -5
- package/src/runtime/query/iteration/phases/tool-review.ts +5 -3
- package/src/runtime/query/iteration/stream-turn.ts +51 -1
- package/src/runtime/query/resume-pending.ts +11 -4
- package/src/runtime/query/review-policy.ts +157 -24
- package/src/runtime/query/turn/completion-audit.ts +71 -0
- package/src/runtime/query/turn/stall-monitor.ts +158 -0
- package/src/session/paths.ts +2 -6
- package/src/tools/builtins/bash.ts +6 -2
- package/src/tools/builtins/content-fingerprint.ts +25 -0
- package/src/tools/builtins/edit.ts +11 -2
- package/src/tools/builtins/shell-read-credit.ts +159 -0
- package/src/tools/paths.ts +18 -2
- package/src/turn/evidence-recall.ts +7 -15
- package/src/types/acp/index.ts +6 -0
- package/src/types/agent/base.ts +4 -0
- package/src/types/hitl/index.ts +8 -0
- package/src/types/ids/index.ts +1 -1
- package/src/types/message/index.ts +1 -0
- package/src/types/provider/interface.ts +13 -0
- package/src/types/session/config.ts +27 -0
- package/src/types/session/records.ts +2 -0
- package/src/types/session/turn.ts +2 -1
- package/dist/learning/deprecated.d.ts +0 -86
- package/dist/learning/deprecated.d.ts.map +0 -1
- package/dist/learning/deprecated.js +0 -22
- package/dist/learning/deprecated.js.map +0 -1
- package/dist/manager/resident/activity.d.ts +0 -74
- package/dist/manager/resident/activity.d.ts.map +0 -1
- package/dist/manager/resident/activity.js +0 -125
- package/dist/manager/resident/activity.js.map +0 -1
- package/dist/manager/resident/agenda.d.ts +0 -167
- package/dist/manager/resident/agenda.d.ts.map +0 -1
- package/dist/manager/resident/agenda.js +0 -588
- package/dist/manager/resident/agenda.js.map +0 -1
- package/dist/manager/resident/consumption.d.ts +0 -98
- package/dist/manager/resident/consumption.d.ts.map +0 -1
- package/dist/manager/resident/consumption.js +0 -237
- package/dist/manager/resident/consumption.js.map +0 -1
- package/dist/manager/resident/delivery-window.d.ts +0 -28
- package/dist/manager/resident/delivery-window.d.ts.map +0 -1
- package/dist/manager/resident/delivery-window.js +0 -80
- package/dist/manager/resident/delivery-window.js.map +0 -1
- package/dist/manager/resident/evidence-recall.d.ts +0 -30
- package/dist/manager/resident/evidence-recall.d.ts.map +0 -1
- package/dist/manager/resident/evidence-recall.js +0 -297
- package/dist/manager/resident/evidence-recall.js.map +0 -1
- package/dist/manager/resident/history-disk.d.ts +0 -10
- package/dist/manager/resident/history-disk.d.ts.map +0 -1
- package/dist/manager/resident/history-disk.js +0 -50
- package/dist/manager/resident/history-disk.js.map +0 -1
- package/dist/manager/resident/history.d.ts +0 -115
- package/dist/manager/resident/history.d.ts.map +0 -1
- package/dist/manager/resident/history.js +0 -203
- package/dist/manager/resident/history.js.map +0 -1
- package/dist/manager/resident/host.d.ts +0 -112
- package/dist/manager/resident/host.d.ts.map +0 -1
- package/dist/manager/resident/host.js +0 -254
- package/dist/manager/resident/host.js.map +0 -1
- package/dist/manager/resident/initiative.d.ts +0 -86
- package/dist/manager/resident/initiative.d.ts.map +0 -1
- package/dist/manager/resident/initiative.js +0 -131
- package/dist/manager/resident/initiative.js.map +0 -1
- package/dist/manager/resident/loop.d.ts +0 -49
- package/dist/manager/resident/loop.d.ts.map +0 -1
- package/dist/manager/resident/loop.js +0 -75
- package/dist/manager/resident/loop.js.map +0 -1
- package/dist/manager/resident/outbox.d.ts +0 -124
- package/dist/manager/resident/outbox.d.ts.map +0 -1
- package/dist/manager/resident/outbox.js +0 -216
- package/dist/manager/resident/outbox.js.map +0 -1
- package/dist/manager/resident/proposal.d.ts +0 -65
- package/dist/manager/resident/proposal.d.ts.map +0 -1
- package/dist/manager/resident/proposal.js +0 -77
- package/dist/manager/resident/proposal.js.map +0 -1
- package/dist/manager/resident/store.d.ts +0 -108
- package/dist/manager/resident/store.d.ts.map +0 -1
- package/dist/manager/resident/store.js +0 -205
- package/dist/manager/resident/store.js.map +0 -1
- package/dist/manager/resident/tool-evidence.d.ts +0 -112
- package/dist/manager/resident/tool-evidence.d.ts.map +0 -1
- package/dist/manager/resident/tool-evidence.js +0 -289
- package/dist/manager/resident/tool-evidence.js.map +0 -1
- package/dist/prompt/resident-learning.d.ts +0 -29
- package/dist/prompt/resident-learning.d.ts.map +0 -1
- package/dist/prompt/resident-learning.js +0 -126
- package/dist/prompt/resident-learning.js.map +0 -1
- package/dist/prompt/resident-step.d.ts +0 -42
- package/dist/prompt/resident-step.d.ts.map +0 -1
- package/dist/prompt/resident-step.js +0 -137
- package/dist/prompt/resident-step.js.map +0 -1
- package/dist/tools/resident-history.d.ts +0 -12
- package/dist/tools/resident-history.d.ts.map +0 -1
- package/dist/tools/resident-history.js +0 -82
- package/dist/tools/resident-history.js.map +0 -1
- package/dist/tools/resident-tool-evidence.d.ts +0 -9
- package/dist/tools/resident-tool-evidence.d.ts.map +0 -1
- package/dist/tools/resident-tool-evidence.js +0 -61
- package/dist/tools/resident-tool-evidence.js.map +0 -1
- package/src/learning/deprecated.ts +0 -124
- package/src/manager/resident/activity.ts +0 -211
- package/src/manager/resident/agenda.ts +0 -937
- package/src/manager/resident/consumption.ts +0 -335
- package/src/manager/resident/delivery-window.ts +0 -99
- package/src/manager/resident/evidence-recall.ts +0 -369
- package/src/manager/resident/history-disk.ts +0 -63
- package/src/manager/resident/history.ts +0 -348
- package/src/manager/resident/host.ts +0 -390
- package/src/manager/resident/initiative.ts +0 -231
- package/src/manager/resident/loop.ts +0 -119
- package/src/manager/resident/outbox.ts +0 -341
- package/src/manager/resident/proposal.ts +0 -119
- package/src/manager/resident/store.ts +0 -279
- package/src/manager/resident/tool-evidence.ts +0 -455
- package/src/prompt/resident-learning.ts +0 -152
- package/src/prompt/resident-step.ts +0 -182
- package/src/tools/resident-history.ts +0 -88
- package/src/tools/resident-tool-evidence.ts +0 -72
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { setTimeout as sleep } from 'node:timers/promises'
|
|
2
|
-
import {
|
|
3
|
-
ResidentConflictError,
|
|
4
|
-
type ResidentDecision,
|
|
5
|
-
type ResidentExecutionStore,
|
|
6
|
-
type ResidentState,
|
|
7
|
-
} from './store.js'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @experimental Developer-owned step; bind providers, tools and budgets in the host.
|
|
11
|
-
*
|
|
12
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
13
|
-
*/
|
|
14
|
-
export type ResidentStep = (state: ResidentState, signal: AbortSignal) => Promise<ResidentDecision>
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @experimental No model is invoked for an idle, terminal or unresolved resident.
|
|
18
|
-
*
|
|
19
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
20
|
-
*/
|
|
21
|
-
export type ResidentStepResult =
|
|
22
|
-
| { status: 'settled'; state: ResidentState }
|
|
23
|
-
| {
|
|
24
|
-
status: 'idle'
|
|
25
|
-
reason: 'not-due' | 'terminal' | 'unresolved' | 'contended'
|
|
26
|
-
state: ResidentState
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @experimental A failed/aborted callback leaves its durable claim unresolved.
|
|
31
|
-
*
|
|
32
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
33
|
-
*/
|
|
34
|
-
export async function stepResident(
|
|
35
|
-
store: ResidentExecutionStore,
|
|
36
|
-
step: ResidentStep,
|
|
37
|
-
signal: AbortSignal,
|
|
38
|
-
now: () => number = Date.now,
|
|
39
|
-
): Promise<ResidentStepResult> {
|
|
40
|
-
signal.throwIfAborted()
|
|
41
|
-
const state = await store.read()
|
|
42
|
-
signal.throwIfAborted()
|
|
43
|
-
if (!state) throw new Error('Create the resident before running it.')
|
|
44
|
-
if (state.phase === 'running') return { status: 'idle', reason: 'unresolved', state }
|
|
45
|
-
if (state.phase !== 'waiting') return { status: 'idle', reason: 'terminal', state }
|
|
46
|
-
if (state.wakeAt === null || state.wakeAt > now())
|
|
47
|
-
return { status: 'idle', reason: 'not-due', state }
|
|
48
|
-
let claim: ResidentState
|
|
49
|
-
try {
|
|
50
|
-
claim = await store.claim(state, now())
|
|
51
|
-
} catch (error) {
|
|
52
|
-
if (!(error instanceof ResidentConflictError)) throw error
|
|
53
|
-
return {
|
|
54
|
-
status: 'idle',
|
|
55
|
-
reason: 'contended',
|
|
56
|
-
state: (await store.read()) ?? state,
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
signal.throwIfAborted()
|
|
60
|
-
const decision = await step(claim, signal)
|
|
61
|
-
signal.throwIfAborted()
|
|
62
|
-
return {
|
|
63
|
-
status: 'settled',
|
|
64
|
-
state: await store.settle(claim, decision, now()),
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @experimental Bounded local driver; not a daemon, process recovery service or notification transport.
|
|
70
|
-
*
|
|
71
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
72
|
-
*/
|
|
73
|
-
export interface ResidentLoopOptions {
|
|
74
|
-
readonly store: ResidentExecutionStore
|
|
75
|
-
readonly step: ResidentStep
|
|
76
|
-
readonly signal: AbortSignal
|
|
77
|
-
/** Required finite admission cap for this invocation, independent of provider token limits. */
|
|
78
|
-
readonly maxSteps: number
|
|
79
|
-
/** Maximum single idle wait, default 60 seconds. Longer waits return control to the host. */
|
|
80
|
-
readonly maxIdleMs?: number
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @experimental Continue a pursuit without a new user message. Null wake times
|
|
85
|
-
* and terminal states stop immediately; cancellation also interrupts idle waits.
|
|
86
|
-
* An abort cannot undo callback effects or forcibly stop a callback ignoring its signal.
|
|
87
|
-
*
|
|
88
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
89
|
-
*/
|
|
90
|
-
export async function runResident(options: ResidentLoopOptions): Promise<ResidentStepResult> {
|
|
91
|
-
const maxIdleMs = options.maxIdleMs ?? 60_000
|
|
92
|
-
if (
|
|
93
|
-
!Number.isSafeInteger(options.maxSteps) ||
|
|
94
|
-
options.maxSteps < 1 ||
|
|
95
|
-
!Number.isSafeInteger(maxIdleMs) ||
|
|
96
|
-
maxIdleMs < 0 ||
|
|
97
|
-
maxIdleMs > 2_147_483_647
|
|
98
|
-
) {
|
|
99
|
-
throw new TypeError(
|
|
100
|
-
'Resident loop requires positive finite maxSteps and bounded nonnegative maxIdleMs.',
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
let admitted = 0
|
|
104
|
-
while (true) {
|
|
105
|
-
const result = await stepResident(options.store, options.step, options.signal)
|
|
106
|
-
if (result.status === 'settled') admitted++
|
|
107
|
-
if (admitted >= options.maxSteps) return result
|
|
108
|
-
const { state } = result
|
|
109
|
-
if (
|
|
110
|
-
state.phase !== 'waiting' ||
|
|
111
|
-
state.wakeAt === null ||
|
|
112
|
-
(result.status === 'idle' && result.reason !== 'not-due')
|
|
113
|
-
)
|
|
114
|
-
return result
|
|
115
|
-
const delay = Math.max(0, state.wakeAt - Date.now())
|
|
116
|
-
if (delay > maxIdleMs) return result
|
|
117
|
-
await sleep(Math.max(1, delay), undefined, { signal: options.signal })
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto'
|
|
2
|
-
import { z } from 'zod'
|
|
3
|
-
import type { ResidentAgendaState } from './agenda.js'
|
|
4
|
-
import { ResidentConflictError } from './store.js'
|
|
5
|
-
|
|
6
|
-
const time = z.number().int().nonnegative().safe().max(8_640_000_000_000_000)
|
|
7
|
-
const label = z.string().trim().min(1).max(256)
|
|
8
|
-
|
|
9
|
-
export const residentMessageInputSchema = z.object({
|
|
10
|
-
id: z.string().uuid(),
|
|
11
|
-
pursuitId: z.string().uuid(),
|
|
12
|
-
destination: label,
|
|
13
|
-
body: z
|
|
14
|
-
.string()
|
|
15
|
-
.min(1)
|
|
16
|
-
.max(8_000)
|
|
17
|
-
.refine((value) => value.trim().length > 0),
|
|
18
|
-
notBefore: time,
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @experimental Host-approved content and an opaque destination route, never credentials.
|
|
23
|
-
*
|
|
24
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
25
|
-
*/
|
|
26
|
-
export type ResidentMessageInput = Readonly<z.infer<typeof residentMessageInputSchema>>
|
|
27
|
-
|
|
28
|
-
export const residentOutboxMessageSchema = residentMessageInputSchema
|
|
29
|
-
.extend({
|
|
30
|
-
tenantId: z.string().uuid(),
|
|
31
|
-
agentKey: z.string().min(1).max(200),
|
|
32
|
-
sourceClaimId: z.string().uuid().nullable(),
|
|
33
|
-
revision: z.number().int().positive().safe(),
|
|
34
|
-
attempts: z.number().int().nonnegative().safe(),
|
|
35
|
-
phase: z.enum(['pending', 'sending', 'acknowledged', 'cancelled']),
|
|
36
|
-
claimId: z.string().uuid().nullable(),
|
|
37
|
-
nextAttemptAt: time.nullable(),
|
|
38
|
-
receiptId: label.nullable(),
|
|
39
|
-
acknowledgedAt: time.nullable(),
|
|
40
|
-
lastReason: z.string().trim().min(1).max(1_000).nullable(),
|
|
41
|
-
})
|
|
42
|
-
.superRefine((message, context) => {
|
|
43
|
-
if (
|
|
44
|
-
(message.phase === 'sending') !== (message.claimId !== null) ||
|
|
45
|
-
(message.phase === 'pending') !== (message.nextAttemptAt !== null) ||
|
|
46
|
-
(message.phase === 'acknowledged') !== (message.receiptId !== null) ||
|
|
47
|
-
(message.phase === 'acknowledged') !== (message.acknowledgedAt !== null) ||
|
|
48
|
-
(message.nextAttemptAt !== null && message.nextAttemptAt < message.notBefore) ||
|
|
49
|
-
(message.phase !== 'pending' && message.attempts === 0)
|
|
50
|
-
)
|
|
51
|
-
context.addIssue({ code: z.ZodIssueCode.custom, message: 'Invalid outbox lifecycle.' })
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @experimental Acknowledgment proves transport acceptance, not human reading.
|
|
56
|
-
*
|
|
57
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
58
|
-
*/
|
|
59
|
-
export type ResidentOutboxMessage = Readonly<z.infer<typeof residentOutboxMessageSchema>>
|
|
60
|
-
|
|
61
|
-
export const residentDeliveryOutcomeSchema = z.discriminatedUnion('kind', [
|
|
62
|
-
z.object({ kind: z.literal('acknowledged'), receiptId: label }),
|
|
63
|
-
z.object({
|
|
64
|
-
kind: z.literal('not-accepted'),
|
|
65
|
-
retryAt: time.nullable(),
|
|
66
|
-
reason: z.string().trim().min(1).max(1_000),
|
|
67
|
-
}),
|
|
68
|
-
])
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @experimental Retry only with evidence of non-acceptance; null retryAt ends delivery.
|
|
72
|
-
*
|
|
73
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
74
|
-
*/
|
|
75
|
-
export type ResidentDeliveryOutcome = Readonly<z.infer<typeof residentDeliveryOutcomeSchema>>
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @experimental Atomic admission and exact-claim settlement, without automatic claim expiry.
|
|
79
|
-
*
|
|
80
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
81
|
-
*/
|
|
82
|
-
export interface ResidentOutboxStore {
|
|
83
|
-
read(): Promise<ResidentAgendaState | null>
|
|
84
|
-
claimMessage(
|
|
85
|
-
expected: ResidentAgendaState,
|
|
86
|
-
id: string,
|
|
87
|
-
now: number,
|
|
88
|
-
): Promise<ResidentOutboxMessage>
|
|
89
|
-
settleMessage(
|
|
90
|
-
expected: ResidentOutboxMessage,
|
|
91
|
-
outcome: ResidentDeliveryOutcome,
|
|
92
|
-
now: number,
|
|
93
|
-
): Promise<ResidentOutboxMessage>
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @experimental A synchronous host policy, evaluated before claiming and again before sending.
|
|
98
|
-
*
|
|
99
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
100
|
-
*/
|
|
101
|
-
export type ResidentDeliveryGate = (
|
|
102
|
-
message: ResidentOutboxMessage,
|
|
103
|
-
now: number,
|
|
104
|
-
) =>
|
|
105
|
-
| { readonly allow: true }
|
|
106
|
-
| {
|
|
107
|
-
readonly allow: false
|
|
108
|
-
readonly nextCheckAt: number | null
|
|
109
|
-
readonly reason: string
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* @experimental Bind an authorized route; forward message.id as the stable idempotency key.
|
|
114
|
-
*
|
|
115
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
116
|
-
*/
|
|
117
|
-
export type ResidentMessageTransport = (
|
|
118
|
-
message: ResidentOutboxMessage,
|
|
119
|
-
signal: AbortSignal,
|
|
120
|
-
) => Promise<ResidentDeliveryOutcome>
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* @experimental One dispatch admission, with no model invocation, polling or implicit retries.
|
|
124
|
-
*
|
|
125
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
126
|
-
*/
|
|
127
|
-
export interface ResidentDeliveryOptions {
|
|
128
|
-
readonly signal: AbortSignal
|
|
129
|
-
readonly gate: ResidentDeliveryGate
|
|
130
|
-
readonly now?: () => number
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @experimental An idle result never asserts a message reached its destination.
|
|
135
|
-
*
|
|
136
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
137
|
-
*/
|
|
138
|
-
export type ResidentDeliveryResult =
|
|
139
|
-
| { readonly status: 'settled'; readonly message: ResidentOutboxMessage }
|
|
140
|
-
| {
|
|
141
|
-
readonly status: 'idle'
|
|
142
|
-
readonly reason: 'paused' | 'unresolved' | 'empty' | 'not-due' | 'window' | 'contended'
|
|
143
|
-
readonly nextCheckAt: number | null
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/** Internal pure enqueue used in the same revision transaction as pursuit settlement. */
|
|
147
|
-
export function appendResidentMessage(
|
|
148
|
-
state: ResidentAgendaState,
|
|
149
|
-
input: ResidentMessageInput,
|
|
150
|
-
sourceClaimId: string | null = null,
|
|
151
|
-
): readonly ResidentOutboxMessage[] {
|
|
152
|
-
const checked = residentMessageInputSchema.parse(input)
|
|
153
|
-
if (!state.pursuits.some((p) => p.id === checked.pursuitId))
|
|
154
|
-
throw new Error('Outbox message references an unknown pursuit.')
|
|
155
|
-
const messages = state.outbox ?? []
|
|
156
|
-
const existing = messages.find((message) => message.id === checked.id)
|
|
157
|
-
if (existing) {
|
|
158
|
-
if (
|
|
159
|
-
existing.pursuitId !== checked.pursuitId ||
|
|
160
|
-
existing.destination !== checked.destination ||
|
|
161
|
-
existing.body !== checked.body ||
|
|
162
|
-
existing.notBefore !== checked.notBefore ||
|
|
163
|
-
existing.sourceClaimId !== sourceClaimId
|
|
164
|
-
)
|
|
165
|
-
throw new Error('Outbox message ID already names a different immutable intent.')
|
|
166
|
-
return messages
|
|
167
|
-
}
|
|
168
|
-
if (messages.length >= 128) throw new Error('Resident outbox capacity reached (128 intents).')
|
|
169
|
-
return [
|
|
170
|
-
...messages,
|
|
171
|
-
Object.freeze(
|
|
172
|
-
residentOutboxMessageSchema.parse({
|
|
173
|
-
...checked,
|
|
174
|
-
tenantId: state.tenantId,
|
|
175
|
-
agentKey: state.agentKey,
|
|
176
|
-
sourceClaimId,
|
|
177
|
-
revision: 1,
|
|
178
|
-
attempts: 0,
|
|
179
|
-
phase: 'pending',
|
|
180
|
-
claimId: null,
|
|
181
|
-
nextAttemptAt: checked.notBefore,
|
|
182
|
-
receiptId: null,
|
|
183
|
-
acknowledgedAt: null,
|
|
184
|
-
lastReason: null,
|
|
185
|
-
}),
|
|
186
|
-
),
|
|
187
|
-
]
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/** Internal exact-message transition; agenda storage owns exclusive admission. */
|
|
191
|
-
export function claimResidentOutboxMessage(
|
|
192
|
-
message: ResidentOutboxMessage,
|
|
193
|
-
now: number,
|
|
194
|
-
): ResidentOutboxMessage {
|
|
195
|
-
time.parse(now)
|
|
196
|
-
if (message.phase !== 'pending' || message.nextAttemptAt === null || message.nextAttemptAt > now)
|
|
197
|
-
throw new ResidentConflictError()
|
|
198
|
-
return Object.freeze(
|
|
199
|
-
residentOutboxMessageSchema.parse({
|
|
200
|
-
...message,
|
|
201
|
-
revision: message.revision + 1,
|
|
202
|
-
attempts: message.attempts + 1,
|
|
203
|
-
phase: 'sending',
|
|
204
|
-
claimId: randomUUID(),
|
|
205
|
-
nextAttemptAt: null,
|
|
206
|
-
}),
|
|
207
|
-
)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** Internal settlement; unknown failures deliberately have no transition. */
|
|
211
|
-
export function settleResidentOutboxMessage(
|
|
212
|
-
message: ResidentOutboxMessage,
|
|
213
|
-
outcome: ResidentDeliveryOutcome,
|
|
214
|
-
now: number,
|
|
215
|
-
): ResidentOutboxMessage {
|
|
216
|
-
time.parse(now)
|
|
217
|
-
const checked = residentDeliveryOutcomeSchema.parse(outcome)
|
|
218
|
-
if (message.phase !== 'sending' || message.claimId === null) throw new ResidentConflictError()
|
|
219
|
-
if (checked.kind === 'not-accepted' && checked.retryAt !== null && checked.retryAt <= now)
|
|
220
|
-
throw new TypeError('A delivery retry must be scheduled in the future.')
|
|
221
|
-
return Object.freeze(
|
|
222
|
-
residentOutboxMessageSchema.parse({
|
|
223
|
-
...message,
|
|
224
|
-
revision: message.revision + 1,
|
|
225
|
-
claimId: null,
|
|
226
|
-
...(checked.kind === 'acknowledged'
|
|
227
|
-
? { phase: 'acknowledged', receiptId: checked.receiptId, acknowledgedAt: now }
|
|
228
|
-
: {
|
|
229
|
-
phase: checked.retryAt === null ? 'cancelled' : 'pending',
|
|
230
|
-
nextAttemptAt: checked.retryAt,
|
|
231
|
-
lastReason: checked.reason,
|
|
232
|
-
}),
|
|
233
|
-
}),
|
|
234
|
-
)
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function admission(gate: ResidentDeliveryGate, message: ResidentOutboxMessage, now: number) {
|
|
238
|
-
const result = gate(message, now)
|
|
239
|
-
if (result.allow === true) return result
|
|
240
|
-
if (
|
|
241
|
-
result.allow !== false ||
|
|
242
|
-
typeof result.reason !== 'string' ||
|
|
243
|
-
!result.reason.trim() ||
|
|
244
|
-
result.reason.trim().length > 1_000
|
|
245
|
-
)
|
|
246
|
-
throw new TypeError('Invalid resident delivery gate result.')
|
|
247
|
-
if (result.nextCheckAt !== null) {
|
|
248
|
-
time.parse(result.nextCheckAt)
|
|
249
|
-
if (result.nextCheckAt <= now) throw new TypeError('Delivery gate must defer into the future.')
|
|
250
|
-
}
|
|
251
|
-
return result
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* @experimental Persist one send claim before calling a host-owned transport.
|
|
256
|
-
* Throws, malformed outcomes and cancellation keep the claim unresolved. Stop
|
|
257
|
-
* old executors and inspect effects before explicit settleMessage reconciliation.
|
|
258
|
-
*
|
|
259
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
260
|
-
*/
|
|
261
|
-
export async function deliverResidentMessage(
|
|
262
|
-
store: ResidentOutboxStore,
|
|
263
|
-
transport: ResidentMessageTransport,
|
|
264
|
-
options: ResidentDeliveryOptions,
|
|
265
|
-
): Promise<ResidentDeliveryResult> {
|
|
266
|
-
const { signal, gate } = options
|
|
267
|
-
const clock = options.now ?? Date.now
|
|
268
|
-
const now = () => time.parse(clock())
|
|
269
|
-
signal.throwIfAborted()
|
|
270
|
-
const state = await store.read()
|
|
271
|
-
signal.throwIfAborted()
|
|
272
|
-
if (!state) throw new Error('Create the resident agenda before delivering messages.')
|
|
273
|
-
const idle = (
|
|
274
|
-
reason: Extract<ResidentDeliveryResult, { status: 'idle' }>['reason'],
|
|
275
|
-
nextCheckAt: number | null = null,
|
|
276
|
-
): ResidentDeliveryResult => ({ status: 'idle', reason, nextCheckAt })
|
|
277
|
-
if (state.paused) return idle('paused')
|
|
278
|
-
const messages = state.outbox ?? []
|
|
279
|
-
if (messages.some((message) => message.phase === 'sending')) return idle('unresolved')
|
|
280
|
-
const pending = messages.filter((message) => message.phase === 'pending')
|
|
281
|
-
if (!pending.length) return idle('empty')
|
|
282
|
-
let nextCheckAt: number | null = null
|
|
283
|
-
let gated = false
|
|
284
|
-
const at = now()
|
|
285
|
-
for (const message of pending.sort(
|
|
286
|
-
(a, b) => (a.nextAttemptAt ?? 0) - (b.nextAttemptAt ?? 0) || a.id.localeCompare(b.id),
|
|
287
|
-
)) {
|
|
288
|
-
if (message.nextAttemptAt !== null && message.nextAttemptAt > at) {
|
|
289
|
-
nextCheckAt = Math.min(nextCheckAt ?? Number.POSITIVE_INFINITY, message.nextAttemptAt)
|
|
290
|
-
continue
|
|
291
|
-
}
|
|
292
|
-
const permission = admission(gate, message, at)
|
|
293
|
-
signal.throwIfAborted()
|
|
294
|
-
if (!permission.allow) {
|
|
295
|
-
gated = true
|
|
296
|
-
if (permission.nextCheckAt !== null)
|
|
297
|
-
nextCheckAt = Math.min(nextCheckAt ?? Number.POSITIVE_INFINITY, permission.nextCheckAt)
|
|
298
|
-
continue
|
|
299
|
-
}
|
|
300
|
-
let claimed: ResidentOutboxMessage
|
|
301
|
-
try {
|
|
302
|
-
claimed = await store.claimMessage(state, message.id, now())
|
|
303
|
-
} catch (error) {
|
|
304
|
-
if (error instanceof ResidentConflictError) return idle('contended')
|
|
305
|
-
throw error
|
|
306
|
-
}
|
|
307
|
-
signal.throwIfAborted()
|
|
308
|
-
const fresh = await store.read()
|
|
309
|
-
signal.throwIfAborted()
|
|
310
|
-
const current = fresh?.outbox?.find((item) => item.id === claimed.id)
|
|
311
|
-
if (!current || current.revision !== claimed.revision || current.claimId !== claimed.claimId)
|
|
312
|
-
return idle('contended')
|
|
313
|
-
// A pause or closing window during admission must not start the transport.
|
|
314
|
-
const checkedAt = now()
|
|
315
|
-
const permissionNow = fresh?.paused
|
|
316
|
-
? {
|
|
317
|
-
allow: false as const,
|
|
318
|
-
nextCheckAt: checkedAt + 1,
|
|
319
|
-
reason: 'Resident agenda paused before send.',
|
|
320
|
-
}
|
|
321
|
-
: admission(gate, claimed, checkedAt)
|
|
322
|
-
if (!permissionNow.allow) {
|
|
323
|
-
// Transport has not been entered: scheduling another check has no remote effect.
|
|
324
|
-
await store.settleMessage(
|
|
325
|
-
claimed,
|
|
326
|
-
{
|
|
327
|
-
kind: 'not-accepted',
|
|
328
|
-
retryAt: permissionNow.nextCheckAt ?? checkedAt + 1,
|
|
329
|
-
reason: permissionNow.reason,
|
|
330
|
-
},
|
|
331
|
-
checkedAt,
|
|
332
|
-
)
|
|
333
|
-
return idle(fresh?.paused ? 'paused' : 'window', permissionNow.nextCheckAt)
|
|
334
|
-
}
|
|
335
|
-
signal.throwIfAborted()
|
|
336
|
-
const outcome = await transport(claimed, signal)
|
|
337
|
-
signal.throwIfAborted()
|
|
338
|
-
return { status: 'settled', message: await store.settleMessage(claimed, outcome, now()) }
|
|
339
|
-
}
|
|
340
|
-
return idle(gated ? 'window' : 'not-due', nextCheckAt)
|
|
341
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
import type { ResidentAgendaState } from './agenda.js'
|
|
3
|
-
|
|
4
|
-
const identifier = z.string().uuid()
|
|
5
|
-
const revision = z.number().int().positive().safe()
|
|
6
|
-
const domain = z
|
|
7
|
-
.string()
|
|
8
|
-
.min(1)
|
|
9
|
-
.max(120)
|
|
10
|
-
.refine((value) => value.trim().length > 0, 'A proposal domain must contain text.')
|
|
11
|
-
const reason = z.string().trim().min(1).max(1_000)
|
|
12
|
-
const evidenceKey = z.string().trim().min(1).max(256)
|
|
13
|
-
|
|
14
|
-
export const residentProposalSchema = z.object({
|
|
15
|
-
id: identifier,
|
|
16
|
-
parentId: identifier,
|
|
17
|
-
parentRevision: revision,
|
|
18
|
-
domain,
|
|
19
|
-
objective: z.string().trim().min(1).max(8_000),
|
|
20
|
-
reason,
|
|
21
|
-
evidenceKey,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
export const residentProposalLimitsSchema = z.object({
|
|
25
|
-
domains: z.array(domain).min(1),
|
|
26
|
-
maxChildrenPerParent: z.number().int().min(1).max(8),
|
|
27
|
-
maxDepth: z.number().int().min(1).max(4),
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @experimental An inert subgoal proposal; creating it grants no execution authority.
|
|
32
|
-
*
|
|
33
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
34
|
-
*/
|
|
35
|
-
export interface ResidentProposal {
|
|
36
|
-
readonly id: string
|
|
37
|
-
readonly parentId: string
|
|
38
|
-
readonly parentRevision: number
|
|
39
|
-
readonly domain: string
|
|
40
|
-
readonly objective: string
|
|
41
|
-
readonly reason: string
|
|
42
|
-
readonly evidenceKey: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @experimental Host-approved routing domains and finite subgoal admission bounds.
|
|
47
|
-
*
|
|
48
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
49
|
-
*/
|
|
50
|
-
export interface ResidentProposalLimits {
|
|
51
|
-
readonly domains: readonly string[]
|
|
52
|
-
readonly maxChildrenPerParent: number
|
|
53
|
-
readonly maxDepth: number
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Persisted provenance shared with the agenda's schema validation. */
|
|
57
|
-
export const residentProposalOriginSchema = z.object({
|
|
58
|
-
proposalId: identifier,
|
|
59
|
-
parentId: identifier,
|
|
60
|
-
parentRevision: revision,
|
|
61
|
-
domain,
|
|
62
|
-
reason,
|
|
63
|
-
evidenceKey,
|
|
64
|
-
depth: z.number().int().min(1).max(4),
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @experimental Host-admitted ancestry and evidence for a resident subgoal.
|
|
69
|
-
*
|
|
70
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
71
|
-
*/
|
|
72
|
-
export type ResidentProposalOrigin = Readonly<z.infer<typeof residentProposalOriginSchema>>
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @experimental Pure validation against one agenda snapshot. The host must
|
|
76
|
-
* atomically bind this snapshot to admission. Domains are routing metadata;
|
|
77
|
-
* this does not prove an objective fits its domain or authorize any tools.
|
|
78
|
-
*
|
|
79
|
-
* @deprecated Residents are deprecated and removed in the next major release. Learning (`runLearningCycle` and the other `Learning*` names) keeps working, but `runLearningCycle` still takes a resident agenda until learning gets its own activation target in the next major release; for long-running work use scheduled tasks (`LocalTaskScheduler`), session goals and background agents.
|
|
80
|
-
*/
|
|
81
|
-
export function validateResidentProposal(
|
|
82
|
-
agenda: ResidentAgendaState,
|
|
83
|
-
input: ResidentProposal,
|
|
84
|
-
limits: ResidentProposalLimits,
|
|
85
|
-
): ResidentProposalOrigin {
|
|
86
|
-
const proposal = residentProposalSchema.parse(input)
|
|
87
|
-
const policy = residentProposalLimitsSchema.parse(limits)
|
|
88
|
-
if (agenda.paused) throw new Error('A paused agenda cannot admit resident proposals.')
|
|
89
|
-
if (agenda.pursuits.length >= 32) throw new Error('Resident agenda pursuit bound reached.')
|
|
90
|
-
if (agenda.pursuits.some((pursuit) => pursuit.origin?.proposalId === proposal.id))
|
|
91
|
-
throw new Error('Resident proposal has already been admitted.')
|
|
92
|
-
const parent = agenda.pursuits.find((pursuit) => pursuit.id === proposal.parentId)
|
|
93
|
-
if (!parent) throw new Error('Unknown resident proposal parent.')
|
|
94
|
-
if (parent.state.revision !== proposal.parentRevision)
|
|
95
|
-
throw new Error('Resident proposal parent revision is stale.')
|
|
96
|
-
if (parent.state.phase !== 'waiting' && parent.state.phase !== 'complete')
|
|
97
|
-
throw new Error('Resident proposal parent must be waiting or complete.')
|
|
98
|
-
if (!policy.domains.includes(proposal.domain))
|
|
99
|
-
throw new Error('Resident proposal domain is not host-approved.')
|
|
100
|
-
if (
|
|
101
|
-
agenda.pursuits.filter((pursuit) => pursuit.origin?.parentId === parent.id).length +
|
|
102
|
-
(parent.retiredChildren ?? 0) >=
|
|
103
|
-
policy.maxChildrenPerParent
|
|
104
|
-
)
|
|
105
|
-
throw new Error('Resident proposal parent child bound reached.')
|
|
106
|
-
const depth = (parent.origin?.depth ?? 0) + 1
|
|
107
|
-
if (depth > policy.maxDepth) throw new Error('Resident proposal depth bound reached.')
|
|
108
|
-
return Object.freeze(
|
|
109
|
-
residentProposalOriginSchema.parse({
|
|
110
|
-
proposalId: proposal.id,
|
|
111
|
-
parentId: proposal.parentId,
|
|
112
|
-
parentRevision: proposal.parentRevision,
|
|
113
|
-
domain: proposal.domain,
|
|
114
|
-
reason: proposal.reason,
|
|
115
|
-
evidenceKey: proposal.evidenceKey,
|
|
116
|
-
depth,
|
|
117
|
-
}),
|
|
118
|
-
)
|
|
119
|
-
}
|