@calliopelabs/cli 3.5.4 → 3.7.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/README.md +8 -0
- package/dist/acp/controls.d.ts +10 -0
- package/dist/acp/controls.d.ts.map +1 -0
- package/dist/acp/controls.js +81 -0
- package/dist/acp/controls.js.map +1 -0
- package/dist/acp.d.ts +21 -7
- package/dist/acp.d.ts.map +1 -1
- package/dist/acp.js +139 -23
- package/dist/acp.js.map +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +28 -8
- package/dist/bin.js.map +1 -1
- package/dist/build-identity.d.ts +27 -0
- package/dist/build-identity.d.ts.map +1 -0
- package/dist/build-identity.js +32 -0
- package/dist/build-identity.js.map +1 -0
- package/dist/build-metadata.json +1 -0
- package/dist/execution/authority.d.ts +4 -1
- package/dist/execution/authority.d.ts.map +1 -1
- package/dist/execution/authority.js +23 -7
- package/dist/execution/authority.js.map +1 -1
- package/dist/execution/child-grants.d.ts +2 -0
- package/dist/execution/child-grants.d.ts.map +1 -1
- package/dist/execution/child-grants.js +19 -4
- package/dist/execution/child-grants.js.map +1 -1
- package/dist/execution/delegated.d.ts +14 -0
- package/dist/execution/delegated.d.ts.map +1 -0
- package/dist/execution/delegated.js +66 -0
- package/dist/execution/delegated.js.map +1 -0
- package/dist/execution/files.js +6 -6
- package/dist/execution/files.js.map +1 -1
- package/dist/execution/guard.d.ts +5 -0
- package/dist/execution/guard.d.ts.map +1 -1
- package/dist/execution/guard.js +31 -16
- package/dist/execution/guard.js.map +1 -1
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +4 -0
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/ledger-cli.d.ts +2 -1
- package/dist/execution/ledger-cli.d.ts.map +1 -1
- package/dist/execution/ledger-cli.js +51 -14
- package/dist/execution/ledger-cli.js.map +1 -1
- package/dist/execution/ledger-protocol.d.ts +6 -2
- package/dist/execution/ledger-protocol.d.ts.map +1 -1
- package/dist/execution/ledger-protocol.js +110 -24
- package/dist/execution/ledger-protocol.js.map +1 -1
- package/dist/execution/ledger-server.d.ts +13 -0
- package/dist/execution/ledger-server.d.ts.map +1 -1
- package/dist/execution/ledger-server.js +57 -13
- package/dist/execution/ledger-server.js.map +1 -1
- package/dist/execution/ledger-tunnel.d.ts +50 -0
- package/dist/execution/ledger-tunnel.d.ts.map +1 -0
- package/dist/execution/ledger-tunnel.js +307 -0
- package/dist/execution/ledger-tunnel.js.map +1 -0
- package/dist/execution/ledger.d.ts +4 -0
- package/dist/execution/ledger.d.ts.map +1 -1
- package/dist/execution/ledger.js +30 -4
- package/dist/execution/ledger.js.map +1 -1
- package/dist/execution/parent-accounting.d.ts +41 -0
- package/dist/execution/parent-accounting.d.ts.map +1 -0
- package/dist/execution/parent-accounting.js +52 -0
- package/dist/execution/parent-accounting.js.map +1 -0
- package/dist/execution/parent-budget.d.ts +25 -0
- package/dist/execution/parent-budget.d.ts.map +1 -0
- package/dist/execution/parent-budget.js +102 -0
- package/dist/execution/parent-budget.js.map +1 -0
- package/dist/execution/project-spend.d.ts.map +1 -1
- package/dist/execution/project-spend.js +35 -5
- package/dist/execution/project-spend.js.map +1 -1
- package/dist/execution/remote-checkpoint.d.ts +15 -0
- package/dist/execution/remote-checkpoint.d.ts.map +1 -0
- package/dist/execution/remote-checkpoint.js +165 -0
- package/dist/execution/remote-checkpoint.js.map +1 -0
- package/dist/execution/remote-ledger.d.ts +12 -2
- package/dist/execution/remote-ledger.d.ts.map +1 -1
- package/dist/execution/remote-ledger.js +53 -21
- package/dist/execution/remote-ledger.js.map +1 -1
- package/dist/execution/types.d.ts +23 -5
- package/dist/execution/types.d.ts.map +1 -1
- package/dist/execution/types.js.map +1 -1
- package/dist/goals/supervised.js +2 -2
- package/dist/goals/supervised.js.map +1 -1
- package/dist/headless.d.ts +2 -6
- package/dist/headless.d.ts.map +1 -1
- package/dist/headless.js +17 -21
- package/dist/headless.js.map +1 -1
- package/dist/improvement/actions.d.ts +3 -4
- package/dist/improvement/actions.d.ts.map +1 -1
- package/dist/improvement/actions.js +10 -7
- package/dist/improvement/actions.js.map +1 -1
- package/dist/improvement/capabilities.d.ts +54 -0
- package/dist/improvement/capabilities.d.ts.map +1 -0
- package/dist/improvement/capabilities.js +44 -0
- package/dist/improvement/capabilities.js.map +1 -0
- package/dist/improvement/cli.d.ts +1 -1
- package/dist/improvement/cli.d.ts.map +1 -1
- package/dist/improvement/cli.js +29 -3
- package/dist/improvement/cli.js.map +1 -1
- package/dist/improvement/host-capabilities.d.ts +119 -0
- package/dist/improvement/host-capabilities.d.ts.map +1 -0
- package/dist/improvement/host-capabilities.js +18 -0
- package/dist/improvement/host-capabilities.js.map +1 -0
- package/dist/improvement/index.d.ts +6 -0
- package/dist/improvement/index.d.ts.map +1 -1
- package/dist/improvement/index.js +6 -0
- package/dist/improvement/index.js.map +1 -1
- package/dist/improvement/proposal-hash.d.ts +3 -0
- package/dist/improvement/proposal-hash.d.ts.map +1 -0
- package/dist/improvement/proposal-hash.js +5 -0
- package/dist/improvement/proposal-hash.js.map +1 -0
- package/dist/improvement/review-contract.d.ts +32 -0
- package/dist/improvement/review-contract.d.ts.map +1 -0
- package/dist/improvement/review-contract.js +62 -0
- package/dist/improvement/review-contract.js.map +1 -0
- package/dist/improvement/review-requests.d.ts +72 -0
- package/dist/improvement/review-requests.d.ts.map +1 -0
- package/dist/improvement/review-requests.js +63 -0
- package/dist/improvement/review-requests.js.map +1 -0
- package/dist/improvement/source-changes.d.ts +78 -0
- package/dist/improvement/source-changes.d.ts.map +1 -0
- package/dist/improvement/source-changes.js +91 -0
- package/dist/improvement/source-changes.js.map +1 -0
- package/dist/improvement/task-outcomes.d.ts +82 -0
- package/dist/improvement/task-outcomes.d.ts.map +1 -0
- package/dist/improvement/task-outcomes.js +72 -0
- package/dist/improvement/task-outcomes.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/isolation/contracts.d.ts +13 -0
- package/dist/isolation/contracts.d.ts.map +1 -1
- package/dist/isolation/contracts.js +9 -1
- package/dist/isolation/contracts.js.map +1 -1
- package/dist/isolation/coordinator.d.ts.map +1 -1
- package/dist/isolation/coordinator.js +4 -0
- package/dist/isolation/coordinator.js.map +1 -1
- package/dist/isolation/process.d.ts.map +1 -1
- package/dist/isolation/process.js +3 -1
- package/dist/isolation/process.js.map +1 -1
- package/dist/isolation/worktree.d.ts +9 -1
- package/dist/isolation/worktree.d.ts.map +1 -1
- package/dist/isolation/worktree.js +8 -3
- package/dist/isolation/worktree.js.map +1 -1
- package/dist/memory.d.ts +5 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +8 -6
- package/dist/memory.js.map +1 -1
- package/dist/migration/assessment-contract.d.ts +60 -0
- package/dist/migration/assessment-contract.d.ts.map +1 -0
- package/dist/migration/assessment-contract.js +132 -0
- package/dist/migration/assessment-contract.js.map +1 -0
- package/dist/migration/assessment-schema.d.ts +19 -0
- package/dist/migration/assessment-schema.d.ts.map +1 -0
- package/dist/migration/assessment-schema.js +43 -0
- package/dist/migration/assessment-schema.js.map +1 -0
- package/dist/migration/assessment.d.ts +159 -0
- package/dist/migration/assessment.d.ts.map +1 -0
- package/dist/migration/assessment.js +219 -0
- package/dist/migration/assessment.js.map +1 -0
- package/dist/migration/cli.d.ts +6 -0
- package/dist/migration/cli.d.ts.map +1 -0
- package/dist/migration/cli.js +101 -0
- package/dist/migration/cli.js.map +1 -0
- package/dist/migration/evidence.d.ts +27 -0
- package/dist/migration/evidence.d.ts.map +1 -0
- package/dist/migration/evidence.js +124 -0
- package/dist/migration/evidence.js.map +1 -0
- package/dist/migration/example.d.ts +33 -0
- package/dist/migration/example.d.ts.map +1 -0
- package/dist/migration/example.js +28 -0
- package/dist/migration/example.js.map +1 -0
- package/dist/migration/index.d.ts +21 -0
- package/dist/migration/index.d.ts.map +1 -0
- package/dist/migration/index.js +15 -0
- package/dist/migration/index.js.map +1 -0
- package/dist/migration/inventory.d.ts +70 -0
- package/dist/migration/inventory.d.ts.map +1 -0
- package/dist/migration/inventory.js +233 -0
- package/dist/migration/inventory.js.map +1 -0
- package/dist/migration/schema.d.ts +61 -0
- package/dist/migration/schema.d.ts.map +1 -0
- package/dist/migration/schema.js +76 -0
- package/dist/migration/schema.js.map +1 -0
- package/dist/migration/verification.d.ts +146 -0
- package/dist/migration/verification.d.ts.map +1 -0
- package/dist/migration/verification.js +260 -0
- package/dist/migration/verification.js.map +1 -0
- package/dist/orchestration/actions.d.ts +2 -0
- package/dist/orchestration/actions.d.ts.map +1 -1
- package/dist/orchestration/actions.js.map +1 -1
- package/dist/orchestration/artifact-host.d.ts +46 -0
- package/dist/orchestration/artifact-host.d.ts.map +1 -0
- package/dist/orchestration/artifact-host.js +64 -0
- package/dist/orchestration/artifact-host.js.map +1 -0
- package/dist/orchestration/coordinator-actions.d.ts +1 -1
- package/dist/orchestration/coordinator-actions.d.ts.map +1 -1
- package/dist/orchestration/coordinator-actions.js +5 -3
- package/dist/orchestration/coordinator-actions.js.map +1 -1
- package/dist/orchestration/coordinator-types.d.ts +23 -2
- package/dist/orchestration/coordinator-types.d.ts.map +1 -1
- package/dist/orchestration/coordinator.d.ts +5 -0
- package/dist/orchestration/coordinator.d.ts.map +1 -1
- package/dist/orchestration/coordinator.js +30 -13
- package/dist/orchestration/coordinator.js.map +1 -1
- package/dist/orchestration/execution-cli.d.ts +1 -1
- package/dist/orchestration/execution-cli.d.ts.map +1 -1
- package/dist/orchestration/execution-cli.js +29 -6
- package/dist/orchestration/execution-cli.js.map +1 -1
- package/dist/orchestration/execution-journal.d.ts.map +1 -1
- package/dist/orchestration/execution-journal.js +79 -6
- package/dist/orchestration/execution-journal.js.map +1 -1
- package/dist/orchestration/execution-store.d.ts +5 -1
- package/dist/orchestration/execution-store.d.ts.map +1 -1
- package/dist/orchestration/execution-store.js +66 -5
- package/dist/orchestration/execution-store.js.map +1 -1
- package/dist/orchestration/execution.d.ts.map +1 -1
- package/dist/orchestration/execution.js +37 -10
- package/dist/orchestration/execution.js.map +1 -1
- package/dist/orchestration/index.d.ts +6 -0
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +6 -0
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/interruption.d.ts +10 -0
- package/dist/orchestration/interruption.d.ts.map +1 -0
- package/dist/orchestration/interruption.js +38 -0
- package/dist/orchestration/interruption.js.map +1 -0
- package/dist/orchestration/question-contract.d.ts +19 -0
- package/dist/orchestration/question-contract.d.ts.map +1 -0
- package/dist/orchestration/question-contract.js +21 -0
- package/dist/orchestration/question-contract.js.map +1 -0
- package/dist/orchestration/questions.d.ts +9 -0
- package/dist/orchestration/questions.d.ts.map +1 -0
- package/dist/orchestration/questions.js +75 -0
- package/dist/orchestration/questions.js.map +1 -0
- package/dist/orchestration/reviewed-ledger.d.ts +23 -0
- package/dist/orchestration/reviewed-ledger.d.ts.map +1 -0
- package/dist/orchestration/reviewed-ledger.js +57 -0
- package/dist/orchestration/reviewed-ledger.js.map +1 -0
- package/dist/orchestration/routing.d.ts +3 -0
- package/dist/orchestration/routing.d.ts.map +1 -1
- package/dist/orchestration/routing.js +5 -1
- package/dist/orchestration/routing.js.map +1 -1
- package/dist/orchestration/source-candidates.d.ts +64 -0
- package/dist/orchestration/source-candidates.d.ts.map +1 -0
- package/dist/orchestration/source-candidates.js +95 -0
- package/dist/orchestration/source-candidates.js.map +1 -0
- package/dist/orchestration/validation.js +1 -1
- package/dist/orchestration/validation.js.map +1 -1
- package/dist/runlog.js +2 -2
- package/dist/runlog.js.map +1 -1
- package/dist/runtime/permissions.d.ts.map +1 -1
- package/dist/runtime/permissions.js +3 -2
- package/dist/runtime/permissions.js.map +1 -1
- package/dist/runtime/turn.d.ts +2 -0
- package/dist/runtime/turn.d.ts.map +1 -1
- package/dist/runtime/turn.js +21 -7
- package/dist/runtime/turn.js.map +1 -1
- package/dist/session-management/actions.js +1 -1
- package/dist/session-management/actions.js.map +1 -1
- package/dist/sessions/execution-binding.d.ts +8 -0
- package/dist/sessions/execution-binding.d.ts.map +1 -0
- package/dist/sessions/execution-binding.js +9 -0
- package/dist/sessions/execution-binding.js.map +1 -0
- package/dist/sessions/index.d.ts +1 -0
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +1 -0
- package/dist/sessions/index.js.map +1 -1
- package/dist/source-changes/writer.d.ts +77 -0
- package/dist/source-changes/writer.d.ts.map +1 -0
- package/dist/source-changes/writer.js +189 -0
- package/dist/source-changes/writer.js.map +1 -0
- package/dist/spawning/actions.d.ts +10 -1
- package/dist/spawning/actions.d.ts.map +1 -1
- package/dist/spawning/actions.js +26 -7
- package/dist/spawning/actions.js.map +1 -1
- package/dist/spawning/cli.js +1 -1
- package/dist/spawning/cli.js.map +1 -1
- package/dist/spawning/execution.d.ts.map +1 -1
- package/dist/spawning/execution.js +2 -0
- package/dist/spawning/execution.js.map +1 -1
- package/dist/spawning/types.d.ts +19 -6
- package/dist/spawning/types.d.ts.map +1 -1
- package/dist/spawning/validation.d.ts +16 -0
- package/dist/spawning/validation.d.ts.map +1 -1
- package/dist/spawning/validation.js +44 -8
- package/dist/spawning/validation.js.map +1 -1
- package/dist/storage.d.ts +5 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +10 -1
- package/dist/storage.js.map +1 -1
- package/dist/supervision/contracts.js +4 -1
- package/dist/supervision/contracts.js.map +1 -1
- package/dist/tools.d.ts +1 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +5 -0
- package/dist/tools.js.map +1 -1
- package/docs/README.md +66 -0
- package/docs/acp.md +228 -0
- package/docs/delegation-ledger.md +331 -0
- package/docs/improvement-cycles.md +304 -0
- package/docs/migration-assessment.md +113 -0
- package/docs/migration-example-plan.json +88 -0
- package/docs/migration-example-report.json +511 -0
- package/docs/migration-inventory.md +63 -0
- package/docs/migration-playbook.md +152 -0
- package/docs/migration-verification.md +177 -0
- package/docs/releases/3.6.0.md +43 -0
- package/docs/releases/3.7.0.md +53 -0
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -152,3 +152,11 @@ Issues and PRs welcome — [CONTRIBUTING.md](CONTRIBUTING.md). The codebase is T
|
|
|
152
152
|
## License
|
|
153
153
|
|
|
154
154
|
MIT © Calliope Labs Inc
|
|
155
|
+
|
|
156
|
+
## Code migration kit
|
|
157
|
+
|
|
158
|
+
The packaged [migration playbook](docs/migration-playbook.md) provides versioned
|
|
159
|
+
inventory, baseline, assessment and verification helpers for the initial
|
|
160
|
+
JavaScript-to-TypeScript CLI adapter. Discover them offline with
|
|
161
|
+
`calliope migration capabilities --json`; native reviewed execution remains the
|
|
162
|
+
authority for worker commands, budgets and file scope.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ModelPreference } from '../preferences/types.js';
|
|
2
|
+
export interface AcpControls {
|
|
3
|
+
version: 1;
|
|
4
|
+
revision: string | null;
|
|
5
|
+
mode: 'work' | 'plan';
|
|
6
|
+
selection?: ModelPreference;
|
|
7
|
+
}
|
|
8
|
+
export declare function readAcpControls(id: string, creating?: boolean): AcpControls;
|
|
9
|
+
export declare function saveAcpControls(id: string, value: AcpControls, creating?: boolean): AcpControls;
|
|
10
|
+
//# sourceMappingURL=controls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controls.d.ts","sourceRoot":"","sources":["../../src/acp/controls.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAQD,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,WAAW,CAazE;AACD,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,UAAQ,GAAG,WAAW,CAwB7F"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** Session controls are preferences, never a grant of execution authority. */
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { getSessionById, getSessionDirById } from '../storage.js';
|
|
6
|
+
import { assertSessionDirectory, readPrivateSessionFile } from '../sessions/index.js';
|
|
7
|
+
import { validatePreference } from '../preferences/validate.js';
|
|
8
|
+
const invalid = () => new Error('ACP session controls are missing, damaged or changed; reload the session or restore its saved controls.');
|
|
9
|
+
function location(id) {
|
|
10
|
+
const dir = getSessionDirById(id);
|
|
11
|
+
if (!dir)
|
|
12
|
+
throw invalid();
|
|
13
|
+
assertSessionDirectory(dir);
|
|
14
|
+
return join(dir, 'acp-controls.json');
|
|
15
|
+
}
|
|
16
|
+
export function readAcpControls(id, creating = false) {
|
|
17
|
+
const raw = readPrivateSessionFile(location(id), 16384);
|
|
18
|
+
if (raw === null) {
|
|
19
|
+
if (!creating && getSessionById(id)?.acpControlsVersion === 1)
|
|
20
|
+
throw invalid();
|
|
21
|
+
return { version: 1, revision: null, mode: 'work' };
|
|
22
|
+
}
|
|
23
|
+
let value;
|
|
24
|
+
try {
|
|
25
|
+
value = JSON.parse(raw);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw invalid();
|
|
29
|
+
}
|
|
30
|
+
if (!value || Array.isArray(value) || value.version !== 1 || typeof value.revision !== 'string' ||
|
|
31
|
+
!/^[a-f0-9-]{36}$/.test(value.revision) || !['work', 'plan'].includes(value.mode) ||
|
|
32
|
+
Object.keys(value).some(key => !['version', 'revision', 'mode', 'selection'].includes(key)))
|
|
33
|
+
throw invalid();
|
|
34
|
+
if (value.selection !== undefined)
|
|
35
|
+
value.selection = validatePreference(value.selection);
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
export function saveAcpControls(id, value, creating = false) {
|
|
39
|
+
const file = location(id), lock = file + '.lock', temporary = file + '.' + randomUUID() + '.tmp';
|
|
40
|
+
let fd;
|
|
41
|
+
try {
|
|
42
|
+
fd = fs.openSync(lock, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 0o600);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
throw new Error('ACP session controls have another writer; reload before retrying.');
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
if (readAcpControls(id, creating).revision !== value.revision)
|
|
49
|
+
throw invalid();
|
|
50
|
+
const next = { version: 1, revision: randomUUID(), mode: value.mode,
|
|
51
|
+
...(value.selection ? { selection: validatePreference(value.selection) } : {}) };
|
|
52
|
+
if (!['work', 'plan'].includes(next.mode))
|
|
53
|
+
throw invalid();
|
|
54
|
+
const output = fs.openSync(temporary, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 0o600);
|
|
55
|
+
try {
|
|
56
|
+
fs.writeFileSync(output, JSON.stringify(next) + '\n');
|
|
57
|
+
fs.fsyncSync(output);
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
fs.closeSync(output);
|
|
61
|
+
}
|
|
62
|
+
fs.renameSync(temporary, file);
|
|
63
|
+
// Match native session commits: NTFS does not support flushing a read-only directory handle.
|
|
64
|
+
if (process.platform !== 'win32') {
|
|
65
|
+
const directory = fs.openSync(dirname(file), fs.constants.O_RDONLY);
|
|
66
|
+
try {
|
|
67
|
+
fs.fsyncSync(directory);
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
fs.closeSync(directory);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return next;
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
fs.closeSync(fd);
|
|
77
|
+
fs.rmSync(temporary, { force: true });
|
|
78
|
+
fs.unlinkSync(lock);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=controls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controls.js","sourceRoot":"","sources":["../../src/acp/controls.ts"],"names":[],"mappings":"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"}
|
package/dist/acp.d.ts
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* agent logic.
|
|
10
10
|
*
|
|
11
11
|
* Baseline agent surface implemented: `initialize`, `authenticate`, `session/new`,
|
|
12
|
-
* `session/load`, `session/prompt
|
|
12
|
+
* `session/load`, `session/prompt`, `session/set_mode`, `session/set_config_option`;
|
|
13
|
+
* `session/cancel`; streaming `session/update`
|
|
13
14
|
* notifications; and the `session/request_permission` flow. When the client advertises `fs`
|
|
14
15
|
* capabilities, file tools are routed through the client's `fs/read_text_file` and
|
|
15
16
|
* `fs/write_text_file` so edits land on the editor's (possibly unsaved) buffers.
|
|
@@ -19,18 +20,27 @@
|
|
|
19
20
|
* lazy-loaded from bin.ts only for the `acp` subcommand, so it adds nothing to the
|
|
20
21
|
* default cold-start path.
|
|
21
22
|
*/
|
|
22
|
-
import { type AgentContext, type Stream, type InitializeRequest, type InitializeResponse, type NewSessionRequest, type NewSessionResponse, type LoadSessionRequest, type LoadSessionResponse, type AuthenticateResponse, type PromptRequest, type PromptResponse, type CancelNotification } from '@agentclientprotocol/sdk';
|
|
23
|
+
import { type AgentContext, type Stream, type InitializeRequest, type InitializeResponse, type NewSessionRequest, type NewSessionResponse, type LoadSessionRequest, type LoadSessionResponse, type AuthenticateResponse, type PromptRequest, type PromptResponse, type CancelNotification, type SetSessionModeRequest, type SetSessionConfigOptionRequest, type SetSessionConfigOptionResponse } from '@agentclientprotocol/sdk';
|
|
24
|
+
import { type AgentExecution } from './execution/guard.js';
|
|
25
|
+
import { type DelegatedExecutionOptions } from './execution/delegated.js';
|
|
23
26
|
declare class CalliopeAgent {
|
|
24
27
|
private readonly conn;
|
|
28
|
+
private readonly execution?;
|
|
25
29
|
private readonly approvals;
|
|
26
30
|
private clientCapabilities;
|
|
27
31
|
private readonly sessions;
|
|
28
32
|
/** Tail of the outgoing write chain; awaited to flush notifications. */
|
|
29
33
|
private lastWrite;
|
|
30
|
-
constructor(conn: AgentContext);
|
|
34
|
+
constructor(conn: AgentContext, execution?: AgentExecution | undefined);
|
|
35
|
+
private controlsState;
|
|
36
|
+
private configOptions;
|
|
37
|
+
private discoverModels;
|
|
38
|
+
private idleSession;
|
|
39
|
+
setMode(params: SetSessionModeRequest, signal?: AbortSignal): Promise<{}>;
|
|
40
|
+
setConfigOption(params: SetSessionConfigOptionRequest, signal?: AbortSignal): Promise<SetSessionConfigOptionResponse>;
|
|
31
41
|
initialize(params: InitializeRequest): Promise<InitializeResponse>;
|
|
32
42
|
authenticate(): Promise<AuthenticateResponse>;
|
|
33
|
-
newSession(params: NewSessionRequest): Promise<NewSessionResponse>;
|
|
43
|
+
newSession(params: NewSessionRequest, signal?: AbortSignal): Promise<NewSessionResponse>;
|
|
34
44
|
/**
|
|
35
45
|
* Restore a saved session and replay its conversation as session/update
|
|
36
46
|
* notifications before responding. Same store and rules as terminal /resume:
|
|
@@ -38,7 +48,7 @@ declare class CalliopeAgent {
|
|
|
38
48
|
* without a recorded result are closed as unknown outcomes. No provider
|
|
39
49
|
* request is made and no tool runs.
|
|
40
50
|
*/
|
|
41
|
-
loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse>;
|
|
51
|
+
loadSession(params: LoadSessionRequest, signal?: AbortSignal): Promise<LoadSessionResponse>;
|
|
42
52
|
prompt(params: PromptRequest): Promise<PromptResponse>;
|
|
43
53
|
cancel(params: CancelNotification): Promise<void>;
|
|
44
54
|
private runTurn;
|
|
@@ -73,11 +83,15 @@ declare class CalliopeAgent {
|
|
|
73
83
|
* which drive the SDK's client side against it over an in-memory stream pair.
|
|
74
84
|
* The SDK calls onConnect before dispatch, so the returned agent is ready.
|
|
75
85
|
*/
|
|
76
|
-
export declare function serveAcp(stream: Stream
|
|
86
|
+
export declare function serveAcp(stream: Stream, options?: {
|
|
87
|
+
execution?: AgentExecution;
|
|
88
|
+
}): CalliopeAgent;
|
|
77
89
|
/**
|
|
78
90
|
* Run Calliope as an ACP agent over stdio (stdout/stdin carry JSON-RPC). Started
|
|
79
91
|
* from bin.ts when argv[0] === 'acp'. Resolves when the client closes the stream.
|
|
80
92
|
*/
|
|
81
|
-
export declare function runAcpAgent(
|
|
93
|
+
export declare function runAcpAgent(options?: {
|
|
94
|
+
ledger?: DelegatedExecutionOptions;
|
|
95
|
+
}): Promise<number>;
|
|
82
96
|
export {};
|
|
83
97
|
//# sourceMappingURL=acp.d.ts.map
|
package/dist/acp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acp.d.ts","sourceRoot":"","sources":["../src/acp.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"acp.d.ts","sourceRoot":"","sources":["../src/acp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,OAAO,EAGL,KAAK,YAAY,EAIjB,KAAK,MAAM,EAKX,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EAEpC,MAAM,0BAA0B,CAAC;AAkBlC,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAuE,KAAK,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AA0J/I,cAAM,aAAa;IAOL,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAgB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAN5E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuB;IACjD,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,wEAAwE;IACxE,OAAO,CAAC,SAAS,CAAoC;IAErD,YAA6B,IAAI,EAAE,YAAY,EAAmB,SAAS,CAAC,EAAE,cAAc,YAAA,EAAI;IAEhG,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,aAAa;YAOP,cAAc;IAa5B,OAAO,CAAC,WAAW;IAQb,OAAO,CAAC,MAAM,EAAC,qBAAqB,EAAC,MAAM,CAAC,EAAC,WAAW,eAS7D;IACK,eAAe,CAAC,MAAM,EAAC,6BAA6B,EAAC,MAAM,CAAC,EAAC,WAAW,GAAE,OAAO,CAAC,8BAA8B,CAAC,CAkBtH;IAIK,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAqBvE;IAIK,YAAY,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAElD;IAIK,UAAU,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAC,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyC5F;IAID;;;;;;OAMG;IACG,WAAW,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAC,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAmE/F;IAIK,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAuB3D;IAIK,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOtD;YAIa,OAAO;IA4DrB,yEAAyE;IACzE,OAAO,CAAC,gBAAgB;IAkBxB;;;;OAIG;YACW,iBAAiB;IAkC/B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAsBxB;;;;OAIG;IACH,OAAO,CAAC,IAAI;IAQZ,gDAAgD;IAChD,OAAO,CAAC,KAAK;IAIb,iEAAiE;IAC3D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAM9B;CACF;AAMD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,cAAc,CAAA;CAAO,GAAG,aAAa,CAepG;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,yBAAyB,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBvG"}
|
package/dist/acp.js
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* agent logic.
|
|
10
10
|
*
|
|
11
11
|
* Baseline agent surface implemented: `initialize`, `authenticate`, `session/new`,
|
|
12
|
-
* `session/load`, `session/prompt
|
|
12
|
+
* `session/load`, `session/prompt`, `session/set_mode`, `session/set_config_option`;
|
|
13
|
+
* `session/cancel`; streaming `session/update`
|
|
13
14
|
* notifications; and the `session/request_permission` flow. When the client advertises `fs`
|
|
14
15
|
* capabilities, file tools are routed through the client's `fs/read_text_file` and
|
|
15
16
|
* `fs/write_text_file` so edits land on the editor's (possibly unsaved) buffers.
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
* default cold-start path.
|
|
21
22
|
*/
|
|
22
23
|
import { boundAcpInput, ACP_INPUT_LIMIT_METHOD } from './acp/input.js';
|
|
24
|
+
import { readAcpControls, saveAcpControls } from './acp/controls.js';
|
|
23
25
|
import { ApprovalStore } from './approvals/index.js';
|
|
24
26
|
import { realpathSync } from 'node:fs';
|
|
25
27
|
import * as path from 'node:path';
|
|
@@ -31,6 +33,7 @@ import { completePendingTools, runTurn } from './runtime/index.js';
|
|
|
31
33
|
import { createSession, getSessionById, getSessionDirById, readSessionConversation, saveSessionConversation } from './storage.js';
|
|
32
34
|
import { SessionRecoveryError, readToolOutputs } from './sessions/index.js';
|
|
33
35
|
import { resolvePreferences } from './preferences/index.js';
|
|
36
|
+
import { getAvailableModels } from './model-detection.js';
|
|
34
37
|
import { cancellable, isCancellation } from './cancellation.js';
|
|
35
38
|
import { TOOLS } from './tools.js';
|
|
36
39
|
import { DEFAULT_MODELS } from './types.js';
|
|
@@ -39,6 +42,8 @@ import * as memory from './memory.js';
|
|
|
39
42
|
import { resolveIterationLimit } from './iteration-limit.js';
|
|
40
43
|
import { formatBudgetHalt } from './budget.js';
|
|
41
44
|
import { RunLog } from './runlog.js';
|
|
45
|
+
import { ExecutionGuard } from './execution/guard.js';
|
|
46
|
+
import { connectDelegatedExecution, executionBinding, assertExecutionBinding } from './execution/delegated.js';
|
|
42
47
|
// ============================================================================
|
|
43
48
|
// Diagnostics — stderr only (stdout carries the protocol).
|
|
44
49
|
// ============================================================================
|
|
@@ -141,10 +146,10 @@ function promptToText(blocks) {
|
|
|
141
146
|
return parts.join('\n');
|
|
142
147
|
}
|
|
143
148
|
/** Provider/model preferences for a session's project; session/new and session/load resolve them alike. */
|
|
144
|
-
function sessionPreferences(cwd) {
|
|
149
|
+
function sessionPreferences(cwd, controls) {
|
|
145
150
|
let preference;
|
|
146
151
|
try {
|
|
147
|
-
preference = resolvePreferences(cwd);
|
|
152
|
+
preference = resolvePreferences(cwd, { session: controls?.selection });
|
|
148
153
|
}
|
|
149
154
|
catch (error) {
|
|
150
155
|
throw RequestError.invalidParams({ error: error instanceof Error ? error.message : String(error) });
|
|
@@ -167,13 +172,94 @@ function sessionPreferences(cwd) {
|
|
|
167
172
|
// ============================================================================
|
|
168
173
|
class CalliopeAgent {
|
|
169
174
|
conn;
|
|
175
|
+
execution;
|
|
170
176
|
approvals = new ApprovalStore();
|
|
171
177
|
clientCapabilities = {};
|
|
172
178
|
sessions = new Map();
|
|
173
179
|
/** Tail of the outgoing write chain; awaited to flush notifications. */
|
|
174
180
|
lastWrite = Promise.resolve();
|
|
175
|
-
constructor(conn) {
|
|
181
|
+
constructor(conn, execution) {
|
|
176
182
|
this.conn = conn;
|
|
183
|
+
this.execution = execution;
|
|
184
|
+
}
|
|
185
|
+
controlsState(session) {
|
|
186
|
+
return { modes: { currentModeId: session.controls.mode, availableModes: [
|
|
187
|
+
{ id: 'work', name: 'Work', description: 'Use normal permissions and confirmations.' },
|
|
188
|
+
{ id: 'plan', name: 'Plan', description: 'Analyze and plan without executing workspace mutations.' },
|
|
189
|
+
] }, configOptions: this.configOptions(session) };
|
|
190
|
+
}
|
|
191
|
+
configOptions(session) {
|
|
192
|
+
const current = session.controls.selection?.model ? 'model:' + session.controls.selection.model : 'default';
|
|
193
|
+
const options = [{ value: 'default', name: this.execution ? 'Parent-managed model' : `Configured model${session.model ? ': ' + session.model : ''}` }];
|
|
194
|
+
if (!this.execution)
|
|
195
|
+
options.push(...session.modelOptions);
|
|
196
|
+
if (!options.some(option => option.value === current))
|
|
197
|
+
options.push({ value: current, name: session.model });
|
|
198
|
+
return [{ id: 'model', name: 'Model', category: 'model', type: 'select', currentValue: current, options }];
|
|
199
|
+
}
|
|
200
|
+
async discoverModels(session, signal) {
|
|
201
|
+
session.modelOptions = [];
|
|
202
|
+
if (this.execution)
|
|
203
|
+
return;
|
|
204
|
+
const bounded = signal ? AbortSignal.any([signal, AbortSignal.timeout(5000)]) : AbortSignal.timeout(5000);
|
|
205
|
+
try {
|
|
206
|
+
const models = await getAvailableModels(session.resolvedProvider, { quiet: true, signal: bounded });
|
|
207
|
+
session.modelOptions = models.filter(model => model.evidence?.source === 'live' && model.capabilities?.chat !== false && model.id.length <= 512 && !/[\x00-\x1f\x7f]/.test(model.id))
|
|
208
|
+
.slice(0, 256).map(model => ({ value: 'model:' + model.id, name: model.name || model.id }));
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
if (signal?.aborted)
|
|
212
|
+
throw signal.reason;
|
|
213
|
+
// Unavailable discovery never invents selectable model IDs.
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
idleSession(id) {
|
|
217
|
+
const session = this.sessions.get(id);
|
|
218
|
+
if (!session)
|
|
219
|
+
throw RequestError.invalidParams({ error: `unknown session: ${id}` });
|
|
220
|
+
if (session.controller)
|
|
221
|
+
throw RequestError.invalidParams({ error: 'A prompt is already running in this session' });
|
|
222
|
+
if (readAcpControls(id).revision !== session.controls.revision)
|
|
223
|
+
throw RequestError.invalidParams({ error: 'Session controls changed; load the current session before continuing.' });
|
|
224
|
+
if (this.execution)
|
|
225
|
+
new ExecutionGuard(this.execution, session.cwd).assertActive();
|
|
226
|
+
return session;
|
|
227
|
+
}
|
|
228
|
+
async setMode(params, signal) {
|
|
229
|
+
signal?.throwIfAborted();
|
|
230
|
+
let session = this.idleSession(params.sessionId);
|
|
231
|
+
if (params.modeId !== 'work' && params.modeId !== 'plan')
|
|
232
|
+
throw RequestError.invalidParams({ error: 'Unsupported session mode' });
|
|
233
|
+
if (this.execution) {
|
|
234
|
+
await new ExecutionGuard(this.execution, session.cwd).refreshAuthority(signal);
|
|
235
|
+
session = this.idleSession(params.sessionId);
|
|
236
|
+
}
|
|
237
|
+
signal?.throwIfAborted();
|
|
238
|
+
session.controls = saveAcpControls(session.id, { ...session.controls, mode: params.modeId });
|
|
239
|
+
await this.emit(session.id, { sessionUpdate: 'current_mode_update', currentModeId: session.controls.mode });
|
|
240
|
+
return {};
|
|
241
|
+
}
|
|
242
|
+
async setConfigOption(params, signal) {
|
|
243
|
+
signal?.throwIfAborted();
|
|
244
|
+
const session = this.idleSession(params.sessionId);
|
|
245
|
+
if (params.configId !== 'model' || typeof params.value !== 'string')
|
|
246
|
+
throw RequestError.invalidParams({ error: 'Unsupported session configuration' });
|
|
247
|
+
if (this.execution)
|
|
248
|
+
throw RequestError.invalidParams({ error: 'The parent controls the delegated model selection.' });
|
|
249
|
+
const revision = session.controls.revision, provider = session.resolvedProvider;
|
|
250
|
+
await this.discoverModels(session, signal);
|
|
251
|
+
if (this.idleSession(params.sessionId) !== session || session.controls.revision !== revision || session.resolvedProvider !== provider)
|
|
252
|
+
throw RequestError.invalidParams({ error: 'Session changed during model discovery; retry with its current controls.' });
|
|
253
|
+
const value = params.value;
|
|
254
|
+
if (value !== 'default' && !session.modelOptions.some(option => option.value === value))
|
|
255
|
+
throw RequestError.invalidParams({ error: 'Select a currently discovered model.' });
|
|
256
|
+
const next = { ...session.controls, selection: value === 'default' ? undefined : { provider: session.resolvedProvider, model: value.slice(6) } };
|
|
257
|
+
const preferences = sessionPreferences(session.cwd, next);
|
|
258
|
+
const controls = saveAcpControls(session.id, next);
|
|
259
|
+
Object.assign(session, preferences, { controls });
|
|
260
|
+
const configOptions = this.configOptions(session);
|
|
261
|
+
await this.emit(session.id, { sessionUpdate: 'config_option_update', configOptions });
|
|
262
|
+
return { configOptions };
|
|
177
263
|
}
|
|
178
264
|
// ---- ACP: initialize --------------------------------------------------
|
|
179
265
|
async initialize(params) {
|
|
@@ -186,7 +272,8 @@ class CalliopeAgent {
|
|
|
186
272
|
return {
|
|
187
273
|
protocolVersion: negotiated,
|
|
188
274
|
agentCapabilities: {
|
|
189
|
-
|
|
275
|
+
_meta: { calliopeDelegation: { version: 1, workspaceBinding: 1, sessionBinding: 1 }, calliopeSessionControls: { version: 1 } },
|
|
276
|
+
// MCP-over-ACP remains unsupported.
|
|
190
277
|
loadSession: true,
|
|
191
278
|
promptCapabilities: { image: false, audio: false, embeddedContext: false },
|
|
192
279
|
},
|
|
@@ -200,14 +287,25 @@ class CalliopeAgent {
|
|
|
200
287
|
return {};
|
|
201
288
|
}
|
|
202
289
|
// ---- ACP: session/new -------------------------------------------------
|
|
203
|
-
async newSession(params) {
|
|
290
|
+
async newSession(params, signal) {
|
|
204
291
|
const cwd = params.cwd || process.cwd();
|
|
292
|
+
let guard;
|
|
293
|
+
try {
|
|
294
|
+
if (this.execution) {
|
|
295
|
+
guard = new ExecutionGuard(this.execution, cwd);
|
|
296
|
+
guard.assertActive();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
throw RequestError.invalidParams({ error: errMessage(error) });
|
|
301
|
+
}
|
|
205
302
|
const { preference, provider, resolvedProvider, model } = sessionPreferences(cwd);
|
|
206
303
|
const costModel = model || DEFAULT_MODELS[resolvedProvider];
|
|
207
|
-
const sessionId = createSession(cwd, { activate: false, prefix: 'acp' }).id;
|
|
304
|
+
const sessionId = createSession(cwd, { activate: false, prefix: 'acp', acpControlsVersion: 1, ...(this.execution ? { executionBinding: executionBinding(this.execution) } : {}) }).id;
|
|
305
|
+
const controls = saveAcpControls(sessionId, { version: 1, revision: null, mode: 'work' }, true);
|
|
208
306
|
const runlog = RunLog.open(sessionId);
|
|
209
307
|
const systemPrompt = getSystemPromptForProvider(resolvedProvider);
|
|
210
|
-
const memoryContext = memory.buildMemoryContext(cwd);
|
|
308
|
+
const memoryContext = guard ? memory.buildMemoryContext(cwd, { allowPath: file => !guard.check({ id: 'context', name: 'read_file', arguments: { path: file } }) }) : memory.buildMemoryContext(cwd);
|
|
211
309
|
const fullPrompt = memoryContext.trim()
|
|
212
310
|
? systemPrompt + '\n\n--- Project Context ---\n' + memoryContext
|
|
213
311
|
: systemPrompt;
|
|
@@ -226,9 +324,12 @@ class CalliopeAgent {
|
|
|
226
324
|
messages,
|
|
227
325
|
runlog,
|
|
228
326
|
cancelled: false,
|
|
327
|
+
controls, modelOptions: [],
|
|
229
328
|
});
|
|
329
|
+
const session = this.sessions.get(sessionId);
|
|
330
|
+
await this.discoverModels(session, signal);
|
|
230
331
|
debug(`session/new: ${sessionId} cwd=${cwd} provider=${resolvedProvider} model=${costModel}`);
|
|
231
|
-
return { sessionId };
|
|
332
|
+
return { sessionId, ...this.controlsState(session) };
|
|
232
333
|
}
|
|
233
334
|
// ---- ACP: session/load ------------------------------------------------
|
|
234
335
|
/**
|
|
@@ -238,7 +339,7 @@ class CalliopeAgent {
|
|
|
238
339
|
* without a recorded result are closed as unknown outcomes. No provider
|
|
239
340
|
* request is made and no tool runs.
|
|
240
341
|
*/
|
|
241
|
-
async loadSession(params) {
|
|
342
|
+
async loadSession(params, signal) {
|
|
242
343
|
const { sessionId, cwd } = params;
|
|
243
344
|
if (this.sessions.get(sessionId)?.controller)
|
|
244
345
|
throw RequestError.invalidParams({ error: 'A prompt is already running in this session' });
|
|
@@ -247,6 +348,9 @@ class CalliopeAgent {
|
|
|
247
348
|
throw RequestError.invalidParams({ error: `unknown session: ${sessionId}` });
|
|
248
349
|
let state;
|
|
249
350
|
try {
|
|
351
|
+
assertExecutionBinding(saved.executionBinding, this.execution, !!this.execution);
|
|
352
|
+
if (this.execution)
|
|
353
|
+
new ExecutionGuard(this.execution, cwd).assertActive();
|
|
250
354
|
if (!path.isAbsolute(cwd) || realpathSync(cwd) !== realpathSync(saved.projectPath)) {
|
|
251
355
|
throw new Error(`Session belongs to ${saved.projectPath}; load it with that working directory.`);
|
|
252
356
|
}
|
|
@@ -257,9 +361,13 @@ class CalliopeAgent {
|
|
|
257
361
|
catch (error) {
|
|
258
362
|
throw RequestError.invalidParams({ error: errMessage(error) });
|
|
259
363
|
}
|
|
364
|
+
const controls = readAcpControls(sessionId);
|
|
365
|
+
if (this.execution && controls.selection)
|
|
366
|
+
throw RequestError.invalidParams({ error: 'A delegated session cannot restore an independently selected model.' });
|
|
260
367
|
const session = {
|
|
261
|
-
id: sessionId, cwd, ...sessionPreferences(cwd), revision: state.revision,
|
|
368
|
+
id: sessionId, cwd, ...sessionPreferences(cwd, controls), revision: state.revision,
|
|
262
369
|
messages: state.messages, runlog: RunLog.open(sessionId), cancelled: false,
|
|
370
|
+
controls, modelOptions: [],
|
|
263
371
|
};
|
|
264
372
|
// An idle copy already open here is replaced by the saved state; a prompt sent
|
|
265
373
|
// before the load responds is refused as an unknown session.
|
|
@@ -301,18 +409,16 @@ class CalliopeAgent {
|
|
|
301
409
|
await this.emit(sessionId, { sessionUpdate: 'agent_thought_chunk', content: { type: 'text', text: `[${notices.join(' ')}]\n` } });
|
|
302
410
|
await this.flush();
|
|
303
411
|
this.sessions.set(sessionId, session);
|
|
412
|
+
await this.discoverModels(session, signal);
|
|
304
413
|
session.runlog.policyEvent({ tool: 'session', source: 'session-recovery', decision: 'allow', durationMs: 0,
|
|
305
414
|
reason: `session/load revision=${state.revision} messages=${session.messages.length}` });
|
|
306
415
|
await session.runlog.flush();
|
|
307
416
|
debug(`session/load: ${sessionId} cwd=${cwd} messages=${session.messages.length} status=${state.status}`);
|
|
308
|
-
return
|
|
417
|
+
return this.controlsState(session);
|
|
309
418
|
}
|
|
310
419
|
// ---- ACP: session/prompt ---------------------------------------------
|
|
311
420
|
async prompt(params) {
|
|
312
|
-
const session = this.
|
|
313
|
-
if (!session) {
|
|
314
|
-
throw RequestError.invalidParams({ error: `unknown session: ${params.sessionId}` });
|
|
315
|
-
}
|
|
421
|
+
const session = this.idleSession(params.sessionId);
|
|
316
422
|
if (session.controller)
|
|
317
423
|
throw RequestError.invalidParams({ error: 'A prompt is already running in this session' });
|
|
318
424
|
session.controller = new AbortController();
|
|
@@ -353,6 +459,11 @@ class CalliopeAgent {
|
|
|
353
459
|
// ---- The agent loop (ACP-flavoured mirror of the headless loop) --------
|
|
354
460
|
async runTurn(session, prompt) {
|
|
355
461
|
const messages = { current: session.messages };
|
|
462
|
+
const controlRevision = session.controls.revision;
|
|
463
|
+
const assertControls = () => {
|
|
464
|
+
if (readAcpControls(session.id).revision !== controlRevision)
|
|
465
|
+
throw new Error('Session controls changed during execution; reload before continuing.');
|
|
466
|
+
};
|
|
356
467
|
let streamedChars = 0;
|
|
357
468
|
try {
|
|
358
469
|
for (const warning of session.preference.warnings)
|
|
@@ -360,6 +471,7 @@ class CalliopeAgent {
|
|
|
360
471
|
const result = await runTurn({
|
|
361
472
|
captureToolOutput: true,
|
|
362
473
|
client: 'acp',
|
|
474
|
+
execution: this.execution,
|
|
363
475
|
onSafetyBranch: async () => {
|
|
364
476
|
const { branchSession } = await import('./session-management/index.js');
|
|
365
477
|
const branch = await branchSession(session.id, { kind: 'safety', signal: session.controller?.signal, runlog: session.runlog });
|
|
@@ -371,11 +483,12 @@ class CalliopeAgent {
|
|
|
371
483
|
session.runlog.sessionCheckpoint({ revision: saved.revision, status, messageCount: saved.messages.length, checksum: saved.checksum });
|
|
372
484
|
},
|
|
373
485
|
sessionId: session.id, cwd: session.cwd, provider: session.provider,
|
|
486
|
+
get mode() { assertControls(); return session.controls.mode; },
|
|
374
487
|
model: session.model || undefined, prompt, messages, signal: session.controller?.signal,
|
|
375
488
|
preferenceSources: session.preference.sources,
|
|
376
489
|
runlog: session.runlog, maxIterations: resolveIterationLimit(config.get('maxIterations')),
|
|
377
490
|
confirmation: 'mutating', approvals: this.approvals, tools: () => TOOLS, toolOptions: { fs: this.clientFsDelegate(session.id) },
|
|
378
|
-
prepare: async (request) => { streamedChars = 0; return request; },
|
|
491
|
+
prepare: async (request) => { assertControls(); streamedChars = 0; return request; },
|
|
379
492
|
approve: (call, decision) => this.requestPermission(session, call, decision.request?.reusable ?? false),
|
|
380
493
|
onToken: token => {
|
|
381
494
|
if (!token || session.cancelled)
|
|
@@ -528,15 +641,17 @@ class CalliopeAgent {
|
|
|
528
641
|
* which drive the SDK's client side against it over an in-memory stream pair.
|
|
529
642
|
* The SDK calls onConnect before dispatch, so the returned agent is ready.
|
|
530
643
|
*/
|
|
531
|
-
export function serveAcp(stream) {
|
|
644
|
+
export function serveAcp(stream, options = {}) {
|
|
532
645
|
let agent;
|
|
533
646
|
createAgent()
|
|
534
|
-
.onConnect(connection => { agent = new CalliopeAgent(connection.client); })
|
|
647
|
+
.onConnect(connection => { agent = new CalliopeAgent(connection.client, options.execution); })
|
|
535
648
|
.onRequest(ACP_INPUT_LIMIT_METHOD, () => undefined, () => { throw RequestError.invalidParams({ error: 'ACP input complexity limit exceeded.' }); })
|
|
536
649
|
.onRequest(methods.agent.initialize, ({ params }) => agent.initialize(params))
|
|
537
650
|
.onRequest(methods.agent.authenticate, () => agent.authenticate())
|
|
538
|
-
.onRequest(methods.agent.session.new, ({ params }) => agent.newSession(params))
|
|
539
|
-
.onRequest(methods.agent.session.load, ({ params }) => agent.loadSession(params))
|
|
651
|
+
.onRequest(methods.agent.session.new, ({ params, signal }) => agent.newSession(params, signal))
|
|
652
|
+
.onRequest(methods.agent.session.load, ({ params, signal }) => agent.loadSession(params, signal))
|
|
653
|
+
.onRequest(methods.agent.session.setMode, ({ params, signal }) => agent.setMode(params, signal))
|
|
654
|
+
.onRequest(methods.agent.session.setConfigOption, ({ params, signal }) => agent.setConfigOption(params, signal))
|
|
540
655
|
.onRequest(methods.agent.session.prompt, ({ params }) => agent.prompt(params))
|
|
541
656
|
.onNotification(methods.agent.session.cancel, ({ params }) => agent.cancel(params))
|
|
542
657
|
.connect({ ...stream, readable: boundAcpInput(stream.readable) });
|
|
@@ -546,11 +661,12 @@ export function serveAcp(stream) {
|
|
|
546
661
|
* Run Calliope as an ACP agent over stdio (stdout/stdin carry JSON-RPC). Started
|
|
547
662
|
* from bin.ts when argv[0] === 'acp'. Resolves when the client closes the stream.
|
|
548
663
|
*/
|
|
549
|
-
export async function runAcpAgent() {
|
|
664
|
+
export async function runAcpAgent(options = {}) {
|
|
665
|
+
const execution = options.ledger ? await connectDelegatedExecution(process.cwd(), options.ledger) : undefined;
|
|
550
666
|
const input = Readable.toWeb(process.stdin);
|
|
551
667
|
const output = Writable.toWeb(process.stdout);
|
|
552
668
|
const stream = ndJsonStream(output, input);
|
|
553
|
-
const agent = serveAcp(stream);
|
|
669
|
+
const agent = serveAcp(stream, { execution });
|
|
554
670
|
log(`Calliope ACP agent ready on stdio (protocol v${PROTOCOL_VERSION}). Logs go to stderr.`);
|
|
555
671
|
// Stay alive until the client disconnects (stdin closes).
|
|
556
672
|
await new Promise((resolve) => {
|