@tangle-network/agent-app 0.34.0 → 0.35.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/completion-Kaqp_tWk.d.ts +41 -0
- package/dist/intakes/api.d.ts +2 -2
- package/dist/intakes/drizzle.d.ts +2 -2
- package/dist/intakes/index.d.ts +108 -32
- package/dist/intakes/index.js +66 -0
- package/dist/intakes/index.js.map +1 -1
- package/dist/intakes-react/index.d.ts +1 -1
- package/dist/intakes-react/lazy.d.ts +1 -1
- package/dist/{model-Cuj7d-xT.d.ts → model-Bzi5i63l.d.ts} +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { e as IntakeAnswers, b as IntakeGraph, I as IntakeAnswerValue } from './model-Bzi5i63l.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pure completion-state helpers for an intake payload — the small algebra over
|
|
5
|
+
* the JSON blob the store persists. No I/O: the store reads/writes the row;
|
|
6
|
+
* these functions only build and judge the payload shape, so the same logic
|
|
7
|
+
* runs in the UI, the handlers, and the DB layer without divergence.
|
|
8
|
+
*
|
|
9
|
+
* A payload is `{ graphId, answers, completedAt? }`. It carries the answers
|
|
10
|
+
* and the id of the graph they were collected against, so a later graph
|
|
11
|
+
* revision can detect a stale payload (`graphId` mismatch) rather than
|
|
12
|
+
* silently mixing answers from two question sets.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** The persisted JSON for one intake (the `payload` column). */
|
|
16
|
+
interface IntakePayload {
|
|
17
|
+
/** The graph id the answers were collected against — guards stale schemas. */
|
|
18
|
+
graphId: string;
|
|
19
|
+
answers: IntakeAnswers;
|
|
20
|
+
/** ISO-8601 instant the intake was completed, or undefined while in progress. */
|
|
21
|
+
completedAt?: string;
|
|
22
|
+
}
|
|
23
|
+
/** An empty payload for a fresh intake against `graph`. */
|
|
24
|
+
declare function emptyPayload(graph: IntakeGraph): IntakePayload;
|
|
25
|
+
/** A copy of `payload` with one answer set (does not mutate the input). */
|
|
26
|
+
declare function withAnswer(payload: IntakePayload, questionId: string, value: IntakeAnswerValue): IntakePayload;
|
|
27
|
+
/**
|
|
28
|
+
* True when the payload's answers complete the graph AND the payload was
|
|
29
|
+
* collected against THIS graph. A `graphId` mismatch is never "complete" —
|
|
30
|
+
* the answers belong to a different question set and must be re-collected.
|
|
31
|
+
*/
|
|
32
|
+
declare function payloadComplete(graph: IntakeGraph, payload: IntakePayload): boolean;
|
|
33
|
+
/** True when the payload was collected against a DIFFERENT graph revision. */
|
|
34
|
+
declare function payloadIsStale(graph: IntakeGraph, payload: IntakePayload): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Stamp the payload complete at `at` (default now). Returns a copy; pure. The
|
|
37
|
+
* caller has already checked `payloadComplete` — this only records the instant.
|
|
38
|
+
*/
|
|
39
|
+
declare function markComplete(payload: IntakePayload, at?: Date): IntakePayload;
|
|
40
|
+
|
|
41
|
+
export { type IntakePayload as I, payloadIsStale as a, emptyPayload as e, markComplete as m, payloadComplete as p, withAnswer as w };
|
package/dist/intakes/api.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { I as IntakeAnswerValue, a as IntakeQuestion, b as IntakeGraph } from '../model-
|
|
1
|
+
import { I as IntakeAnswerValue, a as IntakeQuestion, b as IntakeGraph } from '../model-Bzi5i63l.js';
|
|
2
2
|
import { IntakeStore } from './drizzle.js';
|
|
3
3
|
import 'drizzle-orm/sqlite-core';
|
|
4
|
-
import '
|
|
4
|
+
import '../completion-Kaqp_tWk.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Framework-neutral intake API: the get-current / save-answer / complete logic,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as drizzle_orm_sqlite_core from 'drizzle-orm/sqlite-core';
|
|
2
2
|
import { AnySQLiteTable, AnySQLiteColumn, BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';
|
|
3
|
-
import { I as IntakeAnswerValue, b as IntakeGraph } from '../model-
|
|
4
|
-
import { IntakePayload } from '
|
|
3
|
+
import { I as IntakeAnswerValue, b as IntakeGraph } from '../model-Bzi5i63l.js';
|
|
4
|
+
import { I as IntakePayload } from '../completion-Kaqp_tWk.js';
|
|
5
5
|
|
|
6
6
|
/** A product table referenced by FK — only the `id` column is touched. */
|
|
7
7
|
type IntakeParentTable = AnySQLiteTable & {
|
package/dist/intakes/index.d.ts
CHANGED
|
@@ -1,42 +1,118 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
export { A as AnswerRejectionReason, c as AnswerValidationResult, d as IntakeAnswerType, I as IntakeAnswerValue, e as IntakeAnswers, b as IntakeGraph, f as IntakeOption, a as IntakeQuestion, g as getQuestion, h as hasAnswer, i as intakeProgress, j as isComplete, n as nextQuestion, r as reachableQuestions, v as validateAnswer } from '../model-Bzi5i63l.js';
|
|
2
|
+
export { I as IntakePayload, e as emptyPayload, m as markComplete, p as payloadComplete, a as payloadIsStale, w as withAnswer } from '../completion-Kaqp_tWk.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Pure
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Pure context-sufficiency floor + conversational-gather scaffold — the
|
|
6
|
+
* product-agnostic core of a CONVERSATIONAL intake. Where the question-graph
|
|
7
|
+
* model (`./model`) runs a one-question-at-a-time interview, this leaf judges
|
|
8
|
+
* whether an agent has gathered ENOUGH context to act, and renders the prompt
|
|
9
|
+
* directive that tells the agent to fold the remaining gaps into its work
|
|
10
|
+
* instead of running a form.
|
|
9
11
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Zero dependencies: no drizzle, no env, no react, no I/O, no product reads.
|
|
13
|
+
* A product declares WHICH facts matter (`ContextFactSpec`), and its own
|
|
14
|
+
* adapter resolves those facts + named substrate flags from whatever substrate
|
|
15
|
+
* it owns (`ResolvedContextSignals`); this leaf only does the deterministic
|
|
16
|
+
* combine and the wording. That separation is what makes the framework opt-in
|
|
17
|
+
* and tree-shakeable, and what lets gtm/tax/legal/insurance share one core.
|
|
18
|
+
*
|
|
19
|
+
* Readiness is a two-part floor: SCOPE (every required fact has a value) AND
|
|
20
|
+
* SUBSTRATE (at least one named substrate flag is true). Scope alone is not
|
|
21
|
+
* enough — knowing the goal without any durable thing to act on is still
|
|
22
|
+
* not-ready; substrate alone is not enough either. The product's adapter
|
|
23
|
+
* decides what counts as a fact and what counts as substrate.
|
|
14
24
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
|
|
25
|
+
/** One fact the product treats as known context once it has a value. */
|
|
26
|
+
interface ContextFact {
|
|
27
|
+
/** Stable key the resolved-signals map is keyed on. */
|
|
28
|
+
key: string;
|
|
29
|
+
/** Human label shown in the prompt's known/missing lists. */
|
|
30
|
+
label: string;
|
|
31
|
+
/** When true, this fact must have a value for SCOPE to be met. */
|
|
32
|
+
required?: boolean;
|
|
33
|
+
/** How the agent should gather this fact conversationally, if missing. */
|
|
34
|
+
gatherHint?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The product's declaration of what context matters: the facts that make up
|
|
38
|
+
* scope, plus optional tool hints appended verbatim to the gather prompt (e.g.
|
|
39
|
+
* a product passes the command that extracts a brand from a URL). Pure data —
|
|
40
|
+
* the product supplies labels, hints, and tool lines; the framework never
|
|
41
|
+
* names a product-specific concept itself.
|
|
42
|
+
*/
|
|
43
|
+
interface ContextFactSpec {
|
|
44
|
+
facts: ContextFact[];
|
|
45
|
+
/** Lines appended after the gather directive — e.g. product tool pointers. */
|
|
46
|
+
toolHints?: string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* What a product's adapter resolves from its own substrate, ready to combine.
|
|
50
|
+
* `facts` carries the resolved VALUE per fact key (undefined/empty = not
|
|
51
|
+
* known); `substrate` carries named boolean flags (e.g.
|
|
52
|
+
* `{ brandConfirmed, configHasContext, coreKnowledgePresent }`) — any one true
|
|
53
|
+
* satisfies the substrate half of the floor.
|
|
54
|
+
*/
|
|
55
|
+
interface ResolvedContextSignals {
|
|
56
|
+
facts: Record<string, string | undefined>;
|
|
57
|
+
substrate: Record<string, boolean>;
|
|
58
|
+
}
|
|
59
|
+
/** A resolved fact that has a value — surfaced to the prompt as known context. */
|
|
60
|
+
interface KnownFact {
|
|
61
|
+
key: string;
|
|
62
|
+
label: string;
|
|
63
|
+
value: string;
|
|
64
|
+
}
|
|
65
|
+
/** A required fact with no value — surfaced to the prompt as a gap to close. */
|
|
66
|
+
interface MissingFact {
|
|
67
|
+
key: string;
|
|
68
|
+
label: string;
|
|
69
|
+
gatherHint?: string;
|
|
70
|
+
}
|
|
71
|
+
/** The deterministic verdict over the resolved signals. */
|
|
72
|
+
interface ContextSufficiency {
|
|
73
|
+
/** True when the floor is met: `hasScope && hasSubstrate`. */
|
|
74
|
+
ready: boolean;
|
|
75
|
+
/** Every REQUIRED fact has a non-empty value. */
|
|
76
|
+
hasScope: boolean;
|
|
77
|
+
/** At least one named substrate flag is true. */
|
|
78
|
+
hasSubstrate: boolean;
|
|
79
|
+
/** Facts (required or not) that have a value. */
|
|
80
|
+
knownFacts: KnownFact[];
|
|
81
|
+
/** Required facts that have no value yet. */
|
|
82
|
+
missingFacts: MissingFact[];
|
|
83
|
+
/** The substrate flags as resolved, passed through for the prompt/caller. */
|
|
84
|
+
substrate: Record<string, boolean>;
|
|
23
85
|
}
|
|
24
|
-
/** An empty payload for a fresh intake against `graph`. */
|
|
25
|
-
declare function emptyPayload(graph: IntakeGraph): IntakePayload;
|
|
26
|
-
/** A copy of `payload` with one answer set (does not mutate the input). */
|
|
27
|
-
declare function withAnswer(payload: IntakePayload, questionId: string, value: IntakeAnswerValue): IntakePayload;
|
|
28
86
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
87
|
+
* Combine a fact spec with resolved signals into the readiness verdict. Pure,
|
|
88
|
+
* deterministic, never throws — a missing fact key or an empty substrate map
|
|
89
|
+
* reads as not-ready, not an error, so a fresh scope is honestly not-ready
|
|
90
|
+
* rather than crashing the caller.
|
|
91
|
+
*
|
|
92
|
+
* SCOPE = every `required` fact resolves to a non-empty value.
|
|
93
|
+
* SUBSTRATE = any value in `signals.substrate` is true.
|
|
94
|
+
* READY = SCOPE && SUBSTRATE.
|
|
95
|
+
*
|
|
96
|
+
* `knownFacts` lists every fact (required or optional) that resolved to a
|
|
97
|
+
* value, in spec declaration order; `missingFacts` lists every REQUIRED fact
|
|
98
|
+
* that did not — optional facts never appear as missing because they never gate
|
|
99
|
+
* scope.
|
|
32
100
|
*/
|
|
33
|
-
declare function
|
|
34
|
-
/** True when the payload was collected against a DIFFERENT graph revision. */
|
|
35
|
-
declare function payloadIsStale(graph: IntakeGraph, payload: IntakePayload): boolean;
|
|
101
|
+
declare function computeContextSufficiency(spec: ContextFactSpec, signals: ResolvedContextSignals): ContextSufficiency;
|
|
36
102
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
103
|
+
* Render the prompt section that mirrors a conversational-gather flow:
|
|
104
|
+
* - "### Context you already have" — the known facts, as `label: value`.
|
|
105
|
+
* - "### Context still missing — gather it while you work, not as a form" —
|
|
106
|
+
* the missing facts (with their gather hints), the act-first directive, and
|
|
107
|
+
* any product tool hints appended verbatim.
|
|
108
|
+
*
|
|
109
|
+
* When scope is met but the floor still is not (no substrate flag), it emits
|
|
110
|
+
* the substrate directive instead of a missing-facts list. Returns '' when
|
|
111
|
+
* there is nothing to say (no known facts, no gaps, and ready) so a caller can
|
|
112
|
+
* concatenate it unconditionally. Pure: wording is product-neutral; every
|
|
113
|
+
* product-specific phrase comes from the spec's labels, gather hints, and tool
|
|
114
|
+
* hints.
|
|
39
115
|
*/
|
|
40
|
-
declare function
|
|
116
|
+
declare function buildContextGatherPrompt(spec: ContextFactSpec, sufficiency: ContextSufficiency): string;
|
|
41
117
|
|
|
42
|
-
export {
|
|
118
|
+
export { type ContextFact, type ContextFactSpec, type ContextSufficiency, type KnownFact, type MissingFact, type ResolvedContextSignals, buildContextGatherPrompt, computeContextSufficiency };
|
package/dist/intakes/index.js
CHANGED
|
@@ -14,7 +14,73 @@ import {
|
|
|
14
14
|
reachableQuestions,
|
|
15
15
|
validateAnswer
|
|
16
16
|
} from "../chunk-ND3XEGBE.js";
|
|
17
|
+
|
|
18
|
+
// src/intakes/context-sufficiency.ts
|
|
19
|
+
function presentValue(value) {
|
|
20
|
+
if (typeof value !== "string") return void 0;
|
|
21
|
+
const trimmed = value.trim();
|
|
22
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
23
|
+
}
|
|
24
|
+
function computeContextSufficiency(spec, signals) {
|
|
25
|
+
const facts = spec.facts ?? [];
|
|
26
|
+
const resolvedFacts = signals.facts ?? {};
|
|
27
|
+
const substrate = signals.substrate ?? {};
|
|
28
|
+
const knownFacts = [];
|
|
29
|
+
const missingFacts = [];
|
|
30
|
+
let hasScope = true;
|
|
31
|
+
for (const fact of facts) {
|
|
32
|
+
const value = presentValue(resolvedFacts[fact.key]);
|
|
33
|
+
if (value !== void 0) {
|
|
34
|
+
knownFacts.push({ key: fact.key, label: fact.label, value });
|
|
35
|
+
} else if (fact.required) {
|
|
36
|
+
hasScope = false;
|
|
37
|
+
missingFacts.push({ key: fact.key, label: fact.label, gatherHint: fact.gatherHint });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const hasSubstrate = Object.values(substrate).some(Boolean);
|
|
41
|
+
return {
|
|
42
|
+
ready: hasScope && hasSubstrate,
|
|
43
|
+
hasScope,
|
|
44
|
+
hasSubstrate,
|
|
45
|
+
knownFacts,
|
|
46
|
+
missingFacts,
|
|
47
|
+
substrate
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var GATHER_DIRECTIVE = "Do not run an interview. Act on the message first, then fold AT MOST one or two pointed questions into the same turn to close the highest-leverage gap. Never present a form.";
|
|
51
|
+
var SUBSTRATE_DIRECTIVE = "You have the scope but no durable substrate to act on yet. As you work, persist what you learn \u2014 that is what makes this context-ready.";
|
|
52
|
+
function buildContextGatherPrompt(spec, sufficiency) {
|
|
53
|
+
const lines = [];
|
|
54
|
+
if (sufficiency.knownFacts.length > 0) {
|
|
55
|
+
lines.push("### Context you already have");
|
|
56
|
+
lines.push(sufficiency.knownFacts.map((f) => `- ${f.label}: ${f.value}`).join("\n"));
|
|
57
|
+
}
|
|
58
|
+
if (sufficiency.missingFacts.length > 0) {
|
|
59
|
+
if (lines.length > 0) lines.push("");
|
|
60
|
+
lines.push("### Context still missing \u2014 gather it while you work, not as a form");
|
|
61
|
+
const gaps = sufficiency.missingFacts.map((f) => f.gatherHint ? `- ${f.label} \u2014 ${f.gatherHint}` : `- ${f.label}`).join("\n");
|
|
62
|
+
lines.push(`You do NOT have:
|
|
63
|
+
${gaps}`);
|
|
64
|
+
lines.push(GATHER_DIRECTIVE);
|
|
65
|
+
for (const hint of spec.toolHints ?? []) {
|
|
66
|
+
const trimmed = hint.trim();
|
|
67
|
+
if (trimmed) lines.push(trimmed);
|
|
68
|
+
}
|
|
69
|
+
} else if (!sufficiency.ready) {
|
|
70
|
+
if (lines.length > 0) lines.push("");
|
|
71
|
+
lines.push(SUBSTRATE_DIRECTIVE);
|
|
72
|
+
for (const hint of spec.toolHints ?? []) {
|
|
73
|
+
const trimmed = hint.trim();
|
|
74
|
+
if (trimmed) lines.push(trimmed);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (lines.length === 0) return "";
|
|
78
|
+
return `## Project Context & Sufficiency
|
|
79
|
+
${lines.join("\n")}`;
|
|
80
|
+
}
|
|
17
81
|
export {
|
|
82
|
+
buildContextGatherPrompt,
|
|
83
|
+
computeContextSufficiency,
|
|
18
84
|
emptyPayload,
|
|
19
85
|
getQuestion,
|
|
20
86
|
hasAnswer,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/intakes/context-sufficiency.ts"],"sourcesContent":["/**\n * Pure context-sufficiency floor + conversational-gather scaffold — the\n * product-agnostic core of a CONVERSATIONAL intake. Where the question-graph\n * model (`./model`) runs a one-question-at-a-time interview, this leaf judges\n * whether an agent has gathered ENOUGH context to act, and renders the prompt\n * directive that tells the agent to fold the remaining gaps into its work\n * instead of running a form.\n *\n * Zero dependencies: no drizzle, no env, no react, no I/O, no product reads.\n * A product declares WHICH facts matter (`ContextFactSpec`), and its own\n * adapter resolves those facts + named substrate flags from whatever substrate\n * it owns (`ResolvedContextSignals`); this leaf only does the deterministic\n * combine and the wording. That separation is what makes the framework opt-in\n * and tree-shakeable, and what lets gtm/tax/legal/insurance share one core.\n *\n * Readiness is a two-part floor: SCOPE (every required fact has a value) AND\n * SUBSTRATE (at least one named substrate flag is true). Scope alone is not\n * enough — knowing the goal without any durable thing to act on is still\n * not-ready; substrate alone is not enough either. The product's adapter\n * decides what counts as a fact and what counts as substrate.\n */\n\n/** One fact the product treats as known context once it has a value. */\nexport interface ContextFact {\n /** Stable key the resolved-signals map is keyed on. */\n key: string\n /** Human label shown in the prompt's known/missing lists. */\n label: string\n /** When true, this fact must have a value for SCOPE to be met. */\n required?: boolean\n /** How the agent should gather this fact conversationally, if missing. */\n gatherHint?: string\n}\n\n/**\n * The product's declaration of what context matters: the facts that make up\n * scope, plus optional tool hints appended verbatim to the gather prompt (e.g.\n * a product passes the command that extracts a brand from a URL). Pure data —\n * the product supplies labels, hints, and tool lines; the framework never\n * names a product-specific concept itself.\n */\nexport interface ContextFactSpec {\n facts: ContextFact[]\n /** Lines appended after the gather directive — e.g. product tool pointers. */\n toolHints?: string[]\n}\n\n/**\n * What a product's adapter resolves from its own substrate, ready to combine.\n * `facts` carries the resolved VALUE per fact key (undefined/empty = not\n * known); `substrate` carries named boolean flags (e.g.\n * `{ brandConfirmed, configHasContext, coreKnowledgePresent }`) — any one true\n * satisfies the substrate half of the floor.\n */\nexport interface ResolvedContextSignals {\n facts: Record<string, string | undefined>\n substrate: Record<string, boolean>\n}\n\n/** A resolved fact that has a value — surfaced to the prompt as known context. */\nexport interface KnownFact {\n key: string\n label: string\n value: string\n}\n\n/** A required fact with no value — surfaced to the prompt as a gap to close. */\nexport interface MissingFact {\n key: string\n label: string\n gatherHint?: string\n}\n\n/** The deterministic verdict over the resolved signals. */\nexport interface ContextSufficiency {\n /** True when the floor is met: `hasScope && hasSubstrate`. */\n ready: boolean\n /** Every REQUIRED fact has a non-empty value. */\n hasScope: boolean\n /** At least one named substrate flag is true. */\n hasSubstrate: boolean\n /** Facts (required or not) that have a value. */\n knownFacts: KnownFact[]\n /** Required facts that have no value yet. */\n missingFacts: MissingFact[]\n /** The substrate flags as resolved, passed through for the prompt/caller. */\n substrate: Record<string, boolean>\n}\n\n/** Trim a fact value to a present string, or undefined when blank/absent. */\nfunction presentValue(value: string | undefined): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\n/**\n * Combine a fact spec with resolved signals into the readiness verdict. Pure,\n * deterministic, never throws — a missing fact key or an empty substrate map\n * reads as not-ready, not an error, so a fresh scope is honestly not-ready\n * rather than crashing the caller.\n *\n * SCOPE = every `required` fact resolves to a non-empty value.\n * SUBSTRATE = any value in `signals.substrate` is true.\n * READY = SCOPE && SUBSTRATE.\n *\n * `knownFacts` lists every fact (required or optional) that resolved to a\n * value, in spec declaration order; `missingFacts` lists every REQUIRED fact\n * that did not — optional facts never appear as missing because they never gate\n * scope.\n */\nexport function computeContextSufficiency(\n spec: ContextFactSpec,\n signals: ResolvedContextSignals,\n): ContextSufficiency {\n const facts = spec.facts ?? []\n const resolvedFacts = signals.facts ?? {}\n const substrate = signals.substrate ?? {}\n\n const knownFacts: KnownFact[] = []\n const missingFacts: MissingFact[] = []\n let hasScope = true\n\n for (const fact of facts) {\n const value = presentValue(resolvedFacts[fact.key])\n if (value !== undefined) {\n knownFacts.push({ key: fact.key, label: fact.label, value })\n } else if (fact.required) {\n hasScope = false\n missingFacts.push({ key: fact.key, label: fact.label, gatherHint: fact.gatherHint })\n }\n }\n\n const hasSubstrate = Object.values(substrate).some(Boolean)\n\n return {\n ready: hasScope && hasSubstrate,\n hasScope,\n hasSubstrate,\n knownFacts,\n missingFacts,\n substrate,\n }\n}\n\n/** The directive that turns gaps into conversational gathering, not a form. */\nconst GATHER_DIRECTIVE =\n 'Do not run an interview. Act on the message first, then fold AT MOST one or two pointed questions into the same turn to close the highest-leverage gap. Never present a form.'\n\n/** What to say when scope is met but no durable substrate exists yet. */\nconst SUBSTRATE_DIRECTIVE =\n 'You have the scope but no durable substrate to act on yet. As you work, persist what you learn — that is what makes this context-ready.'\n\n/**\n * Render the prompt section that mirrors a conversational-gather flow:\n * - \"### Context you already have\" — the known facts, as `label: value`.\n * - \"### Context still missing — gather it while you work, not as a form\" —\n * the missing facts (with their gather hints), the act-first directive, and\n * any product tool hints appended verbatim.\n *\n * When scope is met but the floor still is not (no substrate flag), it emits\n * the substrate directive instead of a missing-facts list. Returns '' when\n * there is nothing to say (no known facts, no gaps, and ready) so a caller can\n * concatenate it unconditionally. Pure: wording is product-neutral; every\n * product-specific phrase comes from the spec's labels, gather hints, and tool\n * hints.\n */\nexport function buildContextGatherPrompt(\n spec: ContextFactSpec,\n sufficiency: ContextSufficiency,\n): string {\n const lines: string[] = []\n\n if (sufficiency.knownFacts.length > 0) {\n lines.push('### Context you already have')\n lines.push(sufficiency.knownFacts.map((f) => `- ${f.label}: ${f.value}`).join('\\n'))\n }\n\n if (sufficiency.missingFacts.length > 0) {\n if (lines.length > 0) lines.push('')\n lines.push('### Context still missing — gather it while you work, not as a form')\n const gaps = sufficiency.missingFacts\n .map((f) => (f.gatherHint ? `- ${f.label} — ${f.gatherHint}` : `- ${f.label}`))\n .join('\\n')\n lines.push(`You do NOT have:\\n${gaps}`)\n lines.push(GATHER_DIRECTIVE)\n for (const hint of spec.toolHints ?? []) {\n const trimmed = hint.trim()\n if (trimmed) lines.push(trimmed)\n }\n } else if (!sufficiency.ready) {\n if (lines.length > 0) lines.push('')\n lines.push(SUBSTRATE_DIRECTIVE)\n for (const hint of spec.toolHints ?? []) {\n const trimmed = hint.trim()\n if (trimmed) lines.push(trimmed)\n }\n }\n\n if (lines.length === 0) return ''\n return `## Project Context & Sufficiency\\n${lines.join('\\n')}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0FA,SAAS,aAAa,OAA+C;AACnE,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAiBO,SAAS,0BACd,MACA,SACoB;AACpB,QAAM,QAAQ,KAAK,SAAS,CAAC;AAC7B,QAAM,gBAAgB,QAAQ,SAAS,CAAC;AACxC,QAAM,YAAY,QAAQ,aAAa,CAAC;AAExC,QAAM,aAA0B,CAAC;AACjC,QAAM,eAA8B,CAAC;AACrC,MAAI,WAAW;AAEf,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,aAAa,cAAc,KAAK,GAAG,CAAC;AAClD,QAAI,UAAU,QAAW;AACvB,iBAAW,KAAK,EAAE,KAAK,KAAK,KAAK,OAAO,KAAK,OAAO,MAAM,CAAC;AAAA,IAC7D,WAAW,KAAK,UAAU;AACxB,iBAAW;AACX,mBAAa,KAAK,EAAE,KAAK,KAAK,KAAK,OAAO,KAAK,OAAO,YAAY,KAAK,WAAW,CAAC;AAAA,IACrF;AAAA,EACF;AAEA,QAAM,eAAe,OAAO,OAAO,SAAS,EAAE,KAAK,OAAO;AAE1D,SAAO;AAAA,IACL,OAAO,YAAY;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGA,IAAM,mBACJ;AAGF,IAAM,sBACJ;AAgBK,SAAS,yBACd,MACA,aACQ;AACR,QAAM,QAAkB,CAAC;AAEzB,MAAI,YAAY,WAAW,SAAS,GAAG;AACrC,UAAM,KAAK,8BAA8B;AACzC,UAAM,KAAK,YAAY,WAAW,IAAI,CAAC,MAAM,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,EACrF;AAEA,MAAI,YAAY,aAAa,SAAS,GAAG;AACvC,QAAI,MAAM,SAAS,EAAG,OAAM,KAAK,EAAE;AACnC,UAAM,KAAK,0EAAqE;AAChF,UAAM,OAAO,YAAY,aACtB,IAAI,CAAC,MAAO,EAAE,aAAa,KAAK,EAAE,KAAK,WAAM,EAAE,UAAU,KAAK,KAAK,EAAE,KAAK,EAAG,EAC7E,KAAK,IAAI;AACZ,UAAM,KAAK;AAAA,EAAqB,IAAI,EAAE;AACtC,UAAM,KAAK,gBAAgB;AAC3B,eAAW,QAAQ,KAAK,aAAa,CAAC,GAAG;AACvC,YAAM,UAAU,KAAK,KAAK;AAC1B,UAAI,QAAS,OAAM,KAAK,OAAO;AAAA,IACjC;AAAA,EACF,WAAW,CAAC,YAAY,OAAO;AAC7B,QAAI,MAAM,SAAS,EAAG,OAAM,KAAK,EAAE;AACnC,UAAM,KAAK,mBAAmB;AAC9B,eAAW,QAAQ,KAAK,aAAa,CAAC,GAAG;AACvC,YAAM,UAAU,KAAK,KAAK;AAC1B,UAAI,QAAS,OAAM,KAAK,OAAO;AAAA,IACjC;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO;AAAA,EAAqC,MAAM,KAAK,IAAI,CAAC;AAC9D;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { IntakeInterview } from './index.js';
|
|
3
3
|
export { IntakeInterviewProps } from './index.js';
|
|
4
|
-
import '../model-
|
|
4
|
+
import '../model-Bzi5i63l.js';
|
|
5
5
|
|
|
6
6
|
declare const IntakeInterviewLazy: react.LazyExoticComponent<typeof IntakeInterview>;
|
|
7
7
|
|
|
@@ -113,4 +113,4 @@ declare function intakeProgress(graph: IntakeGraph, answers: IntakeAnswers): {
|
|
|
113
113
|
/** The questions reachable under the current answers, in traversal order. */
|
|
114
114
|
declare function reachableQuestions(graph: IntakeGraph, answers: IntakeAnswers): IntakeQuestion[];
|
|
115
115
|
|
|
116
|
-
export { type AnswerRejectionReason as A, type IntakeAnswerValue as I, type IntakeQuestion as a, type IntakeGraph as b, type
|
|
116
|
+
export { type AnswerRejectionReason as A, type IntakeAnswerValue as I, type IntakeQuestion as a, type IntakeGraph as b, type AnswerValidationResult as c, type IntakeAnswerType as d, type IntakeAnswers as e, type IntakeOption as f, getQuestion as g, hasAnswer as h, intakeProgress as i, isComplete as j, nextQuestion as n, reachableQuestions as r, validateAnswer as v };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"packageManager": "pnpm@10.33.4",
|
|
5
5
|
"description": "Application-shell framework for Tangle agent products: a bounded tool loop, the structured agent→app tool side channel, integration-hub client, per-workspace billing, and crypto — composed over the Tangle agent substrate through typed seams.",
|
|
6
6
|
"keywords": [
|