@kontourai/flow-agents 0.1.2 → 0.3.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/.github/dependabot.yml +23 -0
- package/.github/workflows/release-please.yml +31 -0
- package/.github/workflows/runtime-compat.yml +118 -0
- package/CHANGELOG.md +46 -0
- package/CONTRIBUTING.md +4 -0
- package/README.md +80 -18
- package/build/src/cli/flow-kit.js +9 -4
- package/build/src/cli/init.js +215 -5
- package/build/src/cli/runtime-adapter.js +9 -5
- package/build/src/cli/telemetry-doctor.js +4 -1
- package/build/src/cli/utterance-check.js +65 -1
- package/build/src/runtime-adapters.js +34 -0
- package/build/src/tools/build-universal-bundles.js +285 -0
- package/build/src/tools/filter-installed-packs.js +3 -0
- package/build/src/tools/validate-source-tree.js +5 -1
- package/console.telemetry.json +115 -20
- package/context/scripts/telemetry/lib/config.sh +5 -1
- package/context/settings/flow-agents-settings.json +7 -0
- package/docs/_layouts/default.html +2 -0
- package/docs/context-map.md +1 -0
- package/docs/index.md +53 -4
- package/docs/integrations/conformance.md +246 -0
- package/docs/integrations/framework-adapter.md +275 -0
- package/docs/integrations/harness-install.md +213 -0
- package/docs/integrations/index.md +58 -0
- package/docs/integrations/knowledge-kit-live.md +211 -0
- package/docs/kit-authoring-guide.md +169 -0
- package/docs/north-star.md +2 -2
- package/docs/spec/runtime-hook-surface.md +525 -0
- package/docs/survey-utterance-check.md +211 -94
- package/docs/vision.md +45 -0
- package/evals/acceptance/run.sh +13 -2
- package/evals/acceptance/test_knowledge_kit_live.sh +221 -0
- package/evals/acceptance/test_opencode_harness.sh +121 -0
- package/evals/acceptance/test_pi_harness.sh +113 -0
- package/evals/integration/test_bundle_install.sh +226 -1
- package/evals/integration/test_bundle_lifecycle.sh +641 -0
- package/evals/integration/test_runtime_adapter_activation.sh +113 -1
- package/evals/integration/test_utterance_check.sh +291 -44
- package/evals/run.sh +2 -0
- package/evals/static/test_universal_bundles.sh +137 -2
- package/integrations/strands/README.md +256 -0
- package/integrations/strands/example.py +74 -0
- package/integrations/strands/examples/knowledge_kit_live.py +461 -0
- package/integrations/strands/flow_agents_strands/__init__.py +27 -0
- package/integrations/strands/flow_agents_strands/hooks.py +194 -0
- package/integrations/strands/flow_agents_strands/policy.py +348 -0
- package/integrations/strands/flow_agents_strands/steering.py +225 -0
- package/integrations/strands/flow_agents_strands/telemetry.py +238 -0
- package/integrations/strands/pyproject.toml +38 -0
- package/integrations/strands/tests/__init__.py +0 -0
- package/integrations/strands/tests/test_hooks.py +392 -0
- package/integrations/strands/tests/test_policy.py +315 -0
- package/integrations/strands/tests/test_telemetry.py +184 -0
- package/integrations/strands-ts/README.md +224 -0
- package/integrations/strands-ts/bin/conformance-shim.mjs +257 -0
- package/integrations/strands-ts/package.json +53 -0
- package/integrations/strands-ts/src/hooks.ts +312 -0
- package/integrations/strands-ts/src/index.ts +22 -0
- package/integrations/strands-ts/src/policy.ts +345 -0
- package/integrations/strands-ts/src/telemetry.ts +251 -0
- package/integrations/strands-ts/test/test-policy.ts +322 -0
- package/integrations/strands-ts/test/test-steering.ts +159 -0
- package/integrations/strands-ts/test/test-telemetry.ts +226 -0
- package/integrations/strands-ts/tsconfig.json +20 -0
- package/kits/catalog.json +6 -0
- package/kits/knowledge/adapters/default-store/index.js +821 -0
- package/kits/knowledge/adapters/flow-runner/index.js +1179 -0
- package/kits/knowledge/adapters/flow-runner/telemetry.js +174 -0
- package/kits/knowledge/docs/README.md +135 -0
- package/kits/knowledge/docs/store-contract.md +526 -0
- package/kits/knowledge/evals/consolidation/suite.test.js +1234 -0
- package/kits/knowledge/evals/contract-suite/suite.test.js +670 -0
- package/kits/knowledge/evals/ingest-compile/suite.test.js +574 -0
- package/kits/knowledge/evals/synthesis/suite.test.js +909 -0
- package/kits/knowledge/flows/compile.flow.json +60 -0
- package/kits/knowledge/flows/consolidate.flow.json +77 -0
- package/kits/knowledge/flows/ingest.flow.json +60 -0
- package/kits/knowledge/flows/store-contract.flow.json +48 -0
- package/kits/knowledge/flows/synthesize.flow.json +77 -0
- package/kits/knowledge/kit.json +78 -0
- package/package.json +7 -2
- package/packaging/conformance/README.md +142 -0
- package/packaging/conformance/fixtures/config-protection--allow-no-path.json +18 -0
- package/packaging/conformance/fixtures/config-protection--allow-safe-file.json +20 -0
- package/packaging/conformance/fixtures/config-protection--block-biome.json +20 -0
- package/packaging/conformance/fixtures/config-protection--block-eslintrc.json +20 -0
- package/packaging/conformance/fixtures/quality-gate--allow-no-path.json +17 -0
- package/packaging/conformance/fixtures/quality-gate--allow-nonexistent-file.json +19 -0
- package/packaging/conformance/fixtures/stop-goal-fit--allow-clean-cwd.json +17 -0
- package/packaging/conformance/fixtures/stop-goal-fit--block-strict-mode.json +23 -0
- package/packaging/conformance/fixtures/stop-goal-fit--warn-active-delivery.json +21 -0
- package/packaging/conformance/fixtures/workflow-steering--allow-no-state.json +16 -0
- package/packaging/conformance/fixtures/workflow-steering--inject-active-state.json +29 -0
- package/packaging/conformance/fixtures/workflow-steering--inject-subagent-steering.json +25 -0
- package/packaging/conformance/package.json +4 -0
- package/packaging/conformance/run-conformance.js +322 -0
- package/packaging/manifest.json +59 -0
- package/schemas/flow-agents-settings.schema.json +48 -0
- package/scripts/README.md +4 -0
- package/scripts/dogfood.js +16 -0
- package/scripts/hooks/opencode-hook-adapter.js +123 -0
- package/scripts/hooks/opencode-telemetry-hook.js +101 -0
- package/scripts/hooks/pi-hook-adapter.js +123 -0
- package/scripts/hooks/pi-telemetry-hook.js +105 -0
- package/scripts/hooks/run-hook.js +8 -0
- package/scripts/hooks/utterance-check.js +124 -22
- package/scripts/telemetry/lib/config.sh +5 -1
- package/src/cli/flow-kit.ts +10 -4
- package/src/cli/init.ts +219 -6
- package/src/cli/runtime-adapter.ts +10 -5
- package/src/cli/telemetry-doctor.ts +4 -1
- package/src/cli/utterance-check.ts +71 -1
- package/src/runtime-adapters.ts +35 -0
- package/src/tools/build-universal-bundles.ts +283 -0
- package/src/tools/filter-installed-packs.ts +3 -0
- package/src/tools/validate-source-tree.ts +5 -1
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Knowledge Kit — Telemetry Helper
|
|
3
|
+
*
|
|
4
|
+
* Emits canonical Flow Agents telemetry events (schema v0.3.0) to a JSONL
|
|
5
|
+
* sink file. Matches the event shape produced by telemetry.sh and the Python
|
|
6
|
+
* TelemetrySink in integrations/strands/flow_agents_strands/telemetry.py.
|
|
7
|
+
*
|
|
8
|
+
* Zero runtime dependencies beyond Node.js built-ins.
|
|
9
|
+
* Fails open: telemetry errors never block kit operations.
|
|
10
|
+
*
|
|
11
|
+
* Sink path: <workspace>/.telemetry/full.jsonl
|
|
12
|
+
* The workspace is resolved from FLOW_AGENTS_WORKSPACE env var, falling back
|
|
13
|
+
* to process.cwd().
|
|
14
|
+
*
|
|
15
|
+
* @module adapters/flow-runner/telemetry
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import * as fs from "node:fs";
|
|
19
|
+
import * as path from "node:path";
|
|
20
|
+
import * as crypto from "node:crypto";
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Schema constants
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
const SCHEMA_VERSION = "0.3.0";
|
|
27
|
+
|
|
28
|
+
// Canonical event name → schema event_type (mirrors telemetry.sh schema_event_type())
|
|
29
|
+
const CANONICAL_TO_SCHEMA = {
|
|
30
|
+
agentSpawn: "session.start",
|
|
31
|
+
userPromptSubmit: "turn.user",
|
|
32
|
+
preToolUse: "tool.invoke",
|
|
33
|
+
permissionRequest: "tool.permission_request",
|
|
34
|
+
postToolUse: "tool.result",
|
|
35
|
+
stop: "session.end",
|
|
36
|
+
subagentStart: "agent.delegate",
|
|
37
|
+
subagentStop: "agent.delegate",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function schemaEventType(canonical) {
|
|
41
|
+
return CANONICAL_TO_SCHEMA[canonical] || "unknown";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Sink resolution
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
function resolveSinkPath(workspace) {
|
|
49
|
+
const ws = workspace || process.env.FLOW_AGENTS_WORKSPACE || process.cwd();
|
|
50
|
+
return path.join(ws, ".telemetry", "full.jsonl");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// KnowledgeTelemetry
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Thin telemetry sink for the Knowledge Kit flow runner.
|
|
59
|
+
*
|
|
60
|
+
* Usage:
|
|
61
|
+
* const tel = new KnowledgeTelemetry({ workspace: "/path/to/workspace" });
|
|
62
|
+
* tel.emitGate("knowledge.ingest", "classify-gate", { category: "research", record_id: id });
|
|
63
|
+
*/
|
|
64
|
+
export class KnowledgeTelemetry {
|
|
65
|
+
/**
|
|
66
|
+
* @param {{ workspace?: string, agentName?: string, sessionId?: string }} options
|
|
67
|
+
*/
|
|
68
|
+
constructor({ workspace, agentName, sessionId } = {}) {
|
|
69
|
+
this._sinkPath = resolveSinkPath(workspace);
|
|
70
|
+
this._agentName = agentName || "knowledge-kit";
|
|
71
|
+
this._sessionId = sessionId || crypto.randomUUID();
|
|
72
|
+
|
|
73
|
+
// Ensure the sink directory exists; fail open on error
|
|
74
|
+
try {
|
|
75
|
+
fs.mkdirSync(path.dirname(this._sinkPath), { recursive: true });
|
|
76
|
+
} catch {
|
|
77
|
+
// fail open
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// -------------------------------------------------------------------------
|
|
82
|
+
// Core emit
|
|
83
|
+
// -------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Build and append a canonical telemetry event to the JSONL sink.
|
|
87
|
+
* Returns the emitted event object (useful for tests).
|
|
88
|
+
* Fails open: never throws.
|
|
89
|
+
*
|
|
90
|
+
* @param {string} canonicalEvent - canonical event name (e.g. "preToolUse")
|
|
91
|
+
* @param {object} [extra] - additional fields merged into the event
|
|
92
|
+
* @returns {object} the emitted event
|
|
93
|
+
*/
|
|
94
|
+
emit(canonicalEvent, extra) {
|
|
95
|
+
const schemaType = schemaEventType(canonicalEvent);
|
|
96
|
+
const event = {
|
|
97
|
+
schema_version: SCHEMA_VERSION,
|
|
98
|
+
timestamp: String(Date.now()),
|
|
99
|
+
session_id: this._sessionId,
|
|
100
|
+
event_id: crypto.randomUUID(),
|
|
101
|
+
event_type: schemaType,
|
|
102
|
+
agent: {
|
|
103
|
+
name: this._agentName,
|
|
104
|
+
runtime: "knowledge-kit",
|
|
105
|
+
version: "unknown",
|
|
106
|
+
},
|
|
107
|
+
hook: {
|
|
108
|
+
event_name: canonicalEvent,
|
|
109
|
+
runtime_session_id: "",
|
|
110
|
+
turn_id: "",
|
|
111
|
+
transcript_path: "",
|
|
112
|
+
model: "",
|
|
113
|
+
source: "knowledge-kit",
|
|
114
|
+
stop_hook_active: null,
|
|
115
|
+
last_assistant_message: "",
|
|
116
|
+
raw_input: null,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
if (extra && typeof extra === "object") {
|
|
121
|
+
Object.assign(event, extra);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
fs.appendFileSync(this._sinkPath, JSON.stringify(event) + "\n", "utf8");
|
|
126
|
+
} catch {
|
|
127
|
+
// fail open — telemetry must never block kit operations
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return event;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// -------------------------------------------------------------------------
|
|
134
|
+
// Semantic helpers
|
|
135
|
+
// -------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Emit a gate event. Used at each flow gate point in the runner.
|
|
139
|
+
*
|
|
140
|
+
* @param {string} flowId - e.g. "knowledge.ingest"
|
|
141
|
+
* @param {string} gateId - e.g. "classify-gate"
|
|
142
|
+
* @param {object} [context] - gate-specific context payload
|
|
143
|
+
* @returns {object} the emitted event
|
|
144
|
+
*/
|
|
145
|
+
emitGate(flowId, gateId, context) {
|
|
146
|
+
return this.emit("preToolUse", {
|
|
147
|
+
tool: {
|
|
148
|
+
name: `${flowId}.${gateId}`,
|
|
149
|
+
normalized_name: "flow.gate",
|
|
150
|
+
input: context || null,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Emit a gate-result event.
|
|
157
|
+
*
|
|
158
|
+
* @param {string} flowId - e.g. "knowledge.ingest"
|
|
159
|
+
* @param {string} gateId - e.g. "classify-gate"
|
|
160
|
+
* @param {object} [result] - gate result payload
|
|
161
|
+
* @returns {object} the emitted event
|
|
162
|
+
*/
|
|
163
|
+
emitGateResult(flowId, gateId, result) {
|
|
164
|
+
return this.emit("postToolUse", {
|
|
165
|
+
tool: {
|
|
166
|
+
name: `${flowId}.${gateId}`,
|
|
167
|
+
normalized_name: "flow.gate",
|
|
168
|
+
output: result || null,
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export default KnowledgeTelemetry;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Knowledge Kit
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Knowledge Kit
|
|
6
|
+
|
|
7
|
+
A Flow Kit for durable, gated knowledge storage. The kit defines a store contract with precise
|
|
8
|
+
record types, mutation operations, and provenance requirements — then ships a default adapter
|
|
9
|
+
backed by markdown files, YAML frontmatter, `[[wikilink]]` inline links, and a JSON graph
|
|
10
|
+
index.
|
|
11
|
+
|
|
12
|
+
Any storage backend can adopt this kit by implementing the contract without forking kit flows.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Contract Summary
|
|
17
|
+
|
|
18
|
+
See [`store-contract.md`](store-contract.md) for the full specification. Quick reference:
|
|
19
|
+
|
|
20
|
+
**Record types**
|
|
21
|
+
|
|
22
|
+
| Type | Purpose |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `raw` | Unprocessed source material — excerpts, transcripts, URLs with notes. |
|
|
25
|
+
| `compiled` | Normalized, editor-reviewed distillations of raw records. |
|
|
26
|
+
| `concept` | Named ideas or principles that other records reference. |
|
|
27
|
+
|
|
28
|
+
**Mutation operations**
|
|
29
|
+
|
|
30
|
+
| Op | Required evidence fields |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `create` | `type`, `title`, `body`, `category`, `provenance.agent` |
|
|
33
|
+
| `update` | `agent` (in evidence) + at least one mutable field |
|
|
34
|
+
| `link` | `agent`, non-empty `links` array |
|
|
35
|
+
| `propose` | `agent`, `proposal` (non-empty) |
|
|
36
|
+
| `apply` | `agent`, `new_body` (non-empty), `rationale` (non-empty) |
|
|
37
|
+
| `reject` | `agent`, `reason` (non-empty) |
|
|
38
|
+
|
|
39
|
+
Every mutation throws with `error.code === "MISSING_EVIDENCE"` when required evidence is absent.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Running the Contract Suite
|
|
44
|
+
|
|
45
|
+
The contract suite is a `node:test` suite parameterized by adapter.
|
|
46
|
+
|
|
47
|
+
### Default adapter (runs automatically)
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
node --test kits/knowledge/evals/contract-suite/suite.test.js
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Alternative adapter
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
KNOWLEDGE_ADAPTER=/path/to/my-adapter.js \
|
|
57
|
+
node --test kits/knowledge/evals/contract-suite/suite.test.js
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or via CLI flag:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
node --test kits/knowledge/evals/contract-suite/suite.test.js \
|
|
64
|
+
-- --adapter=/path/to/my-adapter.js
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Expected output (default adapter)
|
|
68
|
+
|
|
69
|
+
All tests pass and exit 0. Any failure indicates a contract regression or an adapter gap.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Acceptance Criteria Mapping
|
|
74
|
+
|
|
75
|
+
| AC | Requirement | Evidence |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| AC1 | Contract doc exists; mutation ops enumerate evidence fields. | [`docs/store-contract.md`](store-contract.md) — §6 covers all six ops with required-field tables. |
|
|
78
|
+
| AC2 | Default adapter passes contract suite (command evidence). | Run `node --test kits/knowledge/evals/contract-suite/suite.test.js` — exit 0, all tests pass. |
|
|
79
|
+
| AC3 | Record round-trips raw → stored → queried with category + links intact. | Suite §2 "create: round-trip raw → stored → queried" tests this directly. |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Default Adapter Details
|
|
84
|
+
|
|
85
|
+
Located at `adapters/default-store/index.js`. Zero runtime dependencies; uses Node.js
|
|
86
|
+
built-ins only.
|
|
87
|
+
|
|
88
|
+
**Storage layout**
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
<store_root>/
|
|
92
|
+
records/
|
|
93
|
+
<id>.md ← one markdown file per record, YAML frontmatter + body
|
|
94
|
+
graph-index.json ← forward + reverse link index, schema_version 1.0
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Constructor**
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
import DefaultKnowledgeStore from './adapters/default-store/index.js';
|
|
101
|
+
const store = new DefaultKnowledgeStore({ storeRoot: '/path/to/store' });
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Interface** (all methods return Promises):
|
|
105
|
+
|
|
106
|
+
- `create(input)` → `Promise<string>` (new id)
|
|
107
|
+
- `update(id, fields, evidence)` → `Promise<void>`
|
|
108
|
+
- `link(sourceId, links, evidence)` → `Promise<void>`
|
|
109
|
+
- `propose(conceptId, proposerId, evidence)` → `Promise<void>`
|
|
110
|
+
- `apply(conceptId, proposerId, evidence)` → `Promise<void>`
|
|
111
|
+
- `reject(conceptId, proposerId, evidence)` → `Promise<void>`
|
|
112
|
+
- `get(id)` → `Promise<Record | null>`
|
|
113
|
+
- `getLinks(id)` → `Promise<{ forward: Link[], reverse: Link[] }>`
|
|
114
|
+
- `listByCategory(category, options?)` → `Promise<Record[]>`
|
|
115
|
+
- `listByType(type)` → `Promise<Record[]>`
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Flow
|
|
120
|
+
|
|
121
|
+
The kit ships one flow:
|
|
122
|
+
|
|
123
|
+
**`knowledge.store-contract`** — gates on three evidence claims before a store implementation
|
|
124
|
+
is accepted: contract-suite pass, provenance-enforcement pass, and round-trip integrity pass.
|
|
125
|
+
S2 will add pipeline flows for raw ingestion, compilation, and concept management; this flow
|
|
126
|
+
and adapter infrastructure remain the foundation.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Non-Goals (this iteration)
|
|
131
|
+
|
|
132
|
+
- Vector/semantic retrieval (parked as I10)
|
|
133
|
+
- Multi-user concurrency
|
|
134
|
+
- Store migrations
|
|
135
|
+
- Personal-KB import (parked as I11)
|