@revealui/ai 0.2.7 → 0.2.9
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/LICENSE +104 -17
- package/README.md +2 -2
- package/dist/a2a/card.d.ts +1 -1
- package/dist/a2a/card.d.ts.map +1 -1
- package/dist/a2a/card.js +4 -4
- package/dist/a2a/handler.d.ts +4 -4
- package/dist/a2a/handler.js +5 -5
- package/dist/a2a/index.d.ts +1 -1
- package/dist/a2a/index.js +1 -1
- package/dist/audit/emitter.d.ts +1 -1
- package/dist/audit/emitter.js +2 -2
- package/dist/audit/index.d.ts +2 -2
- package/dist/audit/index.js +2 -2
- package/dist/audit/store.d.ts +2 -2
- package/dist/audit/store.js +2 -2
- package/dist/client/errors.d.ts +13 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +28 -0
- package/dist/client/hooks/useAgentContext.d.ts.map +1 -1
- package/dist/client/hooks/useAgentContext.js +6 -5
- package/dist/client/hooks/useAgentStream.d.ts +2 -2
- package/dist/client/hooks/useAgentStream.js +3 -3
- package/dist/client/hooks/useEpisodicMemory.d.ts.map +1 -1
- package/dist/client/hooks/useEpisodicMemory.js +6 -5
- package/dist/client/hooks/useWorkingMemory.d.ts.map +1 -1
- package/dist/client/hooks/useWorkingMemory.js +7 -6
- package/dist/embeddings/index.d.ts +1 -1
- package/dist/embeddings/index.js +4 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/inference/context-budget.d.ts +1 -1
- package/dist/inference/context-budget.js +4 -4
- package/dist/inference/index.d.ts +1 -1
- package/dist/inference/index.js +1 -1
- package/dist/inference/runRag.d.ts +3 -3
- package/dist/inference/runRag.d.ts.map +1 -1
- package/dist/inference/runRag.js +1 -1
- package/dist/inference/task-decomposer.d.ts +1 -1
- package/dist/inference/task-decomposer.d.ts.map +1 -1
- package/dist/inference/task-decomposer.js +3 -3
- package/dist/inference/tool-result-compressor.d.ts +1 -1
- package/dist/inference/tool-result-compressor.js +1 -1
- package/dist/ingestion/{cms-indexer.d.ts → admin-indexer.d.ts} +12 -12
- package/dist/ingestion/admin-indexer.d.ts.map +1 -0
- package/dist/ingestion/{cms-indexer.js → admin-indexer.js} +9 -9
- package/dist/ingestion/bm25.d.ts +1 -1
- package/dist/ingestion/bm25.js +1 -1
- package/dist/ingestion/file-parsers.d.ts +1 -1
- package/dist/ingestion/file-parsers.d.ts.map +1 -1
- package/dist/ingestion/file-parsers.js +36 -17
- package/dist/ingestion/hybrid-search.d.ts +1 -1
- package/dist/ingestion/hybrid-search.js +1 -1
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/index.d.ts.map +1 -1
- package/dist/ingestion/index.js +1 -1
- package/dist/ingestion/rag-vector-service.d.ts +1 -1
- package/dist/ingestion/rag-vector-service.js +1 -1
- package/dist/ingestion/reranker.d.ts +1 -1
- package/dist/ingestion/reranker.js +1 -1
- package/dist/ingestion/text-splitter.d.ts +1 -1
- package/dist/ingestion/text-splitter.js +2 -2
- package/dist/llm/cache-utils.d.ts.map +1 -1
- package/dist/llm/cache-utils.js +1 -17
- package/dist/llm/client.d.ts +8 -13
- package/dist/llm/client.d.ts.map +1 -1
- package/dist/llm/client.js +12 -60
- package/dist/llm/key-validator.d.ts +1 -1
- package/dist/llm/key-validator.js +8 -8
- package/dist/llm/providers/base.d.ts +2 -2
- package/dist/llm/providers/groq.d.ts +2 -2
- package/dist/llm/providers/groq.d.ts.map +1 -1
- package/dist/llm/providers/groq.js +4 -4
- package/dist/llm/providers/inference-snaps.d.ts +5 -5
- package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
- package/dist/llm/providers/inference-snaps.js +6 -6
- package/dist/llm/providers/ollama.d.ts +2 -2
- package/dist/llm/providers/ollama.d.ts.map +1 -1
- package/dist/llm/providers/ollama.js +3 -3
- package/dist/llm/providers/{openai.d.ts → openai-compat.d.ts} +8 -7
- package/dist/llm/providers/openai-compat.d.ts.map +1 -0
- package/dist/llm/providers/{openai.js → openai-compat.js} +13 -17
- package/dist/llm/providers/vultr.d.ts.map +1 -1
- package/dist/llm/providers/vultr.js +1 -0
- package/dist/llm/server.d.ts +1 -3
- package/dist/llm/server.d.ts.map +1 -1
- package/dist/llm/server.js +1 -3
- package/dist/llm/token-counter.d.ts.map +1 -1
- package/dist/llm/token-counter.js +11 -8
- package/dist/llm/workspace-provider-config.d.ts +1 -1
- package/dist/llm/workspace-provider-config.d.ts.map +1 -1
- package/dist/llm/workspace-provider-config.js +1 -1
- package/dist/memory/crdt/or-set.d.ts +12 -0
- package/dist/memory/crdt/or-set.d.ts.map +1 -1
- package/dist/memory/crdt/or-set.js +27 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +1 -0
- package/dist/memory/persistence/crdt-persistence.d.ts +21 -1
- package/dist/memory/persistence/crdt-persistence.d.ts.map +1 -1
- package/dist/memory/persistence/crdt-persistence.js +67 -0
- package/dist/memory/preferences/user-preferences-manager.d.ts.map +1 -1
- package/dist/memory/preferences/user-preferences-manager.js +11 -1
- package/dist/memory/stores/episodic-memory.js +2 -2
- package/dist/memory/stores/working-memory.d.ts +7 -2
- package/dist/memory/stores/working-memory.d.ts.map +1 -1
- package/dist/memory/stores/working-memory.js +31 -17
- package/dist/memory/sync/index.d.ts +2 -0
- package/dist/memory/sync/index.d.ts.map +1 -0
- package/dist/memory/sync/index.js +1 -0
- package/dist/memory/sync/sync-manager.d.ts +104 -0
- package/dist/memory/sync/sync-manager.d.ts.map +1 -0
- package/dist/memory/sync/sync-manager.js +137 -0
- package/dist/memory/utils/validation.js +1 -1
- package/dist/memory/vector/vector-memory-service.d.ts +1 -1
- package/dist/memory/vector/vector-memory-service.js +1 -1
- package/dist/orchestration/agent.d.ts +2 -2
- package/dist/orchestration/defaults.d.ts +1 -1
- package/dist/orchestration/defaults.js +1 -1
- package/dist/orchestration/orchestrator.d.ts +3 -3
- package/dist/orchestration/orchestrator.js +3 -3
- package/dist/orchestration/runtime.d.ts +1 -1
- package/dist/orchestration/runtime.js +1 -1
- package/dist/orchestration/streaming-runtime.d.ts +2 -2
- package/dist/orchestration/streaming-runtime.js +2 -2
- package/dist/orchestration/ticket-agent.d.ts +11 -11
- package/dist/orchestration/ticket-agent.d.ts.map +1 -1
- package/dist/orchestration/ticket-agent.js +10 -10
- package/dist/skills/catalog/vercel-catalog.d.ts.map +1 -1
- package/dist/skills/catalog/vercel-catalog.js +7 -4
- package/dist/skills/loader/github-loader.d.ts.map +1 -1
- package/dist/skills/loader/github-loader.js +2 -0
- package/dist/skills/loader/local-loader.js +1 -1
- package/dist/skills/loader/vercel-loader.d.ts.map +1 -1
- package/dist/skills/loader/vercel-loader.js +2 -0
- package/dist/skills/parser/skill-md-parser.js +2 -2
- package/dist/skills/registry/skill-registry.js +1 -1
- package/dist/skills/types.d.ts +6 -6
- package/dist/templates/prompt-spec.js +1 -1
- package/dist/templates/skill-spec.js +1 -1
- package/dist/tools/{cms → admin}/collection-tools.d.ts +2 -2
- package/dist/tools/admin/collection-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/collection-tools.js +8 -8
- package/dist/tools/{cms → admin}/factory.d.ts +11 -11
- package/dist/tools/admin/factory.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/factory.js +4 -4
- package/dist/tools/{cms → admin}/global-tools.d.ts +1 -1
- package/dist/tools/admin/global-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/global-tools.js +4 -4
- package/dist/tools/{cms → admin}/index.d.ts +4 -4
- package/dist/tools/admin/index.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/index.js +3 -3
- package/dist/tools/{cms → admin}/media-tools.d.ts +1 -1
- package/dist/tools/admin/media-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/media-tools.js +4 -4
- package/dist/tools/{cms → admin}/user-tools.d.ts +1 -1
- package/dist/tools/admin/user-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/user-tools.js +1 -1
- package/dist/tools/coding/file-edit.d.ts +1 -1
- package/dist/tools/coding/file-edit.js +2 -2
- package/dist/tools/coding/file-glob.d.ts +1 -1
- package/dist/tools/coding/file-glob.d.ts.map +1 -1
- package/dist/tools/coding/file-glob.js +2 -1
- package/dist/tools/coding/file-grep.d.ts +1 -1
- package/dist/tools/coding/file-grep.d.ts.map +1 -1
- package/dist/tools/coding/file-grep.js +2 -1
- package/dist/tools/coding/file-read.d.ts +1 -1
- package/dist/tools/coding/file-read.d.ts.map +1 -1
- package/dist/tools/coding/file-read.js +15 -9
- package/dist/tools/coding/file-write.d.ts +1 -1
- package/dist/tools/coding/file-write.js +1 -1
- package/dist/tools/coding/git-ops.d.ts +1 -1
- package/dist/tools/coding/git-ops.d.ts.map +1 -1
- package/dist/tools/coding/git-ops.js +5 -7
- package/dist/tools/coding/index.d.ts +1 -1
- package/dist/tools/coding/index.d.ts.map +1 -1
- package/dist/tools/coding/lint-fix.d.ts +1 -1
- package/dist/tools/coding/lint-fix.d.ts.map +1 -1
- package/dist/tools/coding/lint-fix.js +8 -4
- package/dist/tools/coding/project-context.d.ts +1 -1
- package/dist/tools/coding/project-context.d.ts.map +1 -1
- package/dist/tools/coding/project-context.js +25 -24
- package/dist/tools/coding/safety.d.ts +1 -1
- package/dist/tools/coding/safety.d.ts.map +1 -1
- package/dist/tools/coding/shell-exec.d.ts +1 -1
- package/dist/tools/coding/shell-exec.js +1 -1
- package/dist/tools/coding/test-runner.d.ts +1 -1
- package/dist/tools/coding/test-runner.d.ts.map +1 -1
- package/dist/tools/coding/test-runner.js +12 -7
- package/dist/tools/deduplicator.js +1 -1
- package/dist/tools/document-summarizer.js +2 -2
- package/dist/tools/memory/store-memory.d.ts +1 -1
- package/dist/tools/memory/store-memory.js +2 -2
- package/dist/tools/ticket-tools.d.ts +2 -2
- package/dist/tools/ticket-tools.js +3 -3
- package/dist/tools/web/duck-duck-go.d.ts +3 -3
- package/dist/tools/web/duck-duck-go.js +4 -4
- package/dist/tools/web/exa.d.ts +1 -1
- package/dist/tools/web/exa.js +1 -1
- package/dist/tools/web/scraper.js +1 -1
- package/dist/tools/web/tavily.d.ts +2 -2
- package/dist/tools/web/tavily.js +2 -2
- package/dist/tools/web/types.d.ts +2 -2
- package/dist/tools/web/types.js +2 -2
- package/package.json +23 -17
- package/LICENSE.commercial +0 -111
- package/dist/ingestion/cms-indexer.d.ts.map +0 -1
- package/dist/llm/providers/anthropic.d.ts +0 -31
- package/dist/llm/providers/anthropic.d.ts.map +0 -1
- package/dist/llm/providers/anthropic.js +0 -264
- package/dist/llm/providers/bitnet.d.ts +0 -28
- package/dist/llm/providers/bitnet.d.ts.map +0 -1
- package/dist/llm/providers/bitnet.js +0 -36
- package/dist/llm/providers/openai.d.ts.map +0 -1
- package/dist/tools/cms/collection-tools.d.ts.map +0 -1
- package/dist/tools/cms/factory.d.ts.map +0 -1
- package/dist/tools/cms/global-tools.d.ts.map +0 -1
- package/dist/tools/cms/index.d.ts.map +0 -1
- package/dist/tools/cms/media-tools.d.ts.map +0 -1
- package/dist/tools/cms/user-tools.d.ts.map +0 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRDT Sync Manager
|
|
3
|
+
*
|
|
4
|
+
* Coordinates state synchronization between distributed nodes.
|
|
5
|
+
* Supports both full-state merge and delta-based sync via the operation log.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* - State-based sync: serialize → transfer → merge (simple, higher bandwidth)
|
|
9
|
+
* - Op-based sync: log ops → transfer deltas → replay (efficient, requires op log)
|
|
10
|
+
* - Anti-entropy: periodic full-state reconciliation to catch missed ops
|
|
11
|
+
*
|
|
12
|
+
* Transport-agnostic: the SyncManager produces/consumes serialized payloads.
|
|
13
|
+
* The actual transport (HTTP, WebSocket, message queue) is the caller's concern.
|
|
14
|
+
*/
|
|
15
|
+
import type { LWWRegisterData } from '../crdt/lww-register.js';
|
|
16
|
+
import type { ORSetData } from '../crdt/or-set.js';
|
|
17
|
+
import type { PNCounterData } from '../crdt/pn-counter.js';
|
|
18
|
+
import type { CRDTOperationPayload, CRDTPersistence, CRDTType } from '../persistence/crdt-persistence.js';
|
|
19
|
+
import type { WorkingMemory } from '../stores/working-memory.js';
|
|
20
|
+
export interface SyncState {
|
|
21
|
+
/** CRDT instance identifier */
|
|
22
|
+
crdtId: string;
|
|
23
|
+
/** Node that produced this state */
|
|
24
|
+
sourceNodeId: string;
|
|
25
|
+
/** Timestamp of this state snapshot */
|
|
26
|
+
timestamp: number;
|
|
27
|
+
/** Serialized CRDT states (composite) */
|
|
28
|
+
states: Record<string, LWWRegisterData<unknown> | ORSetData<unknown> | PNCounterData>;
|
|
29
|
+
}
|
|
30
|
+
export interface SyncDelta {
|
|
31
|
+
/** CRDT instance identifier */
|
|
32
|
+
crdtId: string;
|
|
33
|
+
/** Node that produced these operations */
|
|
34
|
+
sourceNodeId: string;
|
|
35
|
+
/** Operations since last sync point */
|
|
36
|
+
operations: CRDTOperationPayload[];
|
|
37
|
+
/** Timestamp of the last synced operation (for next delta request) */
|
|
38
|
+
lastSyncTimestamp: number;
|
|
39
|
+
}
|
|
40
|
+
export interface SyncResult {
|
|
41
|
+
/** Whether state changed as a result of sync */
|
|
42
|
+
changed: boolean;
|
|
43
|
+
/** Number of operations applied */
|
|
44
|
+
operationsApplied: number;
|
|
45
|
+
/** Number of conflicts resolved */
|
|
46
|
+
conflictsResolved: number;
|
|
47
|
+
/** Timestamp to use for next delta sync */
|
|
48
|
+
syncTimestamp: number;
|
|
49
|
+
}
|
|
50
|
+
export declare class SyncManager {
|
|
51
|
+
private nodeId;
|
|
52
|
+
private persistence;
|
|
53
|
+
/** Tracks the last sync timestamp per remote node */
|
|
54
|
+
private syncPoints;
|
|
55
|
+
constructor(nodeId: string, persistence: CRDTPersistence);
|
|
56
|
+
/**
|
|
57
|
+
* Produces a full-state snapshot for transfer to another node.
|
|
58
|
+
* The receiving node calls `mergeRemoteState()` with this payload.
|
|
59
|
+
*/
|
|
60
|
+
getLocalState(crdtId: string): Promise<SyncState>;
|
|
61
|
+
/**
|
|
62
|
+
* Merges a remote node's full state into local state.
|
|
63
|
+
* Uses CRDT merge semantics - order doesn't matter, result is deterministic.
|
|
64
|
+
*
|
|
65
|
+
* @returns WorkingMemory with merged state (caller decides whether to persist)
|
|
66
|
+
*/
|
|
67
|
+
mergeRemoteWorkingMemory(local: WorkingMemory, remote: WorkingMemory): {
|
|
68
|
+
merged: WorkingMemory;
|
|
69
|
+
changed: boolean;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Produces a delta payload (operations since a timestamp) for efficient sync.
|
|
73
|
+
* The receiving node calls `applyDelta()` with this payload.
|
|
74
|
+
*/
|
|
75
|
+
getDelta(crdtId: string, since: number): Promise<SyncDelta>;
|
|
76
|
+
/**
|
|
77
|
+
* Applies a delta from a remote node by replaying operations.
|
|
78
|
+
* Logs each remote operation locally for future delta requests from other nodes.
|
|
79
|
+
*/
|
|
80
|
+
applyDelta(delta: SyncDelta): Promise<SyncResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Logs a local operation to the persistence layer.
|
|
83
|
+
* Called by memory stores when they mutate CRDT state.
|
|
84
|
+
*/
|
|
85
|
+
logOperation(crdtId: string, crdtType: CRDTType, operationType: CRDTOperationPayload['operationType'], payload: Record<string, unknown>): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Gets the last sync timestamp for a remote node.
|
|
88
|
+
* Used to request only new operations on the next sync.
|
|
89
|
+
*/
|
|
90
|
+
getSyncPoint(remoteNodeId: string): number;
|
|
91
|
+
/**
|
|
92
|
+
* Sets the sync point for a remote node (e.g., after initial full-state sync).
|
|
93
|
+
*/
|
|
94
|
+
setSyncPoint(remoteNodeId: string, timestamp: number): void;
|
|
95
|
+
/**
|
|
96
|
+
* Gets all tracked sync points.
|
|
97
|
+
*/
|
|
98
|
+
getAllSyncPoints(): Map<string, number>;
|
|
99
|
+
/**
|
|
100
|
+
* Gets this manager's node ID.
|
|
101
|
+
*/
|
|
102
|
+
getNodeId(): string;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=sync-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-manager.d.ts","sourceRoot":"","sources":["../../../src/memory/sync/sync-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,QAAQ,EACT,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAMjE,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,CAAC;CACvF;AAED,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;CACvB;AAMD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAkB;IACrC,qDAAqD;IACrD,OAAO,CAAC,UAAU,CAAkC;gBAExC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe;IAKxD;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAmBvD;;;;;OAKG;IACH,wBAAwB,CACtB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,aAAa,GACpB;QAAE,MAAM,EAAE,aAAa,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAgB9C;;;OAGG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAYjE;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;IAyBvD;;;OAGG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,oBAAoB,CAAC,eAAe,CAAC,EACpD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAWhB;;;OAGG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAI1C;;OAEG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI3D;;OAEG;IACH,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIvC;;OAEG;IACH,SAAS,IAAI,MAAM;CAGpB"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRDT Sync Manager
|
|
3
|
+
*
|
|
4
|
+
* Coordinates state synchronization between distributed nodes.
|
|
5
|
+
* Supports both full-state merge and delta-based sync via the operation log.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* - State-based sync: serialize → transfer → merge (simple, higher bandwidth)
|
|
9
|
+
* - Op-based sync: log ops → transfer deltas → replay (efficient, requires op log)
|
|
10
|
+
* - Anti-entropy: periodic full-state reconciliation to catch missed ops
|
|
11
|
+
*
|
|
12
|
+
* Transport-agnostic: the SyncManager produces/consumes serialized payloads.
|
|
13
|
+
* The actual transport (HTTP, WebSocket, message queue) is the caller's concern.
|
|
14
|
+
*/
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// SyncManager
|
|
17
|
+
// =============================================================================
|
|
18
|
+
export class SyncManager {
|
|
19
|
+
nodeId;
|
|
20
|
+
persistence;
|
|
21
|
+
/** Tracks the last sync timestamp per remote node */
|
|
22
|
+
syncPoints = new Map();
|
|
23
|
+
constructor(nodeId, persistence) {
|
|
24
|
+
this.nodeId = nodeId;
|
|
25
|
+
this.persistence = persistence;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Produces a full-state snapshot for transfer to another node.
|
|
29
|
+
* The receiving node calls `mergeRemoteState()` with this payload.
|
|
30
|
+
*/
|
|
31
|
+
async getLocalState(crdtId) {
|
|
32
|
+
const states = await this.persistence.loadCompositeState(crdtId);
|
|
33
|
+
const stateRecord = {};
|
|
34
|
+
for (const [key, data] of states) {
|
|
35
|
+
stateRecord[key] = data;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
crdtId,
|
|
39
|
+
sourceNodeId: this.nodeId,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
states: stateRecord,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Merges a remote node's full state into local state.
|
|
46
|
+
* Uses CRDT merge semantics - order doesn't matter, result is deterministic.
|
|
47
|
+
*
|
|
48
|
+
* @returns WorkingMemory with merged state (caller decides whether to persist)
|
|
49
|
+
*/
|
|
50
|
+
mergeRemoteWorkingMemory(local, remote) {
|
|
51
|
+
const localData = local.toData();
|
|
52
|
+
const remoteData = remote.toData();
|
|
53
|
+
// Quick equality check - if timestamps match, nothing changed
|
|
54
|
+
if (localData.context.timestamp === remoteData.context.timestamp &&
|
|
55
|
+
localData.sessionState.timestamp === remoteData.sessionState.timestamp) {
|
|
56
|
+
return { merged: local, changed: false };
|
|
57
|
+
}
|
|
58
|
+
const merged = local.merge(remote);
|
|
59
|
+
return { merged, changed: true };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Produces a delta payload (operations since a timestamp) for efficient sync.
|
|
63
|
+
* The receiving node calls `applyDelta()` with this payload.
|
|
64
|
+
*/
|
|
65
|
+
async getDelta(crdtId, since) {
|
|
66
|
+
const operations = await this.persistence.getOperationsSince(crdtId, since);
|
|
67
|
+
return {
|
|
68
|
+
crdtId,
|
|
69
|
+
sourceNodeId: this.nodeId,
|
|
70
|
+
operations,
|
|
71
|
+
lastSyncTimestamp: operations.length > 0 ? (operations[operations.length - 1]?.timestamp ?? since) : since,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Applies a delta from a remote node by replaying operations.
|
|
76
|
+
* Logs each remote operation locally for future delta requests from other nodes.
|
|
77
|
+
*/
|
|
78
|
+
async applyDelta(delta) {
|
|
79
|
+
let applied = 0;
|
|
80
|
+
for (const op of delta.operations) {
|
|
81
|
+
// Skip operations from our own node (already applied locally)
|
|
82
|
+
if (op.nodeId === this.nodeId) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
// Log the remote operation locally
|
|
86
|
+
await this.persistence.appendOperation(op);
|
|
87
|
+
applied++;
|
|
88
|
+
}
|
|
89
|
+
// Update sync point for this remote node
|
|
90
|
+
this.syncPoints.set(delta.sourceNodeId, delta.lastSyncTimestamp);
|
|
91
|
+
return {
|
|
92
|
+
changed: applied > 0,
|
|
93
|
+
operationsApplied: applied,
|
|
94
|
+
conflictsResolved: 0, // CRDTs resolve conflicts automatically
|
|
95
|
+
syncTimestamp: delta.lastSyncTimestamp,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Logs a local operation to the persistence layer.
|
|
100
|
+
* Called by memory stores when they mutate CRDT state.
|
|
101
|
+
*/
|
|
102
|
+
async logOperation(crdtId, crdtType, operationType, payload) {
|
|
103
|
+
await this.persistence.appendOperation({
|
|
104
|
+
crdtId,
|
|
105
|
+
crdtType,
|
|
106
|
+
operationType,
|
|
107
|
+
payload,
|
|
108
|
+
nodeId: this.nodeId,
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Gets the last sync timestamp for a remote node.
|
|
114
|
+
* Used to request only new operations on the next sync.
|
|
115
|
+
*/
|
|
116
|
+
getSyncPoint(remoteNodeId) {
|
|
117
|
+
return this.syncPoints.get(remoteNodeId) ?? 0;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Sets the sync point for a remote node (e.g., after initial full-state sync).
|
|
121
|
+
*/
|
|
122
|
+
setSyncPoint(remoteNodeId, timestamp) {
|
|
123
|
+
this.syncPoints.set(remoteNodeId, timestamp);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Gets all tracked sync points.
|
|
127
|
+
*/
|
|
128
|
+
getAllSyncPoints() {
|
|
129
|
+
return new Map(this.syncPoints);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Gets this manager's node ID.
|
|
133
|
+
*/
|
|
134
|
+
getNodeId() {
|
|
135
|
+
return this.nodeId;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -118,7 +118,7 @@ export function estimateObjectSize(obj) {
|
|
|
118
118
|
const type = typeof obj;
|
|
119
119
|
if (type === 'string') {
|
|
120
120
|
// UTF-16 char units × 2 bytes each. This over-estimates multi-byte UTF-8 code
|
|
121
|
-
// points but is intentionally conservative
|
|
121
|
+
// points but is intentionally conservative - the limit stays tighter than the
|
|
122
122
|
// real in-process memory cost, which is what we want for a safety bound.
|
|
123
123
|
return obj.length * 2 + 8;
|
|
124
124
|
}
|
|
@@ -41,7 +41,7 @@ export declare class VectorMemoryService {
|
|
|
41
41
|
/**
|
|
42
42
|
* Search for similar memories using vector similarity.
|
|
43
43
|
*
|
|
44
|
-
* @param queryEmbedding - Query embedding vector (768 dimensions
|
|
44
|
+
* @param queryEmbedding - Query embedding vector (768 dimensions - Ollama nomic-embed-text)
|
|
45
45
|
* @param options - Search options (filtering, limits, etc.)
|
|
46
46
|
* @returns Array of memories with similarity scores, sorted by similarity (highest first)
|
|
47
47
|
*
|
|
@@ -42,7 +42,7 @@ export class VectorMemoryService {
|
|
|
42
42
|
/**
|
|
43
43
|
* Search for similar memories using vector similarity.
|
|
44
44
|
*
|
|
45
|
-
* @param queryEmbedding - Query embedding vector (768 dimensions
|
|
45
|
+
* @param queryEmbedding - Query embedding vector (768 dimensions - Ollama nomic-embed-text)
|
|
46
46
|
* @param options - Search options (filtering, limits, etc.)
|
|
47
47
|
* @returns Array of memories with similarity scores, sorted by similarity (highest first)
|
|
48
48
|
*
|
|
@@ -22,7 +22,7 @@ export interface AgentConfig {
|
|
|
22
22
|
webSearchProvider?: WebSearchProvider;
|
|
23
23
|
/**
|
|
24
24
|
* Capability tags used by AgentOrchestrator.findBestAgent() for routing.
|
|
25
|
-
* Example: ['
|
|
25
|
+
* Example: ['admin', 'search', 'ticket', 'summarize']
|
|
26
26
|
*/
|
|
27
27
|
capabilities?: string[];
|
|
28
28
|
}
|
|
@@ -70,7 +70,7 @@ export interface Agent {
|
|
|
70
70
|
*/
|
|
71
71
|
tools: Tool[];
|
|
72
72
|
/**
|
|
73
|
-
* Memory system (optional
|
|
73
|
+
* Memory system (optional - agents without memory skip episodic recall)
|
|
74
74
|
*/
|
|
75
75
|
memory?: EpisodicMemory;
|
|
76
76
|
/**
|
|
@@ -15,7 +15,7 @@ import type { Tool } from '../tools/base.js';
|
|
|
15
15
|
export declare const WORKSPACE_AGENT_DEFAULT_TOOLS: Tool[];
|
|
16
16
|
/**
|
|
17
17
|
* Returns the workspace agent default tool set, optionally merged with
|
|
18
|
-
* additional tools (e.g.
|
|
18
|
+
* additional tools (e.g. admin tools, MCP-discovered tools).
|
|
19
19
|
*/
|
|
20
20
|
export declare function getWorkspaceAgentTools(additionalTools?: Tool[]): Tool[];
|
|
21
21
|
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -15,7 +15,7 @@ import { webSearchTool } from '../tools/web/index.js';
|
|
|
15
15
|
export const WORKSPACE_AGENT_DEFAULT_TOOLS = [webSearchTool];
|
|
16
16
|
/**
|
|
17
17
|
* Returns the workspace agent default tool set, optionally merged with
|
|
18
|
-
* additional tools (e.g.
|
|
18
|
+
* additional tools (e.g. admin tools, MCP-discovered tools).
|
|
19
19
|
*/
|
|
20
20
|
export function getWorkspaceAgentTools(additionalTools = []) {
|
|
21
21
|
return [...WORKSPACE_AGENT_DEFAULT_TOOLS, ...additionalTools];
|
|
@@ -51,11 +51,11 @@ export declare class AgentOrchestrator {
|
|
|
51
51
|
* Find the best agent for a task.
|
|
52
52
|
*
|
|
53
53
|
* Routing priority:
|
|
54
|
-
* 1. Capability intersection
|
|
54
|
+
* 1. Capability intersection - agent whose AgentConfig.capabilities overlaps
|
|
55
55
|
* with task.requiredCapabilities (highest-overlap agent wins)
|
|
56
|
-
* 2. Tool-name substring match
|
|
56
|
+
* 2. Tool-name substring match - agent has a tool whose name includes the
|
|
57
57
|
* task type string (legacy fallback)
|
|
58
|
-
* 3. First registered agent
|
|
58
|
+
* 3. First registered agent - last-resort fallback
|
|
59
59
|
*/
|
|
60
60
|
private findBestAgent;
|
|
61
61
|
/**
|
|
@@ -92,11 +92,11 @@ export class AgentOrchestrator {
|
|
|
92
92
|
* Find the best agent for a task.
|
|
93
93
|
*
|
|
94
94
|
* Routing priority:
|
|
95
|
-
* 1. Capability intersection
|
|
95
|
+
* 1. Capability intersection - agent whose AgentConfig.capabilities overlaps
|
|
96
96
|
* with task.requiredCapabilities (highest-overlap agent wins)
|
|
97
|
-
* 2. Tool-name substring match
|
|
97
|
+
* 2. Tool-name substring match - agent has a tool whose name includes the
|
|
98
98
|
* task type string (legacy fallback)
|
|
99
|
-
* 3. First registered agent
|
|
99
|
+
* 3. First registered agent - last-resort fallback
|
|
100
100
|
*/
|
|
101
101
|
findBestAgent(task) {
|
|
102
102
|
// 1. Capability-based routing
|
|
@@ -10,7 +10,7 @@ import type { MCPToolSource } from '../tools/mcp-adapter.js';
|
|
|
10
10
|
import type { Agent, AgentResult, Task } from './agent.js';
|
|
11
11
|
/**
|
|
12
12
|
* Controls how much of the model's token budget is allocated to internal reasoning.
|
|
13
|
-
* Applies to Anthropic Claude only
|
|
13
|
+
* Applies to Anthropic Claude only - ignored by other providers.
|
|
14
14
|
*
|
|
15
15
|
* | Level | Budget (tokens) | Use case |
|
|
16
16
|
* |---------|-----------------|-----------------------------------|
|
|
@@ -176,7 +176,7 @@ export class AgentRuntime {
|
|
|
176
176
|
const needsApproval = tool.requiresApproval || this.config.alwaysRequireApproval?.includes(tool.name);
|
|
177
177
|
if (needsApproval) {
|
|
178
178
|
if (!this.config.approvalCallback) {
|
|
179
|
-
// No approval callback
|
|
179
|
+
// No approval callback - deny by default
|
|
180
180
|
const denied = {
|
|
181
181
|
success: false,
|
|
182
182
|
error: `Tool "${tool.label ?? tool.name}" requires human approval but no approval handler is configured.`,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Each yielded AgentStreamChunk maps to one SSE event.
|
|
6
6
|
*
|
|
7
7
|
* AnythingLLM lesson: SSE is the correct approach for unidirectional LLM output.
|
|
8
|
-
* EventSource is not used client-side because it doesn't support POST
|
|
8
|
+
* EventSource is not used client-side because it doesn't support POST - use fetch + ReadableStream.
|
|
9
9
|
*/
|
|
10
10
|
import type { LLMClient } from '../llm/client.js';
|
|
11
11
|
import type { ToolResult } from '../tools/base.js';
|
|
@@ -29,7 +29,7 @@ export declare class StreamingAgentRuntime extends AgentRuntime {
|
|
|
29
29
|
constructor(config?: RuntimeConfig);
|
|
30
30
|
/**
|
|
31
31
|
* Stream a task execution, yielding typed events as they occur.
|
|
32
|
-
* Accepts an AbortSignal
|
|
32
|
+
* Accepts an AbortSignal - on abort, emits an error event and stops.
|
|
33
33
|
*/
|
|
34
34
|
streamTask(agent: Agent, task: Task, llmClient: LLMClient, signal?: AbortSignal): AsyncGenerator<AgentStreamChunk>;
|
|
35
35
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Each yielded AgentStreamChunk maps to one SSE event.
|
|
6
6
|
*
|
|
7
7
|
* AnythingLLM lesson: SSE is the correct approach for unidirectional LLM output.
|
|
8
|
-
* EventSource is not used client-side because it doesn't support POST
|
|
8
|
+
* EventSource is not used client-side because it doesn't support POST - use fetch + ReadableStream.
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod/v4';
|
|
11
11
|
import { compressToolResult } from '../inference/tool-result-compressor.js';
|
|
@@ -17,7 +17,7 @@ export class StreamingAgentRuntime extends AgentRuntime {
|
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Stream a task execution, yielding typed events as they occur.
|
|
20
|
-
* Accepts an AbortSignal
|
|
20
|
+
* Accepts an AbortSignal - on abort, emits an error event and stops.
|
|
21
21
|
*/
|
|
22
22
|
async *streamTask(agent, task, llmClient, signal) {
|
|
23
23
|
const startTime = Date.now();
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Closes the loop between the ticketing system and the AI agent system.
|
|
5
5
|
*
|
|
6
6
|
* Flow:
|
|
7
|
-
* Ticket (title + description) → Task → Agent (
|
|
8
|
-
* → agentic loop →
|
|
7
|
+
* Ticket (title + description) → Task → Agent (admin tools + ticket tools)
|
|
8
|
+
* → agentic loop → admin mutations + ticket status updated + comment written
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
11
|
* const dispatcher = new TicketAgentDispatcher({ llmClient, apiClient, ticketClient })
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import type { Database } from '@revealui/db/client';
|
|
15
15
|
import type { LLMClient } from '../llm/client.js';
|
|
16
16
|
import type { EpisodicMemory } from '../memory/stores/episodic-memory.js';
|
|
17
|
-
import type {
|
|
17
|
+
import type { AdminAPIClient, CollectionMetadata, GlobalMetadata } from '../tools/admin/factory.js';
|
|
18
18
|
import type { TicketMutationClient } from '../tools/ticket-tools.js';
|
|
19
19
|
import type { AgentResult } from './agent.js';
|
|
20
20
|
export interface TicketInput {
|
|
@@ -28,22 +28,22 @@ export interface TicketInput {
|
|
|
28
28
|
export interface TicketAgentConfig {
|
|
29
29
|
/** LLM client (Anthropic, OpenAI, etc.) */
|
|
30
30
|
llmClient: LLMClient;
|
|
31
|
-
/**
|
|
32
|
-
apiClient:
|
|
33
|
-
/** Ticket mutation client
|
|
31
|
+
/** admin API client - used to inject into admin tools */
|
|
32
|
+
apiClient: AdminAPIClient;
|
|
33
|
+
/** Ticket mutation client - used to update status and add comments */
|
|
34
34
|
ticketClient: TicketMutationClient;
|
|
35
|
-
/** Available
|
|
35
|
+
/** Available admin collections (optional, improves tool descriptions) */
|
|
36
36
|
collections?: CollectionMetadata[];
|
|
37
|
-
/** Available
|
|
37
|
+
/** Available admin globals (optional) */
|
|
38
38
|
globals?: GlobalMetadata[];
|
|
39
39
|
/**
|
|
40
40
|
* Memory instance to share across dispatches (optional).
|
|
41
|
-
* If omitted, each dispatch uses a no-op stub
|
|
41
|
+
* If omitted, each dispatch uses a no-op stub - the runtime does not
|
|
42
42
|
* call agent.memory directly, so this is safe for stateless dispatch.
|
|
43
43
|
*/
|
|
44
44
|
memory?: EpisodicMemory;
|
|
45
45
|
/**
|
|
46
|
-
* Database client
|
|
46
|
+
* Database client - enables the document_summarize tool.
|
|
47
47
|
* If omitted, the summarizer tool is not included in the agent's toolset.
|
|
48
48
|
*/
|
|
49
49
|
db?: Database;
|
|
@@ -61,7 +61,7 @@ export declare class TicketAgentDispatcher {
|
|
|
61
61
|
*
|
|
62
62
|
* The agent will:
|
|
63
63
|
* - Receive the ticket as its task description
|
|
64
|
-
* - Have access to all
|
|
64
|
+
* - Have access to all admin tools (create/update/delete content, globals, media, users)
|
|
65
65
|
* - Have access to ticket mutation tools (update status, add comment)
|
|
66
66
|
* - Run the agentic loop until done or max iterations
|
|
67
67
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticket-agent.d.ts","sourceRoot":"","sources":["../../src/orchestration/ticket-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"ticket-agent.d.ts","sourceRoot":"","sources":["../../src/orchestration/ticket-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,KAAK,EACV,cAAc,EAEd,kBAAkB,EAClB,cAAc,EACf,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGrE,OAAO,KAAK,EAAS,WAAW,EAAQ,MAAM,YAAY,CAAC;AAG3D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,0GAA0G;IAC1G,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,2CAA2C;IAC3C,SAAS,EAAE,SAAS,CAAC;IAErB,2DAA2D;IAC3D,SAAS,EAAE,cAAc,CAAC;IAE1B,wEAAwE;IACxE,YAAY,EAAE,oBAAoB,CAAC;IAEnC,yEAAyE;IACzE,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAEnC,yCAAyC;IACzC,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAE3B;;;;OAIG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB;;;OAGG;IACH,EAAE,CAAC,EAAE,QAAQ,CAAC;IAEd,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAwDD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,YAAY,CAAoB;gBAE5B,MAAM,EAAE,iBAAiB;IAUrC;;;;;;;;OAQG;IACG,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;CAwD1D"}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* Closes the loop between the ticketing system and the AI agent system.
|
|
5
5
|
*
|
|
6
6
|
* Flow:
|
|
7
|
-
* Ticket (title + description) → Task → Agent (
|
|
8
|
-
* → agentic loop →
|
|
7
|
+
* Ticket (title + description) → Task → Agent (admin tools + ticket tools)
|
|
8
|
+
* → agentic loop → admin mutations + ticket status updated + comment written
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
11
|
* const dispatcher = new TicketAgentDispatcher({ llmClient, apiClient, ticketClient })
|
|
12
12
|
* const result = await dispatcher.dispatch(ticket)
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
14
|
+
import { createAdminTools } from '../tools/admin/factory.js';
|
|
15
15
|
import { createDocumentSummarizerTool } from '../tools/document-summarizer.js';
|
|
16
16
|
import { createTicketTools } from '../tools/ticket-tools.js';
|
|
17
17
|
import { webScraperTool } from '../tools/web/scraper.js';
|
|
@@ -61,7 +61,7 @@ function buildInstructions(ticket) {
|
|
|
61
61
|
|
|
62
62
|
Your job is to:
|
|
63
63
|
1. Understand the intent of the ticket
|
|
64
|
-
2. Use the available
|
|
64
|
+
2. Use the available admin tools to take the necessary actions (create, update, or delete content)
|
|
65
65
|
3. When your work is done, call add_ticket_comment to summarize what you did
|
|
66
66
|
4. Finally, call update_ticket_status with status="done"
|
|
67
67
|
5. If you cannot complete the task, call add_ticket_comment to explain why, then update_ticket_status with status="blocked"
|
|
@@ -91,21 +91,21 @@ export class TicketAgentDispatcher {
|
|
|
91
91
|
*
|
|
92
92
|
* The agent will:
|
|
93
93
|
* - Receive the ticket as its task description
|
|
94
|
-
* - Have access to all
|
|
94
|
+
* - Have access to all admin tools (create/update/delete content, globals, media, users)
|
|
95
95
|
* - Have access to ticket mutation tools (update status, add comment)
|
|
96
96
|
* - Run the agentic loop until done or max iterations
|
|
97
97
|
*/
|
|
98
98
|
async dispatch(ticket) {
|
|
99
99
|
const { apiClient, ticketClient, collections, globals, memory: sharedMemory, db } = this.config;
|
|
100
|
-
// Build tool set:
|
|
100
|
+
// Build tool set: admin tools + ticket mutation tools + web scraper + optional summarizer
|
|
101
101
|
const cmsConfig = { apiClient, collections, globals };
|
|
102
|
-
const cmsTools =
|
|
102
|
+
const cmsTools = createAdminTools(cmsConfig);
|
|
103
103
|
const ticketTools = createTicketTools(ticket.id, ticketClient);
|
|
104
104
|
const extraTools = db
|
|
105
105
|
? [webScraperTool, createDocumentSummarizerTool(db, this.config.llmClient)]
|
|
106
106
|
: [webScraperTool];
|
|
107
107
|
const tools = [...cmsTools, ...ticketTools, ...extraTools];
|
|
108
|
-
// The runtime does not call agent.memory
|
|
108
|
+
// The runtime does not call agent.memory - satisfy the interface with a stub when no
|
|
109
109
|
// shared memory instance is provided. Cast is safe: only runtime touches this field.
|
|
110
110
|
const memory = (sharedMemory ?? {});
|
|
111
111
|
const agent = {
|
|
@@ -119,7 +119,7 @@ export class TicketAgentDispatcher {
|
|
|
119
119
|
agentId: `ticket-agent-${ticket.id}`,
|
|
120
120
|
currentTask: {
|
|
121
121
|
id: ticket.id,
|
|
122
|
-
type: ticket.type ?? '
|
|
122
|
+
type: ticket.type ?? 'admin',
|
|
123
123
|
description: descriptionToString(ticket.description),
|
|
124
124
|
},
|
|
125
125
|
};
|
|
@@ -133,7 +133,7 @@ export class TicketAgentDispatcher {
|
|
|
133
133
|
: ticket.title;
|
|
134
134
|
const task = {
|
|
135
135
|
id: ticket.id,
|
|
136
|
-
type: ticket.type ?? '
|
|
136
|
+
type: ticket.type ?? 'admin',
|
|
137
137
|
description: taskDescription,
|
|
138
138
|
priority: ticket.priority === 'critical' ? 1 : ticket.priority === 'high' ? 2 : 3,
|
|
139
139
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vercel-catalog.d.ts","sourceRoot":"","sources":["../../../src/skills/catalog/vercel-catalog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAmB,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7F;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAiBD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAgC3F;
|
|
1
|
+
{"version":3,"file":"vercel-catalog.d.ts","sourceRoot":"","sources":["../../../src/skills/catalog/vercel-catalog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAmB,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7F;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAiBD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAgC3F;AAkHD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,SAAK,EACV,MAAM,GAAE,aAAkB,GACzB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAO/B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAKzD"}
|
|
@@ -64,15 +64,18 @@ export async function fetchVercelCatalog(config = {}) {
|
|
|
64
64
|
* Load catalog from cache if valid.
|
|
65
65
|
*/
|
|
66
66
|
function loadFromCache(cachePath, ttl) {
|
|
67
|
-
|
|
67
|
+
// Read first to avoid TOCTOU between stat and read (file could disappear between calls)
|
|
68
|
+
let content;
|
|
69
|
+
try {
|
|
70
|
+
content = fs.readFileSync(cachePath, 'utf-8');
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
68
73
|
return null;
|
|
69
74
|
}
|
|
70
|
-
const
|
|
71
|
-
const age = Date.now() - stats.mtimeMs;
|
|
75
|
+
const age = Date.now() - fs.statSync(cachePath).mtimeMs;
|
|
72
76
|
if (age > ttl) {
|
|
73
77
|
return null;
|
|
74
78
|
}
|
|
75
|
-
const content = fs.readFileSync(cachePath, 'utf-8');
|
|
76
79
|
return JSON.parse(content);
|
|
77
80
|
}
|
|
78
81
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-loader.d.ts","sourceRoot":"","sources":["../../../src/skills/loader/github-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAezC;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CA+B9D;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAElB,uCAAuC;IACvC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAE1B,sCAAsC;IACtC,QAAQ,EAAE,aAAa,CAAC;IAExB,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,wCAAwC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"github-loader.d.ts","sourceRoot":"","sources":["../../../src/skills/loader/github-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAezC;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CA+B9D;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAElB,uCAAuC;IACvC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAE1B,sCAAsC;IACtC,QAAQ,EAAE,aAAa,CAAC;IAExB,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,wCAAwC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAkE/F;AAmED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAS5B;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAY3E"}
|
|
@@ -59,6 +59,8 @@ export function parseGitHubSource(source) {
|
|
|
59
59
|
*/
|
|
60
60
|
export async function loadFromGitHub(source, options) {
|
|
61
61
|
const parsed = parseGitHubSource(source);
|
|
62
|
+
validateGitArg(parsed.owner, 'owner');
|
|
63
|
+
validateGitArg(parsed.repo, 'repo');
|
|
62
64
|
const repoUrl = `https://github.com/${parsed.owner}/${parsed.repo}.git`;
|
|
63
65
|
// Determine skill name from path or repo name
|
|
64
66
|
const skillName = parsed.path ? path.basename(parsed.path) : parsed.repo;
|
|
@@ -94,7 +94,7 @@ export async function loadAllFromDirectory(dir, options) {
|
|
|
94
94
|
skills.push(skill);
|
|
95
95
|
}
|
|
96
96
|
catch {
|
|
97
|
-
// Skip malformed or unreadable skill files
|
|
97
|
+
// Skip malformed or unreadable skill files - partial load is better than a hard crash
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
return skills;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vercel-loader.d.ts","sourceRoot":"","sources":["../../../src/skills/loader/vercel-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,mBAAmB,CAAC;AAgB3B;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAElB,uCAAuC;IACvC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAE1B,sCAAsC;IACtC,QAAQ,EAAE,aAAa,CAAC;IAExB,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,wCAAwC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,KAAK,CAAC,CAgFhB;
|
|
1
|
+
{"version":3,"file":"vercel-loader.d.ts","sourceRoot":"","sources":["../../../src/skills/loader/vercel-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,mBAAmB,CAAC;AAgB3B;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAElB,uCAAuC;IACvC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAE1B,sCAAsC;IACtC,QAAQ,EAAE,aAAa,CAAC;IAExB,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,wCAAwC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,KAAK,CAAC,CAgFhB;AAkLD;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,UAAU,CAAC,CAyCrB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,KAAK,CAAC,CAwBhB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO7D"}
|
|
@@ -182,6 +182,8 @@ function extractInstallPath(output, baseDir, source) {
|
|
|
182
182
|
* @returns Installation path
|
|
183
183
|
*/
|
|
184
184
|
async function fallbackGitClone(source, targetPath) {
|
|
185
|
+
validateGitArg(source.owner, 'owner');
|
|
186
|
+
validateGitArg(source.repo, 'repo');
|
|
185
187
|
const repoUrl = `https://github.com/${source.owner}/${source.repo}.git`;
|
|
186
188
|
if (source.path) {
|
|
187
189
|
// Use sparse checkout for subdirectory
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { SkillMetadataSchema } from '../types.js';
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
|
-
// Minimal YAML parser/stringifier
|
|
8
|
+
// Minimal YAML parser/stringifier - replaces the `yaml` package.
|
|
9
9
|
// Handles the flat key-value + block-sequence subset used in SKILL.md files.
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
function yamlParseScalar(s) {
|
|
@@ -48,7 +48,7 @@ function yamlParse(input) {
|
|
|
48
48
|
// Inline array: key: [a, b] OR block sequence (items follow indented with `- `)
|
|
49
49
|
const peek = lines[i]?.trim() ?? '';
|
|
50
50
|
if (peek.startsWith('[')) {
|
|
51
|
-
// inline
|
|
51
|
+
// inline - handled below on next iteration; should not happen in this branch
|
|
52
52
|
}
|
|
53
53
|
const items = [];
|
|
54
54
|
while (i < lines.length) {
|