Polyweave

@polyweave/state-search (1.0.7)

Published 2026-07-11 15:33:08 +00:00 by Dvorak

Installation

@polyweave:registry=https://hub.kl1.tenere.ai/api/packages/Polyweave/npm/
npm install @polyweave/state-search@1.0.7
"@polyweave/state-search": "1.0.7"

About this package

@polyweave/state-search

Composable filter algebra, recursive tree traversal, async tool routing, and DSL query parsing over Polyweave state stores.

Synopsis

import {
  createSleuthRetriever,
  createTreeSearchHarness,
  createTreeSearchToolDuplex,
  traverseTree,
  createTreeClient,
  createTreeSearchTool,
  createMultiStateQueryTool,
  createStateSearchTooling,
  andFilters,
  orFilters,
  notFilter,
  graphFilter,
  treeFilter,
  textFilter,
  predicateFilter,
  temporalFilter,
  spatialFilter,
  leafScope,
  citesDoc,
  writtenBetween,
  locatedIn,
  parseFilter,
  FilterParseError,
  FilterErrorLayer,
  createAsyncToolRouter
} from '@polyweave/state-search';

const retriever = createSleuthRetriever({
  multiState: myMultiStateStore,
  defaultLimit: 10
});

retriever({ query: 'machine learning' }, (err, results) => {
  console.log('Results:', results);
});

Install

npm install @polyweave/state-search

Why

State-search provides a composable filter algebra over polyweave state stores, bridging multi-state document/text/graph/tree stores with a unified query interface. It supports AND/OR/NOT filter composition, DSL parsing, programmatic filter construction, recursive tree traversal with bt-harness navigation, async tool routing for deferred execution, and a SLEUTH-compatible retriever with embedding support. Use it for structured search, filtering, traversal, and agent-driven exploration over federated state backends.

API

Sleuth Retriever (sleuth-retriever.js)

createSleuthRetriever(options) → retrieverFunction

Creates a SLEUTH-compatible retriever for multi-state stores.

createSleuthRetriever(options: object) → (payload: object, done: function) → void
Parameter Type Required Default Description
options.multiState multi-state store Yes Multi-state store with search(); must expose typeof multiState.search === 'function'
options.textStore text store No Optional text store for page content resolution via textStore.get()
options.embeddingRunner embedding runner No Optional embedding runner with runEmbedding(text, callback) for vector search
options.resolvePage function No Custom page resolver: (entry, done)
options.defaultLimit number No 5 Default result limit
options.useProvidedPages boolean No true If true and payload.pages is non-empty, return those pages directly
options.useEmbeddings boolean No false If true, enrich query with embedding before search
options.queryMode string No Query mode passed through to multiState.search()
options.filters filter object No Default filters applied to all searches
options.filterBuilder function No Dynamic filter builder: ({ query, payload }) → filter; overrides filters
options.candidateStores string[] No Candidate stores passed through to multiState.search()
options.candidateLimit number No Candidate limit passed through to multiState.search()
options.planner boolean No true Whether to enable the query planner

Throws: Error('Sleuth retriever requires a multiState store with search().')

The returned retriever function accepts:

Payload Type Description
payload.query / payload.question / payload string Search query
payload.pages any[] Provided pages (returned directly if useProvidedPages is true)
payload.topK number Result limit override
payload.filters filter object Additional filters (combined with default via AND)
payload.useEmbeddings boolean Per-call override for embedding enrichment

Filter System (query-builder.js)

andFilters(...filters) → filter | null

Combines filters with AND logic. Flattens nested arrays. Single filter is returned unwrapped.

Returns: { op: 'and', filters: [...] } or the sole filter, or null if no filters.

orFilters(...filters) → filter | null

Combines filters with OR logic. Same semantics as andFilters.

notFilter(filter) → filter | null

Negates a filter. Returns null if filter is falsy.

Returns: { op: 'not', filter }

graphFilter({ entity?, relation?, temporal?, spatial? }) → filter

Matches documents in a fact graph. Fields are optional; at least one should be provided.

Returns: { source: 'graph', entity, relation, temporal, spatial }

treeFilter({ treeId?, path?, prefix?, nodeId? }) → filter

Matches documents in a tree store by path or node.

Returns: { source: 'tree', treeId, path, prefix: boolean, nodeId }

textFilter(query: string | object) → filter

Full-text match filter. When passed a string, creates { source: 'text', query }. When passed an object, spreads it.

Parameter Type Description
query string object

predicateFilter({ name?, predicate?, args? }) → filter

Field-level predicate filter.

Returns: { source: 'predicate', name, predicate, args }

temporalFilter({ relation?, start?, end? }) → filter

Time-range filter.

Returns: { temporal: { relation, start, end } }

spatialFilter({ relation?, minX?, minY?, maxX?, maxY? }) → filter

Spatial bounding box filter.

Returns: { spatial: { relation, minX, minY, maxX, maxY } }

leafScope({ treeId?, path?, nodeId? }) → filter

Scope filter for leaf node descendants. Wraps treeFilter with prefix: true.

citesDoc(docId: string) → filter

Filter for documents citing a given document. Wraps graphFilter with relation: 'cites'.

writtenBetween(start: any, end: any) → filter

Convenience temporal filter. Wraps graphFilter with relation: 'written_at' and temporal range.

locatedIn(bounds: object) → filter

Convenience spatial filter. Wraps graphFilter with relation: 'located_in' and spatial bounds.


Filter DSL Parser (query-parser.js)

parseFilter(text: string) → filter

Parses a DSL filter string into a filter object using a Peggy grammar.

Throws: FilterParseError on parse failure or semantic validation failure.

DSL grammar examples:

text("climate change")
and(text("neural"), graph(entity="doc:1", relation="cites"))
or(tree(treeId="t1"), not(predicate(name="spam")))
text(query="search", limit=5)

FilterParseError

Error class for filter parsing failures. Extends Error.

Property Type Description
name 'FilterParseError' Error name
layer 'syntax' 'semantic'
location { line, column } null
expected string[] null
youWrote string null
rule string null
fix string null
cause Error null
format(sourceText) function Formats error with source context

FilterErrorLayer

Enum: { SYNTAX: 'syntax', SEMANTIC: 'semantic' }


Error Utilities (query-errors.js)

getLineColumnFromLocation(location) → { line, column, length } | null

Extracts line/column from a Peggy-style location object. Handles both { start: { line, column }, end: { line, column } } and { line, column } formats.

extractYouWrote(sourceText: string, location) → string | null

Extracts the source text fragment at a given location.


Tree Search (tree-search.js)

createTreeClient(store: duplex) → { query }

Creates a callback-based client for a tree store. Handles TREE_RESULT frame routing via streamId.

Returns: { query(content: object, callback: (err, result) => void) } — the content object is merged into a TREE_QUERY frame with a generated streamId.

traverseTree(options, done) → void

Recursive tree traversal with user-guided child selection.

Parameter Type Required Default Description
options.treeStore duplex Yes Tree store to traverse
options.treeId string Yes Tree identifier
options.query string '' Query string passed to chooseChild
options.chooseChild function Yes (query, labels, context, callback) → void — called with candidate child labels; callback receives (err, index) where -1 = stop, 0..n = descend to that child
options.labeler function No defaultLabeler (candidate) → string — labels a candidate for chooseChild
options.leafSelector function No defaultLeafSelector `(result) → { text, citations }
options.maxDepth number No 12 Maximum recursion depth

Error callbacks: traverseTree returns Error via done if treeStore/treeId missing or chooseChild is not a function.

defaultLabeler(candidate) → string

Default node labeler: returns first 80 chars of candidate.data.text for paragraphs, or candidate.data.summary preview for other nodes.

defaultLeafSelector(result) → { text, citations } | null

Default leaf selector: finds first node with data.kind === 'paragraph', returns its text and citations.


Tree Search Harness (tree-search-harness.js)

createTreeSearchHarness(options) → bt-harness

Creates a bt-harness that navigates a hierarchical summary tree using an LLM agent.

Parameter Type Required Default Description
options.treeStore duplex Yes Tree store to navigate
options.treeId string Yes Tree identifier
options.query string No '' Search query
options.maxDepth number No 12 Maximum recursion depth
options.apiKey string Yes API key for LLM calls
options.agentModel string No 'deepseek-v4-flash' Model for the navigation agent
options.evalModel string No 'deepseek-v4-flash' Model for the evaluator
options.agentSystem string No Custom agent system prompt
options.evalSystem string No Custom evaluator system prompt
options.createAdapter function No Custom adapter factory
options.adapterConfig object No Adapter factory configuration
options.timeoutMs number No 120000 Harness timeout
options._debug / options.debug boolean No false Debug output

Returns: bt-harness object ({ source, sink, valid, errors, warnings, symbolics, ... }) or { valid: false, errors: [...] } if treeStore/treeId missing.

createTreeSearchToolDuplex(options) → duplex

Wraps createTreeSearchHarness into a push-stream duplex tool with TOOL_CALL/TICK/CANCEL/ABORT frame handling.

Parameter Type Required Default Description
options.name string No 'tree_recursive_search' Tool name
options.description string No Tool description
options.treeStore duplex Yes Tree store
options.treeId string Yes Tree identifier
options.maxDepth number No 12 Maximum depth
options.apiKey string Yes API key
options.agentModel string No 'deepseek-v4-flash' Agent model
options.evalModel string No 'deepseek-v4-flash' Eval model
options.debug boolean No false Debug flag
options.timeoutMs number No 120000 Timeout
options.createAdapter function No Custom adapter factory
options.adapterConfig object No Adapter factory configuration

Frame protocol:

Input frame Description
TOOL_CALL { query } Start tree search with the given query
TICK Advance the harness one tick
CANCEL Cancel current harness
ABORT Abort current harness
DESCRIBE Returns DESCRIPTION with tool schema
Output frame Description
TOOL_RESULT { text, path, leaf } Search completed
TOOL_RESULT { error } Search failed or harness invalid
DESCRIPTION Response to DESCRIBE

Error conditions:

  • TOOL_CALL while running: returns TOOL_RESULT { error: 'Already running' }
  • Invalid harness: returns TOOL_RESULT { error } with joined error messages
  • BT failure: returns TOOL_RESULT { error } with failure reason
  • BT error: returns TOOL_RESULT { error } with error message

Tooling (tooling.js)

createTreeSearchTool(options) → { tool, handler }

Creates a simple (non-harness) tree search tool and handler pair.

Parameter Type Required Default Description
options.name string No 'tree_recursive_search' Tool name
options.description string No Tool description
options.treeStore duplex Yes Tree store
options.treeId string Yes Tree identifier
options.chooseChild function Yes Child selection function
options.labeler function No Node labeler
options.leafSelector function No Leaf content selector
options.maxDepth number No Maximum depth

createMultiStateQueryTool(options) → { tool, handler }

Creates a multi-state query tool.

Parameter Type Required Default Description
options.name string No 'multistore_query' Tool name
options.description string No Tool description
options.multiState multi-state store Yes Multi-state store
options.defaultLimit number No 5 Default result limit

createStateSearchTooling(options) → { tools, handlers }

Combines tree search and multi-state query tooling into a unified tools + handlers map.

Parameter Type Required Default Description
options.treeStore duplex No If provided, creates a tree search tool
options.treeId string No Required with treeStore
options.chooseChild function No Required with treeStore
options.labeler function No Node labeler
options.leafSelector function No Leaf selector
options.maxDepth number No Maximum depth
options.multiState multi-state store No If provided, creates a multi-state query tool
options.defaultLimit number No Default result limit
options.treeTool object No Overrides for the tree search tool config
options.multiTool object No Overrides for the multi-state query tool config

Async Tool Router (async-tool-router.js)

createAsyncToolRouter(options)

Re-exported from @polyweave/tools. Creates an async tool router for deferred tool execution with concurrency control.

Parameter Type Required Default Description
options.tools Map<string, function> Yes Map of tool name to handler function
options.timeoutMs number No Default timeout for async tools
options.maxConcurrency number No Maximum concurrent tool executions

Returns: { route(toolCall, callback), cancel(requestId), close }

Tests

npm test

Covers: sleuth retriever creation and search with/without embeddings/embedding runners, filter composition (AND/OR/NOT) and all filter types, filter DSL parsing and error handling (syntax, semantic, repair suggestions), tree search traversal with custom labelers/leafSelectors, tree search harness creation and tick-driven execution, async tool routing with concurrency control, and bt-harness tree search integration.

Requirements

  • Node.js 22+
  • ESM only

Dependencies: @polyweave/bt-harness, @polyweave/tools, peggy Peer dependencies: @polyweave/core, @polyweave/state

Dependencies

Dependencies

ID Version
@polyweave/bt-harness *
@polyweave/tools *
peggy ^4.0.2

Development Dependencies

ID Version
@rigor/core *

Peer Dependencies

ID Version
@polyweave/core *

Keywords

polyweave state search tools traversal
Details
npm
2026-07-11 15:33:08 +00:00
446
John Dvorak
SEE LICENSE IN LICENSE
latest
15 KiB
Assets (1)
Versions (5) View all
1.0.7 2026-07-11
1.0.4 2026-07-11
1.0.3 2026-07-11
1.0.2 2026-07-10
1.0.1 2026-07-10