@harperfast/harper-pro 5.1.0-beta.3 → 5.1.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/core/DESIGN.md +24 -0
- package/core/bin/copyDb.ts +16 -3
- package/core/package-lock.json +44 -54
- package/core/resources/Table.ts +41 -4
- package/core/resources/databases.ts +134 -42
- package/core/resources/graphql.ts +3 -0
- package/core/resources/replayLogs.ts +114 -42
- package/core/resources/replayLogsGuards.ts +58 -9
- package/core/server/nodeName.ts +9 -3
- package/core/server/operationsServer.ts +17 -0
- package/core/utility/install/installer.ts +12 -5
- package/dist/core/bin/copyDb.js +16 -3
- package/dist/core/bin/copyDb.js.map +1 -1
- package/dist/core/resources/Table.js +43 -4
- package/dist/core/resources/Table.js.map +1 -1
- package/dist/core/resources/databases.js +135 -41
- package/dist/core/resources/databases.js.map +1 -1
- package/dist/core/resources/graphql.js +3 -0
- package/dist/core/resources/graphql.js.map +1 -1
- package/dist/core/resources/replayLogs.js +100 -40
- package/dist/core/resources/replayLogs.js.map +1 -1
- package/dist/core/resources/replayLogsGuards.js +50 -10
- package/dist/core/resources/replayLogsGuards.js.map +1 -1
- package/dist/core/server/nodeName.js +9 -3
- package/dist/core/server/nodeName.js.map +1 -1
- package/dist/core/server/operationsServer.js +20 -0
- package/dist/core/server/operationsServer.js.map +1 -1
- package/dist/core/utility/install/installer.js +12 -6
- package/dist/core/utility/install/installer.js.map +1 -1
- package/dist/replication/knownNodes.js +106 -17
- package/dist/replication/knownNodes.js.map +1 -1
- package/dist/replication/replicator.js +6 -3
- package/dist/replication/replicator.js.map +1 -1
- package/npm-shrinkwrap.json +43 -52
- package/package.json +3 -3
- package/replication/knownNodes.ts +104 -14
- package/replication/replicator.ts +7 -3
- package/studio/web/assets/{Chat-BdFickL8.js → Chat-DMBW4pI2.js} +2 -2
- package/studio/web/assets/{Chat-BdFickL8.js.map → Chat-DMBW4pI2.js.map} +1 -1
- package/studio/web/assets/{FloatingChat-CaAoco8I.js → FloatingChat-DTmhPsrm.js} +4 -4
- package/studio/web/assets/{FloatingChat-CaAoco8I.js.map → FloatingChat-DTmhPsrm.js.map} +1 -1
- package/studio/web/assets/{applications-C3y3xwyG.js → applications-CigxJarn.js} +2 -2
- package/studio/web/assets/{applications-C3y3xwyG.js.map → applications-CigxJarn.js.map} +1 -1
- package/studio/web/assets/{index-Cd3Zh3nK.js → index-oRZw5GW3.js} +6 -6
- package/studio/web/assets/index-oRZw5GW3.js.map +1 -0
- package/studio/web/assets/{index.lazy-0hLbh5Fo.js → index.lazy-DY3VcR86.js} +4 -4
- package/studio/web/assets/{index.lazy-0hLbh5Fo.js.map → index.lazy-DY3VcR86.js.map} +1 -1
- package/studio/web/assets/{profile-CwBWGuVt.js → profile-DiV60L50.js} +2 -2
- package/studio/web/assets/{profile-CwBWGuVt.js.map → profile-DiV60L50.js.map} +1 -1
- package/studio/web/assets/{setComponentFile-Dhrmd8eR.js → setComponentFile-Bz6WI4jy.js} +2 -2
- package/studio/web/assets/{setComponentFile-Dhrmd8eR.js.map → setComponentFile-Bz6WI4jy.js.map} +1 -1
- package/studio/web/assets/{status-Bykq6QcD.js → status-fW6PBpPM.js} +2 -2
- package/studio/web/assets/{status-Bykq6QcD.js.map → status-fW6PBpPM.js.map} +1 -1
- package/studio/web/assets/{swagger-ui-react-CF94s29D.js → swagger-ui-react-DRYf7G3J.js} +2 -2
- package/studio/web/assets/{swagger-ui-react-CF94s29D.js.map → swagger-ui-react-DRYf7G3J.js.map} +1 -1
- package/studio/web/assets/{useEntityRestURL-D7vuaG2W.js → useEntityRestURL-14jWKu9J.js} +2 -2
- package/studio/web/assets/{useEntityRestURL-D7vuaG2W.js.map → useEntityRestURL-14jWKu9J.js.map} +1 -1
- package/studio/web/index.html +1 -1
- package/studio/web/assets/index-Cd3Zh3nK.js.map +0 -1
|
@@ -129,22 +129,12 @@ export async function runNodeUpdateWatcher(listener: (node: any, id: string) =>
|
|
|
129
129
|
}
|
|
130
130
|
/**
|
|
131
131
|
* Raw existence check for an hdb_nodes record that does NOT decode the stored value.
|
|
132
|
-
* A decode failure (e.g. stale msgpackr shared-structures, harper#1163) must not
|
|
133
|
-
* misread as the record being absent: `primaryStore.get()` would throw/return undefined
|
|
134
|
-
*
|
|
132
|
+
* A decode failure (e.g. stale msgpackr shared-structures, harper#1163 / harper-pro#352) must not
|
|
133
|
+
* be misread as the record being absent: `primaryStore.get()` would throw/return undefined for an
|
|
134
|
+
* undecodable-but-present row, so we probe via the scan path (`getKeys`) instead.
|
|
135
135
|
*/
|
|
136
136
|
export function nodeRecordPhysicallyExists(name: string): boolean {
|
|
137
|
-
|
|
138
|
-
if (typeof store.doesExist === 'function') return store.doesExist(name);
|
|
139
|
-
// getBinaryFast returns the raw value bytes (or undefined when the key is absent).
|
|
140
|
-
if (typeof store.getBinaryFast === 'function') return store.getBinaryFast(name) != null;
|
|
141
|
-
// Last-resort fallback: a present-but-undecodable record will still throw here, so be
|
|
142
|
-
// conservative and treat a throw as "present" (don't let it look like a deletion).
|
|
143
|
-
try {
|
|
144
|
-
return store.get(name) != null;
|
|
145
|
-
} catch {
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
137
|
+
return storeRecordRangeVisible(getHDBNodeTable().primaryStore, name);
|
|
148
138
|
}
|
|
149
139
|
|
|
150
140
|
/**
|
|
@@ -179,6 +169,106 @@ export function isValidNodeRecord(record: unknown): boolean {
|
|
|
179
169
|
);
|
|
180
170
|
}
|
|
181
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Resolve an hdb_nodes record for the replication auth path (cert common-name / IP lookup).
|
|
174
|
+
*
|
|
175
|
+
* Root cause of harper-pro#352 (field variant #345): during a rolling in-place v4→v5 upgrade, a
|
|
176
|
+
* freshly-flipped node's replication auth path reads a peer's `hdb_nodes` row via the POINT lookup
|
|
177
|
+
* (`primaryStore.get()`) very early at boot. A v5-era msgpackr *shared-structure* row can
|
|
178
|
+
* transiently misread through that point-lookup path — yielding `[]` / a non-record (it does not
|
|
179
|
+
* necessarily throw) — even though the row is present on disk and the table's shared structures are
|
|
180
|
+
* present too. (Diagnosis: on the wedged node the local log replay had already completed and the
|
|
181
|
+
* read-path structures key `[Symbol.for('structures'), 'hdb_nodes']` was present and valid; the
|
|
182
|
+
* point decode simply loses a race with the `hdb_nodes` base-copy resync that re-encodes the row
|
|
183
|
+
* against local structures and heals it within seconds. The SCAN path lists the key reliably the
|
|
184
|
+
* whole time.) `isValidNodeRecord` then (correctly) refuses the misread — but on a replication
|
|
185
|
+
* socket the "require credentials" fallback can never succeed, so the peer is rejected with cycling
|
|
186
|
+
* 1008 Unauthorized and its post-flip writes strand at origin.
|
|
187
|
+
*
|
|
188
|
+
* The information the auth decision actually needs is the peer's `name`, which is the table's
|
|
189
|
+
* primary key — and the SCAN path (`getKeys`/`getRange`) lists that key reliably even while the
|
|
190
|
+
* point decode transiently fails. So when the point lookup yields no valid record but the key is
|
|
191
|
+
* range-visible (a known peer), reconstruct a minimal node descriptor from the key. This is safe:
|
|
192
|
+
* the connection's certificate is independently validated by TLS and `verifyCertificate` in
|
|
193
|
+
* replicator.ts before this record is consulted, and the hostname must already be a range-visible
|
|
194
|
+
* known node to be reconstructed at all — we are not inventing a peer, we are recovering the
|
|
195
|
+
* identity of one whose descriptor transiently failed to decode; the full record self-heals on the
|
|
196
|
+
* next decodable update.
|
|
197
|
+
*
|
|
198
|
+
* Note: keying the reconstruction off range-visibility (not the point-lookup `doesExist`/`get`) is
|
|
199
|
+
* deliberate — the point lookup is exactly the path that misreads, so depending on it would leave
|
|
200
|
+
* the wedge open in the observed failure shape.
|
|
201
|
+
*
|
|
202
|
+
* (Separate, latent: `replayLogs` persists replication-applied structure updates under the plain
|
|
203
|
+
* key `Symbol.for('structures')`, which the RocksDB decode path — composite `[Symbol.for('structures'),
|
|
204
|
+
* name]` — never reads. Not the proximate trigger here, tracked separately.)
|
|
205
|
+
*
|
|
206
|
+
* Returns a valid node record, or `undefined` when the hostname is genuinely unknown (not range-
|
|
207
|
+
* visible and no route). `isValidNodeRecord` is retained as defense-in-depth at the call sites.
|
|
208
|
+
*/
|
|
209
|
+
export function readNodeForAuth(name: string, routeRecord?: any): any {
|
|
210
|
+
return resolveNodeForAuth(getHDBNodeTable().primaryStore, name, routeRecord);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Pure resolution logic for {@link readNodeForAuth}, taking the store explicitly so it can be
|
|
215
|
+
* unit-tested against a real (or fake) store without standing up a server. See readNodeForAuth
|
|
216
|
+
* for the full root-cause rationale (harper-pro#352).
|
|
217
|
+
*/
|
|
218
|
+
export function resolveNodeForAuth(store: any, name: string, routeRecord?: any): any {
|
|
219
|
+
let record: any;
|
|
220
|
+
try {
|
|
221
|
+
record = store.get(name);
|
|
222
|
+
} catch {
|
|
223
|
+
// A present-but-undecodable row throws here (missing shared structure); fall through to
|
|
224
|
+
// the physical-existence check below rather than treating the peer as unknown.
|
|
225
|
+
record = undefined;
|
|
226
|
+
}
|
|
227
|
+
if (isValidNodeRecord(record)) return record;
|
|
228
|
+
// A static-route record (from replication.routes config) is already a valid descriptor and
|
|
229
|
+
// carries fields the reconstructed minimal record cannot (e.g. revoked_certificates) — prefer it.
|
|
230
|
+
if (isValidNodeRecord(routeRecord)) return routeRecord;
|
|
231
|
+
// The point lookup yielded no valid record. If the key is RANGE-VISIBLE (the scan path reliably
|
|
232
|
+
// lists v5-era rows even while the point decode transiently misreads — harper-pro#352), this is
|
|
233
|
+
// a known peer: reconstruct its identity from the key so a cryptographically-validated peer is
|
|
234
|
+
// not stranded by a transiently-undecodable descriptor.
|
|
235
|
+
if (storeRecordRangeVisible(store, name)) {
|
|
236
|
+
logger.warn?.(
|
|
237
|
+
'hdb_nodes record for',
|
|
238
|
+
name,
|
|
239
|
+
'did not decode to a valid node descriptor on the point lookup but is range-visible (likely a v5-era shared-structure row transiently misreading at boot during an in-place upgrade; see harper-pro#352). Authorizing the peer by its certificate-validated name; the full record self-heals on the next decodable update.'
|
|
240
|
+
);
|
|
241
|
+
return { name };
|
|
242
|
+
}
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Existence probe for an hdb_nodes key that prefers the RANGE/scan path. A v5-era shared-structure
|
|
248
|
+
* row can transiently misread to `[]`/null through the point lookup (`doesExist`/`get`) at early
|
|
249
|
+
* boot (harper-pro#352), but `getKeys` lists the key reliably because it never decodes the value.
|
|
250
|
+
* Falls back to point checks only if `getKeys` is unavailable.
|
|
251
|
+
*/
|
|
252
|
+
function storeRecordRangeVisible(store: any, name: string): boolean {
|
|
253
|
+
if (typeof store.getKeys === 'function') {
|
|
254
|
+
try {
|
|
255
|
+
for (const key of store.getKeys({ start: name, limit: 1 })) {
|
|
256
|
+
return key === name;
|
|
257
|
+
}
|
|
258
|
+
return false;
|
|
259
|
+
} catch {
|
|
260
|
+
// fall through to point checks
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (typeof store.doesExist === 'function' && store.doesExist(name)) return true;
|
|
264
|
+
if (typeof store.getBinaryFast === 'function' && store.getBinaryFast(name) != null) return true;
|
|
265
|
+
try {
|
|
266
|
+
return store.get(name) != null;
|
|
267
|
+
} catch {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
182
272
|
async function processNodeUpdateEvent(event: any, listener: (node: any, id: string) => void) {
|
|
183
273
|
// remove any nodes that have been updated or deleted
|
|
184
274
|
const node_name = event?.value?.name || event?.id;
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
getReplicationSharedStatus,
|
|
40
40
|
getNodeURL,
|
|
41
41
|
isValidNodeRecord,
|
|
42
|
+
readNodeForAuth,
|
|
42
43
|
} from './knownNodes.ts';
|
|
43
44
|
import { CONFIG_PARAMS } from '../core/utility/hdbTerms.ts';
|
|
44
45
|
import { exportIdMapping, getIdOfRemoteNode } from '../core/resources/nodeIdMapping.ts';
|
|
@@ -178,7 +179,10 @@ export function start(options) {
|
|
|
178
179
|
let node: any;
|
|
179
180
|
for (const hostname of hostnames) {
|
|
180
181
|
if (!hostname) continue;
|
|
181
|
-
|
|
182
|
+
// readNodeForAuth decodes the hdb_nodes row (falling back to the static route record,
|
|
183
|
+
// then to a key-reconstructed identity for a present-but-undecodable row — the
|
|
184
|
+
// harper-pro#352 in-place-upgrade case). isValidNodeRecord stays as defense-in-depth.
|
|
185
|
+
const candidate = readNodeForAuth(hostname, routeByHostname.get(hostname));
|
|
182
186
|
if (isValidNodeRecord(candidate)) {
|
|
183
187
|
node = candidate;
|
|
184
188
|
break;
|
|
@@ -226,8 +230,8 @@ export function start(options) {
|
|
|
226
230
|
);
|
|
227
231
|
}
|
|
228
232
|
} else if (request.ip) {
|
|
229
|
-
// try by IP address
|
|
230
|
-
const candidate =
|
|
233
|
+
// try by IP address (readNodeForAuth: same decode-then-reconstruct path as the cert lookup)
|
|
234
|
+
const candidate = readNodeForAuth(request.ip, routeByHostname.get(request.ip));
|
|
231
235
|
if (isValidNodeRecord(candidate)) {
|
|
232
236
|
request.user = candidate;
|
|
233
237
|
} else if (!authorizationError) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as e,t}from"./rolldown-runtime-Cyuzqnbw.js";import{h as n,t as r}from"./button-kCMf1ZBL.js";import{C as i,S as a,T as o,_ as s,a as c,b as l,c as u,d,h as f,i as p,l as m,m as h,r as g,s as _,t as v,u as ee,v as y,w as b,x,y as S}from"./vendor-core-BIhSIGPv.js";import{A as te,C as ne,M as re,P as ie}from"./vendor-tanstack-DmFvmRiZ.js";import{a as ae}from"./vendor-datadog-Bq_0f1ke.js";import{r as oe}from"./vendor-react-BqTNj-ZI.js";import{Tt as C}from"./vendor-ui-to0aD0Fq.js";import{t as w}from"./createLucideIcon-D6HmSa4x.js";import{l as se,t as ce}from"./proxy-BJ77EweZ.js";import{_ as le,b as ue,c as de,h as fe,i as pe,m as me,p as he,r as ge,t as _e,v as ve,y as ye}from"./setComponentFile-
|
|
1
|
+
import{a as e,t}from"./rolldown-runtime-Cyuzqnbw.js";import{h as n,t as r}from"./button-kCMf1ZBL.js";import{C as i,S as a,T as o,_ as s,a as c,b as l,c as u,d,h as f,i as p,l as m,m as h,r as g,s as _,t as v,u as ee,v as y,w as b,x,y as S}from"./vendor-core-BIhSIGPv.js";import{A as te,C as ne,M as re,P as ie}from"./vendor-tanstack-DmFvmRiZ.js";import{a as ae}from"./vendor-datadog-Bq_0f1ke.js";import{r as oe}from"./vendor-react-BqTNj-ZI.js";import{Tt as C}from"./vendor-ui-to0aD0Fq.js";import{t as w}from"./createLucideIcon-D6HmSa4x.js";import{l as se,t as ce}from"./proxy-BJ77EweZ.js";import{_ as le,b as ue,c as de,h as fe,i as pe,m as me,p as he,r as ge,t as _e,v as ve,y as ye}from"./setComponentFile-Bz6WI4jy.js";import{$t as be,A as xe,E as Se,Gt as Ce,It as we,Jt as Te,Kt as Ee,N as De,O as Oe,Pt as ke,Qt as Ae,Rt as je,Ut as Me,V as Ne,Vt as Pe,Wt as Fe,X as Ie,Yt as Le,_ as Re,a as ze,b as Be,cn as Ve,i as He,in as Ue,j as We,k as Ge,ln as Ke,nn as qe,o as Je,p as Ye,r as Xe,rn as Ze,t as Qe,un as $e}from"./index-oRZw5GW3.js";import{t as et}from"./useEntityRestURL-14jWKu9J.js";import{n as tt}from"./getAnalytics-HqW0hniG.js";var nt=w(`between-horizontal-start`,[[`rect`,{width:`13`,height:`7`,x:`8`,y:`3`,rx:`1`,key:`pkso9a`}],[`path`,{d:`m2 9 3 3-3 3`,key:`1agib5`}],[`rect`,{width:`13`,height:`7`,x:`8`,y:`14`,rx:`1`,key:`1q5fc1`}]]),rt=w(`book`,[[`path`,{d:`M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20`,key:`k3hazp`}]]),it=w(`chart-area`,[[`path`,{d:`M3 3v16a2 2 0 0 0 2 2h16`,key:`c24i48`}],[`path`,{d:`M7 11.207a.5.5 0 0 1 .146-.353l2-2a.5.5 0 0 1 .708 0l3.292 3.292a.5.5 0 0 0 .708 0l4.292-4.292a.5.5 0 0 1 .854.353V16a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1z`,key:`q0gr47`}]]),at=w(`circle-x`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m15 9-6 6`,key:`1uzhvr`}],[`path`,{d:`m9 9 6 6`,key:`z0biqf`}]]),ot=w(`file-pen`,[[`path`,{d:`M12.659 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v9.34`,key:`o6klzx`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M10.378 12.622a1 1 0 0 1 3 3.003L8.36 20.637a2 2 0 0 1-.854.506l-2.867.837a.5.5 0 0 1-.62-.62l.836-2.869a2 2 0 0 1 .506-.853z`,key:`zhnas1`}]]),st=w(`logs`,[[`path`,{d:`M3 5h1`,key:`1mv5vm`}],[`path`,{d:`M3 12h1`,key:`lp3yf2`}],[`path`,{d:`M3 19h1`,key:`w6f3n9`}],[`path`,{d:`M8 5h1`,key:`1nxr5w`}],[`path`,{d:`M8 12h1`,key:`1con00`}],[`path`,{d:`M8 19h1`,key:`k7p10e`}],[`path`,{d:`M13 5h8`,key:`a7qcls`}],[`path`,{d:`M13 12h8`,key:`h98zly`}],[`path`,{d:`M13 19h8`,key:`c3s6r1`}]]),ct=w(`message-square-heart`,[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`,key:`18887p`}],[`path`,{d:`M7.5 9.5c0 .687.265 1.383.697 1.844l3.009 3.264a1.14 1.14 0 0 0 .407.314 1 1 0 0 0 .783-.004 1.14 1.14 0 0 0 .398-.31l3.008-3.264A2.77 2.77 0 0 0 16.5 9.5 2.5 2.5 0 0 0 12 8a2.5 2.5 0 0 0-4.5 1.5`,key:`1faxuh`}]]),lt=w(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]);async function ut(){await n.delete(`/Chat/Messages/`)}var T=e(ae(),1),E=oe();function dt({setMessages:e}){let[t,n]=(0,T.useState)(!1);return(0,E.jsxs)(`button`,{type:`button`,className:`clear-chat-button gap-1`,onClick:(0,T.useCallback)(async()=>{if(!t){n(!0);try{await ut(),e([])}catch(e){console.error(`Failed to clear chat:`,e)}finally{n(!1)}}},[t,e]),disabled:t,title:`Clear chat`,children:[t?(0,E.jsx)(Ae,{className:`animate-spin`,size:18}):(0,E.jsx)(Ee,{size:18}),`Clear`]})}async function ft(){let{data:e}=await n.get(`/Chat/Messages/`);return e}var pt=`vercel.ai.error`,mt=Symbol.for(pt),ht,gt,D=class e extends (gt=Error,ht=mt,gt){constructor({name:e,message:t,cause:n}){super(t),this[ht]=!0,this.name=e,this.cause=n}static isInstance(t){return e.hasMarker(t,pt)}static hasMarker(e,t){let n=Symbol.for(t);return typeof e==`object`&&!!e&&n in e&&typeof e[n]==`boolean`&&e[n]===!0}};function _t(e){return e==null?`unknown error`:typeof e==`string`?e:e instanceof Error?e.message:JSON.stringify(e)}var vt=`AI_InvalidArgumentError`,yt=`vercel.ai.error.${vt}`,bt=Symbol.for(yt),xt,St,Ct=class extends (St=D,xt=bt,St){constructor({message:e,cause:t,argument:n}){super({name:vt,message:e,cause:t}),this[xt]=!0,this.argument=n}static isInstance(e){return D.hasMarker(e,yt)}},wt=`AI_JSONParseError`,Tt=`vercel.ai.error.${wt}`,Et=Symbol.for(Tt),Dt,Ot,kt=class extends (Ot=D,Dt=Et,Ot){constructor({text:e,cause:t}){super({name:wt,message:`JSON parsing failed: Text: ${e}.
|
|
2
2
|
Error message: ${_t(t)}`,cause:t}),this[Dt]=!0,this.text=e}static isInstance(e){return D.hasMarker(e,Tt)}},At=`AI_TypeValidationError`,jt=`vercel.ai.error.${At}`,Mt=Symbol.for(jt),Nt,Pt,O=class e extends (Pt=D,Nt=Mt,Pt){constructor({value:e,cause:t,context:n}){let r=`Type validation failed`;if(n?.field&&(r+=` for ${n.field}`),n?.entityName||n?.entityId){r+=` (`;let e=[];n.entityName&&e.push(n.entityName),n.entityId&&e.push(`id: "${n.entityId}"`),r+=e.join(`, `),r+=`)`}super({name:At,message:`${r}: Value: ${JSON.stringify(e)}.
|
|
3
3
|
Error message: ${_t(t)}`,cause:t}),this[Nt]=!0,this.value=e,this.context=n}static isInstance(e){return D.hasMarker(e,jt)}static wrap({value:t,cause:n,context:r}){return e.isInstance(n)&&n.value===t&&n.context?.field===r?.field&&n.context?.entityName===r?.entityName&&n.context?.entityId===r?.entityId?n:new e({value:t,cause:n,context:r})}},Ft=class extends Error{constructor(e,t){super(e),this.name=`ParseError`,this.type=t.type,this.field=t.field,this.value=t.value,this.line=t.line}},It=10,Lt=13,k=32;function Rt(e){}function zt(e){if(typeof e==`function`)throw TypeError("`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?");let{onEvent:t=Rt,onError:n=Rt,onRetry:r=Rt,onComment:i,maxBufferSize:a}=e,o=[],s=0,c=!0,l,u=``,d=0,f,p=!1;function m(e){if(p)throw Error("Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.");if(c&&(c=!1,e.charCodeAt(0)===239&&e.charCodeAt(1)===187&&e.charCodeAt(2)===191&&(e=e.slice(3))),o.length===0){let t=g(e);t!==``&&(o.push(t),s=t.length),h();return}if(e.indexOf(`
|
|
4
4
|
`)===-1&&e.indexOf(`\r`)===-1){o.push(e),s+=e.length,h();return}o.push(e);let t=o.join(``);o.length=0,s=0;let n=g(t);n!==``&&(o.push(n),s=n.length),h()}function h(){a!==void 0&&(s+u.length<=a||(p=!0,o.length=0,s=0,l=void 0,u=``,d=0,f=void 0,n(new Ft(`Buffered data exceeded max buffer size of ${a} characters`,{type:`max-buffer-size-exceeded`}))))}function g(e){let n=0;if(e.indexOf(`\r`)===-1){let r=e.indexOf(`
|
|
@@ -1698,4 +1698,4 @@ let results = Document.search({
|
|
|
1698
1698
|
`},Xi={name:`readHarperSkill`,description:`Returns documentation for a Harper skill or best practice. Skills provide guidance on developing Harper applications.`,inputSchema:y({skill:g(Ji)})};async function Zi({input:{skill:e}}){return{success:!!Yi[e],message:Yi[e]||`No skill found with the name ${e}`}}var Qi={...Xi,icon:rt,execute:Zi},$i={name:`readLogs`,description:`Returns the matching logs from the server.`,inputSchema:y({log_name:g([`hdb.log`,`system.log`]).default(`hdb.log`),limit:x().or(c()).optional(),level:g([`notify`,`error`,`warn`,`info`,`debug`,`trace`,`undefined`]).or(c()).optional(),from:x().or(c()).optional(),until:x().or(c()).optional()})};async function ea({input:e,instanceClientParams:t}){try{return{success:!0,data:await Qe({...t,logFilters:e,replicated:t.entityType===`cluster`})}}catch(e){return{success:!1,message:`Error: ${e}`}}}var ta={...$i,icon:st,execute:ea},na={name:`readTableRecords`,description:`Retrieves some or all table records from a database on the server.`,inputSchema:y({database:x().trim(),table:x().trim(),pageIndex:s().default(0),pageSize:s().default(10),primaryKey:x(),conditions:u(y({search_attribute:x(),search_type:g([`between`,`eq`,`equals`,`greater_than`,`greater_than_equal`,`less_than`,`less_than_equal`,`ne`,`not_equal`,`starts_with`]),search_value:_()})),sort:y({attribute:x(),descending:m()})})};async function ra({input:{database:e,table:t,conditions:n,primaryKey:r,...i},instanceClientParams:a}){try{if(!n.length){let{data:n}=await Ge({...a,databaseName:e,tableName:t,onlyIfCached:!0,searchAttribute:r,...i});return{success:!0,data:n}}let{data:o}=await He({...a,databaseName:e,tableName:t,onlyIfCached:!0,conditions:n,...i});return{success:!0,data:o}}catch(e){return{success:!1,message:`Error: ${e}`}}}var ia={...na,icon:Le,execute:ra},aa={name:`restartHTTPService`,description:`Restarts the HTTP service on the server to allow schema and resource changes to be applied.`,inputSchema:y({})};async function oa({instanceClientParams:e,baseURL:t}){let n=C.loading(`Restarting HTTP service...`,{description:`This may take a bit.`,duration:3e5});try{await Se({...e,operation:`restart_service`,replicated:e.entityType===`cluster`})}catch(e){return{success:!1,message:`Error: ${e}`}}return C.success(`Done!`,{description:`HTTP Service restarted!`,id:n,duration:5e3}),{success:!0,message:`HTTP Service restarted!`,webURL:t}}var sa={...aa,icon:Ae,execute:oa,requiresApproval:!0},ca={name:`setComponentFile`,description:`Returns the contents of a component file by its full path (which was returned by getComponents)`,inputSchema:y({path:x().trim(),payload:x(),encoding:g([`utf8`,`ASCII`,`binary`,`hex`,`base64`,`utf16le`,`latin1`,`ucs2`])})};async function la({input:{path:e,encoding:t,payload:n},instanceClientParams:r}){try{let i=e.split(`/`),a=i.shift(),o=i.join(`/`),s=await _e({...r,file:o,project:a,payload:n,encoding:t});return await Pe.invalidateQueries({queryKey:[r.entityId,`get_component_file`,a,o]}),De(`ReloadApplicationRootEntries`,!0),{success:!0,data:s}}catch(e){return{success:!1,message:`Error: ${e}`}}}var ua={...ca,icon:ot,execute:la,requiresApproval:!0},da={name:`updateTableRecords`,description:`Updates records in a particular table in a particular database on the server.`,inputSchema:y({database:x().trim(),table:x().trim(),records:u(_())})};async function fa({input:{database:e,table:t,records:n},instanceClientParams:r,params:i}){try{let a=await Xe({...r,databaseName:e,tableName:t,records:n}),{databaseName:o,tableName:s}=i;return await Pe.invalidateQueries({queryKey:[r.entityId,o,s]}),{success:!0,data:a}}catch(e){return{success:!1,message:`Error: ${e}`}}}var pa={readHarperSkill:Qi,createApp:gi,readLogs:ta,getAnalytics:Ti,listAnalyticsMetrics:qi,restartHTTPService:sa,collectFeedback:pi,getUserContext:Bi,getComponentFile:Oi,getComponents:ji,setComponentFile:ua,dropComponentFile:Si,getDescribeAll:Pi,getDescribeTable:Li,insertTableRecords:Ui,readTableRecords:ia,updateTableRecords:{...da,icon:nt,execute:fa,requiresApproval:!0},deleteTableRecords:yi};function ma(e){return pa[e]}function ha({part:e,onApprove:t,onDeny:n,onAlwaysApprove:i,isApproving:a}){let[o,s]=(0,T.useState)(!1),[c,l]=(0,T.useState)(!1),u=Br(e),d=ma(u),f=d?.icon||Ze,p=d?.requiresApproval,m=(0,T.useMemo)(()=>e.input?typeof e.input==`object`?Object.keys(e.input).length===0:!1:!0,[e.input]),h=(0,T.useMemo)(()=>{let t=JSON.stringify(e.input,null,` `);return{json:t,lines:t?t.split(`
|
|
1699
1699
|
`).length:0}},[e.input]),g=(0,T.useMemo)(()=>{let t=JSON.stringify(e.output,null,` `);return{json:t,lines:t?t.split(`
|
|
1700
1700
|
`).length:0}},[e.output]);return(0,E.jsxs)(`div`,{className:`tool-invocation ${e.state}`,children:[(0,E.jsxs)(`div`,{className:`tool-info`,children:[(0,E.jsxs)(`div`,{className:`tool-name`,children:[(0,E.jsx)(f,{size:14}),(0,E.jsx)(`span`,{children:u})]}),(0,E.jsxs)(`div`,{className:`tool-status`,children:[e.state===`input-streaming`&&`Thinking...`,e.state===`input-available`&&(a?`Executing...`:p?`Awaiting Approval...`:`Executing...`),e.state===`output-available`&&(e.output?.error?(0,E.jsx)(at,{size:14,className:`text-destructive`}):(0,E.jsx)($e,{size:14}))]})]}),e.state!==`input-streaming`&&(0,E.jsxs)(`div`,{className:`tool-io`,children:[!m&&(0,E.jsxs)(`div`,{className:`tool-args`,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between gap-2 mb-1`,children:[(0,E.jsx)(`strong`,{children:`Input:`}),h.lines>3&&(0,E.jsx)(r,{type:`button`,variant:`ghost`,size:`sm`,className:`h-6 px-2 text-[10px] uppercase tracking-wider text-muted-foreground hover:text-foreground`,onClick:()=>s(!o),children:o?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(Ve,{size:12}),`Hide`]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(Ke,{size:12}),`Show`]})})]}),(0,E.jsx)(`div`,{className:o?`whitespace-pre-wrap`:`line-clamp-3 overflow-hidden whitespace-pre-wrap`,children:h.json})]}),e.state===`input-available`&&p&&(0,E.jsxs)(`div`,{className:`flex gap-2 mt-3 pt-3 border-t`,children:[(0,E.jsxs)(r,{size:`sm`,className:`h-8 text-xs bg-green-600 hover:bg-green-700 text-white`,onClick:()=>t?.(e.toolCallId),disabled:a,children:[a?(0,E.jsx)(qe,{className:`mr-2 h-3 w-3 animate-spin`}):null,`Approve`]}),(0,E.jsx)(r,{type:`button`,size:`sm`,variant:`outline`,className:`h-8 text-xs`,onClick:()=>i?.(e.toolCallId),disabled:a,children:`Always Approve`}),(0,E.jsx)(r,{type:`button`,size:`sm`,variant:`outline`,className:`h-8 text-xs`,onClick:()=>n?.(e.toolCallId),disabled:a,children:`Deny`})]}),e.state===`output-available`&&(0,E.jsx)(E.Fragment,{children:d?.render?d.render(e):(0,E.jsxs)(`div`,{className:`tool-result`,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between gap-2 mb-1`,children:[(0,E.jsx)(`strong`,{children:`Result:`}),g.lines>3&&(0,E.jsx)(r,{type:`button`,variant:`ghost`,size:`sm`,className:`h-6 px-2 text-[10px] uppercase tracking-wider text-muted-foreground hover:text-foreground`,onClick:()=>l(!c),children:c?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(Ve,{size:12}),`Hide`]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(Ke,{size:12}),`Show`]})})]}),(0,E.jsx)(`div`,{className:c?`whitespace-pre-wrap`:`line-clamp-3 overflow-hidden whitespace-pre-wrap`,children:g.json})]})})]})]})}function ga({message:e,onApprove:t,onDeny:n,onAlwaysApprove:r,approvingToolCallIds:i}){return(0,E.jsxs)(ce.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},className:`message-bubble ${e.role===`user`?`user`:`assistant`}`,children:[(0,E.jsx)(`div`,{className:`avatar`,children:e.role===`user`?(0,E.jsx)(Fe,{size:18}):(0,E.jsx)(se,{size:18})}),(0,E.jsx)(`div`,{className:`content`,children:e.parts?.map((e,a)=>Ir(e)?(0,E.jsx)(`div`,{className:`text-block`,children:e.text},a):K(e)?(0,E.jsx)(ha,{part:e,onApprove:t,onDeny:n,onAlwaysApprove:r,isApproving:i?.has(e.toolCallId)},a):null)})]},e.id)}function _a(e){return te({queryKey:[`getMyUsage`,e],queryFn:async()=>{let{data:t}=await n.get(`/Chat/Usage/${e}`);return t}})}function va(){let{organizationId:e}=ne({strict:!1});return re(_a(e))}function ya(){let{data:e,isLoading:t,error:n}=va();if(t||n||!e)return null;let{usageUSD:r,monthlyLimitUSD:i,usageBarPercent:a}=e,o=e=>new Intl.NumberFormat(`en-US`,{style:`currency`,currency:`USD`}).format(e);return(0,E.jsxs)(`div`,{className:`usage-container`,children:[(0,E.jsxs)(`div`,{className:`usage-info`,children:[(0,E.jsx)(`span`,{children:`Monthly Org Usage`}),(0,E.jsxs)(`span`,{children:[o(r),` / `,o(i)]}),(0,E.jsxs)(`span`,{children:[Math.round(a),`%`]})]}),(0,E.jsx)(`div`,{className:`usage-bar-bg`,children:(0,E.jsx)(`div`,{className:`usage-bar-fill`,style:{width:`${a}%`}})})]})}function ba({autoFocus:e,closeChat:t}){let n=ne({strict:!1}),{organizationId:r}=n,[i,a]=xe(`ApplicationChat`,``),[o,s]=(0,T.useState)(!0),[c,l]=(0,T.useState)({}),[u,d]=(0,T.useState)(new Set),[f,p]=je(we.ChatAlwaysApprovedTools,[]),m=new Set(f),h=et(),g=ke(),_=ie(),{messages:v,sendMessage:ee,status:y,addToolOutput:b,setMessages:x}=ci({transport:Xr(r),generateId:A(),sendAutomaticallyWhen:Yr,onFinish(){_.invalidateQueries({queryKey:[`getMyUsage`]})},async onToolCall({toolCall:e}){if(e.dynamic)return;let t=ma(e.toolName);if(t){if(t.requiresApproval&&!m.has(e.toolName)){let t={type:`tool-call`,toolCallId:e.toolCallId,toolName:e.toolName,input:e.input};l(n=>({...n,[e.toolCallId]:t}));return}let r=await t.execute({input:e.input,instanceClientParams:g,baseURL:h,params:n});b({tool:e.toolName,toolCallId:e.toolCallId,output:r})}}}),S=(0,T.useCallback)(async e=>{let t=c[e];if(t){d(t=>{let n=new Set(t);return n.add(e),n});try{let r=ma(t.toolName);if(r){let i=await r.execute({input:t.input,instanceClientParams:g,baseURL:h,params:n});b({tool:t.toolName,toolCallId:t.toolCallId,output:i}),l(t=>{let n={...t};return delete n[e],n})}}finally{d(t=>{let n=new Set(t);return n.delete(e),n})}}},[c,g,h,b,n]),te=(0,T.useCallback)(e=>{let t=c[e];t&&(b({tool:t.toolName,toolCallId:t.toolCallId,output:{error:`User denied the tool execution.`}}),l(t=>{let n={...t};return delete n[e],n}))},[c,b]),re=(0,T.useCallback)(async e=>{let t=c[e];t&&(p(e=>Oe([...e,t.toolName])),await S(e))},[c,p,S]);(0,T.useEffect)(()=>{(async()=>{try{let e=await ft();Array.isArray(e)&&x(e)}catch(e){console.error(`Failed to fetch initial messages:`,e)}finally{s(!1)}})()},[x]);let ae=y===`streaming`||y===`submitted`,oe=(0,T.useRef)(null);return(0,T.useEffect)(()=>{oe.current?.scrollIntoView({behavior:`smooth`})},[v]),(0,E.jsxs)(`div`,{className:`flex flex-col h-full`,children:[(0,E.jsxs)(`div`,{className:`flex items-start justify-between gap-6 px-4 py-2.5 border-b border-border bg-card`,children:[(0,E.jsxs)(`div`,{className:`flex flex-col gap-1 min-w-0 flex-1`,children:[(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(se,{className:`text-primary`,size:20}),(0,E.jsx)(`span`,{className:`font-semibold text-foreground`,children:`Harper Agent`})]}),(0,E.jsx)(ya,{})]}),(0,E.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,E.jsx)(dt,{setMessages:x}),(0,E.jsx)(`button`,{onClick:t,className:`p-1 hover:bg-accent rounded-md transition-colors text-muted-foreground hover:text-foreground`,title:`Close chat`,children:(0,E.jsx)(Me,{size:20})})]})]}),(0,E.jsx)(`div`,{className:`flex-1 overflow-hidden`,children:(0,E.jsxs)(`div`,{className:`chat-interface h-full w-full`,children:[(0,E.jsxs)(`div`,{className:`messages-area`,children:[o&&(0,E.jsx)(ui,{}),!o&&v.length===0&&(0,E.jsxs)(`div`,{className:`empty-state`,children:[(0,E.jsx)(se,{size:48}),(0,E.jsx)(`p`,{children:`Ask me to create a Harper app!`})]}),v.map(e=>(0,E.jsx)(ga,{message:e,onApprove:S,onDeny:te,onAlwaysApprove:re,approvingToolCallIds:u},e.id)),(0,E.jsx)(`div`,{ref:oe})]}),(0,E.jsx)(li,{input:i,setInput:a,onSubmit:e=>{e.preventDefault(),i.trim()&&!ae&&!o&&(ee({text:i}),a(``))},disabled:o,autoFocus:e})]})})]})}export{ba as Chat};
|
|
1701
|
-
//# sourceMappingURL=Chat-
|
|
1701
|
+
//# sourceMappingURL=Chat-DMBW4pI2.js.map
|