@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.
- package/client-dist/assets/{index-Bu_bS_Vd.js → index-CO2ivEdE.js} +90 -6
- package/client-dist/assets/{vendor-Co7ZCNxO.js → vendor-CJ0ET9hP.js} +8488 -1
- package/client-dist/index.html +2 -2
- package/dist/database/dbConfig.js +1 -1
- package/dist/erpServer.js +2 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.js +2 -0
- package/dist/routes/operations/operation-run-transitions.js +15 -6
- package/dist/routes/operations/operation-runs.js +3 -0
- package/dist/routes/production/labor-tickets.js +1 -0
- package/dist/services/operations/operation-run-service.js +2 -1
- package/dist/services/orders/order-revision-service.js +2 -3
- package/dist/services/orders/order-run-service.js +4 -5
- package/dist/services/orders/revision-diff-service.js +10 -9
- package/dist/services/production/labor-ticket-backfill.js +67 -0
- package/dist/services/production/labor-ticket-service.js +20 -14
- package/npm-shrinkwrap.json +50 -28
- package/package.json +6 -6
- package/prisma/migrations/20260517000000_add_op_run_tokens/migration.sql +2 -0
- package/prisma/schema.prisma +2 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __toESM } from "./rolldown-runtime-CvHMtSRF.js";
|
|
2
|
-
import { $ as
|
|
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
|
|
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(
|
|
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);
|