@hasna/skills 0.10.76 → 0.10.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/bin/index.js +202 -57
- package/bin/mcp.js +108 -16
- package/bin/migrate.js +1 -1
- package/bin/server.js +36 -33
- package/bin/worker.js +4 -1
- package/dist/index.js +58 -14
- package/dist/lib/auth-store.d.ts +1 -1
- package/dist/lib/codex-plugin-capability-paths.d.ts +31 -0
- package/dist/lib/credential-profile-command.d.ts +5 -0
- package/dist/lib/fleet-credentials.d.ts +11 -5
- package/dist/lib/instance-credentials.d.ts +2 -0
- package/dist/lib/sign-in.d.ts +1 -1
- package/dist/runtime-prerequisites.js +1 -1
- package/dist/sdk/index.js +163 -121
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,7 +80,11 @@ Stations provisioned with a fleet key keep using the internal gateway
|
|
|
80
80
|
no recorded URL (the Keychain item, `HASNA_SKILLS_API_KEY` alone, or an older
|
|
81
81
|
credentials file) always stays on that gateway and is never sent anywhere else.
|
|
82
82
|
The gateway has no interactive login service, so on such a station
|
|
83
|
-
`skills login` says so
|
|
83
|
+
`skills login` says so and sends nothing. A stored gateway credential or vault
|
|
84
|
+
reference is preserved even with `--url`. Use a separate credential profile for
|
|
85
|
+
customer sign-in: `skills --profile skillsmd login`. Later product commands use that
|
|
86
|
+
profile too, for example `skills --profile skillsmd whoami --json`; fleet
|
|
87
|
+
commands keep their original configuration.
|
|
84
88
|
Obtain a workspace API key through your administrator's provisioning process
|
|
85
89
|
and configure it using the [credential resolution](#credentials) below. Check
|
|
86
90
|
the selected identity and available capabilities before syncing:
|
|
@@ -3318,6 +3322,6 @@ membership too; an executable digest does not prove dynamic backend behavior or
|
|
|
3318
3322
|
native adoption. These captures read files and never launch a native consumer.
|
|
3319
3323
|
|
|
3320
3324
|
|
|
3321
|
-
Codex cache witnesses migrate separately through `skills hook rebind-cache --agent codex`. Preview requires the exact current policy and configuration SHA-256 values. Name each reviewed remote app-only parent with `--app-only-parent`; name each already reviewed native `mcp_tool` parent with `--reviewed-hook-parent`. Hook parents require exact enrolled manifest and hook bytes. When the owning installer created a remote-install receipt, its exact schema, identity and bytes are required. A local marketplace install with no receipt is accepted only when the exact full marketplace source is already enrolled and the unchanged Codex settings enable that exact plugin identity. The complete cache census refuses unknown parents, cache-member aliases, new skills, direct hooks selecting cache inputs, and changed app/MCP/hook/receipt or marketplace capabilities. Reviewed whole Codex root aliases keep their existing identity/CAS guards; hook selection through either the alias or canonical cache path is refused. Commands containing the direct `plugins/cache` selector are conservatively refused, including HOME, tilde and relative spellings; no shell evaluation is performed. App-only bootstrap verifies the old full manifest and receipt sources, then explicitly reviews current app capabilities; it does not claim those app bytes were historically witnessed.
|
|
3325
|
+
Codex cache witnesses migrate separately through `skills hook rebind-cache --agent codex`. Preview requires the exact current policy and configuration SHA-256 values. Name each reviewed remote app-only parent with `--app-only-parent`; name each already reviewed native `mcp_tool` parent with `--reviewed-hook-parent`. Hook parents require exact enrolled manifest and hook bytes. When the owning installer created a remote-install receipt, its exact schema, identity and bytes are required. A local marketplace install with no receipt is accepted only when the exact full marketplace source is already enrolled and the unchanged Codex settings enable that exact plugin identity. The complete cache census refuses unknown parents, cache-member aliases, new skills, direct hooks selecting cache inputs, and changed app/MCP/hook/receipt or marketplace capabilities. It also refuses every capability location Codex reads in a plugin version root that the witness does not bind (the Agent Plugins root `plugin.json`, `.claude-plugin` and `.cursor-plugin` manifests, a root `hooks.json`, `commands/` and `agents/` directories, and a skill document not spelled exactly `SKILL.md`), compared without regard to case; the vendor-refresh guard reads the same list. A semantic binding captured by an earlier release is checked against this census at every guard run, so one of these paths makes it refuse until a fresh discovery review. Reviewed whole Codex root aliases keep their existing identity/CAS guards; hook selection through either the alias or canonical cache path is refused. Commands containing the direct `plugins/cache` selector are conservatively refused, including HOME, tilde and relative spellings; no shell evaluation is performed. App-only bootstrap verifies the old full manifest and receipt sources, then explicitly reviews current app capabilities; it does not claim those app bytes were historically witnessed.
|
|
3322
3326
|
|
|
3323
3327
|
Review the returned semantic cache digest, then repeat with `--expected-cache-witness-sha256 <digest> --apply`. The owning apply path preserves/readbacks the original policy, recomputes the whole plan, compares policy/config/cache preimages, writes only the Skills policy, and verifies the resulting consumer. Historical directory hashes and source rows remain retained as provenance; this command cannot reconstruct an unavailable old directory tree or waive an ancestor directory containing unrelated inputs. Equivalent version materializations and inert assets then leave the new Codex-specific witness unchanged. Every other discovery source, directory, settings witness, native control and session pin stays under its existing contract. Settings and cache upgrades remain independent; neither silently repairs drift in the other.
|
package/bin/index.js
CHANGED
|
@@ -36888,7 +36888,7 @@ var package_default;
|
|
|
36888
36888
|
var init_package = __esm(() => {
|
|
36889
36889
|
package_default = {
|
|
36890
36890
|
name: "@hasna/skills",
|
|
36891
|
-
version: "0.10.
|
|
36891
|
+
version: "0.10.77",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -50455,6 +50455,40 @@ var init_codex_settings_witness_v1 = __esm(() => {
|
|
|
50455
50455
|
VERBOSITY = new Set(["low", "medium", "high"]);
|
|
50456
50456
|
});
|
|
50457
50457
|
|
|
50458
|
+
// src/lib/codex-plugin-capability-paths.ts
|
|
50459
|
+
function foldCodexPluginEntryName(name) {
|
|
50460
|
+
return name.toUpperCase().toLowerCase();
|
|
50461
|
+
}
|
|
50462
|
+
function codexPluginRootCapabilityEntry(name) {
|
|
50463
|
+
const folded = foldCodexPluginEntryName(name);
|
|
50464
|
+
return CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES.includes(folded) ? folded : null;
|
|
50465
|
+
}
|
|
50466
|
+
function isCodexSkillDocumentName(name) {
|
|
50467
|
+
return foldCodexPluginEntryName(name) === "skill.md";
|
|
50468
|
+
}
|
|
50469
|
+
var CODEX_PLUGIN_MANIFEST_LOCATIONS, CODEX_PLUGIN_MANIFEST_DIRECTORIES, CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES;
|
|
50470
|
+
var init_codex_plugin_capability_paths = __esm(() => {
|
|
50471
|
+
CODEX_PLUGIN_MANIFEST_LOCATIONS = Object.freeze([
|
|
50472
|
+
"plugin.json",
|
|
50473
|
+
".codex-plugin/plugin.json",
|
|
50474
|
+
".claude-plugin/plugin.json",
|
|
50475
|
+
".cursor-plugin/plugin.json"
|
|
50476
|
+
]);
|
|
50477
|
+
CODEX_PLUGIN_MANIFEST_DIRECTORIES = Object.freeze([".codex-plugin", ".claude-plugin", ".cursor-plugin"]);
|
|
50478
|
+
CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES = Object.freeze([
|
|
50479
|
+
"plugin.json",
|
|
50480
|
+
".codex-plugin",
|
|
50481
|
+
".claude-plugin",
|
|
50482
|
+
".cursor-plugin",
|
|
50483
|
+
"hooks",
|
|
50484
|
+
"hooks.json",
|
|
50485
|
+
".mcp.json",
|
|
50486
|
+
".app.json",
|
|
50487
|
+
"commands",
|
|
50488
|
+
"agents"
|
|
50489
|
+
]);
|
|
50490
|
+
});
|
|
50491
|
+
|
|
50458
50492
|
// src/lib/codex-hook-mcp-dependencies.ts
|
|
50459
50493
|
import { createHash as createHash13 } from "crypto";
|
|
50460
50494
|
import { basename as basename6, dirname as dirname11, isAbsolute as isAbsolute11, join as join17, resolve as resolve12, sep as sep4 } from "path";
|
|
@@ -50599,15 +50633,13 @@ function captureCodexHookMcpDependencies(configPath, reviewed, configText, chang
|
|
|
50599
50633
|
}
|
|
50600
50634
|
};
|
|
50601
50635
|
const root = join17(cacheRoot, identity3, selectCodexPluginVersion(versions, selectionBudget));
|
|
50602
|
-
const
|
|
50636
|
+
const [agentPluginManifest, ...legacyManifests] = CODEX_PLUGIN_MANIFEST_LOCATIONS;
|
|
50637
|
+
const agent = read2(join17(root, agentPluginManifest));
|
|
50603
50638
|
if (agent !== null) {
|
|
50604
50639
|
const schema = JSON.parse(agent).$schema;
|
|
50605
50640
|
need5(typeof schema !== "string" || !schema.startsWith("https://agent-plugins.org/schemas/"));
|
|
50606
50641
|
}
|
|
50607
|
-
const
|
|
50608
|
-
const claude = read2(join17(root, ".claude-plugin/plugin.json"));
|
|
50609
|
-
const cursor = read2(join17(root, ".cursor-plugin/plugin.json"));
|
|
50610
|
-
const text2 = codex ?? claude ?? cursor;
|
|
50642
|
+
const text2 = legacyManifests.map((location) => read2(join17(root, location))).find((value) => value !== null) ?? null;
|
|
50611
50643
|
if (text2 === null)
|
|
50612
50644
|
continue;
|
|
50613
50645
|
const manifest = JSON.parse(text2);
|
|
@@ -50629,6 +50661,7 @@ var init_codex_hook_mcp_dependencies = __esm(() => {
|
|
|
50629
50661
|
init_claude_settings_witness();
|
|
50630
50662
|
init_agent_discovery_directories();
|
|
50631
50663
|
init_agent_discovery_bytes();
|
|
50664
|
+
init_codex_plugin_capability_paths();
|
|
50632
50665
|
events = new Set(["PreToolUse", "PermissionRequest", "PostToolUse", "PreCompact", "PostCompact", "SessionStart", "SessionEnd", "UserPromptSubmit", "SubagentStart", "SubagentStop", "Stop", "Interrupt"]);
|
|
50633
50666
|
});
|
|
50634
50667
|
|
|
@@ -52942,15 +52975,17 @@ function codexVendorConfigCandidates(text2, cache3, options = {}) {
|
|
|
52942
52975
|
var CODEX_VENDOR_MARKETPLACES, CODEX_REMOTE_VENDOR_MARKETPLACES, identifier3 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value), record4 = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value)), directory = (path) => {
|
|
52943
52976
|
const stat2 = lstatSync14(path, { throwIfNoEntry: false });
|
|
52944
52977
|
return Boolean(stat2?.isDirectory() && !stat2.isSymbolicLink());
|
|
52945
|
-
}, OTHER_PLUGIN_CONTROLS, VENDOR_MANIFEST_KEYS, DEFAULT_SKILLS_PATHS, VENDOR_APP_DECLARATION = "./.app.json", MAX_SUBTREE_ENTRIES = 20000, MAX_SUBTREE_DEPTH = 32, hiddenName = (name) => name.startsWith(".") || name === "node_modules", isSkillDocument
|
|
52978
|
+
}, OTHER_PLUGIN_CONTROLS, VENDOR_MANIFEST_KEYS, DEFAULT_SKILLS_PATHS, VENDOR_APP_DECLARATION = "./.app.json", MAX_SUBTREE_ENTRIES = 20000, MAX_SUBTREE_DEPTH = 32, hiddenName = (name) => name.startsWith(".") || name === "node_modules", isSkillDocument, present = (path) => lstatSync14(path, { throwIfNoEntry: false }) !== undefined, holdsOtherControl = (path) => readdirSync7(path).some((name) => OTHER_PLUGIN_CONTROLS.includes(codexPluginRootCapabilityEntry(name) ?? "")), MAX_TRAILING_VENDOR_ROWS = 16, MAX_VENDOR_TABLES = 8, MAX_CONFIG_CANDIDATES = 128, HEADER;
|
|
52946
52979
|
var init_codex_vendor_refresh = __esm(() => {
|
|
52947
52980
|
init_claude_settings_witness();
|
|
52948
52981
|
init_codex_plugin_skill_controls();
|
|
52982
|
+
init_codex_plugin_capability_paths();
|
|
52949
52983
|
CODEX_VENDOR_MARKETPLACES = Object.freeze(["openai-bundled", "openai-curated", "openai-curated-remote"]);
|
|
52950
52984
|
CODEX_REMOTE_VENDOR_MARKETPLACES = Object.freeze(["openai-curated-remote"]);
|
|
52951
|
-
OTHER_PLUGIN_CONTROLS = Object.freeze(
|
|
52985
|
+
OTHER_PLUGIN_CONTROLS = Object.freeze(CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES.filter((entry) => entry !== ".codex-plugin" && entry !== ".app.json"));
|
|
52952
52986
|
VENDOR_MANIFEST_KEYS = Object.freeze(["name", "version", "description", "author", "homepage", "repository", "license", "keywords", "interface", "skills", "apps"]);
|
|
52953
52987
|
DEFAULT_SKILLS_PATHS = Object.freeze(["./skills", "./skills/"]);
|
|
52988
|
+
isSkillDocument = isCodexSkillDocumentName;
|
|
52954
52989
|
HEADER = /^[ \t]*(\[\[|\[)[ \t]*([^[\]\r\n]+?)[ \t]*(\]\]|\])[ \t]*(?:#[^\r\n]*)?\r?\n?$/;
|
|
52955
52990
|
});
|
|
52956
52991
|
|
|
@@ -54056,6 +54091,10 @@ function skillsFileHasCredential(file) {
|
|
|
54056
54091
|
return false;
|
|
54057
54092
|
return /^\s*(?:export\s+)?(?:HASNA_SKILLS_API_KEY|SKILLS_API_KEY|HASNA_SKILLS_API_KEY_REF)\s*=\s*\S/m.test(text2);
|
|
54058
54093
|
}
|
|
54094
|
+
function skillsFileHasVaultReference(file) {
|
|
54095
|
+
const text2 = readMetadataText(file);
|
|
54096
|
+
return text2 !== null && /^\s*(?:export\s+)?HASNA_SKILLS_API_KEY_REF\s*=\s*\S/m.test(text2);
|
|
54097
|
+
}
|
|
54059
54098
|
var SKILLS_BOUND_API_URL = "HASNA_SKILLS_BOUND_API_URL";
|
|
54060
54099
|
var init_instance_credentials = __esm(() => {
|
|
54061
54100
|
init_transport();
|
|
@@ -54090,6 +54129,25 @@ var init_local_opt_in = __esm(() => {
|
|
|
54090
54129
|
// src/lib/product-default.ts
|
|
54091
54130
|
var SKILLS_PRODUCT_DEFAULT_ORIGIN = "https://skills.md";
|
|
54092
54131
|
|
|
54132
|
+
// src/lib/credential-profile-command.ts
|
|
54133
|
+
function skillsShellArgument(value) {
|
|
54134
|
+
return /^[A-Za-z0-9._:/-]+$/.test(value) ? value : `'${value.replace(/'/g, "'\\''")}'`;
|
|
54135
|
+
}
|
|
54136
|
+
function skillsApiUrlEnvironment(origin) {
|
|
54137
|
+
return urlKeys.map((name) => `${name}=${skillsShellArgument(origin)}`).join(" ");
|
|
54138
|
+
}
|
|
54139
|
+
function skillsProfileCommand(command, env3 = process.env, origin) {
|
|
54140
|
+
const profile = selectedSkillsProfile(env3);
|
|
54141
|
+
const prefix = origin && urlKeys.some((name) => env3[name]?.trim()) ? `${skillsApiUrlEnvironment(origin)} ` : "";
|
|
54142
|
+
return `${prefix}skills${profile ? ` --profile ${profile}` : ""} ${command}`;
|
|
54143
|
+
}
|
|
54144
|
+
var urlKeys;
|
|
54145
|
+
var init_credential_profile_command = __esm(() => {
|
|
54146
|
+
init_instance_credentials();
|
|
54147
|
+
init_transport();
|
|
54148
|
+
urlKeys = clientTransportEnvKeys("skills").apiUrlKeys;
|
|
54149
|
+
});
|
|
54150
|
+
|
|
54093
54151
|
// src/lib/fleet-credentials.ts
|
|
54094
54152
|
var exports_fleet_credentials = {};
|
|
54095
54153
|
__export(exports_fleet_credentials, {
|
|
@@ -54114,6 +54172,8 @@ __export(exports_fleet_credentials, {
|
|
|
54114
54172
|
gatewaySignInRefusal: () => gatewaySignInRefusal,
|
|
54115
54173
|
credentialPairing: () => credentialPairing,
|
|
54116
54174
|
configuredSkillsApiUrl: () => configuredSkillsApiUrl,
|
|
54175
|
+
captureSkillsSignInTarget: () => captureSkillsSignInTarget,
|
|
54176
|
+
assertSkillsSignInCredentialReplaceable: () => assertSkillsSignInCredentialReplaceable,
|
|
54117
54177
|
SkillsFleetCredentialError: () => SkillsFleetCredentialError,
|
|
54118
54178
|
SKILLS_LOCAL_OPT_IN_ENV_KEYS: () => SKILLS_LOCAL_OPT_IN_ENV_KEYS,
|
|
54119
54179
|
SKILLS_CREDENTIAL_TIERS: () => SKILLS_CREDENTIAL_TIERS,
|
|
@@ -54419,8 +54479,24 @@ function gatewaySignInRefusal(target) {
|
|
|
54419
54479
|
if (normalizeSkillsApiOrigin(target.origin) !== normalizeSkillsApiOrigin(defaultFleetGatewayBaseUrl(SKILLS_APP)))
|
|
54420
54480
|
return null;
|
|
54421
54481
|
const cause = target.credentialSource ? `${target.credentialSource} holds a Skills credential for the internal gateway` : target.source === "--url" ? "--url names the internal gateway" : `${target.source} selects the internal gateway`;
|
|
54422
|
-
const
|
|
54423
|
-
return new SkillsFleetCredentialError(`${cause}, which has no sign-in service. Nothing was sent
|
|
54482
|
+
const command = (SKILLS_API_URL_ENV_KEYS.includes(target.source) ? `${skillsApiUrlEnvironment(SKILLS_PRODUCT_DEFAULT_ORIGIN)} ` : "") + "skills --profile <new-profile> login";
|
|
54483
|
+
return new SkillsFleetCredentialError(`${cause}, which has no sign-in service. Nothing was sent. ` + `Keep the fleet configuration and use a separate profile for product sign-in: ${command}.`, "GATEWAY_AUTH_UNAVAILABLE", [command]);
|
|
54484
|
+
}
|
|
54485
|
+
function assertSkillsSignInCredentialReplaceable(env3 = process.env, profile) {
|
|
54486
|
+
const files = skillsProfileCredentialFiles(env3, profile);
|
|
54487
|
+
const verifyUnchanged = captureSkillsCredentialFiles(files);
|
|
54488
|
+
const gateway = normalizeSkillsApiOrigin(defaultFleetGatewayBaseUrl(SKILLS_APP));
|
|
54489
|
+
const command = (SKILLS_API_URL_ENV_KEYS.some((name) => env3[name]?.trim()) ? `${skillsApiUrlEnvironment(SKILLS_PRODUCT_DEFAULT_ORIGIN)} ` : "") + "skills --profile <new-profile> login";
|
|
54490
|
+
for (const file of files) {
|
|
54491
|
+
if (!skillsFileHasCredential(file))
|
|
54492
|
+
continue;
|
|
54493
|
+
const metadata = readSkillsInstanceMetadata(file);
|
|
54494
|
+
const instance = metadata.binding ?? metadata.apiUrl;
|
|
54495
|
+
if (skillsFileHasVaultReference(file) || !instance || normalizeSkillsApiOrigin(instance) === gateway) {
|
|
54496
|
+
throw new SkillsFleetCredentialError("The selected profile contains a protected fleet credential or vault reference. Nothing was sent or changed. " + `Use a separate profile for product sign-in: ${command}.`, "STORED_CREDENTIAL_PROTECTED", [command]);
|
|
54497
|
+
}
|
|
54498
|
+
}
|
|
54499
|
+
verifyUnchanged();
|
|
54424
54500
|
}
|
|
54425
54501
|
function explicitSignInOrigin(url) {
|
|
54426
54502
|
if (!url.trim() || /[\x00-\x1f\x7f]/.test(url)) {
|
|
@@ -54448,13 +54524,15 @@ function resolveSkillsSignInOrigin(env3 = process.env, options = {}, explicitUrl
|
|
|
54448
54524
|
const snapshot = snapshotSkillsEnvironment(env3);
|
|
54449
54525
|
const resolvedOptions = snapshotSkillsOptions(env3, options);
|
|
54450
54526
|
const profile = resolvedOptions.credentials?.profile;
|
|
54527
|
+
assertSkillsSignInCredentialReplaceable(snapshot, profile);
|
|
54451
54528
|
const configured = configuredSkillsApiUrl(snapshot, resolvedOptions.credentials?.keychain, profile);
|
|
54452
54529
|
const declared = configured && configured.source !== "default" ? configured : null;
|
|
54453
54530
|
if (explicitUrl !== undefined) {
|
|
54454
54531
|
const origin = explicitSignInOrigin(explicitUrl);
|
|
54455
54532
|
const storedHere = declared ? skillsProfileCredentialFiles(snapshot, profile).includes(declared.source) : false;
|
|
54456
54533
|
if (declared && !storedHere && normalizeSkillsApiOrigin(declared.value) !== origin) {
|
|
54457
|
-
|
|
54534
|
+
const command = `${skillsApiUrlEnvironment(origin)} skills --profile <new-profile> login`;
|
|
54535
|
+
throw new SkillsFleetCredentialError(`--url ${origin} conflicts with ${declared.source}, which outranks the saved configuration and would ` + `shadow the key this sign-in stores. Keep the existing configuration and use a separate process and profile: ${command}.`, "INVALID_API_URL", [command]);
|
|
54458
54536
|
}
|
|
54459
54537
|
return { origin, source: "--url" };
|
|
54460
54538
|
}
|
|
@@ -54486,6 +54564,14 @@ function resolveSkillsSignInOrigin(env3 = process.env, options = {}, explicitUrl
|
|
|
54486
54564
|
throw error;
|
|
54487
54565
|
}
|
|
54488
54566
|
}
|
|
54567
|
+
function captureSkillsSignInTarget(env3 = process.env, options = {}, explicitUrl) {
|
|
54568
|
+
const snapshot = snapshotSkillsEnvironment(env3);
|
|
54569
|
+
const profile = options.credentials?.profile ?? selectedCliSkillsCredentialProfile();
|
|
54570
|
+
const unchanged2 = captureSkillsCredentialFiles(skillsProfileCredentialFiles(snapshot, profile));
|
|
54571
|
+
const target = resolveSkillsSignInOrigin(env3, options, explicitUrl);
|
|
54572
|
+
unchanged2();
|
|
54573
|
+
return { ...target, unchanged: unchanged2 };
|
|
54574
|
+
}
|
|
54489
54575
|
function requireSkillsFleet(action = "This command", env3 = process.env, options = {}) {
|
|
54490
54576
|
const fleet = resolveSkillsFleet(env3, options);
|
|
54491
54577
|
if (fleet.mode === "hosted")
|
|
@@ -54497,6 +54583,7 @@ var init_fleet_credentials = __esm(() => {
|
|
|
54497
54583
|
init_transport();
|
|
54498
54584
|
init_instance_credentials();
|
|
54499
54585
|
init_local_opt_in();
|
|
54586
|
+
init_credential_profile_command();
|
|
54500
54587
|
init_local_opt_in();
|
|
54501
54588
|
ENV_KEYS = clientTransportEnvKeys(SKILLS_APP);
|
|
54502
54589
|
SKILLS_API_URL_ENV_KEYS = ENV_KEYS.apiUrlKeys;
|
|
@@ -56074,14 +56161,23 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
|
|
|
56074
56161
|
continue;
|
|
56075
56162
|
const parent = join28(cacheRoot, parts[0], parts[1]);
|
|
56076
56163
|
const root = join28(parent, parts[2]);
|
|
56077
|
-
const base2 = parts[parts.length - 1];
|
|
56078
|
-
if (parts.
|
|
56164
|
+
const base2 = parts[parts.length - 1], folded = foldCodexPluginEntryName(base2);
|
|
56165
|
+
if (parts.length === 3 && (codexPluginRootCapabilityEntry(base2) !== null || isCodexSkillDocumentName(base2)))
|
|
56166
|
+
refuse4();
|
|
56167
|
+
const rootEntry = parts.length >= 4 ? codexPluginRootCapabilityEntry(parts[3]) : null;
|
|
56168
|
+
if (rootEntry !== null && rootEntry !== parts[3])
|
|
56169
|
+
refuse4();
|
|
56170
|
+
if (rootEntry !== null && !SEMANTIC_BOUND_ROOT_ENTRIES.includes(rootEntry))
|
|
56079
56171
|
refuse4();
|
|
56080
|
-
if (
|
|
56172
|
+
if (isCodexSkillDocumentName(base2) && base2 !== "SKILL.md")
|
|
56081
56173
|
refuse4();
|
|
56082
|
-
if (
|
|
56174
|
+
if (parts.some((part) => CODEX_PLUGIN_MANIFEST_DIRECTORIES.includes(foldCodexPluginEntryName(part))) && (parts.length < 4 || parts[3] !== ".codex-plugin" || (parts.length === 4 ? base2 !== ".codex-plugin" : parts.length !== 5 || base2 !== "plugin.json")))
|
|
56083
56175
|
refuse4();
|
|
56084
|
-
if (
|
|
56176
|
+
if ([".app.json", ".mcp.json"].includes(folded) && (parts.length !== 4 || dirname18(member) !== root))
|
|
56177
|
+
refuse4();
|
|
56178
|
+
if ([".app.json", ".mcp.json"].includes(folded) && hookParents.some((reviewed) => reviewed.pluginParent === parent))
|
|
56179
|
+
refuse4();
|
|
56180
|
+
if ((rootEntry === "hooks" || folded === "hooks.json") && (![4, 5].includes(parts.length) || parts[3] !== "hooks" || (parts.length === 4 ? base2 !== "hooks" : base2 !== "hooks.json") || !hookParents.some((reviewed) => reviewed.pluginParent === join28(cacheRoot, parts[0], parts[1]))))
|
|
56085
56181
|
refuse4();
|
|
56086
56182
|
}
|
|
56087
56183
|
}
|
|
@@ -56303,13 +56399,15 @@ function assertCodexSemanticCacheWitnessUnchanged(previous, current) {
|
|
|
56303
56399
|
if (hash2(priorProjection) !== previous.sha256 || hash2(currentProjection) !== current.sha256 || canonical8(comparable(priorProjection)) !== canonical8(comparable(currentProjection)))
|
|
56304
56400
|
refuse4();
|
|
56305
56401
|
}
|
|
56306
|
-
var CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA = "hasna.codex-semantic-cache-witness.v1", identifier5 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value), digest = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), refuse4 = () => {
|
|
56402
|
+
var CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA = "hasna.codex-semantic-cache-witness.v1", SEMANTIC_BOUND_ROOT_ENTRIES, identifier5 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value), digest = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), refuse4 = () => {
|
|
56307
56403
|
throw new Error("CODEX_SEMANTIC_CACHE_WITNESS_UNSUPPORTED: review Codex plugin cache identity and controls");
|
|
56308
56404
|
}, MAX_DOCUMENT_BYTES, MAX_RECEIPT_BYTES, codexHookEvents;
|
|
56309
56405
|
var init_codex_semantic_cache_witness = __esm(() => {
|
|
56310
56406
|
init_claude_settings_witness();
|
|
56311
56407
|
init_codex_plugin_skill_controls();
|
|
56312
56408
|
init_codex_native_skill_catalog();
|
|
56409
|
+
init_codex_plugin_capability_paths();
|
|
56410
|
+
SEMANTIC_BOUND_ROOT_ENTRIES = Object.freeze([".codex-plugin", ".app.json", ".mcp.json", "hooks"]);
|
|
56313
56411
|
MAX_DOCUMENT_BYTES = 1024 * 1024;
|
|
56314
56412
|
MAX_RECEIPT_BYTES = 16 * 1024;
|
|
56315
56413
|
codexHookEvents = new Set([
|
|
@@ -66250,7 +66348,8 @@ function getAuthConfig(env3 = process.env, options = {}) {
|
|
|
66250
66348
|
return null;
|
|
66251
66349
|
return { apiKey: fleet.apiKey, ...readIdentity(env3) };
|
|
66252
66350
|
}
|
|
66253
|
-
function writeCredentialValues(values2, env3 = process.env) {
|
|
66351
|
+
function writeCredentialValues(values2, env3 = process.env, beforeWrite) {
|
|
66352
|
+
beforeWrite?.();
|
|
66254
66353
|
const file = skillsCredentialFilePath(env3);
|
|
66255
66354
|
mkdirSync14(dirname29(file), { recursive: true, mode: 448 });
|
|
66256
66355
|
const lines = [];
|
|
@@ -66279,9 +66378,16 @@ function writeCredentialValues(values2, env3 = process.env) {
|
|
|
66279
66378
|
`) + `
|
|
66280
66379
|
`;
|
|
66281
66380
|
const temp = `${file}.tmp-${process.pid}`;
|
|
66282
|
-
writeFileSync11(temp, body, { mode: 384 });
|
|
66283
|
-
|
|
66284
|
-
|
|
66381
|
+
writeFileSync11(temp, body, { mode: 384, flag: "wx" });
|
|
66382
|
+
try {
|
|
66383
|
+
chmodSync2(temp, 384);
|
|
66384
|
+
beforeWrite?.();
|
|
66385
|
+
renameSync8(temp, file);
|
|
66386
|
+
} finally {
|
|
66387
|
+
try {
|
|
66388
|
+
unlinkSync6(temp);
|
|
66389
|
+
} catch {}
|
|
66390
|
+
}
|
|
66285
66391
|
return file;
|
|
66286
66392
|
}
|
|
66287
66393
|
function readCredentialValue(key2, env3 = process.env) {
|
|
@@ -66325,7 +66431,14 @@ function safeOrigin(url) {
|
|
|
66325
66431
|
return null;
|
|
66326
66432
|
}
|
|
66327
66433
|
}
|
|
66328
|
-
function saveAuthConfig(config, env3 = process.env, authenticatedOrigin, issuedBy) {
|
|
66434
|
+
function saveAuthConfig(config, env3 = process.env, authenticatedOrigin, issuedBy, assertUnchanged) {
|
|
66435
|
+
const unchanged3 = assertUnchanged ?? captureSkillsCredentialFiles(skillsProfileCredentialFiles(env3));
|
|
66436
|
+
const beforeWrite = () => {
|
|
66437
|
+
unchanged3();
|
|
66438
|
+
if (issuedBy)
|
|
66439
|
+
assertSkillsSignInCredentialReplaceable(env3);
|
|
66440
|
+
};
|
|
66441
|
+
beforeWrite();
|
|
66329
66442
|
const apiKey = config.apiKey.trim();
|
|
66330
66443
|
if (!apiKey)
|
|
66331
66444
|
throw new Error("Refusing to store an empty Skills API key.");
|
|
@@ -66337,7 +66450,7 @@ function saveAuthConfig(config, env3 = process.env, authenticatedOrigin, issuedB
|
|
|
66337
66450
|
const previous = readIdentityRecord(env3);
|
|
66338
66451
|
const loginWroteBefore = previous?.urlWrittenBy === "login" && typeof previous.apiUrl === "string" && safeOrigin(previous.apiUrl) === apiUrl;
|
|
66339
66452
|
const urlWrittenByLogin = issuedBy !== undefined && (!previousUrl || safeOrigin(previousUrl) !== apiUrl || loginWroteBefore);
|
|
66340
|
-
const file = writeCredentialValues({ SKILLS_API_KEY: null, SKILLS_API_URL: null, [SKILLS_API_KEY_REF]: null, [SKILLS_API_KEY_ENV]: apiKey, [SKILLS_BOUND_API_URL]: apiUrl, [SKILLS_API_URL_ENV]: apiUrl }, env3);
|
|
66453
|
+
const file = writeCredentialValues({ SKILLS_API_KEY: null, SKILLS_API_URL: null, [SKILLS_API_KEY_REF]: null, [SKILLS_API_KEY_ENV]: apiKey, [SKILLS_BOUND_API_URL]: apiUrl, [SKILLS_API_URL_ENV]: apiUrl }, env3, beforeWrite);
|
|
66341
66454
|
const identity6 = {};
|
|
66342
66455
|
for (const field3 of ["email", "orgId", "orgSlug", "userId"]) {
|
|
66343
66456
|
const value = config[field3];
|
|
@@ -88497,7 +88610,10 @@ function clearPendingDeviceSignIn(env3 = process.env, origin) {
|
|
|
88497
88610
|
}
|
|
88498
88611
|
}
|
|
88499
88612
|
}
|
|
88500
|
-
async function persistSignIn(result2, origin, env3 = process.env, issuedBy = "sign-in") {
|
|
88613
|
+
async function persistSignIn(result2, origin, env3 = process.env, issuedBy = "sign-in", assertUnchanged) {
|
|
88614
|
+
const unchanged3 = assertUnchanged ?? captureSkillsCredentialFiles(skillsProfileCredentialFiles(env3));
|
|
88615
|
+
unchanged3();
|
|
88616
|
+
assertSkillsSignInCredentialReplaceable(env3);
|
|
88501
88617
|
let apiKey = typeof result2.apiKey === "string" && result2.apiKey.trim() ? result2.apiKey : undefined;
|
|
88502
88618
|
if (!apiKey && typeof result2.token === "string" && result2.token) {
|
|
88503
88619
|
const created = await new RemoteSkillsAuthClient(origin).request("/api/auth/keys", {
|
|
@@ -88515,7 +88631,7 @@ async function persistSignIn(result2, origin, env3 = process.env, issuedBy = "si
|
|
|
88515
88631
|
...boundedText(result2.organization?.id) ? { orgId: result2.organization.id } : {},
|
|
88516
88632
|
...boundedText(result2.organization?.slug) ? { orgSlug: result2.organization.slug } : {},
|
|
88517
88633
|
...boundedText(result2.user?.id) ? { userId: result2.user.id } : {}
|
|
88518
|
-
}, env3, origin, issuedBy);
|
|
88634
|
+
}, env3, origin, issuedBy, unchanged3);
|
|
88519
88635
|
}
|
|
88520
88636
|
function manualRevocationHint(origin) {
|
|
88521
88637
|
if (origin === SKILLS_PRODUCT_DEFAULT_ORIGIN) {
|
|
@@ -111493,6 +111609,7 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
|
|
|
111493
111609
|
const env3 = { ...source }, profile = selectedSkillsProfile(env3);
|
|
111494
111610
|
if (!profile)
|
|
111495
111611
|
return fail4("Workspace login requires an explicit HASNA_PROFILE name.");
|
|
111612
|
+
assertSkillsSignInCredentialReplaceable(env3);
|
|
111496
111613
|
if (["HASNA_SKILLS_API_KEY_OVERRIDE", "HASNA_SKILLS_API_KEY_REF", "HASNA_SKILLS_API_KEY", "SKILLS_API_KEY"].some((name) => env3[name]?.trim()))
|
|
111497
111614
|
return fail4("Clear injected API keys before enrolling a named workspace profile.");
|
|
111498
111615
|
const origin = getApiUrl("Sign in to a workspace", env3);
|
|
@@ -124513,6 +124630,14 @@ async function codeFor(client2, options) {
|
|
|
124513
124630
|
return promptCode();
|
|
124514
124631
|
}
|
|
124515
124632
|
function errorResult(error61, json3) {
|
|
124633
|
+
if (error61 instanceof SkillsFleetCredentialError) {
|
|
124634
|
+
if (json3)
|
|
124635
|
+
console.log(JSON.stringify({ error: error61.message, code: error61.code, next: error61.next }));
|
|
124636
|
+
else
|
|
124637
|
+
console.error(error61.message);
|
|
124638
|
+
process.exitCode = 1;
|
|
124639
|
+
return;
|
|
124640
|
+
}
|
|
124516
124641
|
const message = error61 instanceof NameInputError || error61 instanceof WorkspaceProfileError ? error61.message : "Unable to complete workspace sign-in. Check the selected server, profile, account and fresh verification code.";
|
|
124517
124642
|
if (json3)
|
|
124518
124643
|
console.log(JSON.stringify({ error: message }));
|
|
@@ -124566,6 +124691,7 @@ One workspace key saved. Use HASNA_PROFILE=${result2.profile} for subsequent com
|
|
|
124566
124691
|
}
|
|
124567
124692
|
var init_workspace_selection = __esm(() => {
|
|
124568
124693
|
init_auth_store();
|
|
124694
|
+
init_fleet_credentials();
|
|
124569
124695
|
init_remote_auth();
|
|
124570
124696
|
init_workspace_profile();
|
|
124571
124697
|
init_customer_verification();
|
|
@@ -124711,7 +124837,7 @@ function printWhoami(payload) {
|
|
|
124711
124837
|
}
|
|
124712
124838
|
function signInTarget(url2, json3) {
|
|
124713
124839
|
try {
|
|
124714
|
-
const target =
|
|
124840
|
+
const target = captureSkillsSignInTarget(process.env, {}, url2);
|
|
124715
124841
|
const refusal3 = gatewaySignInRefusal(target);
|
|
124716
124842
|
if (refusal3)
|
|
124717
124843
|
throw refusal3;
|
|
@@ -124722,7 +124848,10 @@ function signInTarget(url2, json3) {
|
|
|
124722
124848
|
}
|
|
124723
124849
|
}
|
|
124724
124850
|
function targetFlag(target) {
|
|
124725
|
-
return target.source === "--url" ? ` --url ${target.origin}` : "";
|
|
124851
|
+
return target.source === "--url" ? ` --url ${skillsShellArgument(target.origin)}` : "";
|
|
124852
|
+
}
|
|
124853
|
+
function skillsCommand(command, target) {
|
|
124854
|
+
return skillsProfileCommand(command, process.env, target.origin);
|
|
124726
124855
|
}
|
|
124727
124856
|
async function finishSignIn(result2, target, json3) {
|
|
124728
124857
|
const email5 = result2.user?.email;
|
|
@@ -124734,7 +124863,7 @@ async function finishSignIn(result2, target, json3) {
|
|
|
124734
124863
|
...organization2 ? { organization: organization2 } : {},
|
|
124735
124864
|
...result2.firstLogin !== undefined ? { firstLogin: result2.firstLogin } : {},
|
|
124736
124865
|
apiUrl: target.origin,
|
|
124737
|
-
next: ["
|
|
124866
|
+
next: [skillsCommand("setup agents", target)]
|
|
124738
124867
|
}));
|
|
124739
124868
|
return;
|
|
124740
124869
|
}
|
|
@@ -124744,20 +124873,20 @@ async function finishSignIn(result2, target, json3) {
|
|
|
124744
124873
|
console.log(source_default.dim(` Organization: ${result2.organization.name}`));
|
|
124745
124874
|
console.log(source_default.dim(` Server: ${target.origin}`));
|
|
124746
124875
|
console.log(source_default.dim(` API key saved to ${getAuthFilePath()}`));
|
|
124747
|
-
await offerAgentSetup();
|
|
124876
|
+
await offerAgentSetup(target);
|
|
124748
124877
|
}
|
|
124749
|
-
async function offerAgentSetup() {
|
|
124878
|
+
async function offerAgentSetup(target) {
|
|
124750
124879
|
const before2 = process.exitCode;
|
|
124751
124880
|
const answer = await prompt(`
|
|
124752
|
-
Register Skills with your coding agents now (
|
|
124881
|
+
Register Skills with your coding agents now (${skillsCommand("setup agents", target)})? [Y/n] `);
|
|
124753
124882
|
if (answer === null) {
|
|
124754
124883
|
process.exitCode = before2 ?? 0;
|
|
124755
124884
|
console.log(source_default.dim(`
|
|
124756
|
-
Skipped. Run it any time:
|
|
124885
|
+
Skipped. Run it any time: ${skillsCommand("setup agents", target)}`));
|
|
124757
124886
|
return;
|
|
124758
124887
|
}
|
|
124759
124888
|
if (answer !== "" && !/^y(es)?$/i.test(answer)) {
|
|
124760
|
-
console.log(source_default.dim(
|
|
124889
|
+
console.log(source_default.dim(`Skipped. Run it any time: ${skillsCommand("setup agents", target)}`));
|
|
124761
124890
|
return;
|
|
124762
124891
|
}
|
|
124763
124892
|
const { handleMcp: handleMcp2 } = await Promise.resolve().then(() => (init_runtime_mcp(), exports_runtime_mcp));
|
|
@@ -124834,7 +124963,7 @@ async function doLogin(email5, code2, json3, target) {
|
|
|
124834
124963
|
if (!json3)
|
|
124835
124964
|
console.log(source_default.green("\u2713 Code sent to " + email5));
|
|
124836
124965
|
if (json3 || !isTTY || !process.stderr.isTTY) {
|
|
124837
|
-
console.log(JSON.stringify({ status: "code_sent", email: email5, message: `Supply the fresh six-digit code on stdin to:
|
|
124966
|
+
console.log(JSON.stringify({ status: "code_sent", email: email5, message: `Supply the fresh six-digit code on stdin to: ${skillsCommand("login", target)} --email ${skillsShellArgument(email5)} --code-stdin${targetFlag(target)}` }));
|
|
124838
124967
|
return;
|
|
124839
124968
|
}
|
|
124840
124969
|
const answer = await promptCode();
|
|
@@ -124844,6 +124973,7 @@ async function doLogin(email5, code2, json3, target) {
|
|
|
124844
124973
|
}
|
|
124845
124974
|
let verifyRes;
|
|
124846
124975
|
try {
|
|
124976
|
+
target.unchanged?.();
|
|
124847
124977
|
verifyRes = await apiRequest("/api/auth/verify", {
|
|
124848
124978
|
method: "POST",
|
|
124849
124979
|
body: JSON.stringify({ email: email5, code: code2 })
|
|
@@ -124857,7 +124987,7 @@ async function doLogin(email5, code2, json3, target) {
|
|
|
124857
124987
|
return;
|
|
124858
124988
|
}
|
|
124859
124989
|
try {
|
|
124860
|
-
await persistSignIn(verifyRes, origin, env3, "sign-in");
|
|
124990
|
+
await persistSignIn(verifyRes, origin, env3, "sign-in", target.unchanged);
|
|
124861
124991
|
} catch (err) {
|
|
124862
124992
|
writeCommandError(err, "Login succeeded but API key creation failed", json3);
|
|
124863
124993
|
return;
|
|
@@ -124886,6 +125016,7 @@ async function doApiKeyLogin(apiKey, json3, target) {
|
|
|
124886
125016
|
}
|
|
124887
125017
|
let whoami;
|
|
124888
125018
|
try {
|
|
125019
|
+
target.unchanged?.();
|
|
124889
125020
|
whoami = await apiRequest("/api/auth/whoami", {
|
|
124890
125021
|
headers: { Authorization: `Bearer ${trimmed}` }
|
|
124891
125022
|
}, origin);
|
|
@@ -124898,20 +125029,25 @@ async function doApiKeyLogin(apiKey, json3, target) {
|
|
|
124898
125029
|
const orgId = stringField2(identity6.orgId);
|
|
124899
125030
|
const orgSlug = stringField2(identity6.organization);
|
|
124900
125031
|
const userId = stringField2(identity6.userId);
|
|
124901
|
-
|
|
124902
|
-
|
|
124903
|
-
|
|
124904
|
-
|
|
124905
|
-
|
|
124906
|
-
|
|
124907
|
-
|
|
125032
|
+
try {
|
|
125033
|
+
saveAuthConfig({
|
|
125034
|
+
apiKey: trimmed,
|
|
125035
|
+
...email5 ? { email: email5 } : {},
|
|
125036
|
+
...orgId ? { orgId } : {},
|
|
125037
|
+
...orgSlug ? { orgSlug } : {},
|
|
125038
|
+
...userId ? { userId } : {}
|
|
125039
|
+
}, env3, origin, "api-key", target.unchanged);
|
|
125040
|
+
} catch (error61) {
|
|
125041
|
+
writeCommandError(error61, "API key verified but the selected profile changed", json3);
|
|
125042
|
+
return;
|
|
125043
|
+
}
|
|
124908
125044
|
if (json3 || !isTTY) {
|
|
124909
|
-
console.log(JSON.stringify({ ...identity6, status: "authenticated", apiUrl: origin, next: ["
|
|
125045
|
+
console.log(JSON.stringify({ ...identity6, status: "authenticated", apiUrl: origin, next: [skillsCommand("setup agents", target)] }, null, 2));
|
|
124910
125046
|
return;
|
|
124911
125047
|
}
|
|
124912
125048
|
printWhoami(identity6);
|
|
124913
125049
|
console.log(source_default.dim(`Server: ${origin}`));
|
|
124914
|
-
await offerAgentSetup();
|
|
125050
|
+
await offerAgentSetup(target);
|
|
124915
125051
|
}
|
|
124916
125052
|
function printDeviceCode(session, resumed, write) {
|
|
124917
125053
|
write(source_default.bold(resumed ? `
|
|
@@ -124932,12 +125068,12 @@ async function doDeviceLogin(options, target) {
|
|
|
124932
125068
|
const origin = target.origin;
|
|
124933
125069
|
const json3 = Boolean(options.json);
|
|
124934
125070
|
const interactive = Boolean(isTTY && !json3);
|
|
124935
|
-
const next =
|
|
125071
|
+
const next = `${skillsCommand("login", target)} --poll${targetFlag(target)}`;
|
|
124936
125072
|
let session = options.poll ? loadPendingDeviceSignIn(origin, env3) : null;
|
|
124937
125073
|
if (options.poll && !session) {
|
|
124938
125074
|
const others = pendingDeviceSignInOrigins(env3).filter((other) => other !== origin);
|
|
124939
125075
|
if (others.length > 0) {
|
|
124940
|
-
writeCommandError(new Error(`No pending sign-in for ${origin}. Pending: ${others.map((other) =>
|
|
125076
|
+
writeCommandError(new Error(`No pending sign-in for ${origin}. Pending: ${others.map((other) => `${skillsProfileCommand("login", process.env, other)} --poll --url ${skillsShellArgument(other)}`).join("; ")}`), "No pending sign-in", json3);
|
|
124941
125077
|
return;
|
|
124942
125078
|
}
|
|
124943
125079
|
}
|
|
@@ -124988,7 +125124,10 @@ Waiting for authentication...`));
|
|
|
124988
125124
|
try {
|
|
124989
125125
|
const deviceCode = session.deviceCode;
|
|
124990
125126
|
outcome = await pollDeviceAuthorization({
|
|
124991
|
-
poll: () =>
|
|
125127
|
+
poll: () => {
|
|
125128
|
+
target.unchanged?.();
|
|
125129
|
+
return pollDeviceToken(origin, deviceCode);
|
|
125130
|
+
},
|
|
124992
125131
|
intervalSeconds: session.interval,
|
|
124993
125132
|
deadline: Math.min(Date.now() + timeoutMs, session.expiresAt),
|
|
124994
125133
|
onSlowDown: (intervalMs) => {
|
|
@@ -125002,8 +125141,8 @@ Waiting for authentication...`));
|
|
|
125002
125141
|
}
|
|
125003
125142
|
if (outcome.status !== "authorized") {
|
|
125004
125143
|
const ended = {
|
|
125005
|
-
expired:
|
|
125006
|
-
invalid:
|
|
125144
|
+
expired: `The sign-in code expired before it was approved. Start again: ${skillsCommand("login", target)}${targetFlag(target)}`,
|
|
125145
|
+
invalid: `The server no longer recognises this sign-in code. Start again: ${skillsCommand("login", target)}${targetFlag(target)}`,
|
|
125007
125146
|
denied: "Sign-in was denied in the browser.",
|
|
125008
125147
|
timeout: `Device login timed out before browser authentication completed. Resume with: ${next}`,
|
|
125009
125148
|
cancelled: "Sign-in cancelled."
|
|
@@ -125019,7 +125158,7 @@ Waiting for authentication...`));
|
|
|
125019
125158
|
return;
|
|
125020
125159
|
}
|
|
125021
125160
|
try {
|
|
125022
|
-
await persistSignIn(outcome.result, origin, env3, "sign-in");
|
|
125161
|
+
await persistSignIn(outcome.result, origin, env3, "sign-in", target.unchanged);
|
|
125023
125162
|
} catch (err) {
|
|
125024
125163
|
writeCommandError(err, "Login succeeded but API key creation failed", json3);
|
|
125025
125164
|
return;
|
|
@@ -125271,6 +125410,7 @@ var init_auth = __esm(() => {
|
|
|
125271
125410
|
init_auth_store();
|
|
125272
125411
|
init_fleet_credentials();
|
|
125273
125412
|
init_remote_client();
|
|
125413
|
+
init_credential_profile_command();
|
|
125274
125414
|
init_sign_in();
|
|
125275
125415
|
init_remote_auth();
|
|
125276
125416
|
isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
@@ -133962,6 +134102,7 @@ function InstallProgress({
|
|
|
133962
134102
|
// src/cli/components/AccountView.tsx
|
|
133963
134103
|
var import_react29 = __toESM(require_react(), 1);
|
|
133964
134104
|
init_fleet_credentials();
|
|
134105
|
+
init_credential_profile_command();
|
|
133965
134106
|
init_sign_in();
|
|
133966
134107
|
var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
|
|
133967
134108
|
var SLASH_COMMANDS = [
|
|
@@ -134021,7 +134162,7 @@ function AccountView({ action, argument, onDone }) {
|
|
|
134021
134162
|
});
|
|
134022
134163
|
return;
|
|
134023
134164
|
}
|
|
134024
|
-
const target =
|
|
134165
|
+
const target = captureSkillsSignInTarget(process.env, {}, argument);
|
|
134025
134166
|
const refusal3 = gatewaySignInRefusal(target);
|
|
134026
134167
|
if (refusal3)
|
|
134027
134168
|
throw refusal3;
|
|
@@ -134032,13 +134173,16 @@ function AccountView({ action, argument, onDone }) {
|
|
|
134032
134173
|
update2({ kind: "waiting", userCode: start.userCode, url: url2, origin: target.origin });
|
|
134033
134174
|
openVerificationPage(url2, target.origin);
|
|
134034
134175
|
const outcome = await pollDeviceAuthorization({
|
|
134035
|
-
poll: () =>
|
|
134176
|
+
poll: () => {
|
|
134177
|
+
target.unchanged?.();
|
|
134178
|
+
return pollDeviceToken(target.origin, start.deviceCode);
|
|
134179
|
+
},
|
|
134036
134180
|
intervalSeconds: start.interval,
|
|
134037
134181
|
deadline: Date.now() + start.expiresIn * 1000,
|
|
134038
134182
|
signal: controller.signal
|
|
134039
134183
|
});
|
|
134040
134184
|
if (outcome.status === "authorized") {
|
|
134041
|
-
await persistSignIn(outcome.result, target.origin);
|
|
134185
|
+
await persistSignIn(outcome.result, target.origin, process.env, "sign-in", target.unchanged);
|
|
134042
134186
|
const email4 = outcome.result.user?.email;
|
|
134043
134187
|
update2({
|
|
134044
134188
|
kind: "done",
|
|
@@ -134046,16 +134190,17 @@ function AccountView({ action, argument, onDone }) {
|
|
|
134046
134190
|
lines: [
|
|
134047
134191
|
{ text: email4 ? `Signed in as ${email4}` : "Signed in", tone: "good" },
|
|
134048
134192
|
{ text: `Server: ${target.origin}`, tone: "dim" },
|
|
134049
|
-
{ text:
|
|
134193
|
+
{ text: `Register Skills with your agents from a shell: ${skillsProfileCommand("setup agents", process.env, target.origin)}`, tone: "dim" }
|
|
134050
134194
|
]
|
|
134051
134195
|
});
|
|
134052
134196
|
return;
|
|
134053
134197
|
}
|
|
134198
|
+
const retry = argument !== undefined ? `/login ${target.origin}` : "/login";
|
|
134054
134199
|
const ended = {
|
|
134055
|
-
expired:
|
|
134056
|
-
invalid:
|
|
134200
|
+
expired: `The sign-in code expired before it was approved. Type ${retry} to start again.`,
|
|
134201
|
+
invalid: `The server no longer recognises this sign-in code. Type ${retry} to start again.`,
|
|
134057
134202
|
denied: "Sign-in was denied in the browser.",
|
|
134058
|
-
timeout:
|
|
134203
|
+
timeout: `Sign-in timed out. Type ${retry} to start again.`,
|
|
134059
134204
|
cancelled: "Sign-in cancelled."
|
|
134060
134205
|
}[outcome.status];
|
|
134061
134206
|
update2({ kind: "done", changed: false, lines: [{ text: ended, tone: "bad" }] });
|