Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
333 changes: 254 additions & 79 deletions bin/knowledge-mcp.js

Large diffs are not rendered by default.

675 changes: 656 additions & 19 deletions bin/knowledge-serve.js

Large diffs are not rendered by default.

440 changes: 220 additions & 220 deletions bin/knowledge.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion dist/agent.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type KnowledgeContextPack, type RetrievalOptions } from './retrieval';
import type { HybridSearchResult } from './search';
import type { KnowledgeItem } from './store';
export interface KnowledgePromptOptions extends Omit<RetrievalOptions, 'query'> {
prompt: string;
Expand Down Expand Up @@ -43,4 +44,4 @@ export interface KnowledgePromptOverItemsOptions extends Omit<KnowledgePromptOpt
* key. There is no local sqlite catalog, so run telemetry is not persisted to a
* local db (it would be split-brain); the run id is still returned for the shape.
*/
export declare function runKnowledgePromptOverItems(items: KnowledgeItem[], options: KnowledgePromptOverItemsOptions): Promise<KnowledgePromptResult>;
export declare function runKnowledgePromptOverItems(items: KnowledgeItem[], options: KnowledgePromptOverItemsOptions, producerSearch?: HybridSearchResult): Promise<KnowledgePromptResult>;
39 changes: 34 additions & 5 deletions dist/cloud-store.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,31 @@
import { type HasnaStorageClient } from '@hasna/contracts/client/storage';
import type { KnowledgeItem, KnowledgeItemVersion, KnowledgeItemVersionList } from './store';
import { KNOWLEDGE_APP_SLUG } from './knowledge-mode.js';
export { KNOWLEDGE_APP_SLUG };
import { KNOWLEDGE_BOUNDED_QUERY_CAPABILITY } from './query-contract.js';
export { KNOWLEDGE_APP_SLUG, KNOWLEDGE_BOUNDED_QUERY_CAPABILITY };
/** Cloud resource path served under /v1 by knowledge-serve. */
export declare const KNOWLEDGE_RESOURCE = "notes";
export interface KnowledgeCloudListOptions {
/** Literal id/title/content filter used by `knowledge list`. */
search?: string;
tag?: string;
includeArchived?: boolean;
archivedOnly?: boolean;
tags?: string[];
archive?: 'active' | 'archived' | 'all';
sort?: 'created' | 'title';
direction?: 'asc' | 'desc';
limit?: number;
offset?: number;
}
export interface KnowledgeCloudSearchOptions {
query: string;
archive?: 'active' | 'archived' | 'all';
limit?: number;
offset?: number;
}
export interface KnowledgeCloudSearchHit {
item: KnowledgeItem;
/** Producer-computed PostgreSQL ts_rank_cd score. */
rank: number;
}
export interface KnowledgeCloudCreateInput {
/** Optional caller-supplied stable id. Forwarded to the server, which upserts
* on it — giving `upsert --id`/import the same idempotency as the local store. */
Expand Down Expand Up @@ -76,6 +90,16 @@ export declare class KnowledgeVersionConflictError extends Error {
readonly code = "version_conflict";
constructor(expected: number, current: number);
}
/**
* Raised when the server response cannot prove that it applied a bounded query
* field that older servers silently ignored.
*/
export declare class KnowledgeBoundedQueryCapabilityError extends Error {
readonly operation: 'list' | 'search';
readonly fields: readonly string[];
readonly code = "bounded_query_capability_required";
constructor(operation: 'list' | 'search', fields: readonly string[]);
}
/**
* The knowledge-item storage surface, cloud edition. Mirrors the operations the
* local db.json store supports so the CLI can call either behind one shape.
Expand All @@ -85,7 +109,12 @@ export interface KnowledgeCloudStore {
readonly baseUrl: string;
list(options?: KnowledgeCloudListOptions): Promise<{
items: KnowledgeItem[];
total: number | null;
total: number;
}>;
/** Ranked producer-side PostgreSQL full-text query. */
search(options: KnowledgeCloudSearchOptions): Promise<{
items: KnowledgeCloudSearchHit[];
total: number;
}>;
get(idOrShort: string): Promise<KnowledgeItem | null>;
create(input: KnowledgeCloudCreateInput): Promise<KnowledgeItem>;
Expand Down
126 changes: 123 additions & 3 deletions dist/guarded-write-contract.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import type { KnowledgeItem } from './store.js';
import type { KnowledgeItem, KnowledgeItemVersion } from './store.js';
export declare const KNOWLEDGE_GUARDED_WRITE_CONTRACT: 'FCAME-1';
export declare const KNOWLEDGE_PRIVATE_INPUT_SCHEMA: 'hasna.knowledge.private-input.v1';
export declare const KNOWLEDGE_PRIVATE_TITLE_LOOKUP_SCHEMA: 'hasna.knowledge.private-title-lookup.v1';
export declare const KNOWLEDGE_PRIVATE_QUERY_SCHEMA: 'hasna.knowledge.private-query.v1';
export declare const KNOWLEDGE_PRIVATE_RESULT_SCHEMA: 'hasna.knowledge.private-result.v1';
export declare const KNOWLEDGE_RELATIONS_SCHEMA: 'hasna.knowledge.relations.v1';
export declare const KNOWLEDGE_RELATIONS_METADATA_KEY: 'hasna_knowledge_relations';
export type KnowledgeAuthorityClassification = 'user_hosted' | 'hasna_saas';
export type KnowledgeGuardedWriteVerb = 'create' | 'update';
export interface KnowledgeAuthorityBinding {
Expand Down Expand Up @@ -208,6 +211,76 @@ export interface CreateKnowledgePrivateTitleLookupDescriptorOptions {
/** Defaults to five minutes; bounded to one hour. */
expires_in_ms?: number;
}
export type KnowledgePrivateQueryKind = 'exact_title' | 'lexical_overlap' | 'semantic_overlap' | 'supersession' | 'current_version' | 'historical_version' | 'canonical_pointer';
export type KnowledgePrivateQuerySelector = {
kind: 'exact_title';
title: string;
} | {
kind: 'lexical_overlap';
query: string;
} | {
kind: 'semantic_overlap';
query: string;
} | {
kind: 'supersession';
supersedes_item_id: string;
} | {
kind: 'current_version';
item_id: string;
} | {
kind: 'historical_version';
item_id: string;
version: number;
} | {
kind: 'canonical_pointer';
canonical_item_id: string;
};
export interface KnowledgeRelationsMetadata {
schema: typeof KNOWLEDGE_RELATIONS_SCHEMA;
supersedes_item_id?: string;
canonical_item_id?: string;
}
export type KnowledgePrivateQueryArchive = 'active' | 'archived' | 'all';
export interface KnowledgePrivateQueryPage {
limit: number;
offset: number;
}
export interface KnowledgePrivateQueryBounds extends KnowledgeGuardedBounds {
max_items: number;
}
export interface KnowledgePrivateQueryDescriptor {
readonly contract: typeof KNOWLEDGE_GUARDED_WRITE_CONTRACT;
readonly schema: typeof KNOWLEDGE_PRIVATE_QUERY_SCHEMA;
/** Process-private handle. Deliberately non-enumerable and omitted by toJSON. */
readonly descriptor_id: string;
readonly operation_id: string;
readonly step_id: string;
readonly query_kind: KnowledgePrivateQueryKind;
readonly selector_digest: string;
readonly binding_digest: string;
readonly binding: KnowledgeGuardedBinding;
readonly archive: KnowledgePrivateQueryArchive;
readonly page: KnowledgePrivateQueryPage;
readonly expires_at: string;
toJSON(): Omit<KnowledgePrivateQueryDescriptor, 'descriptor_id' | 'toJSON'>;
}
export interface CreateKnowledgePrivateQueryDescriptorOptions {
operation_id: string;
step_id: string;
binding: KnowledgeGuardedBinding;
selector: KnowledgePrivateQuerySelector;
archive?: KnowledgePrivateQueryArchive;
limit?: number;
offset?: number;
/** Defaults to five minutes; bounded to one hour. */
expires_in_ms?: number;
}
export interface KnowledgePrivateQueryEnvelope {
contract: typeof KNOWLEDGE_GUARDED_WRITE_CONTRACT;
descriptor: Omit<KnowledgePrivateQueryDescriptor, 'descriptor_id' | 'toJSON'>;
selector: KnowledgePrivateQuerySelector;
limits: KnowledgePrivateQueryBounds;
}
export interface KnowledgeGuardedTitleLookupEnvelope {
contract: typeof KNOWLEDGE_GUARDED_WRITE_CONTRACT;
descriptor: Omit<KnowledgePrivateTitleLookupDescriptor, 'descriptor_id' | 'toJSON'>;
Expand Down Expand Up @@ -373,6 +446,40 @@ export interface KnowledgePrivateItemProof {
metadata_sha256: string;
archived: boolean;
}
export interface KnowledgePrivateQueryItemProof {
/** The producer record id is private; only its digest crosses the result boundary. */
id_sha256: string;
version: number;
title_sha256: string;
content_sha256: string;
url_sha256: string | null;
tags_sha256: string;
metadata_sha256: string;
archived: boolean;
record_kind: 'current' | 'historical';
matched_value_sha256: string | null;
}
export interface KnowledgePrivateQueryResult {
contract: typeof KNOWLEDGE_GUARDED_WRITE_CONTRACT;
exact: true;
bounded: true;
private: true;
query_kind: KnowledgePrivateQueryKind;
status: 'available' | 'unavailable';
code: null | 'semantic_query_unavailable';
binding: KnowledgeGuardedBinding;
selector_digest: string;
total: number;
item_count: number;
page: {
limit: number;
offset: number;
returned: number;
has_more: boolean;
};
items: readonly KnowledgePrivateQueryItemProof[];
limits: KnowledgePrivateQueryBounds;
}
export interface KnowledgeGuardedTitleLookup {
contract: typeof KNOWLEDGE_GUARDED_WRITE_CONTRACT;
exact: true;
Expand All @@ -383,7 +490,7 @@ export interface KnowledgeGuardedTitleLookup {
items: readonly KnowledgePrivateItemProof[];
limits: KnowledgeGuardedBounds;
}
export type KnowledgePrivateResultKind = 'write' | 'readback' | 'title_lookup';
export type KnowledgePrivateResultKind = 'write' | 'readback' | 'title_lookup' | 'query';
export interface KnowledgePrivateResultDescriptor {
readonly contract: typeof KNOWLEDGE_GUARDED_WRITE_CONTRACT;
readonly schema: typeof KNOWLEDGE_PRIVATE_RESULT_SCHEMA;
Expand All @@ -398,16 +505,25 @@ export interface KnowledgePrivateResultDescriptor {
export interface KnowledgePrivateResultProof {
kind: KnowledgePrivateResultKind;
item_count: number;
items: readonly KnowledgePrivateItemProof[];
items: readonly (KnowledgePrivateItemProof | KnowledgePrivateQueryItemProof)[];
deterministic_key?: string;
receipt_id?: string;
duplicate?: boolean;
query_kind?: KnowledgePrivateQueryKind;
status?: KnowledgePrivateQueryResult['status'];
code?: KnowledgePrivateQueryResult['code'];
total?: number;
page?: KnowledgePrivateQueryResult['page'];
}
export declare const DEFAULT_KNOWLEDGE_GUARDED_LIMITS: KnowledgeGuardedLimits;
export declare function assertKnowledgeGuardedBinding(binding: KnowledgeGuardedBinding): void;
export declare function assertKnowledgeGuardedPrecondition(verb: KnowledgeGuardedWriteVerb, precondition: KnowledgeGuardedPrecondition): void;
export declare function assertKnowledgeGuardedManifestBinding(manifest: KnowledgeGuardedManifestBinding): void;
export declare function assertKnowledgeGuardedBounds(bounds: KnowledgeGuardedBounds, field?: string): void;
export declare function assertKnowledgePrivateQueryBounds(bounds: KnowledgePrivateQueryBounds, field?: string): void;
export declare function assertKnowledgePrivateQueryPage(page: KnowledgePrivateQueryPage, bounds: KnowledgePrivateQueryBounds): void;
export declare function assertKnowledgePrivateQuerySelector(selector: KnowledgePrivateQuerySelector): void;
export declare function assertKnowledgeRelationsMetadata(metadata: Record<string, unknown>, itemId?: string): void;
export declare function normalizeKnowledgeGuardedLimits(limits?: Partial<KnowledgeGuardedLimits>): KnowledgeGuardedLimits;
export declare function canonicalKnowledgeGuardedJson(value: unknown): string;
export declare function knowledgeGuardedDigest(value: unknown): string;
Expand Down Expand Up @@ -471,7 +587,11 @@ export declare function createKnowledgePrivateInputDescriptor(options: CreateKno
export declare function revokeKnowledgePrivateInputDescriptor(descriptor: KnowledgePrivateInputDescriptor): void;
export declare function createKnowledgePrivateTitleLookupDescriptor(options: CreateKnowledgePrivateTitleLookupDescriptorOptions): KnowledgePrivateTitleLookupDescriptor;
export declare function revokeKnowledgePrivateTitleLookupDescriptor(descriptor: KnowledgePrivateTitleLookupDescriptor): void;
export declare function createKnowledgePrivateQueryDescriptor(options: CreateKnowledgePrivateQueryDescriptorOptions): KnowledgePrivateQueryDescriptor;
export declare function revokeKnowledgePrivateQueryDescriptor(descriptor: KnowledgePrivateQueryDescriptor): void;
export declare function knowledgePrivateItemProof(item: KnowledgeItem): KnowledgePrivateItemProof;
export declare function knowledgePrivateQueryItemProof(item: KnowledgeItem, matchedValue?: string | null): KnowledgePrivateQueryItemProof;
export declare function knowledgePrivateHistoricalQueryItemProof(item: KnowledgeItemVersion, matchedValue?: string | null): KnowledgePrivateQueryItemProof;
export declare function revokeKnowledgePrivateResultDescriptor(descriptor: KnowledgePrivateResultDescriptor): void;
export declare function inspectKnowledgePrivateResult(descriptor: KnowledgePrivateResultDescriptor): KnowledgePrivateResultProof;
export declare function assertKnowledgeTerminalCompleteness(reconciliation: KnowledgeTerminalReconciliation, expected: {
Expand Down
11 changes: 10 additions & 1 deletion dist/guarded-writer.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type CreateKnowledgeGuardedManifestOptions, type KnowledgeGuardedBinding, type KnowledgeGuardedBindingStateReadback, type KnowledgeGuardedBounds, type KnowledgeGuardedAdoptionReconciliation, type KnowledgeGuardedAdoptionReceipt, type KnowledgeGuardedAdoptionResult, type KnowledgeGuardedLegacyAdoptionOptions, type KnowledgeGuardedLegacyRollbackOptions, type KnowledgeGuardedLimits, type KnowledgeGuardedManifestReconciliation, type KnowledgeGuardedManifestSubmission, type KnowledgeGuardedReadback, type KnowledgeGuardedReceipt, type KnowledgeGuardedRollbackResult, type KnowledgeGuardedWriteResult, type KnowledgePrivateInputDescriptor, type KnowledgePrivateResultDescriptor, type KnowledgePrivateTitleLookupDescriptor, type KnowledgeTerminalReconciliation } from './guarded-write-contract.js';
import { type CreateKnowledgeGuardedManifestOptions, type KnowledgeGuardedBinding, type KnowledgeGuardedBindingStateReadback, type KnowledgeGuardedBounds, type KnowledgeGuardedAdoptionReconciliation, type KnowledgeGuardedAdoptionReceipt, type KnowledgeGuardedAdoptionResult, type KnowledgeGuardedLegacyAdoptionOptions, type KnowledgeGuardedLegacyRollbackOptions, type KnowledgeGuardedLimits, type KnowledgeGuardedManifestReconciliation, type KnowledgeGuardedManifestSubmission, type KnowledgeGuardedReadback, type KnowledgeGuardedReceipt, type KnowledgeGuardedRollbackResult, type KnowledgeGuardedWriteResult, type KnowledgePrivateInputDescriptor, type KnowledgePrivateQueryBounds, type KnowledgePrivateQueryDescriptor, type KnowledgePrivateResultDescriptor, type KnowledgePrivateTitleLookupDescriptor, type KnowledgeTerminalReconciliation } from './guarded-write-contract.js';
export interface CreateKnowledgeGuardedWriterOptions {
binding: KnowledgeGuardedBinding;
env?: NodeJS.ProcessEnv;
Expand All @@ -18,6 +18,7 @@ export interface KnowledgeGuardedWriter {
execute(descriptor: KnowledgePrivateInputDescriptor): Promise<KnowledgeGuardedWriteResult>;
executePrivate(descriptor: KnowledgePrivateInputDescriptor): Promise<KnowledgePrivateResultDescriptor>;
lookupTitle(descriptor: KnowledgePrivateTitleLookupDescriptor): Promise<KnowledgePrivateResultDescriptor>;
query(descriptor: KnowledgePrivateQueryDescriptor, bounds?: KnowledgePrivateQueryBounds): Promise<KnowledgePrivateResultDescriptor>;
reconcile(deterministicKey: string, operationId: string, stepId: string, bounds?: KnowledgeGuardedBounds): Promise<KnowledgeTerminalReconciliation>;
readback(fullId: string, bounds?: KnowledgeGuardedBounds): Promise<KnowledgeGuardedReadback>;
readbackPrivate(fullId: string, bounds?: KnowledgeGuardedBounds): Promise<KnowledgePrivateResultDescriptor>;
Expand All @@ -41,6 +42,14 @@ export declare class KnowledgePrivateTitleLookupAmbiguousError extends Error {
readonly code = "private_title_lookup_ambiguous";
constructor();
}
export declare class KnowledgePrivateQueryResponseError extends Error {
readonly code = "private_query_response_invalid";
constructor();
}
export declare class KnowledgeGuardedReadbackError extends Error {
readonly code = "guarded_readback_response_invalid";
constructor();
}
export declare class KnowledgeGuardedManifestConflictError extends Error {
readonly manifest: KnowledgeGuardedManifestSubmission['manifest'];
readonly code = "guarded_manifest_conflict";
Expand Down
Loading
Loading