mcp-scraper 0.28.3 → 0.29.1
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 +1 -1
- package/dist/bin/api-server.cjs +87 -23
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +31 -16
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/chunk-63PP32WV.js +7 -0
- package/dist/chunk-63PP32WV.js.map +1 -0
- package/dist/{chunk-2W4RWWXL.js → chunk-HVQR7VAE.js} +32 -17
- package/dist/chunk-HVQR7VAE.js.map +1 -0
- package/dist/{server-53OTA5HA.js → server-F3I77L26.js} +59 -10
- package/dist/{server-53OTA5HA.js.map → server-F3I77L26.js.map} +1 -1
- package/docs/mcp-tool-manifest.generated.json +14 -14
- package/package.json +2 -2
- package/dist/chunk-2W4RWWXL.js.map +0 -1
- package/dist/chunk-EMF4W6QM.js +0 -7
- package/dist/chunk-EMF4W6QM.js.map +0 -1
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ Build the branded one-click bundle:
|
|
|
88
88
|
npm run build:mcpb
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.
|
|
91
|
+
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.29.1`, SHA-256 `837b6d05ce5bd0d7f104616d4781c3b33216bd4901887995e62a8e456c2b8804`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, and API-key configuration field from the bundle manifest.
|
|
92
92
|
|
|
93
93
|
The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
|
|
94
94
|
|
package/dist/bin/api-server.cjs
CHANGED
|
@@ -29723,7 +29723,7 @@ var PACKAGE_VERSION;
|
|
|
29723
29723
|
var init_version = __esm({
|
|
29724
29724
|
"src/version.ts"() {
|
|
29725
29725
|
"use strict";
|
|
29726
|
-
PACKAGE_VERSION = "0.
|
|
29726
|
+
PACKAGE_VERSION = "0.29.1";
|
|
29727
29727
|
}
|
|
29728
29728
|
});
|
|
29729
29729
|
|
|
@@ -29845,12 +29845,14 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
|
|
|
29845
29845
|
|
|
29846
29846
|
## Memory
|
|
29847
29847
|
mcp-scraper also exposes persistent per-user memory tools (notes, facts, vaults,
|
|
29848
|
-
scheduled actions, tables, channels) backed by memory.mcpscraper.dev. Every account starts with
|
|
29848
|
+
scheduled actions, tables, channels) backed by memory.mcpscraper.dev. Every account starts with 15
|
|
29849
29849
|
vaults \u2014 call **list-vaults** to see what exists before creating anything new. Pick the vault whose job
|
|
29850
29850
|
matches the content: **Ideas** (unvalidated concepts), **Knowledge** (distilled lessons/how-tos),
|
|
29851
29851
|
**Library** (raw source material \u2014 articles, transcripts), **People** (one durable note per person/org),
|
|
29852
|
-
**
|
|
29853
|
-
|
|
29852
|
+
**Deals** (commercial opportunities tied to a known person or organization), **Communications** (individual
|
|
29853
|
+
conversation records and drafts), **Calendar** (time-anchored entries), **Tasks** (independent Inbox action items
|
|
29854
|
+
that may link to a known Project), **Projects** (only codebases, known client projects, personal projects, or ongoing siloed
|
|
29855
|
+
workstreams), **Issues** (something broken),
|
|
29854
29856
|
**Improvement Log** (receipts of changes made and whether they worked), **Experiments** (hypothesis +
|
|
29855
29857
|
measured result), **Sprint** (current cycle's scope), **Inspiration** (other people's work worth
|
|
29856
29858
|
studying), **Skills** (reusable skill packages; each requires \`scripts/\` and at least one of
|
|
@@ -29864,6 +29866,19 @@ deliberate edits and migrations. Use
|
|
|
29864
29866
|
they'll filter/sort by exact value. **memory-search** is meaning-based over full content (embeds, slower);
|
|
29865
29867
|
**memory-list** filters one vault by kind/tags (fast, exact).
|
|
29866
29868
|
|
|
29869
|
+
For People, Deals, Projects, Tasks, and Communications, use the returned contract rather than guessing:
|
|
29870
|
+
People only holds a real person or organization hub. Its contact card uses \`phone\`, \`text_phone\`, and
|
|
29871
|
+
\`email\` for Call/Text/Email; \`memories\` for durable person context; and linked Deals, Projects,
|
|
29872
|
+
Communications, and Calendar records for the other sections. Deals need a known party; Projects need
|
|
29873
|
+
\`project_kind\`; Tasks can be independent Inbox todos or link a verified \`project_ref\` and matching
|
|
29874
|
+
project name; and email drafts awaiting human review need \`direction:"draft"\` with
|
|
29875
|
+
\`approval_state:"pending"\`. Link a known person, project, deal, or communication only when verified.
|
|
29876
|
+
When the user asks to add Gmail or Google Calendar evidence from a connected account, first resolve the
|
|
29877
|
+
existing People hub. Persist Gmail as one linked **Communications** email and Calendar as one linked
|
|
29878
|
+
**Calendar** event, each with the provider's stable reference and \`person_refs\`; do not create a person
|
|
29879
|
+
from a subject line, infer attendees, or silently bulk-import a mailbox/calendar. If a relationship is requested but not clear, ask the user rather than inventing one. Overview is the review queue: editing leaves a draft pending, and
|
|
29880
|
+
approval or denial records a state only\u2014it does not send email.
|
|
29881
|
+
|
|
29867
29882
|
Treat every memory create or update as a graph operation. **prepare-memory-write** supplies the initial
|
|
29868
29883
|
shortlist; use **memory-search** when it is weak or the topic is broad, and **memory-get** to read the best
|
|
29869
29884
|
candidates in full. Add only links supported by the notes: same-
|
|
@@ -32316,7 +32331,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
32316
32331
|
}, async (input) => buildMetaAdCreativeMediaResult(executor, input));
|
|
32317
32332
|
server.registerTool("import_service_connection_to_memory", {
|
|
32318
32333
|
title: "Import Connected Service Snapshot to Memory",
|
|
32319
|
-
description: "Run exactly one bounded, approved read on a tenant-owned connected service and upsert the redacted result into an existing ordinary Memory vault at a server-generated stable path. The saved document is embedded for RAG and marked as untrusted provider data, never instructions. This is a one-result snapshot: it does not paginate, bulk-import an account, continuously sync changes, propagate deletions, or create normalized tables. Use list_service_connections first and supply an exact current readTools entry; action and admin tools are rejected.",
|
|
32334
|
+
description: "Run exactly one bounded, approved read on a tenant-owned connected service and upsert the redacted result into an existing ordinary Memory vault at a server-generated stable path. The saved document is embedded for RAG and marked as untrusted provider data, never instructions. This is a one-result snapshot: it does not paginate, bulk-import an account, continuously sync changes, propagate deletions, or create normalized tables. It is not a People contact-card activity importer: when the user asks to add verified Gmail or Calendar activity to a person, resolve the People hub and create a linked Communications or Calendar record with stable provider references instead. Use list_service_connections first and supply an exact current readTools entry; action and admin tools are rejected.",
|
|
32320
32335
|
inputSchema: ImportServiceConnectionToMemoryInputSchema,
|
|
32321
32336
|
outputSchema: recordOutputSchema("import_service_connection_to_memory", ImportServiceConnectionToMemoryOutputSchema),
|
|
32322
32337
|
annotations: { title: "Import Connected Service Snapshot to Memory", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
@@ -34939,7 +34954,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
34939
34954
|
MemoryCaptureSchema = {
|
|
34940
34955
|
id: "memory-capture",
|
|
34941
34956
|
upstreamName: "memoryCaptureTool",
|
|
34942
|
-
description: "Strict normal-create path for durable memory. Before capture, list the complete tag vocabulary, call prepare-memory-write, run hybrid memory-search for related notes, and read the strongest link candidates. This tool refuses incomplete notes, writes through memory-put, registers canonical tags, and verifies persisted content and props. Reserve memory-put for low-level migrations or deliberate edits.",
|
|
34957
|
+
description: "Strict normal-create path for durable memory. Before capture, list the complete tag vocabulary, call prepare-memory-write, run hybrid memory-search for related notes, and read the strongest link candidates. This tool refuses incomplete notes and invalid relationship-domain writes: projects need a project kind, tasks can be independent Inbox todos or link a verified project, deals need a known party, and draft emails need a pending approval state. It writes through memory-put, registers canonical tags, and verifies persisted content and props. Reserve memory-put for low-level migrations or deliberate edits.",
|
|
34943
34958
|
input: {
|
|
34944
34959
|
vault: import_zod37.z.string(),
|
|
34945
34960
|
folder: import_zod37.z.string().optional(),
|
|
@@ -34997,7 +35012,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
34997
35012
|
PrepareMemoryWriteSchema = {
|
|
34998
35013
|
id: "prepare-memory-write",
|
|
34999
35014
|
upstreamName: "prepareMemoryWriteTool",
|
|
35000
|
-
description: "Mandatory planning pass for a normal new memory. First inspect the complete tag vocabulary with list-memory-tags; then this pass routes the note, returns the live template and natural vault relationships, resolves proposed tags, and shortlists interlinks. Use hybrid memory-search (3 focused queries, 50 fused candidates, bounded graph expansion, rerank to 30 by default) and read strong related notes before capture. This is an explicit AI workflow directive, not a claim of persisted call-order enforcement.",
|
|
35015
|
+
description: "Mandatory planning pass for a normal new memory. First inspect the complete tag vocabulary with list-memory-tags; then this pass routes the note, returns the live template and natural vault relationships, resolves proposed tags, and shortlists interlinks. For People, Deals, Projects, Tasks, and Communications, it also returns relationship and approval guidance: a Task may be an independent Inbox todo, so search existing records only before adding a requested project or party link and never invent one. Use hybrid memory-search (3 focused queries, 50 fused candidates, bounded graph expansion, rerank to 30 by default) and read strong related notes before capture. This is an explicit AI workflow directive, not a claim of persisted call-order enforcement.",
|
|
35001
35016
|
input: {
|
|
35002
35017
|
title: import_zod37.z.string().min(1),
|
|
35003
35018
|
content: import_zod37.z.string().min(1),
|
|
@@ -35704,10 +35719,10 @@ var init_memory_tool_schemas = __esm({
|
|
|
35704
35719
|
PutSchema = {
|
|
35705
35720
|
id: "memory-put",
|
|
35706
35721
|
upstreamName: "putTool",
|
|
35707
|
-
description: "Create or edit one note at a path in a memory vault; content is persisted and indexed for search. For row-shaped datasets you'll filter/sort by exact value, use table-create/table-insert-rows/table-query instead. Ordinary vaults are indexed and shareable \u2014 never store real secrets there; use a secure vault (create-secure-vault) instead, which is never indexed or shareable and is encrypted at rest. Requires write scope.",
|
|
35722
|
+
description: "Create or deliberately edit one note at a path in a memory vault; content is persisted and indexed for search. For normal new People, Deals, Projects, Tasks, or Communications records, use prepare-memory-write then memory-capture: People must be real people or organizations, Deals need a known party, Projects need a supported kind, Tasks may be independent Inbox todos or use a verified Project link when requested, and draft emails need pending approval. For row-shaped datasets you'll filter/sort by exact value, use table-create/table-insert-rows/table-query instead. Ordinary vaults are indexed and shareable \u2014 never store real secrets there; use a secure vault (create-secure-vault) instead, which is never indexed or shareable and is encrypted at rest. Requires write scope.",
|
|
35708
35723
|
input: {
|
|
35709
35724
|
vault: import_zod37.z.string().optional().describe(
|
|
35710
|
-
"Vault to write to. Optional; defaults to the session active vault, then the first vault the caller is entitled to. On a default-provisioned account, pick the vault whose job matches the content (see the server instructions for the full
|
|
35725
|
+
"Vault to write to. Optional; defaults to the session active vault, then the first vault the caller is entitled to. On a default-provisioned account, pick the vault whose job matches the content (see the server instructions for the full 15-vault guide) rather than defaulting blindly \u2014 e.g. a lesson learned goes in Knowledge, the raw source it came from goes in Library, a broken feature goes in Issues, a named real-world initiative goes in Projects. Do not use this low-level tool to create ordinary People, Deals, Projects, Tasks, or Communications records: first use prepare-memory-write then memory-capture so relationships and approval state are validated."
|
|
35711
35726
|
),
|
|
35712
35727
|
path: import_zod37.z.string().optional().describe("Vault-relative note path to create or overwrite, e.g. projects/q3-plan. Writing an existing path replaces it. Required unless shareId is given."),
|
|
35713
35728
|
shareId: import_zod37.z.string().optional().describe("Edit a note someone individually shared with you and you accepted (accept-share), by its shareId, instead of vault+path. Requires the share to grant edit permission, and baseRevision is mandatory (get the current revision first) since you are editing alongside the owner and possibly others."),
|
|
@@ -36494,9 +36509,9 @@ var init_memory_tool_schemas = __esm({
|
|
|
36494
36509
|
GetVaultContractSchema = {
|
|
36495
36510
|
id: "get-vault-contract",
|
|
36496
36511
|
upstreamName: "getVaultContractTool",
|
|
36497
|
-
description: "Read the machine-enforced purpose, template, statuses, types, natural neighbor vaults, and typed relationship guidance for one of the
|
|
36512
|
+
description: "Read the machine-enforced purpose, template, statuses, types, natural neighbor vaults, and typed relationship guidance for one of the 15 governed Obsidian-style vaults. Call before composing a note when the correct shape is uncertain.",
|
|
36498
36513
|
input: {
|
|
36499
|
-
vault: import_zod37.z.string().describe("One governed vault: Ideas, Inspiration, Knowledge, Library, People, Communications, Calendar, Tasks, Projects, Issues, Improvement Log, Experiments, or
|
|
36514
|
+
vault: import_zod37.z.string().describe("One governed vault: Ideas, Inspiration, Knowledge, Library, People, Deals, Communications, Calendar, Tasks, Projects, Issues, Improvement Log, Experiments, Sprint, or Skills.")
|
|
36500
36515
|
},
|
|
36501
36516
|
output: {
|
|
36502
36517
|
ok: import_zod37.z.boolean(),
|
|
@@ -36566,17 +36581,17 @@ var init_memory_tool_schemas = __esm({
|
|
|
36566
36581
|
ProvisionDefaultsSchema = {
|
|
36567
36582
|
id: "provision-defaults",
|
|
36568
36583
|
upstreamName: "provisionDefaultsTool",
|
|
36569
|
-
description: "Provision the standard
|
|
36584
|
+
description: "Provision the standard 15-vault memory structure (Ideas, Inspiration, Knowledge, Library, People, Deals, Communications, Calendar, Tasks, Projects, Issues, Improvement Log, Experiments, Sprint, Skills) for an identity. Idempotent \u2014 existing records are untouched and existing vault contracts are refreshed. Optionally issues a fresh API key entitled to all 15. Requires admin scope.",
|
|
36570
36585
|
input: {
|
|
36571
|
-
granteeIdentity: import_zod37.z.string().min(1).describe("Identity that should OWN the
|
|
36572
|
-
issueKey: import_zod37.z.boolean().optional().describe("When true, also issue a new API key for the identity entitled to all
|
|
36586
|
+
granteeIdentity: import_zod37.z.string().min(1).describe("Identity that should OWN the 15 default vaults (e.g. an email or user id)."),
|
|
36587
|
+
issueKey: import_zod37.z.boolean().optional().describe("When true, also issue a new API key for the identity entitled to all 15 vaults and return its secret once. Default false."),
|
|
36573
36588
|
plan: import_zod37.z.enum(["free", "pro", "team", "enterprise"]).optional().describe("Subscription plan carried by the issued key. Optional; defaults to free. Only used when issueKey is true.")
|
|
36574
36589
|
},
|
|
36575
36590
|
output: {
|
|
36576
36591
|
ok: import_zod37.z.boolean().describe("True when provisioning succeeded; false on auth/scope error."),
|
|
36577
36592
|
identity: import_zod37.z.string().optional().describe("Identity the vaults were provisioned for."),
|
|
36578
|
-
created: import_zod37.z.array(import_zod37.z.string()).optional().describe("Vault names newly created on this call (empty when all
|
|
36579
|
-
vaults: import_zod37.z.array(import_zod37.z.string()).optional().describe("All
|
|
36593
|
+
created: import_zod37.z.array(import_zod37.z.string()).optional().describe("Vault names newly created on this call (empty when all 15 already existed)."),
|
|
36594
|
+
vaults: import_zod37.z.array(import_zod37.z.string()).optional().describe("All 15 default vault names the identity now owns."),
|
|
36580
36595
|
keyId: import_zod37.z.string().optional().describe("Stable id of the issued key. Present only when issueKey was true."),
|
|
36581
36596
|
secret: import_zod37.z.string().optional().describe("The issued key secret \u2014 RETURNED ONCE. Present only when issueKey was true."),
|
|
36582
36597
|
plan: import_zod37.z.string().optional().describe("Plan assigned to the issued key. Present only when issueKey was true."),
|
|
@@ -41218,16 +41233,55 @@ function workspaceRecord(vault, note) {
|
|
|
41218
41233
|
}
|
|
41219
41234
|
function defaultType(vault) {
|
|
41220
41235
|
if (vault === "People" || vault === "Communications") return "unclassified";
|
|
41236
|
+
if (vault === "Deals") return "deal";
|
|
41221
41237
|
if (vault === "Projects") return "project";
|
|
41222
41238
|
if (vault === "Tasks") return "task";
|
|
41239
|
+
if (vault === "Calendar") return "event";
|
|
41223
41240
|
return "unclassified";
|
|
41224
41241
|
}
|
|
41225
41242
|
function defaultStatus(vault) {
|
|
41226
41243
|
if (vault === "People") return "active";
|
|
41244
|
+
if (vault === "Deals") return "lead";
|
|
41227
41245
|
if (vault === "Projects") return "active";
|
|
41228
41246
|
if (vault === "Tasks") return "to_do";
|
|
41247
|
+
if (vault === "Calendar") return "scheduled";
|
|
41229
41248
|
return "inbox";
|
|
41230
41249
|
}
|
|
41250
|
+
function nonEmptyStrings(value) {
|
|
41251
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
|
|
41252
|
+
}
|
|
41253
|
+
function validateNewRecord(vault, props) {
|
|
41254
|
+
const type = typeof props.type === "string" ? props.type : "";
|
|
41255
|
+
if (vault === "People" && !["person", "organization"].includes(type)) return "People records must be a person or organization";
|
|
41256
|
+
if (vault === "Deals") {
|
|
41257
|
+
if (type !== "deal") return "Deals records must have type deal";
|
|
41258
|
+
if (typeof props.organization_ref !== "string" && nonEmptyStrings(props.person_refs).length === 0) {
|
|
41259
|
+
return "Deals require a known organization or person";
|
|
41260
|
+
}
|
|
41261
|
+
}
|
|
41262
|
+
if (vault === "Projects") {
|
|
41263
|
+
if (!["project", "vault_settings"].includes(type)) return "Projects records must have type project";
|
|
41264
|
+
if (type === "project" && !["codebase", "client", "personal", "workstream"].includes(String(props.project_kind ?? ""))) {
|
|
41265
|
+
return "Projects require project_kind: codebase, client, personal, or workstream";
|
|
41266
|
+
}
|
|
41267
|
+
}
|
|
41268
|
+
if (vault === "Tasks") {
|
|
41269
|
+
if (!["task", "milestone"].includes(type)) return "Tasks records must have type task or milestone";
|
|
41270
|
+
const hasProjectRef = typeof props.project_ref === "string" && props.project_ref.trim().length > 0;
|
|
41271
|
+
const hasProjectTitle = typeof props.project === "string" && props.project.trim().length > 0;
|
|
41272
|
+
if (hasProjectRef !== hasProjectTitle) return "Tasks project_ref and project must be supplied together when a task is linked to a project";
|
|
41273
|
+
}
|
|
41274
|
+
if (vault === "Communications") {
|
|
41275
|
+
if (!["email", "slack", "message", "call", "meeting", "social_media", "thread", "decision"].includes(type)) return "Communications records need a valid communication type";
|
|
41276
|
+
if (!["none", "needs_reply", "needs_review", "waiting"].includes(String(props.attention_state ?? ""))) {
|
|
41277
|
+
return "Communications require attention_state: none, needs_reply, needs_review, or waiting";
|
|
41278
|
+
}
|
|
41279
|
+
if (type === "email" && props.direction === "draft" && props.approval_state !== "pending") {
|
|
41280
|
+
return "Email drafts awaiting review must have approval_state pending";
|
|
41281
|
+
}
|
|
41282
|
+
}
|
|
41283
|
+
return null;
|
|
41284
|
+
}
|
|
41231
41285
|
function shouldRetryMemoryRead(error) {
|
|
41232
41286
|
return /deadlock|timeout|timed out|temporar|econnreset|fetch failed/i.test(error ?? "");
|
|
41233
41287
|
}
|
|
@@ -41274,7 +41328,7 @@ var init_vault_routes = __esm({
|
|
|
41274
41328
|
"use strict";
|
|
41275
41329
|
import_hono22 = require("hono");
|
|
41276
41330
|
init_memory();
|
|
41277
|
-
VAULTS = ["People", "Projects", "Tasks", "Communications"];
|
|
41331
|
+
VAULTS = ["People", "Deals", "Projects", "Tasks", "Communications", "Calendar"];
|
|
41278
41332
|
MAX_VAULT_RECORDS = 200;
|
|
41279
41333
|
MAX_MEMORY_READ_CONCURRENCY = 4;
|
|
41280
41334
|
MAX_MEMORY_READ_ATTEMPTS = 3;
|
|
@@ -41308,6 +41362,8 @@ var init_vault_routes = __esm({
|
|
|
41308
41362
|
const content = typeof body.content === "string" && body.content.length <= 1e5 ? body.content : "";
|
|
41309
41363
|
const props = propsValue(body.props) ?? {};
|
|
41310
41364
|
if (!isVault(vault) || !path6 || !title) return c.json({ ok: false, error: "vault, path, and title are required" }, 400);
|
|
41365
|
+
const validationError = validateNewRecord(vault, props);
|
|
41366
|
+
if (validationError) return c.json({ ok: false, error: validationError }, 400);
|
|
41311
41367
|
const baseRevision = typeof body.baseRevision === "number" && Number.isInteger(body.baseRevision) ? body.baseRevision : void 0;
|
|
41312
41368
|
const result = await memoryCall("putTool", { vault, path: path6, title, content: content || title, props, ...baseRevision === void 0 ? {} : { baseRevision } }, token);
|
|
41313
41369
|
return c.json(result, result.ok ? 200 : result.conflict ? 409 : 502);
|
|
@@ -41348,12 +41404,15 @@ var init_vault_routes = __esm({
|
|
|
41348
41404
|
}
|
|
41349
41405
|
const current = await readMemory("getTool", { vault, path: path6 }, token);
|
|
41350
41406
|
if (!current.ok || !current.note) return c.json(current, current.ok ? 404 : 502);
|
|
41407
|
+
const nextProps = { ...current.note.props ?? {}, ...props ?? {} };
|
|
41408
|
+
const validationError = validateNewRecord(vault, nextProps);
|
|
41409
|
+
if (validationError) return c.json({ ok: false, error: validationError }, 400);
|
|
41351
41410
|
const result = await memoryCall("putTool", {
|
|
41352
41411
|
vault,
|
|
41353
41412
|
path: path6,
|
|
41354
41413
|
title: title ?? current.note.title,
|
|
41355
41414
|
content: content ?? current.note.content,
|
|
41356
|
-
props:
|
|
41415
|
+
props: nextProps,
|
|
41357
41416
|
baseRevision: baseRevision ?? current.note.revision
|
|
41358
41417
|
}, token);
|
|
41359
41418
|
return c.json(result, result.ok ? 200 : result.conflict ? 409 : 502);
|
|
@@ -41388,20 +41447,25 @@ var init_vault_routes = __esm({
|
|
|
41388
41447
|
const content = typeof body.content === "string" && body.content.length <= 1e5 ? body.content : void 0;
|
|
41389
41448
|
const feedback = typeof body.feedback === "string" ? body.feedback.trim().slice(0, 1e4) : void 0;
|
|
41390
41449
|
const baseRevision = typeof body.baseRevision === "number" && Number.isInteger(body.baseRevision) ? body.baseRevision : void 0;
|
|
41391
|
-
|
|
41450
|
+
const normalizedAction = action === "accept" ? "approve" : action;
|
|
41451
|
+
if (!path6 || !normalizedAction || !["approve", "deny", "edit"].includes(normalizedAction) || body.title !== void 0 && !title) {
|
|
41392
41452
|
return c.json({ ok: false, error: "valid path, action, and optional draft fields are required" }, 400);
|
|
41393
41453
|
}
|
|
41394
41454
|
const current = await readMemory("getTool", { vault: "Communications", path: path6 }, token);
|
|
41395
41455
|
if (!current.ok || !current.note) return c.json(current, current.ok ? 404 : 502);
|
|
41396
41456
|
if (current.note.props?.type !== "email") return c.json({ ok: false, error: "only email communications can be reviewed" }, 400);
|
|
41397
|
-
const reviewed =
|
|
41398
|
-
const reviewState =
|
|
41399
|
-
const
|
|
41457
|
+
const reviewed = normalizedAction === "approve" || normalizedAction === "deny";
|
|
41458
|
+
const reviewState = normalizedAction === "approve" ? "accepted" : normalizedAction === "deny" ? "denied" : "pending";
|
|
41459
|
+
const approvalState = normalizedAction === "approve" ? "approved" : normalizedAction === "deny" ? "denied" : "pending";
|
|
41460
|
+
const status = normalizedAction === "approve" ? "triaged" : normalizedAction === "deny" ? "archived" : "inbox";
|
|
41400
41461
|
const props = {
|
|
41401
41462
|
...current.note.props ?? {},
|
|
41402
41463
|
status,
|
|
41403
41464
|
review_state: reviewState,
|
|
41465
|
+
approval_state: approvalState,
|
|
41466
|
+
attention_state: normalizedAction === "edit" ? "needs_review" : "none",
|
|
41404
41467
|
...reviewed ? { reviewed_at: (/* @__PURE__ */ new Date()).toISOString() } : {},
|
|
41468
|
+
...normalizedAction === "approve" ? { approved_at: (/* @__PURE__ */ new Date()).toISOString() } : {},
|
|
41405
41469
|
...feedback ? { review_feedback: feedback } : {}
|
|
41406
41470
|
};
|
|
41407
41471
|
const result = await memoryCall("putTool", {
|
|
@@ -41428,7 +41492,7 @@ var init_vault_routes = __esm({
|
|
|
41428
41492
|
path: `Inbox/activity-${stamp}`,
|
|
41429
41493
|
title,
|
|
41430
41494
|
content: content || title,
|
|
41431
|
-
props: { status: "triaged", type: "decision", occurred_at: (/* @__PURE__ */ new Date()).toISOString(), ...props }
|
|
41495
|
+
props: { status: "triaged", type: "decision", attention_state: "none", occurred_at: (/* @__PURE__ */ new Date()).toISOString(), ...props }
|
|
41432
41496
|
}, token);
|
|
41433
41497
|
return c.json(result, result.ok ? 200 : 502);
|
|
41434
41498
|
});
|