@hachej/boring-core 0.1.43 → 0.1.44
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/app/front/index.d.ts +8 -4
- package/dist/app/front/index.js +29 -14
- package/dist/app/server/index.js +20 -2
- package/package.json +4 -4
|
@@ -118,12 +118,16 @@ interface CreditLedgerEntry {
|
|
|
118
118
|
createdAt: string;
|
|
119
119
|
description: string;
|
|
120
120
|
}
|
|
121
|
-
/** Format SIGNED credit micros as a
|
|
122
|
-
|
|
121
|
+
/** Format SIGNED credit micros as a currency string with an explicit +/− sign.
|
|
122
|
+
* `currency` is the configured display currency (1 credit-unit = 1 major unit); defaults
|
|
123
|
+
* to EUR for callers without a configured purchase currency. */
|
|
124
|
+
declare function formatSignedCreditMicros(micros: number, currency?: string, locale?: string): string;
|
|
123
125
|
/** Format a minor-unit price (e.g. cents) in its currency for pack labels/buttons. */
|
|
124
126
|
declare function formatMinorPrice(priceMinor: number, currency: string, locale?: string): string;
|
|
125
|
-
/** Format credit micros as a
|
|
126
|
-
|
|
127
|
+
/** Format credit micros as a currency string. 1 credit-unit = 1 major unit of the
|
|
128
|
+
* configured display `currency` (µ/1e6). Defaults to EUR for callers without a
|
|
129
|
+
* configured purchase currency (e.g. a consumption-only deployment). */
|
|
130
|
+
declare function formatCreditMicros(micros: number, currency?: string, locale?: string): string;
|
|
127
131
|
/** True when the remaining balance is at or below the low-balance threshold. */
|
|
128
132
|
declare function isLowBalance(micros: number, thresholdMicros?: number): boolean;
|
|
129
133
|
/** Stable server error code for an out-of-credits rejection (mirrors the agent's
|
package/dist/app/front/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
CoreFront,
|
|
3
3
|
UserMenu,
|
|
4
4
|
WorkspaceSwitcher,
|
|
5
|
+
routes,
|
|
5
6
|
useCurrentWorkspace,
|
|
6
7
|
useSession,
|
|
7
8
|
useSignIn,
|
|
@@ -144,6 +145,7 @@ function AuthCard({
|
|
|
144
145
|
mode === "signup" ? /* @__PURE__ */ jsx2("input", { className: "w-full rounded-xl border border-border bg-background px-3 py-2.5 text-sm outline-none focus:border-ring", placeholder: "Name", value: name, onChange: (event) => setName(event.currentTarget.value) }) : null,
|
|
145
146
|
/* @__PURE__ */ jsx2("input", { className: "w-full rounded-xl border border-border bg-background px-3 py-2.5 text-sm outline-none focus:border-ring", type: "email", autoComplete: "email", placeholder: "Email", value: email, onChange: (event) => setEmail(event.currentTarget.value), required: true }),
|
|
146
147
|
/* @__PURE__ */ jsx2("input", { className: "w-full rounded-xl border border-border bg-background px-3 py-2.5 text-sm outline-none focus:border-ring", type: "password", autoComplete: mode === "signin" ? "current-password" : "new-password", placeholder: "Password", value: password, onChange: (event) => setPassword(event.currentTarget.value), required: true }),
|
|
148
|
+
mode === "signin" ? /* @__PURE__ */ jsx2("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx2("a", { href: routes.forgotPassword, className: "text-xs text-muted-foreground hover:underline", children: "Forgot password?" }) }) : null,
|
|
147
149
|
/* @__PURE__ */ jsx2("button", { type: "submit", className: "w-full rounded-xl bg-primary px-3 py-2.5 text-sm font-medium text-primary-foreground disabled:opacity-50", disabled: submitting, children: submitting ? "Please wait\u2026" : mode === "signin" ? "Continue with email" : "Create account" })
|
|
148
150
|
] })
|
|
149
151
|
] });
|
|
@@ -617,6 +619,7 @@ function WorkspaceRoute({
|
|
|
617
619
|
{
|
|
618
620
|
...workspaceProps,
|
|
619
621
|
workspaceId,
|
|
622
|
+
workspaceLabel: workspaceProps.workspaceLabel ?? currentWorkspace.name,
|
|
620
623
|
requestHeaders,
|
|
621
624
|
authHeaders,
|
|
622
625
|
chatParams,
|
|
@@ -735,19 +738,19 @@ function creditNetMicros(balance) {
|
|
|
735
738
|
const debt = Number.isFinite(balance.debtMicros) ? balance.debtMicros : 0;
|
|
736
739
|
return remaining - debt;
|
|
737
740
|
}
|
|
738
|
-
function formatSignedCreditMicros(micros, locale) {
|
|
739
|
-
const
|
|
740
|
-
const sign =
|
|
741
|
-
const abs = new Intl.NumberFormat(locale, { style: "currency", currency
|
|
741
|
+
function formatSignedCreditMicros(micros, currency = "EUR", locale) {
|
|
742
|
+
const major = (Number.isFinite(micros) ? micros : 0) / 1e6;
|
|
743
|
+
const sign = major > 0 ? "+" : major < 0 ? "\u2212" : "";
|
|
744
|
+
const abs = new Intl.NumberFormat(locale, { style: "currency", currency }).format(Math.abs(major));
|
|
742
745
|
return `${sign}${abs}`;
|
|
743
746
|
}
|
|
744
747
|
function formatMinorPrice(priceMinor, currency, locale) {
|
|
745
748
|
const major = (Number.isFinite(priceMinor) ? priceMinor : 0) / 100;
|
|
746
749
|
return new Intl.NumberFormat(locale, { style: "currency", currency, maximumFractionDigits: major % 1 === 0 ? 0 : 2 }).format(major);
|
|
747
750
|
}
|
|
748
|
-
function formatCreditMicros(micros, locale) {
|
|
749
|
-
const
|
|
750
|
-
return new Intl.NumberFormat(locale, { style: "currency", currency
|
|
751
|
+
function formatCreditMicros(micros, currency = "EUR", locale) {
|
|
752
|
+
const major = (Number.isFinite(micros) ? Math.max(0, micros) : 0) / 1e6;
|
|
753
|
+
return new Intl.NumberFormat(locale, { style: "currency", currency }).format(major);
|
|
751
754
|
}
|
|
752
755
|
function isLowBalance(micros, thresholdMicros = 5e5) {
|
|
753
756
|
return Number.isFinite(micros) && micros <= thresholdMicros;
|
|
@@ -924,6 +927,7 @@ function CreditBalanceBadge({
|
|
|
924
927
|
const low = inDebt || isLowBalance(balance.remainingMicros);
|
|
925
928
|
const showBuy = balance.checkoutEnabled ?? buyEnabled;
|
|
926
929
|
const packs = (balance.packs ?? []).filter((p) => !p.custom);
|
|
930
|
+
const currency = balance.packs?.[0]?.currency ?? "EUR";
|
|
927
931
|
const pick = async (packId) => {
|
|
928
932
|
setOpen(false);
|
|
929
933
|
await buy(packId);
|
|
@@ -934,7 +938,7 @@ function CreditBalanceBadge({
|
|
|
934
938
|
{
|
|
935
939
|
title: inDebt ? "Amount owed \u2014 top up to resume" : "Remaining credits",
|
|
936
940
|
className: `text-[11px] tabular-nums ${low ? "text-destructive" : "text-muted-foreground"}`,
|
|
937
|
-
children: inDebt ? `\u2212${formatCreditMicros(balance.debtMicros, locale)}` : formatCreditMicros(balance.remainingMicros, locale)
|
|
941
|
+
children: inDebt ? `\u2212${formatCreditMicros(balance.debtMicros, currency, locale)}` : formatCreditMicros(balance.remainingMicros, currency, locale)
|
|
938
942
|
}
|
|
939
943
|
),
|
|
940
944
|
showBuy ? /* @__PURE__ */ jsxs5(Popover, { open, onOpenChange: setOpen, children: [
|
|
@@ -961,7 +965,7 @@ function CreditBalanceBadge({
|
|
|
961
965
|
className: "flex items-center justify-between gap-3 rounded-md px-2 py-1.5 text-[13px] hover:bg-muted disabled:opacity-50",
|
|
962
966
|
children: [
|
|
963
967
|
/* @__PURE__ */ jsx6("span", { className: "tabular-nums font-medium", children: formatMinorPrice(p.priceMinor, p.currency, locale) }),
|
|
964
|
-
/* @__PURE__ */ jsx6("span", { className: "text-[11px] text-muted-foreground", children: formatCreditMicros(p.creditMicros, locale) })
|
|
968
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[11px] text-muted-foreground", children: formatCreditMicros(p.creditMicros, p.currency, locale) })
|
|
965
969
|
]
|
|
966
970
|
},
|
|
967
971
|
p.id
|
|
@@ -1046,6 +1050,7 @@ function CreditsSettingsPanel({ apiBaseUrl = "", locale }) {
|
|
|
1046
1050
|
const low = inDebt || isLowBalance(balance.remainingMicros);
|
|
1047
1051
|
const showBuy = balance.checkoutEnabled ?? false;
|
|
1048
1052
|
const packs = balance.packs ?? [];
|
|
1053
|
+
const currency = packs[0]?.currency ?? "EUR";
|
|
1049
1054
|
const activePack = selectedPack ?? packs.find((p) => p.isDefault)?.id ?? packs[0]?.id ?? null;
|
|
1050
1055
|
const activePackObj = packs.find((p) => p.id === activePack) ?? null;
|
|
1051
1056
|
const doBuy = async (pack) => {
|
|
@@ -1067,10 +1072,10 @@ function CreditsSettingsPanel({ apiBaseUrl = "", locale }) {
|
|
|
1067
1072
|
!inDebt && low && /* @__PURE__ */ jsx7(Notice, { role: "status", tone: "warning", description: "You're low on credits. Top up to avoid interruptions." }),
|
|
1068
1073
|
/* @__PURE__ */ jsxs6(DetailList, { children: [
|
|
1069
1074
|
/* @__PURE__ */ jsx7(DetailLine, { label: "Remaining balance", children: /* @__PURE__ */ jsxs6("p", { style: { fontVariantNumeric: "tabular-nums", fontWeight: 600 }, children: [
|
|
1070
|
-
inDebt ? `\u2212${formatCreditMicros(balance.debtMicros, locale)}` : formatCreditMicros(balance.remainingMicros, locale),
|
|
1075
|
+
inDebt ? `\u2212${formatCreditMicros(balance.debtMicros, currency, locale)}` : formatCreditMicros(balance.remainingMicros, currency, locale),
|
|
1071
1076
|
updating && /* @__PURE__ */ jsx7("span", { className: "ml-2 text-[11px] font-normal text-muted-foreground", "aria-live": "polite", children: "Updating\u2026" })
|
|
1072
1077
|
] }) }),
|
|
1073
|
-
/* @__PURE__ */ jsx7(DetailLine, { label: "Used so far", children: /* @__PURE__ */ jsx7("p", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCreditMicros(balance.usedMicros, locale) }) })
|
|
1078
|
+
/* @__PURE__ */ jsx7(DetailLine, { label: "Used so far", children: /* @__PURE__ */ jsx7("p", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCreditMicros(balance.usedMicros, currency, locale) }) })
|
|
1074
1079
|
] }),
|
|
1075
1080
|
showBuy && packs.length > 0 && /* @__PURE__ */ jsxs6("fieldset", { className: "space-y-2", children: [
|
|
1076
1081
|
/* @__PURE__ */ jsx7("legend", { className: "text-[12px] font-medium text-foreground", children: "Buy credits" }),
|
|
@@ -1101,7 +1106,7 @@ function CreditsSettingsPanel({ apiBaseUrl = "", locale }) {
|
|
|
1101
1106
|
/* @__PURE__ */ jsx7("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatMinorPrice(p.priceMinor, p.currency, locale) }),
|
|
1102
1107
|
/* @__PURE__ */ jsxs6("span", { className: "text-muted-foreground", children: [
|
|
1103
1108
|
"\xB7 ",
|
|
1104
|
-
formatCreditMicros(p.creditMicros, locale)
|
|
1109
|
+
formatCreditMicros(p.creditMicros, p.currency, locale)
|
|
1105
1110
|
] })
|
|
1106
1111
|
] })
|
|
1107
1112
|
]
|
|
@@ -1139,7 +1144,7 @@ function CreditsSettingsPanel({ apiBaseUrl = "", locale }) {
|
|
|
1139
1144
|
{
|
|
1140
1145
|
style: { fontVariantNumeric: "tabular-nums" },
|
|
1141
1146
|
className: e.amountMicros >= 0 ? "text-foreground" : "text-muted-foreground",
|
|
1142
|
-
children: formatSignedCreditMicros(e.amountMicros, locale)
|
|
1147
|
+
children: formatSignedCreditMicros(e.amountMicros, currency, locale)
|
|
1143
1148
|
}
|
|
1144
1149
|
)
|
|
1145
1150
|
] }, e.id)) })
|
|
@@ -1315,7 +1320,17 @@ function BuyCreditsNoticeAction({ apiBaseUrl = "", label = "Buy credits" }) {
|
|
|
1315
1320
|
if (message) setError(message);
|
|
1316
1321
|
};
|
|
1317
1322
|
return /* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [
|
|
1318
|
-
/* @__PURE__ */ jsx9(
|
|
1323
|
+
/* @__PURE__ */ jsx9(
|
|
1324
|
+
Button3,
|
|
1325
|
+
{
|
|
1326
|
+
type: "button",
|
|
1327
|
+
size: "sm",
|
|
1328
|
+
onClick: () => void onBuy(),
|
|
1329
|
+
disabled: buying,
|
|
1330
|
+
className: "bg-foreground text-background hover:bg-foreground/90",
|
|
1331
|
+
children: buying ? "Opening\u2026" : label
|
|
1332
|
+
}
|
|
1333
|
+
),
|
|
1319
1334
|
error ? /* @__PURE__ */ jsx9("span", { role: "alert", className: "text-xs text-destructive", children: error }) : null
|
|
1320
1335
|
] });
|
|
1321
1336
|
}
|
package/dist/app/server/index.js
CHANGED
|
@@ -621,6 +621,25 @@ async function createCoreWorkspaceAgentServer(options = {}) {
|
|
|
621
621
|
const callerOptions = options.getPi ? await options.getPi(ctx) : void 0;
|
|
622
622
|
return mergePiOptions(pluginOptions, callerOptions);
|
|
623
623
|
};
|
|
624
|
+
app.get("/api/v1/workspace/meta", async (request, reply) => {
|
|
625
|
+
try {
|
|
626
|
+
const workspaceId = await resolveWorkspaceId(request);
|
|
627
|
+
const [workspace, workspaceRootForRequest] = await Promise.all([
|
|
628
|
+
workspaceStore.get(workspaceId),
|
|
629
|
+
resolveRoot(workspaceId, request)
|
|
630
|
+
]);
|
|
631
|
+
return {
|
|
632
|
+
workspaceId,
|
|
633
|
+
workspaceRoot: workspaceRootForRequest,
|
|
634
|
+
projectName: workspace?.name ?? "Workspace"
|
|
635
|
+
};
|
|
636
|
+
} catch (error) {
|
|
637
|
+
const statusCode = typeof error?.statusCode === "number" ? error.statusCode : 500;
|
|
638
|
+
const message = error instanceof Error ? error.message : "workspace meta failed";
|
|
639
|
+
return reply.code(statusCode).send({ error: message });
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
const resolveSessionNamespace = async (ctx) => options.getSessionNamespace ? await options.getSessionNamespace(ctx) : options.sessionNamespace ?? ctx.workspaceId;
|
|
624
643
|
await app.register(registerAgentRoutes, {
|
|
625
644
|
workspaceRoot,
|
|
626
645
|
sessionId: options.sessionId,
|
|
@@ -637,8 +656,7 @@ async function createCoreWorkspaceAgentServer(options = {}) {
|
|
|
637
656
|
systemPromptAppend: pluginCollection.agentOptions.systemPromptAppend,
|
|
638
657
|
pi: pluginCollection.agentOptions.pi,
|
|
639
658
|
getPi: resolvePiOptions,
|
|
640
|
-
|
|
641
|
-
getSessionNamespace: options.getSessionNamespace,
|
|
659
|
+
getSessionNamespace: resolveSessionNamespace,
|
|
642
660
|
getExtraTools: async (ctx) => {
|
|
643
661
|
const callerTools = options.getExtraTools ? await options.getExtraTools(ctx) : [];
|
|
644
662
|
return [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hachej/boring-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.44",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Foundation package for boring-ui-v2 apps: DB, auth, config, HTTP app factory, and frontend app shell.",
|
|
@@ -79,9 +79,9 @@
|
|
|
79
79
|
"react-router-dom": "^7.14.2",
|
|
80
80
|
"smol-toml": "^1.6.1",
|
|
81
81
|
"zod": "^3.25.76",
|
|
82
|
-
"@hachej/boring-
|
|
83
|
-
"@hachej/boring-workspace": "0.1.
|
|
84
|
-
"@hachej/boring-
|
|
82
|
+
"@hachej/boring-ui-kit": "0.1.44",
|
|
83
|
+
"@hachej/boring-workspace": "0.1.44",
|
|
84
|
+
"@hachej/boring-agent": "0.1.44"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@testing-library/jest-dom": "^6.9.1",
|