@buildaharness/aielia 0.3.9 → 0.3.10
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/_memory-core-generated.d.ts +6 -0
- package/dist/assistant.d.ts +11 -0
- package/dist/{bin-CCwDFxDe.js → bin-Cz3FY6Ew.js} +30 -11
- package/dist/bin-Cz3FY6Ew.js.map +1 -0
- package/dist/claude-cli-llm-client.d.ts +2 -0
- package/dist/claude-cli-prompt.d.ts +7 -0
- package/dist/cli.js +1 -1
- package/dist/fact-repository.contract.d.ts +2 -0
- package/dist/fact-repository.d.ts +44 -0
- package/dist/file-tools-mcp-server.mjs +29 -0
- package/dist/harness-bridge.d.ts +5 -5
- package/dist/html-to-markdown.d.ts +11 -0
- package/dist/index.d.ts +82 -2
- package/dist/index.js +4975 -173
- package/dist/index.js.map +1 -1
- package/dist/layer-settings.d.ts +16 -3
- package/dist/memory-events.d.ts +177 -0
- package/dist/memory-service.d.ts +15 -0
- package/dist/model-pricing.d.ts +3 -0
- package/dist/{provider-setup-Cy9dwqrd.js → provider-setup-DG8iYm_F.js} +5756 -4787
- package/dist/provider-setup-DG8iYm_F.js.map +1 -0
- package/dist/scripted-llm-client.d.ts +1 -1
- package/dist/{tui-app-Dt72u8vZ.js → tui-app-oWbIUcBW.js} +3 -3
- package/dist/{tui-app-Dt72u8vZ.js.map → tui-app-oWbIUcBW.js.map} +1 -1
- package/dist/turn-abort.d.ts +5 -0
- package/dist/version.d.ts +1 -1
- package/dist/web-fetch-core.d.ts +0 -14
- package/dist/writer/article-autosave.d.ts +12 -0
- package/dist/writer/article-change-summary.d.ts +28 -0
- package/dist/writer/article-claims.d.ts +49 -0
- package/dist/writer/article-comments.d.ts +20 -0
- package/dist/writer/article-consistency.d.ts +27 -0
- package/dist/writer/article-decorations.d.ts +23 -0
- package/dist/writer/article-dependencies.d.ts +44 -0
- package/dist/writer/article-draft.d.ts +23 -0
- package/dist/writer/article-edit-outline.d.ts +16 -0
- package/dist/writer/article-edit-suggest.d.ts +30 -0
- package/dist/writer/article-folder.d.ts +29 -0
- package/dist/writer/article-history.d.ts +73 -0
- package/dist/writer/article-ideas.d.ts +34 -0
- package/dist/writer/article-issues.d.ts +47 -0
- package/dist/writer/article-marks.d.ts +25 -0
- package/dist/writer/article-memory-store.d.ts +3 -0
- package/dist/writer/article-model.d.ts +1337 -0
- package/dist/writer/article-outline.d.ts +43 -0
- package/dist/writer/article-resolver.d.ts +55 -0
- package/dist/writer/article-revisions.d.ts +30 -0
- package/dist/writer/article-rules.d.ts +60 -0
- package/dist/writer/article-sections.d.ts +26 -0
- package/dist/writer/article-selection.d.ts +26 -0
- package/dist/writer/article-service.d.ts +542 -0
- package/dist/writer/article-source-links.d.ts +42 -0
- package/dist/writer/article-sources.d.ts +82 -0
- package/dist/writer/article-style-derive.d.ts +26 -0
- package/dist/writer/article-style.d.ts +31 -0
- package/dist/writer/article-suggestions.d.ts +33 -0
- package/dist/writer/article-support.d.ts +33 -0
- package/dist/writer/article-verify.d.ts +42 -0
- package/dist/writer/local-folder.d.ts +49 -0
- package/dist/writer/model-failure-hint.d.ts +7 -0
- package/dist/writer/repo-reader.d.ts +29 -0
- package/dist/writer/repo-search.d.ts +33 -0
- package/dist/writer/repo-verify-loop.d.ts +61 -0
- package/dist/writer/text-tool-calls.d.ts +11 -0
- package/dist/writer/work-progress.d.ts +51 -0
- package/dist/writer/write-activity.d.ts +61 -0
- package/dist/writer/write-models.d.ts +12 -0
- package/dist/writer/write-parameters.d.ts +31 -0
- package/dist/writer/write-permissions.d.ts +89 -0
- package/dist/writer/write-spend.d.ts +16 -0
- package/dist/writer/writer-chat-capture.d.ts +25 -0
- package/dist/writer/writer-chat-history.d.ts +17 -0
- package/dist/writer/writer-chat-state.d.ts +358 -0
- package/dist/writer/writer-chat-turn.d.ts +52 -0
- package/dist/writer/writer-intent.d.ts +20 -0
- package/package.json +3 -3
- package/dist/bin-CCwDFxDe.js.map +0 -1
- package/dist/provider-setup-Cy9dwqrd.js.map +0 -1
package/dist/turn-abort.d.ts
CHANGED
|
@@ -16,3 +16,8 @@ export interface AbortGate {
|
|
|
16
16
|
export declare function gateLlmClient(client: ILLMClient, gate: AbortGate): ILLMClient;
|
|
17
17
|
/** Rejects with TurnAbortedError as soon as `signal` aborts, without waiting for `work`; `work`'s own late outcome is swallowed. */
|
|
18
18
|
export declare function raceAbort<T>(work: Promise<T>, signal: AbortSignal): Promise<T>;
|
|
19
|
+
/**
|
|
20
|
+
* A client for one job that can be stopped: every call carries `signal` (so a backend that honours it cuts the request off), the wait ends the
|
|
21
|
+
* moment it aborts even on a backend that ignores it, and what such a call returns later is dropped. With no signal the client is returned as is.
|
|
22
|
+
*/
|
|
23
|
+
export declare function stoppableLlmClient(client: ILLMClient, signal?: AbortSignal): ILLMClient;
|
package/dist/version.d.ts
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* runtime (a bundled/SEA binary has no package.json beside it). `scripts/check-cli-version-sync.mjs`
|
|
4
4
|
* fails CI if this drifts from `package.json`'s `version` — bump both together.
|
|
5
5
|
*/
|
|
6
|
-
export declare const CLI_VERSION = "0.3.
|
|
6
|
+
export declare const CLI_VERSION = "0.3.10";
|
package/dist/web-fetch-core.d.ts
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runtime-agnostic SSRF guard + safe-fetch core used by web-tools.ts (desktop/CLI path). Split
|
|
3
|
-
* out of web-tools.ts so the guard/redirect/byte-cap logic is one focused module instead of
|
|
4
|
-
* living inline in the tool executor.
|
|
5
|
-
*
|
|
6
|
-
* packages/proxy/src/web-fetch.ts (POST /web/fetch, W2) intentionally carries its own copy of
|
|
7
|
-
* this guard rather than importing this module as a workspace dependency — same call W1's
|
|
8
|
-
* web-search.ts already made for the search parsing code: this package's only `exports` entry is
|
|
9
|
-
* the whole `dist/index.js` bundle (nodemailer, the MCP SDK, the CLI), and this repo's proxy CI
|
|
10
|
-
* job (and this plan's own suggested gate script) typechecks/tests packages/proxy without a
|
|
11
|
-
* `build:personal-assistant` step first, so a real cross-package import isn't actually wired up
|
|
12
|
-
* to build here. Keep the two guards in sync by hand if one changes — same discipline the ported
|
|
13
|
-
* DDG/Brave search code in web-search.ts already requires.
|
|
14
|
-
*/
|
|
15
1
|
/**
|
|
16
2
|
* Thrown by assertPublicHttpUrl instead of returning a falsy value, so callers
|
|
17
3
|
* can't accidentally proceed past a rejected URL.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When the page should save a version by itself while the writer types: a sentence has been finished (a full stop, question mark or
|
|
3
|
+
* exclamation mark ends it), a section has been started (a heading line is complete), or the writer has begun changing a different sentence
|
|
4
|
+
* from the one they were editing, which means they are done with that one. Pure: it looks at the text before and after one change.
|
|
5
|
+
*/
|
|
6
|
+
export interface AutosaveStep {
|
|
7
|
+
/** `after`: save the text as it is now. `before`: save the text as it was before this change, which is how the sentence stood when the writer left it. */
|
|
8
|
+
moment: 'before' | 'after' | null;
|
|
9
|
+
/** Where the sentence being edited starts, to hand back with the next change. */
|
|
10
|
+
sentenceStart: number | null;
|
|
11
|
+
}
|
|
12
|
+
export declare function autosaveStep(prev: string, next: string, lastSentenceStart: number | null): AutosaveStep;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a change did to an article, read from the text before and after: the outline (sections added, removed, renamed, moved) and the
|
|
3
|
+
* sections whose wording changed. A comparison of the two texts, so the chat can say exactly what happened without asking a model.
|
|
4
|
+
*/
|
|
5
|
+
export interface SectionChange {
|
|
6
|
+
outline: {
|
|
7
|
+
added: string[];
|
|
8
|
+
removed: string[];
|
|
9
|
+
renamed: {
|
|
10
|
+
from: string;
|
|
11
|
+
to: string;
|
|
12
|
+
}[];
|
|
13
|
+
moved: string[];
|
|
14
|
+
};
|
|
15
|
+
/** The added sections that came with text of their own. */
|
|
16
|
+
addedWithText: string[];
|
|
17
|
+
/** Sections that kept their heading and whose text changed. */
|
|
18
|
+
reworded: string[];
|
|
19
|
+
/** What was done to the text of each of those, judged by how much of the old wording is left. */
|
|
20
|
+
how: Record<string, SectionEdit>;
|
|
21
|
+
}
|
|
22
|
+
export type SectionEdit = 'wrote' | 'cleared' | 'rewrote' | 'added to' | 'shortened' | 'reworded';
|
|
23
|
+
export declare function summarizeSectionChange(before: string, after: string): SectionChange;
|
|
24
|
+
/** Marks a section name inside chat text, so the chat can show names in a colour instead of between quotation marks. Private-use characters: they never occur in real text. */
|
|
25
|
+
export declare const NAME_OPEN = "\uE000";
|
|
26
|
+
export declare const NAME_CLOSE = "\uE001";
|
|
27
|
+
/** The summary as lines for the chat: one for the outline (when it changed) and one for the wording. Empty when nothing changed. */
|
|
28
|
+
export declare function describeSectionChange(c: SectionChange): string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { Claim, Section } from './article-model.js';
|
|
3
|
+
/**
|
|
4
|
+
* Claim extraction and reconciliation (T2). A model reads the sections and says which statements are claims and which
|
|
5
|
+
* stored claim each one is (by meaning); this module checks that every quote really occurs in the text, gives the claim
|
|
6
|
+
* its section from the text's own structure, and applies the match rules from the article-model plan, section 6:
|
|
7
|
+
* - a sure match keeps the id; changed wording resets the check (editClaimText);
|
|
8
|
+
* - an unsure match keeps the claim and marks it "moved or changed, check": not dropped, not silently re-created;
|
|
9
|
+
* - a confirmed claim the model no longer finds is kept and marked for a check, never dropped silently;
|
|
10
|
+
* - an unconfirmed claim that is gone is dropped but reported;
|
|
11
|
+
* - what the model says about a claim the writer confirmed never changes its kind.
|
|
12
|
+
* Any failure leaves the claims as they were and says so.
|
|
13
|
+
*/
|
|
14
|
+
export interface ExtractionResult {
|
|
15
|
+
status: 'extracted' | 'not_extracted';
|
|
16
|
+
claims: Claim[];
|
|
17
|
+
added: string[];
|
|
18
|
+
matched: string[];
|
|
19
|
+
/** Kept but marked needsRecheck because the match was unsure or a confirmed claim could not be found. */
|
|
20
|
+
flagged: string[];
|
|
21
|
+
/** Unconfirmed claims that no longer exist in the text. */
|
|
22
|
+
removed: Claim[];
|
|
23
|
+
/** Model claims whose quote does not occur in the text, so they cannot be anchored. Reported, not stored. */
|
|
24
|
+
unanchored: string[];
|
|
25
|
+
}
|
|
26
|
+
/** Sections grouped so one call stays within a size bound. A section larger than the bound goes alone. */
|
|
27
|
+
export declare function batchSections(sections: readonly Section[], markdown: string, maxChars?: number): Section[][];
|
|
28
|
+
export declare function extractClaims(input: {
|
|
29
|
+
markdown: string;
|
|
30
|
+
sections: readonly Section[];
|
|
31
|
+
claims: readonly Claim[];
|
|
32
|
+
now: string;
|
|
33
|
+
}, llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void): Promise<ExtractionResult>;
|
|
34
|
+
/** Links that start or end at a claim the article no longer has (an unconfirmed claim whose sentence was reworded is dropped by extraction): left in place they fail the integrity check. */
|
|
35
|
+
export declare function dropLinksToMissingClaims<M extends {
|
|
36
|
+
claims: readonly {
|
|
37
|
+
id: string;
|
|
38
|
+
}[];
|
|
39
|
+
links: readonly {
|
|
40
|
+
from: {
|
|
41
|
+
type: string;
|
|
42
|
+
id: string;
|
|
43
|
+
};
|
|
44
|
+
to: {
|
|
45
|
+
type: string;
|
|
46
|
+
id: string;
|
|
47
|
+
};
|
|
48
|
+
}[];
|
|
49
|
+
}>(meta: M): M;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ArticleMeta } from './article-model.js';
|
|
2
|
+
import { WriterComment } from './writer-chat-state.js';
|
|
3
|
+
import { TextRange } from './article-source-links.js';
|
|
4
|
+
/**
|
|
5
|
+
* Comments the writer makes on text: highlight a phrase, a sentence, a paragraph or a section, and type. The comment keeps the quoted text; when
|
|
6
|
+
* the article changes it is found again by that quote, and if the text is gone the comment is kept and marked as outdated, never dropped.
|
|
7
|
+
*/
|
|
8
|
+
export type CommentResult = {
|
|
9
|
+
ok: true;
|
|
10
|
+
meta: ArticleMeta;
|
|
11
|
+
comment: WriterComment;
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
reason: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function addCommentOnText(meta: ArticleMeta, markdown: string, range: TextRange, text: string, now: string): CommentResult;
|
|
17
|
+
/** Comments whose text overlaps the range. Comments that arrived from chat have no text of their own and are not here. */
|
|
18
|
+
export declare function commentsInRange(meta: ArticleMeta, range: TextRange): WriterComment[];
|
|
19
|
+
/** Follows each comment's text through an edit; a comment whose text is gone is marked outdated (and keeps its words). */
|
|
20
|
+
export declare function refreshComments(meta: ArticleMeta, markdown: string): ArticleMeta;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { ArticleMeta } from './article-model.js';
|
|
3
|
+
/**
|
|
4
|
+
* The consistency pass (E10, E11): one model call over the whole article and the text of its sources. It looks for what a check of single claims
|
|
5
|
+
* against their sources cannot see: two statements of the article that cannot both be true (or a conclusion that does not follow from the article's
|
|
6
|
+
* own figures), and advice or a general statement that goes further than the sources say they cover. Every judgement is the model's. This module
|
|
7
|
+
* only keeps findings whose quote is really in the text, marks the section they are in as needing review with the reason (the same mark the resolver
|
|
8
|
+
* uses; only the writer clears it) and reports what it did. A failure, or an article too long to send whole, leaves the article as it was.
|
|
9
|
+
*/
|
|
10
|
+
export interface ConsistencyFinding {
|
|
11
|
+
sectionId: string;
|
|
12
|
+
kind: 'conflict' | 'overreach';
|
|
13
|
+
quote: string;
|
|
14
|
+
reason: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ConsistencyResult {
|
|
17
|
+
status: 'checked' | 'not_checked' | 'too_long';
|
|
18
|
+
meta: ArticleMeta;
|
|
19
|
+
findings: ConsistencyFinding[];
|
|
20
|
+
}
|
|
21
|
+
/** The longest article sent whole, in characters. */
|
|
22
|
+
export declare const CONSISTENCY_MAX_ARTICLE_CHARS = 24000;
|
|
23
|
+
export declare function checkConsistency(input: {
|
|
24
|
+
meta: ArticleMeta;
|
|
25
|
+
markdown: string;
|
|
26
|
+
now: string;
|
|
27
|
+
}, llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void): Promise<ConsistencyResult>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ArticleMeta } from './article-model.js';
|
|
2
|
+
import { MarkTone } from './article-marks.js';
|
|
3
|
+
/**
|
|
4
|
+
* Everything the page shows inside the text, as pieces of the text with what applies to each: the tint of a claim's sentence (green, orange or
|
|
5
|
+
* red), a dotted underline where an open comment sits, a dashed underline where a suggested change would go, and a mark on a heading whose section
|
|
6
|
+
* needs review. Only styling that does not move the text is possible (the marks are drawn on a copy behind the text area), so detail is not shown
|
|
7
|
+
* here: the box under the text and the line "Here:" say what is at the cursor. Pure; a decoration is drawn only where the stored text still
|
|
8
|
+
* stands at the stored place, so text typed since the last save never gets a mark in the wrong place.
|
|
9
|
+
*/
|
|
10
|
+
export interface TextPiece {
|
|
11
|
+
start: number;
|
|
12
|
+
end: number;
|
|
13
|
+
/** The worst claim tone over this piece, when it is inside a claim's sentence. */
|
|
14
|
+
tone?: MarkTone;
|
|
15
|
+
claimId?: string;
|
|
16
|
+
claimStatus?: string;
|
|
17
|
+
commentIds: string[];
|
|
18
|
+
suggestionIds: string[];
|
|
19
|
+
reviewSectionId?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function textPieces(meta: ArticleMeta, markdown: string): TextPiece[];
|
|
22
|
+
/** What applies at one place in the text, in a short line the page shows under it; undefined when nothing does. */
|
|
23
|
+
export declare function describeAt(pieces: readonly TextPiece[], position: number): string | undefined;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { ArticleMeta, Link } from './article-model.js';
|
|
3
|
+
/**
|
|
4
|
+
* Dependency mapping between sections (T4). A section "rests on" another when it builds on it (a thesis and its arguments), and
|
|
5
|
+
* "repeats" another when it restates it (an opening or a conclusion repeating a figure). The assistant proposes links, the writer
|
|
6
|
+
* confirms, removes or draws them by hand; a confirmed or drawn link is never changed by the assistant. When a section changes,
|
|
7
|
+
* the resolver uses these links to say which other sections need a look.
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEPENDENCY_KINDS: readonly ["rests_on", "repeats"];
|
|
10
|
+
export type DependencyKind = (typeof DEPENDENCY_KINDS)[number];
|
|
11
|
+
export declare const DEPENDENCY_LABEL: Record<DependencyKind, string>;
|
|
12
|
+
export interface SectionDependencies {
|
|
13
|
+
/** Links where this section is the one that depends. */
|
|
14
|
+
uses: Link[];
|
|
15
|
+
/** Links where another section depends on this one. */
|
|
16
|
+
usedBy: Link[];
|
|
17
|
+
}
|
|
18
|
+
export declare function dependenciesOf(meta: ArticleMeta, sectionId: string): SectionDependencies;
|
|
19
|
+
/** True when adding "from rests on to" would make a circle of "rests on" links (A rests on B rests on A). */
|
|
20
|
+
export declare function wouldCycle(meta: ArticleMeta, from: string, to: string): boolean;
|
|
21
|
+
export type AddLinkResult = {
|
|
22
|
+
ok: true;
|
|
23
|
+
meta: ArticleMeta;
|
|
24
|
+
link: Link;
|
|
25
|
+
} | {
|
|
26
|
+
ok: false;
|
|
27
|
+
reason: string;
|
|
28
|
+
};
|
|
29
|
+
/** The writer draws a link by hand. It is origin "drawn", so the assistant can never remove or change it. */
|
|
30
|
+
export declare function addDrawnLink(meta: ArticleMeta, from: string, to: string, kind: DependencyKind, now: string): AddLinkResult;
|
|
31
|
+
export interface DependencyProposal {
|
|
32
|
+
status: 'proposed' | 'failed';
|
|
33
|
+
meta: ArticleMeta;
|
|
34
|
+
added: Link[];
|
|
35
|
+
/** Proposals dropped: unknown section, a duplicate, a section depending on itself, or a circle. */
|
|
36
|
+
skipped: string[];
|
|
37
|
+
/** Why the search failed, when it did: the error the model call raised, or that its answer could not be read. */
|
|
38
|
+
reason?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function proposeDependencies(input: {
|
|
41
|
+
meta: ArticleMeta;
|
|
42
|
+
markdown: string;
|
|
43
|
+
now: string;
|
|
44
|
+
}, llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void): Promise<DependencyProposal>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { ArticleMeta } from './article-model.js';
|
|
3
|
+
import { ChatTurn } from './writer-chat-history.js';
|
|
4
|
+
export type ArticleDraft = {
|
|
5
|
+
status: 'drafted';
|
|
6
|
+
markdown: string;
|
|
7
|
+
name: string;
|
|
8
|
+
} | {
|
|
9
|
+
status: 'failed';
|
|
10
|
+
reason: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The text of the string value of `key` in a JSON object that is still being written, as far as it has arrived: escapes are decoded, an escape cut
|
|
14
|
+
* in half at the end is left out, and the value is `undefined` until its opening quote has been written. Used to show a draft as it is typed.
|
|
15
|
+
*/
|
|
16
|
+
export declare function partialJsonString(json: string, key: string): string | undefined;
|
|
17
|
+
/** `onText` is given the article as it has been written so far, while the model is still writing; with it the model's reply is read as it streams. */
|
|
18
|
+
export declare function draftArticle(input: {
|
|
19
|
+
meta: ArticleMeta;
|
|
20
|
+
instruction: string;
|
|
21
|
+
current?: string;
|
|
22
|
+
history?: readonly ChatTurn[];
|
|
23
|
+
}, llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void, onText?: (markdownSoFar: string) => void): Promise<ArticleDraft>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { ArticleMeta } from './article-model.js';
|
|
3
|
+
import { ChatTurn } from './writer-chat-history.js';
|
|
4
|
+
export type OutlineEdit = {
|
|
5
|
+
status: 'edited';
|
|
6
|
+
outline: string;
|
|
7
|
+
} | {
|
|
8
|
+
status: 'failed';
|
|
9
|
+
reason: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function editOutline(input: {
|
|
12
|
+
meta: ArticleMeta;
|
|
13
|
+
outline: string;
|
|
14
|
+
instruction: string;
|
|
15
|
+
history?: readonly ChatTurn[];
|
|
16
|
+
}, llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void): Promise<OutlineEdit>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { ArticleMeta } from './article-model.js';
|
|
3
|
+
import { ChatTurn } from './writer-chat-history.js';
|
|
4
|
+
/**
|
|
5
|
+
* Turns the writer's instruction ("fix the figure as C1 asks", "tighten the intro") into suggested changes: exact quoted
|
|
6
|
+
* text plus a replacement and a reason (T9). Nothing is applied here; every suggestion waits for the writer. Quotes that
|
|
7
|
+
* are not in the text are dropped and reported, so a suggestion can always be found again.
|
|
8
|
+
*/
|
|
9
|
+
export interface EditSuggestResult {
|
|
10
|
+
status: 'suggested' | 'failed';
|
|
11
|
+
meta: ArticleMeta;
|
|
12
|
+
added: string[];
|
|
13
|
+
/** Model proposals that could not be anchored in the text. */
|
|
14
|
+
dropped: string[];
|
|
15
|
+
}
|
|
16
|
+
export declare function suggestEdits(input: {
|
|
17
|
+
meta: ArticleMeta;
|
|
18
|
+
markdown: string;
|
|
19
|
+
instruction: string;
|
|
20
|
+
now: string;
|
|
21
|
+
modelName?: string; /** Revise only the text in this range: the model is shown it, and a change outside it is dropped. */
|
|
22
|
+
focus?: {
|
|
23
|
+
start: number;
|
|
24
|
+
end: number;
|
|
25
|
+
};
|
|
26
|
+
ideaIds?: string[];
|
|
27
|
+
commentIds?: string[];
|
|
28
|
+
sectionIds?: string[]; /** The talk so far, so the instruction can refer to it. */
|
|
29
|
+
history?: readonly ChatTurn[];
|
|
30
|
+
}, llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void): Promise<EditSuggestResult>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ARTICLE_META_VERSION, ArticleMeta } from './article-model.js';
|
|
2
|
+
import { Snapshot } from './article-rules.js';
|
|
3
|
+
/**
|
|
4
|
+
* The portable form of one article (article-model plan, section 2): a small folder, represented here as a map from
|
|
5
|
+
* path to text so the browser database, an exported folder and the terminal runner all use the same layout.
|
|
6
|
+
*
|
|
7
|
+
* article.md the text, ordinary Markdown
|
|
8
|
+
* article.meta.json everything else, with its own format version
|
|
9
|
+
* sources/<id>.txt stored source passages, kept out of the main metadata file
|
|
10
|
+
* versions/<n>.json published snapshots and checkpoints
|
|
11
|
+
*
|
|
12
|
+
* Loading either succeeds completely or refuses with a message naming what could not be read. Nothing is partly loaded.
|
|
13
|
+
*/
|
|
14
|
+
export type ArticleFolder = Record<string, string>;
|
|
15
|
+
export interface ArticleBundle {
|
|
16
|
+
markdown: string;
|
|
17
|
+
meta: ArticleMeta;
|
|
18
|
+
snapshots: Snapshot[];
|
|
19
|
+
}
|
|
20
|
+
export type FolderLoad = {
|
|
21
|
+
ok: true;
|
|
22
|
+
bundle: ArticleBundle;
|
|
23
|
+
} | {
|
|
24
|
+
ok: false;
|
|
25
|
+
reason: string;
|
|
26
|
+
};
|
|
27
|
+
export declare function serializeArticle(bundle: ArticleBundle): ArticleFolder;
|
|
28
|
+
export declare function loadArticleFolder(folder: ArticleFolder): FolderLoad;
|
|
29
|
+
export { ARTICLE_META_VERSION };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ArticleMeta, SourceStatus } from './article-model.js';
|
|
2
|
+
import { Readiness, Snapshot } from './article-rules.js';
|
|
3
|
+
/**
|
|
4
|
+
* Versions and what changed between them (article-model plan, section 7). Pure functions: a line diff of the text, the claims
|
|
5
|
+
* whose shown status changed, the sources added, removed or changed, and the readiness counts side by side.
|
|
6
|
+
*/
|
|
7
|
+
export type DiffLine = {
|
|
8
|
+
type: 'same' | 'add' | 'del';
|
|
9
|
+
text: string;
|
|
10
|
+
};
|
|
11
|
+
/** Line diff by longest common subsequence. Articles are small, so the quadratic table is fine; very long inputs fall back to "all replaced". */
|
|
12
|
+
export declare function diffLines(before: string, after: string): DiffLine[];
|
|
13
|
+
export interface VersionSide {
|
|
14
|
+
markdown: string;
|
|
15
|
+
meta: ArticleMeta;
|
|
16
|
+
}
|
|
17
|
+
export interface VersionComparison {
|
|
18
|
+
text: DiffLine[];
|
|
19
|
+
changedLines: number;
|
|
20
|
+
claims: {
|
|
21
|
+
quote: string;
|
|
22
|
+
from: SourceStatus | 'absent';
|
|
23
|
+
to: SourceStatus | 'absent';
|
|
24
|
+
}[];
|
|
25
|
+
sources: {
|
|
26
|
+
id: string;
|
|
27
|
+
address?: string;
|
|
28
|
+
change: 'added' | 'removed' | 'changed';
|
|
29
|
+
}[];
|
|
30
|
+
readiness: {
|
|
31
|
+
from: Readiness;
|
|
32
|
+
to: Readiness;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export declare function compareVersions(from: VersionSide, to: VersionSide): VersionComparison;
|
|
36
|
+
export interface ChangeSummary {
|
|
37
|
+
/** No earlier version to compare with. */
|
|
38
|
+
first: boolean;
|
|
39
|
+
added: number;
|
|
40
|
+
removed: number;
|
|
41
|
+
/** Headings of the sections whose text changed, were added or were removed. */
|
|
42
|
+
sections: string[];
|
|
43
|
+
/** Claims whose shown status changed, appeared or disappeared. */
|
|
44
|
+
claims: number;
|
|
45
|
+
/** Sources added, removed or changed. */
|
|
46
|
+
sources: number;
|
|
47
|
+
}
|
|
48
|
+
/** What changed from one version to the next, in a form short enough for one line of a list. `from` is undefined for the first version. */
|
|
49
|
+
export declare function summarizeChange(from: VersionSide | undefined, to: VersionSide): ChangeSummary;
|
|
50
|
+
export declare const MAX_CHECKPOINTS = 20;
|
|
51
|
+
/** The label of a version the page saved by itself, and how many of those are kept (the oldest go first). They do not count towards MAX_CHECKPOINTS. */
|
|
52
|
+
export declare const AUTOSAVE_LABEL = "Autosaved";
|
|
53
|
+
export declare const MAX_AUTOSAVES = 30;
|
|
54
|
+
/** Adds a snapshot, keeping every published one, at most MAX_CHECKPOINTS of the newest checkpoints the writer or an action made, and at most MAX_AUTOSAVES of the newest autosaved ones. */
|
|
55
|
+
export declare function addSnapshot(snapshots: readonly Snapshot[], snapshot: Snapshot, maxCheckpoints?: number): Snapshot[];
|
|
56
|
+
/** True when a new text differs enough from the last one that the writer would want to be able to go back: at least 5 changed lines and 40% of the longer text. */
|
|
57
|
+
export declare function isLargeChange(before: string, after: string): boolean;
|
|
58
|
+
export interface InlinePart {
|
|
59
|
+
type: 'same' | 'del' | 'add';
|
|
60
|
+
text: string;
|
|
61
|
+
}
|
|
62
|
+
/** One line of a change as shown to the writer: a line only in one version, or a line changed in place with its words marked. */
|
|
63
|
+
export type DisplayLine = {
|
|
64
|
+
type: 'add' | 'del';
|
|
65
|
+
text: string;
|
|
66
|
+
} | {
|
|
67
|
+
type: 'change';
|
|
68
|
+
parts: InlinePart[];
|
|
69
|
+
};
|
|
70
|
+
/** The words of a line changed into the words of another, as one run of parts; undefined when the two lines have too little in common to read as an edit of each other. */
|
|
71
|
+
export declare function inlineDiff(before: string, after: string): InlinePart[] | undefined;
|
|
72
|
+
/** The changed lines of a comparison, without the unchanged ones; a removed line and an added line that is an edit of it become one line with the changed words marked. */
|
|
73
|
+
export declare function diffForDisplay(lines: readonly DiffLine[]): DisplayLine[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { ArticleMeta, Idea } from './article-model.js';
|
|
3
|
+
export type IdeaResult = {
|
|
4
|
+
ok: true;
|
|
5
|
+
meta: ArticleMeta;
|
|
6
|
+
idea: Idea;
|
|
7
|
+
} | {
|
|
8
|
+
ok: false;
|
|
9
|
+
reason: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function addIdea(meta: ArticleMeta, input: {
|
|
12
|
+
text: string;
|
|
13
|
+
origin: Idea['origin'];
|
|
14
|
+
model?: string;
|
|
15
|
+
sectionId?: string;
|
|
16
|
+
}, now: string): IdeaResult;
|
|
17
|
+
export declare function setIdeaState(meta: ArticleMeta, id: string, state: Idea['state']): IdeaResult;
|
|
18
|
+
export declare function editIdea(meta: ArticleMeta, id: string, patch: {
|
|
19
|
+
text?: string;
|
|
20
|
+
sectionId?: string | null;
|
|
21
|
+
}): IdeaResult;
|
|
22
|
+
export declare function removeIdea(meta: ArticleMeta, id: string): ArticleMeta;
|
|
23
|
+
export interface IdeaSuggestion {
|
|
24
|
+
status: 'suggested' | 'failed';
|
|
25
|
+
meta: ArticleMeta;
|
|
26
|
+
added: Idea[];
|
|
27
|
+
}
|
|
28
|
+
export declare function suggestIdeas(input: {
|
|
29
|
+
meta: ArticleMeta;
|
|
30
|
+
markdown: string;
|
|
31
|
+
request?: string;
|
|
32
|
+
now: string;
|
|
33
|
+
modelName?: string;
|
|
34
|
+
}, llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void): Promise<IdeaSuggestion>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ArticleMeta, Claim } from './article-model.js';
|
|
2
|
+
/**
|
|
3
|
+
* Issues in batches. Everything that needs the writer's attention is grouped by what it is, so it can be dealt with one category at a time
|
|
4
|
+
* or all together. This module only decides which items belong to which category (from the article's own records, no language judgement);
|
|
5
|
+
* the service runs the batch actions.
|
|
6
|
+
*
|
|
7
|
+
* suggestions suggested changes waiting for Accept or Reject
|
|
8
|
+
* comments open reviewer comments the writer can act on (comments in conflict are listed apart: they need the writer's choice)
|
|
9
|
+
* checkable factual claims with a stored source passage that have not been checked, or whose check no longer applies
|
|
10
|
+
* unsupported factual claims with no source, or that their source does not support
|
|
11
|
+
* sections sections marked as needing review
|
|
12
|
+
* links links Aielia proposed (between sections, and between claims and sources) that wait for the writer
|
|
13
|
+
* stale suggestions that can no longer be applied because the text under them changed
|
|
14
|
+
*/
|
|
15
|
+
export type IssueCategory = 'suggestions' | 'comments' | 'checkable' | 'unsupported' | 'sections' | 'links' | 'stale';
|
|
16
|
+
export interface IssueItem {
|
|
17
|
+
id: string;
|
|
18
|
+
label: string;
|
|
19
|
+
detail?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface IssueBatch {
|
|
22
|
+
category: IssueCategory;
|
|
23
|
+
title: string;
|
|
24
|
+
items: IssueItem[];
|
|
25
|
+
/** Open comments that conflict with each other. Not part of any batch action. */
|
|
26
|
+
needsYourChoice?: IssueItem[];
|
|
27
|
+
}
|
|
28
|
+
export declare const ISSUE_CATEGORIES: IssueCategory[];
|
|
29
|
+
/** The factual claims that can be checked right now: a stored passage is attached and nothing valid has been said about the claim yet. */
|
|
30
|
+
export declare function checkableClaims(meta: ArticleMeta): Claim[];
|
|
31
|
+
/** The factual claims that are not backed and cannot be checked now: no source, a source with no passage to read, or a source that does not support them. */
|
|
32
|
+
export declare function unsupportedClaims(meta: ArticleMeta): Claim[];
|
|
33
|
+
export declare function collectIssues(meta: ArticleMeta): IssueBatch[];
|
|
34
|
+
export declare function issueCount(batches: readonly IssueBatch[]): number;
|
|
35
|
+
/**
|
|
36
|
+
* What is left before the article is ready, as plain lines for the answering model, so "what is left?" is answered from the article's own
|
|
37
|
+
* records and not from a guess. At most a few items per group; empty when nothing is open.
|
|
38
|
+
*/
|
|
39
|
+
export declare function renderIssuesForChat(meta: ArticleMeta, perGroup?: number): string;
|
|
40
|
+
/**
|
|
41
|
+
* The article's records cut down to what bears on one piece of text, so `collectIssues` on the result lists only the issues there: suggestions and
|
|
42
|
+
* comments on that text, claims in it, and the section it is in (with the links that start from that section or from a claim in the text).
|
|
43
|
+
*/
|
|
44
|
+
export declare function issuesInRange(meta: ArticleMeta, range: {
|
|
45
|
+
start: number;
|
|
46
|
+
end: number;
|
|
47
|
+
}): ArticleMeta;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ArticleMeta } from './article-model.js';
|
|
2
|
+
/**
|
|
3
|
+
* Where the page tints the text, and in which of three tones. Pure: a claim is marked only where its stored quote still stands at its stored
|
|
4
|
+
* position in the text on screen, so text typed since the last save never gets a tint in the wrong place. The tint covers the whole sentence that
|
|
5
|
+
* holds the claim. Two claims in one sentence share one tint, in the worse tone. Marks never overlap.
|
|
6
|
+
*
|
|
7
|
+
* ok (green): the claim is backed by its source. look (orange): it still needs a source, a check, or a better source (no source, not checked yet,
|
|
8
|
+
* out of date, partly or not backed, or searched for and not found). bad (red): a source says the opposite.
|
|
9
|
+
*/
|
|
10
|
+
export type MarkTone = 'ok' | 'tried' | 'look' | 'bad';
|
|
11
|
+
export interface ClaimMark {
|
|
12
|
+
/** The sentence the tint covers. */
|
|
13
|
+
start: number;
|
|
14
|
+
end: number;
|
|
15
|
+
claimId: string;
|
|
16
|
+
tone: MarkTone;
|
|
17
|
+
/** The status shown to the writer, after the rules for stale and unchecked results. */
|
|
18
|
+
status: string;
|
|
19
|
+
}
|
|
20
|
+
/** The sentence around a quote: back to the end of the previous sentence or the start of the line, forward to the end punctuation or the end of the line. */
|
|
21
|
+
export declare function sentenceAround(text: string, start: number, end: number): {
|
|
22
|
+
start: number;
|
|
23
|
+
end: number;
|
|
24
|
+
};
|
|
25
|
+
export declare function claimMarks(meta: ArticleMeta, markdown: string): ClaimMark[];
|