@agentxm/extension-model 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { PER_AGENT_EXTENSION_TYPES } from "../extensions/common.js";
7
7
  import { AGENTS } from "./catalog.js";
8
- import { CONFIGURABLE_AGENT_IDS } from "./identity.js";
8
+ import { isConfigurableAgentId } from "./identity.js";
9
9
  import { LEAF_EXTENSION_TYPES } from "../extension-types/schema.js";
10
10
  import { SUPPORTED_AXM_SUPPORT, } from "./schema.js";
11
11
  import {} from "../extensions/common.js";
@@ -43,8 +43,6 @@ const capabilityForType = (agent, type) => {
43
43
  return agent.capabilities[type];
44
44
  return undefined;
45
45
  };
46
- const configurableAgentIds = new Set(CONFIGURABLE_AGENT_IDS);
47
- const isConfigurableAgentId = (id) => configurableAgentIds.has(id);
48
46
  const deriveAgentId = (agent) => {
49
47
  if (isConfigurableAgentId(agent.id))
50
48
  return agent.id;
@@ -5,6 +5,8 @@ export declare const CONFIGURABLE_AGENT_IDS: readonly ["adal", "aider-desk", "am
5
5
  /** @experimental This API is unstable and may change without notice. */
6
6
  export type ConfigurableAgentId = (typeof CONFIGURABLE_AGENT_IDS)[number];
7
7
  /** @experimental This API is unstable and may change without notice. */
8
+ export declare const isConfigurableAgentId: (id: string) => id is ConfigurableAgentId;
9
+ /** @experimental This API is unstable and may change without notice. */
8
10
  export declare const HOSTED_AGENT_IDS: readonly ["chatgpt", "claude-ai", "cowork", "gemini-app"];
9
11
  /** @experimental This API is unstable and may change without notice. */
10
12
  export type HostedAgentId = (typeof HOSTED_AGENT_IDS)[number];
@@ -65,6 +65,9 @@ export const CONFIGURABLE_AGENT_IDS = [
65
65
  "zed",
66
66
  "zenflow",
67
67
  ];
68
+ const configurableAgentIdSet = new Set(CONFIGURABLE_AGENT_IDS);
69
+ /** @experimental This API is unstable and may change without notice. */
70
+ export const isConfigurableAgentId = (id) => configurableAgentIdSet.has(id);
68
71
  /** @experimental This API is unstable and may change without notice. */
69
72
  export const HOSTED_AGENT_IDS = ["chatgpt", "claude-ai", "cowork", "gemini-app"];
70
73
  /** @experimental This API is unstable and may change without notice. */
@@ -11,6 +11,6 @@ export { STANDARDS } from "../extension-types/standards.js";
11
11
  export { CAPABILITY_VERIFICATION_BUDGET_DAYS, capabilityVerificationAgeReport, type AgentCapabilitySlot, type CapabilityVerificationAge, } from "./verification.js";
12
12
  export { agentCapabilityStatus, agentSupportsType, axmIntegrationStatus, canonicalCoverage, deriveAgentDescriptor, deriveSkillConvention, deriveHookPortability, getSupportedAgentsForExtension, getSupportedAgentsForExtensionType, getSupportedAgentsForExtensionTypes, getSupportedExtensionTypesForAgent, isCapabilitySupported, isLeafExtensionType, listCapabilities, installable, toNativeAgent, type AgentCapabilityStatus, type AxmIntegrationStatus, type CapabilityListing, type ExtensionCompatibilityInput, type HookDecisionKind, type HookDecisionRequirement, type HookInstallabilityVerdict, type HookInstallBinding, type HookPortabilityRequirement, type HookPortabilityVerdict, type NativeAgent, type NativeAgentCapabilities, } from "./derive.js";
13
13
  export { AGENTS, AGENTS_BY_ID, CONFIGURABLE_AGENTS_BY_ID, HOSTED_AGENTS_BY_ID } from "./catalog.js";
14
- export { AGENT_IDS, AgentIdSchema, CONFIGURABLE_AGENT_IDS, HOSTED_AGENT_IDS, type AgentId, type ConfigurableAgentId, type HostedAgentId, } from "./identity.js";
14
+ export { AGENT_IDS, AgentIdSchema, CONFIGURABLE_AGENT_IDS, HOSTED_AGENT_IDS, isConfigurableAgentId, type AgentId, type ConfigurableAgentId, type HostedAgentId, } from "./identity.js";
15
15
  export { agentById } from "./lookup.js";
16
16
  //# sourceMappingURL=index.d.ts.map
@@ -11,6 +11,6 @@ export { STANDARDS } from "../extension-types/standards.js";
11
11
  export { CAPABILITY_VERIFICATION_BUDGET_DAYS, capabilityVerificationAgeReport, } from "./verification.js";
12
12
  export { agentCapabilityStatus, agentSupportsType, axmIntegrationStatus, canonicalCoverage, deriveAgentDescriptor, deriveSkillConvention, deriveHookPortability, getSupportedAgentsForExtension, getSupportedAgentsForExtensionType, getSupportedAgentsForExtensionTypes, getSupportedExtensionTypesForAgent, isCapabilitySupported, isLeafExtensionType, listCapabilities, installable, toNativeAgent, } from "./derive.js";
13
13
  export { AGENTS, AGENTS_BY_ID, CONFIGURABLE_AGENTS_BY_ID, HOSTED_AGENTS_BY_ID } from "./catalog.js";
14
- export { AGENT_IDS, AgentIdSchema, CONFIGURABLE_AGENT_IDS, HOSTED_AGENT_IDS, } from "./identity.js";
14
+ export { AGENT_IDS, AgentIdSchema, CONFIGURABLE_AGENT_IDS, HOSTED_AGENT_IDS, isConfigurableAgentId, } from "./identity.js";
15
15
  export { agentById } from "./lookup.js";
16
16
  //# sourceMappingURL=index.js.map
@@ -6,28 +6,14 @@
6
6
  * @experimental This API is unstable and may change without notice.
7
7
  * @packageDocumentation
8
8
  */
9
- import { type AgentId, type AgentRegistry } from "./types.js";
9
+ import type { AgentRegistry } from "./types.js";
10
10
  /**
11
- * Complete registry of all known AI coding agents.
11
+ * Derived descriptors for all known AI coding agents, including the synthetic universal target.
12
12
  *
13
13
  * Keys are agent IDs, values are full descriptor objects.
14
14
  * Paths are pre-expanded at module initialization.
15
15
  *
16
16
  * @experimental This API is unstable and may change without notice.
17
17
  */
18
- export declare const AGENTS: AgentRegistry;
19
- /**
20
- * Get all registered agent IDs.
21
- *
22
- * @returns Array of all agent identifiers
23
- *
24
- * @example
25
- * ```typescript
26
- * const ids = getAgentIds();
27
- * // ["adal", "amp", "antigravity", "augment", "claude-code", ...]
28
- * ```
29
- *
30
- * @experimental This API is unstable and may change without notice.
31
- */
32
- export declare const getAgentIds: () => ReadonlyArray<AgentId>;
18
+ export declare const AGENT_DESCRIPTORS: AgentRegistry;
33
19
  //# sourceMappingURL=registry.d.ts.map
@@ -10,7 +10,6 @@ import * as Record from "effect/Record";
10
10
  import { CONFIGURABLE_AGENTS_BY_ID } from "../agent-capabilities/catalog.js";
11
11
  import { deriveAgentDescriptor } from "../agent-capabilities/derive.js";
12
12
  import { UNIVERSAL_SKILLS_DIR } from "../extensions/universal-skills-dir.js";
13
- import { AGENT_IDS } from "./types.js";
14
13
  const UNIVERSAL_AGENT_DESCRIPTOR = {
15
14
  id: "universal",
16
15
  name: "Universal",
@@ -22,29 +21,15 @@ const UNIVERSAL_AGENT_DESCRIPTOR = {
22
21
  detection: { project: { markers: [] }, user: { markers: [] } },
23
22
  };
24
23
  /**
25
- * Complete registry of all known AI coding agents.
24
+ * Derived descriptors for all known AI coding agents, including the synthetic universal target.
26
25
  *
27
26
  * Keys are agent IDs, values are full descriptor objects.
28
27
  * Paths are pre-expanded at module initialization.
29
28
  *
30
29
  * @experimental This API is unstable and may change without notice.
31
30
  */
32
- export const AGENTS = {
31
+ export const AGENT_DESCRIPTORS = {
33
32
  ...Record.map(CONFIGURABLE_AGENTS_BY_ID, deriveAgentDescriptor),
34
33
  universal: UNIVERSAL_AGENT_DESCRIPTOR,
35
34
  };
36
- /**
37
- * Get all registered agent IDs.
38
- *
39
- * @returns Array of all agent identifiers
40
- *
41
- * @example
42
- * ```typescript
43
- * const ids = getAgentIds();
44
- * // ["adal", "amp", "antigravity", "augment", "claude-code", ...]
45
- * ```
46
- *
47
- * @experimental This API is unstable and may change without notice.
48
- */
49
- export const getAgentIds = () => AGENT_IDS;
50
35
  //# sourceMappingURL=registry.js.map
@@ -74,12 +74,10 @@ export interface AgentDetectionDescriptor {
74
74
  }
75
75
  /** @experimental This API is unstable and may change without notice. */
76
76
  export { CONFIGURABLE_AGENT_IDS, type ConfigurableAgentId };
77
+ /** Configurable agents plus the synthetic universal materialization target. @experimental */
78
+ export declare const MATERIALIZATION_TARGET_IDS: readonly ["adal", "aider-desk", "amp", "antigravity", "antigravity-cli", "augment", "claude-code", "cline", "codearts-agent", "codebuddy", "codemaker", "codestudio", "codex", "command-code", "continue", "cortex", "crush", "cursor", "deepagents", "devin", "dexto", "droid", "firebender", "forgecode", "gemini-cli", "github-copilot-cli", "goose", "grok-cli", "hermes", "ibm-bob", "iflow-cli", "junie", "lingma", "kilo", "kimi-cli", "kiro-cli", "kode", "mcpjam", "minimax-code", "mistral-vibe", "mux", "neovate", "openclaw", "opencode", "openhands", "ona", "pi", "pochi", "qoder", "qoder-cn", "qwen-code", "replit", "roo", "rovodev", "tabnine-cli", "trae-cn", "trae", "warp", "windsurf", "zencoder", "zed", "zenflow", "universal"];
77
79
  /** @experimental This API is unstable and may change without notice. */
78
- export declare const AGENT_IDS: readonly ["adal", "aider-desk", "amp", "antigravity", "antigravity-cli", "augment", "claude-code", "cline", "codearts-agent", "codebuddy", "codemaker", "codestudio", "codex", "command-code", "continue", "cortex", "crush", "cursor", "deepagents", "devin", "dexto", "droid", "firebender", "forgecode", "gemini-cli", "github-copilot-cli", "goose", "grok-cli", "hermes", "ibm-bob", "iflow-cli", "junie", "lingma", "kilo", "kimi-cli", "kiro-cli", "kode", "mcpjam", "minimax-code", "mistral-vibe", "mux", "neovate", "openclaw", "opencode", "openhands", "ona", "pi", "pochi", "qoder", "qoder-cn", "qwen-code", "replit", "roo", "rovodev", "tabnine-cli", "trae-cn", "trae", "warp", "windsurf", "zencoder", "zed", "zenflow", "universal"];
79
- /** @experimental This API is unstable and may change without notice. */
80
- export type AgentId = (typeof AGENT_IDS)[number];
81
- /** @experimental This API is unstable and may change without notice. */
82
- export declare const isConfigurableAgentId: (id: AgentId) => id is ConfigurableAgentId;
80
+ export type MaterializationTargetId = (typeof MATERIALIZATION_TARGET_IDS)[number];
83
81
  /**
84
82
  * Configuration for an AI coding agent.
85
83
  *
@@ -87,7 +85,7 @@ export declare const isConfigurableAgentId: (id: AgentId) => id is ConfigurableA
87
85
  */
88
86
  export interface AgentDescriptor {
89
87
  /** Unique identifier (e.g., "claude-code") */
90
- readonly id: AgentId;
88
+ readonly id: MaterializationTargetId;
91
89
  /** Human-readable display name (e.g., "Claude Code") */
92
90
  readonly name: string;
93
91
  /**
@@ -122,5 +120,5 @@ export interface AgentDescriptor {
122
120
  *
123
121
  * @experimental This API is unstable and may change without notice.
124
122
  */
125
- export type AgentRegistry = Record.ReadonlyRecord<AgentId, AgentDescriptor>;
123
+ export type AgentRegistry = Record.ReadonlyRecord<MaterializationTargetId, AgentDescriptor>;
126
124
  //# sourceMappingURL=types.d.ts.map
@@ -10,8 +10,6 @@ import { CONFIGURABLE_AGENT_IDS, } from "../agent-capabilities/identity.js";
10
10
  // -----------------------------------------------------------------------------
11
11
  /** @experimental This API is unstable and may change without notice. */
12
12
  export { CONFIGURABLE_AGENT_IDS };
13
- /** @experimental This API is unstable and may change without notice. */
14
- export const AGENT_IDS = [...CONFIGURABLE_AGENT_IDS, "universal"];
15
- /** @experimental This API is unstable and may change without notice. */
16
- export const isConfigurableAgentId = (id) => id !== "universal";
13
+ /** Configurable agents plus the synthetic universal materialization target. @experimental */
14
+ export const MATERIALIZATION_TARGET_IDS = [...CONFIGURABLE_AGENT_IDS, "universal"];
17
15
  //# sourceMappingURL=types.js.map
@@ -7,15 +7,17 @@
7
7
  * @experimental This API is unstable and may change without notice.
8
8
  */
9
9
  /**
10
- * Expand a glob pattern against a list of names.
10
+ * Match one extension name against a pattern.
11
11
  *
12
12
  * Only `*` wildcards are supported. All other characters (including `?`, `[`, `]`)
13
13
  * are treated as literals. Matching is case-sensitive.
14
14
  *
15
15
  * @param pattern - The pattern to match (may contain `*`)
16
- * @param names - Available names to match against
17
- * @returns Matching names in their original order
16
+ * @param name - The name to check
17
+ * @returns Whether the complete name matches
18
18
  */
19
+ export declare const matchesPattern: (pattern: string, name: string) => boolean;
20
+ /** Expand a glob pattern against names, preserving their original order. */
19
21
  export declare const expandGlob: (pattern: string, names: ReadonlyArray<string>) => ReadonlyArray<string>;
20
22
  /**
21
23
  * Expand multiple glob patterns against a list of extension names.
@@ -7,48 +7,47 @@
7
7
  * @experimental This API is unstable and may change without notice.
8
8
  */
9
9
  /**
10
- * Expand a glob pattern against a list of names.
10
+ * Match one extension name against a pattern.
11
11
  *
12
12
  * Only `*` wildcards are supported. All other characters (including `?`, `[`, `]`)
13
13
  * are treated as literals. Matching is case-sensitive.
14
14
  *
15
15
  * @param pattern - The pattern to match (may contain `*`)
16
- * @param names - Available names to match against
17
- * @returns Matching names in their original order
16
+ * @param name - The name to check
17
+ * @returns Whether the complete name matches
18
18
  */
19
- export const expandGlob = (pattern, names) => {
20
- const matches = (name) => {
21
- let patternIndex = 0;
22
- let nameIndex = 0;
23
- let wildcardIndex = -1;
24
- let wildcardNameIndex = 0;
25
- while (nameIndex < name.length) {
26
- const token = pattern[patternIndex];
27
- if (token !== undefined && token !== "*" && token === name[nameIndex]) {
28
- patternIndex += 1;
29
- nameIndex += 1;
30
- }
31
- else if (token === "*") {
32
- wildcardIndex = patternIndex;
33
- wildcardNameIndex = nameIndex;
34
- patternIndex += 1;
35
- }
36
- else if (wildcardIndex >= 0) {
37
- patternIndex = wildcardIndex + 1;
38
- wildcardNameIndex += 1;
39
- nameIndex = wildcardNameIndex;
40
- }
41
- else {
42
- return false;
43
- }
19
+ export const matchesPattern = (pattern, name) => {
20
+ let patternIndex = 0;
21
+ let nameIndex = 0;
22
+ let wildcardIndex = -1;
23
+ let wildcardNameIndex = 0;
24
+ while (nameIndex < name.length) {
25
+ const token = pattern[patternIndex];
26
+ if (token !== undefined && token !== "*" && token === name[nameIndex]) {
27
+ patternIndex += 1;
28
+ nameIndex += 1;
44
29
  }
45
- while (pattern[patternIndex] === "*") {
30
+ else if (token === "*") {
31
+ wildcardIndex = patternIndex;
32
+ wildcardNameIndex = nameIndex;
46
33
  patternIndex += 1;
47
34
  }
48
- return patternIndex === pattern.length;
49
- };
50
- return names.filter(matches);
35
+ else if (wildcardIndex >= 0) {
36
+ patternIndex = wildcardIndex + 1;
37
+ wildcardNameIndex += 1;
38
+ nameIndex = wildcardNameIndex;
39
+ }
40
+ else {
41
+ return false;
42
+ }
43
+ }
44
+ while (pattern[patternIndex] === "*") {
45
+ patternIndex += 1;
46
+ }
47
+ return patternIndex === pattern.length;
51
48
  };
49
+ /** Expand a glob pattern against names, preserving their original order. */
50
+ export const expandGlob = (pattern, names) => names.filter((name) => matchesPattern(pattern, name));
52
51
  /**
53
52
  * Expand multiple glob patterns against a list of extension names.
54
53
  *
@@ -26,4 +26,10 @@ export declare const makeWorkspaceRelativeSourcePath: (path: Path.Path, workspac
26
26
  * prefix is not mistaken for a child.
27
27
  */
28
28
  export declare const isPathSafe: (path: Path.Path, base: string, target: string) => boolean;
29
+ /** Resolve a child against its base and reject paths that escape it. */
30
+ export declare const safeChildPath: (path: Path.Path, base: string, target: string) => Option.Option<AbsolutePath>;
31
+ /** Relative-path containment, including the parent itself. */
32
+ export declare const isWithinOrEqual: (path: Path.Path, parent: string, child: string) => boolean;
33
+ /** Relative-path containment that excludes the parent itself. */
34
+ export declare const isStrictlyWithin: (path: Path.Path, parent: string, child: string) => boolean;
29
35
  //# sourceMappingURL=path-types.d.ts.map
@@ -56,4 +56,24 @@ export const isPathSafe = (path, base, target) => {
56
56
  const resolvedTarget = path.resolve(target);
57
57
  return resolvedTarget === resolvedBase || resolvedTarget.startsWith(resolvedBase + path.sep);
58
58
  };
59
+ /** Resolve a child against its base and reject paths that escape it. */
60
+ export const safeChildPath = (path, base, target) => {
61
+ const resolvedBase = path.resolve(base);
62
+ const resolvedTarget = path.isAbsolute(target)
63
+ ? path.resolve(target)
64
+ : path.resolve(resolvedBase, target);
65
+ return isPathSafe(path, resolvedBase, resolvedTarget)
66
+ ? Option.some(makeAbsolutePath(path, resolvedTarget))
67
+ : Option.none();
68
+ };
69
+ /** Relative-path containment, including the parent itself. */
70
+ export const isWithinOrEqual = (path, parent, child) => {
71
+ const relative = path.relative(path.resolve(parent), path.resolve(child));
72
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
73
+ };
74
+ /** Relative-path containment that excludes the parent itself. */
75
+ export const isStrictlyWithin = (path, parent, child) => {
76
+ const relative = path.relative(path.resolve(parent), path.resolve(child));
77
+ return relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
78
+ };
59
79
  //# sourceMappingURL=path-types.js.map
@@ -1,22 +1,58 @@
1
1
  /**
2
- * Pure per-forge source shorthand printing grammar.
2
+ * Forge coordinate, clone URL, and browser URL grammar.
3
3
  *
4
- * Each printer formats source params as the forge's canonical shorthand
5
- * string. Probing and acquisition stay with the source-resolution providers;
6
- * only the string grammar lives here.
4
+ * Probing and acquisition stay with source resolution; the model owns the
5
+ * strings and URLs that identify each forge repository.
7
6
  *
8
7
  * @experimental This API is unstable and may change without notice.
9
8
  * @packageDocumentation
10
9
  */
11
- import type { AzureReposSourceParams, BitbucketSourceParams, GitHubSourceParams, GitLabSourceParams, LocalSourceParams } from "./types.js";
10
+ import * as Option from "effect/Option";
11
+ import * as Result from "effect/Result";
12
12
  /** @experimental */
13
- export declare const printGitHubSource: (source: GitHubSourceParams, sourceName?: string) => string;
13
+ export declare const FORGE_PREFIXES: readonly ["github", "gitlab", "bitbucket", "azurerepos"];
14
14
  /** @experimental */
15
- export declare const printGitLabSource: (source: GitLabSourceParams, sourceName?: string) => string;
15
+ export type ForgePrefix = (typeof FORGE_PREFIXES)[number];
16
16
  /** @experimental */
17
- export declare const printBitbucketSource: (source: BitbucketSourceParams, sourceName?: string) => string;
17
+ export declare const isForgePrefix: (value: string) => value is ForgePrefix;
18
18
  /** @experimental */
19
- export declare const printAzureReposSource: (source: AzureReposSourceParams, sourceName?: string) => string;
19
+ export interface ForgeCoordinate {
20
+ readonly forge: ForgePrefix;
21
+ readonly repository: string;
22
+ readonly ref: Option.Option<string>;
23
+ readonly subPath: Option.Option<string>;
24
+ }
25
+ interface BrowserPath {
26
+ readonly repository: string;
27
+ readonly ref?: string;
28
+ readonly subPath?: string;
29
+ }
20
30
  /** @experimental */
21
- export declare const printLocalSource: (source: LocalSourceParams) => string;
31
+ export interface Forge {
32
+ readonly prefix: ForgePrefix;
33
+ readonly hostname: string;
34
+ readonly repositorySegments: (count: number) => boolean;
35
+ readonly cloneUrl: (repository: string) => URL;
36
+ readonly repositoryFromCloneUrl: (pathname: string) => string | undefined;
37
+ readonly parseBrowserPath: (pathname: string) => BrowserPath | undefined;
38
+ }
39
+ /** @experimental */
40
+ export declare const FORGES: Record<ForgePrefix, Forge>;
41
+ /** @experimental */
42
+ export declare const forgeForHostname: (hostname: string) => Forge | undefined;
43
+ /** @experimental */
44
+ export declare const parseForgeCoordinate: (forge: ForgePrefix, body: string) => Result.Result<ForgeCoordinate, {
45
+ readonly reason: string;
46
+ }>;
47
+ /** @experimental */
48
+ export declare const printForgeCoordinateBody: (coordinate: ForgeCoordinate) => string;
49
+ /** @experimental */
50
+ export declare const printForgeCoordinate: (coordinate: ForgeCoordinate) => string;
51
+ /** @experimental */
52
+ export declare const forgeCloneUrl: (coordinate: ForgeCoordinate) => URL;
53
+ /** @experimental */
54
+ export declare const forgeCoordinateFromGitUrl: (url: URL, ref: Option.Option<string>, subPath: Option.Option<string>) => Option.Option<ForgeCoordinate>;
55
+ /** @experimental */
56
+ export declare const parseForgeBrowserUrl: (url: URL) => Option.Option<ForgeCoordinate>;
57
+ export {};
22
58
  //# sourceMappingURL=forge-grammar.d.ts.map
@@ -1,50 +1,170 @@
1
1
  /**
2
- * Pure per-forge source shorthand printing grammar.
2
+ * Forge coordinate, clone URL, and browser URL grammar.
3
3
  *
4
- * Each printer formats source params as the forge's canonical shorthand
5
- * string. Probing and acquisition stay with the source-resolution providers;
6
- * only the string grammar lives here.
4
+ * Probing and acquisition stay with source resolution; the model owns the
5
+ * strings and URLs that identify each forge repository.
7
6
  *
8
7
  * @experimental This API is unstable and may change without notice.
9
8
  * @packageDocumentation
10
9
  */
11
10
  import * as Option from "effect/Option";
11
+ import * as Result from "effect/Result";
12
+ import * as Schema from "effect/Schema";
13
+ import { SourceNamespaceSchema, SourceRefSchema, SourceSubPathSchema } from "./types.js";
12
14
  /** @experimental */
13
- export const printGitHubSource = (source, sourceName = source.sourceName ?? "github") => {
14
- let s = `${sourceName}:${source.owner}/${source.repo}`;
15
- if (Option.isSome(source.subPath))
16
- s += `//${source.subPath.value}`;
17
- if (Option.isSome(source.ref))
18
- s += `@${source.ref.value}`;
19
- return s;
15
+ export const FORGE_PREFIXES = ["github", "gitlab", "bitbucket", "azurerepos"];
16
+ /** @experimental */
17
+ export const isForgePrefix = (value) => FORGE_PREFIXES.some((prefix) => prefix === value);
18
+ const segments = (pathname) => pathname.split("/").filter((segment) => segment.length > 0);
19
+ const withoutGit = (name) => (name.endsWith(".git") ? name.slice(0, -4) : name);
20
+ const hostedRepositoryFromCloneUrl = (pathname) => {
21
+ const parts = segments(pathname);
22
+ const last = parts.at(-1);
23
+ return last === undefined || parts.length < 2
24
+ ? undefined
25
+ : [...parts.slice(0, -1), withoutGit(last)].join("/");
26
+ };
27
+ const hostedBrowserPath = (pathname, marker) => {
28
+ const pattern = marker === "tree"
29
+ ? /^\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/tree\/([^/]+)(?:\/(.+))?)?$/u
30
+ : /^\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/src\/([^/]+)(?:\/(.+))?)?$/u;
31
+ const match = pattern.exec(pathname);
32
+ if (match?.[1] === undefined || match[2] === undefined)
33
+ return undefined;
34
+ return {
35
+ repository: `${match[1]}/${match[2]}`,
36
+ ...(match[3] === undefined ? {} : { ref: match[3] }),
37
+ ...(match[4] === undefined ? {} : { subPath: match[4] }),
38
+ };
39
+ };
40
+ const gitlabBrowserPath = (pathname) => {
41
+ const marker = "/-/tree/";
42
+ const markerIndex = pathname.indexOf(marker);
43
+ const repositoryParts = segments(markerIndex < 0 ? pathname : pathname.slice(0, markerIndex));
44
+ const last = repositoryParts.at(-1);
45
+ if (last === undefined || repositoryParts.length < 2)
46
+ return undefined;
47
+ const treePath = markerIndex < 0 ? [] : pathname.slice(markerIndex + marker.length).split("/");
48
+ const subPath = treePath.slice(1).join("/");
49
+ return {
50
+ repository: [...repositoryParts.slice(0, -1), withoutGit(last)].join("/"),
51
+ ...(treePath[0] === undefined ? {} : { ref: treePath[0] }),
52
+ ...(subPath.length === 0 ? {} : { subPath }),
53
+ };
54
+ };
55
+ const azureRepositoryFromCloneUrl = (pathname) => {
56
+ const parts = segments(pathname);
57
+ return parts.length === 4 && parts[2] === "_git"
58
+ ? `${parts[0]}/${parts[1]}/${withoutGit(parts[3] ?? "")}`
59
+ : undefined;
60
+ };
61
+ const azureBrowserPath = (pathname) => {
62
+ const match = /^\/([^/]+)\/([^/]+)\/_git\/([^/]+?)(?:\.git)?$/u.exec(pathname);
63
+ return match?.[1] === undefined || match[2] === undefined || match[3] === undefined
64
+ ? undefined
65
+ : { repository: `${match[1]}/${match[2]}/${match[3]}` };
66
+ };
67
+ const hostedForge = (prefix, hostname, parseBrowserPath) => ({
68
+ prefix,
69
+ hostname,
70
+ repositorySegments: (count) => count >= 2,
71
+ cloneUrl: (repository) => new URL(`https://${hostname}/${repository}.git`),
72
+ repositoryFromCloneUrl: hostedRepositoryFromCloneUrl,
73
+ parseBrowserPath,
74
+ });
75
+ /** @experimental */
76
+ export const FORGES = {
77
+ github: hostedForge("github", "github.com", (pathname) => hostedBrowserPath(pathname, "tree")),
78
+ gitlab: hostedForge("gitlab", "gitlab.com", gitlabBrowserPath),
79
+ bitbucket: hostedForge("bitbucket", "bitbucket.org", (pathname) => hostedBrowserPath(pathname, "src")),
80
+ azurerepos: {
81
+ prefix: "azurerepos",
82
+ hostname: "dev.azure.com",
83
+ repositorySegments: (count) => count === 3,
84
+ cloneUrl: (repository) => {
85
+ const [organization, project, repo] = repository.split("/");
86
+ return new URL(`https://dev.azure.com/${organization}/${project}/_git/${repo}`);
87
+ },
88
+ repositoryFromCloneUrl: azureRepositoryFromCloneUrl,
89
+ parseBrowserPath: azureBrowserPath,
90
+ },
91
+ };
92
+ /** @experimental */
93
+ export const forgeForHostname = (hostname) => Object.values(FORGES).find((forge) => forge.hostname === hostname);
94
+ const decodeNamespace = Schema.decodeUnknownResult(SourceNamespaceSchema);
95
+ const decodeSubPath = Schema.decodeUnknownResult(SourceSubPathSchema);
96
+ const decodeRef = Schema.decodeUnknownResult(SourceRefSchema);
97
+ const validCoordinate = (coordinate) => FORGES[coordinate.forge].repositorySegments(coordinate.repository.split("/").length) &&
98
+ Result.isSuccess(decodeNamespace(coordinate.repository)) &&
99
+ (Option.isNone(coordinate.subPath) ||
100
+ Result.isSuccess(decodeSubPath(coordinate.subPath.value))) &&
101
+ (Option.isNone(coordinate.ref) || Result.isSuccess(decodeRef(coordinate.ref.value)));
102
+ const splitRef = (input) => {
103
+ const refIndex = input.lastIndexOf("@");
104
+ if (refIndex <= 0)
105
+ return { coordinate: input };
106
+ const ref = input.slice(refIndex + 1);
107
+ const subPathMarker = input.indexOf("//");
108
+ const isAtPathSegment = subPathMarker !== -1 &&
109
+ refIndex > subPathMarker + 1 &&
110
+ input[refIndex - 1] === "/" &&
111
+ ref.includes("/");
112
+ return isAtPathSegment ? { coordinate: input } : { coordinate: input.slice(0, refIndex), ref };
20
113
  };
21
114
  /** @experimental */
22
- export const printGitLabSource = (source, sourceName = source.sourceName ?? "gitlab") => {
23
- let s = `${sourceName}:${source.owner}/${source.repo}`;
24
- if (Option.isSome(source.subPath))
25
- s += `//${source.subPath.value}`;
26
- if (Option.isSome(source.ref))
27
- s += `@${source.ref.value}`;
28
- return s;
115
+ export const parseForgeCoordinate = (forge, body) => {
116
+ const { coordinate, ref } = splitRef(body);
117
+ const marker = coordinate.indexOf("//");
118
+ const repository = marker < 0 ? coordinate : coordinate.slice(0, marker);
119
+ const subPath = marker < 0 ? undefined : coordinate.slice(marker + 2);
120
+ const parsed = {
121
+ forge,
122
+ repository,
123
+ ref: Option.fromUndefinedOr(ref),
124
+ subPath: Option.fromUndefinedOr(subPath),
125
+ };
126
+ return validCoordinate(parsed)
127
+ ? Result.succeed(parsed)
128
+ : Result.fail({ reason: `Expected valid ${forge} repository[//subpath][@ref]` });
29
129
  };
30
130
  /** @experimental */
31
- export const printBitbucketSource = (source, sourceName = source.sourceName ?? "bitbucket") => {
32
- let s = `${sourceName}:${source.owner}/${source.repo}`;
33
- if (Option.isSome(source.subPath))
34
- s += `//${source.subPath.value}`;
35
- if (Option.isSome(source.ref))
36
- s += `@${source.ref.value}`;
37
- return s;
131
+ export const printForgeCoordinateBody = (coordinate) => {
132
+ let body = coordinate.repository;
133
+ if (Option.isSome(coordinate.subPath))
134
+ body += `//${coordinate.subPath.value}`;
135
+ if (Option.isSome(coordinate.ref))
136
+ body += `@${coordinate.ref.value}`;
137
+ return body;
38
138
  };
39
139
  /** @experimental */
40
- export const printAzureReposSource = (source, sourceName = source.sourceName ?? "azurerepos") => {
41
- let s = `${sourceName}:${source.organization}/${source.project}/${source.repo}`;
42
- if (Option.isSome(source.subPath))
43
- s += `//${source.subPath.value}`;
44
- if (Option.isSome(source.ref))
45
- s += `@${source.ref.value}`;
46
- return s;
140
+ export const printForgeCoordinate = (coordinate) => `${coordinate.forge}:${printForgeCoordinateBody(coordinate)}`;
141
+ /** @experimental */
142
+ export const forgeCloneUrl = (coordinate) => FORGES[coordinate.forge].cloneUrl(coordinate.repository);
143
+ /** @experimental */
144
+ export const forgeCoordinateFromGitUrl = (url, ref, subPath) => {
145
+ const forge = forgeForHostname(url.hostname);
146
+ if (forge === undefined)
147
+ return Option.none();
148
+ const repository = forge.repositoryFromCloneUrl(url.pathname);
149
+ if (repository === undefined)
150
+ return Option.none();
151
+ const coordinate = { forge: forge.prefix, repository, ref, subPath };
152
+ return validCoordinate(coordinate) ? Option.some(coordinate) : Option.none();
47
153
  };
48
154
  /** @experimental */
49
- export const printLocalSource = (source) => source.path.startsWith("/") || source.path.startsWith(".") ? source.path : `./${source.path}`;
155
+ export const parseForgeBrowserUrl = (url) => {
156
+ const forge = forgeForHostname(url.hostname);
157
+ if (forge === undefined)
158
+ return Option.none();
159
+ const parsed = forge.parseBrowserPath(url.pathname);
160
+ if (parsed === undefined)
161
+ return Option.none();
162
+ const coordinate = {
163
+ forge: forge.prefix,
164
+ repository: parsed.repository,
165
+ ref: Option.fromUndefinedOr(parsed.ref),
166
+ subPath: Option.fromUndefinedOr(parsed.subPath),
167
+ };
168
+ return validCoordinate(coordinate) ? Option.some(coordinate) : Option.none();
169
+ };
50
170
  //# sourceMappingURL=forge-grammar.js.map
@@ -9,6 +9,7 @@
9
9
  * @packageDocumentation
10
10
  */
11
11
  import * as Option from "effect/Option";
12
+ import { type ForgeCoordinate, type ForgePrefix } from "./forge-grammar.js";
12
13
  import type { VersionRange } from "../version-constraints/version-constraints.js";
13
14
  import type { ExtensionName, ExtensionType, ExtensionTypePlural } from "../extensions/common.js";
14
15
  import type { Handle } from "../extensions/handle.js";
@@ -45,10 +46,7 @@ type GitScpAddress = {
45
46
  /** An `owner/repo[//path][@ref]` style pattern containing `/` (not a URL or file path). */
46
47
  type SlashPattern = {
47
48
  readonly pattern: "slash-pattern";
48
- readonly first: string;
49
- readonly second: string;
50
- readonly third: Option.Option<string>;
51
- readonly ref: Option.Option<string>;
49
+ readonly coordinate: ForgeCoordinate;
52
50
  };
53
51
  /** A local filesystem path matching `LOCAL_PATH_PATTERN`. */
54
52
  type FilePathPattern = {
@@ -58,7 +56,7 @@ type FilePathPattern = {
58
56
  /** A shorthand prefixed input: `<prefix>:...` where prefix is a known source provider. */
59
57
  export type ShorthandInput = {
60
58
  readonly pattern: "shorthand-input";
61
- readonly prefix: string;
59
+ readonly prefix: ForgePrefix;
62
60
  readonly remainingInput: string;
63
61
  };
64
62
  /** A glob pattern containing `*` wildcards (e.g. `effect-*`). */
@@ -10,14 +10,13 @@
10
10
  */
11
11
  import * as Option from "effect/Option";
12
12
  import * as Result from "effect/Result";
13
+ import { isForgePrefix, parseForgeCoordinate, } from "./forge-grammar.js";
13
14
  import { parseFqn } from "../extensions/fqn.js";
14
15
  import { parseSourceQualifiedRegistrySourcePatternParts } from "../extensions/registry-source.js";
15
16
  /** Matches: ./path, ../path, /path, ~/path, ~\path, or Windows paths like C:\path */
16
17
  const LOCAL_PATH_PATTERN = /^(?:\.\.?\/|\/|~\/|~\\|[A-Za-z]:[\\/])/;
17
18
  /** SCP-style: `user@host:path` — no `://` scheme. */
18
19
  const SCP_PATTERN = /^([^@]+)@([^:]+):(.+)$/;
19
- /** Known shorthand prefixes. */
20
- const SHORTHAND_PREFIXES = new Set(["github", "gitlab", "bitbucket", "azurerepos"]);
21
20
  /** Simple name: alphanumeric with hyphens, no leading/trailing hyphen. */
22
21
  const NAME_PATTERN = /^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/;
23
22
  /**
@@ -66,10 +65,11 @@ export const parseInputPattern = (input) => {
66
65
  }
67
66
  // 4. Shorthand prefix (github:..., gitlab:..., etc.) — must check before URL
68
67
  const colonIndex = input.indexOf(":");
69
- if (colonIndex > 0 && SHORTHAND_PREFIXES.has(input.slice(0, colonIndex))) {
68
+ const prefix = input.slice(0, colonIndex);
69
+ if (colonIndex > 0 && isForgePrefix(prefix)) {
70
70
  return Option.some(wrap({
71
71
  pattern: "shorthand-input",
72
- prefix: input.slice(0, colonIndex),
72
+ prefix,
73
73
  remainingInput: input.slice(colonIndex + 1),
74
74
  }));
75
75
  }
@@ -90,34 +90,17 @@ export const parseInputPattern = (input) => {
90
90
  }
91
91
  // 7. Slash pattern (`owner/repo[//path][@ref]`)
92
92
  if (input.includes("/")) {
93
- const refIndex = input.lastIndexOf("@");
94
- const hasRef = refIndex > 0 && refIndex < input.length - 1;
95
- const coordinate = hasRef ? input.slice(0, refIndex) : input;
96
- const ref = hasRef ? input.slice(refIndex + 1) : undefined;
97
- const subPathIndex = coordinate.indexOf("//");
98
- const repositoryCoordinate = subPathIndex < 0 ? coordinate : coordinate.slice(0, subPathIndex);
99
- const subPath = subPathIndex < 0 ? undefined : coordinate.slice(subPathIndex + 2);
100
- const segments = repositoryCoordinate.split("/");
101
- const first = segments.at(0);
102
- const second = segments.at(1);
103
- if (first !== undefined &&
104
- second !== undefined &&
105
- segments.length === 2 &&
106
- NAME_PATTERN.test(first) &&
107
- NAME_PATTERN.test(second) &&
108
- (ref === undefined || (ref.length > 0 && !ref.includes("/"))) &&
109
- (subPath === undefined ||
110
- (subPath.length > 0 &&
111
- subPath.split("/").every((segment) => segment.length > 0 && segment !== "..")))) {
112
- return Option.some(wrap({
113
- pattern: "slash-pattern",
114
- first,
115
- second,
116
- third: Option.fromUndefinedOr(subPath),
117
- ref: Option.fromUndefinedOr(ref),
118
- }));
93
+ const parsed = parseForgeCoordinate("github", input);
94
+ if (Result.isFailure(parsed))
95
+ return Option.none();
96
+ const coordinate = parsed.success;
97
+ const segments = coordinate.repository.split("/");
98
+ if (segments.length !== 2 ||
99
+ !segments.every((segment) => NAME_PATTERN.test(segment)) ||
100
+ Option.exists(coordinate.ref, (ref) => ref.includes("/"))) {
101
+ return Option.none();
119
102
  }
120
- return Option.none();
103
+ return Option.some(wrap({ pattern: "slash-pattern", coordinate }));
121
104
  }
122
105
  // 8. Glob pattern (contains `*` wildcard)
123
106
  if (input.includes("*")) {
@@ -6,7 +6,8 @@
6
6
  */
7
7
  import * as Option from "effect/Option";
8
8
  import { formatFqn } from "../extensions/fqn.js";
9
- import { printLocalSource } from "./forge-grammar.js";
9
+ import { forgeCoordinateFromGitUrl, printForgeCoordinate } from "./forge-grammar.js";
10
+ const printLocalSource = (source) => source.path.startsWith("/") || source.path.startsWith(".") ? source.path : `./${source.path}`;
10
11
  /**
11
12
  * Print source params as their canonical shorthand string.
12
13
  *
@@ -17,40 +18,14 @@ export const printSourceParams = (source) => {
17
18
  case "local":
18
19
  return printLocalSource(source);
19
20
  case "git": {
20
- const repositorySegments = source.url.pathname
21
- .split("/")
22
- .filter((segment) => segment.length > 0);
23
- if (source.url.hostname === "dev.azure.com" &&
24
- repositorySegments.length === 4 &&
25
- repositorySegments[2] === "_git") {
26
- let shorthand = `azurerepos:${repositorySegments[0]}/${repositorySegments[1]}/${repositorySegments[3]}`;
27
- if (Option.isSome(source.subPath))
28
- shorthand += `//${source.subPath.value}`;
29
- if (Option.isSome(source.ref))
30
- shorthand += `@${source.ref.value}`;
31
- return shorthand;
32
- }
33
- const lastSegment = repositorySegments.at(-1);
34
- const repo = lastSegment?.endsWith(".git") ? lastSegment.slice(0, -4) : lastSegment;
35
- const sourcePrefix = source.url.hostname === "github.com"
36
- ? "github"
37
- : source.url.hostname === "gitlab.com"
38
- ? "gitlab"
39
- : source.url.hostname === "bitbucket.org"
40
- ? "bitbucket"
41
- : undefined;
42
- if (sourcePrefix !== undefined && repo !== undefined && repositorySegments.length >= 2) {
43
- const owner = repositorySegments.slice(0, -1).join("/");
44
- let shorthand = `${sourcePrefix}:${owner}/${repo}`;
45
- if (Option.isSome(source.subPath))
46
- shorthand += `//${source.subPath.value}`;
47
- if (Option.isSome(source.ref))
48
- shorthand += `@${source.ref.value}`;
49
- return shorthand;
50
- }
51
- const url = new URL(source.url.href);
52
- url.hash = Option.getOrElse(source.ref, () => "");
53
- return url.href;
21
+ return Option.match(forgeCoordinateFromGitUrl(source.url, source.ref, source.subPath), {
22
+ onSome: printForgeCoordinate,
23
+ onNone: () => {
24
+ const url = new URL(source.url.href);
25
+ url.hash = Option.getOrElse(source.ref, () => "");
26
+ return url.href;
27
+ },
28
+ });
54
29
  }
55
30
  case "registry": {
56
31
  return source.sourceName ?? ("name" in source ? String(source.name) : "agentxm");
@@ -29,7 +29,7 @@ export type SourceType = Schema.Schema.Type<typeof SourceTypeSchema>;
29
29
  /**
30
30
  * Ref type discriminator for extension ref hosting categories.
31
31
  *
32
- * - `"git-hosted"` - Git-based sources (GitHub, GitLab, Bitbucket, AzureRepos, Git)
32
+ * - `"git-hosted"` - Git-based sources, including the built-in forges
33
33
  * - `"registry"` - Package registry source
34
34
  * - `"local"` - Local filesystem path source
35
35
  * - `"workspace"` - Intrinsic managed workspace package
@@ -43,60 +43,9 @@ export declare const RefTypeSchema: Schema.Literals<readonly ["git-hosted", "reg
43
43
  * @experimental This API is unstable and may change without notice.
44
44
  */
45
45
  export type RefType = Schema.Schema.Type<typeof RefTypeSchema>;
46
- export declare const SourceSegmentSchema: Schema.NonEmptyString;
47
46
  export declare const SourceRefSchema: Schema.NonEmptyString;
48
47
  export declare const SourceNamespaceSchema: Schema.NonEmptyString;
49
48
  export declare const SourceSubPathSchema: Schema.NonEmptyString;
50
- export declare const GitHostedSourceParamPartsSchema: Schema.Struct<{
51
- sourceName: Schema.optional<Schema.String>;
52
- owner: Schema.NonEmptyString;
53
- repo: Schema.NonEmptyString;
54
- ref: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
55
- subPath: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
56
- }>;
57
- export type GitHostedSourceParamParts = Schema.Schema.Type<typeof GitHostedSourceParamPartsSchema>;
58
- export declare const AzureReposSourceParamPartsSchema: Schema.Struct<{
59
- sourceName: Schema.optional<Schema.String>;
60
- organization: Schema.NonEmptyString;
61
- project: Schema.NonEmptyString;
62
- repo: Schema.NonEmptyString;
63
- ref: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
64
- subPath: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
65
- }>;
66
- export type AzureReposSourceParamParts = Schema.Schema.Type<typeof AzureReposSourceParamPartsSchema>;
67
- export declare const GitHubSourceParamsSchema: Schema.Struct<{
68
- readonly sourceName: Schema.optional<Schema.String>;
69
- readonly owner: Schema.NonEmptyString;
70
- readonly repo: Schema.NonEmptyString;
71
- readonly ref: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
72
- readonly subPath: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
73
- readonly type: Schema.Literal<"github">;
74
- }>;
75
- export declare const GitLabSourceParamsSchema: Schema.Struct<{
76
- readonly sourceName: Schema.optional<Schema.String>;
77
- readonly owner: Schema.NonEmptyString;
78
- readonly repo: Schema.NonEmptyString;
79
- readonly ref: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
80
- readonly subPath: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
81
- readonly type: Schema.Literal<"gitlab">;
82
- }>;
83
- export declare const BitbucketSourceParamsSchema: Schema.Struct<{
84
- readonly sourceName: Schema.optional<Schema.String>;
85
- readonly owner: Schema.NonEmptyString;
86
- readonly repo: Schema.NonEmptyString;
87
- readonly ref: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
88
- readonly subPath: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
89
- readonly type: Schema.Literal<"bitbucket">;
90
- }>;
91
- export declare const AzureReposSourceParamsSchema: Schema.Struct<{
92
- readonly sourceName: Schema.optional<Schema.String>;
93
- readonly organization: Schema.NonEmptyString;
94
- readonly project: Schema.NonEmptyString;
95
- readonly repo: Schema.NonEmptyString;
96
- readonly ref: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
97
- readonly subPath: Schema.OptionFromOptionalKey<Schema.NonEmptyString>;
98
- readonly type: Schema.Literal<"azurerepos">;
99
- }>;
100
49
  /** @experimental */
101
50
  /** Self-describing — the git URL lives in SourceParams. @experimental */
102
51
  export interface GitSourceHost {
@@ -126,47 +75,6 @@ export interface WorkspaceSourceHost {
126
75
  /** @experimental */
127
76
  export type SourceHost = GitSourceHost | RegistrySourceHost | LocalSourceHost | InlineSourceHost | WorkspaceSourceHost;
128
77
  /** @experimental */
129
- export interface GitHubSourceParams {
130
- readonly type: "github";
131
- readonly sourceName?: string | undefined;
132
- readonly owner: string;
133
- readonly repo: string;
134
- readonly ref: Option.Option<string>;
135
- readonly subPath: Option.Option<string>;
136
- readonly cloneUrl?: Option.Option<string>;
137
- }
138
- /** @experimental */
139
- export interface GitLabSourceParams {
140
- readonly type: "gitlab";
141
- readonly sourceName?: string | undefined;
142
- readonly owner: string;
143
- readonly repo: string;
144
- readonly ref: Option.Option<string>;
145
- readonly subPath: Option.Option<string>;
146
- readonly cloneUrl?: Option.Option<string>;
147
- }
148
- /** @experimental */
149
- export interface BitbucketSourceParams {
150
- readonly type: "bitbucket";
151
- readonly sourceName?: string | undefined;
152
- readonly owner: string;
153
- readonly repo: string;
154
- readonly ref: Option.Option<string>;
155
- readonly subPath: Option.Option<string>;
156
- readonly cloneUrl?: Option.Option<string>;
157
- }
158
- /** @experimental */
159
- export interface AzureReposSourceParams {
160
- readonly type: "azurerepos";
161
- readonly sourceName?: string | undefined;
162
- readonly organization: string;
163
- readonly project: string;
164
- readonly repo: string;
165
- readonly ref: Option.Option<string>;
166
- readonly subPath: Option.Option<string>;
167
- readonly cloneUrl?: Option.Option<string>;
168
- }
169
- /** @experimental */
170
78
  export interface GitSourceParams {
171
79
  readonly type: "git";
172
80
  readonly url: URL;
@@ -36,7 +36,7 @@ export const SourceTypeSchema = Schema.Literals([
36
36
  /**
37
37
  * Ref type discriminator for extension ref hosting categories.
38
38
  *
39
- * - `"git-hosted"` - Git-based sources (GitHub, GitLab, Bitbucket, AzureRepos, Git)
39
+ * - `"git-hosted"` - Git-based sources, including the built-in forges
40
40
  * - `"registry"` - Package registry source
41
41
  * - `"local"` - Local filesystem path source
42
42
  * - `"workspace"` - Intrinsic managed workspace package
@@ -53,13 +53,7 @@ export const RefTypeSchema = Schema.Literals([
53
53
  title: "Ref Type",
54
54
  description: "Ref type category: git-hosted, registry, local, or workspace.",
55
55
  });
56
- const noSlashSegmentMessage = "Expected non-empty segment without '/' characters";
57
56
  const noTraversalSegmentMessage = "Expected subpath without '..' traversal segments";
58
- export const SourceSegmentSchema = Schema.NonEmptyString.pipe(Schema.check(Schema.makeFilter((value) => (value.includes("/") ? noSlashSegmentMessage : undefined)))).annotate({
59
- identifier: "SourceSegment",
60
- title: "Source Segment",
61
- description: "A non-empty path segment without slash characters, used for owner/repo identifiers.",
62
- });
63
57
  export const SourceRefSchema = Schema.NonEmptyString;
64
58
  export const SourceNamespaceSchema = Schema.NonEmptyString.pipe(Schema.check(Schema.makeFilter((value) => value.split("/").some((segment) => segment.length === 0 || segment === "..")
65
59
  ? "Expected non-empty namespace path segments without '..' traversal"
@@ -75,45 +69,4 @@ export const SourceSubPathSchema = Schema.NonEmptyString.pipe(Schema.check(Schem
75
69
  title: "Source Subpath",
76
70
  description: "A non-empty repository subpath without empty or '..' traversal segments.",
77
71
  });
78
- const GitHostedSourceParamFields = {
79
- sourceName: Schema.optional(Schema.String),
80
- owner: SourceNamespaceSchema,
81
- repo: SourceSegmentSchema,
82
- ref: Schema.OptionFromOptionalKey(SourceRefSchema),
83
- subPath: Schema.OptionFromOptionalKey(SourceSubPathSchema),
84
- };
85
- export const GitHostedSourceParamPartsSchema = Schema.Struct(GitHostedSourceParamFields).annotate({
86
- identifier: "GitHostedSourceParamParts",
87
- title: "Git Hosted Source Params",
88
- description: "Parameters for a git-hosted source: owner, repo, optional ref and sub-path.",
89
- });
90
- const AzureReposSourceParamFields = {
91
- sourceName: Schema.optional(Schema.String),
92
- organization: SourceSegmentSchema,
93
- project: SourceSegmentSchema,
94
- repo: SourceSegmentSchema,
95
- ref: Schema.OptionFromOptionalKey(SourceRefSchema),
96
- subPath: Schema.OptionFromOptionalKey(SourceSubPathSchema),
97
- };
98
- export const AzureReposSourceParamPartsSchema = Schema.Struct(AzureReposSourceParamFields).annotate({
99
- identifier: "AzureReposSourceParamParts",
100
- title: "Azure Repos Source Params",
101
- description: "Parameters for an Azure Repos source: organization, project, repo, optional ref and sub-path.",
102
- });
103
- export const GitHubSourceParamsSchema = Schema.Struct({
104
- type: Schema.Literal("github"),
105
- ...GitHostedSourceParamFields,
106
- });
107
- export const GitLabSourceParamsSchema = Schema.Struct({
108
- type: Schema.Literal("gitlab"),
109
- ...GitHostedSourceParamFields,
110
- });
111
- export const BitbucketSourceParamsSchema = Schema.Struct({
112
- type: Schema.Literal("bitbucket"),
113
- ...GitHostedSourceParamFields,
114
- });
115
- export const AzureReposSourceParamsSchema = Schema.Struct({
116
- type: Schema.Literal("azurerepos"),
117
- ...AzureReposSourceParamFields,
118
- });
119
72
  //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "description": "Shared AgentXM extension model: identities, manifests, version constraints, and agent capabilities. Unstable and unsupported — use the axm.sh CLI.",
13
13
  "devDependencies": {
14
- "@agentxm/specification-metadata": "0.35.0",
14
+ "@agentxm/specification-metadata": "0.36.0",
15
15
  "@effect/vitest": "4.0.0-rc.117",
16
16
  "@fast-check/vitest": "^0.5.0",
17
17
  "@types/semver": "^7.7.1",
@@ -305,5 +305,5 @@
305
305
  },
306
306
  "sideEffects": false,
307
307
  "type": "module",
308
- "version": "0.35.0"
308
+ "version": "0.36.0"
309
309
  }