@harperfast/harper 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/bin/copyDb.ts +16 -3
- package/dist/bin/copyDb.js +16 -3
- package/dist/bin/copyDb.js.map +1 -1
- package/dist/resources/Table.js +43 -4
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/databases.js +135 -41
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/graphql.js +3 -0
- package/dist/resources/graphql.js.map +1 -1
- package/dist/resources/replayLogs.d.ts +1 -0
- package/dist/resources/replayLogs.js +100 -40
- package/dist/resources/replayLogs.js.map +1 -1
- package/dist/resources/replayLogsGuards.d.ts +25 -8
- package/dist/resources/replayLogsGuards.js +50 -10
- package/dist/resources/replayLogsGuards.js.map +1 -1
- package/dist/server/nodeName.js +9 -3
- package/dist/server/nodeName.js.map +1 -1
- package/dist/server/operationsServer.js +20 -0
- package/dist/server/operationsServer.js.map +1 -1
- package/dist/utility/install/installer.js +12 -6
- package/dist/utility/install/installer.js.map +1 -1
- package/package.json +3 -3
- package/resources/Table.ts +41 -4
- package/resources/databases.ts +134 -42
- package/resources/graphql.ts +3 -0
- package/resources/replayLogs.ts +114 -42
- package/resources/replayLogsGuards.ts +58 -9
- package/server/nodeName.ts +9 -3
- package/server/operationsServer.ts +17 -0
- 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/utility/install/installer.ts +12 -5
- package/studio/web/assets/index-Cd3Zh3nK.js.map +0 -1
|
@@ -42,22 +42,71 @@ export function classifyAuditEntryForReplay(
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
* Whether an audit entry
|
|
46
|
-
*
|
|
45
|
+
* Whether an audit entry runs `validate()` during replay but its record body failed to decode,
|
|
46
|
+
* and so must be skipped.
|
|
47
47
|
*
|
|
48
48
|
* `RecordEncoder.decode` returns `null` (not `undefined`, and it does not throw) when a value
|
|
49
49
|
* fails to decode — e.g. structure-dictionary divergence, which surfaces as msgpackr's
|
|
50
50
|
* "Data read, but end of buffer not reached". `classifyAuditEntryForReplay` only catches a
|
|
51
|
-
* `undefined` body, so a `null` slips through;
|
|
52
|
-
*
|
|
51
|
+
* `undefined` body, so a `null` slips through; the replay path then calls `validate()`, which
|
|
52
|
+
* dereferences the record and crashes on the missing body.
|
|
53
53
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
54
|
+
* Scoped to the actions whose replay reaches `validate()`: `put`/`patch` (via `_writeUpdate` →
|
|
55
|
+
* `save()`) and `message` (via `_writePublish` → `transaction.addWrite` → `save()`; the publish
|
|
56
|
+
* `validate` hook fires whenever the replay context has no `source`, which it never does). Other
|
|
57
|
+
* record-bearing actions must NOT be skipped on a `null` body — notably `invalidate`, which
|
|
58
|
+
* legitimately stores a `null` partial record on a table with no index fields and never reaches
|
|
59
|
+
* `validate()`; `relocate`/`delete` ignore the body entirely. See harper#1255.
|
|
58
60
|
*/
|
|
59
61
|
export function isUndecodableValidatedWrite(type: string | undefined, record: unknown): boolean {
|
|
60
|
-
return record == null && (type === 'put' || type === 'patch');
|
|
62
|
+
return record == null && (type === 'put' || type === 'patch' || type === 'message');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// A node that crashed unclean replays its unflushed audit backlog on boot. When that backlog is
|
|
66
|
+
// dominated by entries that can't be written — undecodable values (the #1163 structure-dictionary
|
|
67
|
+
// divergence), corrupt headers, or entries for a dropped table — every iteration makes no forward
|
|
68
|
+
// progress. A large enough backlog then grinds the main thread for minutes with zero progress,
|
|
69
|
+
// blocking startup entirely (harper#1266). These bounds let replay give up on a run that is making
|
|
70
|
+
// no progress so boot can proceed; the operator then sheds/relocates the offending peer log (or
|
|
71
|
+
// re-clones). They are deliberately conservative: a healthy replay produces writes, which reset
|
|
72
|
+
// the progress tracking, so neither bound can trip on it.
|
|
73
|
+
|
|
74
|
+
// Max consecutive no-progress entries (since the last successful write) before the replay is
|
|
75
|
+
// treated as stalled. ~100k contiguous unwritable entries is unambiguously degenerate and caps the
|
|
76
|
+
// wasted grind well below the multi-minute hangs observed in prod.
|
|
77
|
+
export const REPLAY_NO_PROGRESS_COUNT_LIMIT = 100_000;
|
|
78
|
+
|
|
79
|
+
// Max wall-clock time (ms) since the last successful write before the replay is treated as stalled.
|
|
80
|
+
// Belt-and-suspenders for the count bound: if individual entries are slow enough that fewer than the
|
|
81
|
+
// count limit still burns minutes, this still bounds the hang.
|
|
82
|
+
export const REPLAY_NO_PROGRESS_TIME_LIMIT_MS = 60_000;
|
|
83
|
+
|
|
84
|
+
// The time bound only applies once a substantial no-progress run has built up. Without this floor a
|
|
85
|
+
// single skipped entry followed by an unrelated latency spike (a GC pause, disk throttling, one
|
|
86
|
+
// slow write) would trip the time bound and abort an otherwise-healthy replay; requiring a real run
|
|
87
|
+
// of no-progress entries keeps the time bound a signal of a genuine grind, not a transient stall.
|
|
88
|
+
export const REPLAY_NO_PROGRESS_TIME_SKIP_FLOOR = 1_000;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Whether boot replay should abort because it is making no forward progress — a backlog of
|
|
92
|
+
* unwritable entries (undecodable/corrupt, or for a dropped table) that produces no writes
|
|
93
|
+
* (harper#1266). Returns `true` once the contiguous run of no-progress entries since the last
|
|
94
|
+
* successful write crosses the count bound, or once it has both built up past the time-skip floor
|
|
95
|
+
* AND burned the time bound. All inputs are measured since the last write, so a productive replay
|
|
96
|
+
* (which keeps resetting them) never trips this; only a genuinely stalled, write-free grind does.
|
|
97
|
+
*
|
|
98
|
+
* @param noProgressRun consecutive entries processed without a successful write
|
|
99
|
+
* @param msSinceProgress wall-clock ms elapsed since the last successful write
|
|
100
|
+
*/
|
|
101
|
+
export function shouldAbortStalledReplay(
|
|
102
|
+
noProgressRun: number,
|
|
103
|
+
msSinceProgress: number,
|
|
104
|
+
countLimit = REPLAY_NO_PROGRESS_COUNT_LIMIT,
|
|
105
|
+
timeLimitMs = REPLAY_NO_PROGRESS_TIME_LIMIT_MS,
|
|
106
|
+
timeSkipFloor = REPLAY_NO_PROGRESS_TIME_SKIP_FLOOR
|
|
107
|
+
): boolean {
|
|
108
|
+
if (noProgressRun >= countLimit) return true;
|
|
109
|
+
return noProgressRun >= timeSkipFloor && msSinceProgress >= timeLimitMs;
|
|
61
110
|
}
|
|
62
111
|
|
|
63
112
|
/**
|
package/server/nodeName.ts
CHANGED
|
@@ -29,10 +29,16 @@ export function getThisNodeName(): string {
|
|
|
29
29
|
if (nodeName) return nodeName; // if already determined, just return
|
|
30
30
|
nodeName = env.get(CONFIG_PARAMS.NODE_HOSTNAME); // standard config
|
|
31
31
|
if (nodeName) {
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
const replicationHostname = env.get('replication_hostname');
|
|
33
|
+
if (replicationHostname && replicationHostname !== nodeName) {
|
|
34
|
+
// If these are both set and differ, the node identity is ambiguous. node.hostname
|
|
35
|
+
// wins (it is what this node identifies as), but if it doesn't match the name this
|
|
36
|
+
// node is registered under in hdb_nodes, replication for that name silently turns
|
|
37
|
+
// off (harper-pro#351). Do NOT blindly recommend cementing the already-picked
|
|
38
|
+
// node.hostname value — that's how a wrong identity (e.g. 'localhost') gets locked
|
|
39
|
+
// in. Steer the operator to reconcile against the registered node name instead.
|
|
34
40
|
logger.warn?.(
|
|
35
|
-
`The node.hostname and replication.hostname configuration values are both set and
|
|
41
|
+
`The node.hostname (${nodeName}) and replication.hostname (${replicationHostname}) configuration values are both set and differ. This node will identify as "${nodeName}". Ensure that name matches this node's row in system.hdb_nodes; if it does not, set node.hostname (or remove it to fall back to replication.hostname) to match the registered node name, otherwise replication for this node will be disabled.`
|
|
36
42
|
);
|
|
37
43
|
}
|
|
38
44
|
return nodeName;
|
|
@@ -16,6 +16,7 @@ import { PACKAGE_ROOT } from '../utility/packageUtils.js';
|
|
|
16
16
|
import * as globalSchema from '../utility/globalSchema.ts';
|
|
17
17
|
import * as commonUtils from '../utility/common_utils.ts';
|
|
18
18
|
import * as userSchema from '../security/user.ts';
|
|
19
|
+
import { authentication } from '../security/auth.ts';
|
|
19
20
|
import { server as serverRegistration, type ServerOptions } from '../server/Server.ts';
|
|
20
21
|
import {
|
|
21
22
|
authHandler,
|
|
@@ -74,6 +75,22 @@ async function operationsServer(options: ServerOptions & { resources?: Resources
|
|
|
74
75
|
// now that server is fully loaded/ready, start listening on port provided in config settings or just use
|
|
75
76
|
// zero to wait for sockets from the main thread
|
|
76
77
|
serverRegistration.http(server.server, options);
|
|
78
|
+
// The operations API runs only on the main thread, where auth's worker-only
|
|
79
|
+
// handleApplication never registers the authentication middleware. Register it here
|
|
80
|
+
// (after the node server, so its port already exists) so operations requests get
|
|
81
|
+
// `request.login`/`session`/`user` set up — without it the `login` operation that
|
|
82
|
+
// Studio uses to bootstrap a new instance fails with "No session for login".
|
|
83
|
+
// Node only: on Bun the ops API is served by delegating to Fastify via inject(), and
|
|
84
|
+
// auth is applied through fastifyAuth's Bun shim (there is no `_nodeRequest` for the
|
|
85
|
+
// auth middleware to attach the resolved user to). Register per port because `http()`
|
|
86
|
+
// tags each responder entry with `options.port || port`, so passing both ports in one
|
|
87
|
+
// call would mis-tag the secure entry with the plain port and leave the secure
|
|
88
|
+
// listener's chain without authentication.
|
|
89
|
+
if (typeof globalThis.Bun === 'undefined') {
|
|
90
|
+
if (options.port) serverRegistration.http(authentication, { port: options.port });
|
|
91
|
+
if (options.securePort) serverRegistration.http(authentication, { securePort: options.securePort });
|
|
92
|
+
if (!options.port && !options.securePort) serverRegistration.http(authentication, { port: 'all' });
|
|
93
|
+
}
|
|
77
94
|
// On Bun, register the Fastify instance so requests can be delegated via inject()
|
|
78
95
|
if (typeof globalThis.Bun !== 'undefined') {
|
|
79
96
|
const port = options.port || options.securePort || env.get(CONFIG_PARAMS.OPERATIONSAPI_NETWORK_PORT);
|
|
@@ -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
|