clishop 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/config.ts ADDED
@@ -0,0 +1,127 @@
1
+ import Conf from "conf";
2
+ import path from "path";
3
+
4
+ /**
5
+ * Local configuration store.
6
+ * All config is scoped per-agent. The "default" agent always exists.
7
+ */
8
+
9
+ export interface AgentConfig {
10
+ name: string;
11
+ /** Max price per order (safety threshold) */
12
+ maxOrderAmount?: number;
13
+ /** Allowed product categories (empty = all) */
14
+ allowedCategories?: string[];
15
+ /** Blocked product categories */
16
+ blockedCategories?: string[];
17
+ /** Whether the agent requires confirmation before ordering */
18
+ requireConfirmation: boolean;
19
+ /** Default address ID for this agent */
20
+ defaultAddressId?: string;
21
+ /** Default payment method ID for this agent */
22
+ defaultPaymentMethodId?: string;
23
+ }
24
+
25
+ export interface AppConfig {
26
+ /** Currently active agent name */
27
+ activeAgent: string;
28
+ /** All configured agents */
29
+ agents: Record<string, AgentConfig>;
30
+ /** API base URL */
31
+ apiBaseUrl: string;
32
+ /** Output format */
33
+ outputFormat: "human" | "json";
34
+ /** Whether the first-run setup wizard has been completed */
35
+ setupCompleted: boolean;
36
+ }
37
+
38
+ const DEFAULT_AGENT: AgentConfig = {
39
+ name: "default",
40
+ requireConfirmation: true,
41
+ maxOrderAmount: 500,
42
+ allowedCategories: [],
43
+ blockedCategories: [],
44
+ };
45
+
46
+ const config = new Conf<AppConfig>({
47
+ projectName: "clishop",
48
+ defaults: {
49
+ activeAgent: "default",
50
+ agents: {
51
+ default: DEFAULT_AGENT,
52
+ },
53
+ apiBaseUrl: "https://clishop-backend.vercel.app/api",
54
+ outputFormat: "human",
55
+ setupCompleted: false,
56
+ },
57
+ });
58
+
59
+ export function getConfig(): Conf<AppConfig> {
60
+ return config;
61
+ }
62
+
63
+ export function getActiveAgent(): AgentConfig {
64
+ const cfg = config.store;
65
+ // Respect per-command --agent override
66
+ const override = process.env.__CLISHOP_AGENT_OVERRIDE;
67
+ if (override && cfg.agents[override]) {
68
+ return cfg.agents[override];
69
+ }
70
+ return cfg.agents[cfg.activeAgent] || cfg.agents["default"];
71
+ }
72
+
73
+ export function getAgent(name: string): AgentConfig | undefined {
74
+ return config.store.agents[name];
75
+ }
76
+
77
+ export function setActiveAgent(name: string): void {
78
+ if (!config.store.agents[name]) {
79
+ throw new Error(`Agent "${name}" does not exist. Create it first with: clishop agent create ${name}`);
80
+ }
81
+ config.set("activeAgent", name);
82
+ }
83
+
84
+ export function createAgent(name: string, opts: Partial<AgentConfig> = {}): AgentConfig {
85
+ if (config.store.agents[name]) {
86
+ throw new Error(`Agent "${name}" already exists.`);
87
+ }
88
+ const agent: AgentConfig = {
89
+ name,
90
+ requireConfirmation: true,
91
+ maxOrderAmount: 500,
92
+ allowedCategories: [],
93
+ blockedCategories: [],
94
+ ...opts,
95
+ };
96
+ config.set(`agents.${name}`, agent);
97
+ return agent;
98
+ }
99
+
100
+ export function updateAgent(name: string, opts: Partial<AgentConfig>): AgentConfig {
101
+ const existing = config.store.agents[name];
102
+ if (!existing) {
103
+ throw new Error(`Agent "${name}" does not exist.`);
104
+ }
105
+ const updated = { ...existing, ...opts, name }; // name is immutable
106
+ config.set(`agents.${name}`, updated);
107
+ return updated;
108
+ }
109
+
110
+ export function deleteAgent(name: string): void {
111
+ if (name === "default") {
112
+ throw new Error('Cannot delete the "default" agent.');
113
+ }
114
+ if (!config.store.agents[name]) {
115
+ throw new Error(`Agent "${name}" does not exist.`);
116
+ }
117
+ const agents = { ...config.store.agents };
118
+ delete agents[name];
119
+ config.set("agents", agents);
120
+ if (config.store.activeAgent === name) {
121
+ config.set("activeAgent", "default");
122
+ }
123
+ }
124
+
125
+ export function listAgents(): AgentConfig[] {
126
+ return Object.values(config.store.agents);
127
+ }
package/src/index.ts ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+ import chalk from "chalk";
5
+ import { registerAuthCommands } from "./commands/auth.js";
6
+ import { registerAgentCommands } from "./commands/agent.js";
7
+ import { registerAddressCommands } from "./commands/address.js";
8
+ import { registerPaymentCommands } from "./commands/payment.js";
9
+ import { registerSearchCommands } from "./commands/search.js";
10
+ import { registerOrderCommands } from "./commands/order.js";
11
+ import { registerReviewCommands } from "./commands/review.js";
12
+ import { registerConfigCommands } from "./commands/config.js";
13
+ import { registerStoreCommands } from "./commands/store.js";
14
+ import { registerStatusCommand } from "./commands/status.js";
15
+ import { registerSetupCommand, runSetupWizard } from "./commands/setup.js";
16
+ import { registerAdvertiseCommands } from "./commands/advertise.js";
17
+ import { registerSupportCommands } from "./commands/support.js";
18
+ import { getConfig } from "./config.js";
19
+
20
+ const program = new Command();
21
+
22
+ program
23
+ .name("clishop")
24
+ .version("0.1.0")
25
+ .description(
26
+ chalk.bold("CLISHOP") +
27
+ " — Order anything from your terminal.\n\n" +
28
+ " Use agents to set safety limits, addresses, and payment methods.\n" +
29
+ ' The "default" agent is used when no agent is specified.'
30
+ )
31
+ .option("--agent <name>", "Use a specific agent for this command")
32
+ .hook("preAction", (thisCommand) => {
33
+ const agentOpt = thisCommand.opts().agent;
34
+ if (agentOpt) {
35
+ const config = getConfig();
36
+ if (!config.store.agents[agentOpt]) {
37
+ console.error(chalk.red(`✗ Agent "${agentOpt}" does not exist.`));
38
+ process.exit(1);
39
+ }
40
+ // Override the active agent for this run
41
+ process.env.__CLISHOP_AGENT_OVERRIDE = agentOpt;
42
+ }
43
+ });
44
+
45
+ // Register all command groups
46
+ registerAuthCommands(program);
47
+ registerAgentCommands(program);
48
+ registerAddressCommands(program);
49
+ registerPaymentCommands(program);
50
+ registerSearchCommands(program);
51
+ registerOrderCommands(program);
52
+ registerReviewCommands(program);
53
+ registerConfigCommands(program);
54
+ registerStoreCommands(program);
55
+ registerStatusCommand(program);
56
+ registerSetupCommand(program);
57
+ registerAdvertiseCommands(program);
58
+ registerSupportCommands(program);
59
+
60
+ // Main entry with first-run detection
61
+ async function main() {
62
+ const hasSubcommand = process.argv.length > 2;
63
+
64
+ // If the user just types "clishop" with no arguments and hasn't
65
+ // completed setup yet, start the onboarding wizard automatically.
66
+ if (!hasSubcommand) {
67
+ const config = getConfig();
68
+ if (!config.get("setupCompleted")) {
69
+ await runSetupWizard();
70
+ return;
71
+ }
72
+ }
73
+
74
+ await program.parseAsync(process.argv);
75
+ }
76
+
77
+ main().catch((err) => {
78
+ console.error(chalk.red(err.message));
79
+ process.exit(1);
80
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true,
17
+ "allowImportingTsExtensions": true,
18
+ "noEmit": true
19
+ },
20
+ "include": ["src/**/*"],
21
+ "exclude": ["node_modules", "dist"]
22
+ }