@awesomate/sdk 0.62.0 → 0.63.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/dist/index.d.ts CHANGED
@@ -26,7 +26,7 @@
26
26
  * Docs: https://hub.awesomate.ai/docs/sdk/
27
27
  */
28
28
  /** This package's version, sent to the hub with every server call. */
29
- export declare const VERSION = "0.62.0";
29
+ export declare const VERSION = "0.63.0";
30
30
  /** Augmented by the generated awesomate.d.ts, so each kind's rows are typed. */
31
31
  export interface Kinds {
32
32
  }
@@ -1128,6 +1128,35 @@ export declare class AwesomateClient {
1128
1128
  * for one already thrown away answers `already: true`.
1129
1129
  */
1130
1130
  discard: (id: string) => Promise<EmailDiscarded>;
1131
+ /**
1132
+ * Ask the account's own writing agent for an email. It writes in the business's voice from its
1133
+ * details, lists and past results. It may ask first (`questions`): put them to the person and
1134
+ * call again with the same `brief`, the `sessionId` it gave and `answers`. Otherwise it saves a
1135
+ * draft (new to `topic`, or written over the draft `email`) for a person to approve at
1136
+ * `reviewUrl`; or answers `pending` with a `jobId` for `briefStatus()`. Needs crm:draft and
1137
+ * the copywriter on the account. Each email is one of the month's drafts on Awesomate's AI,
1138
+ * none on the account's own OpenRouter key. No writing agent throws `unavailable` (server code
1139
+ * `no_copywriter`): the owner adds one in the hub.
1140
+ *
1141
+ * @example
1142
+ * let r = await db.emails.brief({ brief: 'A special offer for our list this month', topic: 'news' });
1143
+ * if (r.questions) r = await db.emails.brief({ brief: 'A special offer for our list this month', topic: 'news',
1144
+ * sessionId: r.sessionId, answers: r.questions.map((q) => ({ q: q.q, a: 'A free 30-minute review' })) });
1145
+ * if (r.reviewUrl) console.log(r.summary, r.reviewUrl);
1146
+ */
1147
+ brief: (input: {
1148
+ brief: string;
1149
+ topic?: string;
1150
+ email?: string;
1151
+ answers?: Array<{
1152
+ q: string;
1153
+ a: string;
1154
+ }>;
1155
+ sessionId?: string;
1156
+ agent?: string;
1157
+ }) => Promise<EmailBrief>;
1158
+ /** The result of a `brief()` that answered `pending`: still `pending`, or the questions or the draft. */
1159
+ briefStatus: (jobId: string) => Promise<EmailBrief>;
1131
1160
  };
1132
1161
  /**
1133
1162
  * Email series: emails that go to one person at a time over days, starting when something
@@ -1193,6 +1222,21 @@ export declare class AwesomateClient {
1193
1222
  }) => Promise<EmailSeriesDraft>;
1194
1223
  /** Change one email of a series (by its key); the rest of the draft, or what is live, is kept. */
1195
1224
  updateEmail: (id: string, key: string, doc: EmailSeriesEmail["doc"]) => Promise<EmailSeriesDraft>;
1225
+ /**
1226
+ * Ask the account's own writing agent to write a series' emails from one brief: every email
1227
+ * still holding a [gap], or every one with `all`. One draft version is saved, never made live:
1228
+ * an approver approves it at `reviewUrl`. A long write answers `pending` with a `jobId` for
1229
+ * `writeStatus()`. Needs crm:draft and the copywriter on the account; each email is one of
1230
+ * the month's drafts on Awesomate's AI. Several writing agents and none named throws `invalid`
1231
+ * (server code `pick_copywriter`).
1232
+ */
1233
+ write: (id: string, input: {
1234
+ brief: string;
1235
+ all?: boolean;
1236
+ agent?: string;
1237
+ }) => Promise<EmailSeriesWrite>;
1238
+ /** The result of a `write()` that answered `pending`. */
1239
+ writeStatus: (id: string, jobId: string) => Promise<EmailSeriesWrite>;
1196
1240
  };
1197
1241
  /**
1198
1242
  * Sign-up forms: the business's own form on its website that puts each person into Contacts,
@@ -3376,6 +3420,51 @@ export interface EmailListReach {
3376
3420
  /** How many are left out, by reason (unsubscribed, bounced, ...). */
3377
3421
  leftOut: Record<string, number>;
3378
3422
  }
3423
+ /** What `emails.brief()` answers: the agent's questions, a saved draft, or `pending`. */
3424
+ export interface EmailBrief {
3425
+ /** The agent needs these answered first; pass them back as `answers` with this `sessionId`. */
3426
+ questions?: Array<{
3427
+ q: string;
3428
+ choices?: string[];
3429
+ }>;
3430
+ sessionId?: string;
3431
+ /** The draft saved for review. */
3432
+ id?: string;
3433
+ summary?: string;
3434
+ why?: string;
3435
+ reviewUrl?: string;
3436
+ /** Still writing: ask `briefStatus(jobId)`. */
3437
+ pending?: true;
3438
+ jobId?: string;
3439
+ /** This month's drafts on Awesomate's AI. */
3440
+ allowance?: {
3441
+ ownKey: boolean;
3442
+ used: number;
3443
+ limit: number | null;
3444
+ left: number | null;
3445
+ blocked: boolean;
3446
+ };
3447
+ /** What to do next, to tell the owner. */
3448
+ next?: string;
3449
+ }
3450
+ /** What `emailSeries.write()` answers. */
3451
+ export interface EmailSeriesWrite {
3452
+ id?: string;
3453
+ /** How many emails were written and saved. */
3454
+ written?: number;
3455
+ /** The emails that were not, and why. */
3456
+ failed?: Array<{
3457
+ key: string;
3458
+ message: string;
3459
+ }>;
3460
+ /** One sentence for the owner. */
3461
+ sentence?: string;
3462
+ reviewUrl?: string;
3463
+ next?: string;
3464
+ /** Still writing: ask `writeStatus(id, job_id)`. */
3465
+ pending?: true;
3466
+ job_id?: string;
3467
+ }
3379
3468
  /** A draft, from `emails.draft()` or `emails.update()`. */
3380
3469
  export interface EmailDraft {
3381
3470
  id: string;
@@ -4204,12 +4293,17 @@ export interface KnowledgeAnswer {
4204
4293
  answer: string | null;
4205
4294
  /** True only for an ok answer with sources. An ok answer with none came from the model, not the content. */
4206
4295
  grounded: boolean;
4296
+ /**
4297
+ * `watchUrl`: a cited video anyone can watch, its permanent player page at the cited second
4298
+ * (`https://<host>/v/<id>?t=612`). Safe to store or put on a page; null for anything else.
4299
+ */
4207
4300
  sources: Array<{
4208
4301
  ref: number;
4209
4302
  title: string | null;
4210
4303
  kind: string | null;
4211
4304
  locator: string | null;
4212
4305
  url: string | null;
4306
+ watchUrl: string | null;
4213
4307
  }>;
4214
4308
  /** What the owner set the assistant to say when it has no answer. */
4215
4309
  noAnswerMessage: string | null;
package/dist/index.js CHANGED
@@ -26,8 +26,10 @@
26
26
  * Docs: https://hub.awesomate.ai/docs/sdk/
27
27
  */
28
28
  /** This package's version, sent to the hub with every server call. */
29
- export const VERSION = '0.62.0';
29
+ export const VERSION = '0.63.0';
30
30
  const DEFAULT_BASE = 'https://hub.awesomate.ai';
31
+ /** The one check for a platform `watch_url` (mirrored in the hub's awesomate-knowledge.ts and its MCP). */
32
+ const WATCH_URL = /^https:\/\/[^\s"'<>]+$/i;
31
33
  /** Every record and contact id is a UUID; anything else can name no row. */
32
34
  const RECORD_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
33
35
  const ERROR_CODES = [
@@ -809,6 +811,30 @@ export class AwesomateClient {
809
811
  * for one already thrown away answers `already: true`.
810
812
  */
811
813
  discard: async (id) => this.request('DELETE', `/api/my-crm/v1/emails/${emailId(id)}`, undefined, false),
814
+ /**
815
+ * Ask the account's own writing agent for an email. It writes in the business's voice from its
816
+ * details, lists and past results. It may ask first (`questions`): put them to the person and
817
+ * call again with the same `brief`, the `sessionId` it gave and `answers`. Otherwise it saves a
818
+ * draft (new to `topic`, or written over the draft `email`) for a person to approve at
819
+ * `reviewUrl`; or answers `pending` with a `jobId` for `briefStatus()`. Needs crm:draft and
820
+ * the copywriter on the account. Each email is one of the month's drafts on Awesomate's AI,
821
+ * none on the account's own OpenRouter key. No writing agent throws `unavailable` (server code
822
+ * `no_copywriter`): the owner adds one in the hub.
823
+ *
824
+ * @example
825
+ * let r = await db.emails.brief({ brief: 'A special offer for our list this month', topic: 'news' });
826
+ * if (r.questions) r = await db.emails.brief({ brief: 'A special offer for our list this month', topic: 'news',
827
+ * sessionId: r.sessionId, answers: r.questions.map((q) => ({ q: q.q, a: 'A free 30-minute review' })) });
828
+ * if (r.reviewUrl) console.log(r.summary, r.reviewUrl);
829
+ */
830
+ brief: async (input) => {
831
+ const r = await this.request('POST', '/api/my-crm/v1/emails/brief', {
832
+ brief: input.brief, topic: input.topic, email: input.email, answers: input.answers, session_id: input.sessionId, agent: input.agent,
833
+ }, false);
834
+ return briefFromWire(r);
835
+ },
836
+ /** The result of a `brief()` that answered `pending`: still `pending`, or the questions or the draft. */
837
+ briefStatus: async (jobId) => briefFromWire(await this.request('GET', `/api/my-crm/v1/emails/brief/${encodeURIComponent(jobId)}`)),
812
838
  };
813
839
  /**
814
840
  * Email series: emails that go to one person at a time over days, starting when something
@@ -872,6 +898,17 @@ export class AwesomateClient {
872
898
  update: (id, input) => this.request('PUT', `/api/my-crm/v1/series/${encodeURIComponent(id)}/draft`, input, false),
873
899
  /** Change one email of a series (by its key); the rest of the draft, or what is live, is kept. */
874
900
  updateEmail: (id, key, doc) => this.request('PUT', `/api/my-crm/v1/series/${encodeURIComponent(id)}/emails/${encodeURIComponent(key)}`, { doc }, false),
901
+ /**
902
+ * Ask the account's own writing agent to write a series' emails from one brief: every email
903
+ * still holding a [gap], or every one with `all`. One draft version is saved, never made live:
904
+ * an approver approves it at `reviewUrl`. A long write answers `pending` with a `jobId` for
905
+ * `writeStatus()`. Needs crm:draft and the copywriter on the account; each email is one of
906
+ * the month's drafts on Awesomate's AI. Several writing agents and none named throws `invalid`
907
+ * (server code `pick_copywriter`).
908
+ */
909
+ write: (id, input) => this.request('POST', `/api/my-crm/v1/series/${encodeURIComponent(id)}/write`, input, false),
910
+ /** The result of a `write()` that answered `pending`. */
911
+ writeStatus: (id, jobId) => this.request('GET', `/api/my-crm/v1/series/${encodeURIComponent(id)}/write/${encodeURIComponent(jobId)}`),
875
912
  };
876
913
  /**
877
914
  * Sign-up forms: the business's own form on its website that puts each person into Contacts,
@@ -1191,6 +1228,7 @@ export class AwesomateClient {
1191
1228
  kind: typeof s.kind === 'string' ? s.kind : null,
1192
1229
  locator: (typeof s.locator === 'string' ? s.locator : typeof s.section_path === 'string' ? s.section_path : null),
1193
1230
  url: typeof s.url === 'string' ? s.url : null,
1231
+ watchUrl: typeof s.watch_url === 'string' && WATCH_URL.test(s.watch_url) ? s.watch_url : null,
1194
1232
  }));
1195
1233
  const text = typeof r.answer_plain === 'string' && r.answer_plain ? r.answer_plain : typeof r.answer === 'string' ? r.answer : null;
1196
1234
  return {
@@ -1701,6 +1739,10 @@ export class AwesomateClient {
1701
1739
  return { ...r.usage, own_key: r.own_key };
1702
1740
  }
1703
1741
  }
1742
+ function briefFromWire(r) {
1743
+ const { session_id, job_id, ...rest } = r;
1744
+ return { ...rest, ...(session_id ? { sessionId: session_id } : {}), ...(job_id ? { jobId: job_id } : {}) };
1745
+ }
1704
1746
  function memoryStorage() {
1705
1747
  const m = new Map();
1706
1748
  return { getItem: (k) => m.get(k) ?? null, setItem: (k, v) => { m.set(k, v); }, removeItem: (k) => { m.delete(k); } };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awesomate/sdk",
3
- "version": "0.62.0",
3
+ "version": "0.63.0",
4
4
  "description": "Your own Awesomate data from Node and the browser: query contacts and app data with generated types, and sign your app's own users in",
5
5
  "license": "MIT",
6
6
  "type": "module",