@theholocron/cli 2.0.2 → 2.1.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.
- package/dist/capabilities/index.d.mts +4 -3
- package/dist/cli.mjs +56 -3
- package/dist/index.d.mts +0 -1
- package/package.json +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ProviderApiError } from "@theholocron/http-client";
|
|
2
|
-
|
|
3
2
|
//#region src/capabilities/index.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Capability interfaces — the contracts that providers implement.
|
|
@@ -276,7 +275,8 @@ interface Issues extends ProviderIdentity {
|
|
|
276
275
|
create(input: {
|
|
277
276
|
summary: string;
|
|
278
277
|
body?: string;
|
|
279
|
-
labels?: string[];
|
|
278
|
+
labels?: string[];
|
|
279
|
+
/** Numeric id or exact title (case-insensitive). */
|
|
280
280
|
milestone?: string;
|
|
281
281
|
}): Promise<{
|
|
282
282
|
key: string;
|
|
@@ -322,7 +322,8 @@ interface Deployment extends ProviderIdentity {
|
|
|
322
322
|
/** Create if missing, otherwise return existing. Idempotent. */
|
|
323
323
|
ensureProject(input: {
|
|
324
324
|
name: string;
|
|
325
|
-
framework?: string;
|
|
325
|
+
framework?: string;
|
|
326
|
+
/** "owner/repo" — passed when linking to a Git provider. */
|
|
326
327
|
repo?: string;
|
|
327
328
|
rootDirectory?: string;
|
|
328
329
|
}): Promise<DeploymentProject>;
|
package/dist/cli.mjs
CHANGED
|
@@ -3590,7 +3590,8 @@ async function runSetup(input) {
|
|
|
3590
3590
|
"prd"
|
|
3591
3591
|
]) {
|
|
3592
3592
|
steps.push(await runStep("vault", `ensureEnvironment ${envName}`, dryRun, async () => {
|
|
3593
|
-
|
|
3593
|
+
const result = await vault.ensureEnvironment(config.name, envName);
|
|
3594
|
+
return `${envName} ${result.alreadyExists ? "exists" : "created"}`;
|
|
3594
3595
|
}));
|
|
3595
3596
|
print(formatStep(steps[steps.length - 1]));
|
|
3596
3597
|
}
|
|
@@ -3676,6 +3677,21 @@ async function runSetup(input) {
|
|
|
3676
3677
|
summary
|
|
3677
3678
|
};
|
|
3678
3679
|
}
|
|
3680
|
+
/**
|
|
3681
|
+
* Fetch a single SKILL.md from its upstream GitHub source.
|
|
3682
|
+
* Verifies the SHA-256 hash when `computedHash` is present in the lock entry.
|
|
3683
|
+
*/
|
|
3684
|
+
async function fetchExternalSkill(entry) {
|
|
3685
|
+
if (entry.sourceType !== "github") throw new Error(`unsupported sourceType: ${entry.sourceType}`);
|
|
3686
|
+
const url = `https://raw.githubusercontent.com/${entry.source}/HEAD/${entry.skillPath}`;
|
|
3687
|
+
const res = await fetch(url);
|
|
3688
|
+
if (!res.ok) throw new Error(`HTTP ${res.status} fetching ${url}`);
|
|
3689
|
+
const content = await res.text();
|
|
3690
|
+
return {
|
|
3691
|
+
content,
|
|
3692
|
+
stale: !!entry.computedHash && createHash("sha256").update(content).digest("hex") !== entry.computedHash
|
|
3693
|
+
};
|
|
3694
|
+
}
|
|
3679
3695
|
const AGENTS_SKILLS_ROOT = ".agents/skills";
|
|
3680
3696
|
/** Relative path of the agent-specific symlink. undefined = unsupported agent. */
|
|
3681
3697
|
const AGENT_SYMLINK_PATHS = { claude: (name) => `.claude/skills/${name}` };
|
|
@@ -3723,9 +3739,45 @@ async function installSkills({ agent, skills, repoRoot }) {
|
|
|
3723
3739
|
await symlink(relative(dirname(symlinkPath), agentsDir).replace(/\\/g, "/"), symlinkPath);
|
|
3724
3740
|
installed.push(name);
|
|
3725
3741
|
}
|
|
3726
|
-
|
|
3742
|
+
const externalFailed = [];
|
|
3743
|
+
const externalStale = [];
|
|
3744
|
+
if (missing.length > 0) {
|
|
3745
|
+
let lock = null;
|
|
3746
|
+
try {
|
|
3747
|
+
lock = JSON.parse(await readFile(join(skillsRoot, "skills-lock.json"), "utf8"));
|
|
3748
|
+
} catch {}
|
|
3749
|
+
if (lock?.skills) for (const name of [...missing]) {
|
|
3750
|
+
const entry = lock.skills[name];
|
|
3751
|
+
if (!entry) continue;
|
|
3752
|
+
try {
|
|
3753
|
+
const { content, stale: isStale } = await fetchExternalSkill(entry);
|
|
3754
|
+
const agentsDir = join(repoRoot, AGENTS_SKILLS_ROOT, name);
|
|
3755
|
+
await mkdir(agentsDir, { recursive: true });
|
|
3756
|
+
await writeFile(join(agentsDir, "SKILL.md"), content);
|
|
3757
|
+
const symlinkPath = join(repoRoot, symlinkFn(name));
|
|
3758
|
+
await mkdir(dirname(symlinkPath), { recursive: true });
|
|
3759
|
+
try {
|
|
3760
|
+
await unlink(symlinkPath);
|
|
3761
|
+
} catch {}
|
|
3762
|
+
await symlink(relative(dirname(symlinkPath), agentsDir).replace(/\\/g, "/"), symlinkPath);
|
|
3763
|
+
missing.splice(missing.indexOf(name), 1);
|
|
3764
|
+
installed.push(name);
|
|
3765
|
+
if (isStale) externalStale.push(name);
|
|
3766
|
+
} catch {
|
|
3767
|
+
missing.splice(missing.indexOf(name), 1);
|
|
3768
|
+
externalFailed.push(name);
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
if (installed.length > 0 || stale.length > 0 || missing.length > 0 || externalFailed.length > 0) await updateSkillsGitignore(gitignorePath, existingContent, [
|
|
3773
|
+
...installed,
|
|
3774
|
+
...missing,
|
|
3775
|
+
...externalFailed
|
|
3776
|
+
], symlinkFn);
|
|
3727
3777
|
const parts = [`installed ${installed.length}`];
|
|
3728
3778
|
if (stale.length > 0) parts.push(`pruned: ${stale.join(", ")}`);
|
|
3779
|
+
if (externalStale.length > 0) parts.push(`stale: ${externalStale.join(", ")} (run \`holocron skills update\` to refresh)`);
|
|
3780
|
+
if (externalFailed.length > 0) parts.push(`fetch failed: ${externalFailed.join(", ")}`);
|
|
3729
3781
|
if (missing.length > 0) parts.push(`unknown: ${missing.join(", ")}`);
|
|
3730
3782
|
return parts.join("; ");
|
|
3731
3783
|
}
|
|
@@ -3750,9 +3802,10 @@ async function copyDirRecursive(src, dest) {
|
|
|
3750
3802
|
}
|
|
3751
3803
|
}
|
|
3752
3804
|
async function updateSkillsGitignore(gitignorePath, existingContent, skills, symlinkFn) {
|
|
3805
|
+
const entries = [`/${AGENTS_SKILLS_ROOT}/`, ...skills.map((n) => `/${symlinkFn(n)}`)];
|
|
3753
3806
|
const block = [
|
|
3754
3807
|
GITIGNORE_BLOCK_START,
|
|
3755
|
-
...
|
|
3808
|
+
...entries,
|
|
3756
3809
|
GITIGNORE_BLOCK_END
|
|
3757
3810
|
].join("\n");
|
|
3758
3811
|
let content;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Analytics, Auth, AuthDescription, AuthEvent, AuthEventType, AuthIdentity, AuthUser, CARDINALITY, CapabilityImpls, CapabilityKey, Cardinality, CardinalityFor, Ci, CiRun, CiRunFilter, CiRunStatus, ConnectionStringOptions, CreateAuthUserInput, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, Dns, DnsRecord, DnsRecordType, EnsureResult, Environment, EnvironmentReviewer, Environments, Issue, IssueSearchFilter, Issues, LabelDef, LifecycleResult, LifecycleSlot, NormalizedAuthUser, Notifications, Observability, ParseWebhookInput, ProviderApiError, ProviderIdentity, REQUIRED_CAPABILITIES, RepoRef, RepoSettings, ResolvedCapability, Ruleset, SecretScope, Secrets, Source, StatusCategory, Storage, StorageBranch, TeamEntry, TeamPermission, Tooling, ToolingDoctorReport, TrackerDoctorReport, TrackerUser, Vault, WebhookDashboardInfo, WebhookVerificationError, isMulti } from "./capabilities/index.mjs";
|
|
2
2
|
import { AuthError, RequestOptions, ResolveTokenConfig as ResolveTokenConfig$1, ResolveTokenInput, RestClient, RestClientConfig, createRestClient } from "@theholocron/http-client";
|
|
3
|
-
|
|
4
3
|
//#region src/auth-resolver.d.ts
|
|
5
4
|
type ResolveTokenConfig = Omit<ResolveTokenConfig$1, "getKeyringToken">;
|
|
6
5
|
/** Wraps `createResolveToken` from `@theholocron/http` and injects the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "The Holocron CLI — a pluggable, capability-based orchestrator for spinning up and operating software projects.",
|
|
5
5
|
"homepage": "https://github.com/theholocron/holocron/tree/main/packages/cli#readme",
|
|
6
6
|
"bugs": "https://github.com/theholocron/holocron/issues",
|