@hiai-gg/docsmint 0.6.8 → 0.7.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/README.md +20 -4
- package/backend/src/lib/api-keys.ts +14 -6
- package/backend/src/lib/lifecycle-service.ts +397 -73
- package/dist/backend/index.js +13038 -10864
- package/dist/backend-account-runtime-cleanup.js +152 -42
- package/dist/backend-api-key-facade.js +207 -61
- package/dist/backend-pipeline-cancellation.js +144 -42
- package/dist/client.d.ts +12 -2
- package/dist/client.js +83 -30
- package/dist/frontend/{CategoryDialog-CbXBMBZB.js → CategoryDialog-C67_TXf0.js} +4 -4
- package/dist/frontend/{ConfirmDialog-DgMTQBq4.js → ConfirmDialog-_LlrA--f.js} +3 -3
- package/dist/frontend/{CreateSnapshotDialog-FUq-ZfBH.js → CreateSnapshotDialog-BmCRpOMv.js} +3 -3
- package/dist/frontend/{DatePicker-D6E-EEtZ.js → DatePicker-DsoepNdb.js} +8 -8
- package/dist/frontend/{DeleteDialog-8k6JYWCx.js → DeleteDialog-L1A3FhMM.js} +1 -1
- package/dist/frontend/{FolderNode-DAAn_T8_.js → FolderNode-CNwi0ySr.js} +1 -1
- package/dist/frontend/{HiAiEditor-DSVG3GNd.js → HiAiEditor-B1EDGsnA.js} +6 -6
- package/dist/frontend/{SettingsDialog-BDNgf5rv.js → SettingsDialog-AP42xOGg.js} +12 -12
- package/dist/frontend/ShareDialog-wGTXuXFE.js +281 -0
- package/dist/frontend/{Sidebar-DX08utdV.js → Sidebar-lKQT3dEf.js} +17 -16
- package/dist/frontend/{TagCreateDialog-Bb0-Vtzh.js → TagCreateDialog-su8BhLzS.js} +3 -3
- package/dist/frontend/api/attachments.js +1 -1
- package/dist/frontend/api/settings.js +1 -1
- package/dist/frontend/app-shell.js +2 -2
- package/dist/frontend/{attachments-B8AuDjno.js → attachments-B2aH3hXF.js} +10 -9
- package/dist/frontend/{auth-client-Cygmp1I2.js → auth-client-CnDZwPfp.js} +11 -11
- package/dist/frontend/components/category-dialog.js +1 -1
- package/dist/frontend/components/create-snapshot-dialog.js +1 -1
- package/dist/frontend/components/delete-dialog.js +1 -1
- package/dist/frontend/components/editor/compact-editor.js +1 -1
- package/dist/frontend/components/editor/document-editor.js +1 -1
- package/dist/frontend/components/folder-node.js +1 -1
- package/dist/frontend/components/save-as-dialog.js +3 -3
- package/dist/frontend/components/settings.js +1 -1
- package/dist/frontend/components/share-dialog.d.ts +2 -1
- package/dist/frontend/components/share-dialog.js +1 -1
- package/dist/frontend/components/sidebar.js +1 -1
- package/dist/frontend/components/tag-create-dialog.js +1 -1
- package/dist/frontend/components/version-history.js +2 -2
- package/dist/frontend/{confirm-dialog-CzmoZw3a.js → confirm-dialog-BG8y2Pum.js} +4 -4
- package/dist/frontend/dashboard.js +1008 -998
- package/dist/frontend/{db-ByrlYfaI.js → db-Bo1t_76T.js} +1 -1
- package/dist/frontend/{dialog-Ce79C9fd.js → dialog-C2iKObEu.js} +7 -7
- package/dist/frontend/{dropdown-menu-CJ_7V3N0.js → dropdown-menu-BXIl2E26.js} +12 -12
- package/dist/frontend/{floating-layer-anchor-S5RSefGN.js → floating-layer-anchor-BGIndLY-.js} +63 -63
- package/dist/frontend/{identity-DyWeNzu_.js → identity-Ynrglr5i.js} +1 -1
- package/dist/frontend/{input-BWlOML_m.js → input-eHFb2qiL.js} +2 -2
- package/dist/frontend/{label-C2HfJNQ2.js → label-_I1iiaNU.js} +2 -2
- package/dist/frontend/offline/identity.js +1 -1
- package/dist/frontend/search.js +2 -2
- package/dist/frontend/{select-value-JCAp2PmU.js → select-value-CtMyrvDJ.js} +18 -18
- package/dist/frontend/{settings-DSrUl4hW.js → settings-BR48ihB4.js} +6 -23
- package/dist/frontend/{textarea-DOAE-h42.js → textarea-2eslfANY.js} +2 -2
- package/dist/frontend/{utils-BPDRytUU.js → utils-CDBqTgoV.js} +1 -1
- package/dist/frontend-ssr/api/attachments.js +1 -1
- package/dist/frontend-ssr/api/settings.js +1 -1
- package/dist/frontend-ssr/app-shell.js +2 -2
- package/dist/frontend-ssr/assets/{CategoryDialog-QHEv_9N4.js → CategoryDialog-BGuHTb3K.js} +4 -4
- package/dist/frontend-ssr/assets/{ConfirmDialog-BhAelejz.js → ConfirmDialog-D1BDXXll.js} +3 -3
- package/dist/frontend-ssr/assets/{CreateSnapshotDialog-CI8vXXcN.js → CreateSnapshotDialog-BZ45odvJ.js} +3 -3
- package/dist/frontend-ssr/assets/{DatePicker-D84cJ-Eq.js → DatePicker-CPtl6W5E.js} +3 -3
- package/dist/frontend-ssr/assets/{DeleteDialog-DG9Lm38J.js → DeleteDialog-oHT_p_vG.js} +1 -1
- package/dist/frontend-ssr/assets/{FolderNode-kmilhDjO.js → FolderNode-D9kgJG9d.js} +1 -1
- package/dist/frontend-ssr/assets/{HiAiEditor-CUOJmKzT.js → HiAiEditor-DOd2MXjD.js} +5 -5
- package/dist/frontend-ssr/assets/{SettingsDialog-BjJIiVLc.js → SettingsDialog-CIVbMKmf.js} +12 -12
- package/dist/frontend-ssr/assets/{ShareDialog-C9C-XTm4.js → ShareDialog-D2UNUbF7.js} +19 -6
- package/dist/frontend-ssr/assets/{Sidebar-C2sUfGNk.js → Sidebar-Bb-k2R-Z.js} +13 -12
- package/dist/frontend-ssr/assets/{TagCreateDialog-DUPMitlL.js → TagCreateDialog-6Gk7L3D-.js} +3 -3
- package/dist/frontend-ssr/assets/{attachments-Cj3fQyUp.js → attachments-BdkOp8ha.js} +5 -4
- package/dist/frontend-ssr/assets/{auth-client-x26kqY8Z.js → auth-client-CojKIzqy.js} +13 -13
- package/dist/frontend-ssr/assets/{confirm-dialog-XuyaL8sr.js → confirm-dialog-B9MVS_bF.js} +4 -4
- package/dist/frontend-ssr/assets/{db-CnxeO66n.js → db-BhwJPEkn.js} +1 -1
- package/dist/frontend-ssr/assets/{dialog-BOV1u6zP.js → dialog-1SB5neow.js} +8 -8
- package/dist/frontend-ssr/assets/{dropdown-menu-Dn_vQq9b.js → dropdown-menu-DqoOkdqB.js} +12 -12
- package/dist/frontend-ssr/assets/{floating-layer-anchor-BIAu-252.js → floating-layer-anchor-BoiiIEiK.js} +71 -71
- package/dist/frontend-ssr/assets/{identity-B3uHoDtf.js → identity-DcMMBKWg.js} +1 -1
- package/dist/frontend-ssr/assets/{input-DezGsU3y.js → input-Df-QP3Km.js} +2 -2
- package/dist/frontend-ssr/assets/{label-Bj8-TfFN.js → label-CbUOUz6L.js} +2 -2
- package/dist/frontend-ssr/assets/{select-value-DBhbkNcc.js → select-value-CXEDWrZg.js} +18 -18
- package/dist/frontend-ssr/assets/{settings-Bk5Hk9Vq.js → settings-Mp8EuFSn.js} +3 -21
- package/dist/frontend-ssr/assets/{textarea-Dev-qSEc.js → textarea-CHh8NuSS.js} +2 -2
- package/dist/frontend-ssr/assets/{utils-DtlPPXpJ.js → utils-DtX0ta7y.js} +1 -1
- package/dist/frontend-ssr/components/category-dialog.js +1 -1
- package/dist/frontend-ssr/components/create-snapshot-dialog.js +1 -1
- package/dist/frontend-ssr/components/delete-dialog.js +1 -1
- package/dist/frontend-ssr/components/editor/compact-editor.js +1 -1
- package/dist/frontend-ssr/components/editor/document-editor.js +1 -1
- package/dist/frontend-ssr/components/folder-node.js +1 -1
- package/dist/frontend-ssr/components/save-as-dialog.js +3 -3
- package/dist/frontend-ssr/components/settings.js +1 -1
- package/dist/frontend-ssr/components/share-dialog.js +1 -1
- package/dist/frontend-ssr/components/sidebar.js +1 -1
- package/dist/frontend-ssr/components/tag-create-dialog.js +1 -1
- package/dist/frontend-ssr/components/version-history.js +2 -2
- package/dist/frontend-ssr/dashboard.js +31 -29
- package/dist/frontend-ssr/offline/identity.js +1 -1
- package/dist/frontend-ssr/search.js +2 -2
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/lifecycle-persistent.d.ts +1 -1
- package/dist/lifecycle-runtime.js +52659 -338
- package/dist/mcp-cli.js +1056 -0
- package/dist/mcp-server.d.ts +39 -0
- package/dist/mcp-server.js +1053 -0
- package/dist/storage-quota.d.ts +5 -1
- package/dist/types.d.ts +7 -0
- package/dist/workspace.d.ts +11 -2
- package/dist/workspace.js +82 -10
- package/package.json +7 -13
- package/packages/cli/src/index.ts +1 -1
- package/packages/db/src/client.ts +56 -5
- package/packages/db/src/schema.ts +192 -1
- package/packages/db/src/with-tenant.ts +20 -2
- package/server.json +2 -2
- package/dist/frontend/ShareDialog-2Mty7hm4.js +0 -258
- package/packages/mcp-server/src/capabilities.ts +0 -189
- package/packages/mcp-server/src/client.ts +0 -225
- package/packages/mcp-server/src/index.ts +0 -8
- package/packages/mcp-server/src/server.ts +0 -87
- package/packages/mcp-server/src/tools/create-document.ts +0 -34
- package/packages/mcp-server/src/tools/create-folder.ts +0 -31
- package/packages/mcp-server/src/tools/create-snapshot.ts +0 -27
- package/packages/mcp-server/src/tools/export-document.ts +0 -22
- package/packages/mcp-server/src/tools/get-document.ts +0 -22
- package/packages/mcp-server/src/tools/list-documents.ts +0 -34
- package/packages/mcp-server/src/tools/list-folders.ts +0 -26
- package/packages/mcp-server/src/tools/search.ts +0 -39
- package/packages/mcp-server/src/tools/update-document.ts +0 -38
- package/packages/mcp-server/src/tools/version-history.ts +0 -27
- package/packages/mcp-server/src/types.ts +0 -126
package/dist/storage-quota.d.ts
CHANGED
|
@@ -67,7 +67,11 @@ export type AttachmentStorageQuotaFinalization = Readonly<{
|
|
|
67
67
|
}>;
|
|
68
68
|
/**
|
|
69
69
|
* OSS invokes this only after it has verified tenant context and document
|
|
70
|
-
* access.
|
|
70
|
+
* access. A host provider is never exposed to HTTP or browser code. Every
|
|
71
|
+
* method MUST be idempotent for `context.idempotencyKey`: repeated reserve
|
|
72
|
+
* returns the same logical reservation, repeated finalize has one charge, and
|
|
73
|
+
* repeated release is a successful no-op after the first release. The OSS
|
|
74
|
+
* durable upload/cleanup saga relies on this contract at crash boundaries.
|
|
71
75
|
*/
|
|
72
76
|
export type AttachmentStorageQuotaAdmission = Readonly<{
|
|
73
77
|
reserve(context: AttachmentStorageQuotaContext): Promise<Readonly<{
|
package/dist/types.d.ts
CHANGED
|
@@ -304,6 +304,8 @@ export interface DocsAttachmentPresignInput {
|
|
|
304
304
|
export interface DocsAttachmentPresignResponse {
|
|
305
305
|
url: string;
|
|
306
306
|
key: string;
|
|
307
|
+
/** Signed, exact admission identity required by confirmAttachment. */
|
|
308
|
+
uploadToken: string;
|
|
307
309
|
/**
|
|
308
310
|
* Opaque server-issued reservation. Present only when workspace storage
|
|
309
311
|
* enforcement is enabled and required verbatim by confirmAttachment.
|
|
@@ -314,6 +316,7 @@ export interface DocsAttachmentPresignResponse {
|
|
|
314
316
|
}
|
|
315
317
|
export interface DocsAttachmentConfirmInput extends DocsAttachmentPresignInput {
|
|
316
318
|
key: string;
|
|
319
|
+
uploadToken: string;
|
|
317
320
|
/** The opaque reservation returned by presignAttachment when present. */
|
|
318
321
|
quotaReservationId?: string;
|
|
319
322
|
}
|
|
@@ -434,4 +437,8 @@ export interface DocsRequestContext {
|
|
|
434
437
|
workspaceAssertion?: string;
|
|
435
438
|
headers?: HeadersInit;
|
|
436
439
|
signal?: AbortSignal;
|
|
440
|
+
/** Per-request timeout in milliseconds, overriding the client default. */
|
|
441
|
+
timeoutMs?: number;
|
|
442
|
+
/** Idempotency key forwarded as the standard Idempotency-Key header. */
|
|
443
|
+
idempotencyKey?: string;
|
|
437
444
|
}
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
/** Public, server-only workspace assertion contract. */
|
|
2
2
|
export declare const DOCSMINT_WORKSPACE_CONTEXT_HEADER = "x-docsmint-workspace-context";
|
|
3
|
-
export type
|
|
3
|
+
export type WorkspaceRole = "owner" | "admin" | "editor" | "viewer";
|
|
4
|
+
export type WorkspaceResourcePermission = "read" | "edit" | "write";
|
|
5
|
+
export type WorkspaceResourceScope = Readonly<{
|
|
6
|
+
kind: "category";
|
|
7
|
+
categoryId: string;
|
|
8
|
+
permissions: readonly WorkspaceResourcePermission[];
|
|
9
|
+
}>;
|
|
10
|
+
export type WorkspaceAssertionPayload = Readonly<{
|
|
4
11
|
actorUserId: string;
|
|
5
12
|
workspaceId: string;
|
|
6
|
-
actorRole:
|
|
13
|
+
actorRole: WorkspaceRole;
|
|
14
|
+
resourceScope?: WorkspaceResourceScope;
|
|
7
15
|
issuedAt: number;
|
|
8
16
|
expiresAt: number;
|
|
9
17
|
issuer: string;
|
|
10
18
|
}>;
|
|
19
|
+
export type DocsmintWorkspaceContext = WorkspaceAssertionPayload;
|
|
11
20
|
export type WorkspaceAssertionOptions = Readonly<{
|
|
12
21
|
secret: string;
|
|
13
22
|
issuer: string;
|
package/dist/workspace.js
CHANGED
|
@@ -4,6 +4,22 @@ const encoder = new TextEncoder();
|
|
|
4
4
|
const decoder = new TextDecoder();
|
|
5
5
|
export const DOCSMINT_WORKSPACE_ASSERTION_TTL_SECONDS = 60;
|
|
6
6
|
export const DOCSMINT_WORKSPACE_ASSERTION_CLOCK_SKEW_SECONDS = 5;
|
|
7
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
8
|
+
const CONTEXT_FIELDS = new Set([
|
|
9
|
+
"actorUserId",
|
|
10
|
+
"workspaceId",
|
|
11
|
+
"actorRole",
|
|
12
|
+
"resourceScope",
|
|
13
|
+
"issuedAt",
|
|
14
|
+
"expiresAt",
|
|
15
|
+
"issuer",
|
|
16
|
+
]);
|
|
17
|
+
const RESOURCE_SCOPE_FIELDS = new Set(["kind", "categoryId", "permissions"]);
|
|
18
|
+
const RESOURCE_PERMISSIONS = new Set([
|
|
19
|
+
"read",
|
|
20
|
+
"edit",
|
|
21
|
+
"write",
|
|
22
|
+
]);
|
|
7
23
|
function toBase64Url(bytes) {
|
|
8
24
|
let binary = "";
|
|
9
25
|
for (const byte of bytes)
|
|
@@ -26,11 +42,14 @@ async function sign(payload, secret) {
|
|
|
26
42
|
return toBase64Url(new Uint8Array(await crypto.subtle.sign("HMAC", key, encoder.encode(payload))));
|
|
27
43
|
}
|
|
28
44
|
function assertContext(value) {
|
|
29
|
-
if (!value || typeof value !== "object")
|
|
45
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
30
46
|
throw new Error("Invalid workspace assertion payload");
|
|
31
47
|
const context = value;
|
|
48
|
+
if (Object.keys(context).some((field) => !CONTEXT_FIELDS.has(field))) {
|
|
49
|
+
throw new Error("Invalid workspace assertion payload fields");
|
|
50
|
+
}
|
|
32
51
|
if (typeof context.actorUserId !== "string" ||
|
|
33
|
-
|
|
52
|
+
!UUID_PATTERN.test(context.actorUserId))
|
|
34
53
|
throw new Error("Invalid actorUserId");
|
|
35
54
|
if (typeof context.workspaceId !== "string" ||
|
|
36
55
|
!context.workspaceId.trim() ||
|
|
@@ -39,15 +58,69 @@ function assertContext(value) {
|
|
|
39
58
|
throw new Error("Invalid workspaceId");
|
|
40
59
|
if (!["owner", "admin", "editor", "viewer"].includes(context.actorRole))
|
|
41
60
|
throw new Error("Invalid actorRole");
|
|
61
|
+
if (context.resourceScope !== undefined) {
|
|
62
|
+
assertResourceScope(context.resourceScope);
|
|
63
|
+
}
|
|
42
64
|
if (!Number.isFinite(context.issuedAt) ||
|
|
43
65
|
!Number.isFinite(context.expiresAt) ||
|
|
44
66
|
typeof context.issuer !== "string" ||
|
|
45
67
|
!context.issuer)
|
|
46
68
|
throw new Error("Invalid workspace assertion timestamps or issuer");
|
|
47
69
|
}
|
|
70
|
+
function assertResourceScope(value) {
|
|
71
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
72
|
+
throw new Error("Invalid workspace resource scope");
|
|
73
|
+
}
|
|
74
|
+
const scope = value;
|
|
75
|
+
const fields = Object.keys(scope);
|
|
76
|
+
if (fields.length !== RESOURCE_SCOPE_FIELDS.size ||
|
|
77
|
+
fields.some((field) => !RESOURCE_SCOPE_FIELDS.has(field))) {
|
|
78
|
+
throw new Error("Invalid workspace resource scope fields");
|
|
79
|
+
}
|
|
80
|
+
if (scope.kind !== "category") {
|
|
81
|
+
throw new Error("Invalid workspace resource scope kind");
|
|
82
|
+
}
|
|
83
|
+
if (typeof scope.categoryId !== "string" ||
|
|
84
|
+
!UUID_PATTERN.test(scope.categoryId)) {
|
|
85
|
+
throw new Error("Invalid workspace resource categoryId");
|
|
86
|
+
}
|
|
87
|
+
if (!Array.isArray(scope.permissions) ||
|
|
88
|
+
Array.from(scope.permissions).some((permission) => typeof permission !== "string" ||
|
|
89
|
+
!RESOURCE_PERMISSIONS.has(permission))) {
|
|
90
|
+
throw new Error("Invalid workspace resource permissions");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function assertStaticLifetime(context) {
|
|
94
|
+
if (context.expiresAt <= context.issuedAt) {
|
|
95
|
+
throw new Error("Invalid workspace assertion lifetime");
|
|
96
|
+
}
|
|
97
|
+
if (context.expiresAt - context.issuedAt >
|
|
98
|
+
DOCSMINT_WORKSPACE_ASSERTION_TTL_SECONDS) {
|
|
99
|
+
throw new Error("Workspace assertion lifetime exceeds maximum TTL");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function immutableContext(context) {
|
|
103
|
+
const resourceScope = context.resourceScope
|
|
104
|
+
? Object.freeze({
|
|
105
|
+
kind: context.resourceScope.kind,
|
|
106
|
+
categoryId: context.resourceScope.categoryId,
|
|
107
|
+
permissions: Object.freeze([...context.resourceScope.permissions]),
|
|
108
|
+
})
|
|
109
|
+
: undefined;
|
|
110
|
+
return Object.freeze({
|
|
111
|
+
actorUserId: context.actorUserId,
|
|
112
|
+
workspaceId: context.workspaceId,
|
|
113
|
+
actorRole: context.actorRole,
|
|
114
|
+
...(resourceScope ? { resourceScope } : {}),
|
|
115
|
+
issuedAt: context.issuedAt,
|
|
116
|
+
expiresAt: context.expiresAt,
|
|
117
|
+
issuer: context.issuer,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
48
120
|
export async function createDocsmintWorkspaceAssertion(context, secret) {
|
|
49
121
|
assertContext(context);
|
|
50
|
-
|
|
122
|
+
assertStaticLifetime(context);
|
|
123
|
+
const payload = toBase64Url(encoder.encode(JSON.stringify(immutableContext(context))));
|
|
51
124
|
return `${payload}.${await sign(payload, secret)}`;
|
|
52
125
|
}
|
|
53
126
|
export async function verifyDocsmintWorkspaceAssertion(assertion, options) {
|
|
@@ -66,6 +139,7 @@ export async function verifyDocsmintWorkspaceAssertion(assertion, options) {
|
|
|
66
139
|
throw new Error("Invalid workspace assertion payload");
|
|
67
140
|
}
|
|
68
141
|
assertContext(context);
|
|
142
|
+
assertStaticLifetime(context);
|
|
69
143
|
if (context.issuer !== options.issuer)
|
|
70
144
|
throw new Error("Invalid workspace assertion issuer");
|
|
71
145
|
const now = options.nowSeconds ?? Math.floor(Date.now() / 1000);
|
|
@@ -75,11 +149,9 @@ export async function verifyDocsmintWorkspaceAssertion(assertion, options) {
|
|
|
75
149
|
skew > DOCSMINT_WORKSPACE_ASSERTION_CLOCK_SKEW_SECONDS) {
|
|
76
150
|
throw new Error("Invalid workspace assertion clock skew");
|
|
77
151
|
}
|
|
78
|
-
if (context.issuedAt > now + skew
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
throw new Error("Invalid workspace assertion lifetime");
|
|
84
|
-
return Object.freeze({ ...context });
|
|
152
|
+
if (context.issuedAt > now + skew)
|
|
153
|
+
throw new Error("Workspace assertion is not yet valid");
|
|
154
|
+
if (context.expiresAt <= now - skew)
|
|
155
|
+
throw new Error("Workspace assertion is expired");
|
|
156
|
+
return immutableContext(context);
|
|
85
157
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hiai-gg/docsmint",
|
|
3
3
|
"mcpName": "io.github.HiAi-gg/docsmint",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"browser": {
|
|
7
7
|
"./dist/backend-launcher.js": false,
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"types": "./dist/index.d.ts"
|
|
60
60
|
},
|
|
61
61
|
"./mcp": {
|
|
62
|
-
"import": "./
|
|
63
|
-
"types": "./
|
|
62
|
+
"import": "./dist/mcp-server.js",
|
|
63
|
+
"types": "./dist/mcp-server.d.ts"
|
|
64
64
|
},
|
|
65
65
|
"./lifecycle": {
|
|
66
66
|
"browser": "./dist/server-only-browser-entry.js",
|
|
@@ -339,9 +339,9 @@
|
|
|
339
339
|
},
|
|
340
340
|
"bin": {
|
|
341
341
|
"docsmint": "./packages/cli/src/index.ts",
|
|
342
|
-
"docsmint-mcp": "./
|
|
342
|
+
"docsmint-mcp": "./dist/mcp-cli.js",
|
|
343
343
|
"hiai-docs": "./packages/cli/src/index.ts",
|
|
344
|
-
"hiai-docs-mcp": "./
|
|
344
|
+
"hiai-docs-mcp": "./dist/mcp-cli.js"
|
|
345
345
|
},
|
|
346
346
|
"files": [
|
|
347
347
|
"dist",
|
|
@@ -353,12 +353,6 @@
|
|
|
353
353
|
"packages/cli/src/config.ts",
|
|
354
354
|
"packages/cli/src/format.ts",
|
|
355
355
|
"packages/cli/src/commands",
|
|
356
|
-
"packages/mcp-server/src/client.ts",
|
|
357
|
-
"packages/mcp-server/src/index.ts",
|
|
358
|
-
"packages/mcp-server/src/server.ts",
|
|
359
|
-
"packages/mcp-server/src/capabilities.ts",
|
|
360
|
-
"packages/mcp-server/src/types.ts",
|
|
361
|
-
"packages/mcp-server/src/tools",
|
|
362
356
|
"skills",
|
|
363
357
|
"backend/src/lib/redis-factory.ts",
|
|
364
358
|
"backend/src/lib/storage-factory.ts",
|
|
@@ -397,7 +391,7 @@
|
|
|
397
391
|
"postgres": "^3.4.9",
|
|
398
392
|
"@aws-sdk/client-s3": "^3.0.0",
|
|
399
393
|
"pino": "^10.0.0",
|
|
400
|
-
"@sveltejs/kit": "^2.
|
|
394
|
+
"@sveltejs/kit": "^2.70.3",
|
|
401
395
|
"svelte": "^5.56.4"
|
|
402
396
|
},
|
|
403
397
|
"peerDependenciesMeta": {
|
|
@@ -414,4 +408,4 @@
|
|
|
414
408
|
"optional": true
|
|
415
409
|
}
|
|
416
410
|
}
|
|
417
|
-
}
|
|
411
|
+
}
|
|
@@ -24,7 +24,7 @@ import { registerSearch } from './commands/search.js';
|
|
|
24
24
|
import { registerSnapshot } from './commands/snapshot.js';
|
|
25
25
|
import { registerUpdate } from './commands/update.js';
|
|
26
26
|
|
|
27
|
-
const VERSION = '0.
|
|
27
|
+
const VERSION = '0.7.0';
|
|
28
28
|
|
|
29
29
|
const program = new Command();
|
|
30
30
|
program.name('hiai-docs').description('CLI for the hiai-docs knowledge base').version(VERSION);
|
|
@@ -5,16 +5,67 @@ import postgres from "postgres";
|
|
|
5
5
|
export type Schema = typeof schema;
|
|
6
6
|
export type Database = PostgresJsDatabase<Schema>;
|
|
7
7
|
|
|
8
|
+
export type DatabaseQueryObservation = Readonly<{
|
|
9
|
+
query: string;
|
|
10
|
+
}>;
|
|
11
|
+
|
|
12
|
+
export type DatabaseQueryObserver = (
|
|
13
|
+
observation: DatabaseQueryObservation,
|
|
14
|
+
) => void;
|
|
15
|
+
|
|
16
|
+
function observeDatabaseQuery(
|
|
17
|
+
observer: DatabaseQueryObserver | undefined,
|
|
18
|
+
query: string,
|
|
19
|
+
): void {
|
|
20
|
+
if (!observer) return;
|
|
21
|
+
try {
|
|
22
|
+
observer(Object.freeze({ query }));
|
|
23
|
+
} catch {
|
|
24
|
+
// Query observation is diagnostic only. Observer bugs must never affect the
|
|
25
|
+
// database protocol, application result, or error surface.
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type DatabaseClientOptions = Readonly<{
|
|
30
|
+
max?: number;
|
|
31
|
+
idleTimeout?: number;
|
|
32
|
+
connectTimeout?: number;
|
|
33
|
+
/** Explicit client-local test hook. Omitted clients install no debug callback. */
|
|
34
|
+
queryObserver?: DatabaseQueryObserver;
|
|
35
|
+
}>;
|
|
36
|
+
|
|
37
|
+
export function createDatabaseClient(
|
|
38
|
+
databaseUrl: string,
|
|
39
|
+
options: DatabaseClientOptions = {},
|
|
40
|
+
) {
|
|
41
|
+
const sqlClient = postgres(databaseUrl, {
|
|
42
|
+
max: options.max ?? 20,
|
|
43
|
+
idle_timeout: options.idleTimeout ?? 30,
|
|
44
|
+
connect_timeout: options.connectTimeout ?? 10,
|
|
45
|
+
...(options.queryObserver
|
|
46
|
+
? {
|
|
47
|
+
debug: (_connection: number, query: string) => {
|
|
48
|
+
observeDatabaseQuery(options.queryObserver, query);
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
: {}),
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
client: sqlClient,
|
|
55
|
+
db: drizzle(sqlClient, { schema }) as Database,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
8
59
|
const databaseUrl =
|
|
9
60
|
process.env.DATABASE_URL ||
|
|
10
61
|
"postgresql://hiai_app:changeme@localhost:5437/hiai_docs";
|
|
11
62
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
connect_timeout: 10,
|
|
63
|
+
const database = createDatabaseClient(databaseUrl, {
|
|
64
|
+
// Production deliberately owns no query observer. Contract tests create an
|
|
65
|
+
// explicit client-local observer and close that client after each capture.
|
|
16
66
|
});
|
|
17
67
|
|
|
18
|
-
|
|
68
|
+
const client = database.client;
|
|
69
|
+
export const db: Database = database.db;
|
|
19
70
|
|
|
20
71
|
export { client };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { pgTable, uuid, text, timestamp, bigint, jsonb, index, uniqueIndex, customType, boolean, check, integer, pgEnum, type AnyPgColumn } from "drizzle-orm/pg-core";
|
|
1
|
+
import { pgTable, uuid, text, timestamp, bigint, jsonb, index, uniqueIndex, customType, boolean, check, integer, pgEnum, primaryKey, type AnyPgColumn } from "drizzle-orm/pg-core";
|
|
2
2
|
|
|
3
3
|
// pgvector vector type — maps to PostgreSQL vector(n) column
|
|
4
4
|
const vector = customType<{
|
|
@@ -226,6 +226,7 @@ export const documents = pgTable(
|
|
|
226
226
|
activeEmbeddingGeneration: uuid("active_embedding_generation"),
|
|
227
227
|
pendingEmbeddingGeneration: uuid("pending_embedding_generation"),
|
|
228
228
|
embeddingProfile: text("embedding_profile"),
|
|
229
|
+
embeddingContextHash: text("embedding_context_hash"),
|
|
229
230
|
embeddingErrorCode: text("embedding_error_code"),
|
|
230
231
|
embeddingUpdatedAt: timestamp("embedding_updated_at"),
|
|
231
232
|
/** Soft-delete marker. Trashed documents remain tenant-scoped until purge. */
|
|
@@ -281,6 +282,8 @@ export const documentPipelineRuns = pgTable(
|
|
|
281
282
|
generationId: uuid("generation_id").notNull(),
|
|
282
283
|
revision: text("revision").notNull(),
|
|
283
284
|
source: text("source").notNull(),
|
|
285
|
+
embeddingContextHash: text("embedding_context_hash"),
|
|
286
|
+
refreshMode: text("refresh_mode").notNull().default("full"),
|
|
284
287
|
status: pipelineStatusEnum("status").notNull().default("pending"),
|
|
285
288
|
prepareStatus: pipelineStatusEnum("prepare_status").notNull().default("pending"),
|
|
286
289
|
embedStatus: pipelineStatusEnum("embed_status").notNull().default("pending"),
|
|
@@ -310,6 +313,10 @@ export const documentPipelineRuns = pgTable(
|
|
|
310
313
|
table.status,
|
|
311
314
|
table.updatedAt,
|
|
312
315
|
),
|
|
316
|
+
check(
|
|
317
|
+
"document_pipeline_runs_refresh_mode_check",
|
|
318
|
+
sql`${table.refreshMode} in ('incremental', 'full')`,
|
|
319
|
+
),
|
|
313
320
|
],
|
|
314
321
|
);
|
|
315
322
|
|
|
@@ -354,6 +361,41 @@ export const documentPipelineBatches = pgTable(
|
|
|
354
361
|
],
|
|
355
362
|
);
|
|
356
363
|
|
|
364
|
+
// ============================================
|
|
365
|
+
// metadata_reembed_outbox -- exact metadata-impact snapshots
|
|
366
|
+
// ============================================
|
|
367
|
+
export const metadataReembedOutbox = pgTable(
|
|
368
|
+
"metadata_reembed_outbox",
|
|
369
|
+
{
|
|
370
|
+
// The outbox row id is also the deterministic pipeline generation id.
|
|
371
|
+
id: uuid("id").primaryKey(),
|
|
372
|
+
operationId: uuid("operation_id").notNull(),
|
|
373
|
+
documentId: uuid("document_id")
|
|
374
|
+
.notNull()
|
|
375
|
+
.references(() => documents.id, { onDelete: "cascade" }),
|
|
376
|
+
ownerId: uuid("owner_id")
|
|
377
|
+
.notNull()
|
|
378
|
+
.references(() => users.id, { onDelete: "cascade" }),
|
|
379
|
+
workspaceId: text("workspace_id"),
|
|
380
|
+
revision: text("revision").notNull(),
|
|
381
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
382
|
+
},
|
|
383
|
+
(table) => [
|
|
384
|
+
uniqueIndex("metadata_reembed_outbox_operation_document_idx").on(
|
|
385
|
+
table.operationId,
|
|
386
|
+
table.documentId,
|
|
387
|
+
),
|
|
388
|
+
index("metadata_reembed_outbox_operation_id_idx").on(
|
|
389
|
+
table.operationId,
|
|
390
|
+
table.id,
|
|
391
|
+
),
|
|
392
|
+
index("metadata_reembed_outbox_created_id_idx").on(
|
|
393
|
+
table.createdAt,
|
|
394
|
+
table.id,
|
|
395
|
+
),
|
|
396
|
+
],
|
|
397
|
+
);
|
|
398
|
+
|
|
357
399
|
// ============================================
|
|
358
400
|
// document_knowledge_summaries — generation-scoped retrieval metadata
|
|
359
401
|
// ============================================
|
|
@@ -575,6 +617,9 @@ export const attachments = pgTable(
|
|
|
575
617
|
.notNull()
|
|
576
618
|
.references(() => documents.id, { onDelete: "cascade" }),
|
|
577
619
|
workspaceId: text("workspace_id"),
|
|
620
|
+
uploadedBy: uuid("uploaded_by")
|
|
621
|
+
.notNull()
|
|
622
|
+
.references(() => users.id, { onDelete: "restrict" }),
|
|
578
623
|
filename: text("filename").notNull(),
|
|
579
624
|
mimeType: text("mime_type").notNull(),
|
|
580
625
|
size: bigint("size", { mode: "number" }).notNull(),
|
|
@@ -583,10 +628,156 @@ export const attachments = pgTable(
|
|
|
583
628
|
},
|
|
584
629
|
(table) => [
|
|
585
630
|
index("attachments_document_id_idx").on(table.documentId),
|
|
631
|
+
index("attachments_uploaded_by_idx").on(table.uploadedBy),
|
|
586
632
|
uniqueIndex("attachments_storage_key_unique").on(table.storageKey),
|
|
587
633
|
]
|
|
588
634
|
);
|
|
589
635
|
|
|
636
|
+
// A direct upload URL can outlive the request that created it. Keeping the
|
|
637
|
+
// exact actor/key/expiry admission durable lets confirmation authenticate the
|
|
638
|
+
// key after session/document disappearance and lets account purge wait through
|
|
639
|
+
// the unrevocable URL lifetime before deleting the exact object.
|
|
640
|
+
export const pendingAttachmentUploads = pgTable(
|
|
641
|
+
"pending_attachment_uploads",
|
|
642
|
+
{
|
|
643
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
644
|
+
documentId: uuid("document_id")
|
|
645
|
+
.notNull()
|
|
646
|
+
.references(() => documents.id, { onDelete: "restrict" }),
|
|
647
|
+
actorUserId: uuid("actor_user_id")
|
|
648
|
+
.notNull()
|
|
649
|
+
.references(() => users.id, { onDelete: "restrict" }),
|
|
650
|
+
workspaceId: text("workspace_id"),
|
|
651
|
+
storageKey: text("storage_key").notNull(),
|
|
652
|
+
tokenHash: text("token_hash").notNull(),
|
|
653
|
+
filename: text("filename").notNull(),
|
|
654
|
+
mimeType: text("mime_type").notNull(),
|
|
655
|
+
declaredSize: bigint("declared_size", { mode: "number" }).notNull(),
|
|
656
|
+
quotaReservationId: text("quota_reservation_id"),
|
|
657
|
+
quotaOperationKey: text("quota_operation_key").notNull(),
|
|
658
|
+
quotaState: text("quota_state").notNull(),
|
|
659
|
+
actualSize: bigint("actual_size", { mode: "number" }),
|
|
660
|
+
urlIssuedAt: timestamp("url_issued_at"),
|
|
661
|
+
confirmingAt: timestamp("confirming_at"),
|
|
662
|
+
leaseOwner: text("lease_owner"),
|
|
663
|
+
leaseExpiresAt: timestamp("lease_expires_at"),
|
|
664
|
+
attemptCount: integer("attempt_count").default(0).notNull(),
|
|
665
|
+
lastError: text("last_error"),
|
|
666
|
+
expiresAt: timestamp("expires_at").notNull(),
|
|
667
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
668
|
+
},
|
|
669
|
+
(table) => [
|
|
670
|
+
uniqueIndex("pending_attachment_uploads_storage_key_unique").on(table.storageKey),
|
|
671
|
+
uniqueIndex("pending_attachment_uploads_token_hash_unique").on(table.tokenHash),
|
|
672
|
+
index("pending_attachment_uploads_actor_expiry_idx").on(
|
|
673
|
+
table.actorUserId,
|
|
674
|
+
table.expiresAt,
|
|
675
|
+
),
|
|
676
|
+
index("pending_attachment_uploads_document_idx").on(table.documentId),
|
|
677
|
+
index("pending_attachment_uploads_cleanup_lease_idx").on(
|
|
678
|
+
table.expiresAt,
|
|
679
|
+
table.leaseExpiresAt,
|
|
680
|
+
table.id,
|
|
681
|
+
),
|
|
682
|
+
check(
|
|
683
|
+
"pending_attachment_uploads_quota_state_check",
|
|
684
|
+
sql`${table.quotaState} IN ('not_required', 'reserve_pending', 'reserved', 'finalize_pending', 'committed')`,
|
|
685
|
+
),
|
|
686
|
+
],
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
// DB-authoritative intents for object removal and quota release. Source rows
|
|
690
|
+
// are deleted in the same transaction that inserts an intent; S3 and quota
|
|
691
|
+
// effects happen only after commit and remain recoverable across crashes.
|
|
692
|
+
export const attachmentStorageCleanupOutbox = pgTable(
|
|
693
|
+
"attachment_storage_cleanup_outbox",
|
|
694
|
+
{
|
|
695
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
696
|
+
sourceKind: text("source_kind").notNull(),
|
|
697
|
+
sourceId: uuid("source_id").notNull(),
|
|
698
|
+
storageKey: text("storage_key").notNull(),
|
|
699
|
+
documentId: uuid("document_id").notNull(),
|
|
700
|
+
actorUserId: uuid("actor_user_id").notNull(),
|
|
701
|
+
ownerUserId: uuid("owner_user_id").notNull(),
|
|
702
|
+
requestedByUserId: uuid("requested_by_user_id").notNull(),
|
|
703
|
+
workspaceId: text("workspace_id"),
|
|
704
|
+
size: bigint("size", { mode: "number" }).notNull(),
|
|
705
|
+
quotaOperationKey: text("quota_operation_key").notNull(),
|
|
706
|
+
quotaReleaseKind: text("quota_release_kind").default("none").notNull(),
|
|
707
|
+
quotaReservationId: text("quota_reservation_id"),
|
|
708
|
+
notBefore: timestamp("not_before").defaultNow().notNull(),
|
|
709
|
+
retainUntil: timestamp("retain_until"),
|
|
710
|
+
objectDeletedAt: timestamp("object_deleted_at"),
|
|
711
|
+
leaseOwner: text("lease_owner"),
|
|
712
|
+
leaseExpiresAt: timestamp("lease_expires_at"),
|
|
713
|
+
attemptCount: integer("attempt_count").default(0).notNull(),
|
|
714
|
+
lastError: text("last_error"),
|
|
715
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
716
|
+
},
|
|
717
|
+
(table) => [
|
|
718
|
+
uniqueIndex("attachment_storage_cleanup_outbox_source_unique").on(
|
|
719
|
+
table.sourceKind,
|
|
720
|
+
table.sourceId,
|
|
721
|
+
),
|
|
722
|
+
uniqueIndex("attachment_storage_cleanup_outbox_storage_key_unique").on(
|
|
723
|
+
table.storageKey,
|
|
724
|
+
),
|
|
725
|
+
index("attachment_storage_cleanup_outbox_ready_idx").on(
|
|
726
|
+
table.notBefore,
|
|
727
|
+
table.leaseExpiresAt,
|
|
728
|
+
table.createdAt,
|
|
729
|
+
table.id,
|
|
730
|
+
),
|
|
731
|
+
index("attachment_storage_cleanup_outbox_actor_idx").on(
|
|
732
|
+
table.actorUserId,
|
|
733
|
+
table.id,
|
|
734
|
+
),
|
|
735
|
+
index("attachment_storage_cleanup_outbox_owner_idx").on(
|
|
736
|
+
table.ownerUserId,
|
|
737
|
+
table.id,
|
|
738
|
+
),
|
|
739
|
+
index("attachment_storage_cleanup_outbox_requester_idx").on(
|
|
740
|
+
table.requestedByUserId,
|
|
741
|
+
table.id,
|
|
742
|
+
),
|
|
743
|
+
check(
|
|
744
|
+
"attachment_storage_cleanup_outbox_source_kind_check",
|
|
745
|
+
sql`${table.sourceKind} IN ('attachment', 'pending_upload', 'uncommitted_upload')`,
|
|
746
|
+
),
|
|
747
|
+
check(
|
|
748
|
+
"attachment_storage_cleanup_outbox_quota_kind_check",
|
|
749
|
+
sql`${table.quotaReleaseKind} IN ('none', 'reserve_pending', 'reservation', 'finalize_pending', 'committed')`,
|
|
750
|
+
),
|
|
751
|
+
check("attachment_storage_cleanup_outbox_size_check", sql`${table.size} >= 0`),
|
|
752
|
+
check(
|
|
753
|
+
"attachment_storage_cleanup_outbox_reservation_check",
|
|
754
|
+
sql`${table.quotaReleaseKind} NOT IN ('reservation', 'finalize_pending') OR ${table.quotaReservationId} IS NOT NULL`,
|
|
755
|
+
),
|
|
756
|
+
],
|
|
757
|
+
);
|
|
758
|
+
|
|
759
|
+
// Internal transaction-bound proof used only by the narrow signed-admission
|
|
760
|
+
// abandonment SECURITY DEFINER function. The runtime role has no table grants.
|
|
761
|
+
export const pendingAttachmentCleanupAuthorizations = pgTable(
|
|
762
|
+
"pending_attachment_cleanup_authorizations",
|
|
763
|
+
{
|
|
764
|
+
backendPid: integer("backend_pid").notNull(),
|
|
765
|
+
transactionId: bigint("transaction_id", { mode: "bigint" }).notNull(),
|
|
766
|
+
admissionId: uuid("admission_id").notNull(),
|
|
767
|
+
documentId: uuid("document_id").notNull(),
|
|
768
|
+
actorUserId: uuid("actor_user_id").notNull(),
|
|
769
|
+
ownerUserId: uuid("owner_user_id").notNull(),
|
|
770
|
+
workspaceId: text("workspace_id"),
|
|
771
|
+
storageKey: text("storage_key").notNull(),
|
|
772
|
+
tokenHash: text("token_hash").notNull(),
|
|
773
|
+
},
|
|
774
|
+
(table) => [
|
|
775
|
+
primaryKey({
|
|
776
|
+
columns: [table.backendPid, table.transactionId, table.admissionId],
|
|
777
|
+
}),
|
|
778
|
+
],
|
|
779
|
+
);
|
|
780
|
+
|
|
590
781
|
export const attachmentRelations = relations(attachments, ({ one }) => ({
|
|
591
782
|
document: one(documents, {
|
|
592
783
|
fields: [attachments.documentId],
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { sql } from "drizzle-orm";
|
|
2
|
-
import {
|
|
2
|
+
import { type Database, db } from "./client";
|
|
3
|
+
|
|
4
|
+
export type WorkspaceResourcePermission = "read" | "edit" | "write";
|
|
5
|
+
export type WorkspaceResourceScope = Readonly<{
|
|
6
|
+
kind: "category";
|
|
7
|
+
categoryId: string;
|
|
8
|
+
permissions: readonly WorkspaceResourcePermission[];
|
|
9
|
+
}>;
|
|
3
10
|
|
|
4
11
|
/** A transaction carrying the same query surface as the tenant-scoped DB. */
|
|
5
12
|
export type TenantTransaction = Parameters<
|
|
@@ -44,6 +51,8 @@ export interface TenantContext {
|
|
|
44
51
|
workspaceId?: string;
|
|
45
52
|
source?: "personal" | "external";
|
|
46
53
|
actorRole?: "owner" | "admin" | "editor" | "viewer";
|
|
54
|
+
/** Resource restriction copied from a verified external assertion. */
|
|
55
|
+
resourceScope?: WorkspaceResourceScope;
|
|
47
56
|
/** Unix timestamp from a verified external workspace assertion. */
|
|
48
57
|
assertionExpiresAt?: number;
|
|
49
58
|
}
|
|
@@ -99,7 +108,16 @@ export async function withTenant<T>(
|
|
|
99
108
|
ctx: TenantContext,
|
|
100
109
|
fn: (tx: Parameters<Parameters<typeof db.transaction>[0]>[0]) => Promise<T>,
|
|
101
110
|
): Promise<T> {
|
|
102
|
-
return db
|
|
111
|
+
return withTenantDatabase(db, ctx, fn);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Execute the canonical tenant transaction against an explicitly owned client. */
|
|
115
|
+
export async function withTenantDatabase<T>(
|
|
116
|
+
database: Database,
|
|
117
|
+
ctx: TenantContext,
|
|
118
|
+
fn: (tx: TenantTransaction) => Promise<T>,
|
|
119
|
+
): Promise<T> {
|
|
120
|
+
return database.transaction(async (tx) => {
|
|
103
121
|
await tx.execute(
|
|
104
122
|
sql`SELECT set_config('app.current_user_id', ${ctx.userId}, true)`,
|
|
105
123
|
);
|
package/server.json
CHANGED
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"source": "github",
|
|
9
9
|
"id": "1249550690"
|
|
10
10
|
},
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.7.0",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "@hiai-gg/docsmint",
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.7.0",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
},
|