@agentxm/workspace-configuration 0.28.11 → 0.28.13

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.
Files changed (38) hide show
  1. package/dist/src/errors.d.ts +29 -0
  2. package/dist/src/errors.js +68 -0
  3. package/dist/src/index.d.ts +17 -12
  4. package/dist/src/index.js +28 -11
  5. package/dist/src/inline-mcp/add-inline-mcp-server.d.ts +63 -0
  6. package/dist/src/inline-mcp/add-inline-mcp-server.js +253 -0
  7. package/dist/src/{inline-mcp.d.ts → inline-mcp/definition.d.ts} +3 -3
  8. package/dist/src/{inline-mcp.js → inline-mcp/definition.js} +2 -2
  9. package/dist/src/instructions/manage-instructions.d.ts +125 -0
  10. package/dist/src/instructions/manage-instructions.js +361 -0
  11. package/dist/src/mcp-import/apply.d.ts +33 -0
  12. package/dist/src/{mcp-import.js → mcp-import/apply.js} +8 -50
  13. package/dist/src/mcp-import/import-mcp-servers.d.ts +49 -0
  14. package/dist/src/mcp-import/import-mcp-servers.js +117 -0
  15. package/dist/src/{mcp-import-preflight.d.ts → mcp-import/preflight.d.ts} +1 -1
  16. package/dist/src/{mcp-import-preflight.js → mcp-import/preflight.js} +2 -2
  17. package/dist/src/membership/agent-lifecycle.d.ts +20 -0
  18. package/dist/src/membership/agent-lifecycle.js +33 -0
  19. package/dist/src/membership/atomic-membership.d.ts +41 -0
  20. package/dist/src/membership/atomic-membership.js +125 -0
  21. package/dist/src/membership/configure-agents.d.ts +197 -0
  22. package/dist/src/membership/configure-agents.js +395 -0
  23. package/dist/src/membership/validate-agent-ids.d.ts +16 -0
  24. package/dist/src/membership/validate-agent-ids.js +85 -0
  25. package/dist/src/{initialization-interaction.d.ts → setup/initialization-interaction.d.ts} +1 -1
  26. package/dist/src/{initialization.d.ts → setup/initialization.d.ts} +11 -11
  27. package/dist/src/{initialization.js → setup/initialization.js} +3 -3
  28. package/dist/src/setup/setup-workspace.d.ts +264 -0
  29. package/dist/src/setup/setup-workspace.js +512 -0
  30. package/dist/src/testing.d.ts +95 -4
  31. package/dist/src/testing.js +215 -4
  32. package/package.json +11 -9
  33. package/dist/src/instruction-reconciliation.d.ts +0 -57
  34. package/dist/src/instruction-reconciliation.js +0 -93
  35. package/dist/src/mcp-import.d.ts +0 -40
  36. package/dist/src/membership.d.ts +0 -29
  37. package/dist/src/membership.js +0 -162
  38. /package/dist/src/{initialization-interaction.js → setup/initialization-interaction.js} +0 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Adopting the MCP servers a workspace already had.
3
+ *
4
+ * People arrive with MCP servers configured directly in their coding agents.
5
+ * Import records each one the workspace can represent losslessly as an inline
6
+ * settings entry and marks the native entry as AXM-managed, so the next
7
+ * reconciliation recognises it instead of treating it as someone else's file.
8
+ * A server whose definitions disagree across agents is a conflict, not a
9
+ * choice AXM makes on the person's behalf.
10
+ *
11
+ * @experimental This API is unstable and may change without notice.
12
+ */
13
+ import * as DateTime from "effect/DateTime";
14
+ import * as Effect from "effect/Effect";
15
+ import * as FileSystem from "effect/FileSystem";
16
+ import * as Option from "effect/Option";
17
+ import * as Path from "effect/Path";
18
+ import { OperationJournal, ResolvePlanInteraction, operationPresentation, prepareExecutionCandidate, resolveExecutionCandidate, } from "@agentxm/workspace-operations";
19
+ import { ConfiguredAgentOutcomesProvider, WorkspaceMutations } from "@agentxm/workspace-state";
20
+ import { FootprintRecorder, WorkspaceTransactionScope } from "@agentxm/workspace-transactions";
21
+ import { WorkspaceConfigurationFailed, configurationFailedToStepFailure, workspaceChangeFailedToStepFailure, } from "../errors.js";
22
+ import { applyMcpImport, collectMcpImportSources } from "./apply.js";
23
+ import { preflightMcpImports } from "./preflight.js";
24
+ const plural = (count, singular) => `${String(count)} ${singular}${count === 1 ? "" : "s"}`;
25
+ const settingsDisplayPath = (scope) => scope === "project" ? "axm.json" : ".axm/workspace/axm.json";
26
+ /**
27
+ * Discover and classify every unmanaged MCP server the configured agents and
28
+ * the workspace itself declare. Nothing is written; the candidate names the
29
+ * servers that can be adopted, the ones that conflict, and the ones skipped.
30
+ */
31
+ export const prepareImportMcpServers = () => Effect.gen(function* () {
32
+ const workspace = yield* WorkspaceMutations;
33
+ const fileSystem = yield* FileSystem.FileSystem;
34
+ const path = yield* Path.Path;
35
+ const now = yield* DateTime.now;
36
+ const configured = yield* workspace.getConfiguredMcpServerEntries();
37
+ const discovery = yield* collectMcpImportSources(workspace, fileSystem, path);
38
+ const normalized = preflightMcpImports({
39
+ configuredNames: new Set(Object.keys(configured)),
40
+ now,
41
+ sources: discovery.sources,
42
+ });
43
+ return {
44
+ _tag: "ImportMcpServers",
45
+ preflight: {
46
+ ...normalized,
47
+ skipped: [...normalized.skipped, ...discovery.skipped].sort((left, right) => left.name.localeCompare(right.name) || left.reason.localeCompare(right.reason)),
48
+ },
49
+ scope: workspace.scope,
50
+ };
51
+ });
52
+ const importArtifact = (candidate, baseDir, path) => {
53
+ const adoptions = candidate.preflight.candidates.flatMap((entry) => entry.adoptions);
54
+ const files = [...new Set(adoptions.map((adoption) => adoption.filePath))].sort();
55
+ return {
56
+ path: settingsDisplayPath(candidate.scope),
57
+ scope: candidate.scope,
58
+ change: "updated",
59
+ fileCount: 1 + files.length,
60
+ targets: [
61
+ { path: settingsDisplayPath(candidate.scope), change: "updated" },
62
+ ...files.map((filePath) => ({
63
+ path: path.relative(baseDir, filePath),
64
+ change: "updated",
65
+ })),
66
+ ],
67
+ };
68
+ };
69
+ /**
70
+ * Preview or apply the inline adoption. Every adopted entry is recorded and
71
+ * every native entry marked in one transaction, and the transaction validates
72
+ * the readback before it settles: a half-adopted server would look managed
73
+ * without being managed.
74
+ */
75
+ export const previewOrApplyImportMcpServers = (candidate, execution) => Effect.gen(function* () {
76
+ const workspace = yield* WorkspaceMutations;
77
+ const fileSystem = yield* FileSystem.FileSystem;
78
+ const path = yield* Path.Path;
79
+ const artifact = importArtifact(candidate, workspace.baseDir, path);
80
+ const conflictSteps = candidate.preflight.conflicts.map((conflict) => ({
81
+ label: conflict.name,
82
+ readiness: "error",
83
+ errorMessage: conflict.reason,
84
+ }));
85
+ const importSteps = candidate.preflight.candidates.length === 0
86
+ ? []
87
+ : [
88
+ {
89
+ label: `Import ${plural(candidate.preflight.candidates.length, "MCP server")}`,
90
+ readiness: "ready",
91
+ message: `Candidates: ${candidate.preflight.candidates.map((entry) => entry.name).join(", ")}`,
92
+ artifact,
93
+ run: applyMcpImport(candidate.preflight.candidates, workspace, fileSystem).pipe(Effect.mapError((failure) => failure instanceof WorkspaceConfigurationFailed
94
+ ? configurationFailedToStepFailure(failure)
95
+ : workspaceChangeFailedToStepFailure(failure)), Effect.as({
96
+ result: "success",
97
+ message: `Imported ${plural(candidate.preflight.candidates.length, "MCP server")}`,
98
+ artifact,
99
+ })),
100
+ },
101
+ ];
102
+ const plan = {
103
+ _tag: "Plan",
104
+ name: "Import MCP servers",
105
+ description: Option.some(`Adopt ${plural(candidate.preflight.candidates.length, "unmanaged MCP server")}`),
106
+ presentation: operationPresentation({ imperative: "import", past: "Imported", gerund: "Importing" }, "mcp-server"),
107
+ jobs: [{ concurrency: 1, steps: [...conflictSteps, ...importSteps] }],
108
+ };
109
+ const prepared = yield* prepareExecutionCandidate(plan);
110
+ return yield* resolveExecutionCandidate(prepared, execution);
111
+ });
112
+ /** The inline MCP import use case. */
113
+ export const ImportMcpServers = {
114
+ prepare: prepareImportMcpServers,
115
+ previewOrApply: previewOrApplyImportMcpServers,
116
+ };
117
+ //# sourceMappingURL=import-mcp-servers.js.map
@@ -38,4 +38,4 @@ export declare const preflightMcpImports: (args: {
38
38
  readonly now: DateTime.Utc;
39
39
  readonly sources: ReadonlyArray<McpImportSource>;
40
40
  }) => McpImportPreflight;
41
- //# sourceMappingURL=mcp-import-preflight.d.ts.map
41
+ //# sourceMappingURL=preflight.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import * as DateTime from "effect/DateTime";
2
- import { isAxmManagedMcpEntry } from "@agentxm/workspace-state";
2
+ import { isAxmManagedMcpEntry } from "@agentxm/agent-integration";
3
3
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
4
4
  const stringArray = (value) => Array.isArray(value) && value.every((item) => typeof item === "string") ? value : undefined;
5
5
  const stringRecord = (value) => {
@@ -266,4 +266,4 @@ export const preflightMcpImports = (args) => {
266
266
  conflicts: uniqueConflicts,
267
267
  };
268
268
  };
269
- //# sourceMappingURL=mcp-import-preflight.js.map
269
+ //# sourceMappingURL=preflight.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Whether the vendor still maintains a coding agent, and what a person must
3
+ * be told before AXM configures one it has stopped maintaining.
4
+ *
5
+ * The catalog records the lifecycle; membership policy decides what it means:
6
+ * a retired agent is never configured by detection alone, and configuring one
7
+ * explicitly reports why the vendor stopped maintaining it.
8
+ *
9
+ * @experimental This API is unstable and may change without notice.
10
+ */
11
+ import { type AgentId, type AgentLifecycle } from "@agentxm/extension-model/unstable/agent-capabilities";
12
+ /** Narrows a raw id to a catalog agent id. */
13
+ export declare const isCatalogAgentId: (id: string) => id is AgentId;
14
+ /** Lifecycle for a catalog agent; non-catalog ids (e.g. `universal`) are active. */
15
+ export declare const agentLifecycle: (id: string) => AgentLifecycle;
16
+ /** Whether an agent must only be configured through an explicit user choice. */
17
+ export declare const isRetiredAgent: (id: string) => boolean;
18
+ /** Warning text for configuring an agent its vendor no longer maintains. */
19
+ export declare const lifecycleWarning: (id: string) => string | undefined;
20
+ //# sourceMappingURL=agent-lifecycle.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Whether the vendor still maintains a coding agent, and what a person must
3
+ * be told before AXM configures one it has stopped maintaining.
4
+ *
5
+ * The catalog records the lifecycle; membership policy decides what it means:
6
+ * a retired agent is never configured by detection alone, and configuring one
7
+ * explicitly reports why the vendor stopped maintaining it.
8
+ *
9
+ * @experimental This API is unstable and may change without notice.
10
+ */
11
+ import { AGENTS_BY_ID, AGENT_IDS, } from "@agentxm/extension-model/unstable/agent-capabilities";
12
+ const catalogAgentIds = new Set(AGENT_IDS);
13
+ /** Narrows a raw id to a catalog agent id. */
14
+ export const isCatalogAgentId = (id) => catalogAgentIds.has(id);
15
+ const ACTIVE = { state: "active" };
16
+ /** Lifecycle for a catalog agent; non-catalog ids (e.g. `universal`) are active. */
17
+ export const agentLifecycle = (id) => isCatalogAgentId(id) ? AGENTS_BY_ID[id].lifecycle : ACTIVE;
18
+ /** Whether an agent must only be configured through an explicit user choice. */
19
+ export const isRetiredAgent = (id) => agentLifecycle(id).state === "retired";
20
+ /** Warning text for configuring an agent its vendor no longer maintains. */
21
+ export const lifecycleWarning = (id) => {
22
+ if (!isCatalogAgentId(id))
23
+ return undefined;
24
+ const name = AGENTS_BY_ID[id].name;
25
+ const lifecycle = agentLifecycle(id);
26
+ if (lifecycle.state === "active")
27
+ return undefined;
28
+ const since = lifecycle.since === null ? "" : ` since ${lifecycle.since}`;
29
+ const successor = lifecycle.supersededBy === null ? "" : ` Superseded by ${lifecycle.supersededBy}.`;
30
+ const note = lifecycle.note === null ? "" : ` ${lifecycle.note}`;
31
+ return `${name} is ${lifecycle.state}${since}.${successor}${note}`;
32
+ };
33
+ //# sourceMappingURL=agent-lifecycle.js.map
@@ -0,0 +1,41 @@
1
+ /**
2
+ * One workspace transaction for a configured-agent membership change.
3
+ *
4
+ * Membership is a set: a request that records `cursor` and then fails to
5
+ * realize its outputs must leave the set as it found it. Every step of the
6
+ * change therefore runs inside a single transaction, and the transaction only
7
+ * settles once the workspace actually reports the transition the request
8
+ * asked for. Both the post-transaction check and the failure vocabulary
9
+ * belong here — an application that supplied either could make the same
10
+ * membership change mean two different things.
11
+ *
12
+ * @experimental This API is unstable and may change without notice.
13
+ */
14
+ import * as Effect from "effect/Effect";
15
+ import type * as FileSystem from "effect/FileSystem";
16
+ import type * as Path from "effect/Path";
17
+ import { type PlannedJobStep } from "@agentxm/workspace-operations";
18
+ import { WorkspaceMutations } from "@agentxm/workspace-state";
19
+ import { WorkspaceTransactionScope } from "@agentxm/workspace-transactions";
20
+ /** What the workspace must report once the transition has settled. */
21
+ export type MembershipTransition = {
22
+ readonly kind: "add";
23
+ readonly agentIds: ReadonlyArray<string>;
24
+ } | {
25
+ readonly kind: "remove";
26
+ readonly agentIds: ReadonlyArray<string>;
27
+ };
28
+ interface AtomicMembershipStepsArgs<Requirements, Output> {
29
+ readonly steps: ReadonlyArray<PlannedJobStep<Requirements, Output>>;
30
+ /** The membership change the settled workspace is checked against. */
31
+ readonly transition: MembershipTransition;
32
+ }
33
+ /** The transaction scope and platform every atomic membership step joins. */
34
+ export type AtomicMembershipRequirements<Requirements> = Requirements | FileSystem.FileSystem | Path.Path | WorkspaceTransactionScope;
35
+ /**
36
+ * Keep plan-level preview and per-step results while applying every membership
37
+ * and artifact step through one workspace transaction.
38
+ */
39
+ export declare const makeAtomicMembershipSteps: <Requirements, Output>(args: AtomicMembershipStepsArgs<Requirements, Output>) => Effect.Effect<ReadonlyArray<PlannedJobStep<AtomicMembershipRequirements<Requirements>, Output>>, never, WorkspaceMutations>;
40
+ export {};
41
+ //# sourceMappingURL=atomic-membership.d.ts.map
@@ -0,0 +1,125 @@
1
+ /**
2
+ * One workspace transaction for a configured-agent membership change.
3
+ *
4
+ * Membership is a set: a request that records `cursor` and then fails to
5
+ * realize its outputs must leave the set as it found it. Every step of the
6
+ * change therefore runs inside a single transaction, and the transaction only
7
+ * settles once the workspace actually reports the transition the request
8
+ * asked for. Both the post-transaction check and the failure vocabulary
9
+ * belong here — an application that supplied either could make the same
10
+ * membership change mean two different things.
11
+ *
12
+ * @experimental This API is unstable and may change without notice.
13
+ */
14
+ import * as Effect from "effect/Effect";
15
+ import * as Ref from "effect/Ref";
16
+ import { StepFailure, } from "@agentxm/workspace-operations";
17
+ import { WorkspaceMutations } from "@agentxm/workspace-state";
18
+ import { WorkspaceTransactionScope, runWorkspaceTransaction, } from "@agentxm/workspace-transactions";
19
+ import { WorkspaceConfigurationFailed, configurationFailedToStepFailure, workspaceChangeFailedToStepFailure, } from "../errors.js";
20
+ const failedResult = (error, message = error.detail) => ({
21
+ result: "error",
22
+ message,
23
+ error,
24
+ });
25
+ const blockedResult = (message) => failedResult(new StepFailure({
26
+ category: "conflict",
27
+ detail: message,
28
+ }), message);
29
+ const rollbackResults = (executable, attempt, transactionError) => {
30
+ const actualFailureIndex = attempt.failedIndex ?? Math.max(0, attempt.results.length - 1);
31
+ const failedLabel = executable[actualFailureIndex]?.label ?? "atomic agent membership validation";
32
+ return executable.map((_, index) => {
33
+ if (index < actualFailureIndex) {
34
+ return blockedResult(`blocked: rolled back after ${failedLabel} failed`);
35
+ }
36
+ if (index > actualFailureIndex) {
37
+ return blockedResult(`blocked by ${failedLabel} failure`);
38
+ }
39
+ const attempted = attempt.results[index];
40
+ return attempted?.result === "error"
41
+ ? attempted
42
+ : failedResult(transactionError, transactionError.detail);
43
+ });
44
+ };
45
+ /**
46
+ * Read the settled membership back and refuse the transaction when it does
47
+ * not show the requested transition. A transition that wrote nothing and one
48
+ * that wrote half are the same answer to the caller: the change did not
49
+ * happen, and the transaction restores what it found.
50
+ */
51
+ const verifyTransition = (workspace, transition) => Effect.gen(function* () {
52
+ const configured = new Set(yield* workspace
53
+ .getConfiguredAgents()
54
+ .pipe(Effect.mapError(workspaceChangeFailedToStepFailure)));
55
+ const unmet = transition.kind === "add"
56
+ ? transition.agentIds.filter((agentId) => !configured.has(agentId))
57
+ : transition.agentIds.filter((agentId) => configured.has(agentId));
58
+ if (unmet.length === 0)
59
+ return;
60
+ return yield* configurationFailedToStepFailure(new WorkspaceConfigurationFailed({
61
+ category: "internal",
62
+ detail: transition.kind === "add"
63
+ ? `Agent membership transition did not configure: ${unmet.join(", ")}`
64
+ : `Agent membership transition did not remove: ${unmet.join(", ")}`,
65
+ }));
66
+ });
67
+ /**
68
+ * Keep plan-level preview and per-step results while applying every membership
69
+ * and artifact step through one workspace transaction.
70
+ */
71
+ export const makeAtomicMembershipSteps = (args) => Effect.gen(function* () {
72
+ const workspace = yield* WorkspaceMutations;
73
+ if (args.steps.some((step) => step.readiness === "error")) {
74
+ return args.steps.map((step) => step);
75
+ }
76
+ const executable = args.steps.filter((step) => step.readiness !== "error");
77
+ const attemptRef = yield* Ref.make({ results: [] });
78
+ const transition = runWorkspaceTransaction({
79
+ transition: Effect.gen(function* () {
80
+ const results = [];
81
+ for (const [index, step] of executable.entries()) {
82
+ const result = yield* step.run.pipe(Effect.catch((error) => Effect.succeed(failedResult(error))));
83
+ results.push(result);
84
+ yield* Ref.set(attemptRef, {
85
+ results: [...results],
86
+ ...(result.result === "error" ? { failedIndex: index } : {}),
87
+ });
88
+ if (result.result === "error") {
89
+ return yield* result.error;
90
+ }
91
+ }
92
+ return results;
93
+ }),
94
+ validate: () => verifyTransition(workspace, args.transition),
95
+ }).pipe(Effect.catch((transactionError) => Ref.get(attemptRef).pipe(Effect.map((attempt) => rollbackResults(executable, attempt, transactionError._tag === "StepFailure"
96
+ ? transactionError
97
+ : new StepFailure({
98
+ category: "internal",
99
+ detail: "The agent membership transition did not complete",
100
+ cause: transactionError,
101
+ }))))));
102
+ const sharedTransition = yield* Effect.cached(transition);
103
+ let resultIndex = 0;
104
+ // Every step now runs the shared transaction, so the transaction scope and
105
+ // platform join its requirements; the plan carries them to the boundary.
106
+ return args.steps.map((step) => {
107
+ if (step.readiness === "error")
108
+ return step;
109
+ const index = resultIndex;
110
+ resultIndex += 1;
111
+ return {
112
+ ...step,
113
+ run: sharedTransition.pipe(Effect.flatMap((results) => {
114
+ const result = results[index];
115
+ return result === undefined
116
+ ? new StepFailure({
117
+ category: "internal",
118
+ detail: `Atomic agent membership transition omitted step ${index + 1}`,
119
+ })
120
+ : Effect.succeed(result);
121
+ })),
122
+ };
123
+ });
124
+ });
125
+ //# sourceMappingURL=atomic-membership.js.map
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Configured-agent membership: which coding agents this workspace configures,
3
+ * and the change a request makes to that set.
4
+ *
5
+ * Membership is a set of decisions, not a list of writes. Adding names the
6
+ * agents a request actually configures — the ids it gave plus what detection
7
+ * found, minus the ones already configured and the ones whose vendor retired
8
+ * them unless the request named them itself. Removing names the agents that
9
+ * leave and the projection state the workspace must be reconciled to once
10
+ * they have. Either change settles atomically: the recorded set and the agent
11
+ * outputs realized for it move together or not at all.
12
+ *
13
+ * Realizing installed extensions for a new membership, and cleaning up the
14
+ * outputs a departing agent owned, are reconciliation work. The application
15
+ * plans those steps through the reconciliation feature and hands them to
16
+ * `previewOrApply` as ordinary plan steps, so this feature never depends on a
17
+ * peer feature and the whole change still settles as one closure.
18
+ *
19
+ * @experimental This API is unstable and may change without notice.
20
+ */
21
+ import * as Effect from "effect/Effect";
22
+ import type * as FileSystem from "effect/FileSystem";
23
+ import type * as Path from "effect/Path";
24
+ import * as Schema from "effect/Schema";
25
+ import { detectAgentsForScope } from "@agentxm/agent-integration";
26
+ import type { PerAgentType } from "@agentxm/extension-model/unstable/extensions/common";
27
+ import type { WorkspaceScope } from "@agentxm/extension-model/unstable/workspace-scope";
28
+ import { OperationJournal, ResolvePlanInteraction, type OperationResolution, type PlanExecution, type PlannedJobStep } from "@agentxm/workspace-operations";
29
+ import { ConfiguredAgentOutcomesProvider, WorkspaceMutations, type WorkspaceStateReadFailure } from "@agentxm/workspace-state";
30
+ import { FootprintRecorder, WorkspaceTransactionScope } from "@agentxm/workspace-transactions";
31
+ import { WorkspaceConfigurationFailed, type WorkspaceConfigurationExecutionFailure } from "../errors.js";
32
+ /** Every failure a membership request settles into before it is planned. */
33
+ export type ConfigureAgentsFailure = WorkspaceConfigurationFailed | WorkspaceStateReadFailure | Effect.Error<ReturnType<typeof detectAgentsForScope>>;
34
+ /** Every failure resolving a prepared membership change can surface. */
35
+ export type MembershipExecutionFailure = WorkspaceConfigurationExecutionFailure;
36
+ /**
37
+ * A request that changes nothing still has an answer: what it named and why
38
+ * the workspace already satisfies it.
39
+ */
40
+ export interface ConfiguredAgentsUnchanged {
41
+ readonly _tag: "Unchanged";
42
+ readonly reason: "already-configured" | "no-active-detected" | "already-absent";
43
+ readonly message: string;
44
+ /** Retired agents detection offered and did not configure, if any. */
45
+ readonly retiredDetected: ReadonlyArray<RetiredAgentNotice>;
46
+ }
47
+ /** A retired agent detection found, and why a person should know about it. */
48
+ export interface RetiredAgentNotice {
49
+ readonly agentId: string;
50
+ /** The vendor-lifecycle sentence, and that detection did not configure it. */
51
+ readonly detail: string;
52
+ }
53
+ export interface AddConfiguredAgentsRequest {
54
+ /** Agent ids the person named explicitly. */
55
+ readonly ids: ReadonlyArray<string>;
56
+ /** Also configure the agents detection finds for this workspace's scope. */
57
+ readonly detected: boolean;
58
+ /** The person accepted the vendor-lifecycle warnings this change carries. */
59
+ readonly acceptWarnings?: boolean;
60
+ }
61
+ export interface AddConfiguredAgentsCandidate {
62
+ readonly _tag: "AddConfiguredAgents";
63
+ /** The agents this change configures, in the order they were decided. */
64
+ readonly agentIds: ReadonlyArray<string>;
65
+ /** The membership the workspace holds once the change settles. */
66
+ readonly configuredAgents: ReadonlyArray<string>;
67
+ /**
68
+ * Retired agents detection offered. They are not configured by detection
69
+ * alone; naming one explicitly configures it and warns.
70
+ */
71
+ readonly retiredDetected: ReadonlyArray<RetiredAgentNotice>;
72
+ /** One sentence per configured agent whose vendor no longer maintains it. */
73
+ readonly lifecycleWarnings: ReadonlyArray<string>;
74
+ readonly acceptWarnings: boolean;
75
+ readonly scope: WorkspaceScope;
76
+ }
77
+ /**
78
+ * Settle which agents an add request configures.
79
+ *
80
+ * Explicitly named ids are validated first, so a typo is refused before
81
+ * detection runs. Detection contributes what it found minus the agents whose
82
+ * vendor retired them: a retired agent is a deliberate choice, never a
83
+ * consequence of having it installed.
84
+ */
85
+ export declare const prepareAddConfiguredAgents: (request: AddConfiguredAgentsRequest) => Effect.Effect<AddConfiguredAgentsCandidate | ConfiguredAgentsUnchanged, ConfigureAgentsFailure, WorkspaceMutations | FileSystem.FileSystem | Path.Path>;
86
+ /**
87
+ * Steps the application planned through the reconciliation feature, applied
88
+ * inside this change's closure so membership and realized outputs settle
89
+ * together.
90
+ */
91
+ export interface MembershipReconciliation<Requirements, Output> {
92
+ readonly steps: ReadonlyArray<PlannedJobStep<Requirements, Output>>;
93
+ }
94
+ /**
95
+ * The plan pipeline a membership change resolves through, plus the workspace
96
+ * transition its steps settle inside. `Requirements` carries whatever the
97
+ * reconciliation steps the application supplied still need.
98
+ */
99
+ export type MembershipExecutionRequirements<Requirements> = Requirements | ConfiguredAgentOutcomesProvider | FileSystem.FileSystem | FootprintRecorder | OperationJournal | Path.Path | ResolvePlanInteraction | WorkspaceMutations | WorkspaceTransactionScope;
100
+ /**
101
+ * Preview or apply a settled add. The membership writes and the supplied
102
+ * reconciliation steps run inside one workspace transaction, and the
103
+ * transaction only settles once the workspace reports the arriving agents as
104
+ * configured.
105
+ */
106
+ export declare const previewOrApplyAddConfiguredAgents: <MaterializeRequirements = never, Output = void>(candidate: AddConfiguredAgentsCandidate, execution: PlanExecution, reconciliation?: MembershipReconciliation<MaterializeRequirements, Output>) => Effect.Effect<OperationResolution<Output>, MembershipExecutionFailure, MembershipExecutionRequirements<MaterializeRequirements>>;
107
+ export interface RemoveConfiguredAgentsRequest {
108
+ readonly ids: ReadonlyArray<string>;
109
+ }
110
+ /** The projection state the workspace is reconciled to once the agents leave. */
111
+ export interface DepartingAgentReconciliation {
112
+ readonly desiredAgentIds: ReadonlySet<string>;
113
+ readonly expectedNames: Readonly<Record<PerAgentType, ReadonlySet<string>>>;
114
+ }
115
+ export interface RemoveConfiguredAgentsCandidate {
116
+ readonly _tag: "RemoveConfiguredAgents";
117
+ readonly agentIds: ReadonlyArray<string>;
118
+ /** The membership the workspace holds once the change settles. */
119
+ readonly configuredAgents: ReadonlyArray<string>;
120
+ readonly reconciliation: DepartingAgentReconciliation;
121
+ /** The workspace root removed artifacts are reported relative to. */
122
+ readonly baseDir: string;
123
+ readonly scope: WorkspaceScope;
124
+ }
125
+ /**
126
+ * Settle which agents a remove request takes out of membership, and the
127
+ * reconciliation state their outputs are cleaned up against.
128
+ *
129
+ * Removing every named agent when none of them is configured is a reported
130
+ * no-op; removing a mixture is a refusal, because the request described a
131
+ * workspace that does not exist. Cleaning up owned projections needs a
132
+ * complete desired graph — without one, AXM cannot tell its own output from
133
+ * a person's file, so it refuses rather than guess.
134
+ */
135
+ export declare const prepareRemoveConfiguredAgents: (request: RemoveConfiguredAgentsRequest) => Effect.Effect<RemoveConfiguredAgentsCandidate | ConfiguredAgentsUnchanged, ConfigureAgentsFailure, WorkspaceMutations>;
136
+ /**
137
+ * Preview or apply a settled removal. The cleanup steps the application
138
+ * planned run before the membership writes and inside the same transaction,
139
+ * so a cleanup that cannot complete leaves the agent configured.
140
+ */
141
+ export declare const previewOrApplyRemoveConfiguredAgents: <CleanupRequirements = never, Output = void>(candidate: RemoveConfiguredAgentsCandidate, execution: PlanExecution, reconciliation?: MembershipReconciliation<CleanupRequirements, Output>) => Effect.Effect<OperationResolution<Output>, MembershipExecutionFailure, MembershipExecutionRequirements<CleanupRequirements>>;
142
+ declare const ConfiguredAgentRowSchema: Schema.Struct<{
143
+ readonly id: Schema.String;
144
+ readonly name: Schema.String;
145
+ readonly configured: Schema.Boolean;
146
+ readonly detected: Schema.Boolean;
147
+ /** Instruction-projection health for a configured agent; `-` when not configured. */
148
+ readonly instructions: Schema.String;
149
+ /** Whether the vendor still maintains the agent: active, deprecated, retired. */
150
+ readonly lifecycle: Schema.String;
151
+ }>;
152
+ export type ConfiguredAgentRow = typeof ConfiguredAgentRowSchema.Type;
153
+ export declare const ConfiguredAgentInventorySchema: Schema.Struct<{
154
+ readonly items: Schema.$Array<Schema.Struct<{
155
+ readonly id: Schema.String;
156
+ readonly name: Schema.String;
157
+ readonly configured: Schema.Boolean;
158
+ readonly detected: Schema.Boolean;
159
+ /** Instruction-projection health for a configured agent; `-` when not configured. */
160
+ readonly instructions: Schema.String;
161
+ /** Whether the vendor still maintains the agent: active, deprecated, retired. */
162
+ readonly lifecycle: Schema.String;
163
+ }>>;
164
+ readonly configured: Schema.$Array<Schema.String>;
165
+ readonly detected: Schema.$Array<Schema.String>;
166
+ readonly available: Schema.$Array<Schema.String>;
167
+ readonly count: Schema.Number;
168
+ }>;
169
+ export type ConfiguredAgentInventory = typeof ConfiguredAgentInventorySchema.Type;
170
+ export interface ListConfiguredAgentsRequest {
171
+ /** Report only the agents detection found. */
172
+ readonly detected?: boolean;
173
+ /** Report every supported agent id, configured or not. */
174
+ readonly available?: boolean;
175
+ }
176
+ /**
177
+ * Report configured, detected, and available coding agents.
178
+ *
179
+ * The default view answers "what is in play here": the agents this workspace
180
+ * configures and the ones present on the machine. `universal` is materialized
181
+ * for every workspace and is never reported as a membership choice.
182
+ */
183
+ export declare const listConfiguredAgents: (request?: ListConfiguredAgentsRequest) => Effect.Effect<ConfiguredAgentInventory, ConfigureAgentsFailure, WorkspaceMutations | FileSystem.FileSystem | Path.Path>;
184
+ /** The configured-agent membership use case. */
185
+ export declare const ConfigureAgents: {
186
+ readonly add: {
187
+ readonly prepare: (request: AddConfiguredAgentsRequest) => Effect.Effect<AddConfiguredAgentsCandidate | ConfiguredAgentsUnchanged, ConfigureAgentsFailure, WorkspaceMutations | FileSystem.FileSystem | Path.Path>;
188
+ readonly previewOrApply: <MaterializeRequirements = never, Output = void>(candidate: AddConfiguredAgentsCandidate, execution: PlanExecution, reconciliation?: MembershipReconciliation<MaterializeRequirements, Output>) => Effect.Effect<OperationResolution<Output>, MembershipExecutionFailure, MembershipExecutionRequirements<MaterializeRequirements>>;
189
+ };
190
+ readonly remove: {
191
+ readonly prepare: (request: RemoveConfiguredAgentsRequest) => Effect.Effect<RemoveConfiguredAgentsCandidate | ConfiguredAgentsUnchanged, ConfigureAgentsFailure, WorkspaceMutations>;
192
+ readonly previewOrApply: <CleanupRequirements = never, Output = void>(candidate: RemoveConfiguredAgentsCandidate, execution: PlanExecution, reconciliation?: MembershipReconciliation<CleanupRequirements, Output>) => Effect.Effect<OperationResolution<Output>, MembershipExecutionFailure, MembershipExecutionRequirements<CleanupRequirements>>;
193
+ };
194
+ readonly list: (request?: ListConfiguredAgentsRequest) => Effect.Effect<ConfiguredAgentInventory, ConfigureAgentsFailure, WorkspaceMutations | FileSystem.FileSystem | Path.Path>;
195
+ };
196
+ export {};
197
+ //# sourceMappingURL=configure-agents.d.ts.map