@scheduler-systems/gal-run 0.0.264 → 0.0.266
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/index.cjs +720 -76
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3970,7 +3970,7 @@ var cliVersion, defaultApiUrl, BUILD_CONSTANTS, constants_default;
|
|
|
3970
3970
|
var init_constants = __esm({
|
|
3971
3971
|
"src/constants.ts"() {
|
|
3972
3972
|
"use strict";
|
|
3973
|
-
cliVersion = true ? "0.0.
|
|
3973
|
+
cliVersion = true ? "0.0.266" : "0.0.0-dev";
|
|
3974
3974
|
defaultApiUrl = true ? "https://api.gal.run" : "http://localhost:3000";
|
|
3975
3975
|
BUILD_CONSTANTS = Object.freeze([cliVersion, defaultApiUrl]);
|
|
3976
3976
|
constants_default = BUILD_CONSTANTS;
|
|
@@ -4812,7 +4812,7 @@ function detectEnvironment() {
|
|
|
4812
4812
|
return "dev";
|
|
4813
4813
|
}
|
|
4814
4814
|
try {
|
|
4815
|
-
const version = true ? "0.0.
|
|
4815
|
+
const version = true ? "0.0.266" : void 0;
|
|
4816
4816
|
if (version && version.includes("-local")) {
|
|
4817
4817
|
return "dev";
|
|
4818
4818
|
}
|
|
@@ -5181,7 +5181,7 @@ function getId() {
|
|
|
5181
5181
|
}
|
|
5182
5182
|
function getCliVersion() {
|
|
5183
5183
|
try {
|
|
5184
|
-
return true ? "0.0.
|
|
5184
|
+
return true ? "0.0.266" : "0.0.0-dev";
|
|
5185
5185
|
} catch {
|
|
5186
5186
|
return "0.0.0-dev";
|
|
5187
5187
|
}
|
|
@@ -7731,7 +7731,7 @@ var init_feature_flags2 = __esm({
|
|
|
7731
7731
|
init_src();
|
|
7732
7732
|
COMMAND_CATEGORIES = {
|
|
7733
7733
|
// Core convenience package (always visible)
|
|
7734
|
-
core: ["auth", "sync", "mcp", "feedback", "update", "hooks", "status", "discover", "approve", "propose", "workspace", "fetch", "join", "scan", "memory"],
|
|
7734
|
+
core: ["auth", "sync", "mcp", "feedback", "update", "hooks", "status", "discover", "approve", "approved-config", "propose", "workspace", "fetch", "join", "scan", "memory"],
|
|
7735
7735
|
// Internal development commands (requires admin org membership or GAL_INTERNAL=true)
|
|
7736
7736
|
internal: [
|
|
7737
7737
|
"admin",
|
|
@@ -20802,56 +20802,6 @@ var init_agent = __esm({
|
|
|
20802
20802
|
}
|
|
20803
20803
|
});
|
|
20804
20804
|
|
|
20805
|
-
// src/utils/capability-checker.ts
|
|
20806
|
-
async function checkOrgCapability(authRepo, orgName, requiredCapability, commandName) {
|
|
20807
|
-
try {
|
|
20808
|
-
const context = await authRepo.getUserContext();
|
|
20809
|
-
const org = context.orgs.find((o) => o.name === orgName);
|
|
20810
|
-
if (!org) {
|
|
20811
|
-
console.error(source_default.red(`You don't have access to organization "${orgName}"`));
|
|
20812
|
-
console.log(source_default.dim("\nAvailable organizations:"));
|
|
20813
|
-
if (context.orgs.length === 0) {
|
|
20814
|
-
console.log(source_default.dim(" (none)"));
|
|
20815
|
-
console.log(source_default.dim("\nMake sure you have joined the organization on GitHub."));
|
|
20816
|
-
} else {
|
|
20817
|
-
context.orgs.forEach((o) => {
|
|
20818
|
-
console.log(source_default.dim(` - ${o.name} (${o.githubRole})`));
|
|
20819
|
-
});
|
|
20820
|
-
}
|
|
20821
|
-
return false;
|
|
20822
|
-
}
|
|
20823
|
-
if (!org.capabilities[requiredCapability]) {
|
|
20824
|
-
const capabilityMessages = {
|
|
20825
|
-
canManageApprovedConfig: `manage approved configs for ${orgName}`,
|
|
20826
|
-
canRunDiscovery: `run discovery scans for ${orgName}`,
|
|
20827
|
-
canManageTeam: `manage team members for ${orgName}`,
|
|
20828
|
-
canSyncConfig: `sync configs from ${orgName}`
|
|
20829
|
-
};
|
|
20830
|
-
console.error(source_default.red(`You don't have permission to ${capabilityMessages[requiredCapability]}`));
|
|
20831
|
-
console.log(source_default.dim(`
|
|
20832
|
-
Your role in ${orgName}: ${source_default.white(org.githubRole)}`));
|
|
20833
|
-
console.log(source_default.dim("Required role: admin"));
|
|
20834
|
-
console.log(source_default.dim("\nContact your organization admin to grant you admin access on GitHub."));
|
|
20835
|
-
return false;
|
|
20836
|
-
}
|
|
20837
|
-
return true;
|
|
20838
|
-
} catch (error2) {
|
|
20839
|
-
if ((error2 instanceof Error ? error2.message : "").includes("401") || (error2 instanceof Error ? error2.message : "").includes("Unauthorized")) {
|
|
20840
|
-
console.error(source_default.red("Authentication failed. Please log in again:"));
|
|
20841
|
-
console.log(source_default.dim(" gal auth login"));
|
|
20842
|
-
} else {
|
|
20843
|
-
console.error(source_default.red(`Failed to check permissions: ${error2 instanceof Error ? error2.message : String(error2)}`));
|
|
20844
|
-
}
|
|
20845
|
-
return false;
|
|
20846
|
-
}
|
|
20847
|
-
}
|
|
20848
|
-
var init_capability_checker = __esm({
|
|
20849
|
-
"src/utils/capability-checker.ts"() {
|
|
20850
|
-
"use strict";
|
|
20851
|
-
init_source();
|
|
20852
|
-
}
|
|
20853
|
-
});
|
|
20854
|
-
|
|
20855
20805
|
// src/services/CoreServiceProvider.ts
|
|
20856
20806
|
var CoreServiceProvider;
|
|
20857
20807
|
var init_CoreServiceProvider = __esm({
|
|
@@ -21075,6 +21025,378 @@ var init_CoreServiceProvider = __esm({
|
|
|
21075
21025
|
}
|
|
21076
21026
|
});
|
|
21077
21027
|
|
|
21028
|
+
// src/commands/approved-config.ts
|
|
21029
|
+
function makeProvider(config) {
|
|
21030
|
+
return new CoreServiceProvider({
|
|
21031
|
+
apiUrl: config.apiUrl || process.env.GAL_API_URL || "",
|
|
21032
|
+
authToken: config.authToken
|
|
21033
|
+
});
|
|
21034
|
+
}
|
|
21035
|
+
function resolveOrg(options, config) {
|
|
21036
|
+
const org = options.org || config.defaultOrg;
|
|
21037
|
+
if (!org) {
|
|
21038
|
+
console.error(source_default.red("No organization specified."));
|
|
21039
|
+
console.error(source_default.dim("Use --org <name> or run `gal workspace use <name>` to set a default."));
|
|
21040
|
+
process.exit(1);
|
|
21041
|
+
}
|
|
21042
|
+
return org;
|
|
21043
|
+
}
|
|
21044
|
+
function printApprovedConfig(config, org) {
|
|
21045
|
+
console.log();
|
|
21046
|
+
console.log(source_default.bold(`Approved config for "${org}" (${config.platform})`));
|
|
21047
|
+
console.log(source_default.dim(` Version: ${config.version || "unknown"}`));
|
|
21048
|
+
console.log(source_default.dim(` Approved at: ${config.approvedAt || "unknown"}`));
|
|
21049
|
+
console.log(source_default.dim(` Approved by: ${config.approvedBy || "unknown"}`));
|
|
21050
|
+
console.log(source_default.dim(` Hash: ${config.hash || "unknown"}`));
|
|
21051
|
+
if (config.policyName) {
|
|
21052
|
+
console.log(source_default.dim(` Policy: ${config.policyName}`));
|
|
21053
|
+
}
|
|
21054
|
+
console.log();
|
|
21055
|
+
const commandCount = config.commandCount ?? config.commands?.length ?? 0;
|
|
21056
|
+
const subagentCount = config.subagentCount ?? config.subagents?.length ?? 0;
|
|
21057
|
+
const skillCount = config.skillCount ?? config.skills?.length ?? 0;
|
|
21058
|
+
const ruleCount = config.ruleCount ?? config.rules?.length ?? 0;
|
|
21059
|
+
console.log(source_default.bold(" Contents:"));
|
|
21060
|
+
console.log(` Commands: ${commandCount}`);
|
|
21061
|
+
console.log(` Agents: ${subagentCount}`);
|
|
21062
|
+
console.log(` Skills: ${skillCount}`);
|
|
21063
|
+
console.log(` Rules: ${ruleCount}`);
|
|
21064
|
+
console.log(` Instructions: ${config.instructions ? "yes" : "no"}`);
|
|
21065
|
+
console.log(` Settings: ${config.settings ? "yes" : "no"}`);
|
|
21066
|
+
if (commandCount > 0 && config.commands) {
|
|
21067
|
+
console.log();
|
|
21068
|
+
console.log(source_default.bold(" Commands:"));
|
|
21069
|
+
config.commands.forEach((c) => console.log(` /${c.name}`));
|
|
21070
|
+
}
|
|
21071
|
+
if (subagentCount > 0 && config.subagents) {
|
|
21072
|
+
console.log();
|
|
21073
|
+
console.log(source_default.bold(" Agents:"));
|
|
21074
|
+
config.subagents.forEach((s) => console.log(` ${s.name}`));
|
|
21075
|
+
}
|
|
21076
|
+
if (skillCount > 0 && config.skills) {
|
|
21077
|
+
console.log();
|
|
21078
|
+
console.log(source_default.bold(" Skills:"));
|
|
21079
|
+
config.skills.forEach((s) => console.log(` ${s.name}`));
|
|
21080
|
+
}
|
|
21081
|
+
if (ruleCount > 0 && config.rules) {
|
|
21082
|
+
console.log();
|
|
21083
|
+
console.log(source_default.bold(" Rules:"));
|
|
21084
|
+
config.rules.forEach((r) => console.log(` ${r.name}`));
|
|
21085
|
+
}
|
|
21086
|
+
console.log();
|
|
21087
|
+
}
|
|
21088
|
+
function createApprovedConfigCommand() {
|
|
21089
|
+
const command = new Command("approved-config");
|
|
21090
|
+
command.description("View and manage the org-approved AI agent configuration");
|
|
21091
|
+
command.command("show").description("Show the current approved configuration for an organization").option("-o, --org <name>", "Organization name (default: from config)").option("-p, --platform <platform>", "Platform (default: claude)", "claude").option("--json", "Output as JSON").action(async (options) => {
|
|
21092
|
+
const config = ConfigManager.load();
|
|
21093
|
+
if (!config.authToken) {
|
|
21094
|
+
console.error(source_default.red("Not authenticated. Run: gal auth login"));
|
|
21095
|
+
process.exit(1);
|
|
21096
|
+
}
|
|
21097
|
+
const org = resolveOrg(options, config);
|
|
21098
|
+
const provider = makeProvider(config);
|
|
21099
|
+
const configRepo = provider.getConfigRepository();
|
|
21100
|
+
const spinner = options.json ? null : ora(`Fetching approved config for "${org}"...`).start();
|
|
21101
|
+
try {
|
|
21102
|
+
const approved = await configRepo.getApprovedConfig(org, options.platform);
|
|
21103
|
+
spinner?.stop();
|
|
21104
|
+
if (!approved) {
|
|
21105
|
+
if (options.json) {
|
|
21106
|
+
console.log(JSON.stringify({ organization: org, platform: options.platform, approved: null }));
|
|
21107
|
+
} else {
|
|
21108
|
+
console.log(source_default.yellow(`No approved config found for "${org}" (${options.platform}).`));
|
|
21109
|
+
console.log(source_default.dim("Run `gal approve` to set one."));
|
|
21110
|
+
}
|
|
21111
|
+
return;
|
|
21112
|
+
}
|
|
21113
|
+
if (options.json) {
|
|
21114
|
+
console.log(JSON.stringify({ organization: org, approved }));
|
|
21115
|
+
} else {
|
|
21116
|
+
printApprovedConfig(approved, org);
|
|
21117
|
+
}
|
|
21118
|
+
} catch (error2) {
|
|
21119
|
+
spinner?.stop();
|
|
21120
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
21121
|
+
if (options.json) {
|
|
21122
|
+
console.log(JSON.stringify({ error: msg }));
|
|
21123
|
+
} else {
|
|
21124
|
+
console.error(source_default.red(`Error: ${msg}`));
|
|
21125
|
+
}
|
|
21126
|
+
process.exit(1);
|
|
21127
|
+
}
|
|
21128
|
+
});
|
|
21129
|
+
command.command("diff").description("Show diff between local configs and the approved config").option("-o, --org <name>", "Organization name (default: from config)").option("-p, --platform <platform>", "Platform (default: claude)", "claude").option("-d, --dir <path>", "Local directory to compare against (default: cwd)").option("--json", "Output as JSON").action(async (options) => {
|
|
21130
|
+
const config = ConfigManager.load();
|
|
21131
|
+
if (!config.authToken) {
|
|
21132
|
+
console.error(source_default.red("Not authenticated. Run: gal auth login"));
|
|
21133
|
+
process.exit(1);
|
|
21134
|
+
}
|
|
21135
|
+
const org = resolveOrg(options, config);
|
|
21136
|
+
const provider = makeProvider(config);
|
|
21137
|
+
const configRepo = provider.getConfigRepository();
|
|
21138
|
+
const spinner = options.json ? null : ora(`Fetching approved config for "${org}"...`).start();
|
|
21139
|
+
try {
|
|
21140
|
+
let findMdFiles2 = function(dir) {
|
|
21141
|
+
if (!existsSync41(dir)) return [];
|
|
21142
|
+
const entries = readdirSync16(dir, { withFileTypes: true });
|
|
21143
|
+
const files = [];
|
|
21144
|
+
for (const entry of entries) {
|
|
21145
|
+
const fullPath = join45(dir, entry.name);
|
|
21146
|
+
if (entry.isDirectory()) files.push(...findMdFiles2(fullPath));
|
|
21147
|
+
else if (entry.name.endsWith(".md")) files.push(fullPath);
|
|
21148
|
+
}
|
|
21149
|
+
return files;
|
|
21150
|
+
};
|
|
21151
|
+
var findMdFiles = findMdFiles2;
|
|
21152
|
+
const approved = await configRepo.getApprovedConfig(org, options.platform);
|
|
21153
|
+
spinner?.stop();
|
|
21154
|
+
if (!approved) {
|
|
21155
|
+
if (options.json) {
|
|
21156
|
+
console.log(JSON.stringify({ organization: org, platform: options.platform, approved: null, diff: null }));
|
|
21157
|
+
} else {
|
|
21158
|
+
console.log(source_default.yellow(`No approved config found for "${org}" (${options.platform}).`));
|
|
21159
|
+
console.log(source_default.dim("Run `gal approve` to set one."));
|
|
21160
|
+
}
|
|
21161
|
+
return;
|
|
21162
|
+
}
|
|
21163
|
+
const { existsSync: existsSync41, readdirSync: readdirSync16, readFileSync: readFileSync37 } = await import("fs");
|
|
21164
|
+
const { join: join45, relative: relative10, basename: basename9 } = await import("path");
|
|
21165
|
+
const baseDir = options.dir || process.cwd();
|
|
21166
|
+
const commandsDir = join45(baseDir, ".claude", "commands");
|
|
21167
|
+
const agentsDir = join45(baseDir, ".claude", "agents");
|
|
21168
|
+
const localCommandNames = findMdFiles2(commandsDir).map(
|
|
21169
|
+
(f) => relative10(commandsDir, f).replace(/\.md$/, "").replace(/\//g, ":")
|
|
21170
|
+
);
|
|
21171
|
+
const localAgentNames = findMdFiles2(agentsDir).map(
|
|
21172
|
+
(f) => relative10(agentsDir, f).replace(/\.md$/, "").replace(/\//g, ":")
|
|
21173
|
+
);
|
|
21174
|
+
const approvedCommandNames = (approved.commands ?? []).map((c) => c.name);
|
|
21175
|
+
const approvedAgentNames = (approved.subagents ?? []).map((s) => s.name);
|
|
21176
|
+
const addedCommands = localCommandNames.filter((n) => !approvedCommandNames.includes(n));
|
|
21177
|
+
const removedCommands = approvedCommandNames.filter((n) => !localCommandNames.includes(n));
|
|
21178
|
+
const addedAgents = localAgentNames.filter((n) => !approvedAgentNames.includes(n));
|
|
21179
|
+
const removedAgents = approvedAgentNames.filter((n) => !localAgentNames.includes(n));
|
|
21180
|
+
if (options.json) {
|
|
21181
|
+
console.log(JSON.stringify({
|
|
21182
|
+
organization: org,
|
|
21183
|
+
platform: options.platform,
|
|
21184
|
+
diff: {
|
|
21185
|
+
commands: { added: addedCommands, removed: removedCommands },
|
|
21186
|
+
agents: { added: addedAgents, removed: removedAgents }
|
|
21187
|
+
}
|
|
21188
|
+
}));
|
|
21189
|
+
return;
|
|
21190
|
+
}
|
|
21191
|
+
const hasChanges = addedCommands.length || removedCommands.length || addedAgents.length || removedAgents.length;
|
|
21192
|
+
if (!hasChanges) {
|
|
21193
|
+
console.log(source_default.green(`\u2713 Local configs match approved config for "${org}" (${options.platform}).`));
|
|
21194
|
+
return;
|
|
21195
|
+
}
|
|
21196
|
+
console.log();
|
|
21197
|
+
console.log(source_default.bold(`Diff: local vs. approved config for "${org}" (${options.platform})`));
|
|
21198
|
+
console.log();
|
|
21199
|
+
if (addedCommands.length) {
|
|
21200
|
+
console.log(source_default.bold(" Commands only in local (would be added on `gal approve`):"));
|
|
21201
|
+
addedCommands.forEach((n) => console.log(source_default.green(` + /${n}`)));
|
|
21202
|
+
}
|
|
21203
|
+
if (removedCommands.length) {
|
|
21204
|
+
console.log(source_default.bold(" Commands only in approved (would be removed locally):"));
|
|
21205
|
+
removedCommands.forEach((n) => console.log(source_default.red(` - /${n}`)));
|
|
21206
|
+
}
|
|
21207
|
+
if (addedAgents.length) {
|
|
21208
|
+
console.log(source_default.bold(" Agents only in local:"));
|
|
21209
|
+
addedAgents.forEach((n) => console.log(source_default.green(` + ${n}`)));
|
|
21210
|
+
}
|
|
21211
|
+
if (removedAgents.length) {
|
|
21212
|
+
console.log(source_default.bold(" Agents only in approved:"));
|
|
21213
|
+
removedAgents.forEach((n) => console.log(source_default.red(` - ${n}`)));
|
|
21214
|
+
}
|
|
21215
|
+
console.log();
|
|
21216
|
+
} catch (error2) {
|
|
21217
|
+
spinner?.stop();
|
|
21218
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
21219
|
+
if (options.json) {
|
|
21220
|
+
console.log(JSON.stringify({ error: msg }));
|
|
21221
|
+
} else {
|
|
21222
|
+
console.error(source_default.red(`Error: ${msg}`));
|
|
21223
|
+
}
|
|
21224
|
+
process.exit(1);
|
|
21225
|
+
}
|
|
21226
|
+
});
|
|
21227
|
+
command.command("remove <type> <name>").description("Remove a specific item (command, agent, skill, rule) from the approved config").option("-o, --org <name>", "Organization name (default: from config)").option("-p, --platform <platform>", "Platform (default: claude)", "claude").option("--dry-run", "Preview removal without making changes").option("--json", "Output as JSON").action(async (type, name, options) => {
|
|
21228
|
+
const validTypes = ["command", "agent", "skill", "rule"];
|
|
21229
|
+
if (!validTypes.includes(type)) {
|
|
21230
|
+
const msg = `Invalid type "${type}". Valid types: ${validTypes.join(", ")}`;
|
|
21231
|
+
if (options.json) console.log(JSON.stringify({ error: msg }));
|
|
21232
|
+
else console.error(source_default.red(msg));
|
|
21233
|
+
process.exit(1);
|
|
21234
|
+
}
|
|
21235
|
+
const config = ConfigManager.load();
|
|
21236
|
+
if (!config.authToken) {
|
|
21237
|
+
console.error(source_default.red("Not authenticated. Run: gal auth login"));
|
|
21238
|
+
process.exit(1);
|
|
21239
|
+
}
|
|
21240
|
+
const org = resolveOrg(options, config);
|
|
21241
|
+
const provider = makeProvider(config);
|
|
21242
|
+
const configRepo = provider.getConfigRepository();
|
|
21243
|
+
if (options.dryRun) {
|
|
21244
|
+
if (options.json) {
|
|
21245
|
+
console.log(JSON.stringify({ dryRun: true, type, name, org, platform: options.platform }));
|
|
21246
|
+
} else {
|
|
21247
|
+
console.log(source_default.yellow(`Dry run: would remove ${type} "${name}" from "${org}" (${options.platform}).`));
|
|
21248
|
+
}
|
|
21249
|
+
return;
|
|
21250
|
+
}
|
|
21251
|
+
const spinner = options.json ? null : ora(`Removing ${type} "${name}"...`).start();
|
|
21252
|
+
try {
|
|
21253
|
+
const items = {};
|
|
21254
|
+
if (type === "command") items.commands = [name];
|
|
21255
|
+
else if (type === "agent") items.subagents = [name];
|
|
21256
|
+
else if (type === "skill") items.skills = [name];
|
|
21257
|
+
else if (type === "rule") items.rules = [name];
|
|
21258
|
+
const result = await configRepo.removeFromApprovedConfig(org, options.platform, items);
|
|
21259
|
+
spinner?.succeed(`Removed ${type} "${name}"`);
|
|
21260
|
+
if (options.json) {
|
|
21261
|
+
console.log(JSON.stringify({ success: true, ...result }));
|
|
21262
|
+
} else {
|
|
21263
|
+
console.log(source_default.dim(` Remaining: ${result.remaining.commands} commands, ${result.remaining.subagents} agents, ${result.remaining.skills} skills, ${result.remaining.rules} rules`));
|
|
21264
|
+
console.log(source_default.dim(` New hash: ${result.hash}`));
|
|
21265
|
+
}
|
|
21266
|
+
} catch (error2) {
|
|
21267
|
+
spinner?.stop();
|
|
21268
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
21269
|
+
if (options.json) {
|
|
21270
|
+
console.log(JSON.stringify({ error: msg }));
|
|
21271
|
+
} else {
|
|
21272
|
+
console.error(source_default.red(`Error: ${msg}`));
|
|
21273
|
+
}
|
|
21274
|
+
process.exit(1);
|
|
21275
|
+
}
|
|
21276
|
+
});
|
|
21277
|
+
command.command("clear").description("Clear the entire approved configuration for a platform").option("-o, --org <name>", "Organization name (default: from config)").option("-p, --platform <platform>", "Platform (default: claude)", "claude").option("--dry-run", "Preview clearing without making changes").option("--json", "Output as JSON").action(async (options) => {
|
|
21278
|
+
const config = ConfigManager.load();
|
|
21279
|
+
if (!config.authToken) {
|
|
21280
|
+
console.error(source_default.red("Not authenticated. Run: gal auth login"));
|
|
21281
|
+
process.exit(1);
|
|
21282
|
+
}
|
|
21283
|
+
const org = resolveOrg(options, config);
|
|
21284
|
+
if (options.dryRun) {
|
|
21285
|
+
if (options.json) {
|
|
21286
|
+
console.log(JSON.stringify({ dryRun: true, org, platform: options.platform }));
|
|
21287
|
+
} else {
|
|
21288
|
+
console.log(source_default.yellow(`Dry run: would clear approved config for "${org}" (${options.platform}).`));
|
|
21289
|
+
}
|
|
21290
|
+
return;
|
|
21291
|
+
}
|
|
21292
|
+
const provider = makeProvider(config);
|
|
21293
|
+
const configRepo = provider.getConfigRepository();
|
|
21294
|
+
const spinner = options.json ? null : ora(`Clearing approved config for "${org}" (${options.platform})...`).start();
|
|
21295
|
+
try {
|
|
21296
|
+
await configRepo.deleteApprovedConfig(org, options.platform);
|
|
21297
|
+
spinner?.succeed(`Cleared approved config for "${org}" (${options.platform})`);
|
|
21298
|
+
if (options.json) {
|
|
21299
|
+
console.log(JSON.stringify({ success: true, org, platform: options.platform }));
|
|
21300
|
+
}
|
|
21301
|
+
} catch (error2) {
|
|
21302
|
+
spinner?.stop();
|
|
21303
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
21304
|
+
if (options.json) {
|
|
21305
|
+
console.log(JSON.stringify({ error: msg }));
|
|
21306
|
+
} else {
|
|
21307
|
+
console.error(source_default.red(`Error: ${msg}`));
|
|
21308
|
+
}
|
|
21309
|
+
process.exit(1);
|
|
21310
|
+
}
|
|
21311
|
+
});
|
|
21312
|
+
command.command("export").description("Export the approved configuration to stdout or a file").option("-o, --org <name>", "Organization name (default: from config)").option("-p, --platform <platform>", "Platform (default: claude)", "claude").option("--format <format>", "Output format: json (default)", "json").action(async (options) => {
|
|
21313
|
+
const config = ConfigManager.load();
|
|
21314
|
+
if (!config.authToken) {
|
|
21315
|
+
console.error(source_default.red("Not authenticated. Run: gal auth login"));
|
|
21316
|
+
process.exit(1);
|
|
21317
|
+
}
|
|
21318
|
+
const org = resolveOrg(options, config);
|
|
21319
|
+
const provider = makeProvider(config);
|
|
21320
|
+
const configRepo = provider.getConfigRepository();
|
|
21321
|
+
const spinner = ora(`Fetching approved config for "${org}"...`).start();
|
|
21322
|
+
try {
|
|
21323
|
+
const approved = await configRepo.getApprovedConfig(org, options.platform);
|
|
21324
|
+
spinner?.stop();
|
|
21325
|
+
if (!approved) {
|
|
21326
|
+
console.log(JSON.stringify({ organization: org, platform: options.platform, approved: null }));
|
|
21327
|
+
return;
|
|
21328
|
+
}
|
|
21329
|
+
console.log(JSON.stringify({ organization: org, approved }, null, 2));
|
|
21330
|
+
} catch (error2) {
|
|
21331
|
+
spinner?.stop();
|
|
21332
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
21333
|
+
console.error(source_default.red(`Error: ${msg}`));
|
|
21334
|
+
process.exit(1);
|
|
21335
|
+
}
|
|
21336
|
+
});
|
|
21337
|
+
return command;
|
|
21338
|
+
}
|
|
21339
|
+
var init_approved_config = __esm({
|
|
21340
|
+
"src/commands/approved-config.ts"() {
|
|
21341
|
+
"use strict";
|
|
21342
|
+
init_esm();
|
|
21343
|
+
init_source();
|
|
21344
|
+
init_ora();
|
|
21345
|
+
init_config_manager();
|
|
21346
|
+
init_CoreServiceProvider();
|
|
21347
|
+
}
|
|
21348
|
+
});
|
|
21349
|
+
|
|
21350
|
+
// src/utils/capability-checker.ts
|
|
21351
|
+
async function checkOrgCapability(authRepo, orgName, requiredCapability, commandName) {
|
|
21352
|
+
try {
|
|
21353
|
+
const context = await authRepo.getUserContext();
|
|
21354
|
+
const org = context.orgs.find((o) => o.name === orgName);
|
|
21355
|
+
if (!org) {
|
|
21356
|
+
console.error(source_default.red(`You don't have access to organization "${orgName}"`));
|
|
21357
|
+
console.log(source_default.dim("\nAvailable organizations:"));
|
|
21358
|
+
if (context.orgs.length === 0) {
|
|
21359
|
+
console.log(source_default.dim(" (none)"));
|
|
21360
|
+
console.log(source_default.dim("\nMake sure you have joined the organization on GitHub."));
|
|
21361
|
+
} else {
|
|
21362
|
+
context.orgs.forEach((o) => {
|
|
21363
|
+
console.log(source_default.dim(` - ${o.name} (${o.githubRole})`));
|
|
21364
|
+
});
|
|
21365
|
+
}
|
|
21366
|
+
return false;
|
|
21367
|
+
}
|
|
21368
|
+
if (!org.capabilities[requiredCapability]) {
|
|
21369
|
+
const capabilityMessages = {
|
|
21370
|
+
canManageApprovedConfig: `manage approved configs for ${orgName}`,
|
|
21371
|
+
canRunDiscovery: `run discovery scans for ${orgName}`,
|
|
21372
|
+
canManageTeam: `manage team members for ${orgName}`,
|
|
21373
|
+
canSyncConfig: `sync configs from ${orgName}`
|
|
21374
|
+
};
|
|
21375
|
+
console.error(source_default.red(`You don't have permission to ${capabilityMessages[requiredCapability]}`));
|
|
21376
|
+
console.log(source_default.dim(`
|
|
21377
|
+
Your role in ${orgName}: ${source_default.white(org.githubRole)}`));
|
|
21378
|
+
console.log(source_default.dim("Required role: admin"));
|
|
21379
|
+
console.log(source_default.dim("\nContact your organization admin to grant you admin access on GitHub."));
|
|
21380
|
+
return false;
|
|
21381
|
+
}
|
|
21382
|
+
return true;
|
|
21383
|
+
} catch (error2) {
|
|
21384
|
+
if ((error2 instanceof Error ? error2.message : "").includes("401") || (error2 instanceof Error ? error2.message : "").includes("Unauthorized")) {
|
|
21385
|
+
console.error(source_default.red("Authentication failed. Please log in again:"));
|
|
21386
|
+
console.log(source_default.dim(" gal auth login"));
|
|
21387
|
+
} else {
|
|
21388
|
+
console.error(source_default.red(`Failed to check permissions: ${error2 instanceof Error ? error2.message : String(error2)}`));
|
|
21389
|
+
}
|
|
21390
|
+
return false;
|
|
21391
|
+
}
|
|
21392
|
+
}
|
|
21393
|
+
var init_capability_checker = __esm({
|
|
21394
|
+
"src/utils/capability-checker.ts"() {
|
|
21395
|
+
"use strict";
|
|
21396
|
+
init_source();
|
|
21397
|
+
}
|
|
21398
|
+
});
|
|
21399
|
+
|
|
21078
21400
|
// ../../node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/dist/nodes/identity.js
|
|
21079
21401
|
var require_identity = __commonJS({
|
|
21080
21402
|
"../../node_modules/.pnpm/yaml@2.8.2/node_modules/yaml/dist/nodes/identity.js"(exports2) {
|
|
@@ -29348,7 +29670,7 @@ function incrementVersion(version) {
|
|
|
29348
29670
|
return version;
|
|
29349
29671
|
}
|
|
29350
29672
|
function createApproveCommand() {
|
|
29351
|
-
const approve = new Command("approve").description("Upload local configs to org approved config").option("-o, --org <name>", "Organization name (default: from config)").option("-p, --platform <platform>", "Platform to approve for", "claude").option("-d, --dir <path>", "Directory to read configs from", process.cwd()).option("--dry-run", "Preview what would be uploaded without making changes").option("--commands-only", "Only approve commands (no agents, instructions, settings)").option("--agents-only", "Only approve agents (no commands, instructions, settings)").option("--clear", "Clear entire approved config for the platform").option("--remove <names...>", "Remove specific commands/agents by name (comma-separated)").option("--local", "Save to .gal/config.yaml locally (no auth required, no API upload)").action(async (options) => {
|
|
29673
|
+
const approve = new Command("approve").description("Upload local configs to org approved config").option("-o, --org <name>", "Organization name (default: from config)").option("-p, --platform <platform>", "Platform to approve for", "claude").option("-d, --dir <path>", "Directory to read configs from", process.cwd()).option("--dry-run", "Preview what would be uploaded without making changes").option("--commands-only", "Only approve commands (no agents, instructions, settings)").option("--agents-only", "Only approve agents (no commands, instructions, settings)").option("--clear", "Clear entire approved config for the platform").option("--remove <names...>", "Remove specific commands/agents by name (comma-separated)").option("--local", "Save to .gal/config.yaml locally (no auth required, no API upload)").option("--from-discovered", "Approve configs sourced from the discovered repositories pool").option("--type <type>", "Filter discovered configs by type: command, agent, skill, rule").option("--repo <repo>", "Filter discovered configs to a specific repository").option("--diff", "Show a unified diff before approving").action(async (options) => {
|
|
29352
29674
|
if (options.commandsOnly && options.agentsOnly) {
|
|
29353
29675
|
console.error(source_default.red("\nError: --commands-only and --agents-only are mutually exclusive."));
|
|
29354
29676
|
console.log(source_default.dim("Use one or the other, or neither to approve all configs.\n"));
|
|
@@ -29362,6 +29684,67 @@ function createApproveCommand() {
|
|
|
29362
29684
|
console.error(source_default.red("\nError: --remove cannot be combined with --commands-only or --agents-only."));
|
|
29363
29685
|
process.exit(1);
|
|
29364
29686
|
}
|
|
29687
|
+
if (options.fromDiscovered) {
|
|
29688
|
+
const config2 = ConfigManager.load();
|
|
29689
|
+
if (!config2.authToken) {
|
|
29690
|
+
console.error(source_default.red("Not authenticated. Run: gal auth login"));
|
|
29691
|
+
process.exit(1);
|
|
29692
|
+
}
|
|
29693
|
+
const orgName2 = options.org || config2.defaultOrg;
|
|
29694
|
+
if (!orgName2) {
|
|
29695
|
+
console.error(source_default.red("No organization specified. Use --org or run `gal workspace use <name>`."));
|
|
29696
|
+
process.exit(1);
|
|
29697
|
+
}
|
|
29698
|
+
const provider2 = new CoreServiceProvider({
|
|
29699
|
+
apiUrl: config2.apiUrl || process.env.GAL_API_URL || "",
|
|
29700
|
+
authToken: config2.authToken
|
|
29701
|
+
});
|
|
29702
|
+
const scanRepo = provider2.getScanResultRepository();
|
|
29703
|
+
const spinner2 = ora(`Fetching discovered configs for "${orgName2}"...`).start();
|
|
29704
|
+
try {
|
|
29705
|
+
const cache = await scanRepo.getDiscoveredConfigsCache(orgName2);
|
|
29706
|
+
spinner2.stop();
|
|
29707
|
+
let configs = cache?.configs || [];
|
|
29708
|
+
if (options.repo) {
|
|
29709
|
+
configs = configs.filter((c) => c.repo === options.repo || c.repoName === options.repo);
|
|
29710
|
+
}
|
|
29711
|
+
if (options.type) {
|
|
29712
|
+
configs = configs.filter((c) => c.type === options.type || c.configType === options.type);
|
|
29713
|
+
}
|
|
29714
|
+
if (configs.length === 0) {
|
|
29715
|
+
console.log(source_default.yellow("No discovered configs found matching your filters."));
|
|
29716
|
+
console.log(source_default.dim("Run `gal discover --scan` to trigger a discovery scan."));
|
|
29717
|
+
process.exit(0);
|
|
29718
|
+
}
|
|
29719
|
+
console.log(source_default.bold(`
|
|
29720
|
+
Discovered configs to approve (${orgName2}):
|
|
29721
|
+
`));
|
|
29722
|
+
for (const c of configs.slice(0, 20)) {
|
|
29723
|
+
const repoLabel = c.repo || c.repoName || "(unknown repo)";
|
|
29724
|
+
const typeLabel = c.type || c.configType || c.platform || "?";
|
|
29725
|
+
const nameLabel = c.name || c.path || "(unnamed)";
|
|
29726
|
+
console.log(` ${source_default.cyan(repoLabel)} / ${source_default.dim(typeLabel)} : ${nameLabel}`);
|
|
29727
|
+
}
|
|
29728
|
+
if (configs.length > 20) {
|
|
29729
|
+
console.log(source_default.dim(` ... and ${configs.length - 20} more`));
|
|
29730
|
+
}
|
|
29731
|
+
console.log();
|
|
29732
|
+
if (options.dryRun) {
|
|
29733
|
+
console.log(source_default.yellow(`Dry run: would approve ${configs.length} discovered configs.
|
|
29734
|
+
`));
|
|
29735
|
+
process.exit(0);
|
|
29736
|
+
}
|
|
29737
|
+
console.log(source_default.dim("To approve these configs, integrate them into your local .claude/ directory"));
|
|
29738
|
+
console.log(source_default.dim("and then run `gal approve` (without --from-discovered)."));
|
|
29739
|
+
console.log();
|
|
29740
|
+
console.log(source_default.dim("Direct auto-approval of discovered configs is coming in a future release."));
|
|
29741
|
+
process.exit(0);
|
|
29742
|
+
} catch (error2) {
|
|
29743
|
+
spinner2.stop();
|
|
29744
|
+
console.error(source_default.red(`Error: ${error2 instanceof Error ? error2.message : String(error2)}`));
|
|
29745
|
+
process.exit(1);
|
|
29746
|
+
}
|
|
29747
|
+
}
|
|
29365
29748
|
const earlyConfig = ConfigManager.load();
|
|
29366
29749
|
const isOrgMode = !!(options.org || options.clear || options.remove);
|
|
29367
29750
|
const isLocalMode = options.local || !earlyConfig.authToken && !isOrgMode;
|
|
@@ -39179,6 +39562,54 @@ Discovery Results for "${org}"`));
|
|
|
39179
39562
|
}
|
|
39180
39563
|
}
|
|
39181
39564
|
});
|
|
39565
|
+
command.command("show").description("Show content of a specific discovered config").argument("<repo>", 'Repository name (e.g. "my-org/my-repo")').argument("<path>", 'Config file path within the repository (e.g. "CLAUDE.md")').option("--org <orgName>", "Organization name (alternative to positional arg)").option("--format <format>", "Output format: text (default) or json", "text").action(async (repo, path8, options) => {
|
|
39566
|
+
const config = ConfigManager.load();
|
|
39567
|
+
const org = options.org || config.defaultOrg;
|
|
39568
|
+
if (!org) {
|
|
39569
|
+
console.error(source_default.red("No organization specified."));
|
|
39570
|
+
console.error(source_default.dim("Usage: gal discover show <repo> <path> --org <orgName>"));
|
|
39571
|
+
return;
|
|
39572
|
+
}
|
|
39573
|
+
const provider = new CoreServiceProvider({
|
|
39574
|
+
apiUrl: config.apiUrl || process.env.GAL_API_URL || "",
|
|
39575
|
+
authToken: config.authToken
|
|
39576
|
+
});
|
|
39577
|
+
const scanRepo = provider.getScanResultRepository();
|
|
39578
|
+
try {
|
|
39579
|
+
const cache = await scanRepo.getDiscoveredConfigsCache(org);
|
|
39580
|
+
const configs = cache?.configs || [];
|
|
39581
|
+
const match = configs.find((c) => {
|
|
39582
|
+
const repoMatch = c.repo === repo || c.repoName === repo || c.repo?.endsWith(`/${repo}`) || c.repoName?.endsWith(`/${repo}`);
|
|
39583
|
+
const pathMatch = c.path === path8 || c.filePath === path8 || c.path && c.path.endsWith(path8) || c.filePath && c.filePath.endsWith(path8);
|
|
39584
|
+
return repoMatch && pathMatch;
|
|
39585
|
+
});
|
|
39586
|
+
if (!match) {
|
|
39587
|
+
console.log(source_default.yellow(`Config not found: ${repo}/${path8}`));
|
|
39588
|
+
console.log(source_default.dim(`Run \`gal discover ${org}\` to see available configs.`));
|
|
39589
|
+
return;
|
|
39590
|
+
}
|
|
39591
|
+
if (options.format === "json") {
|
|
39592
|
+
console.log(JSON.stringify({ organization: org, repo, path: path8, config: match }, null, 2));
|
|
39593
|
+
} else {
|
|
39594
|
+
console.log(source_default.bold(`
|
|
39595
|
+
Config: ${repo}/${path8}
|
|
39596
|
+
`));
|
|
39597
|
+
if (match.platform) console.log(source_default.dim(`Platform: ${match.platform}`));
|
|
39598
|
+
if (match.type || match.configType) console.log(source_default.dim(`Type: ${match.type || match.configType}`));
|
|
39599
|
+
if (match.discoveredAt) console.log(source_default.dim(`Discovered: ${new Date(match.discoveredAt).toLocaleString()}`));
|
|
39600
|
+
console.log();
|
|
39601
|
+
const content = match.content || match.rawContent;
|
|
39602
|
+
if (content) {
|
|
39603
|
+
console.log(content);
|
|
39604
|
+
} else {
|
|
39605
|
+
console.log(source_default.dim("(No content available \u2014 run `gal discover --scan` to refresh.)"));
|
|
39606
|
+
}
|
|
39607
|
+
}
|
|
39608
|
+
} catch (error2) {
|
|
39609
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
39610
|
+
console.error(source_default.red(`Error: ${msg}`));
|
|
39611
|
+
}
|
|
39612
|
+
});
|
|
39182
39613
|
return command;
|
|
39183
39614
|
}
|
|
39184
39615
|
var VALID_PLATFORMS, POLL_INTERVAL, SCAN_TIMEOUT;
|
|
@@ -44068,6 +44499,104 @@ function createPolicyCommand() {
|
|
|
44068
44499
|
process.exit(1);
|
|
44069
44500
|
}
|
|
44070
44501
|
});
|
|
44502
|
+
command.command("show <id>").description("Show details of a specific policy (admin only)").option("--json", "Output as JSON").action(async (id, options) => {
|
|
44503
|
+
const config = ConfigManager.load();
|
|
44504
|
+
const authToken = config.authToken || config.apiKey;
|
|
44505
|
+
if (!authToken) {
|
|
44506
|
+
console.error(source_default.red("Not authenticated. Run: gal auth login"));
|
|
44507
|
+
process.exit(1);
|
|
44508
|
+
}
|
|
44509
|
+
const orgName = config.defaultOrg;
|
|
44510
|
+
if (!orgName) {
|
|
44511
|
+
console.error(source_default.red("No default organization set. Run: gal auth login"));
|
|
44512
|
+
process.exit(1);
|
|
44513
|
+
}
|
|
44514
|
+
const apiUrl = config.apiUrl || defaultApiUrl11;
|
|
44515
|
+
const spinner = options.json ? null : ora(`Fetching policy "${id}"...`).start();
|
|
44516
|
+
try {
|
|
44517
|
+
const res = await fetchWithAuth2(
|
|
44518
|
+
`${apiUrl}/organizations/${encodeURIComponent(orgName)}/agent-security-policies/${encodeURIComponent(id)}`,
|
|
44519
|
+
authToken
|
|
44520
|
+
);
|
|
44521
|
+
if (!res.ok) {
|
|
44522
|
+
const body = await res.json().catch(() => ({}));
|
|
44523
|
+
throw new Error(body.error || `HTTP ${res.status}`);
|
|
44524
|
+
}
|
|
44525
|
+
const data = await res.json();
|
|
44526
|
+
spinner?.stop();
|
|
44527
|
+
if (options.json) {
|
|
44528
|
+
console.log(JSON.stringify(data, null, 2));
|
|
44529
|
+
} else {
|
|
44530
|
+
const p = data.policy || data;
|
|
44531
|
+
console.log();
|
|
44532
|
+
console.log(` ${source_default.bold(p.name)} ${source_default.dim(`(${p.type || "policy"})`)}`);
|
|
44533
|
+
console.log(` ID: ${source_default.bold(p.id)}`);
|
|
44534
|
+
console.log(` Description: ${p.description || ""}`);
|
|
44535
|
+
console.log(` Enabled: ${p.enabled ? source_default.green("yes") : source_default.yellow("no")}`);
|
|
44536
|
+
console.log(` Version: ${p.version || "N/A"}`);
|
|
44537
|
+
console.log(` Created by: ${p.createdBy || "unknown"}`);
|
|
44538
|
+
if (p.allowedTools?.length > 0) {
|
|
44539
|
+
console.log(` Allowed tools: ${p.allowedTools.join(", ")}`);
|
|
44540
|
+
}
|
|
44541
|
+
if (p.blockedTools?.length > 0) {
|
|
44542
|
+
console.log(` Blocked tools: ${p.blockedTools.join(", ")}`);
|
|
44543
|
+
}
|
|
44544
|
+
console.log();
|
|
44545
|
+
}
|
|
44546
|
+
} catch (error2) {
|
|
44547
|
+
spinner?.stop();
|
|
44548
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
44549
|
+
if (options.json) {
|
|
44550
|
+
console.log(JSON.stringify({ error: msg }));
|
|
44551
|
+
} else {
|
|
44552
|
+
console.error(source_default.red("Error fetching policy:"), msg);
|
|
44553
|
+
}
|
|
44554
|
+
process.exit(1);
|
|
44555
|
+
}
|
|
44556
|
+
});
|
|
44557
|
+
command.command("activate <id>").description("Activate (enable) an agent security policy (admin only)").option("--json", "Output as JSON").action(async (id, options) => {
|
|
44558
|
+
const config = ConfigManager.load();
|
|
44559
|
+
const authToken = config.authToken || config.apiKey;
|
|
44560
|
+
if (!authToken) {
|
|
44561
|
+
console.error(source_default.red("Not authenticated. Run: gal auth login"));
|
|
44562
|
+
process.exit(1);
|
|
44563
|
+
}
|
|
44564
|
+
const orgName = config.defaultOrg;
|
|
44565
|
+
if (!orgName) {
|
|
44566
|
+
console.error(source_default.red("No default organization set. Run: gal auth login"));
|
|
44567
|
+
process.exit(1);
|
|
44568
|
+
}
|
|
44569
|
+
const apiUrl = config.apiUrl || defaultApiUrl11;
|
|
44570
|
+
const spinner = options.json ? null : ora(`Activating policy "${id}"...`).start();
|
|
44571
|
+
try {
|
|
44572
|
+
const res = await fetchWithAuth2(
|
|
44573
|
+
`${apiUrl}/organizations/${encodeURIComponent(orgName)}/agent-security-policies/${encodeURIComponent(id)}`,
|
|
44574
|
+
authToken,
|
|
44575
|
+
"PUT",
|
|
44576
|
+
{ enabled: true }
|
|
44577
|
+
);
|
|
44578
|
+
if (!res.ok) {
|
|
44579
|
+
const data2 = await res.json().catch(() => ({}));
|
|
44580
|
+
throw new Error(data2.error || `HTTP ${res.status}`);
|
|
44581
|
+
}
|
|
44582
|
+
const data = await res.json();
|
|
44583
|
+
spinner?.succeed(`Policy "${id}" activated`);
|
|
44584
|
+
if (options.json) {
|
|
44585
|
+
console.log(JSON.stringify(data, null, 2));
|
|
44586
|
+
} else {
|
|
44587
|
+
console.log(` Policy ${source_default.bold(id)} is now ${source_default.green("enabled")}.`);
|
|
44588
|
+
}
|
|
44589
|
+
} catch (error2) {
|
|
44590
|
+
spinner?.stop();
|
|
44591
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
44592
|
+
if (options.json) {
|
|
44593
|
+
console.log(JSON.stringify({ error: msg }));
|
|
44594
|
+
} else {
|
|
44595
|
+
console.error(source_default.red("Error activating policy:"), msg);
|
|
44596
|
+
}
|
|
44597
|
+
process.exit(1);
|
|
44598
|
+
}
|
|
44599
|
+
});
|
|
44071
44600
|
command.command("distribute <id>").description("Trigger distribution of an active policy").option("--json", "Output as JSON").action(async (id, options) => {
|
|
44072
44601
|
const config = ConfigManager.load();
|
|
44073
44602
|
const authToken = config.authToken || config.apiKey;
|
|
@@ -52743,14 +53272,63 @@ function printNoWorkspacesMessage() {
|
|
|
52743
53272
|
console.log(" gal approve # Approve a local config");
|
|
52744
53273
|
console.log(" gal sync # Sync approved config to all agents");
|
|
52745
53274
|
}
|
|
53275
|
+
function switchWorkspaceAction(name, options) {
|
|
53276
|
+
const trimmedName = name.trim();
|
|
53277
|
+
const config = ConfigManager.load();
|
|
53278
|
+
const memberships = config.orgMemberships ?? [];
|
|
53279
|
+
if (!trimmedName) {
|
|
53280
|
+
if (options.json) {
|
|
53281
|
+
console.log(JSON.stringify({ error: "Workspace name cannot be empty." }));
|
|
53282
|
+
} else {
|
|
53283
|
+
console.error(source_default.red("Workspace name cannot be empty."));
|
|
53284
|
+
}
|
|
53285
|
+
process.exit(1);
|
|
53286
|
+
}
|
|
53287
|
+
if (memberships.length > 0 && !memberships.includes(trimmedName)) {
|
|
53288
|
+
if (options.json) {
|
|
53289
|
+
console.log(JSON.stringify({
|
|
53290
|
+
error: `Workspace "${trimmedName}" not found.`,
|
|
53291
|
+
available: memberships
|
|
53292
|
+
}));
|
|
53293
|
+
} else {
|
|
53294
|
+
console.error(
|
|
53295
|
+
source_default.red(
|
|
53296
|
+
`Workspace "${trimmedName}" not found. Run \`gal workspace list\` to see available workspaces.`
|
|
53297
|
+
)
|
|
53298
|
+
);
|
|
53299
|
+
}
|
|
53300
|
+
process.exit(1);
|
|
53301
|
+
}
|
|
53302
|
+
ConfigManager.save({
|
|
53303
|
+
...config,
|
|
53304
|
+
defaultOrg: trimmedName
|
|
53305
|
+
});
|
|
53306
|
+
if (options.json) {
|
|
53307
|
+
console.log(JSON.stringify({ active: trimmedName }));
|
|
53308
|
+
} else {
|
|
53309
|
+
console.log(source_default.green(`\u2713 Switched to ${trimmedName}`));
|
|
53310
|
+
console.log(" Run `gal sync --pull` to sync the approved config for this workspace.");
|
|
53311
|
+
}
|
|
53312
|
+
}
|
|
52746
53313
|
function createWorkspaceCommand() {
|
|
52747
53314
|
const command = new Command("workspace");
|
|
52748
53315
|
command.description("Manage workspaces (GitHub organizations and personal accounts)");
|
|
52749
|
-
command.command("list").description("List all connected workspaces").action(() => {
|
|
53316
|
+
command.command("list").description("List all connected workspaces").option("--json", "Output as JSON").action((options) => {
|
|
52750
53317
|
const config = ConfigManager.load();
|
|
52751
53318
|
const memberships = config.orgMemberships ?? [];
|
|
52752
53319
|
if (memberships.length === 0) {
|
|
52753
|
-
|
|
53320
|
+
if (options.json) {
|
|
53321
|
+
console.log(JSON.stringify({ workspaces: [], active: null }));
|
|
53322
|
+
} else {
|
|
53323
|
+
printNoWorkspacesMessage();
|
|
53324
|
+
}
|
|
53325
|
+
return;
|
|
53326
|
+
}
|
|
53327
|
+
if (options.json) {
|
|
53328
|
+
console.log(JSON.stringify({
|
|
53329
|
+
workspaces: memberships,
|
|
53330
|
+
active: config.defaultOrg ?? null
|
|
53331
|
+
}));
|
|
52754
53332
|
return;
|
|
52755
53333
|
}
|
|
52756
53334
|
for (const workspace of memberships) {
|
|
@@ -52760,36 +53338,100 @@ function createWorkspaceCommand() {
|
|
|
52760
53338
|
console.log(`${prefix} ${workspace}${suffix}`);
|
|
52761
53339
|
}
|
|
52762
53340
|
});
|
|
52763
|
-
command.command("current").description("Show the currently active workspace").action(() => {
|
|
53341
|
+
command.command("current").description("Show the currently active workspace").option("--json", "Output as JSON").action((options) => {
|
|
52764
53342
|
const config = ConfigManager.load();
|
|
52765
53343
|
if (!config.defaultOrg) {
|
|
52766
|
-
|
|
53344
|
+
if (options.json) {
|
|
53345
|
+
console.log(JSON.stringify({ active: null }));
|
|
53346
|
+
} else {
|
|
53347
|
+
console.log("No active workspace set. Run `gal workspace use <name>` to set one.");
|
|
53348
|
+
}
|
|
52767
53349
|
return;
|
|
52768
53350
|
}
|
|
52769
|
-
|
|
53351
|
+
if (options.json) {
|
|
53352
|
+
console.log(JSON.stringify({ active: config.defaultOrg }));
|
|
53353
|
+
} else {
|
|
53354
|
+
console.log(`Active workspace: ${config.defaultOrg}`);
|
|
53355
|
+
}
|
|
52770
53356
|
});
|
|
52771
|
-
command.command("
|
|
52772
|
-
|
|
53357
|
+
command.command("use").description("Switch the active workspace").argument("<name>", "Workspace name to activate").option("--json", "Output as JSON").action((name, options) => {
|
|
53358
|
+
switchWorkspaceAction(name, options);
|
|
53359
|
+
});
|
|
53360
|
+
command.command("switch").description("Switch the active workspace (alias: use)").argument("<name>", "Workspace name to activate").option("--json", "Output as JSON").action((name, options) => {
|
|
53361
|
+
switchWorkspaceAction(name, options);
|
|
53362
|
+
});
|
|
53363
|
+
command.command("add").description("Add an organization to the workspace list").argument("<org>", "Organization name to add").option("--json", "Output as JSON").action((org, options) => {
|
|
53364
|
+
const trimmedOrg = org.trim();
|
|
53365
|
+
if (!trimmedOrg) {
|
|
53366
|
+
if (options.json) {
|
|
53367
|
+
console.log(JSON.stringify({ error: "Organization name cannot be empty." }));
|
|
53368
|
+
} else {
|
|
53369
|
+
console.error(source_default.red("Organization name cannot be empty."));
|
|
53370
|
+
}
|
|
53371
|
+
process.exit(1);
|
|
53372
|
+
}
|
|
52773
53373
|
const config = ConfigManager.load();
|
|
52774
53374
|
const memberships = config.orgMemberships ?? [];
|
|
52775
|
-
if (
|
|
52776
|
-
|
|
53375
|
+
if (memberships.includes(trimmedOrg)) {
|
|
53376
|
+
if (options.json) {
|
|
53377
|
+
console.log(JSON.stringify({ workspace: trimmedOrg, added: false, message: "Already in workspace list." }));
|
|
53378
|
+
} else {
|
|
53379
|
+
console.log(source_default.yellow(`"${trimmedOrg}" is already in your workspace list.`));
|
|
53380
|
+
}
|
|
53381
|
+
return;
|
|
53382
|
+
}
|
|
53383
|
+
ConfigManager.save({
|
|
53384
|
+
...config,
|
|
53385
|
+
orgMemberships: [...memberships, trimmedOrg]
|
|
53386
|
+
});
|
|
53387
|
+
if (options.json) {
|
|
53388
|
+
console.log(JSON.stringify({ workspace: trimmedOrg, added: true }));
|
|
53389
|
+
} else {
|
|
53390
|
+
console.log(source_default.green(`\u2713 Added "${trimmedOrg}" to workspaces.`));
|
|
53391
|
+
console.log(source_default.dim(` Run \`gal workspace use ${trimmedOrg}\` to make it active.`));
|
|
53392
|
+
}
|
|
53393
|
+
});
|
|
53394
|
+
command.command("remove").description("Remove an organization from the workspace list").argument("<org>", "Organization name to remove").option("--json", "Output as JSON").action((org, options) => {
|
|
53395
|
+
const trimmedOrg = org.trim();
|
|
53396
|
+
if (!trimmedOrg) {
|
|
53397
|
+
if (options.json) {
|
|
53398
|
+
console.log(JSON.stringify({ error: "Organization name cannot be empty." }));
|
|
53399
|
+
} else {
|
|
53400
|
+
console.error(source_default.red("Organization name cannot be empty."));
|
|
53401
|
+
}
|
|
52777
53402
|
process.exit(1);
|
|
52778
53403
|
}
|
|
52779
|
-
|
|
52780
|
-
|
|
52781
|
-
|
|
52782
|
-
|
|
52783
|
-
)
|
|
52784
|
-
|
|
53404
|
+
const config = ConfigManager.load();
|
|
53405
|
+
const memberships = config.orgMemberships ?? [];
|
|
53406
|
+
if (!memberships.includes(trimmedOrg)) {
|
|
53407
|
+
if (options.json) {
|
|
53408
|
+
console.log(JSON.stringify({ error: `Workspace "${trimmedOrg}" not found.`, available: memberships }));
|
|
53409
|
+
} else {
|
|
53410
|
+
console.error(source_default.red(`Workspace "${trimmedOrg}" not found.`));
|
|
53411
|
+
}
|
|
52785
53412
|
process.exit(1);
|
|
52786
53413
|
}
|
|
52787
|
-
|
|
53414
|
+
const updated = memberships.filter((m) => m !== trimmedOrg);
|
|
53415
|
+
const newConfig = {
|
|
52788
53416
|
...config,
|
|
52789
|
-
|
|
52790
|
-
}
|
|
52791
|
-
|
|
52792
|
-
|
|
53417
|
+
orgMemberships: updated
|
|
53418
|
+
};
|
|
53419
|
+
if (config.defaultOrg === trimmedOrg) {
|
|
53420
|
+
delete newConfig.defaultOrg;
|
|
53421
|
+
}
|
|
53422
|
+
ConfigManager.save(newConfig);
|
|
53423
|
+
if (options.json) {
|
|
53424
|
+
console.log(JSON.stringify({
|
|
53425
|
+
workspace: trimmedOrg,
|
|
53426
|
+
removed: true,
|
|
53427
|
+
active: newConfig.defaultOrg ?? null
|
|
53428
|
+
}));
|
|
53429
|
+
} else {
|
|
53430
|
+
console.log(source_default.green(`\u2713 Removed "${trimmedOrg}" from workspaces.`));
|
|
53431
|
+
if (config.defaultOrg === trimmedOrg) {
|
|
53432
|
+
console.log(source_default.yellow(" Active workspace cleared. Run `gal workspace use <name>` to set a new one."));
|
|
53433
|
+
}
|
|
53434
|
+
}
|
|
52793
53435
|
});
|
|
52794
53436
|
return command;
|
|
52795
53437
|
}
|
|
@@ -52809,6 +53451,7 @@ var init_command_registry = __esm({
|
|
|
52809
53451
|
"use strict";
|
|
52810
53452
|
init_admin();
|
|
52811
53453
|
init_agent();
|
|
53454
|
+
init_approved_config();
|
|
52812
53455
|
init_approve();
|
|
52813
53456
|
init_audit();
|
|
52814
53457
|
init_auth2();
|
|
@@ -52856,6 +53499,7 @@ var init_command_registry = __esm({
|
|
|
52856
53499
|
COMMAND_FACTORIES = [
|
|
52857
53500
|
{ name: "admin", create: createAdminCommand },
|
|
52858
53501
|
{ name: "agent", create: createAgentCommand },
|
|
53502
|
+
{ name: "approved-config", create: createApprovedConfigCommand },
|
|
52859
53503
|
{ name: "approve", create: createApproveCommand },
|
|
52860
53504
|
{ name: "audit", create: createAuditCommand },
|
|
52861
53505
|
{ name: "auth", create: createAuthCommand },
|
|
@@ -53377,7 +54021,7 @@ var init_index = __esm({
|
|
|
53377
54021
|
});
|
|
53378
54022
|
|
|
53379
54023
|
// src/bootstrap.ts
|
|
53380
|
-
var cliVersion10 = true ? "0.0.
|
|
54024
|
+
var cliVersion10 = true ? "0.0.266" : "0.0.0-dev";
|
|
53381
54025
|
var args = process.argv.slice(2);
|
|
53382
54026
|
var requestedGlobalHelp = args.length === 1 && (args[0] === "--help" || args[0] === "-h");
|
|
53383
54027
|
var requestedVersion = args.length === 1 && (args[0] === "--version" || args[0] === "-V");
|
package/package.json
CHANGED