@ouro.bot/cli 0.1.0-alpha.226 → 0.1.0-alpha.228

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.
@@ -1,290 +0,0 @@
1
- "use strict";
2
- /**
3
- * Bitwarden vault client for credential management.
4
- *
5
- * SDK-first approach: attempts dynamic import of @bitwarden/sdk-napi,
6
- * falls back to `bw` CLI with --session flag.
7
- *
8
- * Raw secrets are NEVER returned to callers except via getRawSecret(),
9
- * which is reserved for internal use by the credential gateway (apiRequest vaultKey).
10
- */
11
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
- if (k2 === undefined) k2 = k;
13
- var desc = Object.getOwnPropertyDescriptor(m, k);
14
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
- desc = { enumerable: true, get: function() { return m[k]; } };
16
- }
17
- Object.defineProperty(o, k2, desc);
18
- }) : (function(o, m, k, k2) {
19
- if (k2 === undefined) k2 = k;
20
- o[k2] = m[k];
21
- }));
22
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
- Object.defineProperty(o, "default", { enumerable: true, value: v });
24
- }) : function(o, v) {
25
- o["default"] = v;
26
- });
27
- var __importStar = (this && this.__importStar) || (function () {
28
- var ownKeys = function(o) {
29
- ownKeys = Object.getOwnPropertyNames || function (o) {
30
- var ar = [];
31
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
- return ar;
33
- };
34
- return ownKeys(o);
35
- };
36
- return function (mod) {
37
- if (mod && mod.__esModule) return mod;
38
- var result = {};
39
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
- __setModuleDefault(result, mod);
41
- return result;
42
- };
43
- })();
44
- Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.BitwardenClient = void 0;
46
- exports.getBitwardenClient = getBitwardenClient;
47
- exports.resetBitwardenClient = resetBitwardenClient;
48
- const child_process_1 = require("child_process");
49
- const runtime_1 = require("../nerves/runtime");
50
- class BitwardenClient {
51
- sessionKey = null;
52
- connected = false;
53
- clientMode = null;
54
- async connect(config) {
55
- (0, runtime_1.emitNervesEvent)({
56
- event: "client.vault_connect_start",
57
- component: "clients",
58
- message: "connecting to Bitwarden vault",
59
- meta: { mode: config.mode ?? "auto" },
60
- });
61
- try {
62
- if (config.mode === "cli") {
63
- await this.connectCli(config);
64
- }
65
- else {
66
- // Try SDK first, fall back to CLI
67
- try {
68
- await this.connectSdk(config);
69
- }
70
- catch {
71
- (0, runtime_1.emitNervesEvent)({
72
- event: "client.vault_sdk_fallback",
73
- component: "clients",
74
- message: "SDK not available, falling back to bw CLI",
75
- meta: {},
76
- });
77
- await this.connectCli(config);
78
- }
79
- }
80
- (0, runtime_1.emitNervesEvent)({
81
- event: "client.vault_connect_end",
82
- component: "clients",
83
- message: "connected to Bitwarden vault",
84
- meta: { mode: this.clientMode },
85
- });
86
- }
87
- catch (err) {
88
- (0, runtime_1.emitNervesEvent)({
89
- level: "error",
90
- event: "client.vault_connect_error",
91
- component: "clients",
92
- message: "failed to connect to Bitwarden vault",
93
- /* v8 ignore next -- defensive: execCli always wraps in Error @preserve */
94
- meta: { reason: err instanceof Error ? err.message : String(err) },
95
- });
96
- throw err;
97
- }
98
- }
99
- async disconnect() {
100
- this.sessionKey = null;
101
- this.connected = false;
102
- this.clientMode = null;
103
- (0, runtime_1.emitNervesEvent)({
104
- event: "client.vault_disconnect",
105
- component: "clients",
106
- message: "disconnected from Bitwarden vault",
107
- meta: {},
108
- });
109
- }
110
- isConnected() {
111
- return this.connected;
112
- }
113
- async getItem(id) {
114
- this.requireConnected();
115
- return this.withNervesEvents("getItem", { id }, async () => {
116
- const raw = await this.fetchRawItem(id);
117
- return this.stripSecrets(raw);
118
- });
119
- }
120
- async createItem(name, fields) {
121
- this.requireConnected();
122
- return this.withNervesEvents("createItem", { name }, async () => {
123
- const itemFields = Object.entries(fields).map(([k, v]) => ({
124
- name: k,
125
- value: v,
126
- type: 0, // text type
127
- }));
128
- const itemTemplate = {
129
- type: 1, // login type
130
- name,
131
- fields: itemFields,
132
- login: {},
133
- };
134
- const encoded = Buffer.from(JSON.stringify(itemTemplate)).toString("base64");
135
- const stdout = await this.execCli(["create", "item", encoded]);
136
- const parsed = this.parseCliResponse(stdout);
137
- return { id: parsed.id, name: parsed.name, type: parsed.type };
138
- });
139
- }
140
- async listItems(search) {
141
- this.requireConnected();
142
- return this.withNervesEvents("listItems", { search }, async () => {
143
- const args = ["list", "items"];
144
- if (search) {
145
- args.push("--search", search);
146
- }
147
- const stdout = await this.execCli(args);
148
- const parsed = this.parseCliResponse(stdout);
149
- const items = Array.isArray(parsed.data) ? parsed.data : (Array.isArray(parsed) ? parsed : []);
150
- return items.map((item) => ({ id: item.id, name: item.name, type: item.type }));
151
- });
152
- }
153
- async deleteItem(id) {
154
- this.requireConnected();
155
- return this.withNervesEvents("deleteItem", { id }, async () => {
156
- await this.execCli(["delete", "item", id]);
157
- });
158
- }
159
- /**
160
- * Internal: used by credential gateway (PR 5) to get raw secret for HTTP injection.
161
- * NOT exposed via tools -- only called by apiRequest() internally.
162
- */
163
- async getRawSecret(itemId, fieldName) {
164
- this.requireConnected();
165
- return this.withNervesEvents("getRawSecret", { itemId, fieldName }, async () => {
166
- const raw = await this.fetchRawItem(itemId);
167
- // Check custom fields first
168
- if (raw.fields) {
169
- const field = raw.fields.find((f) => f.name === fieldName);
170
- if (field)
171
- return field.value;
172
- }
173
- // Check login.password
174
- if (fieldName === "password" && raw.login?.password) {
175
- return raw.login.password;
176
- }
177
- throw new Error(`field "${fieldName}" not found on vault item "${itemId}"`);
178
- });
179
- }
180
- // --- Private methods ---
181
- requireConnected() {
182
- if (!this.connected) {
183
- throw new Error("vault not connected -- call connect() first");
184
- }
185
- }
186
- async withNervesEvents(operation, meta, fn) {
187
- (0, runtime_1.emitNervesEvent)({
188
- event: "client.request_start",
189
- component: "clients",
190
- message: `vault ${operation} starting`,
191
- meta: { operation, ...meta },
192
- });
193
- try {
194
- const result = await fn();
195
- (0, runtime_1.emitNervesEvent)({
196
- event: "client.request_end",
197
- component: "clients",
198
- message: `vault ${operation} complete`,
199
- meta: { operation, ...meta },
200
- });
201
- return result;
202
- }
203
- catch (err) {
204
- (0, runtime_1.emitNervesEvent)({
205
- level: "error",
206
- event: "client.error",
207
- component: "clients",
208
- message: `vault ${operation} failed`,
209
- /* v8 ignore next -- defensive: callers always throw Error instances @preserve */
210
- meta: { operation, reason: err instanceof Error ? err.message : String(err), ...meta },
211
- });
212
- throw err;
213
- }
214
- }
215
- async connectSdk(_config) {
216
- // Attempt dynamic import of SDK
217
- // This will throw if the package is not installed
218
- const sdk = await Promise.resolve(`${"@bitwarden/sdk-napi"}`).then(s => __importStar(require(s)));
219
- /* v8 ignore start -- SDK not yet published; path tested when package becomes available @preserve */
220
- const client = new sdk.BitwardenClient({ apiUrl: _config.serverUrl ?? "https://api.bitwarden.com" }, 0);
221
- await client.auth().loginAccessToken(_config.accessToken, "");
222
- this.connected = true;
223
- this.clientMode = "sdk";
224
- /* v8 ignore stop */
225
- }
226
- async connectCli(config) {
227
- this.sessionKey = config.accessToken;
228
- // Verify CLI is available and session key works
229
- await this.execCli(["status"]);
230
- this.connected = true;
231
- this.clientMode = "cli";
232
- }
233
- async fetchRawItem(id) {
234
- const stdout = await this.execCli(["get", "item", id]);
235
- const parsed = this.parseCliResponse(stdout);
236
- return parsed;
237
- }
238
- stripSecrets(raw) {
239
- const item = {
240
- id: raw.id,
241
- name: raw.name,
242
- type: raw.type,
243
- };
244
- if (raw.notes)
245
- item.notes = raw.notes;
246
- if (raw.fields)
247
- item.fields = raw.fields;
248
- if (raw.login) {
249
- item.login = {};
250
- if (raw.login.username)
251
- item.login.username = raw.login.username;
252
- if (raw.login.uris)
253
- item.login.uris = raw.login.uris;
254
- // password intentionally NOT copied
255
- }
256
- return item;
257
- }
258
- parseCliResponse(stdout) {
259
- const parsed = JSON.parse(stdout);
260
- // bw CLI with --response wraps in { success, data }
261
- if (parsed.success !== undefined && parsed.data !== undefined) {
262
- return parsed.data;
263
- }
264
- return parsed;
265
- }
266
- execCli(args) {
267
- return new Promise((resolve, reject) => {
268
- const fullArgs = [...args, "--session", this.sessionKey, "--response"];
269
- (0, child_process_1.execFile)("bw", fullArgs, { timeout: 30_000 }, (err, stdout, _stderr) => {
270
- if (err) {
271
- reject(new Error(`bw CLI error: ${err.message}`));
272
- return;
273
- }
274
- resolve(stdout);
275
- });
276
- });
277
- }
278
- }
279
- exports.BitwardenClient = BitwardenClient;
280
- // Singleton accessor
281
- let _client = null;
282
- function getBitwardenClient() {
283
- if (!_client) {
284
- _client = new BitwardenClient();
285
- }
286
- return _client;
287
- }
288
- function resetBitwardenClient() {
289
- _client = null;
290
- }
@@ -1,185 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.vaultToolDefinitions = void 0;
4
- const bitwarden_client_1 = require("./bitwarden-client");
5
- const runtime_1 = require("../nerves/runtime");
6
- exports.vaultToolDefinitions = [
7
- {
8
- tool: {
9
- type: "function",
10
- function: {
11
- name: "vault_get",
12
- description: "Retrieve a credential from the Bitwarden vault by ID or name. Returns metadata and fields but never raw passwords.",
13
- parameters: {
14
- type: "object",
15
- properties: {
16
- id: { type: "string", description: "Vault item ID (preferred)" },
17
- name: {
18
- type: "string",
19
- description: "Search by name (less precise, uses first match)",
20
- },
21
- },
22
- },
23
- },
24
- },
25
- handler: async (args) => {
26
- (0, runtime_1.emitNervesEvent)({
27
- component: "repertoire",
28
- event: "repertoire.vault_tool_call",
29
- message: "vault_get invoked",
30
- meta: { tool: "vault_get" },
31
- });
32
- try {
33
- const client = (0, bitwarden_client_1.getBitwardenClient)();
34
- if (args.id) {
35
- const item = await client.getItem(args.id);
36
- return JSON.stringify(item, null, 2);
37
- }
38
- if (args.name) {
39
- const items = await client.listItems(args.name);
40
- if (items.length === 0) {
41
- return `No vault item found matching "${args.name}". Try vault_list to see available items.`;
42
- }
43
- const item = await client.getItem(items[0].id);
44
- return JSON.stringify(item, null, 2);
45
- }
46
- return "Please provide either an id or name to look up a vault item.";
47
- }
48
- catch (err) {
49
- /* v8 ignore next -- defensive: callers throw Error instances @preserve */
50
- return `Vault error: ${err instanceof Error ? err.message : String(err)}`;
51
- }
52
- },
53
- summaryKeys: ["id", "name"],
54
- },
55
- {
56
- tool: {
57
- type: "function",
58
- function: {
59
- name: "vault_store",
60
- description: "Store a new credential in the Bitwarden vault. Supports login credentials, API keys, and structured fields.",
61
- parameters: {
62
- type: "object",
63
- properties: {
64
- name: { type: "string", description: "Name for the credential" },
65
- username: { type: "string", description: "Username (optional)" },
66
- password: { type: "string", description: "Password (optional)" },
67
- uri: { type: "string", description: "URI/URL (optional)" },
68
- notes: { type: "string", description: "Notes (optional)" },
69
- fields: {
70
- type: "string",
71
- description: 'JSON string of custom fields, e.g. {"apiKey": "key123", "region": "us-east"}',
72
- },
73
- },
74
- required: ["name"],
75
- },
76
- },
77
- },
78
- handler: async (args) => {
79
- (0, runtime_1.emitNervesEvent)({
80
- component: "repertoire",
81
- event: "repertoire.vault_tool_call",
82
- message: "vault_store invoked",
83
- meta: { tool: "vault_store", name: args.name },
84
- });
85
- try {
86
- const client = (0, bitwarden_client_1.getBitwardenClient)();
87
- const fields = {};
88
- if (args.username)
89
- fields.username = args.username;
90
- if (args.password)
91
- fields.password = args.password;
92
- if (args.uri)
93
- fields.uri = args.uri;
94
- if (args.notes)
95
- fields.notes = args.notes;
96
- if (args.fields) {
97
- const parsed = JSON.parse(args.fields);
98
- Object.assign(fields, parsed);
99
- }
100
- const handle = await client.createItem(args.name, fields);
101
- return JSON.stringify(handle, null, 2);
102
- }
103
- catch (err) {
104
- /* v8 ignore next -- defensive: callers throw Error instances @preserve */
105
- return `Vault error: ${err instanceof Error ? err.message : String(err)}`;
106
- }
107
- },
108
- confirmationRequired: true,
109
- summaryKeys: ["name"],
110
- },
111
- {
112
- tool: {
113
- type: "function",
114
- function: {
115
- name: "vault_list",
116
- description: "List credentials in the Bitwarden vault. Returns names and IDs only, never secrets.",
117
- parameters: {
118
- type: "object",
119
- properties: {
120
- search: {
121
- type: "string",
122
- description: "Optional search filter",
123
- },
124
- },
125
- },
126
- },
127
- },
128
- handler: async (args) => {
129
- (0, runtime_1.emitNervesEvent)({
130
- component: "repertoire",
131
- event: "repertoire.vault_tool_call",
132
- message: "vault_list invoked",
133
- meta: { tool: "vault_list" },
134
- });
135
- try {
136
- const client = (0, bitwarden_client_1.getBitwardenClient)();
137
- const items = await client.listItems(args.search);
138
- return JSON.stringify(items, null, 2);
139
- }
140
- catch (err) {
141
- /* v8 ignore next -- defensive: callers throw Error instances @preserve */
142
- return `Vault error: ${err instanceof Error ? err.message : String(err)}`;
143
- }
144
- },
145
- summaryKeys: ["search"],
146
- },
147
- {
148
- tool: {
149
- type: "function",
150
- function: {
151
- name: "vault_delete",
152
- description: "Delete a credential from the Bitwarden vault by ID.",
153
- parameters: {
154
- type: "object",
155
- properties: {
156
- id: {
157
- type: "string",
158
- description: "ID of the vault item to delete",
159
- },
160
- },
161
- required: ["id"],
162
- },
163
- },
164
- },
165
- handler: async (args) => {
166
- (0, runtime_1.emitNervesEvent)({
167
- component: "repertoire",
168
- event: "repertoire.vault_tool_call",
169
- message: "vault_delete invoked",
170
- meta: { tool: "vault_delete", id: args.id },
171
- });
172
- try {
173
- const client = (0, bitwarden_client_1.getBitwardenClient)();
174
- await client.deleteItem(args.id);
175
- return `Vault item ${args.id} deleted successfully.`;
176
- }
177
- catch (err) {
178
- /* v8 ignore next -- defensive: callers throw Error instances @preserve */
179
- return `Vault delete failed: ${err instanceof Error ? err.message : String(err)}`;
180
- }
181
- },
182
- confirmationRequired: true,
183
- summaryKeys: ["id"],
184
- },
185
- ];