@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.
Files changed (52) hide show
  1. package/bin/copyDb.ts +16 -3
  2. package/dist/bin/copyDb.js +16 -3
  3. package/dist/bin/copyDb.js.map +1 -1
  4. package/dist/resources/Table.js +43 -4
  5. package/dist/resources/Table.js.map +1 -1
  6. package/dist/resources/databases.js +135 -41
  7. package/dist/resources/databases.js.map +1 -1
  8. package/dist/resources/graphql.js +3 -0
  9. package/dist/resources/graphql.js.map +1 -1
  10. package/dist/resources/replayLogs.d.ts +1 -0
  11. package/dist/resources/replayLogs.js +100 -40
  12. package/dist/resources/replayLogs.js.map +1 -1
  13. package/dist/resources/replayLogsGuards.d.ts +25 -8
  14. package/dist/resources/replayLogsGuards.js +50 -10
  15. package/dist/resources/replayLogsGuards.js.map +1 -1
  16. package/dist/server/nodeName.js +9 -3
  17. package/dist/server/nodeName.js.map +1 -1
  18. package/dist/server/operationsServer.js +20 -0
  19. package/dist/server/operationsServer.js.map +1 -1
  20. package/dist/utility/install/installer.js +12 -6
  21. package/dist/utility/install/installer.js.map +1 -1
  22. package/package.json +3 -3
  23. package/resources/Table.ts +41 -4
  24. package/resources/databases.ts +134 -42
  25. package/resources/graphql.ts +3 -0
  26. package/resources/replayLogs.ts +114 -42
  27. package/resources/replayLogsGuards.ts +58 -9
  28. package/server/nodeName.ts +9 -3
  29. package/server/operationsServer.ts +17 -0
  30. package/studio/web/assets/{Chat-BdFickL8.js → Chat-DMBW4pI2.js} +2 -2
  31. package/studio/web/assets/{Chat-BdFickL8.js.map → Chat-DMBW4pI2.js.map} +1 -1
  32. package/studio/web/assets/{FloatingChat-CaAoco8I.js → FloatingChat-DTmhPsrm.js} +4 -4
  33. package/studio/web/assets/{FloatingChat-CaAoco8I.js.map → FloatingChat-DTmhPsrm.js.map} +1 -1
  34. package/studio/web/assets/{applications-C3y3xwyG.js → applications-CigxJarn.js} +2 -2
  35. package/studio/web/assets/{applications-C3y3xwyG.js.map → applications-CigxJarn.js.map} +1 -1
  36. package/studio/web/assets/{index-Cd3Zh3nK.js → index-oRZw5GW3.js} +6 -6
  37. package/studio/web/assets/index-oRZw5GW3.js.map +1 -0
  38. package/studio/web/assets/{index.lazy-0hLbh5Fo.js → index.lazy-DY3VcR86.js} +4 -4
  39. package/studio/web/assets/{index.lazy-0hLbh5Fo.js.map → index.lazy-DY3VcR86.js.map} +1 -1
  40. package/studio/web/assets/{profile-CwBWGuVt.js → profile-DiV60L50.js} +2 -2
  41. package/studio/web/assets/{profile-CwBWGuVt.js.map → profile-DiV60L50.js.map} +1 -1
  42. package/studio/web/assets/{setComponentFile-Dhrmd8eR.js → setComponentFile-Bz6WI4jy.js} +2 -2
  43. package/studio/web/assets/{setComponentFile-Dhrmd8eR.js.map → setComponentFile-Bz6WI4jy.js.map} +1 -1
  44. package/studio/web/assets/{status-Bykq6QcD.js → status-fW6PBpPM.js} +2 -2
  45. package/studio/web/assets/{status-Bykq6QcD.js.map → status-fW6PBpPM.js.map} +1 -1
  46. package/studio/web/assets/{swagger-ui-react-CF94s29D.js → swagger-ui-react-DRYf7G3J.js} +2 -2
  47. package/studio/web/assets/{swagger-ui-react-CF94s29D.js.map → swagger-ui-react-DRYf7G3J.js.map} +1 -1
  48. package/studio/web/assets/{useEntityRestURL-D7vuaG2W.js → useEntityRestURL-14jWKu9J.js} +2 -2
  49. package/studio/web/assets/{useEntityRestURL-D7vuaG2W.js.map → useEntityRestURL-14jWKu9J.js.map} +1 -1
  50. package/studio/web/index.html +1 -1
  51. package/utility/install/installer.ts +12 -5
  52. 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 is a validated write (`put`/`patch`) whose record body failed to
46
- * decode, and so must be skipped during replay.
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; for `put`/`patch` the replay path then calls
52
- * `save()` → `validate()`, which dereferences the record and crashes on the missing body.
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
- * This is deliberately scoped to `put`/`patch` (the only replay actions that run `validate()`).
55
- * Other record-bearing actions must NOT be skipped on a `null` body notably `invalidate`,
56
- * which legitimately stores a `null` partial record on a table with no index fields and never
57
- * reaches `validate()`. See harper#1255.
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
  /**
@@ -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
- if (env.get('replication_hostname') && env.get('replication_hostname') !== nodeName) {
33
- // if these are both set, it can be very confusing, make sure to warn
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 are different. It is recommended that you set the node.hostname, using node.hostname: ${nodeName})`
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-Dhrmd8eR.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-Cd3Zh3nK.js";import{t as et}from"./useEntityRestURL-D7vuaG2W.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}.
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-BdFickL8.js.map
1701
+ //# sourceMappingURL=Chat-DMBW4pI2.js.map