@jsm-mit/sultana-agent-tools-package 0.2.0 → 0.4.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 +106 -8
- package/dist/confirmations.d.ts +61 -0
- package/dist/confirmations.d.ts.map +1 -0
- package/dist/confirmations.js +100 -0
- package/dist/create-salon-tools.d.ts +13 -2
- package/dist/create-salon-tools.d.ts.map +1 -1
- package/dist/create-salon-tools.js +10 -4
- package/dist/customer/create-customer-tools.d.ts +38 -0
- package/dist/customer/create-customer-tools.d.ts.map +1 -0
- package/dist/customer/create-customer-tools.js +47 -0
- package/dist/customer/customer-core-port.d.ts +94 -0
- package/dist/customer/customer-core-port.d.ts.map +1 -0
- package/dist/customer/customer-core-port.js +1 -0
- package/dist/customer/ic-customer-core-port.d.ts +45 -0
- package/dist/customer/ic-customer-core-port.d.ts.map +1 -0
- package/dist/customer/ic-customer-core-port.js +132 -0
- package/dist/customer/persona.d.ts +6 -0
- package/dist/customer/persona.d.ts.map +1 -0
- package/dist/customer/persona.js +27 -0
- package/dist/customer/time.d.ts +27 -0
- package/dist/customer/time.d.ts.map +1 -0
- package/dist/customer/time.js +113 -0
- package/dist/customer/tools.d.ts +17 -0
- package/dist/customer/tools.d.ts.map +1 -0
- package/dist/customer/tools.js +415 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/persona.d.ts +4 -1
- package/dist/persona.d.ts.map +1 -1
- package/dist/persona.js +18 -7
- package/dist/tools/promos.d.ts +2 -1
- package/dist/tools/promos.d.ts.map +1 -1
- package/dist/tools/promos.js +79 -39
- package/dist/tools/schedule.d.ts +2 -1
- package/dist/tools/schedule.d.ts.map +1 -1
- package/dist/tools/schedule.js +51 -31
- package/dist/tools/services.d.ts +4 -2
- package/dist/tools/services.d.ts.map +1 -1
- package/dist/tools/services.js +75 -30
- package/dist/tools/write-gate.d.ts +29 -0
- package/dist/tools/write-gate.d.ts.map +1 -0
- package/dist/tools/write-gate.js +37 -0
- package/package.json +4 -3
package/dist/tools/promos.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { MAX_ACTIVE_PROMOS_PER_SALON, MAX_PROMOS_PER_SALON } from "@jsm-mit/sultana-core-motoko-package";
|
|
2
2
|
import { toToolError } from "../errors.js";
|
|
3
|
-
import { err,
|
|
3
|
+
import { err, ok } from "../types.js";
|
|
4
4
|
import { ArgumentError, phrasesMatch, readBoolean, readOptionalNumber, readOptionalString, readOptionalStringArray, readString, } from "./args.js";
|
|
5
|
+
import { writeGate } from "./write-gate.js";
|
|
5
6
|
const MAX_PROMO_NAME_LENGTH = 60;
|
|
6
7
|
const MAX_TEXT_LINES = 2;
|
|
7
8
|
const MAX_CHIPS = 2;
|
|
@@ -9,17 +10,17 @@ const CONFIRMED_FIELD = {
|
|
|
9
10
|
type: "boolean",
|
|
10
11
|
description: "false dla podglądu: narzędzie nic nie zapisze i odda opis zmiany do zatwierdzenia przez właściciela. true dopiero po potwierdzeniu.",
|
|
11
12
|
};
|
|
12
|
-
export function createPromoTools(port) {
|
|
13
|
+
export function createPromoTools(port, confirmations) {
|
|
13
14
|
return [
|
|
14
15
|
listMediaTool(port),
|
|
15
16
|
listPromosTool(port),
|
|
16
|
-
addPromoTool(port),
|
|
17
|
-
updatePromoTool(port),
|
|
18
|
-
setPromoActiveTool(port),
|
|
19
|
-
removePromoTool(port),
|
|
17
|
+
addPromoTool(port, confirmations),
|
|
18
|
+
updatePromoTool(port, confirmations),
|
|
19
|
+
setPromoActiveTool(port, confirmations),
|
|
20
|
+
removePromoTool(port, confirmations),
|
|
20
21
|
listDiscountCodesTool(port),
|
|
21
|
-
addDiscountCodeTool(port),
|
|
22
|
-
removeDiscountCodeTool(port),
|
|
22
|
+
addDiscountCodeTool(port, confirmations),
|
|
23
|
+
removeDiscountCodeTool(port, confirmations),
|
|
23
24
|
];
|
|
24
25
|
}
|
|
25
26
|
function listMediaTool(port) {
|
|
@@ -81,12 +82,13 @@ export function listPromosTool(port, access = "owner") {
|
|
|
81
82
|
},
|
|
82
83
|
};
|
|
83
84
|
}
|
|
84
|
-
function addPromoTool(port) {
|
|
85
|
+
function addPromoTool(port, confirmations) {
|
|
86
|
+
const gate = writeGate("add_promo", confirmations);
|
|
85
87
|
return {
|
|
86
88
|
name: "add_promo",
|
|
87
89
|
progress: "Zakładam promocję…",
|
|
88
90
|
description: "Zakłada nową promocję na materiale z biblioteki. Najpierw wywołaj list_media i wybierz assetId. Nowa promocja jest nieaktywna — włącz ją potem przez set_promo_active.",
|
|
89
|
-
parameters: {
|
|
91
|
+
parameters: gate.parameters({
|
|
90
92
|
type: "object",
|
|
91
93
|
properties: {
|
|
92
94
|
name: { type: "string", description: `Nazwa kampanii, maksymalnie ${MAX_PROMO_NAME_LENGTH} znaków.` },
|
|
@@ -104,13 +106,19 @@ function addPromoTool(port) {
|
|
|
104
106
|
},
|
|
105
107
|
required: ["name", "assetId", "confirmed"],
|
|
106
108
|
additionalProperties: false,
|
|
107
|
-
},
|
|
109
|
+
}),
|
|
108
110
|
execute: async (args) => {
|
|
109
111
|
try {
|
|
112
|
+
const refusal = gate.refusal(args);
|
|
113
|
+
if (refusal)
|
|
114
|
+
return refusal;
|
|
110
115
|
const input = await buildPromoInput(port, args, null);
|
|
111
116
|
if (!readBoolean(args, "confirmed")) {
|
|
112
|
-
return
|
|
117
|
+
return gate.preview(`Założę promocję ${await describePromo(port, input)}.`, args);
|
|
113
118
|
}
|
|
119
|
+
const refused = gate.redeem(args);
|
|
120
|
+
if (refused)
|
|
121
|
+
return refused;
|
|
114
122
|
const promoId = await port.addPromo(input);
|
|
115
123
|
return ok(`Założono promocję „${input.name}”. Jest jeszcze nieaktywna.`, { promoId });
|
|
116
124
|
}
|
|
@@ -122,12 +130,13 @@ function addPromoTool(port) {
|
|
|
122
130
|
},
|
|
123
131
|
};
|
|
124
132
|
}
|
|
125
|
-
function updatePromoTool(port) {
|
|
133
|
+
function updatePromoTool(port, confirmations) {
|
|
134
|
+
const gate = writeGate("update_promo", confirmations);
|
|
126
135
|
return {
|
|
127
136
|
name: "update_promo",
|
|
128
137
|
progress: "Zmieniam promocję…",
|
|
129
138
|
description: "Zmienia istniejącą promocję. Podaj tylko pola, które mają się zmienić — reszta zostanie zachowana. Promocja zachowuje swoje miejsce w kanale, więc poprawka nie restartuje kampanii.",
|
|
130
|
-
parameters: {
|
|
139
|
+
parameters: gate.parameters({
|
|
131
140
|
type: "object",
|
|
132
141
|
properties: {
|
|
133
142
|
promoId: { type: "string", description: "Id promocji z list_promos." },
|
|
@@ -142,20 +151,23 @@ function updatePromoTool(port) {
|
|
|
142
151
|
},
|
|
143
152
|
required: ["promoId", "confirmed"],
|
|
144
153
|
additionalProperties: false,
|
|
145
|
-
},
|
|
154
|
+
}),
|
|
146
155
|
execute: async (args) => {
|
|
147
156
|
try {
|
|
157
|
+
const refusal = gate.refusal(args);
|
|
158
|
+
if (refusal)
|
|
159
|
+
return refusal;
|
|
148
160
|
const promoId = readString(args, "promoId");
|
|
149
161
|
const current = await findPromo(port, promoId);
|
|
150
162
|
if (!current)
|
|
151
163
|
return err("not_found", `W tym salonie nie ma promocji o id ${promoId}.`);
|
|
152
164
|
const input = await buildPromoInput(port, args, current);
|
|
153
165
|
if (!readBoolean(args, "confirmed")) {
|
|
154
|
-
return
|
|
155
|
-
...args,
|
|
156
|
-
confirmed: true,
|
|
157
|
-
});
|
|
166
|
+
return gate.preview(`Zmienię promocję „${current.name}” na: ${await describePromo(port, input)}.`, args);
|
|
158
167
|
}
|
|
168
|
+
const refused = gate.redeem(args);
|
|
169
|
+
if (refused)
|
|
170
|
+
return refused;
|
|
159
171
|
await port.updatePromo(promoId, input);
|
|
160
172
|
return ok(`Zmieniono promocję „${input.name}”.`);
|
|
161
173
|
}
|
|
@@ -167,12 +179,13 @@ function updatePromoTool(port) {
|
|
|
167
179
|
},
|
|
168
180
|
};
|
|
169
181
|
}
|
|
170
|
-
function setPromoActiveTool(port) {
|
|
182
|
+
function setPromoActiveTool(port, confirmations) {
|
|
183
|
+
const gate = writeGate("set_promo_active", confirmations);
|
|
171
184
|
return {
|
|
172
185
|
name: "set_promo_active",
|
|
173
186
|
progress: "Zmieniam status promocji…",
|
|
174
187
|
description: `Włącza promocję w kanale albo ją wyłącza. Naraz może być aktywnych najwyżej ${MAX_ACTIVE_PROMOS_PER_SALON} — żeby włączyć kolejną, najpierw wyłącz inną.`,
|
|
175
|
-
parameters: {
|
|
188
|
+
parameters: gate.parameters({
|
|
176
189
|
type: "object",
|
|
177
190
|
properties: {
|
|
178
191
|
promoId: { type: "string", description: "Id promocji z list_promos." },
|
|
@@ -181,9 +194,12 @@ function setPromoActiveTool(port) {
|
|
|
181
194
|
},
|
|
182
195
|
required: ["promoId", "active", "confirmed"],
|
|
183
196
|
additionalProperties: false,
|
|
184
|
-
},
|
|
197
|
+
}),
|
|
185
198
|
execute: async (args) => {
|
|
186
199
|
try {
|
|
200
|
+
const refusal = gate.refusal(args);
|
|
201
|
+
if (refusal)
|
|
202
|
+
return refusal;
|
|
187
203
|
const promoId = readString(args, "promoId");
|
|
188
204
|
const current = await findPromo(port, promoId);
|
|
189
205
|
if (!current)
|
|
@@ -191,11 +207,11 @@ function setPromoActiveTool(port) {
|
|
|
191
207
|
const active = readBoolean(args, "active");
|
|
192
208
|
const verb = active ? "włączę" : "wyłączę";
|
|
193
209
|
if (!readBoolean(args, "confirmed")) {
|
|
194
|
-
return
|
|
195
|
-
...args,
|
|
196
|
-
confirmed: true,
|
|
197
|
-
});
|
|
210
|
+
return gate.preview(`${verb[0].toUpperCase()}${verb.slice(1)} promocję „${current.name}”.`, args);
|
|
198
211
|
}
|
|
212
|
+
const refused = gate.redeem(args);
|
|
213
|
+
if (refused)
|
|
214
|
+
return refused;
|
|
199
215
|
await port.setPromoActive(promoId, active);
|
|
200
216
|
return ok(`Promocja „${current.name}” jest teraz ${active ? "aktywna" : "wyłączona"}.`);
|
|
201
217
|
}
|
|
@@ -207,12 +223,13 @@ function setPromoActiveTool(port) {
|
|
|
207
223
|
},
|
|
208
224
|
};
|
|
209
225
|
}
|
|
210
|
-
function removePromoTool(port) {
|
|
226
|
+
function removePromoTool(port, confirmations) {
|
|
227
|
+
const gate = writeGate("remove_promo", confirmations);
|
|
211
228
|
return {
|
|
212
229
|
name: "remove_promo",
|
|
213
230
|
progress: "Kasuję promocję…",
|
|
214
231
|
description: "Kasuje promocję z biblioteki. Nieodwracalne — właściciel musi przepisać jej nazwę w confirmationPhrase. Żeby tylko zdjąć ją z kanału, użyj set_promo_active.",
|
|
215
|
-
parameters: {
|
|
232
|
+
parameters: gate.parameters({
|
|
216
233
|
type: "object",
|
|
217
234
|
properties: {
|
|
218
235
|
promoId: { type: "string", description: "Id promocji z list_promos." },
|
|
@@ -221,20 +238,29 @@ function removePromoTool(port) {
|
|
|
221
238
|
},
|
|
222
239
|
required: ["promoId", "confirmed"],
|
|
223
240
|
additionalProperties: false,
|
|
224
|
-
},
|
|
241
|
+
}),
|
|
225
242
|
execute: async (args) => {
|
|
226
243
|
try {
|
|
227
244
|
const promoId = readString(args, "promoId");
|
|
245
|
+
// No confirmationPhrase in the echo: the name is the owner's to type, so a model that
|
|
246
|
+
// simply sends the echo back cannot delete anything.
|
|
247
|
+
const echo = { promoId };
|
|
248
|
+
const refusal = gate.refusal(args, echo);
|
|
249
|
+
if (refusal)
|
|
250
|
+
return refusal;
|
|
228
251
|
const current = await findPromo(port, promoId);
|
|
229
252
|
if (!current)
|
|
230
253
|
return err("not_found", `W tym salonie nie ma promocji o id ${promoId}.`);
|
|
231
254
|
if (!readBoolean(args, "confirmed")) {
|
|
232
|
-
return
|
|
255
|
+
return gate.preview(`Skasuję promocję „${current.name}”. Tego nie da się cofnąć — poproś właścicielkę, żeby sama napisała dokładną nazwę promocji, i wstaw ją w confirmationPhrase. Jeśli chodzi tylko o zdjęcie z kanału, lepiej ją wyłączyć.`, echo);
|
|
233
256
|
}
|
|
234
257
|
const phrase = readOptionalString(args, "confirmationPhrase");
|
|
235
258
|
if (!phrase || !phrasesMatch(phrase, current.name)) {
|
|
236
|
-
return err("invalid_arguments", `Aby skasować promocję,
|
|
259
|
+
return err("invalid_arguments", `Aby skasować promocję, właścicielka musi sama napisać jej dokładną nazwę: „${current.name}”.`);
|
|
237
260
|
}
|
|
261
|
+
const refused = gate.redeem(args, echo);
|
|
262
|
+
if (refused)
|
|
263
|
+
return refused;
|
|
238
264
|
await port.removePromo(promoId);
|
|
239
265
|
return ok(`Skasowano promocję „${current.name}”.`);
|
|
240
266
|
}
|
|
@@ -265,12 +291,13 @@ function listDiscountCodesTool(port) {
|
|
|
265
291
|
},
|
|
266
292
|
};
|
|
267
293
|
}
|
|
268
|
-
function addDiscountCodeTool(port) {
|
|
294
|
+
function addDiscountCodeTool(port, confirmations) {
|
|
295
|
+
const gate = writeGate("add_discount_code", confirmations);
|
|
269
296
|
return {
|
|
270
297
|
name: "add_discount_code",
|
|
271
298
|
progress: "Dodaję kod rabatowy…",
|
|
272
299
|
description: "Dodaje kod rabatowy salonu. Podaj albo percent, albo amountPln — nie oba. Kod nie ma daty ważności ani limitu użyć; działa, dopóki go nie usuniesz.",
|
|
273
|
-
parameters: {
|
|
300
|
+
parameters: gate.parameters({
|
|
274
301
|
type: "object",
|
|
275
302
|
properties: {
|
|
276
303
|
code: { type: "string", description: "Treść kodu, którą wpisze klientka." },
|
|
@@ -281,9 +308,12 @@ function addDiscountCodeTool(port) {
|
|
|
281
308
|
},
|
|
282
309
|
required: ["code", "confirmed"],
|
|
283
310
|
additionalProperties: false,
|
|
284
|
-
},
|
|
311
|
+
}),
|
|
285
312
|
execute: async (args) => {
|
|
286
313
|
try {
|
|
314
|
+
const refusal = gate.refusal(args);
|
|
315
|
+
if (refusal)
|
|
316
|
+
return refusal;
|
|
287
317
|
const code = readString(args, "code");
|
|
288
318
|
const percent = readOptionalNumber(args, "percent");
|
|
289
319
|
const amountPln = readOptionalNumber(args, "amountPln");
|
|
@@ -301,8 +331,11 @@ function addDiscountCodeTool(port) {
|
|
|
301
331
|
const value = percent !== undefined ? `${percent}%` : `${amountPln} zł`;
|
|
302
332
|
const scope = scopeServiceId ? "na jedną usługę" : "na cały salon";
|
|
303
333
|
if (!readBoolean(args, "confirmed")) {
|
|
304
|
-
return
|
|
334
|
+
return gate.preview(`Dodam kod rabatowy „${code}”: ${value}, ${scope}.`, args);
|
|
305
335
|
}
|
|
336
|
+
const refused = gate.redeem(args);
|
|
337
|
+
if (refused)
|
|
338
|
+
return refused;
|
|
306
339
|
await port.addDiscountCode({ code, percent, amountPln, scopeServiceId });
|
|
307
340
|
return ok(`Dodano kod rabatowy „${code}” (${value}, ${scope}).`);
|
|
308
341
|
}
|
|
@@ -314,12 +347,13 @@ function addDiscountCodeTool(port) {
|
|
|
314
347
|
},
|
|
315
348
|
};
|
|
316
349
|
}
|
|
317
|
-
function removeDiscountCodeTool(port) {
|
|
350
|
+
function removeDiscountCodeTool(port, confirmations) {
|
|
351
|
+
const gate = writeGate("remove_discount_code", confirmations);
|
|
318
352
|
return {
|
|
319
353
|
name: "remove_discount_code",
|
|
320
354
|
progress: "Usuwam kod rabatowy…",
|
|
321
355
|
description: "Usuwa kod rabatowy salonu. Kanister odmówi, dopóki jakakolwiek promocja ten kod rozgłasza — wtedy najpierw zmień promocję.",
|
|
322
|
-
parameters: {
|
|
356
|
+
parameters: gate.parameters({
|
|
323
357
|
type: "object",
|
|
324
358
|
properties: {
|
|
325
359
|
code: { type: "string", description: "Treść kodu z list_discount_codes." },
|
|
@@ -327,18 +361,24 @@ function removeDiscountCodeTool(port) {
|
|
|
327
361
|
},
|
|
328
362
|
required: ["code", "confirmed"],
|
|
329
363
|
additionalProperties: false,
|
|
330
|
-
},
|
|
364
|
+
}),
|
|
331
365
|
// No confirmation phrase here, unlike a service or a promo: a removed code can simply be
|
|
332
366
|
// added back with the same text, and nothing else in the salon points at it.
|
|
333
367
|
execute: async (args) => {
|
|
334
368
|
try {
|
|
369
|
+
const refusal = gate.refusal(args);
|
|
370
|
+
if (refusal)
|
|
371
|
+
return refusal;
|
|
335
372
|
const code = readString(args, "code");
|
|
336
373
|
const codes = await port.listDiscountCodes();
|
|
337
374
|
if (!codes.some((entry) => entry.code === code))
|
|
338
375
|
return err("not_found", `Salon nie ma kodu „${code}”.`);
|
|
339
376
|
if (!readBoolean(args, "confirmed")) {
|
|
340
|
-
return
|
|
377
|
+
return gate.preview(`Usunę kod rabatowy „${code}”.`, args);
|
|
341
378
|
}
|
|
379
|
+
const refused = gate.redeem(args);
|
|
380
|
+
if (refused)
|
|
381
|
+
return refused;
|
|
342
382
|
await port.removeDiscountCode(code);
|
|
343
383
|
return ok(`Usunięto kod rabatowy „${code}”.`);
|
|
344
384
|
}
|
package/dist/tools/schedule.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import type { TurnConfirmations } from "../confirmations.js";
|
|
1
2
|
import type { SalonCorePort } from "../salon-core-port.js";
|
|
2
3
|
import { type AgentTool } from "../types.js";
|
|
3
|
-
export declare function createScheduleTools(port: SalonCorePort): AgentTool[];
|
|
4
|
+
export declare function createScheduleTools(port: SalonCorePort, confirmations?: TurnConfirmations): AgentTool[];
|
|
4
5
|
//# sourceMappingURL=schedule.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/tools/schedule.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/tools/schedule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAyB,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAsBtD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,iBAAiB,GAAG,SAAS,EAAE,CASvG"}
|
package/dist/tools/schedule.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { formatMinutesToTime, parseTimeRangesToSlots, parseTimeToMinutes } from "@jsm-mit/sultana-core-motoko-package";
|
|
2
2
|
import { toToolError } from "../errors.js";
|
|
3
|
-
import { err,
|
|
3
|
+
import { err, ok } from "../types.js";
|
|
4
4
|
import { ArgumentError, readBoolean, readOptionalString, readString } from "./args.js";
|
|
5
|
+
import { writeGate } from "./write-gate.js";
|
|
5
6
|
/** 0 = Monday, matching the canister's own day index. */
|
|
6
7
|
const DAY_NAMES_PL = ["poniedziałek", "wtorek", "środa", "czwartek", "piątek", "sobota", "niedziela"];
|
|
7
8
|
const CONFIRMED_FIELD = {
|
|
@@ -14,14 +15,14 @@ const RANGES_FIELD = {
|
|
|
14
15
|
type: "string",
|
|
15
16
|
description: 'Zakresy godzin oddzielone przecinkiem, np. "10-18" albo "9:30-13,14-18".',
|
|
16
17
|
};
|
|
17
|
-
export function createScheduleTools(port) {
|
|
18
|
+
export function createScheduleTools(port, confirmations) {
|
|
18
19
|
return [
|
|
19
20
|
getWeeklyHoursTool(port),
|
|
20
|
-
setWeeklyHoursTool(port),
|
|
21
|
+
setWeeklyHoursTool(port, confirmations),
|
|
21
22
|
getDayScheduleTool(port),
|
|
22
|
-
setDayOffTool(port),
|
|
23
|
-
setBusyHoursTool(port),
|
|
24
|
-
clearDailyOverrideTool(port),
|
|
23
|
+
setDayOffTool(port, confirmations),
|
|
24
|
+
setBusyHoursTool(port, confirmations),
|
|
25
|
+
clearDailyOverrideTool(port, confirmations),
|
|
25
26
|
];
|
|
26
27
|
}
|
|
27
28
|
function getWeeklyHoursTool(port) {
|
|
@@ -53,12 +54,13 @@ function getWeeklyHoursTool(port) {
|
|
|
53
54
|
},
|
|
54
55
|
};
|
|
55
56
|
}
|
|
56
|
-
function setWeeklyHoursTool(port) {
|
|
57
|
+
function setWeeklyHoursTool(port, confirmations) {
|
|
58
|
+
const gate = writeGate("set_weekly_hours", confirmations);
|
|
57
59
|
return {
|
|
58
60
|
name: "set_weekly_hours",
|
|
59
61
|
progress: "Ustawiam grafik…",
|
|
60
62
|
description: "Ustawia godziny PRACY pracownika w wybranych dniach tygodnia. Zastępuje dotychczasowe godziny w tych dniach. Pusty zakres oznacza dzień niepracujący.",
|
|
61
|
-
parameters: {
|
|
63
|
+
parameters: gate.parameters({
|
|
62
64
|
type: "object",
|
|
63
65
|
properties: {
|
|
64
66
|
workerId: WORKER_FIELD,
|
|
@@ -72,20 +74,23 @@ function setWeeklyHoursTool(port) {
|
|
|
72
74
|
},
|
|
73
75
|
required: ["workerId", "days", "ranges", "confirmed"],
|
|
74
76
|
additionalProperties: false,
|
|
75
|
-
},
|
|
77
|
+
}),
|
|
76
78
|
execute: async (args) => {
|
|
77
79
|
try {
|
|
80
|
+
const refusal = gate.refusal(args);
|
|
81
|
+
if (refusal)
|
|
82
|
+
return refusal;
|
|
78
83
|
const worker = await resolveWorker(port, readString(args, "workerId"));
|
|
79
84
|
const days = readDays(args);
|
|
80
85
|
const parsed = normalizeRanges(readOptionalString(args, "ranges") ?? "");
|
|
81
86
|
const dayNames = days.map((day) => DAY_NAMES_PL[day]).join(", ");
|
|
82
87
|
const hours = parsed.ranges.length === 0 ? "dzień wolny" : formatRanges(parsed.ranges).join(", ");
|
|
83
88
|
if (!readBoolean(args, "confirmed")) {
|
|
84
|
-
return
|
|
85
|
-
...args,
|
|
86
|
-
confirmed: true,
|
|
87
|
-
});
|
|
89
|
+
return gate.preview(`Ustawię ${worker.name}: ${dayNames} — ${hours}.${noteSuffix(parsed.notes)}`, args);
|
|
88
90
|
}
|
|
91
|
+
const refused = gate.redeem(args);
|
|
92
|
+
if (refused)
|
|
93
|
+
return refused;
|
|
89
94
|
for (const day of days) {
|
|
90
95
|
await port.setWeeklyHours(worker.id, day, parsed.ranges);
|
|
91
96
|
}
|
|
@@ -127,24 +132,31 @@ function getDayScheduleTool(port) {
|
|
|
127
132
|
},
|
|
128
133
|
};
|
|
129
134
|
}
|
|
130
|
-
function setDayOffTool(port) {
|
|
135
|
+
function setDayOffTool(port, confirmations) {
|
|
136
|
+
const gate = writeGate("set_day_off", confirmations);
|
|
131
137
|
return {
|
|
132
138
|
name: "set_day_off",
|
|
133
139
|
progress: "Ustawiam dzień wolny…",
|
|
134
140
|
description: "Oznacza cały wskazany dzień jako wolny dla pracownika.",
|
|
135
|
-
parameters: {
|
|
141
|
+
parameters: gate.parameters({
|
|
136
142
|
type: "object",
|
|
137
143
|
properties: { workerId: WORKER_FIELD, date: DATE_FIELD, confirmed: CONFIRMED_FIELD },
|
|
138
144
|
required: ["workerId", "date", "confirmed"],
|
|
139
145
|
additionalProperties: false,
|
|
140
|
-
},
|
|
146
|
+
}),
|
|
141
147
|
execute: async (args) => {
|
|
142
148
|
try {
|
|
149
|
+
const refusal = gate.refusal(args);
|
|
150
|
+
if (refusal)
|
|
151
|
+
return refusal;
|
|
143
152
|
const worker = await resolveWorker(port, readString(args, "workerId"));
|
|
144
153
|
const date = readDate(args);
|
|
145
154
|
if (!readBoolean(args, "confirmed")) {
|
|
146
|
-
return
|
|
155
|
+
return gate.preview(`Ustawię ${worker.name} dzień wolny: ${date}.`, args);
|
|
147
156
|
}
|
|
157
|
+
const refused = gate.redeem(args);
|
|
158
|
+
if (refused)
|
|
159
|
+
return refused;
|
|
148
160
|
await port.setDayOff(worker.id, date);
|
|
149
161
|
return ok(`${worker.name} ma wolne ${date}.`);
|
|
150
162
|
}
|
|
@@ -156,19 +168,23 @@ function setDayOffTool(port) {
|
|
|
156
168
|
},
|
|
157
169
|
};
|
|
158
170
|
}
|
|
159
|
-
function setBusyHoursTool(port) {
|
|
171
|
+
function setBusyHoursTool(port, confirmations) {
|
|
172
|
+
const gate = writeGate("set_busy_hours", confirmations);
|
|
160
173
|
return {
|
|
161
174
|
name: "set_busy_hours",
|
|
162
175
|
progress: "Zapisuję godziny zajęte…",
|
|
163
176
|
description: "Ustawia godziny ZAJĘTE w konkretnym dniu — nadpisuje grafik tygodniowy tylko tego dnia. Używaj do jednorazowych nieobecności („we wtorek jestem zajęta od 12 do 15”).",
|
|
164
|
-
parameters: {
|
|
177
|
+
parameters: gate.parameters({
|
|
165
178
|
type: "object",
|
|
166
179
|
properties: { workerId: WORKER_FIELD, date: DATE_FIELD, ranges: RANGES_FIELD, confirmed: CONFIRMED_FIELD },
|
|
167
180
|
required: ["workerId", "date", "ranges", "confirmed"],
|
|
168
181
|
additionalProperties: false,
|
|
169
|
-
},
|
|
182
|
+
}),
|
|
170
183
|
execute: async (args) => {
|
|
171
184
|
try {
|
|
185
|
+
const refusal = gate.refusal(args);
|
|
186
|
+
if (refusal)
|
|
187
|
+
return refusal;
|
|
172
188
|
const worker = await resolveWorker(port, readString(args, "workerId"));
|
|
173
189
|
const date = readDate(args);
|
|
174
190
|
const parsed = normalizeRanges(readString(args, "ranges"));
|
|
@@ -177,11 +193,11 @@ function setBusyHoursTool(port) {
|
|
|
177
193
|
}
|
|
178
194
|
const hours = formatRanges(parsed.ranges).join(", ");
|
|
179
195
|
if (!readBoolean(args, "confirmed")) {
|
|
180
|
-
return
|
|
181
|
-
...args,
|
|
182
|
-
confirmed: true,
|
|
183
|
-
});
|
|
196
|
+
return gate.preview(`Zaznaczę ${worker.name} jako zajętą ${date}: ${hours}.${noteSuffix(parsed.notes)}`, args);
|
|
184
197
|
}
|
|
198
|
+
const refused = gate.redeem(args);
|
|
199
|
+
if (refused)
|
|
200
|
+
return refused;
|
|
185
201
|
await port.setDailyBusy(worker.id, date, parsed.ranges);
|
|
186
202
|
return ok(`${worker.name}, ${date}: zajęte ${hours}.${noteSuffix(parsed.notes)}`);
|
|
187
203
|
}
|
|
@@ -193,27 +209,31 @@ function setBusyHoursTool(port) {
|
|
|
193
209
|
},
|
|
194
210
|
};
|
|
195
211
|
}
|
|
196
|
-
function clearDailyOverrideTool(port) {
|
|
212
|
+
function clearDailyOverrideTool(port, confirmations) {
|
|
213
|
+
const gate = writeGate("clear_daily_override", confirmations);
|
|
197
214
|
return {
|
|
198
215
|
name: "clear_daily_override",
|
|
199
216
|
progress: "Przywracam grafik tygodniowy…",
|
|
200
217
|
description: "Usuwa nadpisanie dla wskazanego dnia — od tej chwili obowiązuje zwykły grafik tygodniowy.",
|
|
201
|
-
parameters: {
|
|
218
|
+
parameters: gate.parameters({
|
|
202
219
|
type: "object",
|
|
203
220
|
properties: { workerId: WORKER_FIELD, date: DATE_FIELD, confirmed: CONFIRMED_FIELD },
|
|
204
221
|
required: ["workerId", "date", "confirmed"],
|
|
205
222
|
additionalProperties: false,
|
|
206
|
-
},
|
|
223
|
+
}),
|
|
207
224
|
execute: async (args) => {
|
|
208
225
|
try {
|
|
226
|
+
const refusal = gate.refusal(args);
|
|
227
|
+
if (refusal)
|
|
228
|
+
return refusal;
|
|
209
229
|
const worker = await resolveWorker(port, readString(args, "workerId"));
|
|
210
230
|
const date = readDate(args);
|
|
211
231
|
if (!readBoolean(args, "confirmed")) {
|
|
212
|
-
return
|
|
213
|
-
...args,
|
|
214
|
-
confirmed: true,
|
|
215
|
-
});
|
|
232
|
+
return gate.preview(`Usunę nadpisanie dnia ${date} dla ${worker.name} — wróci grafik tygodniowy.`, args);
|
|
216
233
|
}
|
|
234
|
+
const refused = gate.redeem(args);
|
|
235
|
+
if (refused)
|
|
236
|
+
return refused;
|
|
217
237
|
await port.clearDailyOverride(worker.id, date);
|
|
218
238
|
return ok(`${worker.name}, ${date}: wrócił grafik tygodniowy.`);
|
|
219
239
|
}
|
package/dist/tools/services.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { TurnConfirmations } from "../confirmations.js";
|
|
1
2
|
import type { SalonAccess, SalonCorePort } from "../salon-core-port.js";
|
|
2
3
|
import { type AgentTool } from "../types.js";
|
|
3
|
-
export declare function createServiceTools(port: SalonCorePort): AgentTool[];
|
|
4
|
+
export declare function createServiceTools(port: SalonCorePort, confirmations?: TurnConfirmations): AgentTool[];
|
|
4
5
|
/** `access` must match the port: `"public"` only for a port that reads the visitor's view. */
|
|
5
6
|
export declare function listServicesTool(port: SalonCorePort, access?: SalonAccess): AgentTool;
|
|
6
|
-
|
|
7
|
+
/** Takes any port that can search the catalogue — the customer set shares this tool. */
|
|
8
|
+
export declare function findServiceTypeTool(port: Pick<SalonCorePort, "findServiceTypes">): AgentTool;
|
|
7
9
|
//# sourceMappingURL=services.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/tools/services.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/tools/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAkC,MAAM,uBAAuB,CAAC;AACxG,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAwBtD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,iBAAiB,GAAG,SAAS,EAAE,CAStG;AAoBD,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,GAAE,WAAqB,GAAG,SAAS,CAmB9F;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,GAAG,SAAS,CAiC5F"}
|