@stamn/agent 0.5.0 → 0.6.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/README.md CHANGED
@@ -1,9 +1,15 @@
1
1
  # @stamn/agent
2
2
 
3
- Daemon CLI for Stamn agents. Connects to the Stamn server via WebSocket, authenticates, sends heartbeats, and executes spend requests with budget validation.
3
+ Daemon CLI for Stamn agents. Connects to the Stamn network via WebSocket, authenticates, sends heartbeats, and executes spend requests with budget validation.
4
4
 
5
5
  ## Install
6
6
 
7
+ ```bash
8
+ curl -fsSL https://stamn.com/install.sh | bash
9
+ ```
10
+
11
+ Or manually:
12
+
7
13
  ```bash
8
14
  npm i -g @stamn/agent
9
15
  ```
@@ -11,14 +17,14 @@ npm i -g @stamn/agent
11
17
  ## Quick Start
12
18
 
13
19
  ```bash
14
- # Configure
15
- stamn config set agent-id <your-agent-uuid>
16
- stamn config set api-key <your-api-key>
17
-
18
- # Start daemon
19
20
  stamn start
21
+ ```
22
+
23
+ On first run, you'll be prompted for your API key. The agent registers itself automatically and starts the daemon.
24
+
25
+ To run as a background process:
20
26
 
21
- # Start as background process
27
+ ```bash
22
28
  stamn start -d
23
29
  ```
24
30
 
@@ -26,20 +32,12 @@ stamn start -d
26
32
 
27
33
  ### `stamn start`
28
34
 
29
- Start the agent daemon.
30
-
31
- ```bash
32
- stamn start # foreground
33
- stamn start -d # background daemon
34
- stamn start --agent-id <uuid> --api-key <key>
35
- ```
35
+ Start the agent daemon. Prompts for setup on first run.
36
36
 
37
- | Flag | Env | Description |
38
- |------|-----|-------------|
39
- | `--daemon, -d` | | Run as background process |
40
- | `--agent-id` | `STAMN_AGENT_ID` | Agent UUID |
41
- | `--api-key` | `STAMN_API_KEY` | API key |
42
- | `--log-level` | | `trace\|debug\|info\|warn\|error\|fatal` |
37
+ | Flag | Description |
38
+ |------|-------------|
39
+ | `--daemon, -d` | Run as background process |
40
+ | `--log-level` | `trace\|debug\|info\|warn\|error\|fatal` |
43
41
 
44
42
  ### `stamn stop`
45
43
 
@@ -47,7 +45,11 @@ Stop the running daemon.
47
45
 
48
46
  ### `stamn status`
49
47
 
50
- Show daemon status, config, and server connectivity.
48
+ Show daemon status and server connectivity.
49
+
50
+ ### `stamn update`
51
+
52
+ Update to the latest version.
51
53
 
52
54
  ### `stamn config`
53
55
 
@@ -82,16 +84,6 @@ stamn spend \
82
84
  | `--recipient-agent` | no | Recipient agent ID (agent-to-agent) |
83
85
  | `--recipient-address` | no | Recipient wallet address (on-chain) |
84
86
 
85
- ## Environment Variables
86
-
87
- All flags can also be set via env vars:
88
-
89
- ```bash
90
- export STAMN_AGENT_ID=<uuid>
91
- export STAMN_API_KEY=<key>
92
- stamn start
93
- ```
94
-
95
87
  ## Requirements
96
88
 
97
89
  - Node.js >= 22
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
2
  import {
3
3
  SERVER_URL
4
- } from "./chunk-5UI5E6YF.js";
4
+ } from "./chunk-JVIBUEVN.js";
5
5
 
6
6
  // src/logging/logger.ts
7
7
  import pino from "pino";
@@ -266,7 +266,7 @@ var WSClient = class {
266
266
  const payload = {
267
267
  agentId: this.options.config.agentId,
268
268
  status,
269
- version: "0.5.0",
269
+ version: "0.6.0",
270
270
  platform: `${process.platform}-${process.arch}`,
271
271
  nodeVersion: process.versions.node
272
272
  };
@@ -373,4 +373,4 @@ export {
373
373
  WSClient,
374
374
  SpendClient
375
375
  };
376
- //# sourceMappingURL=chunk-VTX4GGVR.js.map
376
+ //# sourceMappingURL=chunk-DJ3HR5OC.js.map
@@ -6,6 +6,7 @@ var SERVER_URL = "https://api.stamn.com";
6
6
  var configSchema = z.object({
7
7
  apiKey: z.string().min(1).optional(),
8
8
  agentId: z.string().uuid().optional(),
9
+ agentName: z.string().optional(),
9
10
  logLevel: z.enum(["trace", "debug", "info", "warn", "error", "fatal"]).default("info"),
10
11
  heartbeatIntervalMs: z.number().int().positive().default(3e4),
11
12
  wsReconnectBaseMs: z.number().int().positive().default(1e3),
@@ -13,37 +14,9 @@ var configSchema = z.object({
13
14
  });
14
15
  var CONFIG_DEFAULTS = configSchema.parse({});
15
16
 
16
- // src/config/config-store.ts
17
- import Conf from "conf";
18
- var ConfigStore = class {
19
- store;
20
- constructor() {
21
- this.store = new Conf({
22
- projectName: "stamn",
23
- defaults: CONFIG_DEFAULTS
24
- });
25
- }
26
- get(key) {
27
- return this.store.get(key);
28
- }
29
- set(key, value) {
30
- configSchema.partial().parse({ [key]: value });
31
- this.store.set(key, value);
32
- }
33
- getAll() {
34
- return configSchema.parse(this.store.store);
35
- }
36
- clear() {
37
- this.store.clear();
38
- }
39
- get path() {
40
- return this.store.path;
41
- }
42
- };
43
-
44
17
  export {
45
18
  SERVER_URL,
46
19
  configSchema,
47
- ConfigStore
20
+ CONFIG_DEFAULTS
48
21
  };
49
- //# sourceMappingURL=chunk-5UI5E6YF.js.map
22
+ //# sourceMappingURL=chunk-JVIBUEVN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config/config-schema.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const SERVER_URL = 'https://api.stamn.com';\n\nexport const configSchema = z.object({\n apiKey: z.string().min(1).optional(),\n agentId: z.string().uuid().optional(),\n agentName: z.string().optional(),\n logLevel: z\n .enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal'])\n .default('info'),\n heartbeatIntervalMs: z.number().int().positive().default(30_000),\n wsReconnectBaseMs: z.number().int().positive().default(1_000),\n wsReconnectMaxMs: z.number().int().positive().default(30_000),\n});\n\nexport type AgentConfig = z.infer<typeof configSchema>;\n\nexport const CONFIG_DEFAULTS: AgentConfig = configSchema.parse({});\n"],"mappings":";;;AAAA,SAAS,SAAS;AAEX,IAAM,aAAa;AAEnB,IAAM,eAAe,EAAE,OAAO;AAAA,EACnC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACpC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,UAAU,EACP,KAAK,CAAC,SAAS,SAAS,QAAQ,QAAQ,SAAS,OAAO,CAAC,EACzD,QAAQ,MAAM;AAAA,EACjB,qBAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAM;AAAA,EAC/D,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAK;AAAA,EAC5D,kBAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAM;AAC9D,CAAC;AAIM,IAAM,kBAA+B,aAAa,MAAM,CAAC,CAAC;","names":[]}
@@ -0,0 +1,38 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ CONFIG_DEFAULTS,
4
+ configSchema
5
+ } from "./chunk-JVIBUEVN.js";
6
+
7
+ // src/config/config-store.ts
8
+ import Conf from "conf";
9
+ var ConfigStore = class {
10
+ store;
11
+ constructor() {
12
+ this.store = new Conf({
13
+ projectName: "stamn",
14
+ defaults: CONFIG_DEFAULTS
15
+ });
16
+ }
17
+ get(key) {
18
+ return this.store.get(key);
19
+ }
20
+ set(key, value) {
21
+ configSchema.partial().parse({ [key]: value });
22
+ this.store.set(key, value);
23
+ }
24
+ getAll() {
25
+ return configSchema.parse(this.store.store);
26
+ }
27
+ clear() {
28
+ this.store.clear();
29
+ }
30
+ get path() {
31
+ return this.store.path;
32
+ }
33
+ };
34
+
35
+ export {
36
+ ConfigStore
37
+ };
38
+ //# sourceMappingURL=chunk-KQC5O25P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config/config-store.ts"],"sourcesContent":["import Conf from 'conf';\nimport { configSchema, CONFIG_DEFAULTS, type AgentConfig } from './config-schema.js';\n\nexport class ConfigStore {\n private store: Conf<AgentConfig>;\n\n constructor() {\n this.store = new Conf<AgentConfig>({\n projectName: 'stamn',\n defaults: CONFIG_DEFAULTS,\n });\n }\n\n get<K extends keyof AgentConfig>(key: K): AgentConfig[K] {\n return this.store.get(key);\n }\n\n set<K extends keyof AgentConfig>(key: K, value: AgentConfig[K]): void {\n configSchema.partial().parse({ [key]: value });\n this.store.set(key, value);\n }\n\n getAll(): AgentConfig {\n return configSchema.parse(this.store.store);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n get path(): string {\n return this.store.path;\n }\n}\n"],"mappings":";;;;;;;AAAA,OAAO,UAAU;AAGV,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EAER,cAAc;AACZ,SAAK,QAAQ,IAAI,KAAkB;AAAA,MACjC,aAAa;AAAA,MACb,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,IAAiC,KAAwB;AACvD,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA,EAEA,IAAiC,KAAQ,OAA6B;AACpE,iBAAa,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC;AAC7C,SAAK,MAAM,IAAI,KAAK,KAAK;AAAA,EAC3B;AAAA,EAEA,SAAsB;AACpB,WAAO,aAAa,MAAM,KAAK,MAAM,KAAK;AAAA,EAC5C;AAAA,EAEA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;","names":[]}
@@ -1,15 +1,16 @@
1
1
  import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
2
  import {
3
- ConfigStore,
3
+ ConfigStore
4
+ } from "../../chunk-KQC5O25P.js";
5
+ import {
4
6
  configSchema
5
- } from "../../chunk-5UI5E6YF.js";
7
+ } from "../../chunk-JVIBUEVN.js";
6
8
 
7
9
  // src/commands/config/get.ts
8
10
  import { Args, Command } from "@oclif/core";
9
11
  var VALID_KEYS = Object.keys(configSchema.shape);
10
12
  var KEBAB_TO_CAMEL = {
11
13
  "api-key": "apiKey",
12
- "agent-id": "agentId",
13
14
  "log-level": "logLevel",
14
15
  "heartbeat-interval-ms": "heartbeatIntervalMs",
15
16
  "ws-reconnect-base-ms": "wsReconnectBaseMs",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/config/get.ts"],"sourcesContent":["import { Args, Command } from '@oclif/core';\nimport { ConfigStore } from '../../config/config-store.js';\nimport { configSchema } from '../../config/config-schema.js';\n\nconst VALID_KEYS = Object.keys(configSchema.shape);\n\nconst KEBAB_TO_CAMEL: Record<string, string> = {\n 'api-key': 'apiKey',\n 'agent-id': 'agentId',\n 'log-level': 'logLevel',\n 'heartbeat-interval-ms': 'heartbeatIntervalMs',\n 'ws-reconnect-base-ms': 'wsReconnectBaseMs',\n 'ws-reconnect-max-ms': 'wsReconnectMaxMs',\n};\n\nfunction resolveKey(input: string): string {\n return KEBAB_TO_CAMEL[input] ?? input;\n}\n\nexport default class ConfigGet extends Command {\n static override description = 'Get a configuration value';\n\n static override args = {\n key: Args.string({ description: 'Config key', required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(ConfigGet);\n const key = resolveKey(args.key);\n\n if (!VALID_KEYS.includes(key)) {\n const display = Object.keys(KEBAB_TO_CAMEL).join(', ');\n this.error(`Invalid key \"${args.key}\". Valid keys: ${display}`);\n }\n\n const store = new ConfigStore();\n const value = store.get(key as keyof typeof configSchema.shape);\n this.log(value != null ? String(value) : '(not set)');\n }\n}\n"],"mappings":";;;;;;;AAAA,SAAS,MAAM,eAAe;AAI9B,IAAM,aAAa,OAAO,KAAK,aAAa,KAAK;AAEjD,IAAM,iBAAyC;AAAA,EAC7C,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,uBAAuB;AACzB;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,eAAe,KAAK,KAAK;AAClC;AAEA,IAAqB,YAArB,MAAqB,mBAAkB,QAAQ;AAAA,EAC7C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,KAAK,KAAK,OAAO,EAAE,aAAa,cAAc,UAAU,KAAK,CAAC;AAAA,EAChE;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,UAAS;AAC3C,UAAM,MAAM,WAAW,KAAK,GAAG;AAE/B,QAAI,CAAC,WAAW,SAAS,GAAG,GAAG;AAC7B,YAAM,UAAU,OAAO,KAAK,cAAc,EAAE,KAAK,IAAI;AACrD,WAAK,MAAM,gBAAgB,KAAK,GAAG,kBAAkB,OAAO,EAAE;AAAA,IAChE;AAEA,UAAM,QAAQ,IAAI,YAAY;AAC9B,UAAM,QAAQ,MAAM,IAAI,GAAsC;AAC9D,SAAK,IAAI,SAAS,OAAO,OAAO,KAAK,IAAI,WAAW;AAAA,EACtD;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/commands/config/get.ts"],"sourcesContent":["import { Args, Command } from '@oclif/core';\nimport { ConfigStore } from '../../config/config-store.js';\nimport { configSchema } from '../../config/config-schema.js';\n\nconst VALID_KEYS = Object.keys(configSchema.shape);\n\nconst KEBAB_TO_CAMEL: Record<string, string> = {\n 'api-key': 'apiKey',\n 'log-level': 'logLevel',\n 'heartbeat-interval-ms': 'heartbeatIntervalMs',\n 'ws-reconnect-base-ms': 'wsReconnectBaseMs',\n 'ws-reconnect-max-ms': 'wsReconnectMaxMs',\n};\n\nfunction resolveKey(input: string): string {\n return KEBAB_TO_CAMEL[input] ?? input;\n}\n\nexport default class ConfigGet extends Command {\n static override description = 'Get a configuration value';\n\n static override args = {\n key: Args.string({ description: 'Config key', required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(ConfigGet);\n const key = resolveKey(args.key);\n\n if (!VALID_KEYS.includes(key)) {\n const display = Object.keys(KEBAB_TO_CAMEL).join(', ');\n this.error(`Invalid key \"${args.key}\". Valid keys: ${display}`);\n }\n\n const store = new ConfigStore();\n const value = store.get(key as keyof typeof configSchema.shape);\n this.log(value != null ? String(value) : '(not set)');\n }\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,MAAM,eAAe;AAI9B,IAAM,aAAa,OAAO,KAAK,aAAa,KAAK;AAEjD,IAAM,iBAAyC;AAAA,EAC7C,WAAW;AAAA,EACX,aAAa;AAAA,EACb,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,uBAAuB;AACzB;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,eAAe,KAAK,KAAK;AAClC;AAEA,IAAqB,YAArB,MAAqB,mBAAkB,QAAQ;AAAA,EAC7C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,KAAK,KAAK,OAAO,EAAE,aAAa,cAAc,UAAU,KAAK,CAAC;AAAA,EAChE;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,UAAS;AAC3C,UAAM,MAAM,WAAW,KAAK,GAAG;AAE/B,QAAI,CAAC,WAAW,SAAS,GAAG,GAAG;AAC7B,YAAM,UAAU,OAAO,KAAK,cAAc,EAAE,KAAK,IAAI;AACrD,WAAK,MAAM,gBAAgB,KAAK,GAAG,kBAAkB,OAAO,EAAE;AAAA,IAChE;AAEA,UAAM,QAAQ,IAAI,YAAY;AAC9B,UAAM,QAAQ,MAAM,IAAI,GAAsC;AAC9D,SAAK,IAAI,SAAS,OAAO,OAAO,KAAK,IAAI,WAAW;AAAA,EACtD;AACF;","names":[]}
@@ -1,7 +1,8 @@
1
1
  import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
2
  import {
3
3
  ConfigStore
4
- } from "../../chunk-5UI5E6YF.js";
4
+ } from "../../chunk-KQC5O25P.js";
5
+ import "../../chunk-JVIBUEVN.js";
5
6
 
6
7
  // src/commands/config/index.ts
7
8
  import { Command } from "@oclif/core";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/config/index.ts"],"sourcesContent":["import { Command } from '@oclif/core';\nimport { ConfigStore } from '../../config/config-store.js';\n\nexport default class ConfigShow extends Command {\n static override description = 'Show current configuration';\n\n async run(): Promise<void> {\n const store = new ConfigStore();\n const config = store.getAll();\n\n this.log(`Config file: ${store.path}\\n`);\n\n for (const [key, value] of Object.entries(config)) {\n const display =\n key === 'apiKey' && value\n ? `${String(value).slice(0, 4)}...`\n : (value ?? '(not set)');\n this.log(` ${key}: ${display}`);\n }\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,eAAe;AAGxB,IAAqB,aAArB,cAAwC,QAAQ;AAAA,EAC9C,OAAgB,cAAc;AAAA,EAE9B,MAAM,MAAqB;AACzB,UAAM,QAAQ,IAAI,YAAY;AAC9B,UAAM,SAAS,MAAM,OAAO;AAE5B,SAAK,IAAI,gBAAgB,MAAM,IAAI;AAAA,CAAI;AAEvC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,YAAM,UACJ,QAAQ,YAAY,QAChB,GAAG,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,QAC3B,SAAS;AAChB,WAAK,IAAI,KAAK,GAAG,KAAK,OAAO,EAAE;AAAA,IACjC;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/commands/config/index.ts"],"sourcesContent":["import { Command } from '@oclif/core';\nimport { ConfigStore } from '../../config/config-store.js';\n\nexport default class ConfigShow extends Command {\n static override description = 'Show current configuration';\n\n async run(): Promise<void> {\n const store = new ConfigStore();\n const config = store.getAll();\n\n this.log(`Config file: ${store.path}\\n`);\n\n for (const [key, value] of Object.entries(config)) {\n const display =\n key === 'apiKey' && value\n ? `${String(value).slice(0, 4)}...`\n : (value ?? '(not set)');\n this.log(` ${key}: ${display}`);\n }\n }\n}\n"],"mappings":";;;;;;;AAAA,SAAS,eAAe;AAGxB,IAAqB,aAArB,cAAwC,QAAQ;AAAA,EAC9C,OAAgB,cAAc;AAAA,EAE9B,MAAM,MAAqB;AACzB,UAAM,QAAQ,IAAI,YAAY;AAC9B,UAAM,SAAS,MAAM,OAAO;AAE5B,SAAK,IAAI,gBAAgB,MAAM,IAAI;AAAA,CAAI;AAEvC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,YAAM,UACJ,QAAQ,YAAY,QAChB,GAAG,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,QAC3B,SAAS;AAChB,WAAK,IAAI,KAAK,GAAG,KAAK,OAAO,EAAE;AAAA,IACjC;AAAA,EACF;AACF;","names":[]}
@@ -1,8 +1,10 @@
1
1
  import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
2
  import {
3
- ConfigStore,
3
+ ConfigStore
4
+ } from "../../chunk-KQC5O25P.js";
5
+ import {
4
6
  configSchema
5
- } from "../../chunk-5UI5E6YF.js";
7
+ } from "../../chunk-JVIBUEVN.js";
6
8
 
7
9
  // src/commands/config/set.ts
8
10
  import { Args, Command } from "@oclif/core";
@@ -14,7 +16,6 @@ var NUMERIC_KEYS = /* @__PURE__ */ new Set([
14
16
  ]);
15
17
  var KEBAB_TO_CAMEL = {
16
18
  "api-key": "apiKey",
17
- "agent-id": "agentId",
18
19
  "log-level": "logLevel",
19
20
  "heartbeat-interval-ms": "heartbeatIntervalMs",
20
21
  "ws-reconnect-base-ms": "wsReconnectBaseMs",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/config/set.ts"],"sourcesContent":["import { Args, Command } from '@oclif/core';\nimport { ConfigStore } from '../../config/config-store.js';\nimport { configSchema } from '../../config/config-schema.js';\n\nconst VALID_KEYS = Object.keys(configSchema.shape);\n\nconst NUMERIC_KEYS = new Set([\n 'heartbeatIntervalMs',\n 'wsReconnectBaseMs',\n 'wsReconnectMaxMs',\n]);\n\nconst KEBAB_TO_CAMEL: Record<string, string> = {\n 'api-key': 'apiKey',\n 'agent-id': 'agentId',\n 'log-level': 'logLevel',\n 'heartbeat-interval-ms': 'heartbeatIntervalMs',\n 'ws-reconnect-base-ms': 'wsReconnectBaseMs',\n 'ws-reconnect-max-ms': 'wsReconnectMaxMs',\n};\n\nfunction resolveKey(input: string): string {\n return KEBAB_TO_CAMEL[input] ?? input;\n}\n\nexport default class ConfigSet extends Command {\n static override description = 'Set a configuration value';\n\n static override args = {\n key: Args.string({ description: 'Config key', required: true }),\n value: Args.string({ description: 'Config value', required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(ConfigSet);\n const key = resolveKey(args.key);\n\n if (!VALID_KEYS.includes(key)) {\n const display = Object.keys(KEBAB_TO_CAMEL).join(', ');\n this.error(`Invalid key \"${args.key}\". Valid keys: ${display}`);\n }\n\n const store = new ConfigStore();\n const parsed = NUMERIC_KEYS.has(key) ? Number(args.value) : args.value;\n\n store.set(key as keyof typeof configSchema.shape, parsed as never);\n this.log(`Set ${args.key} = ${key === 'apiKey' ? '****' : args.value}`);\n }\n}\n"],"mappings":";;;;;;;AAAA,SAAS,MAAM,eAAe;AAI9B,IAAM,aAAa,OAAO,KAAK,aAAa,KAAK;AAEjD,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,iBAAyC;AAAA,EAC7C,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,uBAAuB;AACzB;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,eAAe,KAAK,KAAK;AAClC;AAEA,IAAqB,YAArB,MAAqB,mBAAkB,QAAQ;AAAA,EAC7C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,KAAK,KAAK,OAAO,EAAE,aAAa,cAAc,UAAU,KAAK,CAAC;AAAA,IAC9D,OAAO,KAAK,OAAO,EAAE,aAAa,gBAAgB,UAAU,KAAK,CAAC;AAAA,EACpE;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,UAAS;AAC3C,UAAM,MAAM,WAAW,KAAK,GAAG;AAE/B,QAAI,CAAC,WAAW,SAAS,GAAG,GAAG;AAC7B,YAAM,UAAU,OAAO,KAAK,cAAc,EAAE,KAAK,IAAI;AACrD,WAAK,MAAM,gBAAgB,KAAK,GAAG,kBAAkB,OAAO,EAAE;AAAA,IAChE;AAEA,UAAM,QAAQ,IAAI,YAAY;AAC9B,UAAM,SAAS,aAAa,IAAI,GAAG,IAAI,OAAO,KAAK,KAAK,IAAI,KAAK;AAEjE,UAAM,IAAI,KAAwC,MAAe;AACjE,SAAK,IAAI,OAAO,KAAK,GAAG,MAAM,QAAQ,WAAW,SAAS,KAAK,KAAK,EAAE;AAAA,EACxE;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/commands/config/set.ts"],"sourcesContent":["import { Args, Command } from '@oclif/core';\nimport { ConfigStore } from '../../config/config-store.js';\nimport { configSchema } from '../../config/config-schema.js';\n\nconst VALID_KEYS = Object.keys(configSchema.shape);\n\nconst NUMERIC_KEYS = new Set([\n 'heartbeatIntervalMs',\n 'wsReconnectBaseMs',\n 'wsReconnectMaxMs',\n]);\n\nconst KEBAB_TO_CAMEL: Record<string, string> = {\n 'api-key': 'apiKey',\n 'log-level': 'logLevel',\n 'heartbeat-interval-ms': 'heartbeatIntervalMs',\n 'ws-reconnect-base-ms': 'wsReconnectBaseMs',\n 'ws-reconnect-max-ms': 'wsReconnectMaxMs',\n};\n\nfunction resolveKey(input: string): string {\n return KEBAB_TO_CAMEL[input] ?? input;\n}\n\nexport default class ConfigSet extends Command {\n static override description = 'Set a configuration value';\n\n static override args = {\n key: Args.string({ description: 'Config key', required: true }),\n value: Args.string({ description: 'Config value', required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(ConfigSet);\n const key = resolveKey(args.key);\n\n if (!VALID_KEYS.includes(key)) {\n const display = Object.keys(KEBAB_TO_CAMEL).join(', ');\n this.error(`Invalid key \"${args.key}\". Valid keys: ${display}`);\n }\n\n const store = new ConfigStore();\n const parsed = NUMERIC_KEYS.has(key) ? Number(args.value) : args.value;\n\n store.set(key as keyof typeof configSchema.shape, parsed as never);\n this.log(`Set ${args.key} = ${key === 'apiKey' ? '****' : args.value}`);\n }\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,MAAM,eAAe;AAI9B,IAAM,aAAa,OAAO,KAAK,aAAa,KAAK;AAEjD,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,iBAAyC;AAAA,EAC7C,WAAW;AAAA,EACX,aAAa;AAAA,EACb,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,uBAAuB;AACzB;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,eAAe,KAAK,KAAK;AAClC;AAEA,IAAqB,YAArB,MAAqB,mBAAkB,QAAQ;AAAA,EAC7C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,KAAK,KAAK,OAAO,EAAE,aAAa,cAAc,UAAU,KAAK,CAAC;AAAA,IAC9D,OAAO,KAAK,OAAO,EAAE,aAAa,gBAAgB,UAAU,KAAK,CAAC;AAAA,EACpE;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,UAAS;AAC3C,UAAM,MAAM,WAAW,KAAK,GAAG;AAE/B,QAAI,CAAC,WAAW,SAAS,GAAG,GAAG;AAC7B,YAAM,UAAU,OAAO,KAAK,cAAc,EAAE,KAAK,IAAI;AACrD,WAAK,MAAM,gBAAgB,KAAK,GAAG,kBAAkB,OAAO,EAAE;AAAA,IAChE;AAEA,UAAM,QAAQ,IAAI,YAAY;AAC9B,UAAM,SAAS,aAAa,IAAI,GAAG,IAAI,OAAO,KAAK,KAAK,IAAI,KAAK;AAEjE,UAAM,IAAI,KAAwC,MAAe;AACjE,SAAK,IAAI,OAAO,KAAK,GAAG,MAAM,QAAQ,WAAW,SAAS,KAAK,KAAK,EAAE;AAAA,EACxE;AACF;","names":[]}
@@ -11,8 +11,6 @@ declare class Spend extends Command {
11
11
  description: _oclif_core_interfaces.OptionFlag<string, _oclif_core_interfaces.CustomOptions>;
12
12
  'recipient-agent': _oclif_core_interfaces.OptionFlag<string | undefined, _oclif_core_interfaces.CustomOptions>;
13
13
  'recipient-address': _oclif_core_interfaces.OptionFlag<string | undefined, _oclif_core_interfaces.CustomOptions>;
14
- 'agent-id': _oclif_core_interfaces.OptionFlag<string | undefined, _oclif_core_interfaces.CustomOptions>;
15
- 'api-key': _oclif_core_interfaces.OptionFlag<string | undefined, _oclif_core_interfaces.CustomOptions>;
16
14
  };
17
15
  run(): Promise<void>;
18
16
  }
@@ -3,10 +3,11 @@ import {
3
3
  SpendClient,
4
4
  WSClient,
5
5
  createLogger
6
- } from "../chunk-VTX4GGVR.js";
6
+ } from "../chunk-DJ3HR5OC.js";
7
7
  import {
8
8
  ConfigStore
9
- } from "../chunk-5UI5E6YF.js";
9
+ } from "../chunk-KQC5O25P.js";
10
+ import "../chunk-JVIBUEVN.js";
10
11
 
11
12
  // src/commands/spend.ts
12
13
  import { Command, Flags } from "@oclif/core";
@@ -37,18 +38,14 @@ var Spend = class _Spend extends Command {
37
38
  }),
38
39
  "recipient-address": Flags.string({
39
40
  description: "Recipient wallet address (for on-chain)"
40
- }),
41
- "agent-id": Flags.string({ env: "STAMN_AGENT_ID" }),
42
- "api-key": Flags.string({ env: "STAMN_API_KEY" })
41
+ })
43
42
  };
44
43
  async run() {
45
44
  const { flags } = await this.parse(_Spend);
46
45
  const configStore = new ConfigStore();
47
46
  const config = { ...configStore.getAll() };
48
- if (flags["agent-id"]) config.agentId = flags["agent-id"];
49
- if (flags["api-key"]) config.apiKey = flags["api-key"];
50
47
  if (!config.agentId) {
51
- this.error("agentId is required. Run: stamn config set agent-id <uuid>");
48
+ this.error("Not registered. Run `stamn start` first.");
52
49
  }
53
50
  const logger = createLogger({ logLevel: "info" });
54
51
  this.log("Connecting to Stamn...");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/spend.ts"],"sourcesContent":["import { Command, Flags } from '@oclif/core';\nimport { ConfigStore } from '../config/config-store.js';\nimport { createLogger } from '../logging/logger.js';\nimport { WSClient } from '../ws/ws-client.js';\nimport { SpendClient } from '../spend/spend-client.js';\nimport type { LedgerCategory, LedgerRail } from '@stamn/types';\n\nexport default class Spend extends Command {\n static override description =\n 'Send a spend request through the connected agent';\n\n static override flags = {\n amount: Flags.integer({\n required: true,\n description: 'Amount in cents',\n }),\n category: Flags.string({\n required: true,\n description: 'Spend category',\n options: ['api', 'compute', 'contractor', 'transfer'],\n }),\n rail: Flags.string({\n required: true,\n description: 'Payment rail',\n options: ['crypto_onchain', 'x402', 'internal'],\n }),\n vendor: Flags.string({ description: 'Vendor name' }),\n description: Flags.string({\n required: true,\n description: 'Spend description',\n }),\n 'recipient-agent': Flags.string({\n description: 'Recipient agent ID (for agent-to-agent)',\n }),\n 'recipient-address': Flags.string({\n description: 'Recipient wallet address (for on-chain)',\n }),\n 'agent-id': Flags.string({ env: 'STAMN_AGENT_ID' }),\n 'api-key': Flags.string({ env: 'STAMN_API_KEY' }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Spend);\n const configStore = new ConfigStore();\n const config = { ...configStore.getAll() };\n\n if (flags['agent-id']) config.agentId = flags['agent-id'];\n if (flags['api-key']) config.apiKey = flags['api-key'];\n\n if (!config.agentId) {\n this.error('agentId is required. Run: stamn config set agent-id <uuid>');\n }\n\n const logger = createLogger({ logLevel: 'info' });\n\n this.log('Connecting to Stamn...');\n\n const client = new WSClient({\n config,\n logger,\n onCommand: () => {},\n onDisconnect: () => {},\n onConnected: async () => {\n this.log('Authenticated. Sending spend request...\\n');\n\n const spendClient = new SpendClient(client, logger);\n const result = await spendClient.request({\n amountCents: flags.amount,\n category: flags.category as LedgerCategory,\n rail: flags.rail as LedgerRail,\n vendor: flags.vendor,\n description: flags.description,\n recipientAgentId: flags['recipient-agent'],\n recipientAddress: flags['recipient-address'],\n });\n\n if (result.approved) {\n this.log('Spend APPROVED');\n this.log(` Ledger Entry: ${result.ledgerEntryId}`);\n if (result.transactionHash) {\n this.log(` Tx Hash: ${result.transactionHash}`);\n }\n this.log(` Remaining: ${result.remainingBalanceCents} cents`);\n } else {\n this.log('Spend DENIED');\n this.log(` Reason: ${result.reason}`);\n this.log(` Code: ${result.code}`);\n }\n\n client.disconnect();\n process.exit(0);\n },\n });\n\n client.connect();\n }\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,SAAS,aAAa;AAO/B,IAAqB,QAArB,MAAqB,eAAc,QAAQ;AAAA,EACzC,OAAgB,cACd;AAAA,EAEF,OAAgB,QAAQ;AAAA,IACtB,QAAQ,MAAM,QAAQ;AAAA,MACpB,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IACD,UAAU,MAAM,OAAO;AAAA,MACrB,UAAU;AAAA,MACV,aAAa;AAAA,MACb,SAAS,CAAC,OAAO,WAAW,cAAc,UAAU;AAAA,IACtD,CAAC;AAAA,IACD,MAAM,MAAM,OAAO;AAAA,MACjB,UAAU;AAAA,MACV,aAAa;AAAA,MACb,SAAS,CAAC,kBAAkB,QAAQ,UAAU;AAAA,IAChD,CAAC;AAAA,IACD,QAAQ,MAAM,OAAO,EAAE,aAAa,cAAc,CAAC;AAAA,IACnD,aAAa,MAAM,OAAO;AAAA,MACxB,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IACD,mBAAmB,MAAM,OAAO;AAAA,MAC9B,aAAa;AAAA,IACf,CAAC;AAAA,IACD,qBAAqB,MAAM,OAAO;AAAA,MAChC,aAAa;AAAA,IACf,CAAC;AAAA,IACD,YAAY,MAAM,OAAO,EAAE,KAAK,iBAAiB,CAAC;AAAA,IAClD,WAAW,MAAM,OAAO,EAAE,KAAK,gBAAgB,CAAC;AAAA,EAClD;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,MAAK;AACxC,UAAM,cAAc,IAAI,YAAY;AACpC,UAAM,SAAS,EAAE,GAAG,YAAY,OAAO,EAAE;AAEzC,QAAI,MAAM,UAAU,EAAG,QAAO,UAAU,MAAM,UAAU;AACxD,QAAI,MAAM,SAAS,EAAG,QAAO,SAAS,MAAM,SAAS;AAErD,QAAI,CAAC,OAAO,SAAS;AACnB,WAAK,MAAM,4DAA4D;AAAA,IACzE;AAEA,UAAM,SAAS,aAAa,EAAE,UAAU,OAAO,CAAC;AAEhD,SAAK,IAAI,wBAAwB;AAEjC,UAAM,SAAS,IAAI,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,WAAW,MAAM;AAAA,MAAC;AAAA,MAClB,cAAc,MAAM;AAAA,MAAC;AAAA,MACrB,aAAa,YAAY;AACvB,aAAK,IAAI,2CAA2C;AAEpD,cAAM,cAAc,IAAI,YAAY,QAAQ,MAAM;AAClD,cAAM,SAAS,MAAM,YAAY,QAAQ;AAAA,UACvC,aAAa,MAAM;AAAA,UACnB,UAAU,MAAM;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,QAAQ,MAAM;AAAA,UACd,aAAa,MAAM;AAAA,UACnB,kBAAkB,MAAM,iBAAiB;AAAA,UACzC,kBAAkB,MAAM,mBAAmB;AAAA,QAC7C,CAAC;AAED,YAAI,OAAO,UAAU;AACnB,eAAK,IAAI,gBAAgB;AACzB,eAAK,IAAI,mBAAmB,OAAO,aAAa,EAAE;AAClD,cAAI,OAAO,iBAAiB;AAC1B,iBAAK,IAAI,mBAAmB,OAAO,eAAe,EAAE;AAAA,UACtD;AACA,eAAK,IAAI,mBAAmB,OAAO,qBAAqB,QAAQ;AAAA,QAClE,OAAO;AACL,eAAK,IAAI,cAAc;AACvB,eAAK,IAAI,aAAa,OAAO,MAAM,EAAE;AACrC,eAAK,IAAI,aAAa,OAAO,IAAI,EAAE;AAAA,QACrC;AAEA,eAAO,WAAW;AAClB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF,CAAC;AAED,WAAO,QAAQ;AAAA,EACjB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/commands/spend.ts"],"sourcesContent":["import { Command, Flags } from '@oclif/core';\nimport { ConfigStore } from '../config/config-store.js';\nimport { createLogger } from '../logging/logger.js';\nimport { WSClient } from '../ws/ws-client.js';\nimport { SpendClient } from '../spend/spend-client.js';\nimport type { LedgerCategory, LedgerRail } from '@stamn/types';\n\nexport default class Spend extends Command {\n static override description =\n 'Send a spend request through the connected agent';\n\n static override flags = {\n amount: Flags.integer({\n required: true,\n description: 'Amount in cents',\n }),\n category: Flags.string({\n required: true,\n description: 'Spend category',\n options: ['api', 'compute', 'contractor', 'transfer'],\n }),\n rail: Flags.string({\n required: true,\n description: 'Payment rail',\n options: ['crypto_onchain', 'x402', 'internal'],\n }),\n vendor: Flags.string({ description: 'Vendor name' }),\n description: Flags.string({\n required: true,\n description: 'Spend description',\n }),\n 'recipient-agent': Flags.string({\n description: 'Recipient agent ID (for agent-to-agent)',\n }),\n 'recipient-address': Flags.string({\n description: 'Recipient wallet address (for on-chain)',\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Spend);\n const configStore = new ConfigStore();\n const config = { ...configStore.getAll() };\n\n if (!config.agentId) {\n this.error('Not registered. Run `stamn start` first.');\n }\n\n const logger = createLogger({ logLevel: 'info' });\n\n this.log('Connecting to Stamn...');\n\n const client = new WSClient({\n config,\n logger,\n onCommand: () => {},\n onDisconnect: () => {},\n onConnected: async () => {\n this.log('Authenticated. Sending spend request...\\n');\n\n const spendClient = new SpendClient(client, logger);\n const result = await spendClient.request({\n amountCents: flags.amount,\n category: flags.category as LedgerCategory,\n rail: flags.rail as LedgerRail,\n vendor: flags.vendor,\n description: flags.description,\n recipientAgentId: flags['recipient-agent'],\n recipientAddress: flags['recipient-address'],\n });\n\n if (result.approved) {\n this.log('Spend APPROVED');\n this.log(` Ledger Entry: ${result.ledgerEntryId}`);\n if (result.transactionHash) {\n this.log(` Tx Hash: ${result.transactionHash}`);\n }\n this.log(` Remaining: ${result.remainingBalanceCents} cents`);\n } else {\n this.log('Spend DENIED');\n this.log(` Reason: ${result.reason}`);\n this.log(` Code: ${result.code}`);\n }\n\n client.disconnect();\n process.exit(0);\n },\n });\n\n client.connect();\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,SAAS,aAAa;AAO/B,IAAqB,QAArB,MAAqB,eAAc,QAAQ;AAAA,EACzC,OAAgB,cACd;AAAA,EAEF,OAAgB,QAAQ;AAAA,IACtB,QAAQ,MAAM,QAAQ;AAAA,MACpB,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IACD,UAAU,MAAM,OAAO;AAAA,MACrB,UAAU;AAAA,MACV,aAAa;AAAA,MACb,SAAS,CAAC,OAAO,WAAW,cAAc,UAAU;AAAA,IACtD,CAAC;AAAA,IACD,MAAM,MAAM,OAAO;AAAA,MACjB,UAAU;AAAA,MACV,aAAa;AAAA,MACb,SAAS,CAAC,kBAAkB,QAAQ,UAAU;AAAA,IAChD,CAAC;AAAA,IACD,QAAQ,MAAM,OAAO,EAAE,aAAa,cAAc,CAAC;AAAA,IACnD,aAAa,MAAM,OAAO;AAAA,MACxB,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IACD,mBAAmB,MAAM,OAAO;AAAA,MAC9B,aAAa;AAAA,IACf,CAAC;AAAA,IACD,qBAAqB,MAAM,OAAO;AAAA,MAChC,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,MAAK;AACxC,UAAM,cAAc,IAAI,YAAY;AACpC,UAAM,SAAS,EAAE,GAAG,YAAY,OAAO,EAAE;AAEzC,QAAI,CAAC,OAAO,SAAS;AACnB,WAAK,MAAM,0CAA0C;AAAA,IACvD;AAEA,UAAM,SAAS,aAAa,EAAE,UAAU,OAAO,CAAC;AAEhD,SAAK,IAAI,wBAAwB;AAEjC,UAAM,SAAS,IAAI,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,WAAW,MAAM;AAAA,MAAC;AAAA,MAClB,cAAc,MAAM;AAAA,MAAC;AAAA,MACrB,aAAa,YAAY;AACvB,aAAK,IAAI,2CAA2C;AAEpD,cAAM,cAAc,IAAI,YAAY,QAAQ,MAAM;AAClD,cAAM,SAAS,MAAM,YAAY,QAAQ;AAAA,UACvC,aAAa,MAAM;AAAA,UACnB,UAAU,MAAM;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,QAAQ,MAAM;AAAA,UACd,aAAa,MAAM;AAAA,UACnB,kBAAkB,MAAM,iBAAiB;AAAA,UACzC,kBAAkB,MAAM,mBAAmB;AAAA,QAC7C,CAAC;AAED,YAAI,OAAO,UAAU;AACnB,eAAK,IAAI,gBAAgB;AACzB,eAAK,IAAI,mBAAmB,OAAO,aAAa,EAAE;AAClD,cAAI,OAAO,iBAAiB;AAC1B,iBAAK,IAAI,mBAAmB,OAAO,eAAe,EAAE;AAAA,UACtD;AACA,eAAK,IAAI,mBAAmB,OAAO,qBAAqB,QAAQ;AAAA,QAClE,OAAO;AACL,eAAK,IAAI,cAAc;AACvB,eAAK,IAAI,aAAa,OAAO,MAAM,EAAE;AACrC,eAAK,IAAI,aAAa,OAAO,IAAI,EAAE;AAAA,QACrC;AAEA,eAAO,WAAW;AAClB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF,CAAC;AAED,WAAO,QAAQ;AAAA,EACjB;AACF;","names":[]}
@@ -5,8 +5,6 @@ declare class Start extends Command {
5
5
  static description: string;
6
6
  static flags: {
7
7
  daemon: _oclif_core_interfaces.BooleanFlag<boolean>;
8
- 'agent-id': _oclif_core_interfaces.OptionFlag<string | undefined, _oclif_core_interfaces.CustomOptions>;
9
- 'api-key': _oclif_core_interfaces.OptionFlag<string | undefined, _oclif_core_interfaces.CustomOptions>;
10
8
  'log-level': _oclif_core_interfaces.OptionFlag<string | undefined, _oclif_core_interfaces.CustomOptions>;
11
9
  };
12
10
  run(): Promise<void>;
@@ -6,11 +6,13 @@ import {
6
6
  SpendClient,
7
7
  WSClient,
8
8
  createLogger
9
- } from "../chunk-VTX4GGVR.js";
9
+ } from "../chunk-DJ3HR5OC.js";
10
+ import {
11
+ ConfigStore
12
+ } from "../chunk-KQC5O25P.js";
10
13
  import {
11
- ConfigStore,
12
14
  SERVER_URL
13
- } from "../chunk-5UI5E6YF.js";
15
+ } from "../chunk-JVIBUEVN.js";
14
16
 
15
17
  // src/commands/start.ts
16
18
  import { Command, Flags } from "@oclif/core";
@@ -22,14 +24,6 @@ var Start = class _Start extends Command {
22
24
  description: "Run as background daemon",
23
25
  default: false
24
26
  }),
25
- "agent-id": Flags.string({
26
- description: "Override agent ID",
27
- env: "STAMN_AGENT_ID"
28
- }),
29
- "api-key": Flags.string({
30
- description: "Override API key",
31
- env: "STAMN_API_KEY"
32
- }),
33
27
  "log-level": Flags.string({
34
28
  description: "Override log level",
35
29
  options: ["trace", "debug", "info", "warn", "error", "fatal"]
@@ -39,14 +33,25 @@ var Start = class _Start extends Command {
39
33
  const { flags } = await this.parse(_Start);
40
34
  const configStore = new ConfigStore();
41
35
  const config = { ...configStore.getAll() };
42
- if (flags["agent-id"]) config.agentId = flags["agent-id"];
43
- if (flags["api-key"]) config.apiKey = flags["api-key"];
44
36
  if (flags["log-level"])
45
37
  config.logLevel = flags["log-level"];
46
- if (!config.agentId) {
47
- this.error(
48
- "agentId is required. Run: stamn config set agent-id <uuid>"
49
- );
38
+ if (!config.apiKey || !config.agentId) {
39
+ if (flags.daemon || !process.stdout.isTTY) {
40
+ this.error(
41
+ "Not registered. Run `stamn start` interactively first."
42
+ );
43
+ }
44
+ const { runSetup } = await import("../ui/setup.js");
45
+ try {
46
+ const result = await runSetup();
47
+ configStore.set("apiKey", result.apiKey);
48
+ configStore.set("agentId", result.agentId);
49
+ configStore.set("agentName", result.agentName);
50
+ config.apiKey = result.apiKey;
51
+ config.agentId = result.agentId;
52
+ } catch {
53
+ this.error("Setup cancelled.");
54
+ }
50
55
  }
51
56
  const dm = new DaemonManager();
52
57
  const { running, pid } = dm.isRunning();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/start.ts"],"sourcesContent":["import { Command, Flags } from '@oclif/core';\nimport { ConfigStore } from '../config/config-store.js';\nimport { SERVER_URL, type AgentConfig } from '../config/config-schema.js';\nimport { createLogger } from '../logging/logger.js';\nimport { WSClient } from '../ws/ws-client.js';\nimport { SpendClient } from '../spend/spend-client.js';\nimport { DaemonManager } from '../daemon/daemon-manager.js';\n\nexport default class Start extends Command {\n static override description = 'Start the Stamn agent daemon';\n\n static override flags = {\n daemon: Flags.boolean({\n char: 'd',\n description: 'Run as background daemon',\n default: false,\n }),\n 'agent-id': Flags.string({\n description: 'Override agent ID',\n env: 'STAMN_AGENT_ID',\n }),\n 'api-key': Flags.string({\n description: 'Override API key',\n env: 'STAMN_API_KEY',\n }),\n 'log-level': Flags.string({\n description: 'Override log level',\n options: ['trace', 'debug', 'info', 'warn', 'error', 'fatal'],\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Start);\n const configStore = new ConfigStore();\n const config = { ...configStore.getAll() };\n\n // Apply flag overrides\n if (flags['agent-id']) config.agentId = flags['agent-id'];\n if (flags['api-key']) config.apiKey = flags['api-key'];\n if (flags['log-level'])\n config.logLevel = flags['log-level'] as AgentConfig['logLevel'];\n\n // Validate required fields\n if (!config.agentId) {\n this.error(\n 'agentId is required. Run: stamn config set agent-id <uuid>',\n );\n }\n\n // Check for existing daemon\n const dm = new DaemonManager();\n const { running, pid } = dm.isRunning();\n if (running) {\n this.error(`Daemon already running (PID ${pid})`);\n }\n\n // Daemonize if requested\n if (flags.daemon) {\n const { daemonizeProcess } = await import('../daemon/process.js');\n await daemonizeProcess();\n }\n\n // Write PID\n dm.writePid(process.pid);\n\n const logger = createLogger(config);\n logger.info(\n { agentId: config.agentId, server: SERVER_URL },\n 'Starting Stamn agent',\n );\n\n // Create WebSocket client\n const client = new WSClient({\n config,\n logger,\n onCommand: (command, params) => {\n logger.info({ command, params }, 'Received command');\n if (command === 'shutdown') {\n shutdown();\n }\n },\n onDisconnect: () => {\n logger.warn('Disconnected from server');\n },\n onConnected: () => {\n logger.info('Agent is online and ready — spend capability active');\n },\n });\n\n // Create spend client — available for plugin/task integration\n const spendClient = new SpendClient(client, logger);\n\n // Expose on process for external plugin access\n (globalThis as Record<string, unknown>).__stamnSpendClient = spendClient;\n\n // Graceful shutdown\n const shutdown = () => {\n logger.info('Shutting down...');\n client.disconnect();\n dm.removePid();\n process.exit(0);\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n\n // Connect\n client.connect();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAAA,SAAS,SAAS,aAAa;AAQ/B,IAAqB,QAArB,MAAqB,eAAc,QAAQ;AAAA,EACzC,OAAgB,cAAc;AAAA,EAE9B,OAAgB,QAAQ;AAAA,IACtB,QAAQ,MAAM,QAAQ;AAAA,MACpB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,YAAY,MAAM,OAAO;AAAA,MACvB,aAAa;AAAA,MACb,KAAK;AAAA,IACP,CAAC;AAAA,IACD,WAAW,MAAM,OAAO;AAAA,MACtB,aAAa;AAAA,MACb,KAAK;AAAA,IACP,CAAC;AAAA,IACD,aAAa,MAAM,OAAO;AAAA,MACxB,aAAa;AAAA,MACb,SAAS,CAAC,SAAS,SAAS,QAAQ,QAAQ,SAAS,OAAO;AAAA,IAC9D,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,MAAK;AACxC,UAAM,cAAc,IAAI,YAAY;AACpC,UAAM,SAAS,EAAE,GAAG,YAAY,OAAO,EAAE;AAGzC,QAAI,MAAM,UAAU,EAAG,QAAO,UAAU,MAAM,UAAU;AACxD,QAAI,MAAM,SAAS,EAAG,QAAO,SAAS,MAAM,SAAS;AACrD,QAAI,MAAM,WAAW;AACnB,aAAO,WAAW,MAAM,WAAW;AAGrC,QAAI,CAAC,OAAO,SAAS;AACnB,WAAK;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,UAAM,KAAK,IAAI,cAAc;AAC7B,UAAM,EAAE,SAAS,IAAI,IAAI,GAAG,UAAU;AACtC,QAAI,SAAS;AACX,WAAK,MAAM,+BAA+B,GAAG,GAAG;AAAA,IAClD;AAGA,QAAI,MAAM,QAAQ;AAChB,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,wBAAsB;AAChE,YAAM,iBAAiB;AAAA,IACzB;AAGA,OAAG,SAAS,QAAQ,GAAG;AAEvB,UAAM,SAAS,aAAa,MAAM;AAClC,WAAO;AAAA,MACL,EAAE,SAAS,OAAO,SAAS,QAAQ,WAAW;AAAA,MAC9C;AAAA,IACF;AAGA,UAAM,SAAS,IAAI,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,WAAW,CAAC,SAAS,WAAW;AAC9B,eAAO,KAAK,EAAE,SAAS,OAAO,GAAG,kBAAkB;AACnD,YAAI,YAAY,YAAY;AAC1B,mBAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,cAAc,MAAM;AAClB,eAAO,KAAK,0BAA0B;AAAA,MACxC;AAAA,MACA,aAAa,MAAM;AACjB,eAAO,KAAK,0DAAqD;AAAA,MACnE;AAAA,IACF,CAAC;AAGD,UAAM,cAAc,IAAI,YAAY,QAAQ,MAAM;AAGlD,IAAC,WAAuC,qBAAqB;AAG7D,UAAM,WAAW,MAAM;AACrB,aAAO,KAAK,kBAAkB;AAC9B,aAAO,WAAW;AAClB,SAAG,UAAU;AACb,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,GAAG,WAAW,QAAQ;AAC9B,YAAQ,GAAG,UAAU,QAAQ;AAG7B,WAAO,QAAQ;AAAA,EACjB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/commands/start.ts"],"sourcesContent":["import { Command, Flags } from '@oclif/core';\nimport { ConfigStore } from '../config/config-store.js';\nimport { SERVER_URL, type AgentConfig } from '../config/config-schema.js';\nimport { createLogger } from '../logging/logger.js';\nimport { WSClient } from '../ws/ws-client.js';\nimport { SpendClient } from '../spend/spend-client.js';\nimport { DaemonManager } from '../daemon/daemon-manager.js';\n\nexport default class Start extends Command {\n static override description = 'Start the Stamn agent daemon';\n\n static override flags = {\n daemon: Flags.boolean({\n char: 'd',\n description: 'Run as background daemon',\n default: false,\n }),\n 'log-level': Flags.string({\n description: 'Override log level',\n options: ['trace', 'debug', 'info', 'warn', 'error', 'fatal'],\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Start);\n const configStore = new ConfigStore();\n const config = { ...configStore.getAll() };\n\n // Apply flag overrides\n if (flags['log-level'])\n config.logLevel = flags['log-level'] as AgentConfig['logLevel'];\n\n // Interactive setup when not registered\n if (!config.apiKey || !config.agentId) {\n if (flags.daemon || !process.stdout.isTTY) {\n this.error(\n 'Not registered. Run `stamn start` interactively first.',\n );\n }\n\n const { runSetup } = await import('../ui/setup.js');\n try {\n const result = await runSetup();\n configStore.set('apiKey', result.apiKey);\n configStore.set('agentId', result.agentId);\n configStore.set('agentName', result.agentName);\n config.apiKey = result.apiKey;\n config.agentId = result.agentId;\n } catch {\n this.error('Setup cancelled.');\n }\n }\n\n // Check for existing daemon\n const dm = new DaemonManager();\n const { running, pid } = dm.isRunning();\n if (running) {\n this.error(`Daemon already running (PID ${pid})`);\n }\n\n // Daemonize if requested\n if (flags.daemon) {\n const { daemonizeProcess } = await import('../daemon/process.js');\n await daemonizeProcess();\n }\n\n // Write PID\n dm.writePid(process.pid);\n\n const logger = createLogger(config);\n logger.info(\n { agentId: config.agentId, server: SERVER_URL },\n 'Starting Stamn agent',\n );\n\n // Create WebSocket client\n const client = new WSClient({\n config,\n logger,\n onCommand: (command, params) => {\n logger.info({ command, params }, 'Received command');\n if (command === 'shutdown') {\n shutdown();\n }\n },\n onDisconnect: () => {\n logger.warn('Disconnected from server');\n },\n onConnected: () => {\n logger.info('Agent is online and ready — spend capability active');\n },\n });\n\n // Create spend client — available for plugin/task integration\n const spendClient = new SpendClient(client, logger);\n\n // Expose on process for external plugin access\n (globalThis as Record<string, unknown>).__stamnSpendClient = spendClient;\n\n // Graceful shutdown\n const shutdown = () => {\n logger.info('Shutting down...');\n client.disconnect();\n dm.removePid();\n process.exit(0);\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n\n // Connect\n client.connect();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,aAAa;AAQ/B,IAAqB,QAArB,MAAqB,eAAc,QAAQ;AAAA,EACzC,OAAgB,cAAc;AAAA,EAE9B,OAAgB,QAAQ;AAAA,IACtB,QAAQ,MAAM,QAAQ;AAAA,MACpB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,aAAa,MAAM,OAAO;AAAA,MACxB,aAAa;AAAA,MACb,SAAS,CAAC,SAAS,SAAS,QAAQ,QAAQ,SAAS,OAAO;AAAA,IAC9D,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,MAAK;AACxC,UAAM,cAAc,IAAI,YAAY;AACpC,UAAM,SAAS,EAAE,GAAG,YAAY,OAAO,EAAE;AAGzC,QAAI,MAAM,WAAW;AACnB,aAAO,WAAW,MAAM,WAAW;AAGrC,QAAI,CAAC,OAAO,UAAU,CAAC,OAAO,SAAS;AACrC,UAAI,MAAM,UAAU,CAAC,QAAQ,OAAO,OAAO;AACzC,aAAK;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAEA,YAAM,EAAE,SAAS,IAAI,MAAM,OAAO,gBAAgB;AAClD,UAAI;AACF,cAAM,SAAS,MAAM,SAAS;AAC9B,oBAAY,IAAI,UAAU,OAAO,MAAM;AACvC,oBAAY,IAAI,WAAW,OAAO,OAAO;AACzC,oBAAY,IAAI,aAAa,OAAO,SAAS;AAC7C,eAAO,SAAS,OAAO;AACvB,eAAO,UAAU,OAAO;AAAA,MAC1B,QAAQ;AACN,aAAK,MAAM,kBAAkB;AAAA,MAC/B;AAAA,IACF;AAGA,UAAM,KAAK,IAAI,cAAc;AAC7B,UAAM,EAAE,SAAS,IAAI,IAAI,GAAG,UAAU;AACtC,QAAI,SAAS;AACX,WAAK,MAAM,+BAA+B,GAAG,GAAG;AAAA,IAClD;AAGA,QAAI,MAAM,QAAQ;AAChB,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,wBAAsB;AAChE,YAAM,iBAAiB;AAAA,IACzB;AAGA,OAAG,SAAS,QAAQ,GAAG;AAEvB,UAAM,SAAS,aAAa,MAAM;AAClC,WAAO;AAAA,MACL,EAAE,SAAS,OAAO,SAAS,QAAQ,WAAW;AAAA,MAC9C;AAAA,IACF;AAGA,UAAM,SAAS,IAAI,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,WAAW,CAAC,SAAS,WAAW;AAC9B,eAAO,KAAK,EAAE,SAAS,OAAO,GAAG,kBAAkB;AACnD,YAAI,YAAY,YAAY;AAC1B,mBAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,cAAc,MAAM;AAClB,eAAO,KAAK,0BAA0B;AAAA,MACxC;AAAA,MACA,aAAa,MAAM;AACjB,eAAO,KAAK,0DAAqD;AAAA,MACnE;AAAA,IACF,CAAC;AAGD,UAAM,cAAc,IAAI,YAAY,QAAQ,MAAM;AAGlD,IAAC,WAAuC,qBAAqB;AAG7D,UAAM,WAAW,MAAM;AACrB,aAAO,KAAK,kBAAkB;AAC9B,aAAO,WAAW;AAClB,SAAG,UAAU;AACb,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,GAAG,WAAW,QAAQ;AAC9B,YAAQ,GAAG,UAAU,QAAQ;AAG7B,WAAO,QAAQ;AAAA,EACjB;AACF;","names":[]}
@@ -3,9 +3,11 @@ import {
3
3
  DaemonManager
4
4
  } from "../chunk-DCE6ICKM.js";
5
5
  import {
6
- ConfigStore,
6
+ ConfigStore
7
+ } from "../chunk-KQC5O25P.js";
8
+ import {
7
9
  SERVER_URL
8
- } from "../chunk-5UI5E6YF.js";
10
+ } from "../chunk-JVIBUEVN.js";
9
11
 
10
12
  // src/commands/status.ts
11
13
  import { Command } from "@oclif/core";
@@ -19,7 +21,7 @@ var Status = class extends Command {
19
21
  this.log("Stamn Agent Status");
20
22
  this.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
21
23
  this.log(`Daemon: ${running ? `running (PID ${pid})` : "stopped"}`);
22
- this.log(`Agent ID: ${config.agentId ?? "(not set)"}`);
24
+ this.log(`Agent: ${config.agentName ?? config.agentId ?? "(not registered)"}`);
23
25
  this.log(`Log Level: ${config.logLevel}`);
24
26
  this.log(`Config: ${configStore.path}`);
25
27
  this.log(`PID File: ${dm.pidFilePath}`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/status.ts"],"sourcesContent":["import { Command } from '@oclif/core';\nimport { DaemonManager } from '../daemon/daemon-manager.js';\nimport { ConfigStore } from '../config/config-store.js';\nimport { SERVER_URL } from '../config/config-schema.js';\n\nexport default class Status extends Command {\n static override description = 'Show Stamn agent daemon status';\n\n async run(): Promise<void> {\n const dm = new DaemonManager();\n const configStore = new ConfigStore();\n const config = configStore.getAll();\n const { running, pid } = dm.isRunning();\n\n this.log('Stamn Agent Status');\n this.log('──────────────────');\n this.log(`Daemon: ${running ? `running (PID ${pid})` : 'stopped'}`);\n this.log(`Agent ID: ${config.agentId ?? '(not set)'}`);\n this.log(`Log Level: ${config.logLevel}`);\n this.log(`Config: ${configStore.path}`);\n this.log(`PID File: ${dm.pidFilePath}`);\n\n if (running) {\n try {\n const res = await fetch(`${SERVER_URL}/v1/health`);\n const data = (await res.json()) as { data?: { status?: string } };\n this.log(`Server: ${data.data?.status ?? 'unknown'}`);\n } catch {\n this.log('Server: unreachable');\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,eAAe;AAKxB,IAAqB,SAArB,cAAoC,QAAQ;AAAA,EAC1C,OAAgB,cAAc;AAAA,EAE9B,MAAM,MAAqB;AACzB,UAAM,KAAK,IAAI,cAAc;AAC7B,UAAM,cAAc,IAAI,YAAY;AACpC,UAAM,SAAS,YAAY,OAAO;AAClC,UAAM,EAAE,SAAS,IAAI,IAAI,GAAG,UAAU;AAEtC,SAAK,IAAI,oBAAoB;AAC7B,SAAK,IAAI,8GAAoB;AAC7B,SAAK,IAAI,eAAe,UAAU,gBAAgB,GAAG,MAAM,SAAS,EAAE;AACtE,SAAK,IAAI,eAAe,OAAO,WAAW,WAAW,EAAE;AACvD,SAAK,IAAI,eAAe,OAAO,QAAQ,EAAE;AACzC,SAAK,IAAI,eAAe,YAAY,IAAI,EAAE;AAC1C,SAAK,IAAI,eAAe,GAAG,WAAW,EAAE;AAExC,QAAI,SAAS;AACX,UAAI;AACF,cAAM,MAAM,MAAM,MAAM,GAAG,UAAU,YAAY;AACjD,cAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,aAAK,IAAI,eAAe,KAAK,MAAM,UAAU,SAAS,EAAE;AAAA,MAC1D,QAAQ;AACN,aAAK,IAAI,yBAAyB;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/commands/status.ts"],"sourcesContent":["import { Command } from '@oclif/core';\nimport { DaemonManager } from '../daemon/daemon-manager.js';\nimport { ConfigStore } from '../config/config-store.js';\nimport { SERVER_URL } from '../config/config-schema.js';\n\nexport default class Status extends Command {\n static override description = 'Show Stamn agent daemon status';\n\n async run(): Promise<void> {\n const dm = new DaemonManager();\n const configStore = new ConfigStore();\n const config = configStore.getAll();\n const { running, pid } = dm.isRunning();\n\n this.log('Stamn Agent Status');\n this.log('──────────────────');\n this.log(`Daemon: ${running ? `running (PID ${pid})` : 'stopped'}`);\n this.log(`Agent: ${config.agentName ?? config.agentId ?? '(not registered)'}`);\n this.log(`Log Level: ${config.logLevel}`);\n this.log(`Config: ${configStore.path}`);\n this.log(`PID File: ${dm.pidFilePath}`);\n\n if (running) {\n try {\n const res = await fetch(`${SERVER_URL}/v1/health`);\n const data = (await res.json()) as { data?: { status?: string } };\n this.log(`Server: ${data.data?.status ?? 'unknown'}`);\n } catch {\n this.log('Server: unreachable');\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,eAAe;AAKxB,IAAqB,SAArB,cAAoC,QAAQ;AAAA,EAC1C,OAAgB,cAAc;AAAA,EAE9B,MAAM,MAAqB;AACzB,UAAM,KAAK,IAAI,cAAc;AAC7B,UAAM,cAAc,IAAI,YAAY;AACpC,UAAM,SAAS,YAAY,OAAO;AAClC,UAAM,EAAE,SAAS,IAAI,IAAI,GAAG,UAAU;AAEtC,SAAK,IAAI,oBAAoB;AAC7B,SAAK,IAAI,8GAAoB;AAC7B,SAAK,IAAI,eAAe,UAAU,gBAAgB,GAAG,MAAM,SAAS,EAAE;AACtE,SAAK,IAAI,eAAe,OAAO,aAAa,OAAO,WAAW,kBAAkB,EAAE;AAClF,SAAK,IAAI,eAAe,OAAO,QAAQ,EAAE;AACzC,SAAK,IAAI,eAAe,YAAY,IAAI,EAAE;AAC1C,SAAK,IAAI,eAAe,GAAG,WAAW,EAAE;AAExC,QAAI,SAAS;AACX,UAAI;AACF,cAAM,MAAM,MAAM,MAAM,GAAG,UAAU,YAAY;AACjD,cAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,aAAK,IAAI,eAAe,KAAK,MAAM,UAAU,SAAS,EAAE;AAAA,MAC1D,QAAQ;AACN,aAAK,IAAI,yBAAyB;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -6,13 +6,13 @@ import { execSync } from "child_process";
6
6
  var Update = class extends Command {
7
7
  static description = "Update the Stamn agent to the latest version";
8
8
  async run() {
9
- this.log(`Current version: ${"0.5.0"}`);
9
+ this.log(`Current version: ${"0.6.0"}`);
10
10
  this.log("Checking for updates...");
11
11
  try {
12
12
  const latest = execSync("npm view @stamn/agent version", {
13
13
  encoding: "utf-8"
14
14
  }).trim();
15
- if (latest === "0.5.0") {
15
+ if (latest === "0.6.0") {
16
16
  this.log("Already on the latest version.");
17
17
  return;
18
18
  }
@@ -0,0 +1,12 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ CONFIG_DEFAULTS,
4
+ SERVER_URL,
5
+ configSchema
6
+ } from "./chunk-JVIBUEVN.js";
7
+ export {
8
+ CONFIG_DEFAULTS,
9
+ SERVER_URL,
10
+ configSchema
11
+ };
12
+ //# sourceMappingURL=config-schema-BR4LGISX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,8 @@
1
+ interface SetupResult {
2
+ agentId: string;
3
+ apiKey: string;
4
+ agentName: string;
5
+ }
6
+ declare function runSetup(): Promise<SetupResult>;
7
+
8
+ export { type SetupResult, runSetup };
@@ -0,0 +1,104 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+
3
+ // src/ui/setup.tsx
4
+ import { render } from "ink";
5
+
6
+ // src/ui/components/setup-wizard.tsx
7
+ import { useState } from "react";
8
+ import { Box, Text } from "ink";
9
+ import { TextInput, Spinner, StatusMessage } from "@inkjs/ui";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ function SetupWizard({ onComplete }) {
12
+ const [step, setStep] = useState("api-key");
13
+ const [error, setError] = useState("");
14
+ const register = async (apiKey) => {
15
+ setStep("registering");
16
+ try {
17
+ const { SERVER_URL } = await import("../config-schema-BR4LGISX.js");
18
+ const res = await fetch(`${SERVER_URL}/v1/agents/register`, {
19
+ method: "POST",
20
+ headers: {
21
+ "Content-Type": "application/json",
22
+ Authorization: `Bearer ${apiKey}`
23
+ },
24
+ body: JSON.stringify({
25
+ platform: `${process.platform}-${process.arch}`
26
+ })
27
+ });
28
+ if (!res.ok) {
29
+ const body = await res.text();
30
+ throw new Error(body || `HTTP ${res.status}`);
31
+ }
32
+ const json = await res.json();
33
+ setStep("done");
34
+ onComplete({
35
+ agentId: json.data.id,
36
+ apiKey,
37
+ agentName: json.data.name
38
+ });
39
+ } catch (err) {
40
+ setError(err.message);
41
+ setStep("error");
42
+ }
43
+ };
44
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
45
+ /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
46
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "stamn" }),
47
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " setup" })
48
+ ] }),
49
+ step === "api-key" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
50
+ /* @__PURE__ */ jsx(Text, { children: "Enter your API key from the Stamn dashboard." }),
51
+ /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
52
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "> " }),
53
+ /* @__PURE__ */ jsx(
54
+ TextInput,
55
+ {
56
+ placeholder: "sk-...",
57
+ onSubmit: (value) => {
58
+ if (!value.trim()) {
59
+ setError("API key cannot be empty");
60
+ return;
61
+ }
62
+ setError("");
63
+ register(value.trim());
64
+ }
65
+ }
66
+ )
67
+ ] }),
68
+ error && step === "api-key" && /* @__PURE__ */ jsx(StatusMessage, { variant: "error", children: error })
69
+ ] }),
70
+ step === "registering" && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Spinner, { label: "Registering agent..." }) }),
71
+ step === "done" && /* @__PURE__ */ jsx(StatusMessage, { variant: "success", children: "Agent registered. Starting..." }),
72
+ step === "error" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
73
+ /* @__PURE__ */ jsxs(StatusMessage, { variant: "error", children: [
74
+ "Registration failed: ",
75
+ error
76
+ ] }),
77
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Check your API key and try again." })
78
+ ] }),
79
+ step === "api-key" && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press Ctrl+C to cancel" }) })
80
+ ] });
81
+ }
82
+
83
+ // src/ui/setup.tsx
84
+ import { jsx as jsx2 } from "react/jsx-runtime";
85
+ function runSetup() {
86
+ return new Promise((resolve, reject) => {
87
+ const { unmount, waitUntilExit } = render(
88
+ /* @__PURE__ */ jsx2(
89
+ SetupWizard,
90
+ {
91
+ onComplete: (result) => {
92
+ unmount();
93
+ resolve(result);
94
+ }
95
+ }
96
+ )
97
+ );
98
+ waitUntilExit().catch(reject);
99
+ });
100
+ }
101
+ export {
102
+ runSetup
103
+ };
104
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/ui/setup.tsx","../../src/ui/components/setup-wizard.tsx"],"sourcesContent":["import { render } from 'ink';\nimport { SetupWizard } from './components/setup-wizard.js';\n\nexport interface SetupResult {\n agentId: string;\n apiKey: string;\n agentName: string;\n}\n\nexport function runSetup(): Promise<SetupResult> {\n return new Promise((resolve, reject) => {\n const { unmount, waitUntilExit } = render(\n <SetupWizard\n onComplete={(result) => {\n unmount();\n resolve(result);\n }}\n />,\n );\n\n waitUntilExit().catch(reject);\n });\n}\n","import { useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { TextInput, Spinner, StatusMessage } from '@inkjs/ui';\n\ntype Step = 'api-key' | 'registering' | 'done' | 'error';\n\ninterface Props {\n onComplete: (result: { agentId: string; apiKey: string; agentName: string }) => void;\n}\n\ndeclare const AGENT_VERSION: string;\n\nexport function SetupWizard({ onComplete }: Props) {\n const [step, setStep] = useState<Step>('api-key');\n const [error, setError] = useState('');\n\n const register = async (apiKey: string) => {\n setStep('registering');\n\n try {\n const { SERVER_URL } = await import('../../config/config-schema.js');\n const res = await fetch(`${SERVER_URL}/v1/agents/register`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n platform: `${process.platform}-${process.arch}`,\n }),\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(body || `HTTP ${res.status}`);\n }\n\n const json = (await res.json()) as {\n data: { id: string; name: string };\n };\n setStep('done');\n onComplete({\n agentId: json.data.id,\n apiKey,\n agentName: json.data.name,\n });\n } catch (err) {\n setError((err as Error).message);\n setStep('error');\n }\n };\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box marginBottom={1}>\n <Text bold color=\"cyan\">\n stamn\n </Text>\n <Text dimColor> setup</Text>\n </Box>\n\n {step === 'api-key' && (\n <Box flexDirection=\"column\">\n <Text>Enter your API key from the Stamn dashboard.</Text>\n <Box marginTop={1}>\n <Text color=\"cyan\">{\"> \"}</Text>\n <TextInput\n placeholder=\"sk-...\"\n onSubmit={(value: string) => {\n if (!value.trim()) {\n setError('API key cannot be empty');\n return;\n }\n setError('');\n register(value.trim());\n }}\n />\n </Box>\n {error && step === 'api-key' && (\n <StatusMessage variant=\"error\">{error}</StatusMessage>\n )}\n </Box>\n )}\n\n {step === 'registering' && (\n <Box>\n <Spinner label=\"Registering agent...\" />\n </Box>\n )}\n\n {step === 'done' && (\n <StatusMessage variant=\"success\">\n Agent registered. Starting...\n </StatusMessage>\n )}\n\n {step === 'error' && (\n <Box flexDirection=\"column\">\n <StatusMessage variant=\"error\">\n Registration failed: {error}\n </StatusMessage>\n <Text dimColor>Check your API key and try again.</Text>\n </Box>\n )}\n\n {step === 'api-key' && (\n <Box marginTop={1}>\n <Text dimColor>Press Ctrl+C to cancel</Text>\n </Box>\n )}\n </Box>\n );\n}\n"],"mappings":";;;AAAA,SAAS,cAAc;;;ACAvB,SAAS,gBAAgB;AACzB,SAAS,KAAK,YAAY;AAC1B,SAAS,WAAW,SAAS,qBAAqB;AAoD5C,SACE,KADF;AA1CC,SAAS,YAAY,EAAE,WAAW,GAAU;AACjD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAe,SAAS;AAChD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AAErC,QAAM,WAAW,OAAO,WAAmB;AACzC,YAAQ,aAAa;AAErB,QAAI;AACF,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,8BAA+B;AACnE,YAAM,MAAM,MAAM,MAAM,GAAG,UAAU,uBAAuB;AAAA,QAC1D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,UAAU,MAAM;AAAA,QACjC;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,UAAU,GAAG,QAAQ,QAAQ,IAAI,QAAQ,IAAI;AAAA,QAC/C,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,cAAM,IAAI,MAAM,QAAQ,QAAQ,IAAI,MAAM,EAAE;AAAA,MAC9C;AAEA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAG7B,cAAQ,MAAM;AACd,iBAAW;AAAA,QACT,SAAS,KAAK,KAAK;AAAA,QACnB;AAAA,QACA,WAAW,KAAK,KAAK;AAAA,MACvB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,eAAU,IAAc,OAAO;AAC/B,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AAEA,SACE,qBAAC,OAAI,eAAc,UAAS,SAAS,GACnC;AAAA,yBAAC,OAAI,cAAc,GACjB;AAAA,0BAAC,QAAK,MAAI,MAAC,OAAM,QAAO,mBAExB;AAAA,MACA,oBAAC,QAAK,UAAQ,MAAC,oBAAM;AAAA,OACvB;AAAA,IAEC,SAAS,aACR,qBAAC,OAAI,eAAc,UACjB;AAAA,0BAAC,QAAK,0DAA4C;AAAA,MAClD,qBAAC,OAAI,WAAW,GACd;AAAA,4BAAC,QAAK,OAAM,QAAQ,gBAAK;AAAA,QACzB;AAAA,UAAC;AAAA;AAAA,YACC,aAAY;AAAA,YACZ,UAAU,CAAC,UAAkB;AAC3B,kBAAI,CAAC,MAAM,KAAK,GAAG;AACjB,yBAAS,yBAAyB;AAClC;AAAA,cACF;AACA,uBAAS,EAAE;AACX,uBAAS,MAAM,KAAK,CAAC;AAAA,YACvB;AAAA;AAAA,QACF;AAAA,SACF;AAAA,MACC,SAAS,SAAS,aACjB,oBAAC,iBAAc,SAAQ,SAAS,iBAAM;AAAA,OAE1C;AAAA,IAGD,SAAS,iBACR,oBAAC,OACC,8BAAC,WAAQ,OAAM,wBAAuB,GACxC;AAAA,IAGD,SAAS,UACR,oBAAC,iBAAc,SAAQ,WAAU,2CAEjC;AAAA,IAGD,SAAS,WACR,qBAAC,OAAI,eAAc,UACjB;AAAA,2BAAC,iBAAc,SAAQ,SAAQ;AAAA;AAAA,QACP;AAAA,SACxB;AAAA,MACA,oBAAC,QAAK,UAAQ,MAAC,+CAAiC;AAAA,OAClD;AAAA,IAGD,SAAS,aACR,oBAAC,OAAI,WAAW,GACd,8BAAC,QAAK,UAAQ,MAAC,oCAAsB,GACvC;AAAA,KAEJ;AAEJ;;;ADpGM,gBAAAA,YAAA;AAHC,SAAS,WAAiC;AAC/C,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,EAAE,SAAS,cAAc,IAAI;AAAA,MACjC,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,YAAY,CAAC,WAAW;AACtB,oBAAQ;AACR,oBAAQ,MAAM;AAAA,UAChB;AAAA;AAAA,MACF;AAAA,IACF;AAEA,kBAAc,EAAE,MAAM,MAAM;AAAA,EAC9B,CAAC;AACH;","names":["jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stamn/agent",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Stamn Agent Daemon CLI",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -40,18 +40,22 @@
40
40
  "prepublishOnly": "pnpm build"
41
41
  },
42
42
  "dependencies": {
43
+ "@inkjs/ui": "^2",
43
44
  "@oclif/core": "^4.2.0",
44
45
  "conf": "^13.0.1",
45
46
  "daemonize-process": "^3.0.0",
47
+ "ink": "^5",
46
48
  "pino": "^9.6.0",
47
49
  "pino-pretty": "^13.0.0",
50
+ "react": "^18",
48
51
  "ws": "^8.18.0",
49
52
  "zod": "^3.24.0"
50
53
  },
51
54
  "devDependencies": {
52
55
  "@stamn/types": "^0.1.0",
53
- "@types/ws": "^8.5.0",
54
56
  "@types/node": "^22.19.0",
57
+ "@types/react": "^18",
58
+ "@types/ws": "^8.5.0",
55
59
  "tsup": "^8.4.0",
56
60
  "typescript": "^5.7.0"
57
61
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/config-schema.ts","../src/config/config-store.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const SERVER_URL = 'https://api.stamn.com';\n\nexport const configSchema = z.object({\n apiKey: z.string().min(1).optional(),\n agentId: z.string().uuid().optional(),\n logLevel: z\n .enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal'])\n .default('info'),\n heartbeatIntervalMs: z.number().int().positive().default(30_000),\n wsReconnectBaseMs: z.number().int().positive().default(1_000),\n wsReconnectMaxMs: z.number().int().positive().default(30_000),\n});\n\nexport type AgentConfig = z.infer<typeof configSchema>;\n\nexport const CONFIG_DEFAULTS: AgentConfig = configSchema.parse({});\n","import Conf from 'conf';\nimport { configSchema, CONFIG_DEFAULTS, type AgentConfig } from './config-schema.js';\n\nexport class ConfigStore {\n private store: Conf<AgentConfig>;\n\n constructor() {\n this.store = new Conf<AgentConfig>({\n projectName: 'stamn',\n defaults: CONFIG_DEFAULTS,\n });\n }\n\n get<K extends keyof AgentConfig>(key: K): AgentConfig[K] {\n return this.store.get(key);\n }\n\n set<K extends keyof AgentConfig>(key: K, value: AgentConfig[K]): void {\n configSchema.partial().parse({ [key]: value });\n this.store.set(key, value);\n }\n\n getAll(): AgentConfig {\n return configSchema.parse(this.store.store);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n get path(): string {\n return this.store.path;\n }\n}\n"],"mappings":";;;AAAA,SAAS,SAAS;AAEX,IAAM,aAAa;AAEnB,IAAM,eAAe,EAAE,OAAO;AAAA,EACnC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACpC,UAAU,EACP,KAAK,CAAC,SAAS,SAAS,QAAQ,QAAQ,SAAS,OAAO,CAAC,EACzD,QAAQ,MAAM;AAAA,EACjB,qBAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAM;AAAA,EAC/D,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAK;AAAA,EAC5D,kBAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAM;AAC9D,CAAC;AAIM,IAAM,kBAA+B,aAAa,MAAM,CAAC,CAAC;;;ACjBjE,OAAO,UAAU;AAGV,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EAER,cAAc;AACZ,SAAK,QAAQ,IAAI,KAAkB;AAAA,MACjC,aAAa;AAAA,MACb,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,IAAiC,KAAwB;AACvD,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA,EAEA,IAAiC,KAAQ,OAA6B;AACpE,iBAAa,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC;AAC7C,SAAK,MAAM,IAAI,KAAK,KAAK;AAAA,EAC3B;AAAA,EAEA,SAAsB;AACpB,WAAO,aAAa,MAAM,KAAK,MAAM,KAAK;AAAA,EAC5C;AAAA,EAEA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;","names":[]}