@promptowl/contextnest-community 1.18.0 → 1.19.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/CONFIGURATION.md +1 -1
- package/dist/{chunk-TQACHVVA.js → chunk-3GMGLYTZ.js} +2 -2
- package/dist/{chunk-34UXRZXD.js → chunk-BXUVIAMP.js} +1 -1
- package/dist/{chunk-FUUJG6XP.js → chunk-ENDHMQPD.js} +7 -3
- package/dist/{chunk-HGN45I5P.js → chunk-FBDEESNJ.js} +5 -5
- package/dist/{chunk-QUZXRLUA.js → chunk-GSYMJ3A4.js} +1 -1
- package/dist/{chunk-OOBZG6BW.js → chunk-TNAZJYL5.js} +2 -2
- package/dist/{chunk-GUNJTORH.js → chunk-YVMSM7LS.js} +14 -1
- package/dist/{engine-34E3YNX7.js → engine-V4DY4PYN.js} +2 -2
- package/dist/{external-edit-service-6Q6SHEOF.js → external-edit-service-3NK5DGLA.js} +3 -3
- package/dist/{grants-service-ME7HIVHU.js → grants-service-CADI6LIB.js} +2 -2
- package/dist/index.js +98 -57
- package/dist/{review-service-H2M5ACPQ.js → review-service-LK4M2C43.js} +6 -6
- package/dist/{stewardship-service-U4CKL7Y5.js → stewardship-service-JAFSU5GN.js} +3 -3
- package/dist/{version-service-JWEN5UUW.js → version-service-G7SFFKFO.js} +3 -3
- package/dist/web3/assets/index-C26nM5Kn.css +1 -0
- package/dist/web3/assets/index-C4oalc2K.js +1065 -0
- package/dist/web3/index.html +2 -2
- package/package.json +2 -2
- package/dist/web3/assets/index-DONv5_Ni.css +0 -1
- package/dist/web3/assets/index-jSGrnboh.js +0 -1065
package/CONFIGURATION.md
CHANGED
|
@@ -60,7 +60,7 @@ The server prints a loud warning at startup when `AUTH_MODE=open` is active.
|
|
|
60
60
|
| `PROMPTOWL_SIGN_IN_GATE` | `open` | Restrict "Sign in with PromptOwl". `open` = anyone may; `admin-only` = only the license owner (admin) may, everyone else uses email/password (admin opens the login page with `?admin=1`); `disabled` = nobody may. Enforced server-side at `POST /auth/promptowl` and surfaced on the health endpoint. Unknown values fall back to `open`. |
|
|
61
61
|
| `MANUAL_SIGN_IN` | `open` | Email + password sign-in mode. `open` = anyone may log in and self-register a new account; `invite-only` = existing/invited users may log in but brand-new self-registration returns `403` (the admin provisions accounts via invite/share/steward and shares the password — there is no self-service "set password", which would be account takeover without email verification); `disabled` = no email/password sign-in at all (`POST /auth/login` and `POST /auth/register` return `403`). Independent of `PROMPTOWL_SIGN_IN_GATE`, so the two methods are controlled separately (e.g. `invite-only` manual + `admin-only` PromptOwl). Also settable from Settings → General. The server refuses `disabled` while PromptOwl sign-in is also `disabled` (that would leave no way to log in). Unknown values fall back to `open`. |
|
|
62
62
|
| `OFFICIAL_COMMUNITY_SSO_SECRET` | `""` | **Official deployment only — leave unset on self-hosted.** Shared HMAC secret enabling the one-click "Open Community" SSO auto-login from PromptOwl. Must exactly match the same-named var on PromptOwl. When unset, `GET /auth/sso` returns `404` and the feature is disabled; self-hosted users keep using the manual device-code flow. |
|
|
63
|
-
| `PUBLIC_BASE_URL` | `""` | This server's canonical external URL (e.g. `https://community.promptowl.ai`).
|
|
63
|
+
| `PUBLIC_BASE_URL` | `""` | This server's canonical external URL (e.g. `https://community.promptowl.ai`). Three uses. (1) Checked against the SSO ticket's `aud` claim so a ticket minted for this server can't be replayed against another — only when `OFFICIAL_COMMUNITY_SSO_SECRET` is set; when unset, the audience check is skipped. (2) **Set this whenever `OIDC_ENABLED=true`.** It's the base for the OIDC `redirect_uri` sent to your IdP and replayed at token exchange. Unset, that URI is derived from the incoming request's `Host` header — fine when your proxy overwrites `Host` with a trusted value, but a proxy that passes an attacker-supplied `Host` through would feed it straight into the redirect URI. Setting this pins the value regardless of what the proxy forwards. (Your IdP's own redirect-URI allowlist is a second line of defence, not a substitute.) (3) **Set this wherever `POST /nests/:id/context` citations reach users.** The `url` on each node and the `_source:` line in each context block are built from it; unset, they fall back to the request origin, so a proxy forwarding an untrusted `Host` would put an attacker-influenced URL in front of both the model and the reader as a trustworthy citation. |
|
|
64
64
|
| `OIDC_ENABLED` | `false` | Turn on generic OIDC single sign-on (`GET /auth/oidc/login` / `GET /auth/oidc/callback`). Requires `OIDC_ISSUER`, `OIDC_CLIENT_ID`, and `OIDC_CLIENT_SECRET` — the login-page button only appears once all three are set. Also editable from Settings → Single sign-on. See [Single sign-on (OIDC)](#single-sign-on-oidc). |
|
|
65
65
|
| `OIDC_ISSUER` | `""` | OIDC issuer URL, e.g. `https://login.microsoftonline.com/<tenant>/v2.0` (Microsoft Entra ID) or `https://accounts.google.com` (Google). **`https://` only** — a non-https value is rejected with a warning and SSO stays off. Must serve `<issuer>/.well-known/openid-configuration`. |
|
|
66
66
|
| `OIDC_CLIENT_ID` | `""` | Application (client) ID from your IdP app registration. |
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
resolveNestPermission,
|
|
12
12
|
resolveTeamRolesForUser,
|
|
13
13
|
sendEmailToRecipient
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ENDHMQPD.js";
|
|
15
15
|
import {
|
|
16
16
|
ConflictError,
|
|
17
17
|
ValidationError
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-YVMSM7LS.js";
|
|
19
19
|
import {
|
|
20
20
|
config,
|
|
21
21
|
getDb,
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
ForbiddenError,
|
|
4
4
|
NotFoundError,
|
|
5
5
|
ValidationError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YVMSM7LS.js";
|
|
7
7
|
import {
|
|
8
8
|
config,
|
|
9
9
|
getDb,
|
|
@@ -1101,6 +1101,9 @@ function docLink(nestId, nodeId, baseUrl) {
|
|
|
1101
1101
|
if (nodeId) q.set("doc", nodeId);
|
|
1102
1102
|
return `${base.replace(/\/$/, "")}/?${q.toString()}`;
|
|
1103
1103
|
}
|
|
1104
|
+
function resolveNodeUrl(node, opts) {
|
|
1105
|
+
return docLink(opts.nestId, node.id, opts.baseUrl) || void 0;
|
|
1106
|
+
}
|
|
1104
1107
|
async function buildDocContext(nestId, nodeId, baseUrl) {
|
|
1105
1108
|
const titles = await buildTitleMap(nestId);
|
|
1106
1109
|
const docTitle = titles.get(nodeId) || nodeId;
|
|
@@ -2244,8 +2247,8 @@ async function ensureNodeIndex(nestId) {
|
|
|
2244
2247
|
return run;
|
|
2245
2248
|
}
|
|
2246
2249
|
async function rebuildNodeIndex(nestId) {
|
|
2247
|
-
const { engineCache: engineCache2 } = await import("./engine-
|
|
2248
|
-
const { documentsWithSuggestions } = await import("./external-edit-service-
|
|
2250
|
+
const { engineCache: engineCache2 } = await import("./engine-V4DY4PYN.js");
|
|
2251
|
+
const { documentsWithSuggestions } = await import("./external-edit-service-3NK5DGLA.js");
|
|
2249
2252
|
const { storage, dropDiscoveryCache } = await engineCache2.get(nestId);
|
|
2250
2253
|
dropDiscoveryCache();
|
|
2251
2254
|
const startedAt = writeGeneration.get(nestId) ?? 0;
|
|
@@ -2558,6 +2561,7 @@ export {
|
|
|
2558
2561
|
prettyFolderPath,
|
|
2559
2562
|
nestName,
|
|
2560
2563
|
docLink,
|
|
2564
|
+
resolveNodeUrl,
|
|
2561
2565
|
buildDocContext,
|
|
2562
2566
|
createTeam,
|
|
2563
2567
|
findTeamByExternalId,
|
|
@@ -4,19 +4,19 @@ import {
|
|
|
4
4
|
resolveNestWideRoles,
|
|
5
5
|
resolveStewardsForNode,
|
|
6
6
|
stewardCoverageForUser
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3GMGLYTZ.js";
|
|
8
8
|
import {
|
|
9
9
|
grantCoversNode,
|
|
10
10
|
listUserGrants,
|
|
11
11
|
resolveNodeGrant
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GSYMJ3A4.js";
|
|
13
13
|
import {
|
|
14
14
|
createVersion,
|
|
15
15
|
getApprovedVersion,
|
|
16
16
|
getApprovedVersions,
|
|
17
17
|
getCurrentVersion,
|
|
18
18
|
setApprovedVersion
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-BXUVIAMP.js";
|
|
20
20
|
import {
|
|
21
21
|
buildDocContext,
|
|
22
22
|
buildTitleMap,
|
|
@@ -35,12 +35,12 @@ import {
|
|
|
35
35
|
resolveNestPermission,
|
|
36
36
|
sendEmailToRecipient,
|
|
37
37
|
titleForNode
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-ENDHMQPD.js";
|
|
39
39
|
import {
|
|
40
40
|
ConflictError,
|
|
41
41
|
NotFoundError,
|
|
42
42
|
ValidationError
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-YVMSM7LS.js";
|
|
44
44
|
import {
|
|
45
45
|
config,
|
|
46
46
|
getDb
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
markIndexStale,
|
|
5
5
|
resolveNestPath,
|
|
6
6
|
setSuggestionFlag
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ENDHMQPD.js";
|
|
8
8
|
import {
|
|
9
9
|
getDb
|
|
10
10
|
} from "./chunk-HYSTFMFG.js";
|
|
@@ -253,7 +253,7 @@ async function listExternalEditVerdicts(nestId, documentId) {
|
|
|
253
253
|
async function mirrorVersion(input) {
|
|
254
254
|
const { storage } = await engineCache.get(input.nestId);
|
|
255
255
|
const node = await storage.readDocument(input.documentId);
|
|
256
|
-
const { upsertVersion, setApprovedVersion } = await import("./version-service-
|
|
256
|
+
const { upsertVersion, setApprovedVersion } = await import("./version-service-G7SFFKFO.js");
|
|
257
257
|
await upsertVersion({
|
|
258
258
|
nestId: input.nestId,
|
|
259
259
|
nodeId: input.documentId,
|
|
@@ -43,6 +43,17 @@ var LockedError = class extends AppError {
|
|
|
43
43
|
this.name = "LockedError";
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
|
+
var VaultBusyError = class extends AppError {
|
|
47
|
+
retryAfterSeconds = 5;
|
|
48
|
+
constructor(message = "The vault is busy with another write. Retry shortly.") {
|
|
49
|
+
super(503, message);
|
|
50
|
+
this.name = "VaultBusyError";
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
function isVaultLockTimeout(err) {
|
|
54
|
+
const e = err;
|
|
55
|
+
return e?.name === "VaultLockTimeoutError" || e?.code === "VAULT_LOCK_TIMEOUT";
|
|
56
|
+
}
|
|
46
57
|
|
|
47
58
|
export {
|
|
48
59
|
AppError,
|
|
@@ -51,5 +62,7 @@ export {
|
|
|
51
62
|
UnauthorizedError,
|
|
52
63
|
ValidationError,
|
|
53
64
|
ConflictError,
|
|
54
|
-
LockedError
|
|
65
|
+
LockedError,
|
|
66
|
+
VaultBusyError,
|
|
67
|
+
isVaultLockTimeout
|
|
55
68
|
};
|
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
engineApi,
|
|
3
3
|
engineCache,
|
|
4
4
|
opContext
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-ENDHMQPD.js";
|
|
6
|
+
import "./chunk-YVMSM7LS.js";
|
|
7
7
|
import "./chunk-HYSTFMFG.js";
|
|
8
8
|
import "./chunk-YB3LKF7U.js";
|
|
9
9
|
import "./chunk-FRQJWGN3.js";
|
|
@@ -11,9 +11,9 @@ import {
|
|
|
11
11
|
scanNestForDrift,
|
|
12
12
|
startDriftScanner,
|
|
13
13
|
stopDriftScanner
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-TNAZJYL5.js";
|
|
15
|
+
import "./chunk-ENDHMQPD.js";
|
|
16
|
+
import "./chunk-YVMSM7LS.js";
|
|
17
17
|
import "./chunk-HYSTFMFG.js";
|
|
18
18
|
import "./chunk-YB3LKF7U.js";
|
|
19
19
|
import "./chunk-FRQJWGN3.js";
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
listGrants,
|
|
7
7
|
listUserGrants,
|
|
8
8
|
resolveNodeGrant
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-GSYMJ3A4.js";
|
|
10
|
+
import "./chunk-YVMSM7LS.js";
|
|
11
11
|
import "./chunk-HYSTFMFG.js";
|
|
12
12
|
import "./chunk-YB3LKF7U.js";
|
|
13
13
|
export {
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
submitForReview,
|
|
42
42
|
withNodeWriteLock,
|
|
43
43
|
withdrawDeletionRequest
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-FBDEESNJ.js";
|
|
45
45
|
import {
|
|
46
46
|
canCreateInNest,
|
|
47
47
|
canManageStewards,
|
|
@@ -61,7 +61,7 @@ import {
|
|
|
61
61
|
resolveUserRoles,
|
|
62
62
|
syncFromConfig,
|
|
63
63
|
updateSteward
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-3GMGLYTZ.js";
|
|
65
65
|
import {
|
|
66
66
|
createGrant,
|
|
67
67
|
deleteGrant,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
listGrants,
|
|
71
71
|
listUserGrants,
|
|
72
72
|
resolveNodeGrant
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-GSYMJ3A4.js";
|
|
74
74
|
import {
|
|
75
75
|
generateApiKey,
|
|
76
76
|
getKeyPrefix,
|
|
@@ -93,7 +93,7 @@ import {
|
|
|
93
93
|
listMyDrafts,
|
|
94
94
|
setApprovedVersion,
|
|
95
95
|
upsertVersion
|
|
96
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-BXUVIAMP.js";
|
|
97
97
|
import {
|
|
98
98
|
approveExternalEdit,
|
|
99
99
|
getExternalEditDetail,
|
|
@@ -105,7 +105,7 @@ import {
|
|
|
105
105
|
scanDocumentForDrift,
|
|
106
106
|
scanNestForDrift,
|
|
107
107
|
startDriftScanner
|
|
108
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-TNAZJYL5.js";
|
|
109
109
|
import {
|
|
110
110
|
addMember,
|
|
111
111
|
assertSafeNodeId,
|
|
@@ -174,6 +174,7 @@ import {
|
|
|
174
174
|
resolveNestAccess,
|
|
175
175
|
resolveNestPath,
|
|
176
176
|
resolveNestPermission,
|
|
177
|
+
resolveNodeUrl,
|
|
177
178
|
resolveTeamRolesForUser,
|
|
178
179
|
sendEmailToRecipient,
|
|
179
180
|
setAllowSelfApprove,
|
|
@@ -190,7 +191,7 @@ import {
|
|
|
190
191
|
updateMemberRole,
|
|
191
192
|
validateLicense,
|
|
192
193
|
verifySmtp
|
|
193
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-ENDHMQPD.js";
|
|
194
195
|
import {
|
|
195
196
|
AppError,
|
|
196
197
|
ConflictError,
|
|
@@ -198,8 +199,10 @@ import {
|
|
|
198
199
|
LockedError,
|
|
199
200
|
NotFoundError,
|
|
200
201
|
UnauthorizedError,
|
|
201
|
-
ValidationError
|
|
202
|
-
|
|
202
|
+
ValidationError,
|
|
203
|
+
VaultBusyError,
|
|
204
|
+
isVaultLockTimeout
|
|
205
|
+
} from "./chunk-YVMSM7LS.js";
|
|
203
206
|
import {
|
|
204
207
|
config,
|
|
205
208
|
getDb,
|
|
@@ -1657,16 +1660,14 @@ import {
|
|
|
1657
1660
|
normalizeStatus,
|
|
1658
1661
|
isRejected,
|
|
1659
1662
|
filterDocuments,
|
|
1660
|
-
DocumentNotFoundError
|
|
1663
|
+
DocumentNotFoundError,
|
|
1664
|
+
NODE_TYPES
|
|
1661
1665
|
} from "@promptowl/contextnest-engine";
|
|
1662
1666
|
import { rename, mkdir } from "fs/promises";
|
|
1663
1667
|
import { dirname, join } from "path";
|
|
1664
1668
|
|
|
1665
1669
|
// src/governance/safe-publish.ts
|
|
1666
|
-
import {
|
|
1667
|
-
publishDocument,
|
|
1668
|
-
serializeDocument
|
|
1669
|
-
} from "@promptowl/contextnest-engine";
|
|
1670
|
+
import { serializeDocument } from "@promptowl/contextnest-engine";
|
|
1670
1671
|
function serializeNodeSafe(node) {
|
|
1671
1672
|
return serializeDocument({
|
|
1672
1673
|
...node,
|
|
@@ -1804,6 +1805,10 @@ function toSafeError(err, context, message) {
|
|
|
1804
1805
|
"This document is rejected. Change its status before saving."
|
|
1805
1806
|
);
|
|
1806
1807
|
}
|
|
1808
|
+
if (isVaultLockTimeout(err)) {
|
|
1809
|
+
console.error(`${context}:`, err);
|
|
1810
|
+
return new VaultBusyError();
|
|
1811
|
+
}
|
|
1807
1812
|
console.error(`${context}:`, err);
|
|
1808
1813
|
return new AppError(500, message);
|
|
1809
1814
|
}
|
|
@@ -1818,6 +1823,12 @@ var RUNNABLE_NODE_TYPES = ["agent", "skill"];
|
|
|
1818
1823
|
function isRunnableType(type) {
|
|
1819
1824
|
return RUNNABLE_NODE_TYPES.includes(type || "");
|
|
1820
1825
|
}
|
|
1826
|
+
var ACCEPTED_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
1827
|
+
...NODE_TYPES,
|
|
1828
|
+
...RUNNABLE_NODE_TYPES,
|
|
1829
|
+
"artifact",
|
|
1830
|
+
"table"
|
|
1831
|
+
]);
|
|
1821
1832
|
function toNodeResponse(node) {
|
|
1822
1833
|
const fm = node.frontmatter;
|
|
1823
1834
|
const title = fm.title === void 0 || fm.title === null ? "" : String(fm.title);
|
|
@@ -1947,12 +1958,12 @@ async function listNodesForCaller(nestId, userId, filters = {}) {
|
|
|
1947
1958
|
if (filters.folder !== void 0) assertSafeFolder(filters.folder);
|
|
1948
1959
|
const { versions: versionManager } = await engineCache.get(nestId);
|
|
1949
1960
|
const userEmail = await resolveCallerEmail(userId);
|
|
1950
|
-
const
|
|
1961
|
+
const listFilters = {
|
|
1951
1962
|
...filters.type ? { type: filters.type } : {},
|
|
1952
1963
|
...filters.tag ? { tag: filters.tag } : {},
|
|
1953
|
-
...filters.status ? { status: filters.status } : {}
|
|
1954
|
-
includeRetired: true
|
|
1964
|
+
...filters.status ? { status: filters.status } : {}
|
|
1955
1965
|
};
|
|
1966
|
+
const frontmatterFilters = { ...listFilters, includeRetired: true };
|
|
1956
1967
|
let documents;
|
|
1957
1968
|
if (filters.withContent) {
|
|
1958
1969
|
const scopeInEngine = filters.folder !== void 0 && engineScopesFolders();
|
|
@@ -1960,7 +1971,7 @@ async function listNodesForCaller(nestId, userId, filters = {}) {
|
|
|
1960
1971
|
({ documents } = await engineApi.run(
|
|
1961
1972
|
"context_list",
|
|
1962
1973
|
{
|
|
1963
|
-
...
|
|
1974
|
+
...listFilters,
|
|
1964
1975
|
include_retired: true,
|
|
1965
1976
|
...scopeInEngine ? {
|
|
1966
1977
|
folder: [scopePrefix, filters.folder].filter(Boolean).join("/"),
|
|
@@ -1976,7 +1987,10 @@ async function listNodesForCaller(nestId, userId, filters = {}) {
|
|
|
1976
1987
|
nestId,
|
|
1977
1988
|
filters.folder !== void 0 ? { folder: filters.folder } : {}
|
|
1978
1989
|
);
|
|
1979
|
-
documents = filterDocuments(indexed,
|
|
1990
|
+
documents = filterDocuments(indexed, {
|
|
1991
|
+
...frontmatterFilters,
|
|
1992
|
+
includeRetired: true
|
|
1993
|
+
});
|
|
1980
1994
|
}
|
|
1981
1995
|
const scoped = filters.folder === void 0 ? documents : documents.filter((d) => folderOfId(d.id) === filters.folder);
|
|
1982
1996
|
const nodes = scoped.map((d) => ({
|
|
@@ -2226,6 +2240,11 @@ async function createNodeOnce(nestId, input, userEmail) {
|
|
|
2226
2240
|
if (requestedType === "table" && !config.TYPE_TABLE_ENABLED) {
|
|
2227
2241
|
throw new ValidationError("Table nodes are disabled on this server");
|
|
2228
2242
|
}
|
|
2243
|
+
if (!ACCEPTED_NODE_TYPES.has(requestedType)) {
|
|
2244
|
+
throw new ValidationError(
|
|
2245
|
+
`unknown node type "${requestedType}"; allowed: ${[...ACCEPTED_NODE_TYPES].sort().join(", ")}`
|
|
2246
|
+
);
|
|
2247
|
+
}
|
|
2229
2248
|
if (input.schedule !== void 0 && !isRunnableType(input.type)) {
|
|
2230
2249
|
throw new ValidationError(
|
|
2231
2250
|
`schedule is only valid for runnable node types (${RUNNABLE_NODE_TYPES.join(
|
|
@@ -4229,7 +4248,7 @@ nodeRoutes.post("/", async (c) => {
|
|
|
4229
4248
|
nodeRoutes.get("/:nodeId{.+}/stewards", async (c) => {
|
|
4230
4249
|
const nestId = c.req.param("nestId");
|
|
4231
4250
|
const nodeId = c.req.param("nodeId");
|
|
4232
|
-
const { resolveStewardsWithFallback: resolveStewardsWithFallback2 } = await import("./stewardship-service-
|
|
4251
|
+
const { resolveStewardsWithFallback: resolveStewardsWithFallback2 } = await import("./stewardship-service-JAFSU5GN.js");
|
|
4233
4252
|
const { stewards, fallbackToOwner, ownerEmail } = await resolveStewardsWithFallback2(
|
|
4234
4253
|
nestId,
|
|
4235
4254
|
nodeId
|
|
@@ -4250,7 +4269,7 @@ nodeRoutes.get("/:nodeId{.+}/stewards", async (c) => {
|
|
|
4250
4269
|
nodeRoutes.get("/:nodeId{.+}/reviews", async (c) => {
|
|
4251
4270
|
const nestId = c.req.param("nestId");
|
|
4252
4271
|
const nodeId = c.req.param("nodeId");
|
|
4253
|
-
const { getReviewHistory: getReviewHistory2 } = await import("./review-service-
|
|
4272
|
+
const { getReviewHistory: getReviewHistory2 } = await import("./review-service-LK4M2C43.js");
|
|
4254
4273
|
const history = await getReviewHistory2(nestId, nodeId);
|
|
4255
4274
|
return c.json({ reviews: history });
|
|
4256
4275
|
});
|
|
@@ -4889,7 +4908,6 @@ annotationRoutes.get("/:nodeId{.+}/hosted", async (c) => {
|
|
|
4889
4908
|
|
|
4890
4909
|
// src/nodes/query-routes.ts
|
|
4891
4910
|
import { Hono as Hono10 } from "hono";
|
|
4892
|
-
import { serializeDocument as serializeDocument3 } from "@promptowl/contextnest-engine";
|
|
4893
4911
|
|
|
4894
4912
|
// src/tables/service.ts
|
|
4895
4913
|
function splitCsvLine(line) {
|
|
@@ -5649,11 +5667,15 @@ queryRoutes.get("/graph", async (c) => {
|
|
|
5649
5667
|
function approxTokens(text) {
|
|
5650
5668
|
return Math.ceil(text.length / 4);
|
|
5651
5669
|
}
|
|
5652
|
-
function formatContextBlock(node) {
|
|
5670
|
+
function formatContextBlock(node, url) {
|
|
5653
5671
|
const tags = (node.frontmatter.tags || []).join(" ");
|
|
5654
|
-
const
|
|
5672
|
+
const meta = [
|
|
5673
|
+
tags ? `_tags: ${tags}_` : null,
|
|
5674
|
+
url ? `_source: ${url}_` : null
|
|
5675
|
+
].filter(Boolean);
|
|
5676
|
+
const header = meta.length ? `# ${node.frontmatter.title}
|
|
5655
5677
|
|
|
5656
|
-
|
|
5678
|
+
${meta.join("\n")}
|
|
5657
5679
|
|
|
5658
5680
|
` : `# ${node.frontmatter.title}
|
|
5659
5681
|
|
|
@@ -5666,6 +5688,7 @@ queryRoutes.post("/context", async (c) => {
|
|
|
5666
5688
|
throw new ValidationError("prompt or selector is required");
|
|
5667
5689
|
}
|
|
5668
5690
|
const nestId = c.req.param("nestId");
|
|
5691
|
+
const baseUrl = requestBaseUrl(c.req.url);
|
|
5669
5692
|
const { query: queryEngine, storage } = await engineCache.get(nestId);
|
|
5670
5693
|
const maxTokens = Math.max(50, body.max_tokens ?? 4e3);
|
|
5671
5694
|
const hops = body.hops ?? 2;
|
|
@@ -5774,20 +5797,21 @@ queryRoutes.post("/context", async (c) => {
|
|
|
5774
5797
|
const readable = await Promise.all(
|
|
5775
5798
|
accessible.map(async (doc) => ({
|
|
5776
5799
|
...doc,
|
|
5777
|
-
body: await resolveReadableBody(nestId, doc.id, userId, doc.body || "")
|
|
5800
|
+
body: await resolveReadableBody(nestId, doc.id, userId, doc.body || ""),
|
|
5801
|
+
url: resolveNodeUrl(doc, { nestId, baseUrl })
|
|
5778
5802
|
}))
|
|
5779
5803
|
);
|
|
5780
5804
|
const included = [];
|
|
5781
5805
|
let tokenCount = 0;
|
|
5782
5806
|
for (const doc of readable) {
|
|
5783
|
-
const block = formatContextBlock(doc);
|
|
5807
|
+
const block = formatContextBlock(doc, doc.url);
|
|
5784
5808
|
const blockTokens = approxTokens(block);
|
|
5785
5809
|
if (tokenCount + blockTokens > maxTokens && included.length > 0) break;
|
|
5786
5810
|
included.push(doc);
|
|
5787
5811
|
tokenCount += blockTokens;
|
|
5788
5812
|
}
|
|
5789
5813
|
const truncatedByBudget = accessible.length - included.length;
|
|
5790
|
-
const contextMarkdown = included.map(formatContextBlock).join("\n\n---\n\n");
|
|
5814
|
+
const contextMarkdown = included.map((n) => formatContextBlock(n, n.url)).join("\n\n---\n\n");
|
|
5791
5815
|
trackEvent("context.resolve", {
|
|
5792
5816
|
nestId,
|
|
5793
5817
|
selector_from_prompt: !!compileDetail,
|
|
@@ -5800,6 +5824,7 @@ queryRoutes.post("/context", async (c) => {
|
|
|
5800
5824
|
nodes: included.map((n) => ({
|
|
5801
5825
|
id: n.id,
|
|
5802
5826
|
title: n.frontmatter.title,
|
|
5827
|
+
url: n.url,
|
|
5803
5828
|
tags: n.frontmatter.tags || [],
|
|
5804
5829
|
type: n.frontmatter.type || "document"
|
|
5805
5830
|
})),
|
|
@@ -6013,48 +6038,51 @@ queryRoutes.post("/publish", async (c) => {
|
|
|
6013
6038
|
}
|
|
6014
6039
|
}
|
|
6015
6040
|
const nestId = c.req.param("nestId");
|
|
6016
|
-
const
|
|
6041
|
+
const userEmail = await resolveCallerEmail(c.get("userId"));
|
|
6017
6042
|
const created = [];
|
|
6043
|
+
const skipped = [];
|
|
6044
|
+
const failed = [];
|
|
6018
6045
|
if (body.context_md) {
|
|
6046
|
+
const { storage } = await engineCache.get(nestId);
|
|
6019
6047
|
await storage.writeContextMd(body.context_md);
|
|
6048
|
+
await storage.regenerateIndex();
|
|
6020
6049
|
}
|
|
6021
6050
|
for (const doc of body.documents || []) {
|
|
6022
6051
|
if (!doc.title || !doc.content) continue;
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6052
|
+
try {
|
|
6053
|
+
const result = await createNode(
|
|
6054
|
+
nestId,
|
|
6055
|
+
{
|
|
6056
|
+
title: doc.title,
|
|
6057
|
+
content: doc.content,
|
|
6058
|
+
type: doc.type,
|
|
6059
|
+
tags: doc.tags,
|
|
6060
|
+
scope: doc.scope
|
|
6061
|
+
},
|
|
6062
|
+
userEmail
|
|
6063
|
+
);
|
|
6064
|
+
created.push(result.node.id);
|
|
6065
|
+
} catch (err) {
|
|
6066
|
+
if (err instanceof ConflictError) {
|
|
6067
|
+
skipped.push(doc.title);
|
|
6068
|
+
continue;
|
|
6069
|
+
}
|
|
6070
|
+
if (isVaultLockTimeout(err) || err instanceof VaultBusyError) throw err;
|
|
6071
|
+
if (!(err instanceof AppError)) console.error("bulk publish row failed", err);
|
|
6072
|
+
failed.push({
|
|
6031
6073
|
title: doc.title,
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
version: 1,
|
|
6036
|
-
created_at: now,
|
|
6037
|
-
updated_at: now,
|
|
6038
|
-
metadata: {
|
|
6039
|
-
owners: ["*"],
|
|
6040
|
-
scope: doc.scope || "team"
|
|
6041
|
-
}
|
|
6042
|
-
},
|
|
6043
|
-
body: doc.content,
|
|
6044
|
-
rawContent: ""
|
|
6045
|
-
};
|
|
6046
|
-
const serialized = serializeDocument3(node);
|
|
6047
|
-
await storage.writeDocument(id, serialized);
|
|
6048
|
-
await syncNodeTags(nestId, id, tags);
|
|
6049
|
-
created.push(id);
|
|
6074
|
+
error: err instanceof AppError ? err.message : "Could not create this document"
|
|
6075
|
+
});
|
|
6076
|
+
}
|
|
6050
6077
|
}
|
|
6051
|
-
if (created.length > 0 || body.context_md) await storage.regenerateIndex();
|
|
6052
6078
|
trackEvent("nest.publish", { nestId, count: created.length });
|
|
6053
6079
|
return c.json(
|
|
6054
6080
|
{
|
|
6055
6081
|
published: created.length,
|
|
6056
6082
|
context_md_updated: !!body.context_md,
|
|
6057
|
-
node_ids: created
|
|
6083
|
+
node_ids: created,
|
|
6084
|
+
skipped,
|
|
6085
|
+
failed
|
|
6058
6086
|
},
|
|
6059
6087
|
201
|
|
6060
6088
|
);
|
|
@@ -7664,6 +7692,13 @@ async function handleToolCall(toolName, args, ctx) {
|
|
|
7664
7692
|
try {
|
|
7665
7693
|
return await runTool(toolName, args, ctx);
|
|
7666
7694
|
} catch (err) {
|
|
7695
|
+
if (isVaultLockTimeout(err) || err instanceof VaultBusyError) {
|
|
7696
|
+
status = 503;
|
|
7697
|
+
return toolError(
|
|
7698
|
+
"The vault is busy with another write. Retry in a few seconds.",
|
|
7699
|
+
"VAULT_BUSY"
|
|
7700
|
+
);
|
|
7701
|
+
}
|
|
7667
7702
|
status = 500;
|
|
7668
7703
|
throw err;
|
|
7669
7704
|
} finally {
|
|
@@ -8554,7 +8589,7 @@ ${list}`,
|
|
|
8554
8589
|
if (!target) return "target is required (a node id or folder prefix).";
|
|
8555
8590
|
if (!["read", "write"].includes(role)) return "role must be read or write.";
|
|
8556
8591
|
try {
|
|
8557
|
-
const { createGrant: createGrant2 } = await import("./grants-service-
|
|
8592
|
+
const { createGrant: createGrant2 } = await import("./grants-service-CADI6LIB.js");
|
|
8558
8593
|
const db = (await import("./client-SW5I6ZBK.js")).getDb();
|
|
8559
8594
|
const { normalizeEmail: normalizeEmail2 } = await import("./email-R7DFS6E5.js");
|
|
8560
8595
|
const e = normalizeEmail2(String(args.email || ""));
|
|
@@ -12534,6 +12569,12 @@ function createApp() {
|
|
|
12534
12569
|
);
|
|
12535
12570
|
app.notFound((c) => c.json({ error: "Not found" }, 404));
|
|
12536
12571
|
app.onError((err, c) => {
|
|
12572
|
+
if (isVaultLockTimeout(err) || err instanceof VaultBusyError) {
|
|
12573
|
+
const busy = err instanceof VaultBusyError ? err : new VaultBusyError();
|
|
12574
|
+
return c.json({ error: busy.message }, 503, {
|
|
12575
|
+
"Retry-After": String(busy.retryAfterSeconds)
|
|
12576
|
+
});
|
|
12577
|
+
}
|
|
12537
12578
|
if (err instanceof AppError) {
|
|
12538
12579
|
return c.json({ error: err.message }, err.statusCode);
|
|
12539
12580
|
}
|
|
@@ -16,14 +16,14 @@ import {
|
|
|
16
16
|
requestDeletion,
|
|
17
17
|
submitForReview,
|
|
18
18
|
withdrawDeletionRequest
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-FBDEESNJ.js";
|
|
20
20
|
import {
|
|
21
21
|
canUserApprove
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-
|
|
24
|
-
import "./chunk-
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-3GMGLYTZ.js";
|
|
23
|
+
import "./chunk-GSYMJ3A4.js";
|
|
24
|
+
import "./chunk-BXUVIAMP.js";
|
|
25
|
+
import "./chunk-ENDHMQPD.js";
|
|
26
|
+
import "./chunk-YVMSM7LS.js";
|
|
27
27
|
import "./chunk-HYSTFMFG.js";
|
|
28
28
|
import "./chunk-YB3LKF7U.js";
|
|
29
29
|
import "./chunk-FRQJWGN3.js";
|
|
@@ -23,9 +23,9 @@ import {
|
|
|
23
23
|
syncFromConfig,
|
|
24
24
|
updateSteward,
|
|
25
25
|
updateStewardRole
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-
|
|
26
|
+
} from "./chunk-3GMGLYTZ.js";
|
|
27
|
+
import "./chunk-ENDHMQPD.js";
|
|
28
|
+
import "./chunk-YVMSM7LS.js";
|
|
29
29
|
import "./chunk-HYSTFMFG.js";
|
|
30
30
|
import "./chunk-YB3LKF7U.js";
|
|
31
31
|
import "./chunk-FRQJWGN3.js";
|
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
setApprovedVersion,
|
|
17
17
|
systemAuthor,
|
|
18
18
|
upsertVersion
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-BXUVIAMP.js";
|
|
20
|
+
import "./chunk-ENDHMQPD.js";
|
|
21
|
+
import "./chunk-YVMSM7LS.js";
|
|
22
22
|
import "./chunk-HYSTFMFG.js";
|
|
23
23
|
import "./chunk-YB3LKF7U.js";
|
|
24
24
|
import "./chunk-FRQJWGN3.js";
|