@startanaicompany/crm 2.5.0 → 2.5.2

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.
Files changed (2) hide show
  1. package/index.js +174 -0
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -276,6 +276,9 @@ workspaceCmd
276
276
  .requiredOption('--name <keyname>', 'Name/label for the initial API key')
277
277
  .option('--scope <scope>', 'Key scope: agent (default) or admin', 'agent')
278
278
  .option('--admin-password <password>', 'Admin password (required for scope=admin; will prompt if not provided)')
279
+ .option('--owner-email <email>', 'Owner email — creates a human login account for /workspaces/login')
280
+ .option('--owner-password <password>', 'Owner password (min 8 chars) — required if --owner-email is provided')
281
+ .option('--owner-name <name>', 'Owner display name (default: Owner)')
279
282
  .option('--save-key', 'Save the returned key to CLI config (default: true)', true)
280
283
  .action(async (opts) => {
281
284
  const globalOpts = program.opts();
@@ -299,6 +302,17 @@ workspaceCmd
299
302
  body.admin_password = adminPw;
300
303
  }
301
304
 
305
+ // BUG-S9-B fix: pass owner credentials so /workspaces/login works immediately
306
+ if (opts.ownerEmail) {
307
+ if (!opts.ownerPassword) {
308
+ console.error('Error: --owner-password is required when --owner-email is provided');
309
+ process.exit(1);
310
+ }
311
+ body.owner_email = opts.ownerEmail.trim().toLowerCase();
312
+ body.owner_password = opts.ownerPassword;
313
+ if (opts.ownerName) body.owner_name = opts.ownerName.trim();
314
+ }
315
+
302
316
  try {
303
317
  const res = await axios.post(
304
318
  `${apiUrl.replace(/\/$/, '')}/api/v1/workspaces/register`,
@@ -308,6 +322,9 @@ workspaceCmd
308
322
  const data = res.data.data;
309
323
  console.log(`Workspace '${data.workspace}' initialized. API key created.`);
310
324
  console.log('Store the key — it will not be shown again.');
325
+ if (data.owner_user) {
326
+ console.log(`Owner user created: ${data.owner_user.email} — use POST /api/v1/workspaces/login to get a JWT.`);
327
+ }
311
328
  printJSON(data);
312
329
 
313
330
  // Auto-save to config
@@ -2131,4 +2148,161 @@ program
2131
2148
  }
2132
2149
  });
2133
2150
 
2151
+ // ============================================================
2152
+ // SUPPORT commands — Sprint 10 (saac_crm support bugs|features ...)
2153
+ // ============================================================
2154
+ const supportCmd = program.command('support').description('Submit and manage bug reports and feature requests');
2155
+
2156
+ ['bugs', 'features'].forEach((type) => {
2157
+ const typeCmd = supportCmd.command(type).description(`Manage ${type} support tickets`);
2158
+ const singular = type === 'bugs' ? 'bug' : 'feature';
2159
+
2160
+ typeCmd
2161
+ .command('add')
2162
+ .description(`Submit a new ${singular} report`)
2163
+ .requiredOption('--title <title>', `${singular} title (max 200 chars)`)
2164
+ .requiredOption('--description <desc>', 'Full description (max 2000 chars)')
2165
+ .option('--priority <p>', 'Priority: low|medium|high|critical (default: medium)', 'medium')
2166
+ .option('--cli-version <v>', 'Your CLI version (e.g. 2.5.1)')
2167
+ .option('--tags <tags>', 'Comma-separated tags (e.g. auth,login,ui)')
2168
+ .option('--severity <s>', type === 'bugs' ? 'Severity: cosmetic|minor|major|critical (bugs only)' : '(ignored for features)')
2169
+ .option('--from-agent-name <name>', 'Agent name for attribution (falls back to config defaultAgentName)')
2170
+ .action(async (opts) => {
2171
+ const globalOpts = program.opts();
2172
+ const agentName = resolveAgentName(opts.fromAgentName);
2173
+ const client = getClient(globalOpts, agentName);
2174
+ try {
2175
+ const body = {
2176
+ title: opts.title,
2177
+ description: opts.description,
2178
+ priority: opts.priority
2179
+ };
2180
+ if (opts.cliVersion) body.cli_version = opts.cliVersion;
2181
+ if (opts.tags) body.tags = opts.tags.split(',').map(t => t.trim()).filter(Boolean);
2182
+ if (opts.severity && type === 'bugs') body.severity = opts.severity;
2183
+ // GAP-S10-2: send agent_name in body as well (belt-and-suspenders alongside X-Agent-Name header)
2184
+ if (agentName) body.agent_name = agentName;
2185
+ const res = await client.post(`/support/${type}`, body);
2186
+ console.log(`${singular.charAt(0).toUpperCase() + singular.slice(1)} submitted. ID: ${res.data.data.id}`);
2187
+ printJSON(res.data);
2188
+ } catch (err) {
2189
+ handleError(err);
2190
+ }
2191
+ });
2192
+
2193
+ typeCmd
2194
+ .command('list')
2195
+ .description(`List your workspace's ${type}`)
2196
+ .action(async () => {
2197
+ const globalOpts = program.opts();
2198
+ const client = getClient(globalOpts);
2199
+ try {
2200
+ const res = await client.get(`/support/${type}`);
2201
+ printJSON(res.data);
2202
+ } catch (err) {
2203
+ handleError(err);
2204
+ }
2205
+ });
2206
+
2207
+ typeCmd
2208
+ .command('get')
2209
+ .description(`Get a ${singular} ticket by ID`)
2210
+ .requiredOption('--id <id>', 'Ticket ID')
2211
+ .action(async (opts) => {
2212
+ const globalOpts = program.opts();
2213
+ const client = getClient(globalOpts);
2214
+ try {
2215
+ const res = await client.get(`/support/${type}/${opts.id}`);
2216
+ printJSON(res.data);
2217
+ } catch (err) {
2218
+ handleError(err);
2219
+ }
2220
+ });
2221
+
2222
+ typeCmd
2223
+ .command('comments')
2224
+ .description(`List all comments on your ${singular} ticket`)
2225
+ .requiredOption('--id <id>', 'Ticket ID')
2226
+ .action(async (opts) => {
2227
+ const globalOpts = program.opts();
2228
+ const client = getClient(globalOpts);
2229
+ try {
2230
+ const res = await client.get(`/support/${type}/${opts.id}/comments`);
2231
+ printJSON(res.data);
2232
+ } catch (err) {
2233
+ handleError(err);
2234
+ }
2235
+ });
2236
+
2237
+ typeCmd
2238
+ .command('comment')
2239
+ .description(`Add a comment to your own ${singular} ticket`)
2240
+ .requiredOption('--id <id>', 'Ticket ID')
2241
+ .requiredOption('--message <msg>', 'Comment message (max 2000 chars)')
2242
+ .action(async (opts) => {
2243
+ const globalOpts = program.opts();
2244
+ const client = getClient(globalOpts);
2245
+ try {
2246
+ const res = await client.post(`/support/${type}/${opts.id}/comments`, {
2247
+ message: opts.message
2248
+ });
2249
+ console.log('Comment added.');
2250
+ printJSON(res.data);
2251
+ } catch (err) {
2252
+ handleError(err);
2253
+ }
2254
+ });
2255
+
2256
+ typeCmd
2257
+ .command('close')
2258
+ .description(`Close/withdraw your own ${singular} ticket (requires reason)`)
2259
+ .requiredOption('--id <id>', 'Ticket ID')
2260
+ .requiredOption('--reason <reason>', 'Reason for closing')
2261
+ .action(async (opts) => {
2262
+ const globalOpts = program.opts();
2263
+ const client = getClient(globalOpts);
2264
+ try {
2265
+ const res = await client.patch(`/support/${type}/${opts.id}/close`, { reason: opts.reason });
2266
+ console.log('Ticket closed.');
2267
+ printJSON(res.data);
2268
+ } catch (err) {
2269
+ handleError(err);
2270
+ }
2271
+ });
2272
+
2273
+ typeCmd
2274
+ .command('reopen')
2275
+ .description(`Reopen a resolved ${singular} ticket (requires note)`)
2276
+ .requiredOption('--id <id>', 'Ticket ID')
2277
+ .requiredOption('--note <note>', 'Explanation for reopening')
2278
+ .action(async (opts) => {
2279
+ const globalOpts = program.opts();
2280
+ const client = getClient(globalOpts);
2281
+ try {
2282
+ const res = await client.patch(`/support/${type}/${opts.id}/reopen`, { note: opts.note });
2283
+ console.log('Ticket reopened.');
2284
+ printJSON(res.data);
2285
+ } catch (err) {
2286
+ handleError(err);
2287
+ }
2288
+ });
2289
+
2290
+ typeCmd
2291
+ .command('update')
2292
+ .description(`Add a note to your ${singular} ticket (use when status is needs_more_info)`)
2293
+ .requiredOption('--id <id>', 'Ticket ID')
2294
+ .requiredOption('--note <note>', 'Additional information')
2295
+ .action(async (opts) => {
2296
+ const globalOpts = program.opts();
2297
+ const client = getClient(globalOpts);
2298
+ try {
2299
+ const res = await client.patch(`/support/${type}/${opts.id}/update`, { note: opts.note });
2300
+ console.log('Note added.');
2301
+ printJSON(res.data);
2302
+ } catch (err) {
2303
+ handleError(err);
2304
+ }
2305
+ });
2306
+ });
2307
+
2134
2308
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@startanaicompany/crm",
3
- "version": "2.5.0",
3
+ "version": "2.5.2",
4
4
  "description": "AI-first CRM CLI \u2014 manage leads and API keys from the terminal",
5
5
  "main": "index.js",
6
6
  "bin": {