@naisys/erp 3.0.0-beta.49 → 3.0.0-beta.51

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.
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM } from "./rolldown-runtime-CvHMtSRF.js";
2
- import { $ as string, $t as Popover, A as IconPlus, At as Modal, B as IconCheck, Bt as Card, C as IconCopy, Ct as Stack, D as IconUpload, Dt as PasswordInput, E as IconUser, Et as Tooltip, F as IconLayoutSidebarLeftCollapse, Ft as Drawer, G as require_semver, Gt as AppShell, H as IconApi, Ht as Badge, I as IconInfoCircle, It as Divider, J as array, Jt as Alert, K as ZodIssueCode, Kt as Anchor, L as IconFile, Lt as Container, M as IconLogout, Mt as Textarea, N as IconListDetails, Nt as Image, O as IconTrash, Ot as Pagination, P as IconLayoutSidebarLeftExpand, Pt as FileButton, Q as record, Qt as Loader, R as IconEye$1, Rt as Code, S as IconDownload, St as Switch, T as IconX, Tt as SegmentedControl, U as IconAlertTriangle, Ut as Autocomplete, V as IconArrowBackUp, Vt as Button, W as IconAlertCircle, Wt as Checkbox, X as number, Xt as Group, Y as boolean, Yt as Accordion, Z as object, Zt as ActionIcon, _ as Markdown, _t as DatesProvider, a as _undefined, an as useDebouncedValue, at as Outlet, b as IconEye, bt as Tabs, c as boolean$1, cn as require_react, ct as useLocation, d as object$1, dt as useParams, en as UnstyledButton, et as union, f as string$1, ft as useSearchParams, g as remarkGfm, gt as DateInput, h as diffWordsWithSpace, ht as DateTimePicker, i as _null, in as useDisclosure, it as Navigate, j as IconNote, jt as Menu, k as IconRobot, kt as NumberInput, l as literal, lt as useNavigate, m as datetime, mt as notifications, n as string$2, nn as Box, nt as BrowserRouter, o as any, on as require_jsx_runtime, ot as Route, p as union$1, pt as Notifications, q as _enum, qt as Text, r as _enum$1, rn as MantineProvider, rt as Link, s as array$1, sn as require_client, st as Routes, t as number$1, tn as ScrollArea, tt as unknown, u as number$2, ut as useOutletContext, v as IconRefresh, vt as Title, w as useForm, wt as Select, x as IconEyeOff, xt as Table, y as IconPhoto, yt as TextInput, z as IconChevronDown, zt as Center } from "./vendor-Co7ZCNxO.js";
2
+ import { $ as record, $t as Loader, A as IconPlus, At as NumberInput, B as IconCheck, Bt as Center, C as IconCopy, Ct as Switch, D as IconUpload, Dt as Tooltip, E as IconUser, Et as SegmentedControl, F as IconLayoutSidebarLeftCollapse, Ft as FileButton, G as require_semver, Gt as Checkbox, H as IconApi, Ht as Button, I as IconInfoCircle, It as Drawer, J as _enum, Jt as Text, K as require_dist, Kt as AppShell, L as IconFile, Lt as Divider, M as IconLogout, Mt as Menu, N as IconListDetails, Nt as Textarea, O as IconTrash, Ot as PasswordInput, P as IconLayoutSidebarLeftExpand, Pt as Image, Q as object, Qt as ActionIcon, R as IconEye$1, Rt as Container, S as IconDownload, St as Table, T as IconX, Tt as Select, U as IconAlertTriangle, Ut as Badge, V as IconArrowBackUp, Vt as Card, W as IconAlertCircle, Wt as Autocomplete, X as boolean, Xt as Accordion, Y as array, Yt as Alert, Z as number, Zt as Group, _ as Markdown, _t as DateInput, a as _undefined, an as useDisclosure, at as Navigate, b as IconEye, bt as TextInput, c as boolean$1, cn as require_client, ct as Routes, d as object$1, dt as useOutletContext, en as Popover, et as string, f as string$1, ft as useParams, g as remarkGfm, gt as DateTimePicker, h as diffWordsWithSpace, ht as notifications, i as _null, in as MantineProvider, it as Link, j as IconNote, jt as Modal, k as IconRobot, kt as Pagination, l as literal, ln as require_react, lt as useLocation, m as datetime, mt as Notifications, n as string$2, nn as ScrollArea, nt as unknown, o as any, on as useDebouncedValue, ot as Outlet, p as union$1, pt as useSearchParams, q as ZodIssueCode, qt as Anchor, r as _enum$1, rn as Box, rt as BrowserRouter, s as array$1, sn as require_jsx_runtime, st as Route, t as number$1, tn as UnstyledButton, tt as union, u as number$2, ut as useNavigate, v as IconRefresh, vt as DatesProvider, w as useForm, wt as Stack, x as IconEyeOff, xt as Tabs, y as IconPhoto, yt as Title, z as IconChevronDown, zt as Code } from "./vendor-CJ0ET9hP.js";
3
3
  //#region \0vite/modulepreload-polyfill.js
4
4
  (function polyfill() {
5
5
  const relList = document.createElement("link").relList;
@@ -42,6 +42,32 @@ var URL_SAFE_KEY_MESSAGE = "Must contain only letters, numbers, hyphens, and und
42
42
  /** Target megapixels for screenshots sent to LLMs during computer use */
43
43
  var TARGET_MEGAPIXELS = 1.1;
44
44
  //#endregion
45
+ //#region ../../../packages/common/dist/agent/scheduleUtils.js
46
+ var import_dist = require_dist();
47
+ var ScheduleEntrySchema = object({
48
+ name: string().min(1, "Name is required").regex(URL_SAFE_KEY_REGEX, URL_SAFE_KEY_MESSAGE).describe("Unique identifier for this schedule within the agent"),
49
+ cron: string().min(1, "Cron expression is required").refine((expr) => validateCron(expr).ok, { message: "Invalid cron expression" }).describe("Standard 5-field cron expression in the hub's local timezone"),
50
+ enabled: boolean().optional().describe("When false, the schedule is paused but kept for editing"),
51
+ prompt: string().max(2e3, "Prompt must be at most 2000 characters").optional().describe("Chat message sent to the agent when the schedule fires. Falls back to the schedule name when empty")
52
+ });
53
+ function validateCron(expression) {
54
+ const fields = expression.trim().split(/\s+/).filter(Boolean);
55
+ if (fields.length !== 5) return {
56
+ ok: false,
57
+ error: `Expected 5 fields (min hour day month weekday), got ${fields.length}`
58
+ };
59
+ try {
60
+ import_dist.CronExpressionParser.parse(expression);
61
+ return { ok: true };
62
+ } catch (err) {
63
+ return {
64
+ ok: false,
65
+ error: err instanceof Error ? err.message : String(err)
66
+ };
67
+ }
68
+ }
69
+ object({ schedules: array(unknown()).optional() }).loose();
70
+ //#endregion
45
71
  //#region ../../../packages/common/dist/agent/agentConfigFile.js
46
72
  var commandProtectionValues = [
47
73
  "none",
@@ -82,7 +108,20 @@ object({
82
108
  multipleCommandsEnabled: boolean().optional().describe("Allow the LLM to run multiple commands per turn. Faster but the LLM may get ahead of itself and produce errors. Disable for weaker LLMs."),
83
109
  workspacesEnabled: boolean().optional().describe("Experimental: Allows the LLM to pin files to the end of the context. Each turn the agent sees the latest version without old versions taking up context space"),
84
110
  controlDesktop: boolean().optional().describe(`Allow the agent to operate the desktop GUI. Requires a vision-capable model; computer-use models are ideal. Screens over ${TARGET_MEGAPIXELS}MP will be downscaled.`),
85
- supervisorApiHints: boolean().optional().describe("Tell the agent in its system message how to call the supervisor API to manage NAISYS agents, hosts, variables, models, users, etc. Useful for admin / assistant agents")
111
+ supervisorApiHints: boolean().optional().describe("Tell the agent in its system message how to call the supervisor API to manage NAISYS agents, hosts, variables, models, users, etc. Useful for admin / assistant agents"),
112
+ schedules: array(ScheduleEntrySchema).optional().superRefine((schedules, ctx) => {
113
+ if (!schedules) return;
114
+ const seen = /* @__PURE__ */ new Set();
115
+ for (let i = 0; i < schedules.length; i++) {
116
+ const name = schedules[i].name;
117
+ if (seen.has(name)) ctx.addIssue({
118
+ code: "custom",
119
+ path: [i, "name"],
120
+ message: `Duplicate schedule name "${name}"`
121
+ });
122
+ seen.add(name);
123
+ }
124
+ }).describe("Cron schedules that wake the agent and deliver a chat from admin at fire time. Cron runs in the hub's local timezone. If the agent is offline, the chat queues and dedupes per schedule name.")
86
125
  });
87
126
  //#endregion
88
127
  //#region ../../../packages/common/dist/auth/codexOAuth.js
@@ -299,6 +338,15 @@ LlmApiType.None, LlmApiType.None, LlmApiType.None, LlmApiType.Mock, LlmApiType.M
299
338
  reasoningLevel: "medium"
300
339
  }), LlmApiType.Google, LlmApiType.Google, LlmApiType.Google, LlmApiType.Anthropic, LlmApiType.Anthropic, LlmApiType.Anthropic;
301
340
  //#endregion
341
+ //#region ../../../packages/common/dist/utils/collections.js
342
+ /** Build a plain object record from map entries or projected items. */
343
+ function toRecord(source, keyFn, valueFn) {
344
+ const record = {};
345
+ if (keyFn && valueFn) for (const item of source) record[keyFn(item)] = valueFn(item);
346
+ else for (const [key, value] of source) record[key] = value;
347
+ return record;
348
+ }
349
+ //#endregion
302
350
  //#region ../../../packages/common/dist/utils/formatFileSize.js
303
351
  /** Format a byte count into a human-readable size string (e.g. "1.2 KB") */
304
352
  function formatFileSize(bytes) {
@@ -307,6 +355,14 @@ function formatFileSize(bytes) {
307
355
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
308
356
  }
309
357
  //#endregion
358
+ //#region ../../../packages/common/dist/utils/formatTokens.js
359
+ /** Compact token count for tight UI surfaces (e.g. "12.3k", "1.5M", "123"). */
360
+ function formatTokens(tokens) {
361
+ if (tokens >= 1e6) return `${(tokens / 1e6).toFixed(1)}M`;
362
+ if (tokens >= 1e3) return `${(tokens / 1e3).toFixed(1)}k`;
363
+ return `${Math.round(tokens)}`;
364
+ }
365
+ //#endregion
310
366
  //#region ../../../packages/common/dist/utils/formatVersion.js
311
367
  var import_semver = /* @__PURE__ */ __toESM(require_semver(), 1);
312
368
  /**
@@ -1556,6 +1612,7 @@ var OperationRunSchema = object$1({
1556
1612
  status: OperationRunStatusEnum,
1557
1613
  assignedTo: string$1().nullable(),
1558
1614
  cost: number$2().nullable(),
1615
+ tokens: number$2().nullable(),
1559
1616
  note: string$1().nullable(),
1560
1617
  completedAt: datetime().nullable(),
1561
1618
  stepSummary: array$1(StepRunSummarySchema).optional(),
@@ -1578,6 +1635,7 @@ object$1({
1578
1635
  status: OperationRunStatusEnum,
1579
1636
  assignedTo: string$1().nullable(),
1580
1637
  cost: number$2().nullable(),
1638
+ tokens: number$2().nullable(),
1581
1639
  note: string$1().nullable(),
1582
1640
  completedAt: datetime().nullable(),
1583
1641
  updatedAt: datetime(),
@@ -2047,6 +2105,7 @@ var LaborTicketSchema = object$1({
2047
2105
  clockIn: datetime(),
2048
2106
  clockOut: datetime().nullable(),
2049
2107
  cost: number$2().nullable(),
2108
+ tokens: number$2().nullable(),
2050
2109
  createdAt: datetime(),
2051
2110
  createdBy: string$1(),
2052
2111
  updatedAt: datetime(),
@@ -3976,7 +4035,19 @@ function editKey(fieldId, setIndex) {
3976
4035
  }
3977
4036
  /** Build edits map from field values */
3978
4037
  function buildEdits(fieldValues) {
3979
- return Object.fromEntries(fieldValues.map((fv) => [editKey(fv.fieldId, fv.setIndex), fv.value]));
4038
+ return toRecord(fieldValues, (fv) => editKey(fv.fieldId, fv.setIndex), (fv) => fv.value);
4039
+ }
4040
+ function fieldValueEquals(a, b) {
4041
+ return JSON.stringify(a) === JSON.stringify(b);
4042
+ }
4043
+ function mergeEditsPreservingDirty(previousFieldValues, nextFieldValues, currentEdits) {
4044
+ const previousEdits = buildEdits(previousFieldValues);
4045
+ const nextEdits = buildEdits(nextFieldValues);
4046
+ return toRecord(Object.entries(nextEdits), ([key]) => key, ([key, nextValue]) => {
4047
+ const currentValue = currentEdits[key];
4048
+ const previousValue = previousEdits[key];
4049
+ return currentValue !== void 0 && !fieldValueEquals(currentValue, previousValue) ? currentValue : nextValue;
4050
+ });
3980
4051
  }
3981
4052
  /** Get a string value from FieldValue (for scalar fields) */
3982
4053
  function asString(v) {
@@ -4010,9 +4081,10 @@ var FieldValueRunList = ({ fieldValues: fieldValuesProp, multiSet, completed, _a
4010
4081
  const prevPropRef = (0, import_react.useRef)(fieldValuesProp);
4011
4082
  (0, import_react.useEffect)(() => {
4012
4083
  if (fieldValuesProp !== prevPropRef.current) {
4084
+ const previousFieldValues = prevPropRef.current;
4013
4085
  prevPropRef.current = fieldValuesProp;
4014
4086
  setFieldValues(fieldValuesProp);
4015
- setEdits(buildEdits(fieldValuesProp));
4087
+ setEdits((currentEdits) => mergeEditsPreservingDirty(previousFieldValues, fieldValuesProp, currentEdits));
4016
4088
  }
4017
4089
  }, [fieldValuesProp]);
4018
4090
  const onFieldChange = (fieldId, setIndex, value) => {
@@ -6721,7 +6793,8 @@ var OperationSummaryTable = ({ items, loading, linkBuilder }) => {
6721
6793
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Title" }),
6722
6794
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Prerequisites" }),
6723
6795
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Steps" }),
6724
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Cost" })
6796
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Cost" }),
6797
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Tokens" })
6725
6798
  ] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Tbody, { children: items.map((op) => {
6726
6799
  const opLink = linkBuilder(op.seqNo);
6727
6800
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table.Tr, {
@@ -6781,6 +6854,14 @@ var OperationSummaryTable = ({ items, loading, linkBuilder }) => {
6781
6854
  style: cellLinkStyle,
6782
6855
  children: op.cost ? `$${op.cost.toFixed(2)}` : "—"
6783
6856
  })
6857
+ }),
6858
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
6859
+ style: { padding: 0 },
6860
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
6861
+ to: opLink,
6862
+ style: cellLinkStyle,
6863
+ children: op.tokens ? formatTokens(op.tokens) : "—"
6864
+ })
6784
6865
  })
6785
6866
  ]
6786
6867
  }, op.id);
@@ -8158,6 +8239,7 @@ var LaborTicketList = ({ orderKey, runNo, seqNo, refreshKey, showTitle = true, o
8158
8239
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Clock Out" }),
8159
8240
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Duration" }),
8160
8241
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Cost" }),
8242
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Tokens" }),
8161
8243
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, {})
8162
8244
  ] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Tbody, { children: data.items.map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table.Tr, { children: [
8163
8245
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: ticket.username }),
@@ -8175,6 +8257,7 @@ var LaborTicketList = ({ orderKey, runNo, seqNo, refreshKey, showTitle = true, o
8175
8257
  }) }),
8176
8258
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: formatDuration(ticket.clockIn, ticket.clockOut) }),
8177
8259
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: ticket.cost != null ? `$${ticket.cost.toFixed(2)}` : "—" }),
8260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: ticket.tokens != null ? formatTokens(ticket.tokens) : "—" }),
8178
8261
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: hasActionTemplate(data._actionTemplates, "deleteTicket") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionIcon, {
8179
8262
  size: "xs",
8180
8263
  variant: "subtle",
@@ -8810,7 +8893,8 @@ var OperationRunDetail = () => {
8810
8893
  " on",
8811
8894
  " ",
8812
8895
  new Date(opRun.updatedAt).toLocaleString(),
8813
- opRun.cost ? ` for $${opRun.cost.toFixed(2)}` : ""
8896
+ opRun.cost ? ` for $${opRun.cost.toFixed(2)}` : "",
8897
+ opRun.tokens ? ` (${formatTokens(opRun.tokens)})` : ""
8814
8898
  ]
8815
8899
  }), (() => {
8816
8900
  const reason = formatDisabledReason(reopenAction.disabledReason);