agent-switchboard 0.3.11 → 0.4.1

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 (72) hide show
  1. package/dist/agents/claude-code.d.ts +2 -0
  2. package/dist/agents/claude-code.js +5 -5
  3. package/dist/agents/claude-code.js.map +1 -1
  4. package/dist/agents/codex.d.ts +6 -0
  5. package/dist/agents/codex.js +65 -2
  6. package/dist/agents/codex.js.map +1 -1
  7. package/dist/agents/cursor.d.ts +2 -0
  8. package/dist/agents/cursor.js +5 -3
  9. package/dist/agents/cursor.js.map +1 -1
  10. package/dist/agents/gemini.d.ts +2 -0
  11. package/dist/agents/gemini.js +23 -3
  12. package/dist/agents/gemini.js.map +1 -1
  13. package/dist/agents/json-utils.d.ts +5 -0
  14. package/dist/agents/json-utils.js +21 -0
  15. package/dist/agents/json-utils.js.map +1 -1
  16. package/dist/agents/opencode.d.ts +2 -0
  17. package/dist/agents/opencode.js +14 -6
  18. package/dist/agents/opencode.js.map +1 -1
  19. package/dist/agents/trae.d.ts +2 -0
  20. package/dist/agents/trae.js +5 -3
  21. package/dist/agents/trae.js.map +1 -1
  22. package/dist/commands/distribution.d.ts +2 -2
  23. package/dist/commands/distribution.js +4 -1
  24. package/dist/commands/distribution.js.map +1 -1
  25. package/dist/config/schemas.d.ts +683 -0
  26. package/dist/config/schemas.js +33 -0
  27. package/dist/config/schemas.js.map +1 -1
  28. package/dist/library/distribute-bundle.d.ts +13 -1
  29. package/dist/library/distribute-bundle.js +117 -36
  30. package/dist/library/distribute-bundle.js.map +1 -1
  31. package/dist/library/distribute.d.ts +16 -1
  32. package/dist/library/distribute.js +107 -34
  33. package/dist/library/distribute.js.map +1 -1
  34. package/dist/manifest/store.d.ts +53 -0
  35. package/dist/manifest/store.js +183 -0
  36. package/dist/manifest/store.js.map +1 -0
  37. package/dist/manifest/types.d.ts +52 -0
  38. package/dist/manifest/types.js +9 -0
  39. package/dist/manifest/types.js.map +1 -0
  40. package/dist/mcp/distribution.d.ts +5 -0
  41. package/dist/mcp/distribution.js +34 -1
  42. package/dist/mcp/distribution.js.map +1 -1
  43. package/dist/rules/block-merge.d.ts +24 -0
  44. package/dist/rules/block-merge.js +68 -0
  45. package/dist/rules/block-merge.js.map +1 -0
  46. package/dist/rules/distribution.d.ts +7 -0
  47. package/dist/rules/distribution.js +94 -8
  48. package/dist/rules/distribution.js.map +1 -1
  49. package/dist/skills/distribution.d.ts +5 -1
  50. package/dist/skills/distribution.js +9 -0
  51. package/dist/skills/distribution.js.map +1 -1
  52. package/dist/subagents/distribution.d.ts +2 -2
  53. package/dist/subagents/distribution.js +4 -1
  54. package/dist/subagents/distribution.js.map +1 -1
  55. package/dist/sync/command.js +58 -14
  56. package/dist/sync/command.js.map +1 -1
  57. package/dist/targets/builtin/claude-code.js +3 -1
  58. package/dist/targets/builtin/claude-code.js.map +1 -1
  59. package/dist/targets/builtin/codex.js +3 -1
  60. package/dist/targets/builtin/codex.js.map +1 -1
  61. package/dist/targets/builtin/cursor.js +3 -1
  62. package/dist/targets/builtin/cursor.js.map +1 -1
  63. package/dist/targets/builtin/gemini.js +1 -1
  64. package/dist/targets/builtin/gemini.js.map +1 -1
  65. package/dist/targets/builtin/opencode.js +1 -1
  66. package/dist/targets/builtin/opencode.js.map +1 -1
  67. package/dist/targets/builtin/trae.js +3 -1
  68. package/dist/targets/builtin/trae.js.map +1 -1
  69. package/dist/targets/types.d.ts +8 -1
  70. package/dist/targets/types.js.map +1 -1
  71. package/dist/util/cli.d.ts +1 -1
  72. package/package.json +1 -1
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Project distribution manifest I/O and helpers.
3
+ *
4
+ * The manifest lives at `<project>/.asb/state/distribution.json` and records
5
+ * which artifacts ASB has written, enabling manifest-driven cleanup.
6
+ */
7
+ import type { ManagedMcpEntry, ManifestEntry, ManifestSections, ProjectDistributionManifest, RulesManifestEntry } from './types.js';
8
+ export declare function resolveManifestPath(projectRoot: string): string;
9
+ export declare function loadManifest(projectRoot: string): ProjectDistributionManifest;
10
+ export declare function saveManifest(projectRoot: string, manifest: ProjectDistributionManifest): void;
11
+ export type LibraryManifestSection = 'skills' | 'commands' | 'agents';
12
+ export interface ManifestCleanupItem {
13
+ id: string;
14
+ entry: ManifestEntry;
15
+ }
16
+ export declare function recordLibraryEntry(manifest: ProjectDistributionManifest, section: LibraryManifestSection, id: string, entry: ManifestEntry): void;
17
+ export declare function removeLibraryEntry(manifest: ProjectDistributionManifest, section: LibraryManifestSection, id: string, targetId?: string): void;
18
+ export declare function recordMcpEntry(manifest: ProjectDistributionManifest, serverName: string, entry: ManagedMcpEntry): void;
19
+ /**
20
+ * Remove an MCP manifest entry by its composite key (as returned by
21
+ * `computeMcpCleanupSet`).
22
+ */
23
+ export declare function removeMcpEntry(manifest: ProjectDistributionManifest, compositeKey: string): void;
24
+ export declare function recordRulesEntry(manifest: ProjectDistributionManifest, filePathKey: string, entry: RulesManifestEntry): void;
25
+ export declare function removeRulesEntry(manifest: ProjectDistributionManifest, filePathKey: string): void;
26
+ /**
27
+ * Compute entries that were previously owned by ASB but are no longer in the
28
+ * current desired set. These are safe to clean up.
29
+ *
30
+ * Returns `ManifestCleanupItem[]` with the bare entry id and the full entry,
31
+ * so callers can resolve file paths and remove the manifest record.
32
+ */
33
+ export declare function computeLibraryCleanupSet(manifest: ProjectDistributionManifest, section: LibraryManifestSection, currentDesiredIds: ReadonlySet<string>, targetId?: string): ManifestCleanupItem[];
34
+ /**
35
+ * Compute MCP composite keys that were previously owned but are no longer enabled.
36
+ * Returns composite keys (serverName::targetId) for use with `removeMcpEntry`.
37
+ */
38
+ export declare function computeMcpCleanupSet(manifest: ProjectDistributionManifest, currentDesiredNames: ReadonlySet<string>, targetId?: string): string[];
39
+ /**
40
+ * Get the set of previously-owned MCP server names for a given target.
41
+ * Returns bare server names (not composite keys).
42
+ */
43
+ export declare function getOwnedMcpServers(manifest: ProjectDistributionManifest, targetId: string): Set<string>;
44
+ /**
45
+ * Get manifest entry for a library section item, if it exists.
46
+ * When targetId is provided, looks up the composite key directly.
47
+ * Without targetId, scans for the first entry matching the bare id.
48
+ */
49
+ export declare function getLibraryEntry(manifest: ProjectDistributionManifest, section: LibraryManifestSection, id: string, targetId?: string): ManifestEntry | undefined;
50
+ /**
51
+ * Resolve the effective sections record, ensuring it exists.
52
+ */
53
+ export declare function ensureSections(manifest: ProjectDistributionManifest): ManifestSections;
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Project distribution manifest I/O and helpers.
3
+ *
4
+ * The manifest lives at `<project>/.asb/state/distribution.json` and records
5
+ * which artifacts ASB has written, enabling manifest-driven cleanup.
6
+ */
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ const MANIFEST_DIR = '.asb/state';
10
+ const MANIFEST_FILENAME = 'distribution.json';
11
+ export function resolveManifestPath(projectRoot) {
12
+ return path.join(projectRoot, MANIFEST_DIR, MANIFEST_FILENAME);
13
+ }
14
+ function emptyManifest() {
15
+ return {
16
+ version: 1,
17
+ updatedAt: new Date().toISOString(),
18
+ sections: {},
19
+ };
20
+ }
21
+ export function loadManifest(projectRoot) {
22
+ const filePath = resolveManifestPath(projectRoot);
23
+ try {
24
+ if (!fs.existsSync(filePath))
25
+ return emptyManifest();
26
+ const content = fs.readFileSync(filePath, 'utf-8');
27
+ const parsed = JSON.parse(content);
28
+ if (parsed.version !== 1)
29
+ return emptyManifest();
30
+ return parsed;
31
+ }
32
+ catch {
33
+ return emptyManifest();
34
+ }
35
+ }
36
+ export function saveManifest(projectRoot, manifest) {
37
+ const filePath = resolveManifestPath(projectRoot);
38
+ const dir = path.dirname(filePath);
39
+ if (!fs.existsSync(dir)) {
40
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
41
+ }
42
+ manifest.updatedAt = new Date().toISOString();
43
+ fs.writeFileSync(filePath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf-8');
44
+ }
45
+ // ── Composite key helpers ──────────────────────────────────
46
+ const KEY_SEP = '::';
47
+ /** Build a manifest key that is unique per (id, targetId) pair. */
48
+ function manifestKey(id, targetId) {
49
+ return `${id}${KEY_SEP}${targetId}`;
50
+ }
51
+ /** Parse a composite manifest key back to id and targetId. */
52
+ function parseManifestKey(key) {
53
+ const sep = key.indexOf(KEY_SEP);
54
+ if (sep === -1)
55
+ return { id: key, targetId: '' };
56
+ return { id: key.slice(0, sep), targetId: key.slice(sep + KEY_SEP.length) };
57
+ }
58
+ export function recordLibraryEntry(manifest, section, id, entry) {
59
+ const sec = (manifest.sections[section] ?? {});
60
+ sec[manifestKey(id, entry.targetId)] = entry;
61
+ manifest.sections[section] = sec;
62
+ }
63
+ export function removeLibraryEntry(manifest, section, id, targetId) {
64
+ const sec = manifest.sections[section];
65
+ if (!sec)
66
+ return;
67
+ if (targetId) {
68
+ delete sec[manifestKey(id, targetId)];
69
+ }
70
+ else {
71
+ for (const key of Object.keys(sec)) {
72
+ if (parseManifestKey(key).id === id)
73
+ delete sec[key];
74
+ }
75
+ }
76
+ }
77
+ export function recordMcpEntry(manifest, serverName, entry) {
78
+ const sec = (manifest.sections.mcp ?? {});
79
+ sec[manifestKey(serverName, entry.targetId)] = entry;
80
+ manifest.sections.mcp = sec;
81
+ }
82
+ /**
83
+ * Remove an MCP manifest entry by its composite key (as returned by
84
+ * `computeMcpCleanupSet`).
85
+ */
86
+ export function removeMcpEntry(manifest, compositeKey) {
87
+ const sec = manifest.sections.mcp;
88
+ if (sec)
89
+ delete sec[compositeKey];
90
+ }
91
+ export function recordRulesEntry(manifest, filePathKey, entry) {
92
+ const sec = (manifest.sections.rules ?? {});
93
+ sec[filePathKey] = entry;
94
+ manifest.sections.rules = sec;
95
+ }
96
+ export function removeRulesEntry(manifest, filePathKey) {
97
+ const sec = manifest.sections.rules;
98
+ if (sec)
99
+ delete sec[filePathKey];
100
+ }
101
+ // ── Cleanup computation ────────────────────────────────────
102
+ /**
103
+ * Compute entries that were previously owned by ASB but are no longer in the
104
+ * current desired set. These are safe to clean up.
105
+ *
106
+ * Returns `ManifestCleanupItem[]` with the bare entry id and the full entry,
107
+ * so callers can resolve file paths and remove the manifest record.
108
+ */
109
+ export function computeLibraryCleanupSet(manifest, section, currentDesiredIds, targetId) {
110
+ const sec = manifest.sections[section];
111
+ if (!sec)
112
+ return [];
113
+ const toRemove = [];
114
+ for (const [key, entry] of Object.entries(sec)) {
115
+ if (targetId && entry.targetId !== targetId)
116
+ continue;
117
+ const { id } = parseManifestKey(key);
118
+ if (!currentDesiredIds.has(id)) {
119
+ toRemove.push({ id, entry });
120
+ }
121
+ }
122
+ return toRemove;
123
+ }
124
+ /**
125
+ * Compute MCP composite keys that were previously owned but are no longer enabled.
126
+ * Returns composite keys (serverName::targetId) for use with `removeMcpEntry`.
127
+ */
128
+ export function computeMcpCleanupSet(manifest, currentDesiredNames, targetId) {
129
+ const sec = manifest.sections.mcp;
130
+ if (!sec)
131
+ return [];
132
+ const toRemove = [];
133
+ for (const [key, entry] of Object.entries(sec)) {
134
+ if (targetId && entry.targetId !== targetId)
135
+ continue;
136
+ const { id: serverName } = parseManifestKey(key);
137
+ if (!currentDesiredNames.has(serverName)) {
138
+ toRemove.push(key);
139
+ }
140
+ }
141
+ return toRemove;
142
+ }
143
+ /**
144
+ * Get the set of previously-owned MCP server names for a given target.
145
+ * Returns bare server names (not composite keys).
146
+ */
147
+ export function getOwnedMcpServers(manifest, targetId) {
148
+ const sec = manifest.sections.mcp;
149
+ if (!sec)
150
+ return new Set();
151
+ const owned = new Set();
152
+ for (const [key, entry] of Object.entries(sec)) {
153
+ if (entry.targetId === targetId) {
154
+ owned.add(parseManifestKey(key).id);
155
+ }
156
+ }
157
+ return owned;
158
+ }
159
+ /**
160
+ * Get manifest entry for a library section item, if it exists.
161
+ * When targetId is provided, looks up the composite key directly.
162
+ * Without targetId, scans for the first entry matching the bare id.
163
+ */
164
+ export function getLibraryEntry(manifest, section, id, targetId) {
165
+ const sec = manifest.sections[section];
166
+ if (!sec)
167
+ return undefined;
168
+ if (targetId) {
169
+ return sec[manifestKey(id, targetId)];
170
+ }
171
+ for (const [key, entry] of Object.entries(sec)) {
172
+ if (parseManifestKey(key).id === id)
173
+ return entry;
174
+ }
175
+ return undefined;
176
+ }
177
+ /**
178
+ * Resolve the effective sections record, ensuring it exists.
179
+ */
180
+ export function ensureSections(manifest) {
181
+ return manifest.sections;
182
+ }
183
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/manifest/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Project distribution manifest types.
3
+ *
4
+ * The manifest tracks which artifacts ASB has written to a project directory,
5
+ * enabling safe cleanup (only remove ASB-owned items) and conflict detection
6
+ * (don't overwrite project-native content).
7
+ */
8
+ /** An artifact ASB has distributed (file or bundle directory). */
9
+ export interface ManifestEntry {
10
+ /** Path relative to project root (e.g. ".claude/skills/my-skill") */
11
+ relativePath: string;
12
+ /** Which target app wrote this (e.g. "claude-code", "cursor", "agents") */
13
+ targetId: string;
14
+ /** SHA-256 hash of last-written content */
15
+ hash: string;
16
+ updatedAt: string;
17
+ }
18
+ /** An MCP server key ASB has written into a target config file. */
19
+ export interface ManagedMcpEntry {
20
+ /** Config file path relative to project root (e.g. ".mcp.json") */
21
+ relativePath: string;
22
+ /** Target app that owns this server key */
23
+ targetId: string;
24
+ /** Actual key written into mcpServers (after sanitize) */
25
+ serverKey: string;
26
+ updatedAt: string;
27
+ }
28
+ /** A rules block ASB has injected into a shared or dedicated file. */
29
+ export interface RulesManifestEntry {
30
+ /** File path relative to project root */
31
+ relativePath: string;
32
+ /** "block" = shared file with markers, "full" = dedicated ASB file */
33
+ mode: 'block' | 'full';
34
+ /** Which target apps share this physical file */
35
+ targetIds: string[];
36
+ /** SHA-256 of last-written ASB rules content */
37
+ hash: string;
38
+ updatedAt: string;
39
+ }
40
+ export type ManifestSectionKey = 'skills' | 'commands' | 'agents' | 'mcp' | 'rules';
41
+ export interface ManifestSections {
42
+ skills?: Record<string, ManifestEntry>;
43
+ commands?: Record<string, ManifestEntry>;
44
+ agents?: Record<string, ManifestEntry>;
45
+ mcp?: Record<string, ManagedMcpEntry>;
46
+ rules?: Record<string, RulesManifestEntry>;
47
+ }
48
+ export interface ProjectDistributionManifest {
49
+ version: 1;
50
+ updatedAt: string;
51
+ sections: ManifestSections;
52
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Project distribution manifest types.
3
+ *
4
+ * The manifest tracks which artifacts ASB has written to a project directory,
5
+ * enabling safe cleanup (only remove ASB-owned items) and conflict detection
6
+ * (don't overwrite project-native content).
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/manifest/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -1,4 +1,5 @@
1
1
  import type { ConfigScope } from '../config/scope.js';
2
+ import type { ProjectDistributionManifest } from '../manifest/types.js';
2
3
  export interface McpDistributionResult {
3
4
  application: string;
4
5
  filePath: string;
@@ -9,5 +10,9 @@ export interface McpDistributionResult {
9
10
  export interface DistributeMcpOptions {
10
11
  useSpinner?: boolean;
11
12
  assumeInstalled?: ReadonlySet<string>;
13
+ /** Project distribution manifest for managed merge (project scope only) */
14
+ manifest?: ProjectDistributionManifest;
15
+ /** Project distribution mode */
16
+ projectMode?: 'managed' | 'exclusive' | 'none';
12
17
  }
13
18
  export declare function distributeMcp(scope?: ConfigScope, enabledServerNames?: string[], options?: DistributeMcpOptions): Promise<McpDistributionResult[]>;
@@ -1,4 +1,5 @@
1
1
  import fs from 'node:fs';
2
+ import path from 'node:path';
2
3
  import chalk from 'chalk';
3
4
  import ora from 'ora';
4
5
  import { resolveScopedSectionConfig } from '../config/application-config.js';
@@ -6,6 +7,7 @@ import { loadMcpConfigWithPlugins } from '../config/mcp-config.js';
6
7
  import { scopeToLayerOptions } from '../config/scope.js';
7
8
  import { loadSwitchboardConfig } from '../config/switchboard-config.js';
8
9
  import { loadMcpEnabledState } from '../library/state.js';
10
+ import { computeMcpCleanupSet, getOwnedMcpServers, recordMcpEntry, removeMcpEntry, } from '../manifest/store.js';
9
11
  import { initTargets } from '../targets/init.js';
10
12
  import { getTargetById } from '../targets/registry.js';
11
13
  import { shortenPath } from '../util/cli.js';
@@ -79,7 +81,38 @@ export async function distributeMcp(scope, enabledServerNames, options) {
79
81
  if (scope?.project && mcpHandler.applyProjectConfig) {
80
82
  const projectPath = mcpHandler.projectConfigPath?.(scope.project) ?? 'project config';
81
83
  const before = readFileSafe(projectPath);
82
- mcpHandler.applyProjectConfig(scope.project, configToApply);
84
+ // Build managed merge options if manifest is provided
85
+ const manifest = options?.manifest;
86
+ const isManaged = manifest && (options?.projectMode ?? 'exclusive') === 'managed';
87
+ const sanitize = mcpHandler.sanitizeServerName;
88
+ const ownedServers = isManaged ? getOwnedMcpServers(manifest, agentId) : new Set();
89
+ const managedOpts = isManaged
90
+ ? { previouslyOwned: ownedServers }
91
+ : undefined;
92
+ // Skip silently if no servers to apply and nothing to clean up
93
+ if (Object.keys(configToApply.mcpServers).length === 0 && ownedServers.size === 0) {
94
+ continue;
95
+ }
96
+ mcpHandler.applyProjectConfig(scope.project, configToApply, managedOpts);
97
+ // Record owned servers in manifest (using sanitized names to match on-disk keys)
98
+ if (isManaged && manifest) {
99
+ const timestamp = new Date().toISOString();
100
+ for (const serverName of Object.keys(configToApply.mcpServers)) {
101
+ const manifestName = sanitize ? sanitize(serverName) : serverName;
102
+ recordMcpEntry(manifest, manifestName, {
103
+ relativePath: path.relative(path.resolve(scope.project), projectPath),
104
+ targetId: agentId,
105
+ serverKey: manifestName,
106
+ updatedAt: timestamp,
107
+ });
108
+ }
109
+ // Remove no-longer-enabled servers from manifest
110
+ const currentDesired = new Set(Object.keys(configToApply.mcpServers).map((n) => (sanitize ? sanitize(n) : n)));
111
+ const toRemove = computeMcpCleanupSet(manifest, currentDesired, agentId);
112
+ for (const name of toRemove) {
113
+ removeMcpEntry(manifest, name);
114
+ }
115
+ }
83
116
  const after = readFileSafe(projectPath);
84
117
  const changed = before !== after;
85
118
  persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(projectPath))}`);
@@ -1 +1 @@
1
- {"version":3,"file":"distribution.js","sourceRoot":"","sources":["../../src/mcp/distribution.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"distribution.js","sourceRoot":"","sources":["../../src/mcp/distribution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Block merge for shared rules files (CLAUDE.md, AGENTS.md).
3
+ *
4
+ * In managed project mode, ASB content is wrapped in markers so that
5
+ * project-native content is preserved. If markers already exist, only
6
+ * the block between them is replaced.
7
+ */
8
+ /**
9
+ * Merge ASB rules content into an existing file, preserving non-ASB content.
10
+ *
11
+ * - If markers exist: replace content between markers.
12
+ * - If no markers: insert block according to `placement`.
13
+ * - If `asbContent` is empty: remove the block entirely.
14
+ */
15
+ export declare function mergeRulesBlock(existing: string, asbContent: string, placement?: 'prepend' | 'append'): string;
16
+ /**
17
+ * Remove ASB markers and their content from a file, preserving the rest.
18
+ */
19
+ export declare function removeRulesBlock(content: string): string;
20
+ /**
21
+ * Check if a rules target file is a dedicated ASB file (safe for full replace)
22
+ * vs a shared file (needs block merge).
23
+ */
24
+ export declare function isDedicatedAsbRulesFile(filePath: string): boolean;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Block merge for shared rules files (CLAUDE.md, AGENTS.md).
3
+ *
4
+ * In managed project mode, ASB content is wrapped in markers so that
5
+ * project-native content is preserved. If markers already exist, only
6
+ * the block between them is replaced.
7
+ */
8
+ const ASB_BLOCK_START = '<!-- asb:rules:start -->';
9
+ const ASB_BLOCK_END = '<!-- asb:rules:end -->';
10
+ /**
11
+ * Merge ASB rules content into an existing file, preserving non-ASB content.
12
+ *
13
+ * - If markers exist: replace content between markers.
14
+ * - If no markers: insert block according to `placement`.
15
+ * - If `asbContent` is empty: remove the block entirely.
16
+ */
17
+ export function mergeRulesBlock(existing, asbContent, placement = 'prepend') {
18
+ const startIdx = existing.indexOf(ASB_BLOCK_START);
19
+ const endIdx = existing.indexOf(ASB_BLOCK_END);
20
+ if (asbContent.length === 0) {
21
+ // Remove existing block if present
22
+ if (startIdx !== -1 && endIdx !== -1) {
23
+ return removeRulesBlock(existing);
24
+ }
25
+ return existing;
26
+ }
27
+ const block = `${ASB_BLOCK_START}\n${asbContent.trimEnd()}\n${ASB_BLOCK_END}`;
28
+ if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
29
+ // Replace existing block
30
+ const before = existing.slice(0, startIdx);
31
+ const after = existing.slice(endIdx + ASB_BLOCK_END.length);
32
+ return `${before}${block}${after}`;
33
+ }
34
+ // Insert new block
35
+ const trimmed = existing.trimEnd();
36
+ if (placement === 'prepend') {
37
+ if (trimmed.length === 0)
38
+ return `${block}\n`;
39
+ return `${block}\n\n${trimmed}\n`;
40
+ }
41
+ // append
42
+ if (trimmed.length === 0)
43
+ return `${block}\n`;
44
+ return `${trimmed}\n\n${block}\n`;
45
+ }
46
+ /**
47
+ * Remove ASB markers and their content from a file, preserving the rest.
48
+ */
49
+ export function removeRulesBlock(content) {
50
+ const startIdx = content.indexOf(ASB_BLOCK_START);
51
+ const endIdx = content.indexOf(ASB_BLOCK_END);
52
+ if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx)
53
+ return content;
54
+ const before = content.slice(0, startIdx);
55
+ const after = content.slice(endIdx + ASB_BLOCK_END.length);
56
+ // Clean up extra whitespace left by removal
57
+ const result = (before + after).replace(/\n{3,}/g, '\n\n').trim();
58
+ return result.length > 0 ? `${result}\n` : '';
59
+ }
60
+ /**
61
+ * Check if a rules target file is a dedicated ASB file (safe for full replace)
62
+ * vs a shared file (needs block merge).
63
+ */
64
+ export function isDedicatedAsbRulesFile(filePath) {
65
+ const basename = filePath.split('/').pop() ?? '';
66
+ return basename.startsWith('asb-rules');
67
+ }
68
+ //# sourceMappingURL=block-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block-merge.js","sourceRoot":"","sources":["../../src/rules/block-merge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,eAAe,GAAG,0BAA0B,CAAC;AACnD,MAAM,aAAa,GAAG,wBAAwB,CAAC;AAE/C;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,UAAkB,EAClB,YAAkC,SAAS;IAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,mCAAmC;QACnC,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YACrC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,eAAe,KAAK,UAAU,CAAC,OAAO,EAAE,KAAK,aAAa,EAAE,CAAC;IAE9E,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC1D,yBAAyB;QACzB,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QAC5D,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,EAAE,CAAC;IACrC,CAAC;IAED,mBAAmB;IACnB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;IACnC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,GAAG,KAAK,IAAI,CAAC;QAC9C,OAAO,GAAG,KAAK,OAAO,OAAO,IAAI,CAAC;IACpC,CAAC;IACD,SAAS;IACT,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,KAAK,IAAI,CAAC;IAC9C,OAAO,GAAG,OAAO,OAAO,KAAK,IAAI,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,IAAI,QAAQ;QAAE,OAAO,OAAO,CAAC;IAE3E,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAE3D,4CAA4C;IAC5C,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAClE,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IACjD,OAAO,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAC1C,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { ConfigScope } from '../config/scope.js';
2
+ import type { ProjectDistributionManifest } from '../manifest/types.js';
2
3
  import type { ComposedRules } from './composer.js';
3
4
  export type DistributionStatus = 'written' | 'skipped' | 'error' | 'deleted';
4
5
  export interface DistributionResult {
@@ -16,6 +17,12 @@ interface DistributionOptions {
16
17
  force?: boolean;
17
18
  activeAppIds?: string[];
18
19
  assumeInstalled?: ReadonlySet<string>;
20
+ /** Project distribution manifest for managed mode */
21
+ manifest?: ProjectDistributionManifest;
22
+ /** Project distribution mode */
23
+ projectMode?: 'managed' | 'exclusive' | 'none';
24
+ /** Rules placement in shared files */
25
+ rulesPlacement?: 'prepend' | 'append';
19
26
  }
20
27
  export declare function distributeRules(options?: DistributionOptions, scope?: ConfigScope): DistributionOutcome;
21
28
  export declare function listUnsupportedAgents(): string[];