@jsm-mit/sultana-agent-tools-package 0.8.0 → 0.9.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
@@ -191,7 +191,7 @@ const tools = session
191
191
  `unavailable` instead of booking hours off (`timeZone: null` skips the guard; `hostTimeZoneProblem`
192
192
  lets a host check at start-up).
193
193
 
194
- ## Booksy tools (experimental, since 0.7.0)
194
+ ## Booksy tools (experimental, since 0.7.0; logo and cover since 0.9.0)
195
195
 
196
196
  "Copy my salon from Booksy": three read-only tools that take the address of a PUBLIC Booksy profile
197
197
  and return its content in the shape Sultana's write tools take, and one write tool that copies the
@@ -215,8 +215,20 @@ const tools = [
215
215
  | `read_booksy_services` | services ready for `add_service`: `name`, `pricePln`, `durationMinutes`, plus `booksyCategory`, `description`, `workerNames`, `notes`; optional `category` filter |
216
216
  | `download_booksy_photos` | fetches photos (`logo`, `cover`, `salon` by default; also `inspiration`, `service` — the per-service portfolio —, `staff`) and hands each to the host's `BooksyPhotoSink`; up to 150 a call |
217
217
  | `import_booksy_services` | **write**: copies the catalogue into this salon. Arguments: `url`, optional `category`, optional `overrides` (`{name, skip?, serviceTypeIds?}`), `confirmed` |
218
+ | `import_booksy_logo` | **write**: copies the Booksy logo into the salon's media library and sets it as the salon's THUMBNAIL; the cover is handed back untouched. Arguments: `url`, `confirmed` |
219
+ | `import_booksy_cover` | **write**: the same for the Booksy cover → the salon's COVER; the thumbnail is handed back untouched |
218
220
  | `import_booksy_workers` | **placeholder**: says that copying the team is not built yet, lists the people on Booksy and who is missing in the salon; writes nothing |
219
221
 
222
+ The two photo tools exist only when the port can write pictures — `IcSalonCorePort` built with
223
+ `assetsCanisterId`, and an identity the assets canister accepts (a delegation must list that
224
+ canister in its `targets`, next to core). A salon has exactly two photo slots, and the canister
225
+ replaces both at once, so each tool reads the salon first and hands the other slot back. One
226
+ picture, one call to the assets canister: at most 1.9 MB, JPEG / PNG / WebP — anything else is
227
+ refused with a sentence, nothing is set. The asset is named `Booksy · logo · <mark>`; a picture
228
+ already in the library is not stored twice. The preview downloads nothing; its echo carries the
229
+ picture's mark, and a logo changed on Booksy in between makes the confirmation stale. The other
230
+ Booksy pictures (service portfolio, interior, inspirations, staff) are not copied yet.
231
+
220
232
  `import_booksy_services`:
221
233
 
222
234
  - **The model never carries the services.** It names the profile; the tool reads it again itself
@@ -0,0 +1,18 @@
1
+ import type { TurnConfirmations } from "../confirmations.js";
2
+ import { type SalonCorePort } from "../salon-core-port.js";
3
+ import { type AgentTool } from "../types.js";
4
+ import { type FetchFn } from "./fetch-page.js";
5
+ import { BooksyProfileReader } from "./tools.js";
6
+ export interface CreateBooksyPhotoToolsOptions {
7
+ reader?: BooksyProfileReader;
8
+ confirmations?: TurnConfirmations;
9
+ fetchFn?: FetchFn;
10
+ }
11
+ /**
12
+ * Two write tools, one per photo slot of a salon: the Booksy logo becomes the salon's thumbnail,
13
+ * the Booksy cover becomes the salon's cover. Each copies ONE picture into the salon's media
14
+ * library and sets ONE slot; the other slot is read first and handed back untouched. A port that
15
+ * cannot write pictures gives no tools.
16
+ */
17
+ export declare function createBooksyPhotoTools(port: SalonCorePort, options?: CreateBooksyPhotoToolsOptions): AgentTool[];
18
+ //# sourceMappingURL=import-photos-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-photos-tools.d.ts","sourceRoot":"","sources":["../../src/booksy/import-photos-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAAiD,KAAK,aAAa,EAAuB,MAAM,uBAAuB,CAAC;AAG/H,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAmD,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEhG,OAAO,EAAE,mBAAmB,EAAa,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,6BAA6B;IAC1C,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAyCD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,GAAE,6BAAkC,GAAG,SAAS,EAAE,CAMpH"}
@@ -0,0 +1,124 @@
1
+ import { createHash } from "node:crypto";
2
+ import { toToolError } from "../errors.js";
3
+ import { MAX_IMAGE_UPLOAD_BYTES } from "../salon-core-port.js";
4
+ import { ArgumentError, readBoolean, readOptionalString, readString } from "../tools/args.js";
5
+ import { writeGate } from "../tools/write-gate.js";
6
+ import { err, ok } from "../types.js";
7
+ import { BooksyReadError, fetchPhoto, normalizeBooksyUrl } from "./fetch-page.js";
8
+ import { BooksyProfileReader, URL_FIELD } from "./tools.js";
9
+ const LOGO = {
10
+ toolName: "import_booksy_logo",
11
+ booksyKind: "logo",
12
+ slot: "thumbnailAssetId",
13
+ other: "coverAssetId",
14
+ progress: "Kopiuję logo z Booksy…",
15
+ whatPl: "logo",
16
+ asPl: "miniaturę salonu (kwadratowe zdjęcie na listach i mapie)",
17
+ otherPl: "Okładka salonu",
18
+ };
19
+ const COVER = {
20
+ toolName: "import_booksy_cover",
21
+ booksyKind: "cover",
22
+ slot: "coverAssetId",
23
+ other: "thumbnailAssetId",
24
+ progress: "Kopiuję okładkę z Booksy…",
25
+ whatPl: "okładkę",
26
+ asPl: "okładkę salonu (szerokie zdjęcie na górze strony salonu)",
27
+ otherPl: "Miniatura salonu",
28
+ };
29
+ const UPLOADABLE = new Set(["image/jpeg", "image/png", "image/webp"]);
30
+ /**
31
+ * Two write tools, one per photo slot of a salon: the Booksy logo becomes the salon's thumbnail,
32
+ * the Booksy cover becomes the salon's cover. Each copies ONE picture into the salon's media
33
+ * library and sets ONE slot; the other slot is read first and handed back untouched. A port that
34
+ * cannot write pictures gives no tools.
35
+ */
36
+ export function createBooksyPhotoTools(port, options = {}) {
37
+ if (!port.photos)
38
+ return [];
39
+ const reader = options.reader ?? new BooksyProfileReader(options.fetchFn);
40
+ return [LOGO, COVER].map((slot) => photoTool(slot, port, port.photos, reader, options));
41
+ }
42
+ function photoTool(slot, port, photos, reader, options) {
43
+ const gate = writeGate(slot.toolName, options.confirmations);
44
+ return {
45
+ name: slot.toolName,
46
+ progress: slot.progress,
47
+ description: `Kopiuje ${slot.whatPl} z publicznego profilu Booksy do biblioteki mediów salonu i ustawia jako ${slot.asPl}. ${slot.otherPl} zostaje bez zmian. Przy confirmed=false niczego nie pobiera ani nie zapisuje — oddaje opis zmiany do pokazania właścicielce.`,
48
+ parameters: gate.parameters({
49
+ type: "object",
50
+ properties: {
51
+ url: URL_FIELD,
52
+ photo: { type: "string", description: "Znacznik zdjęcia z podglądu. Narzędzie odmówi, gdy zdjęcie na Booksy zmieniło się od podglądu." },
53
+ confirmed: {
54
+ type: "boolean",
55
+ description: "false dla podglądu: narzędzie nic nie zapisze i odda opis zmiany do zatwierdzenia przez właścicielkę. true dopiero po tym, jak właścicielka potwierdzi.",
56
+ },
57
+ },
58
+ required: ["url", "confirmed"],
59
+ additionalProperties: false,
60
+ }),
61
+ execute: async (args) => {
62
+ try {
63
+ const url = normalizeBooksyUrl(readString(args, "url"));
64
+ const draft = await reader.read(url);
65
+ const picture = draft.photos.find((photo) => photo.kind === slot.booksyKind);
66
+ if (!picture)
67
+ return ok(`Profil Booksy nie ma zdjęcia „${slot.whatPl}” — nie ma czego kopiować.`, { copied: false });
68
+ // The mark ties the confirmation to the picture the owner was told about.
69
+ const mark = markOf(picture.url);
70
+ const expected = readOptionalString(args, "photo") ?? mark;
71
+ const echo = { url, photo: expected };
72
+ const refusal = gate.refusal(args, echo);
73
+ if (refusal)
74
+ return refusal;
75
+ if (expected !== mark) {
76
+ return err("invalid_arguments", "Zdjęcie na Booksy zmieniło się od podglądu — pokaż nowy podgląd (confirmed=false, bez pola photo).");
77
+ }
78
+ const current = await photos.getSalonPhotos();
79
+ if (!readBoolean(args, "confirmed")) {
80
+ const replaced = current[slot.slot] === null ? "Ten slot jest dziś pusty." : "Obecne zdjęcie w tym slocie zostanie zastąpione (zostaje w bibliotece mediów).";
81
+ return gate.preview(`Skopiuję ${slot.whatPl} z Booksy${sizeOf(picture)} do biblioteki mediów i ustawię jako ${slot.asPl}. ${replaced} ${slot.otherPl}: bez zmian.`, echo);
82
+ }
83
+ const refused = gate.redeem(args, echo);
84
+ if (refused)
85
+ return refused;
86
+ const name = `Booksy · ${slot.booksyKind} · ${mark}`;
87
+ const library = await port.listMedia();
88
+ // A picture copied before is not stored twice — a repeated order only sets the slot.
89
+ const known = library.find((media) => media.kind === "image" && media.name === name);
90
+ const assetId = known?.assetId ?? (await photos.uploadImage(await download(picture, name, options.fetchFn)));
91
+ await photos.setSalonPhotos({ ...current, [slot.slot]: assetId });
92
+ return ok(`Ustawiono ${slot.whatPl} z Booksy jako ${slot.asPl}.${known ? " Zdjęcie było już w bibliotece mediów — nie wgrywałem go drugi raz." : ""}`, {
93
+ copied: true,
94
+ assetId,
95
+ });
96
+ }
97
+ catch (error) {
98
+ if (error instanceof ArgumentError)
99
+ return err("invalid_arguments", error.message);
100
+ if (error instanceof BooksyReadError)
101
+ return err(error.code, error.summary);
102
+ return toToolError(error, `Nie udało się skopiować zdjęcia (${slot.whatPl}) z Booksy.`);
103
+ }
104
+ },
105
+ };
106
+ }
107
+ async function download(picture, name, fetchFn) {
108
+ const file = await fetchPhoto(picture.url, fetchFn);
109
+ if (!UPLOADABLE.has(file.contentType)) {
110
+ throw new BooksyReadError("invalid_arguments", `Zdjęcie na Booksy ma format ${file.contentType}, a Sultana przyjmuje JPEG, PNG i WebP.`);
111
+ }
112
+ if (file.bytes.length > MAX_IMAGE_UPLOAD_BYTES) {
113
+ const megabytes = (file.bytes.length / 1_000_000).toFixed(1);
114
+ throw new BooksyReadError("invalid_arguments", `Zdjęcie na Booksy ma ${megabytes} MB, a Sultana przyjmuje do 1,9 MB. Wgraj mniejszą wersję w panelu salonu.`);
115
+ }
116
+ return { name, contentType: file.contentType, bytes: file.bytes };
117
+ }
118
+ /** Eight hex characters of the picture's address: enough to tell a salon's pictures apart. */
119
+ function markOf(pictureUrl) {
120
+ return createHash("sha256").update(pictureUrl).digest("hex").slice(0, 8);
121
+ }
122
+ function sizeOf(picture) {
123
+ return picture.width && picture.height ? ` (${picture.width}×${picture.height})` : "";
124
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"import-tools.d.ts","sourceRoot":"","sources":["../../src/booksy/import-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAkD,MAAM,uBAAuB,CAAC;AAG3G,OAAO,EAAW,KAAK,SAAS,EAAmB,MAAM,aAAa,CAAC;AAGvE,OAAO,EACH,mBAAmB,EAInB,KAAK,8BAA8B,EACtC,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,8BAA8B;IAC3C,8FAA8F;IAC9F,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACrC;AAMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,GAAE,8BAAmC,GAAG,SAAS,EAAE,CAItH;AAED,MAAM,WAAW,wBAAyB,SAAQ,8BAA8B;IAC5E,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACrC;AAED;0EAC0E;AAC1E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,GAAE,wBAA6B,GAAG,SAAS,EAAE,CAO1G"}
1
+ {"version":3,"file":"import-tools.d.ts","sourceRoot":"","sources":["../../src/booksy/import-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAkD,MAAM,uBAAuB,CAAC;AAG3G,OAAO,EAAW,KAAK,SAAS,EAAmB,MAAM,aAAa,CAAC;AAIvE,OAAO,EACH,mBAAmB,EAInB,KAAK,8BAA8B,EACtC,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,8BAA8B;IAC3C,8FAA8F;IAC9F,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACrC;AAMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,GAAE,8BAAmC,GAAG,SAAS,EAAE,CAItH;AAED,MAAM,WAAW,wBAAyB,SAAQ,8BAA8B;IAC5E,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACrC;AAED;0EAC0E;AAC1E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,GAAE,wBAA6B,GAAG,SAAS,EAAE,CAS1G"}
@@ -3,6 +3,7 @@ import { ArgumentError, readBoolean, readOptionalNumber, readOptionalString, rea
3
3
  import { writeGate } from "../tools/write-gate.js";
4
4
  import { err, ok } from "../types.js";
5
5
  import { BooksyReadError, normalizeBooksyUrl } from "./fetch-page.js";
6
+ import { createBooksyPhotoTools } from "./import-photos-tools.js";
6
7
  import { BooksyProfileReader, URL_FIELD, createBooksyReaderTools, degradedSuffix, } from "./tools.js";
7
8
  /** Writes at a time. Enough to bring a 60-service catalogue down from minutes to well under one;
8
9
  * low enough that a canister short on cycles still has room for every call in flight. */
@@ -23,6 +24,8 @@ export function createBooksyTools(port, options = {}) {
23
24
  return [
24
25
  ...createBooksyReaderTools({ ...options, reader }),
25
26
  ...createBooksyImportTools(port, { reader, confirmations: options.confirmations }),
27
+ // None when the port cannot write pictures (no assets canister, or no identity for it).
28
+ ...createBooksyPhotoTools(port, { reader, confirmations: options.confirmations, fetchFn: options.fetchFn }),
26
29
  ];
27
30
  }
28
31
  function importServicesTool(port, reader, confirmations) {
@@ -1,11 +1,17 @@
1
1
  import type { Identity } from "@icp-sdk/core/agent";
2
- import type { DiscountCodeInput, DiscountCodeView, MediaView, PromoView, PromoWriteInput, SalonAccess, SalonCorePort, TimeRange, ServiceTypeView, ServiceView, ServiceWriteInput, WorkerView } from "./salon-core-port.js";
2
+ import type { DiscountCodeInput, DiscountCodeView, MediaView, PromoView, PromoWriteInput, SalonAccess, SalonCorePort, SalonPhotoPort, TimeRange, ServiceTypeView, ServiceView, ServiceWriteInput, WorkerView } from "./salon-core-port.js";
3
3
  export interface IcSalonCorePortOptions {
4
4
  canisterId: string;
5
5
  /** Omit for an anonymous identity — every write will then be refused, which is only useful in
6
6
  * a read-only demo. */
7
7
  identity?: Identity;
8
8
  salonId: string;
9
+ /**
10
+ * The assets canister this core is wired to. With it the port can write pictures (`photos`);
11
+ * without it there is no `photos`, and the tools that need it are not built. The identity must
12
+ * be one the assets canister accepts — a delegation has to name that canister in its targets.
13
+ */
14
+ assetsCanisterId?: string;
9
15
  /** Language of service-type labels the agent sees and quotes back to the owner. */
10
16
  language: string;
11
17
  /**
@@ -32,6 +38,7 @@ export declare class IcSalonCorePort implements SalonCorePort {
32
38
  private readonly promo;
33
39
  private catalog;
34
40
  private readonly discountCodes;
41
+ readonly photos?: SalonPhotoPort;
35
42
  constructor(options: IcSalonCorePortOptions);
36
43
  listServices(): Promise<ServiceView[]>;
37
44
  addService(input: ServiceWriteInput): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"ic-salon-core-port.d.ts","sourceRoot":"","sources":["../src/ic-salon-core-port.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ic-salon-core-port.d.ts","sourceRoot":"","sources":["../src/ic-salon-core-port.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,11 @@
1
1
  import { Principal } from "@icp-sdk/core/principal";
2
- import { AssetsActor, AvailabilityActor, DiscountCodesActor, filterServiceTypes, HrActor, PromoActor, promoMusicOf, SalonServicesActor, ServiceTypesActor, } from "@jsm-mit/sultana-core-motoko-package";
2
+ import { AssetsActor, AvailabilityActor, DiscountCodesActor, filterServiceTypes, HrActor, PromoActor, promoMusicOf, SalonsActor, SalonServicesActor, ServiceTypesActor, } from "@jsm-mit/sultana-core-motoko-package";
3
+ import { AssetsRustSalonActor } from "@jsm-mit/sultana-assets-rust-package";
3
4
  const SERVICE_TYPES_CATALOG_TTL_MS = 60_000;
5
+ /** The assets canister registers a stored image in core with a call of its own; the library lists
6
+ * it a moment after the upload returns. Two seconds is the usual wait — this is the ceiling. */
7
+ const IMAGE_REGISTRATION_TIMEOUT_MS = 20_000;
8
+ const IMAGE_REGISTRATION_POLL_MS = 1_000;
4
9
  /**
5
10
  * The port over the published canister wrapper. Conversions live here and nowhere else: the
6
11
  * canister speaks `bigint` and `Principal`, the tools speak numbers and strings.
@@ -17,6 +22,7 @@ export class IcSalonCorePort {
17
22
  promo;
18
23
  catalog = null;
19
24
  discountCodes;
25
+ photos;
20
26
  constructor(options) {
21
27
  this.salonId = options.salonId;
22
28
  this.language = options.language;
@@ -28,6 +34,9 @@ export class IcSalonCorePort {
28
34
  this.assets = new AssetsActor(options.canisterId, options.identity);
29
35
  this.promo = new PromoActor(options.canisterId, options.identity);
30
36
  this.discountCodes = new DiscountCodesActor(options.canisterId, options.identity);
37
+ if (options.assetsCanisterId && this.access === "owner") {
38
+ this.photos = new IcSalonPhotoPort(options.salonId, new SalonsActor(options.canisterId, options.identity), new AssetsRustSalonActor(options.assetsCanisterId, options.identity), () => this.listMedia());
39
+ }
31
40
  }
32
41
  async listServices() {
33
42
  // Both queries return the same candid record, so one mapping serves both.
@@ -176,3 +185,44 @@ function toContent(input) {
176
185
  music: input.music,
177
186
  };
178
187
  }
188
+ class IcSalonPhotoPort {
189
+ salonId;
190
+ salons;
191
+ assetsRust;
192
+ listMedia;
193
+ constructor(salonId, salons, assetsRust, listMedia) {
194
+ this.salonId = salonId;
195
+ this.salons = salons;
196
+ this.assetsRust = assetsRust;
197
+ this.listMedia = listMedia;
198
+ }
199
+ async getSalonPhotos() {
200
+ const salons = await this.salons.getMySalonsAsyncUnsafe();
201
+ const salon = salons.find((candidate) => candidate.id === this.salonId);
202
+ if (!salon)
203
+ throw new Error("CanisterError", { cause: { errorKey: "NotFound", errorMessage: "salon not found among the owner's salons" } });
204
+ return { thumbnailAssetId: salon.thumbnailAssetId[0] ?? null, coverAssetId: salon.coverAssetId[0] ?? null };
205
+ }
206
+ async setSalonPhotos(photos) {
207
+ // The canister REPLACES both slots — an omitted argument clears that slot.
208
+ await this.salons.setSalonPhotosAsyncUnsafe(this.salonId, photos.thumbnailAssetId ?? undefined, photos.coverAssetId ?? undefined);
209
+ }
210
+ async uploadImage(input) {
211
+ const assetId = await this.assetsRust.uploadImageAsyncUnsafe({
212
+ salonId: this.salonId,
213
+ name: input.name,
214
+ contentType: input.contentType,
215
+ data: input.bytes,
216
+ });
217
+ // `setSalonPhotos` refuses an asset the library does not list yet.
218
+ const deadline = Date.now() + IMAGE_REGISTRATION_TIMEOUT_MS;
219
+ for (;;) {
220
+ const media = await this.listMedia();
221
+ if (media.some((entry) => entry.assetId === assetId))
222
+ return assetId;
223
+ if (Date.now() >= deadline)
224
+ throw new Error("CriticalCanisterError");
225
+ await new Promise((resolve) => setTimeout(resolve, IMAGE_REGISTRATION_POLL_MS));
226
+ }
227
+ }
228
+ }
package/dist/index.d.ts CHANGED
@@ -6,6 +6,8 @@ export type { BooksyImage, BooksyImageKind, BooksyOpenHours, BooksyPriceType, Bo
6
6
  export { parseBooksySalon } from "./booksy/parse-salon.js";
7
7
  export { toSultanaDraft } from "./booksy/to-sultana.js";
8
8
  export type { SultanaDraftDay, SultanaPhotoDraft, SultanaSalonDraft, SultanaSalonDraftProfile, SultanaServiceDraft, SultanaWorkerDraft, } from "./booksy/to-sultana.js";
9
+ export { createBooksyPhotoTools } from "./booksy/import-photos-tools.js";
10
+ export type { CreateBooksyPhotoToolsOptions } from "./booksy/import-photos-tools.js";
9
11
  export { createBooksyImportTools, createBooksyTools } from "./booksy/import-tools.js";
10
12
  export type { CreateBooksyImportToolsOptions, CreateBooksyToolsOptions } from "./booksy/import-tools.js";
11
13
  export { BooksyProfileReader, createBooksyReaderTools, readBooksySalonDraft } from "./booksy/tools.js";
@@ -26,7 +28,8 @@ export { hostTimeZoneProblem } from "./customer/time.js";
26
28
  export { IcSalonCorePort } from "./ic-salon-core-port.js";
27
29
  export type { IcSalonCorePortOptions } from "./ic-salon-core-port.js";
28
30
  export { SALON_AGENT_PERSONA_PL, SALON_BOOKSY_PERSONA_PL, SALON_READ_PERSONA_PL } from "./persona.js";
29
- export type { DiscountCodeInput, DiscountCodeView, MediaView, PromoView, PromoWriteInput, SalonAccess, SalonCorePort, SalonPromoPort, ServiceTypeView, ServiceView, ServiceWriteInput, SalonSchedulePort, TimeRange, WorkerView, } from "./salon-core-port.js";
31
+ export type { DiscountCodeInput, DiscountCodeView, ImageUploadInput, MediaView, PromoView, PromoWriteInput, SalonAccess, SalonCorePort, SalonPhotoPort, SalonPhotosView, SalonPromoPort, ServiceTypeView, ServiceView, ServiceWriteInput, SalonSchedulePort, TimeRange, WorkerView, } from "./salon-core-port.js";
32
+ export { MAX_IMAGE_UPLOAD_BYTES } from "./salon-core-port.js";
30
33
  export { err, needsConfirmation, ok } from "./types.js";
31
34
  export type { AgentTool, ToolErrorCode, ToolParametersSchema, ToolResult } from "./types.js";
32
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ export { ConfirmationLedger, DEFAULT_CONFIRMATION_TTL_MS } from "./confirmations
2
2
  export { BooksyReadError } from "./booksy/fetch-page.js";
3
3
  export { parseBooksySalon } from "./booksy/parse-salon.js";
4
4
  export { toSultanaDraft } from "./booksy/to-sultana.js";
5
+ export { createBooksyPhotoTools } from "./booksy/import-photos-tools.js";
5
6
  export { createBooksyImportTools, createBooksyTools } from "./booksy/import-tools.js";
6
7
  export { BooksyProfileReader, createBooksyReaderTools, readBooksySalonDraft } from "./booksy/tools.js";
7
8
  export { createSalonReadTools, createSalonReadToolsFromPort, createSalonTools, createSalonToolsFromPort, } from "./create-salon-tools.js";
@@ -13,4 +14,5 @@ export { customerLanguageOf, customerTexts } from "./customer/texts.js";
13
14
  export { hostTimeZoneProblem } from "./customer/time.js";
14
15
  export { IcSalonCorePort } from "./ic-salon-core-port.js";
15
16
  export { SALON_AGENT_PERSONA_PL, SALON_BOOKSY_PERSONA_PL, SALON_READ_PERSONA_PL } from "./persona.js";
17
+ export { MAX_IMAGE_UPLOAD_BYTES } from "./salon-core-port.js";
16
18
  export { err, needsConfirmation, ok } from "./types.js";
package/dist/persona.d.ts CHANGED
@@ -22,5 +22,5 @@ export declare const SALON_READ_PERSONA_PL = "Jeste\u015B asystentem w\u0142a\u0
22
22
  * The rules for the Booksy set (`createBooksyTools`) — appended to `SALON_AGENT_PERSONA_PL` by a
23
23
  * host that hands those tools to the agent. Separate, because a host may run without them.
24
24
  */
25
- export declare const SALON_BOOKSY_PERSONA_PL = "Kopiowanie salonu z Booksy:\n- Gdy w\u0142a\u015Bcicielka chce przenie\u015B\u0107 co\u015B z Booksy, popro\u015B o adres jej profilu\n (https://booksy.com/pl-pl/<numer>_<nazwa>\u2026), je\u015Bli go nie poda\u0142a.\n- read_booksy_salon i read_booksy_services tylko czytaj\u0105 profil \u2014 niczego nie zapisuj\u0105.\n- Us\u0142ugi kopiuj WY\u0141\u0104CZNIE przez import_booksy_services (wszystkie naraz, jedno potwierdzenie).\n Nie przepisuj ich pojedynczo przez add_service.\n- Podgl\u0105d importu poka\u017C w\u0142a\u015Bcicielce w ca\u0142o\u015Bci, razem z uwagami pod list\u0105. Poprawki\n (\u201Epomi\u0144 X\u201D, \u201EX to inny typ\u201D) podaj w overrides i poka\u017C nowy podgl\u0105d.\n- Gdy import wypisze us\u0142ugi, kt\u00F3rym nie dobra\u0142 typu, dobierz typy przez find_service_type,\n podaj je w overrides i poka\u017C nowy podgl\u0105d.\n- Kopiowania pracownik\u00F3w jeszcze nie ma: wywo\u0142aj import_booksy_workers i przeka\u017C, co odpowie.\n- Nazwy, adresu, opisu i godzin otwarcia salonu nie da si\u0119 jeszcze zmieni\u0107 przez czat \u2014 powiedz to\n wprost. Nie wymy\u015Blaj innego powodu.";
25
+ export declare const SALON_BOOKSY_PERSONA_PL = "Kopiowanie salonu z Booksy:\n- Gdy w\u0142a\u015Bcicielka chce przenie\u015B\u0107 co\u015B z Booksy, popro\u015B o adres jej profilu\n (https://booksy.com/pl-pl/<numer>_<nazwa>\u2026), je\u015Bli go nie poda\u0142a.\n- read_booksy_salon i read_booksy_services tylko czytaj\u0105 profil \u2014 niczego nie zapisuj\u0105.\n- Us\u0142ugi kopiuj WY\u0141\u0104CZNIE przez import_booksy_services (wszystkie naraz, jedno potwierdzenie).\n Nie przepisuj ich pojedynczo przez add_service.\n- Podgl\u0105d importu poka\u017C w\u0142a\u015Bcicielce w ca\u0142o\u015Bci, razem z uwagami pod list\u0105. Poprawki\n (\u201Epomi\u0144 X\u201D, \u201EX to inny typ\u201D) podaj w overrides i poka\u017C nowy podgl\u0105d.\n- Gdy import wypisze us\u0142ugi, kt\u00F3rym nie dobra\u0142 typu, dobierz typy przez find_service_type,\n podaj je w overrides i poka\u017C nowy podgl\u0105d.\n- Zdj\u0119cia: import_booksy_logo kopiuje logo i ustawia je jako miniatur\u0119 salonu,\n import_booksy_cover kopiuje ok\u0142adk\u0119 i ustawia j\u0105 jako ok\u0142adk\u0119 salonu. To dwa osobne narz\u0119dzia\n i dwie osobne zgody. Je\u015Bli nie masz tych narz\u0119dzi, powiedz, \u017Ce kopiowanie zdj\u0119\u0107 nie jest tu\n dost\u0119pne. Pozosta\u0142ych zdj\u0119\u0107 (portfolio us\u0142ug, wn\u0119trze, inspiracje, zesp\u00F3\u0142) nie da si\u0119 jeszcze\n skopiowa\u0107 \u2014 powiedz to wprost.\n- Kopiowania pracownik\u00F3w jeszcze nie ma: wywo\u0142aj import_booksy_workers i przeka\u017C, co odpowie.\n- Nazwy, adresu, opisu i godzin otwarcia salonu nie da si\u0119 jeszcze zmieni\u0107 przez czat \u2014 powiedz to\n wprost. Nie wymy\u015Blaj innego powodu.";
26
26
  //# sourceMappingURL=persona.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persona.d.ts","sourceRoot":"","sources":["../src/persona.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,i2EAyBoB,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,6wCAee,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,2nCAYE,CAAC"}
1
+ {"version":3,"file":"persona.d.ts","sourceRoot":"","sources":["../src/persona.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,i2EAyBoB,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,6wCAee,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,soDAiBE,CAAC"}
package/dist/persona.js CHANGED
@@ -72,6 +72,11 @@ export const SALON_BOOKSY_PERSONA_PL = `Kopiowanie salonu z Booksy:
72
72
  („pomiń X”, „X to inny typ”) podaj w overrides i pokaż nowy podgląd.
73
73
  - Gdy import wypisze usługi, którym nie dobrał typu, dobierz typy przez find_service_type,
74
74
  podaj je w overrides i pokaż nowy podgląd.
75
+ - Zdjęcia: import_booksy_logo kopiuje logo i ustawia je jako miniaturę salonu,
76
+ import_booksy_cover kopiuje okładkę i ustawia ją jako okładkę salonu. To dwa osobne narzędzia
77
+ i dwie osobne zgody. Jeśli nie masz tych narzędzi, powiedz, że kopiowanie zdjęć nie jest tu
78
+ dostępne. Pozostałych zdjęć (portfolio usług, wnętrze, inspiracje, zespół) nie da się jeszcze
79
+ skopiować — powiedz to wprost.
75
80
  - Kopiowania pracowników jeszcze nie ma: wywołaj import_booksy_workers i przekaż, co odpowie.
76
81
  - Nazwy, adresu, opisu i godzin otwarcia salonu nie da się jeszcze zmienić przez czat — powiedz to
77
82
  wprost. Nie wymyślaj innego powodu.`;
@@ -48,7 +48,36 @@ export interface ServiceTypeView {
48
48
  label: string;
49
49
  category: string | null;
50
50
  }
51
+ /** The salon's two profile photos — there are exactly two slots, not a gallery. */
52
+ export interface SalonPhotosView {
53
+ /** The square picture of the salon on lists and maps. */
54
+ thumbnailAssetId: string | null;
55
+ /** The wide picture at the top of the salon's page. */
56
+ coverAssetId: string | null;
57
+ }
58
+ export interface ImageUploadInput {
59
+ /** The name in the salon's media library. At most 200 characters. */
60
+ name: string;
61
+ contentType: "image/jpeg" | "image/png" | "image/webp";
62
+ /** At most `MAX_IMAGE_UPLOAD_BYTES`. The bytes stay between a tool and the port — a model never sees them. */
63
+ bytes: Uint8Array;
64
+ }
65
+ /** What the assets canister takes in one call; a larger image has to be downscaled first. */
66
+ export declare const MAX_IMAGE_UPLOAD_BYTES = 1900000;
67
+ /**
68
+ * Writing pictures. Optional on the port, because it needs a second canister — the assets
69
+ * canister — and an identity that canister accepts; a host that has neither gets no photo tools.
70
+ */
71
+ export interface SalonPhotoPort {
72
+ getSalonPhotos(): Promise<SalonPhotosView>;
73
+ /** Sets BOTH slots; `null` clears one. A caller that changes one slot passes the other back. */
74
+ setSalonPhotos(photos: SalonPhotosView): Promise<void>;
75
+ /** Stores the image in the salon's media library and resolves, once the library lists it, to its asset id. */
76
+ uploadImage(input: ImageUploadInput): Promise<string>;
77
+ }
51
78
  export interface SalonCorePort extends SalonSchedulePort, SalonPromoPort {
79
+ /** Present only when the port can write pictures. */
80
+ readonly photos?: SalonPhotoPort;
52
81
  listServices(): Promise<ServiceView[]>;
53
82
  addService(input: ServiceWriteInput): Promise<string>;
54
83
  updateService(serviceId: string, input: ServiceWriteInput): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"salon-core-port.d.ts","sourceRoot":"","sources":["../src/salon-core-port.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"salon-core-port.d.ts","sourceRoot":"","sources":["../src/salon-core-port.ts"],"names":[],"mappings":"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"}
@@ -8,4 +8,5 @@
8
8
  * The port is **salon-scoped**: the implementation carries the salon id, so no method takes one.
9
9
  * That is what makes it impossible for a model to address another salon.
10
10
  */
11
- export {};
11
+ /** What the assets canister takes in one call; a larger image has to be downscaled first. */
12
+ export const MAX_IMAGE_UPLOAD_BYTES = 1_900_000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsm-mit/sultana-agent-tools-package",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Agent tool layer for Sultana: framework-agnostic tools over the Sultana core canister wrapper — a salon owner's set (services, promos, schedule) and a customer's set (search, free times, booking), each with a read-only set that needs no identity.",
5
5
  "homepage": "https://github.com/JSM-Sultana/sultana-agent-tools-package#readme",
6
6
  "bugs": {
@@ -38,6 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@icp-sdk/core": "^6.1.0",
41
+ "@jsm-mit/sultana-assets-rust-package": "^0.1.0",
41
42
  "@jsm-mit/sultana-core-motoko-package": "^0.21.1"
42
43
  },
43
44
  "devDependencies": {