agentera 3.0.0-dev.20 → 3.0.0-dev.21
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 +19 -0
- package/bundle/CHANGELOG.md +63 -70
- package/bundle/README.md +17 -0
- package/bundle/UPGRADE.md +38 -0
- package/bundle/references/adapters/package-surface-characterization.md +7 -0
- package/bundle/references/artifacts/artifact-registry-interface-model.yaml +3 -3
- package/bundle/references/artifacts/state-storage-authority.yaml +1446 -0
- package/bundle/references/cli/agent-ready-state-contract.yaml +11 -39
- package/bundle/references/cli/audience-namespace-cli-migration.yaml +30 -15
- package/bundle/references/meta/documentation-inventory.md +1 -0
- package/bundle/skills/agentera/capabilities/audit/schemas/artifacts.yaml +18 -10
- package/bundle/skills/agentera/capabilities/audit/schemas/validation.yaml +10 -10
- package/bundle/skills/agentera/capabilities/build/schemas/artifacts.yaml +11 -6
- package/bundle/skills/agentera/capabilities/discuss/schemas/artifacts.yaml +3 -2
- package/bundle/skills/agentera/capabilities/document/schemas/artifacts.yaml +15 -8
- package/bundle/skills/agentera/capabilities/document/schemas/validation.yaml +13 -13
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/artifacts.yaml +15 -9
- package/bundle/skills/agentera/references/contract.md +65 -23
- package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +15 -10
- package/bundle/skills/agentera/schemas/artifacts/experiments.yaml +134 -3
- package/bundle/skills/agentera/schemas/artifacts/health.yaml +16 -10
- package/bundle/skills/agentera/schemas/artifacts/objective.yaml +18 -4
- package/bundle/skills/agentera/schemas/artifacts/plan.yaml +23 -1
- package/bundle/skills/agentera/schemas/artifacts/progress.yaml +16 -10
- package/bundle/skills/agentera/schemas/artifacts/todo.yaml +34 -0
- package/dist/capabilities/audit/instructions.js +1 -1
- package/dist/capabilities/audit/instructions.js.map +1 -1
- package/dist/capabilities/build/instructions.js +1 -1
- package/dist/capabilities/build/instructions.js.map +1 -1
- package/dist/capabilities/discuss/instructions.js +1 -1
- package/dist/capabilities/discuss/instructions.js.map +1 -1
- package/dist/capabilities/document/instructions.js +1 -1
- package/dist/capabilities/document/instructions.js.map +1 -1
- package/dist/capabilities/optimize/instructions.js +1 -1
- package/dist/capabilities/optimize/instructions.js.map +1 -1
- package/dist/capabilities/orchestrate/instructions.js +1 -1
- package/dist/capabilities/orchestrate/instructions.js.map +1 -1
- package/dist/capabilities/plan/instructions.js +1 -1
- package/dist/capabilities/plan/instructions.js.map +1 -1
- package/dist/capabilities/profile/instructions.js +1 -1
- package/dist/capabilities/profile/instructions.js.map +1 -1
- package/dist/capabilities/vision/instructions.js +1 -1
- package/dist/capabilities/vision/instructions.js.map +1 -1
- package/dist/cli/appContext.js +14 -6
- package/dist/cli/appContext.js.map +1 -1
- package/dist/cli/capabilityContext/bespoke.js +3 -1
- package/dist/cli/capabilityContext/bespoke.js.map +1 -1
- package/dist/cli/capabilityContext/build.js +5 -4
- package/dist/cli/capabilityContext/build.js.map +1 -1
- package/dist/cli/capabilityContext/closeout.js +2 -1
- package/dist/cli/capabilityContext/closeout.js.map +1 -1
- package/dist/cli/capabilityContext/contract.js +29 -0
- package/dist/cli/capabilityContext/contract.js.map +1 -1
- package/dist/cli/capabilityContext/evidence.js +21 -20
- package/dist/cli/capabilityContext/evidence.js.map +1 -1
- package/dist/cli/capabilityContext/orchestration.js +3 -2
- package/dist/cli/capabilityContext/orchestration.js.map +1 -1
- package/dist/cli/capabilityContext/progress.js +9 -4
- package/dist/cli/capabilityContext/progress.js.map +1 -1
- package/dist/cli/capabilityContext/slim.js +37 -6
- package/dist/cli/capabilityContext/slim.js.map +1 -1
- package/dist/cli/capabilityContext/startup.js +30 -6
- package/dist/cli/capabilityContext/startup.js.map +1 -1
- package/dist/cli/capabilityContext/types.js +14 -4
- package/dist/cli/capabilityContext/types.js.map +1 -1
- package/dist/cli/commands/backfill.js +194 -0
- package/dist/cli/commands/backfill.js.map +1 -0
- package/dist/cli/commands/compact.js +40 -11
- package/dist/cli/commands/compact.js.map +1 -1
- package/dist/cli/commands/durability.js +85 -0
- package/dist/cli/commands/durability.js.map +1 -0
- package/dist/cli/commands/migrate.js +677 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/prime/collectOrientationState.js +23 -0
- package/dist/cli/commands/prime/collectOrientationState.js.map +1 -1
- package/dist/cli/commands/prime/orientationOutput.js +4 -2
- package/dist/cli/commands/prime/orientationOutput.js.map +1 -1
- package/dist/cli/commands/query.js +20 -2
- package/dist/cli/commands/query.js.map +1 -1
- package/dist/cli/commands/schema.js +247 -69
- package/dist/cli/commands/schema.js.map +1 -1
- package/dist/cli/commands/state/decisions.js +28 -10
- package/dist/cli/commands/state/decisions.js.map +1 -1
- package/dist/cli/commands/state/experimentRecords.js +156 -0
- package/dist/cli/commands/state/experimentRecords.js.map +1 -0
- package/dist/cli/commands/state/get.js +141 -0
- package/dist/cli/commands/state/get.js.map +1 -0
- package/dist/cli/commands/state/index.js +2 -2
- package/dist/cli/commands/state/index.js.map +1 -1
- package/dist/cli/commands/state/list.js +159 -0
- package/dist/cli/commands/state/list.js.map +1 -0
- package/dist/cli/commands/state/plan.js +146 -41
- package/dist/cli/commands/state/plan.js.map +1 -1
- package/dist/cli/commands/state/planTasks.js +164 -0
- package/dist/cli/commands/state/planTasks.js.map +1 -0
- package/dist/cli/commands/state/plans.js +154 -0
- package/dist/cli/commands/state/plans.js.map +1 -0
- package/dist/cli/commands/state/write.js +8 -3
- package/dist/cli/commands/state/write.js.map +1 -1
- package/dist/cli/dispatch/check.js +71 -4
- package/dist/cli/dispatch/check.js.map +1 -1
- package/dist/cli/dispatch/index.js +48 -30
- package/dist/cli/dispatch/index.js.map +1 -1
- package/dist/cli/dispatch/lifecycle.js +4 -4
- package/dist/cli/dispatch/lifecycle.js.map +1 -1
- package/dist/cli/dispatch/state.js +23 -3
- package/dist/cli/dispatch/state.js.map +1 -1
- package/dist/cli/errors.js +13 -14
- package/dist/cli/errors.js.map +1 -1
- package/dist/cli/help.js +162 -3
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/orientation.js +146 -34
- package/dist/cli/orientation.js.map +1 -1
- package/dist/cli/planArtifacts.js +31 -2
- package/dist/cli/planArtifacts.js.map +1 -1
- package/dist/cli/prime-blob.js +1 -0
- package/dist/cli/prime-blob.js.map +1 -1
- package/dist/cli/startupCompletenessContract.js +3 -2
- package/dist/cli/startupCompletenessContract.js.map +1 -1
- package/dist/cli/stateQuery.js +5 -3
- package/dist/cli/stateQuery.js.map +1 -1
- package/dist/core/text.js +11 -0
- package/dist/core/text.js.map +1 -0
- package/dist/hooks/compaction/apply.js +224 -46
- package/dist/hooks/compaction/apply.js.map +1 -1
- package/dist/hooks/compaction/dryRun.js +2 -0
- package/dist/hooks/compaction/dryRun.js.map +1 -1
- package/dist/hooks/compaction/index.js +4 -4
- package/dist/hooks/compaction/index.js.map +1 -1
- package/dist/hooks/compaction/parse.js +73 -5
- package/dist/hooks/compaction/parse.js.map +1 -1
- package/dist/hooks/compaction/retention.js +22 -21
- package/dist/hooks/compaction/retention.js.map +1 -1
- package/dist/hooks/compaction/status.js +116 -23
- package/dist/hooks/compaction/status.js.map +1 -1
- package/dist/hooks/sessionStart.js +39 -7
- package/dist/hooks/sessionStart.js.map +1 -1
- package/dist/hooks/validateArtifact/index.js +2 -2
- package/dist/hooks/validateArtifact/index.js.map +1 -1
- package/dist/hooks/validateArtifact/markdown.js +9 -9
- package/dist/hooks/validateArtifact/markdown.js.map +1 -1
- package/dist/hooks/validateArtifact/traversal.js +11 -9
- package/dist/hooks/validateArtifact/traversal.js.map +1 -1
- package/dist/registries/artifactRegistry.js +147 -44
- package/dist/registries/artifactRegistry.js.map +1 -1
- package/dist/release/releaseMetadata.js +95 -1
- package/dist/release/releaseMetadata.js.map +1 -1
- package/dist/state/archiveDiscovery.js +589 -0
- package/dist/state/archiveDiscovery.js.map +1 -0
- package/dist/state/archivePublication.js +225 -0
- package/dist/state/archivePublication.js.map +1 -0
- package/dist/state/archiveRecovery.js +238 -0
- package/dist/state/archiveRecovery.js.map +1 -0
- package/dist/state/archiveReplay.js +54 -0
- package/dist/state/archiveReplay.js.map +1 -0
- package/dist/state/decisionOverlay.js +255 -0
- package/dist/state/decisionOverlay.js.map +1 -0
- package/dist/state/directRetrieval.js +322 -0
- package/dist/state/directRetrieval.js.map +1 -0
- package/dist/state/durability.js +451 -0
- package/dist/state/durability.js.map +1 -0
- package/dist/state/experimentArchive.js +64 -0
- package/dist/state/experimentArchive.js.map +1 -0
- package/dist/state/experimentIdentity.js +191 -0
- package/dist/state/experimentIdentity.js.map +1 -0
- package/dist/state/experimentRetrieval.js +447 -0
- package/dist/state/experimentRetrieval.js.map +1 -0
- package/dist/state/gitBackfill.js +561 -0
- package/dist/state/gitBackfill.js.map +1 -0
- package/dist/state/gitBackfillAuthority.js +141 -0
- package/dist/state/gitBackfillAuthority.js.map +1 -0
- package/dist/state/gitBackfillHistory.js +278 -0
- package/dist/state/gitBackfillHistory.js.map +1 -0
- package/dist/state/gitBackfillOutput.js +209 -0
- package/dist/state/gitBackfillOutput.js.map +1 -0
- package/dist/state/healthRepair.js +70 -0
- package/dist/state/healthRepair.js.map +1 -0
- package/dist/state/legacyIdentity.js +48 -0
- package/dist/state/legacyIdentity.js.map +1 -0
- package/dist/state/legacyMigration.js +516 -0
- package/dist/state/legacyMigration.js.map +1 -0
- package/dist/state/legacyMigrationParser.js +489 -0
- package/dist/state/legacyMigrationParser.js.map +1 -0
- package/dist/state/listAccounting.js +55 -0
- package/dist/state/listAccounting.js.map +1 -0
- package/dist/state/listClassification.js +18 -0
- package/dist/state/listClassification.js.map +1 -0
- package/dist/state/listRetrieval.js +782 -0
- package/dist/state/listRetrieval.js.map +1 -0
- package/dist/state/migrationAuthority.js +413 -0
- package/dist/state/migrationAuthority.js.map +1 -0
- package/dist/state/migrationEnrichment.js +35 -0
- package/dist/state/migrationEnrichment.js.map +1 -0
- package/dist/state/planIdentity.js +45 -0
- package/dist/state/planIdentity.js.map +1 -0
- package/dist/state/planRetrieval.js +314 -0
- package/dist/state/planRetrieval.js.map +1 -0
- package/dist/state/planTaskRetrieval.js +285 -0
- package/dist/state/planTaskRetrieval.js.map +1 -0
- package/dist/state/projectionPolicy.js +184 -0
- package/dist/state/projectionPolicy.js.map +1 -0
- package/dist/state/retrievalAuthority.js +326 -0
- package/dist/state/retrievalAuthority.js.map +1 -0
- package/dist/state/startupProjection.js +498 -0
- package/dist/state/startupProjection.js.map +1 -0
- package/dist/state/write/experimentPublication.js +193 -0
- package/dist/state/write/experimentPublication.js.map +1 -0
- package/dist/state/write/explain.js +28 -14
- package/dist/state/write/explain.js.map +1 -1
- package/dist/state/write/helpers.js +8 -0
- package/dist/state/write/helpers.js.map +1 -0
- package/dist/state/write/index.js +1 -0
- package/dist/state/write/index.js.map +1 -1
- package/dist/state/write/lock.js +24 -1
- package/dist/state/write/lock.js.map +1 -1
- package/dist/state/write/mutation.js +190 -0
- package/dist/state/write/mutation.js.map +1 -0
- package/dist/state/write/operations.js +36 -2
- package/dist/state/write/operations.js.map +1 -1
- package/dist/state/write/planPublication.js +172 -0
- package/dist/state/write/planPublication.js.map +1 -0
- package/dist/state/write/transaction.js +238 -225
- package/dist/state/write/transaction.js.map +1 -1
- package/dist/upgrade/migrateArtifactsV2ToV3.js +2 -2
- package/dist/upgrade/migrateArtifactsV2ToV3.js.map +1 -1
- package/dist/validate/crossCapability.js +9 -6
- package/dist/validate/crossCapability.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
5
|
+
import YAML from "yaml";
|
|
6
|
+
import { loadYamlMapping } from "../core/yaml.js";
|
|
7
|
+
import { discoverPlanArtifacts, planCatalogEntry, planDocumentParts } from "../cli/planArtifacts.js";
|
|
8
|
+
import { canonicalRecordJson } from "./archiveDiscovery.js";
|
|
9
|
+
import { StateRetrievalFailure } from "./directRetrieval.js";
|
|
10
|
+
import { PLAN_ID } from "./planIdentity.js";
|
|
11
|
+
const CURSOR_VERSION = 1;
|
|
12
|
+
const ORDER = "created_desc_then_plan_id_asc";
|
|
13
|
+
const MAX_LIST_BYTES = 32_768;
|
|
14
|
+
function hash(value) {
|
|
15
|
+
return createHash("sha256").update(canonicalRecordJson(value), "utf8").digest("hex");
|
|
16
|
+
}
|
|
17
|
+
function fail(exitCode, className, message, verb, details = {}) {
|
|
18
|
+
const list = verb === "list";
|
|
19
|
+
return new StateRetrievalFailure({
|
|
20
|
+
schemaVersion: "agentera.stateFailure.v1",
|
|
21
|
+
status: "fail",
|
|
22
|
+
error: {
|
|
23
|
+
class: className,
|
|
24
|
+
message,
|
|
25
|
+
syntax: list
|
|
26
|
+
? "agentera state plan list [--limit N] [--cursor TOKEN] --format json"
|
|
27
|
+
: "agentera state plan get --plan PLAN_ID --format json",
|
|
28
|
+
example: list
|
|
29
|
+
? "agentera state plan list --limit 20 --format json"
|
|
30
|
+
: "agentera state plan get --plan plan:123e4567-e89b-42d3-a456-426614174000 --format json",
|
|
31
|
+
recovery: details.recovery ?? "Correct the command using one of the valid forms and retry; no state was changed.",
|
|
32
|
+
valid_values: list
|
|
33
|
+
? ["list", "--limit 1..100", "--cursor TOKEN", "--format text|json|yaml"]
|
|
34
|
+
: ["get", "--plan PLAN_ID", "--format text|json|yaml"],
|
|
35
|
+
...details,
|
|
36
|
+
},
|
|
37
|
+
}, exitCode);
|
|
38
|
+
}
|
|
39
|
+
function logicalPlans(discovery) {
|
|
40
|
+
const byId = new Map();
|
|
41
|
+
for (const identity of discovery.identities) {
|
|
42
|
+
const values = byId.get(identity.stableId) ?? [];
|
|
43
|
+
values.push(identity);
|
|
44
|
+
byId.set(identity.stableId, values);
|
|
45
|
+
}
|
|
46
|
+
return [...byId.entries()].map(([stableId, identities]) => {
|
|
47
|
+
const ordered = [...identities].sort((left, right) => {
|
|
48
|
+
const leftActive = left.artifact.path === discovery.activePath ? 0 : 1;
|
|
49
|
+
const rightActive = right.artifact.path === discovery.activePath ? 0 : 1;
|
|
50
|
+
return leftActive - rightActive || left.artifact.path.localeCompare(right.artifact.path);
|
|
51
|
+
});
|
|
52
|
+
const paths = [...new Set(ordered.map((value) => value.artifact.path))].sort();
|
|
53
|
+
return {
|
|
54
|
+
stableId,
|
|
55
|
+
artifact: ordered[0].artifact,
|
|
56
|
+
identity: ordered[0],
|
|
57
|
+
paths,
|
|
58
|
+
active: paths.includes(discovery.activePath),
|
|
59
|
+
archived: paths.some((candidate) => candidate !== discovery.activePath),
|
|
60
|
+
};
|
|
61
|
+
}).sort((left, right) => {
|
|
62
|
+
const created = planDocumentParts(right.artifact.data).created.localeCompare(planDocumentParts(left.artifact.data).created);
|
|
63
|
+
return created || left.stableId.localeCompare(right.stableId);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function catalogEntry(plan) {
|
|
67
|
+
const entry = planCatalogEntry(plan.artifact, plan.active ? plan.artifact.path : "", plan.identity);
|
|
68
|
+
entry.detail_availability = plan.identity.ambiguous ? "unavailable" : "full";
|
|
69
|
+
entry.active = plan.active;
|
|
70
|
+
entry.archived = plan.archived;
|
|
71
|
+
entry.provenance = {
|
|
72
|
+
storage: plan.active && plan.archived ? "active_and_archive_files" : plan.active ? "active_plan_file" : "immutable_plan_archive",
|
|
73
|
+
lifecycle_positions: [...(plan.active ? ["active"] : []), ...(plan.archived ? ["archived"] : [])],
|
|
74
|
+
paths: plan.paths,
|
|
75
|
+
...(plan.paths.length > 1 ? { mirrored_paths: plan.paths } : { path: plan.paths[0] }),
|
|
76
|
+
};
|
|
77
|
+
entry.retrieval = { get: `agentera state plan get --plan ${plan.stableId} --format json` };
|
|
78
|
+
return entry;
|
|
79
|
+
}
|
|
80
|
+
function refs(plans) {
|
|
81
|
+
return plans.map((plan) => ({ stable_id: plan.stableId, paths: plan.paths, canonical_hash: hash(plan.identity.canonicalJson) }));
|
|
82
|
+
}
|
|
83
|
+
function snapshotId(candidateRefs) {
|
|
84
|
+
return hash({ collection: "plan.plans", order: ORDER, candidates: candidateRefs });
|
|
85
|
+
}
|
|
86
|
+
function cursorKey(projectRoot) {
|
|
87
|
+
return createHash("sha256").update(`agentera-plan-cursor\0${path.resolve(projectRoot)}`, "utf8").digest();
|
|
88
|
+
}
|
|
89
|
+
function sign(payload, projectRoot) {
|
|
90
|
+
return createHmac("sha256", cursorKey(projectRoot)).update(canonicalRecordJson(payload), "utf8").digest("hex");
|
|
91
|
+
}
|
|
92
|
+
function encodeCursor(payload, projectRoot) {
|
|
93
|
+
const bytes = Buffer.from(JSON.stringify({ ...payload, signature: sign(payload, projectRoot) }), "utf8");
|
|
94
|
+
return deflateRawSync(bytes).toString("base64url");
|
|
95
|
+
}
|
|
96
|
+
function parseCursor(token, projectRoot) {
|
|
97
|
+
const invalid = (message) => {
|
|
98
|
+
throw fail(2, "cursor_invalid", message, "list", {
|
|
99
|
+
recovery: "Copy response.next_cursor exactly, or omit --cursor to establish a new plan-catalog snapshot.",
|
|
100
|
+
details: { cursor: "opaque; do not parse or construct cursor tokens" },
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
if (!token || token.length > 100_000 || !/^[A-Za-z0-9_-]+$/.test(token))
|
|
104
|
+
invalid("cursor is not a valid opaque token");
|
|
105
|
+
let decoded;
|
|
106
|
+
try {
|
|
107
|
+
const compressed = Buffer.from(token, "base64url");
|
|
108
|
+
if (compressed.toString("base64url") !== token)
|
|
109
|
+
invalid("cursor is not a canonical opaque token");
|
|
110
|
+
decoded = JSON.parse(inflateRawSync(compressed, { maxOutputLength: 1_000_000 }).toString("utf8"));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
invalid("cursor is not a valid opaque token");
|
|
114
|
+
}
|
|
115
|
+
if (decoded === null || typeof decoded !== "object" || Array.isArray(decoded))
|
|
116
|
+
invalid("cursor payload is invalid");
|
|
117
|
+
const record = decoded;
|
|
118
|
+
const { signature, ...unsigned } = record;
|
|
119
|
+
if (typeof signature !== "string" || !/^[0-9a-f]{64}$/.test(signature))
|
|
120
|
+
invalid("cursor signature is invalid");
|
|
121
|
+
const expected = sign(unsigned, projectRoot);
|
|
122
|
+
if (!timingSafeEqual(Buffer.from(signature), Buffer.from(expected)))
|
|
123
|
+
invalid("cursor signature is invalid");
|
|
124
|
+
if (unsigned.version !== CURSOR_VERSION || unsigned.collection !== "plan.plans" || unsigned.order !== ORDER)
|
|
125
|
+
invalid("cursor is bound to a different collection or order");
|
|
126
|
+
if (!Number.isSafeInteger(unsigned.after) || Number(unsigned.after) < 1 || !Array.isArray(unsigned.candidate_ids) || !Array.isArray(unsigned.diagnostics))
|
|
127
|
+
invalid("cursor payload is invalid");
|
|
128
|
+
if (unsigned.candidate_ids.some((candidate) => typeof candidate !== "string" || !PLAN_ID.test(candidate)))
|
|
129
|
+
invalid("cursor candidate snapshot is invalid");
|
|
130
|
+
if (typeof unsigned.snapshot_id !== "string" || !/^[0-9a-f]{64}$/.test(unsigned.snapshot_id) || typeof unsigned.diagnostic_hash !== "string" || !/^[0-9a-f]{64}$/.test(unsigned.diagnostic_hash))
|
|
131
|
+
invalid("cursor snapshot is invalid");
|
|
132
|
+
return unsigned;
|
|
133
|
+
}
|
|
134
|
+
function plansFromSnapshot(discovery, payload) {
|
|
135
|
+
if (hash(discovery.diagnostics) !== payload.diagnostic_hash) {
|
|
136
|
+
throw fail(1, "cursor_snapshot_unavailable", "the plan catalog diagnostics changed and the snapshot cannot be resumed exactly", "list", {
|
|
137
|
+
recovery: "Start a new plan listing without --cursor to establish the current snapshot.",
|
|
138
|
+
details: { snapshot_id: payload.snapshot_id },
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
const current = logicalPlans(discovery);
|
|
142
|
+
const plans = payload.candidate_ids.map((stableId) => {
|
|
143
|
+
const match = current.find((candidate) => candidate.stableId === stableId);
|
|
144
|
+
if (!match) {
|
|
145
|
+
throw fail(1, "cursor_snapshot_unavailable", "the plan catalog snapshot changed and cannot be resumed exactly", "list", {
|
|
146
|
+
recovery: "Start a new plan listing without --cursor to establish the current snapshot.",
|
|
147
|
+
details: { snapshot_id: payload.snapshot_id },
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return match;
|
|
151
|
+
});
|
|
152
|
+
if (snapshotId(refs(plans)) !== payload.snapshot_id) {
|
|
153
|
+
throw fail(1, "cursor_snapshot_unavailable", "the plan catalog snapshot changed and cannot be resumed exactly", "list", {
|
|
154
|
+
recovery: "Start a new plan listing without --cursor to establish the current snapshot.",
|
|
155
|
+
details: { snapshot_id: payload.snapshot_id },
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return plans;
|
|
159
|
+
}
|
|
160
|
+
function baseList(plans, selected, diagnostics, snapshotRefs) {
|
|
161
|
+
const degraded = diagnostics.length > 0 || plans.some((plan) => !plan.identity.persisted || plan.identity.ambiguous);
|
|
162
|
+
return {
|
|
163
|
+
schemaVersion: "agentera.stateRetrieval.v1",
|
|
164
|
+
command: "state plan list",
|
|
165
|
+
status: degraded ? "degraded" : "ok",
|
|
166
|
+
entries: selected.map(catalogEntry),
|
|
167
|
+
counts: { total: plans.length, returned: selected.length, remaining: plans.length - selected.length, omitted: plans.length - selected.length },
|
|
168
|
+
order: ORDER,
|
|
169
|
+
filters: {},
|
|
170
|
+
snapshot: { id: snapshotId(snapshotRefs), candidate_count: plans.length, has_more: plans.length > selected.length },
|
|
171
|
+
source: { artifact: "plan", storage: "active_plan_file_and_immutable_plan_archive_files", compatibility_diagnostics: diagnostics },
|
|
172
|
+
source_contract: {
|
|
173
|
+
authority: "references/artifacts/state-storage-authority.yaml",
|
|
174
|
+
complete_for_plan_list_retrieval: true,
|
|
175
|
+
storage_ownership: "active_plan_file_and_immutable_plan_archive_files",
|
|
176
|
+
},
|
|
177
|
+
retrieval: { get: "agentera state plan get --plan PLAN_ID --format json" },
|
|
178
|
+
omitted: false,
|
|
179
|
+
omitted_count: 0,
|
|
180
|
+
omission_reason: null,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function withPage(plans, diagnostics, start, retained, projectRoot, reason) {
|
|
184
|
+
const snapshotRefs = refs(plans);
|
|
185
|
+
const selected = plans.slice(start, start + retained);
|
|
186
|
+
const remaining = Math.max(0, plans.length - start - selected.length);
|
|
187
|
+
const response = baseList(plans, selected, diagnostics, snapshotRefs);
|
|
188
|
+
response.counts = { total: plans.length, returned: selected.length, remaining, omitted: remaining };
|
|
189
|
+
response.snapshot = { ...response.snapshot, has_more: remaining > 0 };
|
|
190
|
+
if (remaining > 0 && selected.length > 0) {
|
|
191
|
+
const token = encodeCursor({
|
|
192
|
+
version: CURSOR_VERSION,
|
|
193
|
+
collection: "plan.plans",
|
|
194
|
+
order: ORDER,
|
|
195
|
+
snapshot_id: snapshotId(snapshotRefs),
|
|
196
|
+
candidate_ids: plans.map((plan) => plan.stableId),
|
|
197
|
+
diagnostics,
|
|
198
|
+
diagnostic_hash: hash(diagnostics),
|
|
199
|
+
after: start + selected.length,
|
|
200
|
+
}, projectRoot);
|
|
201
|
+
response.next_cursor = token;
|
|
202
|
+
response.omitted = true;
|
|
203
|
+
response.omitted_count = remaining;
|
|
204
|
+
response.omission_reason = reason;
|
|
205
|
+
response.retrieval = {
|
|
206
|
+
continue: `agentera state plan list --cursor ${token} --format json`,
|
|
207
|
+
get: "agentera state plan get --plan PLAN_ID --format json",
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return response;
|
|
211
|
+
}
|
|
212
|
+
function serializedListBytes(response, format) {
|
|
213
|
+
const text = format === "json"
|
|
214
|
+
? JSON.stringify(response, null, 2) + "\n"
|
|
215
|
+
: YAML.stringify(response, { sortMapEntries: false });
|
|
216
|
+
return Buffer.byteLength(text, "utf8");
|
|
217
|
+
}
|
|
218
|
+
export function listPlans(projectRoot, activePath, options) {
|
|
219
|
+
if (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > 100) {
|
|
220
|
+
throw fail(2, "invalid_request", "plan list limit must be an integer from 1 through 100", "list", { valid_values: ["1..100"] });
|
|
221
|
+
}
|
|
222
|
+
const discovery = discoverPlanArtifacts(activePath);
|
|
223
|
+
const parsed = options.cursor ? parseCursor(options.cursor, projectRoot) : undefined;
|
|
224
|
+
const plans = parsed ? plansFromSnapshot(discovery, parsed) : logicalPlans(discovery);
|
|
225
|
+
const diagnostics = parsed?.diagnostics ?? discovery.diagnostics;
|
|
226
|
+
const start = parsed?.after ?? 0;
|
|
227
|
+
if (start > plans.length)
|
|
228
|
+
throw fail(2, "cursor_invalid", "cursor position is outside its plan snapshot", "list");
|
|
229
|
+
const requested = Math.min(options.limit, plans.length - start);
|
|
230
|
+
let response = withPage(plans, diagnostics, start, requested, projectRoot, "page_limit");
|
|
231
|
+
if (options.format === "json" || options.format === "yaml") {
|
|
232
|
+
for (let retained = requested; retained > 0 && serializedListBytes(response, options.format) > MAX_LIST_BYTES; retained -= 1) {
|
|
233
|
+
response = withPage(plans, diagnostics, start, retained - 1, projectRoot, "serialized_output_byte_budget");
|
|
234
|
+
}
|
|
235
|
+
if (serializedListBytes(response, options.format) > MAX_LIST_BYTES || (plans.length > start && response.entries.length === 0)) {
|
|
236
|
+
throw fail(1, "unsupported_state", `one plan cannot fit within the ${MAX_LIST_BYTES}-byte ${options.format.toUpperCase()} list budget`, "list", {
|
|
237
|
+
recovery: "Fetch a plan directly with agentera state plan get --plan PLAN_ID --format json.",
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return response;
|
|
242
|
+
}
|
|
243
|
+
function invalidCandidates(discovery, selectedPlan) {
|
|
244
|
+
const paths = [...discovery.invalidArchivePaths];
|
|
245
|
+
if (!discovery.active)
|
|
246
|
+
paths.push(discovery.activePath);
|
|
247
|
+
return paths.filter((candidatePath) => {
|
|
248
|
+
if (!fs.existsSync(candidatePath))
|
|
249
|
+
return false;
|
|
250
|
+
try {
|
|
251
|
+
const value = loadYamlMapping(fs.readFileSync(candidatePath, "utf8"));
|
|
252
|
+
const header = value.header;
|
|
253
|
+
return header !== null && typeof header === "object" && !Array.isArray(header) && header.id === selectedPlan;
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
}).sort();
|
|
259
|
+
}
|
|
260
|
+
export function getPlan(activePath, selectedPlan) {
|
|
261
|
+
if (!PLAN_ID.test(selectedPlan)) {
|
|
262
|
+
throw fail(2, "invalid_request", `invalid plan identity '${selectedPlan}'`, "get", {
|
|
263
|
+
valid_values: ["plan:<lowercase-rfc9562-uuid>", "legacy-plan:<64-lowercase-hex-digest>"],
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
const discovery = discoverPlanArtifacts(activePath);
|
|
267
|
+
const matches = logicalPlans(discovery).filter((plan) => plan.stableId === selectedPlan);
|
|
268
|
+
const invalid = invalidCandidates(discovery, selectedPlan);
|
|
269
|
+
if (matches.length > 0 && (matches[0].identity.ambiguous || invalid.length > 0)) {
|
|
270
|
+
const paths = [...new Set([...matches[0].paths, ...invalid])].sort();
|
|
271
|
+
throw fail(1, "ambiguous", `plan identity '${selectedPlan}' resolves to multiple incompatible candidates`, "get", {
|
|
272
|
+
stable_id: selectedPlan,
|
|
273
|
+
recovery: "Repair the identity collision; Agentera will not choose a plan by path, mtime, or discovery order.",
|
|
274
|
+
details: { candidate_paths: paths },
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
if (invalid.length > 0) {
|
|
278
|
+
const selectedDiagnostics = discovery.diagnostics.filter((diagnostic) => invalid.includes(diagnostic.path));
|
|
279
|
+
throw fail(1, "corrupt", `plan '${selectedPlan}' exists but cannot be read safely`, "get", {
|
|
280
|
+
stable_id: selectedPlan,
|
|
281
|
+
recovery: "Repair the selected plan archive, then retry the exact get command.",
|
|
282
|
+
details: { candidate_paths: invalid, diagnostics: selectedDiagnostics },
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
const plan = matches[0];
|
|
286
|
+
if (!plan) {
|
|
287
|
+
throw fail(1, "not_found", `plan '${selectedPlan}' was not found`, "get", {
|
|
288
|
+
stable_id: selectedPlan,
|
|
289
|
+
recovery: "List active and archived plan identities with agentera state plan list --format json, then retry.",
|
|
290
|
+
details: { compatibility_diagnostics: discovery.diagnostics },
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
const entry = catalogEntry(plan);
|
|
294
|
+
return {
|
|
295
|
+
schemaVersion: "agentera.stateRetrieval.v1",
|
|
296
|
+
command: "state plan get",
|
|
297
|
+
status: plan.identity.persisted ? "ok" : "degraded",
|
|
298
|
+
entry,
|
|
299
|
+
plan: plan.artifact.data,
|
|
300
|
+
source: {
|
|
301
|
+
artifact: "plan",
|
|
302
|
+
plan_id: selectedPlan,
|
|
303
|
+
compatibility_diagnostics: discovery.diagnostics,
|
|
304
|
+
provenance: (entry.provenance ?? {}),
|
|
305
|
+
},
|
|
306
|
+
source_contract: {
|
|
307
|
+
authority: "references/artifacts/state-storage-authority.yaml",
|
|
308
|
+
complete_for_plan_retrieval: true,
|
|
309
|
+
detail: "full_plan_document",
|
|
310
|
+
storage_ownership: "owning_active_or_archived_plan_file",
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=planRetrieval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planRetrieval.js","sourceRoot":"","sources":["../../src/state/planRetrieval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import YAML from "yaml";
|
|
4
|
+
import { canonicalRecordJson } from "./archiveDiscovery.js";
|
|
5
|
+
import { StateRetrievalFailure } from "./directRetrieval.js";
|
|
6
|
+
import { PLAN_ID } from "./planIdentity.js";
|
|
7
|
+
import { discoverPlanArtifacts, planDocumentParts } from "../cli/planArtifacts.js";
|
|
8
|
+
const CURSOR_VERSION = 1;
|
|
9
|
+
const ORDER = "task_number_asc";
|
|
10
|
+
const MAX_LIST_BYTES = 32_768;
|
|
11
|
+
function hash(value) {
|
|
12
|
+
return createHash("sha256").update(canonicalRecordJson(value), "utf8").digest("hex");
|
|
13
|
+
}
|
|
14
|
+
function fail(exitCode, className, message, verb, details = {}) {
|
|
15
|
+
const syntax = verb === "list"
|
|
16
|
+
? "agentera state plan tasks list [--plan PLAN_ID] [--limit N] [--cursor TOKEN] --format json"
|
|
17
|
+
: "agentera state plan tasks get [--plan PLAN_ID] --task N --format json";
|
|
18
|
+
const example = verb === "list"
|
|
19
|
+
? "agentera state plan tasks list --limit 20 --format json"
|
|
20
|
+
: "agentera state plan tasks get --task 1 --format json";
|
|
21
|
+
return new StateRetrievalFailure({
|
|
22
|
+
schemaVersion: "agentera.stateFailure.v1",
|
|
23
|
+
status: "fail",
|
|
24
|
+
error: {
|
|
25
|
+
class: className,
|
|
26
|
+
message,
|
|
27
|
+
syntax,
|
|
28
|
+
example,
|
|
29
|
+
recovery: details.recovery ?? "Correct the command using one of the valid forms and retry; no state was changed.",
|
|
30
|
+
valid_values: verb === "list"
|
|
31
|
+
? ["list", "--plan PLAN_ID", "--limit 1..100", "--cursor TOKEN", "--format text|json|yaml"]
|
|
32
|
+
: ["get", "--task N", "--plan PLAN_ID", "--format text|json|yaml"],
|
|
33
|
+
...details,
|
|
34
|
+
},
|
|
35
|
+
}, exitCode);
|
|
36
|
+
}
|
|
37
|
+
function activePlan(activePath, selectedPlan, verb) {
|
|
38
|
+
if (selectedPlan !== undefined && !PLAN_ID.test(selectedPlan)) {
|
|
39
|
+
throw fail(2, "invalid_request", `invalid plan identity '${selectedPlan}'`, verb, {
|
|
40
|
+
valid_values: ["plan:<lowercase-rfc9562-uuid>", "legacy-plan:<64-lowercase-hex-digest>"],
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const discovery = discoverPlanArtifacts(activePath);
|
|
44
|
+
if (!discovery.active) {
|
|
45
|
+
const diagnostic = discovery.diagnostics.find((entry) => entry.path === activePath && entry.category !== "legacy");
|
|
46
|
+
if (diagnostic) {
|
|
47
|
+
throw fail(1, "corrupt", `active plan cannot be read: ${diagnostic.message}`, verb, {
|
|
48
|
+
recovery: "Repair the active file-based plan, then retry; archived plan retrieval is a separate command family.",
|
|
49
|
+
details: { path: activePath, category: diagnostic.category },
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
throw fail(1, "not_found", "no active file-based plan exists", verb, {
|
|
53
|
+
recovery: "Create or restore an active plan, then retry the plan task command.",
|
|
54
|
+
details: { path: activePath },
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const artifact = discovery.active;
|
|
58
|
+
const parts = planDocumentParts(artifact.data);
|
|
59
|
+
const identity = discovery.identities.find((candidate) => candidate.artifact.path === artifact.path);
|
|
60
|
+
if (!identity) {
|
|
61
|
+
throw fail(1, "corrupt", "active plan header.id is not a valid plan identity", verb, {
|
|
62
|
+
recovery: "Repair the persisted active-plan identity before listing or fetching its tasks.",
|
|
63
|
+
details: { path: artifact.path, plan_id: parts.header.id ?? null },
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const planId = identity.stableId;
|
|
67
|
+
if (identity.ambiguous) {
|
|
68
|
+
throw fail(1, "ambiguous", `plan identity '${planId}' resolves to different plan documents`, verb, {
|
|
69
|
+
stable_id: planId,
|
|
70
|
+
recovery: "Repair the identity collision; Agentera will not choose a plan by path, mtime, or discovery order.",
|
|
71
|
+
details: { candidate_paths: identity.provenancePaths },
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (selectedPlan !== undefined && selectedPlan !== planId) {
|
|
75
|
+
throw fail(1, "not_found", `active plan '${selectedPlan}' was not found`, verb, {
|
|
76
|
+
stable_id: selectedPlan,
|
|
77
|
+
recovery: `Use the active plan '${planId}', or omit --plan; archived plan retrieval is not part of this command.`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const seen = new Set();
|
|
81
|
+
const tasks = parts.tasks.map((record) => {
|
|
82
|
+
const number = record.number;
|
|
83
|
+
if (!Number.isSafeInteger(number) || Number(number) < 1 || seen.has(Number(number))) {
|
|
84
|
+
throw fail(1, "corrupt", "active plan tasks require unique positive integer numbers", verb, {
|
|
85
|
+
recovery: "Repair duplicate or invalid task numbers in the active plan, then retry.",
|
|
86
|
+
details: { path: artifact.path, task_number: number ?? null },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
seen.add(Number(number));
|
|
90
|
+
return { number: Number(number), record };
|
|
91
|
+
}).sort((left, right) => left.number - right.number);
|
|
92
|
+
return {
|
|
93
|
+
artifact,
|
|
94
|
+
planId,
|
|
95
|
+
compatibility: identity.persisted ? "complete" : "degraded",
|
|
96
|
+
tasks,
|
|
97
|
+
provenancePaths: identity.provenancePaths,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function snapshotId(planId, tasks) {
|
|
101
|
+
return hash({ collection: "plan.tasks", plan_id: planId, order: ORDER, tasks });
|
|
102
|
+
}
|
|
103
|
+
function cursorKey(projectRoot) {
|
|
104
|
+
return createHash("sha256").update(`agentera-plan-task-cursor\0${path.resolve(projectRoot)}`, "utf8").digest();
|
|
105
|
+
}
|
|
106
|
+
function sign(payload, projectRoot) {
|
|
107
|
+
return createHmac("sha256", cursorKey(projectRoot)).update(canonicalRecordJson(payload), "utf8").digest("hex");
|
|
108
|
+
}
|
|
109
|
+
function encodeCursor(payload, projectRoot) {
|
|
110
|
+
return Buffer.from(JSON.stringify({ ...payload, signature: sign(payload, projectRoot) }), "utf8").toString("base64url");
|
|
111
|
+
}
|
|
112
|
+
function parseCursor(token, projectRoot, selectedPlan) {
|
|
113
|
+
const invalid = (message) => {
|
|
114
|
+
throw fail(2, "cursor_invalid", message, "list", {
|
|
115
|
+
recovery: "Copy response.next_cursor exactly, or omit --cursor to establish a new active-plan snapshot.",
|
|
116
|
+
details: { cursor: "opaque; do not parse or construct cursor tokens" },
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
if (!token || token.length > 100_000 || !/^[A-Za-z0-9_-]+$/.test(token))
|
|
120
|
+
invalid("cursor is not a valid opaque token");
|
|
121
|
+
let decoded;
|
|
122
|
+
try {
|
|
123
|
+
const bytes = Buffer.from(token, "base64url");
|
|
124
|
+
if (bytes.toString("base64url") !== token)
|
|
125
|
+
invalid("cursor is not a canonical opaque token");
|
|
126
|
+
decoded = JSON.parse(bytes.toString("utf8"));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
invalid("cursor is not a valid opaque token");
|
|
130
|
+
}
|
|
131
|
+
if (decoded === null || typeof decoded !== "object" || Array.isArray(decoded))
|
|
132
|
+
invalid("cursor payload is invalid");
|
|
133
|
+
const signed = decoded;
|
|
134
|
+
const signature = signed.signature;
|
|
135
|
+
const payload = { ...signed };
|
|
136
|
+
delete payload.signature;
|
|
137
|
+
if (typeof signature !== "string" || !/^[0-9a-f]{64}$/.test(signature))
|
|
138
|
+
invalid("cursor signature is missing or malformed");
|
|
139
|
+
const signatureString = signature;
|
|
140
|
+
const expected = sign(payload, projectRoot);
|
|
141
|
+
if (!timingSafeEqual(Buffer.from(signatureString, "hex"), Buffer.from(expected, "hex")))
|
|
142
|
+
invalid("cursor signature is invalid");
|
|
143
|
+
const parsed = payload;
|
|
144
|
+
if (parsed.version !== CURSOR_VERSION || parsed.collection !== "plan.tasks" || !PLAN_ID.test(parsed.plan_id) ||
|
|
145
|
+
parsed.order !== ORDER || !/^[0-9a-f]{64}$/.test(parsed.snapshot_id) ||
|
|
146
|
+
!Number.isSafeInteger(parsed.candidate_count) || parsed.candidate_count < 1 ||
|
|
147
|
+
!Number.isSafeInteger(parsed.candidate_max) || parsed.candidate_max < 1 ||
|
|
148
|
+
!Number.isSafeInteger(parsed.after) || parsed.after < 1 || parsed.after > parsed.candidate_max)
|
|
149
|
+
invalid("cursor is bound to a different plan task list or has an invalid payload");
|
|
150
|
+
if (selectedPlan !== undefined && parsed.plan_id !== selectedPlan) {
|
|
151
|
+
invalid("cursor is bound to a different explicit plan selector");
|
|
152
|
+
}
|
|
153
|
+
return parsed;
|
|
154
|
+
}
|
|
155
|
+
function taskEntry(plan, task) {
|
|
156
|
+
const get = `agentera state plan tasks get --task ${task.number} --format json`;
|
|
157
|
+
return {
|
|
158
|
+
stable_id: `${plan.planId}/task:${task.number}`,
|
|
159
|
+
addressable: true,
|
|
160
|
+
task_number: task.number,
|
|
161
|
+
detail_availability: "full",
|
|
162
|
+
compatibility: plan.compatibility,
|
|
163
|
+
provenance: {
|
|
164
|
+
storage: "active_plan_file",
|
|
165
|
+
path: plan.artifact.path,
|
|
166
|
+
lifecycle_position: "active",
|
|
167
|
+
plan_id: plan.planId,
|
|
168
|
+
...(plan.provenancePaths.length > 1 ? { mirrored_paths: plan.provenancePaths } : {}),
|
|
169
|
+
},
|
|
170
|
+
retrieval: { get },
|
|
171
|
+
record: task.record,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function baseList(plan, snapshotTasks, pageTasks, projectRoot) {
|
|
175
|
+
const snapshot = snapshotId(plan.planId, snapshotTasks);
|
|
176
|
+
const entries = pageTasks.map((task) => taskEntry(plan, task));
|
|
177
|
+
return {
|
|
178
|
+
schemaVersion: "agentera.stateRetrieval.v1",
|
|
179
|
+
command: "state plan tasks list",
|
|
180
|
+
status: plan.compatibility === "complete" ? "ok" : "degraded",
|
|
181
|
+
entries,
|
|
182
|
+
counts: { total: snapshotTasks.length, returned: entries.length, remaining: 0, omitted: 0 },
|
|
183
|
+
order: ORDER,
|
|
184
|
+
filters: { plan: plan.planId },
|
|
185
|
+
snapshot: { id: snapshot, candidate_count: snapshotTasks.length, has_more: false },
|
|
186
|
+
source: { artifact: "plan", active: true, path: plan.artifact.path, plan_id: plan.planId, storage: "active_plan_file" },
|
|
187
|
+
source_contract: {
|
|
188
|
+
authority: "references/artifacts/state-storage-authority.yaml",
|
|
189
|
+
complete_for_plan_task_retrieval: true,
|
|
190
|
+
storage_ownership: "owning_active_plan_file",
|
|
191
|
+
cursor: "opaque_snapshot_cursor",
|
|
192
|
+
},
|
|
193
|
+
retrieval: { get: "agentera state plan tasks get --task N --format json" },
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function withPage(plan, snapshotTasks, candidates, retained, projectRoot, reason) {
|
|
197
|
+
const selected = candidates.slice(0, retained);
|
|
198
|
+
const remaining = candidates.length - selected.length;
|
|
199
|
+
const response = baseList(plan, snapshotTasks, selected, projectRoot);
|
|
200
|
+
response.counts = { total: snapshotTasks.length, returned: selected.length, remaining, omitted: remaining };
|
|
201
|
+
response.snapshot = { ...response.snapshot, has_more: remaining > 0 };
|
|
202
|
+
if (remaining > 0 && selected.length > 0) {
|
|
203
|
+
const last = selected.at(-1);
|
|
204
|
+
const token = encodeCursor({
|
|
205
|
+
version: CURSOR_VERSION,
|
|
206
|
+
collection: "plan.tasks",
|
|
207
|
+
plan_id: plan.planId,
|
|
208
|
+
order: ORDER,
|
|
209
|
+
snapshot_id: snapshotId(plan.planId, snapshotTasks),
|
|
210
|
+
candidate_count: snapshotTasks.length,
|
|
211
|
+
candidate_max: snapshotTasks.at(-1).number,
|
|
212
|
+
after: last.number,
|
|
213
|
+
}, projectRoot);
|
|
214
|
+
response.next_cursor = token;
|
|
215
|
+
response.omitted = true;
|
|
216
|
+
response.omitted_count = remaining;
|
|
217
|
+
response.omission_reason = reason;
|
|
218
|
+
response.retrieval = {
|
|
219
|
+
continue: `agentera state plan tasks list --cursor ${token} --format json`,
|
|
220
|
+
get: "agentera state plan tasks get --task N --format json",
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return response;
|
|
224
|
+
}
|
|
225
|
+
export function listPlanTasks(projectRoot, activePath, options) {
|
|
226
|
+
if (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > 100) {
|
|
227
|
+
throw fail(2, "invalid_request", "task list limit must be an integer from 1 through 100", "list", {
|
|
228
|
+
valid_values: ["1..100"],
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
const parsed = options.cursor ? parseCursor(options.cursor, projectRoot, options.plan) : undefined;
|
|
232
|
+
const plan = activePlan(activePath, options.plan, "list");
|
|
233
|
+
if (parsed && parsed.plan_id !== plan.planId) {
|
|
234
|
+
throw fail(1, "cursor_snapshot_unavailable", "the cursor plan identity is no longer the active plan snapshot", "list", {
|
|
235
|
+
recovery: "Start a new task listing without --cursor to establish the current active-plan snapshot.",
|
|
236
|
+
details: { cursor_plan_id: parsed.plan_id, current_plan_id: plan.planId },
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
const snapshotTasks = parsed ? plan.tasks.filter((task) => task.number <= parsed.candidate_max) : plan.tasks;
|
|
240
|
+
if (parsed && (snapshotTasks.length !== parsed.candidate_count || snapshotId(plan.planId, snapshotTasks) !== parsed.snapshot_id)) {
|
|
241
|
+
throw fail(1, "cursor_snapshot_unavailable", "the active plan task snapshot changed and cannot be resumed exactly", "list", {
|
|
242
|
+
recovery: "Start a new task listing without --cursor to establish the current active-plan snapshot.",
|
|
243
|
+
details: { snapshot_id: parsed.snapshot_id, current_snapshot_id: snapshotId(plan.planId, snapshotTasks) },
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
const candidates = snapshotTasks.filter((task) => task.number > (parsed?.after ?? 0));
|
|
247
|
+
const requested = Math.min(options.limit, candidates.length);
|
|
248
|
+
let response = withPage(plan, snapshotTasks, candidates, requested, projectRoot, "page_limit");
|
|
249
|
+
if (options.format === "json" || options.format === "yaml") {
|
|
250
|
+
const serializedBytes = (value) => Buffer.byteLength(options.format === "yaml" ? YAML.stringify(value) : JSON.stringify(value, null, 2) + "\n", "utf8");
|
|
251
|
+
for (let retained = requested; retained > 0 && serializedBytes(response) > MAX_LIST_BYTES; retained -= 1) {
|
|
252
|
+
response = withPage(plan, snapshotTasks, candidates, retained - 1, projectRoot, "serialized_output_byte_budget");
|
|
253
|
+
}
|
|
254
|
+
if (serializedBytes(response) > MAX_LIST_BYTES || (candidates.length > 0 && response.entries.length === 0)) {
|
|
255
|
+
throw fail(1, "unsupported_state", `one task cannot fit within the ${MAX_LIST_BYTES}-byte ${options.format.toUpperCase()} list budget`, "list", {
|
|
256
|
+
recovery: "Fetch the task directly with agentera state plan tasks get --task N --format json.",
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return response;
|
|
261
|
+
}
|
|
262
|
+
export function getPlanTask(projectRoot, activePath, taskNumber, selectedPlan) {
|
|
263
|
+
const plan = activePlan(activePath, selectedPlan, "get");
|
|
264
|
+
const task = plan.tasks.find((candidate) => candidate.number === taskNumber);
|
|
265
|
+
if (!task) {
|
|
266
|
+
throw fail(1, "not_found", `task ${taskNumber} was not found in active plan '${plan.planId}'`, "get", {
|
|
267
|
+
stable_id: `${plan.planId}/task:${taskNumber}`,
|
|
268
|
+
entry_number: taskNumber,
|
|
269
|
+
recovery: "List valid active-plan task numbers with agentera state plan tasks list --format json, then retry.",
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
schemaVersion: "agentera.stateRetrieval.v1",
|
|
274
|
+
command: "state plan tasks get",
|
|
275
|
+
status: "ok",
|
|
276
|
+
entry: taskEntry(plan, task),
|
|
277
|
+
source: { artifact: "plan", active: true, path: plan.artifact.path, plan_id: plan.planId, storage: "active_plan_file" },
|
|
278
|
+
source_contract: {
|
|
279
|
+
authority: "references/artifacts/state-storage-authority.yaml",
|
|
280
|
+
complete_for_plan_task_retrieval: true,
|
|
281
|
+
storage_ownership: "owning_active_plan_file",
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=planTaskRetrieval.js.map
|