@sente-labs/cli 0.8.1 → 0.10.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.
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerWebhookCommands = registerWebhookCommands;
4
+ const client_1 = require("../client");
5
+ const identityRef_1 = require("../identityRef");
6
+ const output_1 = require("../output");
7
+ /**
8
+ * `sente webhook …` — register YOUR endpoint so Sente pushes message events to it.
9
+ * Targets the Sente API (`/v1/webhooks`) with the stored API key.
10
+ */
11
+ function registerWebhookCommands(program, globalOpts) {
12
+ const webhook = program.command('webhook').description('Manage Sente webhooks (push delivery)');
13
+ webhook
14
+ .command('register')
15
+ .description('Point Sente at your HTTPS endpoint (idempotent per url+identity)')
16
+ .requiredOption('--url <url>', 'your HTTPS endpoint')
17
+ .option('--identity <ref>', 'scope to one identity — id, email, or local-part (default: all of the org)')
18
+ .option('--events <list>', 'comma-separated events', 'message.received')
19
+ .action(async (cmdOpts) => {
20
+ const opts = globalOpts();
21
+ try {
22
+ const client = new client_1.GatewayClient();
23
+ const body = {
24
+ url: cmdOpts.url,
25
+ events: (cmdOpts.events ?? 'message.received').split(',').map((e) => e.trim()).filter(Boolean),
26
+ };
27
+ if (cmdOpts.identity)
28
+ body.identityId = await (0, identityRef_1.resolveIdentityId)(client, cmdOpts.identity);
29
+ const w = await client.request('/v1/webhooks', { method: 'POST', body });
30
+ (0, output_1.printSuccess)(w, () => process.stdout.write(`Registered webhook ${w.id} → ${w.url}\nSecret: ${w.secret ?? '(unchanged)'}\nVerify the X-Sente-Secret header on each delivery.\n`), opts);
31
+ }
32
+ catch (err) {
33
+ process.exit((0, output_1.printError)(err, opts));
34
+ }
35
+ });
36
+ webhook
37
+ .command('list')
38
+ .description("List the organization's webhooks")
39
+ .action(async () => {
40
+ const opts = globalOpts();
41
+ try {
42
+ const rows = await new client_1.GatewayClient().request('/v1/webhooks');
43
+ (0, output_1.printSuccess)(rows, () => {
44
+ if (rows.length === 0) {
45
+ process.stdout.write('No webhooks. Register one with `sente webhook register --url <url>`.\n');
46
+ return;
47
+ }
48
+ for (const w of rows) {
49
+ process.stdout.write(`${w.id} ${w.url} [${w.events.join(',')}]${w.identityId ? ` →${w.identityId}` : ''}\n`);
50
+ }
51
+ }, opts);
52
+ }
53
+ catch (err) {
54
+ process.exit((0, output_1.printError)(err, opts));
55
+ }
56
+ });
57
+ webhook
58
+ .command('delete')
59
+ .description('Delete a webhook')
60
+ .argument('<id>', 'webhook id')
61
+ .action(async (id) => {
62
+ const opts = globalOpts();
63
+ try {
64
+ await new client_1.GatewayClient().request(`/v1/webhooks/${id}`, { method: 'DELETE' });
65
+ (0, output_1.printSuccess)({ id, deleted: true }, `Deleted webhook ${id}`, opts);
66
+ }
67
+ catch (err) {
68
+ process.exit((0, output_1.printError)(err, opts));
69
+ }
70
+ });
71
+ }
72
+ //# sourceMappingURL=webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/commands/webhook.ts"],"names":[],"mappings":";;AAkBA,0DAsEC;AAvFD,sCAA0C;AAC1C,gDAAmD;AACnD,sCAAiE;AAWjE;;;GAGG;AACH,SAAgB,uBAAuB,CAAC,OAAgB,EAAE,UAA4B;IACpF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,uCAAuC,CAAC,CAAC;IAEhG,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,kEAAkE,CAAC;SAC/E,cAAc,CAAC,aAAa,EAAE,qBAAqB,CAAC;SACpD,MAAM,CAAC,kBAAkB,EAAE,4EAA4E,CAAC;SACxG,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,EAAE,kBAAkB,CAAC;SACvE,MAAM,CAAC,KAAK,EAAE,OAA4D,EAAE,EAAE;QAC7E,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,sBAAa,EAAE,CAAC;YACnC,MAAM,IAAI,GAA4B;gBACpC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,kBAAkB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;aAC/F,CAAC;YACF,IAAI,OAAO,CAAC,QAAQ;gBAAE,IAAI,CAAC,UAAU,GAAG,MAAM,IAAA,+BAAiB,EAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC1F,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,OAAO,CAAU,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAClF,IAAA,qBAAY,EACV,CAAC,EACD,GAAG,EAAE,CACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sBAAsB,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,MAAM,IAAI,aAAa,wDAAwD,CACpI,EACH,IAAI,CACL,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,sBAAa,EAAE,CAAC,OAAO,CAAY,cAAc,CAAC,CAAC;YAC1E,IAAA,qBAAY,EACV,IAAI,EACJ,GAAG,EAAE;gBACH,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;oBAC/F,OAAO;gBACT,CAAC;gBACD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;oBACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAClH,CAAC;YACH,CAAC,EACD,IAAI,CACL,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,kBAAkB,CAAC;SAC/B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;SAC9B,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,IAAI,sBAAa,EAAE,CAAC,OAAO,CAAO,gBAAgB,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpF,IAAA,qBAAY,EAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,mBAAmB,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QACrE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
package/dist/config.js CHANGED
@@ -33,9 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.CREDENTIALS_PATH = exports.CREDENTIALS_DIR = exports.DEFAULT_GATEWAY_URL = void 0;
36
+ exports.DEFAULT_AUTH0_AUDIENCE = exports.DEFAULT_AUTH0_CLIENT_ID = exports.DEFAULT_AUTH0_DOMAIN = exports.CREDENTIALS_PATH = exports.CREDENTIALS_DIR = exports.DEFAULT_GATEWAY_URL = void 0;
37
37
  exports.gatewayUrl = gatewayUrl;
38
38
  exports.envToken = envToken;
39
+ exports.auth0Config = auth0Config;
39
40
  exports.readLocalProjectId = readLocalProjectId;
40
41
  /**
41
42
  * CLI runtime configuration. Env vars take precedence over defaults.
@@ -55,6 +56,18 @@ function gatewayUrl() {
55
56
  function envToken() {
56
57
  return process.env.SENTE_API_TOKEN || undefined;
57
58
  }
59
+ // Auth0 config for the browser login flow. These are PUBLIC values (the clientId already
60
+ // ships in the web app); overridable via env for other tenants.
61
+ exports.DEFAULT_AUTH0_DOMAIN = 'dev-ch2iktq4gawwhcom.us.auth0.com';
62
+ exports.DEFAULT_AUTH0_CLIENT_ID = 'U82GLhHVG8Mmh1NWQErOhKY73mkmq5Rs';
63
+ exports.DEFAULT_AUTH0_AUDIENCE = 'https://senteai.com';
64
+ function auth0Config() {
65
+ return {
66
+ domain: process.env.SENTE_AUTH0_DOMAIN || exports.DEFAULT_AUTH0_DOMAIN,
67
+ clientId: process.env.SENTE_AUTH0_CLIENT_ID || exports.DEFAULT_AUTH0_CLIENT_ID,
68
+ audience: process.env.SENTE_AUTH0_AUDIENCE || exports.DEFAULT_AUTH0_AUDIENCE,
69
+ };
70
+ }
58
71
  /**
59
72
  * Read the project id from the local .sente/config.json, walking up from the
60
73
  * cwd (same discovery as git/node_modules). Returns null if none is found.
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,gCAEC;AAED,4BAEC;AAOD,gDAgBC;AA3CD;;;;;GAKG;AACH,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAEhB,QAAA,mBAAmB,GAAG,uBAAuB,CAAC;AAC9C,QAAA,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACpD,QAAA,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,uBAAe,EAAE,aAAa,CAAC,CAAC;AAE1E,SAAgB,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,2BAAmB,CAAC;AAC9D,CAAC;AAED,SAAgB,QAAQ;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,SAAS,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB;IAChC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC1D,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC9D,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;oBAAE,OAAO,MAAM,CAAC,SAAS,CAAC;YACpE,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,gCAEC;AAED,4BAEC;AAQD,kCAMC;AAOD,gDAgBC;AAzDD;;;;;GAKG;AACH,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAEhB,QAAA,mBAAmB,GAAG,uBAAuB,CAAC;AAC9C,QAAA,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACpD,QAAA,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,uBAAe,EAAE,aAAa,CAAC,CAAC;AAE1E,SAAgB,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,2BAAmB,CAAC;AAC9D,CAAC;AAED,SAAgB,QAAQ;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,SAAS,CAAC;AAClD,CAAC;AAED,yFAAyF;AACzF,gEAAgE;AACnD,QAAA,oBAAoB,GAAG,mCAAmC,CAAC;AAC3D,QAAA,uBAAuB,GAAG,kCAAkC,CAAC;AAC7D,QAAA,sBAAsB,GAAG,qBAAqB,CAAC;AAE5D,SAAgB,WAAW;IACzB,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,4BAAoB;QAC9D,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,+BAAuB;QACtE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,8BAAsB;KACrE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB;IAChC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC1D,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC9D,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;oBAAE,OAAO,MAAM,CAAC,SAAS,CAAC;YACpE,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveIdentityId = resolveIdentityId;
4
+ const client_1 = require("./client");
5
+ /**
6
+ * Resolve an `--identity` value to the `idt_…` id. Accepts:
7
+ * - the id itself (`idt_…`) → returned as-is
8
+ * - the full email (`x@agents…`) → looked up
9
+ * - the local-part (`x`) → looked up (matched against the email's local-part)
10
+ * Names are NOT accepted — they aren't unique. One list call; cached per process.
11
+ */
12
+ let cache = null;
13
+ async function resolveIdentityId(client, value) {
14
+ const v = value.trim();
15
+ if (/^idt_/.test(v))
16
+ return v;
17
+ if (!cache)
18
+ cache = await client.request('/v1/identities');
19
+ const needle = v.toLowerCase();
20
+ const match = cache.find((r) => r.email.toLowerCase() === needle || r.email.toLowerCase().split('@')[0] === needle);
21
+ if (!match) {
22
+ throw new client_1.ApiError(404, 'IDENTITY_NOT_FOUND', `No identity matching "${value}". Use its local-part, email, or id — see \`sente identity list\`.`);
23
+ }
24
+ return match.id;
25
+ }
26
+ //# sourceMappingURL=identityRef.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identityRef.js","sourceRoot":"","sources":["../src/identityRef.ts"],"names":[],"mappings":";;AAgBA,8CAgBC;AAhCD,qCAAmD;AAOnD;;;;;;GAMG;AACH,IAAI,KAAK,GAAyB,IAAI,CAAC;AAEhC,KAAK,UAAU,iBAAiB,CAAC,MAAqB,EAAE,KAAa;IAC1E,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAgB,gBAAgB,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAC1F,CAAC;IACF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,iBAAQ,CAChB,GAAG,EACH,oBAAoB,EACpB,yBAAyB,KAAK,oEAAoE,CACnG,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,EAAE,CAAC;AAClB,CAAC"}
package/dist/index.js CHANGED
@@ -11,7 +11,11 @@ const task_1 = require("./commands/task");
11
11
  const init_1 = require("./commands/init");
12
12
  const secret_1 = require("./commands/secret");
13
13
  const schedule_1 = require("./commands/schedule");
14
+ const deployWebhook_1 = require("./commands/deployWebhook");
14
15
  const auth_1 = require("./commands/auth");
16
+ const identity_1 = require("./commands/identity");
17
+ const inbox_1 = require("./commands/inbox");
18
+ const webhook_1 = require("./commands/webhook");
15
19
  const autoupdate_1 = require("./skill/autoupdate");
16
20
  // Silently refresh the installed Claude Code skill to match the running CLI.
17
21
  // Synchronous + cheap (a file stat + at most one small write). No-op if the
@@ -44,7 +48,11 @@ const globalOpts = () => program.opts();
44
48
  (0, task_1.registerTaskCommands)(program, globalOpts);
45
49
  (0, secret_1.registerSecretCommands)(program, globalOpts);
46
50
  (0, schedule_1.registerScheduleCommands)(program, globalOpts);
51
+ (0, deployWebhook_1.registerDeployWebhookCommands)(program, globalOpts);
47
52
  (0, auth_1.registerAuthCommands)(program, globalOpts);
53
+ (0, identity_1.registerIdentityCommands)(program, globalOpts);
54
+ (0, inbox_1.registerInboxCommands)(program, globalOpts);
55
+ (0, webhook_1.registerWebhookCommands)(program, globalOpts);
48
56
  program.parseAsync(process.argv).catch((err) => {
49
57
  // Defensive: command actions handle their own errors. This only catches
50
58
  // setup-time errors (e.g. unknown subcommand).
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,4CAAwD;AACxD,8CAA0D;AAC1D,gDAAkF;AAClF,kDAA+D;AAC/D,kDAA+D;AAC/D,0CAAuD;AACvD,0CAAmF;AACnF,8CAA2D;AAC3D,kDAA+D;AAC/D,0CAAuD;AACvD,mDAA+E;AAG/E,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,IAAA,mCAAsB,GAAE,CAAC;AAEzB,wEAAwE;AACxE,uEAAuE;AACvE,6DAA6D;AAC7D,KAAK,IAAA,8BAAiB,GAAE,CAAC;AAEzB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,oEAAoE,CAAC;KACjF,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,QAAQ,EAAE,oDAAoD,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,UAAU,GAAG,GAAe,EAAE,CAAC,OAAO,CAAC,IAAI,EAAc,CAAC;AAEhE,IAAA,4BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,8BAAqB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,IAAA,0BAAmB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACzC,IAAA,kCAA2B,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACjD,IAAA,iCAAuB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC7C,IAAA,6BAAmB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACzC,IAAA,mCAAwB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9C,IAAA,mCAAwB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9C,IAAA,2BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,+BAAsB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC5C,IAAA,mCAAwB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9C,IAAA,2BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAE1C,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,wEAAwE;IACxE,+CAA+C;IAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,4CAAwD;AACxD,8CAA0D;AAC1D,gDAAkF;AAClF,kDAA+D;AAC/D,kDAA+D;AAC/D,0CAAuD;AACvD,0CAAmF;AACnF,8CAA2D;AAC3D,kDAA+D;AAC/D,4DAAyE;AACzE,0CAAuD;AACvD,kDAA+D;AAC/D,4CAAyD;AACzD,gDAA6D;AAC7D,mDAA+E;AAG/E,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,IAAA,mCAAsB,GAAE,CAAC;AAEzB,wEAAwE;AACxE,uEAAuE;AACvE,6DAA6D;AAC7D,KAAK,IAAA,8BAAiB,GAAE,CAAC;AAEzB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,oEAAoE,CAAC;KACjF,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,QAAQ,EAAE,oDAAoD,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,UAAU,GAAG,GAAe,EAAE,CAAC,OAAO,CAAC,IAAI,EAAc,CAAC;AAEhE,IAAA,4BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,8BAAqB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,IAAA,0BAAmB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACzC,IAAA,kCAA2B,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACjD,IAAA,iCAAuB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC7C,IAAA,6BAAmB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACzC,IAAA,mCAAwB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9C,IAAA,mCAAwB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9C,IAAA,2BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,+BAAsB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC5C,IAAA,mCAAwB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9C,IAAA,6CAA6B,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACnD,IAAA,2BAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,IAAA,mCAAwB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9C,IAAA,6BAAqB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,IAAA,iCAAuB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAE7C,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,wEAAwE;IACxE,+CAA+C;IAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/dist/oauth.js ADDED
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loginWithBrowser = loginWithBrowser;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const node_http_1 = require("node:http");
6
+ const node_child_process_1 = require("node:child_process");
7
+ const node_os_1 = require("node:os");
8
+ const config_1 = require("./config");
9
+ const client_1 = require("./client");
10
+ function base64url(buf) {
11
+ return buf.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
12
+ }
13
+ function openBrowser(url) {
14
+ let cmd;
15
+ let args;
16
+ if (process.platform === 'darwin') {
17
+ cmd = 'open';
18
+ args = [url];
19
+ }
20
+ else if (process.platform === 'win32') {
21
+ cmd = 'cmd';
22
+ args = ['/c', 'start', '', url];
23
+ }
24
+ else {
25
+ cmd = 'xdg-open';
26
+ args = [url];
27
+ }
28
+ try {
29
+ (0, node_child_process_1.spawn)(cmd, args, { stdio: 'ignore', detached: true }).unref();
30
+ }
31
+ catch {
32
+ // Couldn't auto-open; the printed URL is the fallback.
33
+ }
34
+ }
35
+ // The CLI's OAuth redirect lands on a one-shot local server. We try a small range of ports (all
36
+ // registered as Auth0 callback URLs) so a busy port doesn't break login. Override with SENTE_OAUTH_PORT.
37
+ const OAUTH_PORTS = process.env.SENTE_OAUTH_PORT
38
+ ? [Number(process.env.SENTE_OAUTH_PORT)]
39
+ : Array.from({ length: 11 }, (_, i) => 42789 + i); // 42789–42799
40
+ const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
41
+ // Bind the first available port in the range; resolves with the port actually bound.
42
+ function listenOnAvailablePort(server, ports) {
43
+ return new Promise((resolve, reject) => {
44
+ let i = 0;
45
+ const tryNext = () => {
46
+ if (i >= ports.length) {
47
+ return reject(new client_1.ApiError(0, 'NO_PORT', `No free local port for the login callback (tried ${ports[0]}–${ports[ports.length - 1]}).`));
48
+ }
49
+ const port = ports[i++];
50
+ const onError = (err) => {
51
+ if (err.code === 'EADDRINUSE')
52
+ tryNext();
53
+ else
54
+ reject(new client_1.ApiError(0, 'CALLBACK_SERVER', `Login server error: ${err.message}`));
55
+ };
56
+ server.once('error', onError);
57
+ server.listen(port, '127.0.0.1', () => {
58
+ server.removeListener('error', onError);
59
+ resolve(port);
60
+ });
61
+ };
62
+ tryNext();
63
+ });
64
+ }
65
+ /**
66
+ * Browser sign-in via Auth0 (Authorization Code + PKCE) — the same tenant/login as app.sente.run —
67
+ * then exchange the one-time code for an access token (JWT).
68
+ */
69
+ async function getAuth0AccessToken() {
70
+ const { domain, clientId, audience } = (0, config_1.auth0Config)();
71
+ const verifier = base64url((0, node_crypto_1.randomBytes)(32));
72
+ const challenge = base64url((0, node_crypto_1.createHash)('sha256').update(verifier).digest());
73
+ const state = base64url((0, node_crypto_1.randomBytes)(16));
74
+ let resolveCode;
75
+ let rejectCode;
76
+ const codePromise = new Promise((res, rej) => {
77
+ resolveCode = res;
78
+ rejectCode = rej;
79
+ });
80
+ const server = (0, node_http_1.createServer)((req, res) => {
81
+ const url = new URL(req.url ?? '/', 'http://localhost');
82
+ if (url.pathname !== '/callback') {
83
+ res.writeHead(404);
84
+ res.end();
85
+ return;
86
+ }
87
+ const error = url.searchParams.get('error');
88
+ const returnedState = url.searchParams.get('state');
89
+ const returnedCode = url.searchParams.get('code');
90
+ res.writeHead(200, { 'content-type': 'text/html' });
91
+ res.end('<html><body style="font-family:system-ui;text-align:center;padding-top:3rem">' +
92
+ '<h2>Signed in to Sente</h2><p>You can close this tab and return to the terminal.</p></body></html>');
93
+ server.close();
94
+ if (error)
95
+ return rejectCode(new client_1.ApiError(401, 'AUTH0_ERROR', `Auth0 returned an error: ${error}`));
96
+ if (!returnedState || returnedState !== state)
97
+ return rejectCode(new client_1.ApiError(401, 'STATE_MISMATCH', 'OAuth state mismatch — aborting for safety.'));
98
+ if (!returnedCode)
99
+ return rejectCode(new client_1.ApiError(401, 'NO_CODE', 'No authorization code returned.'));
100
+ resolveCode(returnedCode);
101
+ });
102
+ const port = await listenOnAvailablePort(server, OAUTH_PORTS);
103
+ const redirectUri = `http://localhost:${port}/callback`;
104
+ const authorizeUrl = `https://${domain}/authorize?` +
105
+ new URLSearchParams({
106
+ response_type: 'code',
107
+ client_id: clientId,
108
+ redirect_uri: redirectUri,
109
+ scope: 'openid profile email',
110
+ audience,
111
+ code_challenge: challenge,
112
+ code_challenge_method: 'S256',
113
+ state,
114
+ }).toString();
115
+ process.stderr.write(`Opening your browser to sign in…\nIf it doesn't open, visit:\n\n ${authorizeUrl}\n\n`);
116
+ openBrowser(authorizeUrl);
117
+ const timer = setTimeout(() => {
118
+ server.close();
119
+ rejectCode(new client_1.ApiError(408, 'LOGIN_TIMEOUT', 'Login timed out after 5 minutes.'));
120
+ }, LOGIN_TIMEOUT_MS);
121
+ timer.unref();
122
+ let code;
123
+ try {
124
+ code = await codePromise;
125
+ }
126
+ finally {
127
+ clearTimeout(timer);
128
+ }
129
+ const tokenRes = await fetch(`https://${domain}/oauth/token`, {
130
+ method: 'POST',
131
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
132
+ body: new URLSearchParams({
133
+ grant_type: 'authorization_code',
134
+ client_id: clientId,
135
+ code,
136
+ code_verifier: verifier,
137
+ redirect_uri: redirectUri,
138
+ }).toString(),
139
+ });
140
+ if (!tokenRes.ok) {
141
+ throw new client_1.ApiError(tokenRes.status, 'TOKEN_EXCHANGE', `Auth0 token exchange failed (${tokenRes.status}).`);
142
+ }
143
+ const tok = (await tokenRes.json());
144
+ if (!tok.access_token)
145
+ throw new client_1.ApiError(500, 'NO_ACCESS_TOKEN', 'Auth0 did not return an access token.');
146
+ return tok.access_token;
147
+ }
148
+ /**
149
+ * Full browser login: sign in (Auth0) → resolve the account's organization → mint a long-lived
150
+ * Sente API key (`sk_sente_…`). The raw key is returned exactly once.
151
+ */
152
+ async function loginWithBrowser() {
153
+ const accessToken = await getAuth0AccessToken();
154
+ const base = (0, config_1.gatewayUrl)().replace(/\/$/, '');
155
+ const jsonAuth = { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' };
156
+ // Resolve the org — GET /api/organizations is JWT-only (no x-organization-id). Use the first org.
157
+ const orgsRes = await fetch(`${base}/api/organizations`, { headers: jsonAuth });
158
+ if (!orgsRes.ok)
159
+ throw new client_1.ApiError(orgsRes.status, 'ORG_LOOKUP', `Could not list organizations (${orgsRes.status}).`);
160
+ const orgsBody = (await orgsRes.json());
161
+ const orgs = Array.isArray(orgsBody) ? orgsBody : orgsBody.organizations ?? [];
162
+ const org = orgs[0];
163
+ if (!org)
164
+ throw new client_1.ApiError(404, 'NO_ORG', 'No organization found for this account.');
165
+ // Mint a PAT bound to that org (POST /api/api-tokens accepts the Auth0 JWT + x-organization-id).
166
+ const mintRes = await fetch(`${base}/api/api-tokens`, {
167
+ method: 'POST',
168
+ headers: { ...jsonAuth, 'x-organization-id': org.id },
169
+ body: JSON.stringify({ name: `CLI ${(0, node_os_1.hostname)()}` }),
170
+ });
171
+ if (!mintRes.ok) {
172
+ throw new client_1.ApiError(mintRes.status, 'MINT_FAILED', `Could not create an API key (${mintRes.status}).`);
173
+ }
174
+ const mintBody = (await mintRes.json());
175
+ if (!mintBody.rawToken)
176
+ throw new client_1.ApiError(500, 'NO_TOKEN', 'The API key was not returned.');
177
+ return { token: mintBody.rawToken, organizationId: org.id, organizationName: org.name };
178
+ }
179
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}