openwriter 0.18.1 → 0.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/dist/server/documents.js +10 -17
- package/dist/server/mcp.js +54 -54
- package/package.json +1 -1
package/dist/server/documents.js
CHANGED
|
@@ -129,12 +129,12 @@ export function listDocuments() {
|
|
|
129
129
|
// tag overlay from one HTTP round-trip instead of N. The server already
|
|
130
130
|
// has the parsed frontmatter in hand here; emitting tags is free.
|
|
131
131
|
...(Array.isArray(data.tags) && data.tags.length > 0 ? { tags: data.tags } : {}),
|
|
132
|
-
// Enrichment fields —
|
|
133
|
-
//
|
|
132
|
+
// Enrichment fields — free at this point since data is in hand.
|
|
133
|
+
// v0.19.0 schema: only logline (LLM) + status (agent) + enrichmentStale
|
|
134
|
+
// (system) are surfaced. domain / concepts / docRole stayed on disk for
|
|
135
|
+
// legacy docs but are no longer read (lazy migration via mark_enriched).
|
|
136
|
+
// See brief 2026-05-21-simplify-enrichment-schema-three-fields.
|
|
134
137
|
...(typeof data.logline === 'string' && data.logline ? { logline: data.logline } : {}),
|
|
135
|
-
...(typeof data.domain === 'string' && data.domain ? { domain: data.domain } : {}),
|
|
136
|
-
...(Array.isArray(data.concepts) && data.concepts.length > 0 ? { concepts: data.concepts } : {}),
|
|
137
|
-
...(typeof data.docRole === 'string' && data.docRole ? { docRole: data.docRole } : {}),
|
|
138
138
|
...(typeof data.status === 'string' && data.status ? { status: data.status } : {}),
|
|
139
139
|
...(data.enrichmentStale === true ? { enrichmentStale: true } : {}),
|
|
140
140
|
};
|
|
@@ -425,10 +425,11 @@ export function crawlDocs(filter = {}) {
|
|
|
425
425
|
const { data, content } = matter(raw);
|
|
426
426
|
if (data.archivedAt)
|
|
427
427
|
continue;
|
|
428
|
-
// Apply filters
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
428
|
+
// Apply filters. v0.19.0 schema: status (agent-owned) replaces
|
|
429
|
+
// docRole / domain / concepts. Legacy fields still on disk are
|
|
430
|
+
// ignored by both filtering and output — they retire as docs get
|
|
431
|
+
// re-enriched. See brief 2026-05-21-simplify-enrichment-schema-three-fields.
|
|
432
|
+
if (filter.status && data.status !== filter.status)
|
|
432
433
|
continue;
|
|
433
434
|
if (filter.hasLogline === true && !data.logline)
|
|
434
435
|
continue;
|
|
@@ -439,11 +440,6 @@ export function crawlDocs(filter = {}) {
|
|
|
439
440
|
if (!filter.tags.every((t) => docTags.includes(t)))
|
|
440
441
|
continue;
|
|
441
442
|
}
|
|
442
|
-
if (filter.concepts && filter.concepts.length > 0) {
|
|
443
|
-
const docConcepts = Array.isArray(data.concepts) ? data.concepts : [];
|
|
444
|
-
if (!filter.concepts.every((c) => docConcepts.includes(c)))
|
|
445
|
-
continue;
|
|
446
|
-
}
|
|
447
443
|
const trimmed = content.trim();
|
|
448
444
|
out.push({
|
|
449
445
|
docId: data.docId || '',
|
|
@@ -451,10 +447,7 @@ export function crawlDocs(filter = {}) {
|
|
|
451
447
|
title: data.title || f.replace(/\.md$/, ''),
|
|
452
448
|
wordCount: trimmed ? trimmed.split(/\s+/).length : 0,
|
|
453
449
|
...(typeof data.logline === 'string' && data.logline ? { logline: data.logline } : {}),
|
|
454
|
-
...(typeof data.domain === 'string' && data.domain ? { domain: data.domain } : {}),
|
|
455
450
|
...(Array.isArray(data.tags) && data.tags.length > 0 ? { tags: data.tags } : {}),
|
|
456
|
-
...(Array.isArray(data.concepts) && data.concepts.length > 0 ? { concepts: data.concepts } : {}),
|
|
457
|
-
...(typeof data.docRole === 'string' && data.docRole ? { docRole: data.docRole } : {}),
|
|
458
451
|
...(typeof data.status === 'string' && data.status ? { status: data.status } : {}),
|
|
459
452
|
...(data.enrichmentStale === true ? { enrichmentStale: true } : {}),
|
|
460
453
|
});
|
package/dist/server/mcp.js
CHANGED
|
@@ -363,7 +363,7 @@ export const TOOL_REGISTRY = [
|
|
|
363
363
|
},
|
|
364
364
|
{
|
|
365
365
|
name: 'list_documents',
|
|
366
|
-
description: 'List all documents. Shows title, docId, word count, last modified, active flag, and enrichment fields (logline,
|
|
366
|
+
description: 'List all documents. Shows title, docId, word count, last modified, active flag, and enrichment fields (logline, status, STALE marker) when present. Use the docId to target documents in other tools. v0.19.0: three-field enrichment schema — logline (LLM), status (agent: canonical / draft), STALE (system).',
|
|
367
367
|
schema: {},
|
|
368
368
|
handler: async () => {
|
|
369
369
|
const docs = listDocuments();
|
|
@@ -372,10 +372,10 @@ export const TOOL_REGISTRY = [
|
|
|
372
372
|
const id = d.docId ? ` [${d.docId}]` : '';
|
|
373
373
|
const date = d.lastModified.split('T')[0];
|
|
374
374
|
const enrichBits = [];
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (d.
|
|
378
|
-
enrichBits.push(
|
|
375
|
+
// v0.19.0: only canonical surfaces — draft is the default and would
|
|
376
|
+
// clutter the listing on every doc.
|
|
377
|
+
if (d.status === 'canonical')
|
|
378
|
+
enrichBits.push('canonical');
|
|
379
379
|
if (d.enrichmentStale === true)
|
|
380
380
|
enrichBits.push('STALE');
|
|
381
381
|
const enrichTag = enrichBits.length > 0 ? ` (${enrichBits.join(', ')})` : '';
|
|
@@ -415,8 +415,9 @@ export const TOOL_REGISTRY = [
|
|
|
415
415
|
content_type: z.enum(['document', 'tweet', 'reply', 'quote', 'article', 'linkedin', 'newsletter', 'blog']).describe('Required. Use "document" for plain documents. Tweet/reply/quote/article/linkedin/newsletter/blog set type-specific metadata automatically.'),
|
|
416
416
|
url: z.string().optional().describe('Tweet URL — REQUIRED for content_type "reply" or "quote" (e.g. "https://x.com/user/status/123"). Sets tweetContext.url automatically. Ignored for other content types.'),
|
|
417
417
|
afterId: z.string().optional().describe('Place the new doc immediately after this docId (8-char hex) or containerId inside its parent. Omit to append to the bottom of the parent (the default — matches ascending-order convention: newest at bottom). Requires workspace.'),
|
|
418
|
+
status: z.enum(['canonical', 'draft']).optional().describe('Agent-owned lifecycle. "canonical" = committed to spine / load-bearing for the workspace (use for Beats docs that have locked, Research Notes, Master References). "draft" = working / not load-bearing yet / scratch (DUMP docs, first-pass beats). Defaults to "draft" when omitted. Change later via set_metadata({ status: ... }) on lifecycle transitions. v0.19.0.'),
|
|
418
419
|
},
|
|
419
|
-
handler: async ({ title, path, workspace, container, empty, content_type, url, afterId }) => {
|
|
420
|
+
handler: async ({ title, path, workspace, container, empty, content_type, url, afterId, status }) => {
|
|
420
421
|
// Require url for reply/quote
|
|
421
422
|
if ((content_type === 'reply' || content_type === 'quote') && !url) {
|
|
422
423
|
return { content: [{ type: 'text', text: `Error: content_type "${content_type}" requires a url parameter (e.g. "https://x.com/user/status/123").` }] };
|
|
@@ -444,18 +445,25 @@ export const TOOL_REGISTRY = [
|
|
|
444
445
|
// Track the spinner key so catch can clear exactly this entry
|
|
445
446
|
// (not siblings from a concurrent declare_writes).
|
|
446
447
|
let spinnerKey = null;
|
|
448
|
+
// v0.19.0: agent-owned status. Defaults to "draft" when not supplied —
|
|
449
|
+
// canonical is reserved for docs that have committed to the workspace
|
|
450
|
+
// spine (Beats, Research Notes, Master References). Agent flips to
|
|
451
|
+
// canonical via set_metadata({ status: "canonical" }) on lifecycle
|
|
452
|
+
// transitions. See brief 2026-05-21-simplify-enrichment-schema-three-fields.
|
|
453
|
+
const statusMeta = { status: status ?? 'draft' };
|
|
447
454
|
try {
|
|
448
455
|
if (empty) {
|
|
449
456
|
// Immediate switch — no spinner, no populate_document needed
|
|
450
457
|
const result = createDocument(title, undefined, path);
|
|
451
458
|
setAgentLock(result.filename);
|
|
452
|
-
// Apply type-specific metadata
|
|
459
|
+
// Apply status + type-specific metadata in one merge
|
|
460
|
+
const initMeta = { ...statusMeta };
|
|
453
461
|
if (content_type) {
|
|
454
462
|
const typeMeta = resolveTypeMeta(content_type, url);
|
|
455
|
-
if (typeMeta)
|
|
456
|
-
|
|
457
|
-
}
|
|
463
|
+
if (typeMeta)
|
|
464
|
+
Object.assign(initMeta, typeMeta);
|
|
458
465
|
}
|
|
466
|
+
setMetadata(initMeta);
|
|
459
467
|
let wsInfo = '';
|
|
460
468
|
if (wsTarget) {
|
|
461
469
|
// Resolve afterId: it may be a docId (8-char hex) or containerId.
|
|
@@ -478,8 +486,11 @@ export const TOOL_REGISTRY = [
|
|
|
478
486
|
}
|
|
479
487
|
// Two-step flow: create file on disk WITHOUT switching the user's view.
|
|
480
488
|
// The spinner persists in the sidebar until populate_document is called.
|
|
489
|
+
// Merge status with any content-type metadata so it lands on the first
|
|
490
|
+
// disk write.
|
|
481
491
|
const typeMeta = content_type ? resolveTypeMeta(content_type, url) : undefined;
|
|
482
|
-
const
|
|
492
|
+
const initialMeta = { ...statusMeta, ...(typeMeta || {}) };
|
|
493
|
+
const result = createDocumentFile(title, path, initialMeta);
|
|
483
494
|
let wsInfo = '';
|
|
484
495
|
if (wsTarget) {
|
|
485
496
|
const afterRef = afterId ? (filenameByDocId(afterId) ?? afterId) : null;
|
|
@@ -733,7 +744,7 @@ export const TOOL_REGISTRY = [
|
|
|
733
744
|
},
|
|
734
745
|
{
|
|
735
746
|
name: 'set_metadata',
|
|
736
|
-
description: 'Update frontmatter metadata on a document. Merges with existing metadata — only provided keys are changed. Use for summaries, character lists, tags, arc notes, or any organizational data. Saves to disk immediately.',
|
|
747
|
+
description: 'Update frontmatter metadata on a document. Merges with existing metadata — only provided keys are changed. Use for summaries, character lists, tags, arc notes, or any organizational data. Saves to disk immediately. Lifecycle convention (v0.19.0): use `set_metadata({ status: "canonical" })` when a doc commits to the workspace spine (Beats locks, Research Note becomes load-bearing); use `set_metadata({ status: "draft" })` when a doc is superseded or demoted. Status is the agent\'s field — the enrichment minion never writes it.',
|
|
737
748
|
schema: {
|
|
738
749
|
docId: z.string().describe('Target document by docId (8-char hex from list_documents).'),
|
|
739
750
|
metadata: z.record(z.any()).describe('Key-value pairs to merge into frontmatter. Set a key to null to remove it.'),
|
|
@@ -801,16 +812,12 @@ export const TOOL_REGISTRY = [
|
|
|
801
812
|
},
|
|
802
813
|
{
|
|
803
814
|
name: 'mark_enriched',
|
|
804
|
-
description: 'Mark one or more documents as freshly enriched. Stamps openwriter-maintained baselines (lastEnrichedAt, lastEnrichedCharCount, lastEnrichedSentences) atomically with the supplied enrichment fields, and
|
|
815
|
+
description: 'Mark one or more documents as freshly enriched. Stamps openwriter-maintained baselines (lastEnrichedAt, lastEnrichedCharCount, lastEnrichedSentences) atomically with the supplied logline, clears enrichmentStale, and retires legacy enrichment fields (domain, concepts, docRole, and any LLM-written status). The agent never touches the sentence-hash layer — openwriter computes the baseline from current canonical content. Accepts an array so a workspace-wide sweep is one call. Schema simplified in v0.19.0: only logline is LLM-written; status is now agent-owned via create_document / set_metadata; domain / concepts / docRole are gone. See brief 2026-05-21-simplify-enrichment-schema-three-fields.',
|
|
805
816
|
schema: {
|
|
806
817
|
docs: z.array(z.object({
|
|
807
818
|
docId: z.string().describe('Target document by docId (8-char hex from list_documents).'),
|
|
808
|
-
logline: z.string().
|
|
809
|
-
|
|
810
|
-
concepts: z.array(z.string()).optional().describe('Named concepts the doc references.'),
|
|
811
|
-
docRole: z.string().optional().describe('Doc role: canonical / vignette / reference / draft / chapter / beat.'),
|
|
812
|
-
status: z.string().optional().describe('Doc status: draft / canonical / stale. Archive state is implied by archivedAt.'),
|
|
813
|
-
})).describe('One or more docs to mark enriched. Single-doc calls are a length-1 array.'),
|
|
819
|
+
logline: z.string().max(150).describe('Précis (non-fiction) or logline (fiction). Under 150 chars. Describe the content, not the kind of doc.'),
|
|
820
|
+
}).strict()).describe('One or more docs to mark enriched. Single-doc calls are a length-1 array. Strict schema — passing domain / concepts / docRole / status will fail validation (v0.19.0 schema simplification).'),
|
|
814
821
|
},
|
|
815
822
|
handler: async ({ docs }) => {
|
|
816
823
|
const now = new Date().toISOString();
|
|
@@ -828,23 +835,19 @@ export const TOOL_REGISTRY = [
|
|
|
828
835
|
const blocks = tiptapToBlocks(canonical);
|
|
829
836
|
const lastEnrichedSentences = harvestSentenceHashes(blocks);
|
|
830
837
|
const lastEnrichedCharCount = harvestCharCount(blocks);
|
|
831
|
-
// Build the atomic enrichment payload.
|
|
838
|
+
// Build the atomic enrichment payload. v0.19.0: only logline is
|
|
839
|
+
// LLM-written. The legacy fields (domain / concepts / docRole) get
|
|
840
|
+
// retired on this write — `LEGACY_FIELDS_TO_RETIRE` is deleted from
|
|
841
|
+
// the merged metadata so disk slowly converges to the new schema
|
|
842
|
+
// as each doc gets re-enriched (lazy migration path from the brief).
|
|
832
843
|
const update = {
|
|
833
844
|
lastEnrichedAt: now,
|
|
834
845
|
lastEnrichedCharCount,
|
|
835
846
|
lastEnrichedSentences,
|
|
836
847
|
enrichmentStale: false,
|
|
848
|
+
logline: item.logline,
|
|
837
849
|
};
|
|
838
|
-
|
|
839
|
-
update.logline = item.logline;
|
|
840
|
-
if (item.domain !== undefined)
|
|
841
|
-
update.domain = item.domain;
|
|
842
|
-
if (item.concepts !== undefined)
|
|
843
|
-
update.concepts = item.concepts;
|
|
844
|
-
if (item.docRole !== undefined)
|
|
845
|
-
update.docRole = item.docRole;
|
|
846
|
-
if (item.status !== undefined)
|
|
847
|
-
update.status = item.status;
|
|
850
|
+
const LEGACY_FIELDS_TO_RETIRE = ['domain', 'concepts', 'docRole'];
|
|
848
851
|
if (target.isActive) {
|
|
849
852
|
// Active doc: setMetadata mutates state.metadata but doesn't bump
|
|
850
853
|
// docVersion on its own — without an explicit bump, save() would
|
|
@@ -853,6 +856,9 @@ export const TOOL_REGISTRY = [
|
|
|
853
856
|
// writeToDisk's staleness check will see the just-stamped baseline
|
|
854
857
|
// (volumeRatio=1, drift=0) and NOT flip the flag back to true.
|
|
855
858
|
setMetadata(update);
|
|
859
|
+
const liveMeta = getMetadata();
|
|
860
|
+
for (const k of LEGACY_FIELDS_TO_RETIRE)
|
|
861
|
+
delete liveMeta[k];
|
|
856
862
|
bumpDocVersion();
|
|
857
863
|
save();
|
|
858
864
|
broadcastMetadataChanged(getMetadata());
|
|
@@ -863,6 +869,8 @@ export const TOOL_REGISTRY = [
|
|
|
863
869
|
// serialize cycle before the new baseline lands). Disk write +
|
|
864
870
|
// cache invalidation mirrors set_metadata's non-active path.
|
|
865
871
|
const newMeta = { ...target.metadata, ...update };
|
|
872
|
+
for (const k of LEGACY_FIELDS_TO_RETIRE)
|
|
873
|
+
delete newMeta[k];
|
|
866
874
|
const markdown = tiptapToMarkdown(target.document, target.title, newMeta);
|
|
867
875
|
atomicWriteFileSync(target.filePath, markdown);
|
|
868
876
|
invalidateDocCache(target.filePath);
|
|
@@ -896,13 +904,11 @@ export const TOOL_REGISTRY = [
|
|
|
896
904
|
},
|
|
897
905
|
{
|
|
898
906
|
name: 'crawl',
|
|
899
|
-
description: 'Bulk-read enriched fields per doc, filtered by criteria. The crawl primitive — agents use this to scan the workspace shelf at concept level (~
|
|
907
|
+
description: 'Bulk-read enriched fields per doc, filtered by criteria. The crawl primitive — agents use this to scan the workspace shelf at concept level (~60 tokens/doc) and decide which bodies to actually read. Filters compose with AND semantics. Empty filter returns every non-archived doc. No bodies, no nodes, no pending overlay. v0.19.0 schema: status (canonical / draft) replaces docRole / domain / concepts filters — those legacy filters were dropped because the fields they queried had no authority discipline. See brief 2026-05-21-simplify-enrichment-schema-three-fields.',
|
|
900
908
|
schema: {
|
|
901
909
|
workspaceFile: z.string().optional().describe('Scope to one workspace.'),
|
|
902
|
-
domain: z.string().optional().describe('Exact domain match.'),
|
|
903
910
|
tags: z.array(z.string()).optional().describe('Docs must have ALL listed tags.'),
|
|
904
|
-
|
|
905
|
-
docRole: z.string().optional().describe('Exact docRole match (canonical / vignette / reference / draft / chapter / beat).'),
|
|
911
|
+
status: z.enum(['canonical', 'draft']).optional().describe('Agent-owned lifecycle filter. "canonical" returns the trusted-shelf docs (load-bearing for the workspace); "draft" returns working / superseded / scratch docs. The common crawl is `status: canonical`.'),
|
|
906
912
|
hasLogline: z.boolean().optional().describe('True = only docs with a logline; false = only docs without one.'),
|
|
907
913
|
},
|
|
908
914
|
handler: async (filter) => {
|
|
@@ -953,7 +959,7 @@ export const TOOL_REGISTRY = [
|
|
|
953
959
|
},
|
|
954
960
|
{
|
|
955
961
|
name: 'get_workspace_structure',
|
|
956
|
-
description: 'Get the full structure of a workspace: tree of containers and docs, per-doc enrichment (logline,
|
|
962
|
+
description: 'Get the full structure of a workspace: tree of containers and docs, per-doc enrichment (logline, status, tags, stale flag), plus workspace-level context (characters, settings, rules) and enrichment metadata (schema, vocab, logline). Use to understand a workspace at concept level before reading bodies. v0.19.0: enrichment fields shown per-doc are logline (LLM-owned), status (agent-owned: canonical / draft), tags, and the STALE marker (system-owned).',
|
|
957
963
|
schema: {
|
|
958
964
|
filename: z.string().describe('Workspace manifest filename (e.g. "my-novel-a1b2c3d4.json")'),
|
|
959
965
|
},
|
|
@@ -970,10 +976,11 @@ export const TOOL_REGISTRY = [
|
|
|
970
976
|
const e = enrichByFile.get(node.file);
|
|
971
977
|
const tags = e?.tags ?? [];
|
|
972
978
|
const enrichBits = [];
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
979
|
+
// v0.19.0: status (agent-owned) replaces domain + docRole.
|
|
980
|
+
// Only "canonical" is worth surfacing — draft is the default
|
|
981
|
+
// and would add noise on every line.
|
|
982
|
+
if (e?.status === 'canonical')
|
|
983
|
+
enrichBits.push('canonical');
|
|
977
984
|
if (tags.length > 0)
|
|
978
985
|
enrichBits.push(`tags: ${tags.join(', ')}`);
|
|
979
986
|
if (e?.enrichmentStale === true)
|
|
@@ -1023,7 +1030,7 @@ export const TOOL_REGISTRY = [
|
|
|
1023
1030
|
},
|
|
1024
1031
|
{
|
|
1025
1032
|
name: 'get_item_context',
|
|
1026
|
-
description: 'Get progressive-disclosure context for a document: workspace-level context (characters, settings, rules, vocab), the doc\'s own enrichment (logline,
|
|
1033
|
+
description: 'Get progressive-disclosure context for a document: workspace-level context (characters, settings, rules, vocab), the doc\'s own enrichment (logline, status), tags, and the enrichmentStale flag. Use before writing to understand context, or before reading to decide whether a body read is necessary. v0.19.0: returns the three-field enrichment schema — logline (LLM), status (agent), enrichmentStale (system).',
|
|
1027
1034
|
schema: {
|
|
1028
1035
|
workspaceFile: z.string().describe('Workspace manifest filename'),
|
|
1029
1036
|
docId: z.string().describe('Document docId (8-char hex from list_documents)'),
|
|
@@ -1039,14 +1046,10 @@ export const TOOL_REGISTRY = [
|
|
|
1039
1046
|
const enriched = crawlDocs({ workspaceFile });
|
|
1040
1047
|
const docEnrich = enriched.find((e) => e.filename === filename);
|
|
1041
1048
|
if (docEnrich) {
|
|
1049
|
+
// v0.19.0 three-field schema: logline (LLM), status (agent),
|
|
1050
|
+
// enrichmentStale (system). domain / concepts / docRole dropped.
|
|
1042
1051
|
if (docEnrich.logline)
|
|
1043
1052
|
base.logline = docEnrich.logline;
|
|
1044
|
-
if (docEnrich.domain)
|
|
1045
|
-
base.domain = docEnrich.domain;
|
|
1046
|
-
if (docEnrich.concepts)
|
|
1047
|
-
base.concepts = docEnrich.concepts;
|
|
1048
|
-
if (docEnrich.docRole)
|
|
1049
|
-
base.docRole = docEnrich.docRole;
|
|
1050
1053
|
if (docEnrich.status)
|
|
1051
1054
|
base.status = docEnrich.status;
|
|
1052
1055
|
if (docEnrich.enrichmentStale === true)
|
|
@@ -1811,20 +1814,18 @@ export const TOOL_REGISTRY = [
|
|
|
1811
1814
|
const enriched = raw.slice(0, cap).map((r) => {
|
|
1812
1815
|
let docId = null;
|
|
1813
1816
|
let logline;
|
|
1814
|
-
let
|
|
1815
|
-
let docRole;
|
|
1817
|
+
let status;
|
|
1816
1818
|
let tags;
|
|
1817
1819
|
try {
|
|
1818
1820
|
const filePath = resolveDocPath(r.filename);
|
|
1819
1821
|
const fileRaw = readFileSync(filePath, 'utf-8');
|
|
1820
1822
|
const fm = matter(fileRaw);
|
|
1821
1823
|
docId = fm.data?.docId || null;
|
|
1824
|
+
// v0.19.0 three-field schema: logline (LLM), status (agent), tags.
|
|
1822
1825
|
if (typeof fm.data?.logline === 'string')
|
|
1823
1826
|
logline = fm.data.logline;
|
|
1824
|
-
if (typeof fm.data?.
|
|
1825
|
-
|
|
1826
|
-
if (typeof fm.data?.docRole === 'string')
|
|
1827
|
-
docRole = fm.data.docRole;
|
|
1827
|
+
if (typeof fm.data?.status === 'string')
|
|
1828
|
+
status = fm.data.status;
|
|
1828
1829
|
if (Array.isArray(fm.data?.tags) && fm.data.tags.length > 0)
|
|
1829
1830
|
tags = fm.data.tags;
|
|
1830
1831
|
}
|
|
@@ -1837,8 +1838,7 @@ export const TOOL_REGISTRY = [
|
|
|
1837
1838
|
snippet: r.snippet,
|
|
1838
1839
|
matchedTag: r.matchedTag,
|
|
1839
1840
|
...(logline ? { logline } : {}),
|
|
1840
|
-
...(
|
|
1841
|
-
...(docRole ? { docRole } : {}),
|
|
1841
|
+
...(status ? { status } : {}),
|
|
1842
1842
|
...(tags ? { tags } : {}),
|
|
1843
1843
|
};
|
|
1844
1844
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openwriter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "The open-source writing surface for AI agents. Markdown-native editor with pending change review — your agent writes, you accept or reject.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|