@lota-sdk/core 0.1.5
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/infrastructure/schema/00_workstream.surql +55 -0
- package/infrastructure/schema/01_memory.surql +47 -0
- package/infrastructure/schema/02_execution_plan.surql +62 -0
- package/infrastructure/schema/03_learned_skill.surql +32 -0
- package/infrastructure/schema/04_runtime_bootstrap.surql +8 -0
- package/package.json +128 -0
- package/src/ai/definitions.ts +308 -0
- package/src/bifrost/bifrost.ts +256 -0
- package/src/config/agent-defaults.ts +99 -0
- package/src/config/constants.ts +33 -0
- package/src/config/env-shapes.ts +122 -0
- package/src/config/logger.ts +29 -0
- package/src/config/model-constants.ts +31 -0
- package/src/config/search.ts +17 -0
- package/src/config/workstream-defaults.ts +68 -0
- package/src/db/base.service.ts +55 -0
- package/src/db/cursor-pagination.ts +73 -0
- package/src/db/memory-query-builder.ts +207 -0
- package/src/db/memory-store.helpers.ts +118 -0
- package/src/db/memory-store.rows.ts +29 -0
- package/src/db/memory-store.ts +974 -0
- package/src/db/memory-types.ts +193 -0
- package/src/db/memory.ts +505 -0
- package/src/db/record-id.ts +78 -0
- package/src/db/service.ts +932 -0
- package/src/db/startup.ts +152 -0
- package/src/db/tables.ts +20 -0
- package/src/document/org-document-chunking.ts +224 -0
- package/src/document/parsing.ts +40 -0
- package/src/embeddings/provider.ts +76 -0
- package/src/index.ts +302 -0
- package/src/queues/context-compaction.queue.ts +82 -0
- package/src/queues/document-processor.queue.ts +118 -0
- package/src/queues/memory-consolidation.queue.ts +65 -0
- package/src/queues/post-chat-memory.queue.ts +128 -0
- package/src/queues/recent-activity-title-refinement.queue.ts +69 -0
- package/src/queues/regular-chat-memory-digest.config.ts +12 -0
- package/src/queues/regular-chat-memory-digest.queue.ts +73 -0
- package/src/queues/skill-extraction.config.ts +9 -0
- package/src/queues/skill-extraction.queue.ts +62 -0
- package/src/redis/connection.ts +176 -0
- package/src/redis/index.ts +30 -0
- package/src/redis/org-memory-lock.ts +43 -0
- package/src/redis/redis-lease-lock.ts +158 -0
- package/src/runtime/agent-contract.ts +1 -0
- package/src/runtime/agent-prompt-context.ts +119 -0
- package/src/runtime/agent-runtime-policy.ts +192 -0
- package/src/runtime/agent-stream-helpers.ts +117 -0
- package/src/runtime/agent-types.ts +22 -0
- package/src/runtime/approval-continuation.ts +16 -0
- package/src/runtime/chat-attachments.ts +46 -0
- package/src/runtime/chat-message.ts +10 -0
- package/src/runtime/chat-request-routing.ts +21 -0
- package/src/runtime/chat-run-orchestration.ts +25 -0
- package/src/runtime/chat-run-registry.ts +20 -0
- package/src/runtime/chat-types.ts +18 -0
- package/src/runtime/context-compaction-constants.ts +11 -0
- package/src/runtime/context-compaction-runtime.ts +86 -0
- package/src/runtime/context-compaction.ts +909 -0
- package/src/runtime/execution-plan.ts +59 -0
- package/src/runtime/helper-model.ts +405 -0
- package/src/runtime/indexed-repositories-policy.ts +28 -0
- package/src/runtime/instruction-sections.ts +8 -0
- package/src/runtime/llm-content.ts +71 -0
- package/src/runtime/memory-block.ts +264 -0
- package/src/runtime/memory-digest-policy.ts +14 -0
- package/src/runtime/memory-format.ts +8 -0
- package/src/runtime/memory-pipeline.ts +570 -0
- package/src/runtime/memory-prompts-fact.ts +47 -0
- package/src/runtime/memory-prompts-parse.ts +3 -0
- package/src/runtime/memory-prompts-update.ts +37 -0
- package/src/runtime/memory-scope.ts +43 -0
- package/src/runtime/plugin-types.ts +10 -0
- package/src/runtime/retrieval-adapters.ts +25 -0
- package/src/runtime/retrieval-pipeline.ts +3 -0
- package/src/runtime/runtime-extensions.ts +154 -0
- package/src/runtime/skill-extraction-policy.ts +3 -0
- package/src/runtime/team-consultation-orchestrator.ts +245 -0
- package/src/runtime/team-consultation-prompts.ts +32 -0
- package/src/runtime/title-helpers.ts +12 -0
- package/src/runtime/turn-lifecycle.ts +28 -0
- package/src/runtime/workstream-chat-helpers.ts +187 -0
- package/src/runtime/workstream-routing-policy.ts +301 -0
- package/src/runtime/workstream-state.ts +261 -0
- package/src/services/attachment.service.ts +159 -0
- package/src/services/chat-attachments.service.ts +17 -0
- package/src/services/chat-run-registry.service.ts +3 -0
- package/src/services/context-compaction-runtime.ts +13 -0
- package/src/services/context-compaction.service.ts +115 -0
- package/src/services/document-chunk.service.ts +141 -0
- package/src/services/execution-plan.service.ts +890 -0
- package/src/services/learned-skill.service.ts +328 -0
- package/src/services/memory-assessment.service.ts +43 -0
- package/src/services/memory.service.ts +807 -0
- package/src/services/memory.utils.ts +84 -0
- package/src/services/mutating-approval.service.ts +110 -0
- package/src/services/recent-activity-title.service.ts +74 -0
- package/src/services/recent-activity.service.ts +397 -0
- package/src/services/workstream-change-tracker.service.ts +313 -0
- package/src/services/workstream-message.service.ts +283 -0
- package/src/services/workstream-title.service.ts +58 -0
- package/src/services/workstream-turn-preparation.ts +1340 -0
- package/src/services/workstream-turn.ts +37 -0
- package/src/services/workstream.service.ts +854 -0
- package/src/services/workstream.types.ts +118 -0
- package/src/storage/attachment-parser.ts +101 -0
- package/src/storage/attachment-storage.service.ts +391 -0
- package/src/storage/attachments.types.ts +11 -0
- package/src/storage/attachments.utils.ts +58 -0
- package/src/storage/generated-document-storage.service.ts +55 -0
- package/src/system-agents/agent-result.ts +27 -0
- package/src/system-agents/context-compacter.agent.ts +46 -0
- package/src/system-agents/delegated-agent-factory.ts +177 -0
- package/src/system-agents/helper-agent-options.ts +20 -0
- package/src/system-agents/memory-reranker.agent.ts +38 -0
- package/src/system-agents/memory.agent.ts +58 -0
- package/src/system-agents/recent-activity-title-refiner.agent.ts +53 -0
- package/src/system-agents/regular-chat-memory-digest.agent.ts +75 -0
- package/src/system-agents/researcher.agent.ts +34 -0
- package/src/system-agents/skill-extractor.agent.ts +88 -0
- package/src/system-agents/skill-manager.agent.ts +80 -0
- package/src/system-agents/title-generator.agent.ts +42 -0
- package/src/system-agents/workstream-tracker.agent.ts +58 -0
- package/src/tools/execution-plan.tool.ts +163 -0
- package/src/tools/fetch-webpage.tool.ts +132 -0
- package/src/tools/firecrawl-client.ts +12 -0
- package/src/tools/memory-block.tool.ts +55 -0
- package/src/tools/read-file-parts.tool.ts +80 -0
- package/src/tools/remember-memory.tool.ts +85 -0
- package/src/tools/research-topic.tool.ts +15 -0
- package/src/tools/search-tools.ts +55 -0
- package/src/tools/search-web.tool.ts +175 -0
- package/src/tools/team-think.tool.ts +125 -0
- package/src/tools/tool-contract.ts +21 -0
- package/src/tools/user-questions.tool.ts +18 -0
- package/src/utils/async.ts +50 -0
- package/src/utils/date-time.ts +34 -0
- package/src/utils/error.ts +10 -0
- package/src/utils/errors.ts +28 -0
- package/src/utils/hono-error-handler.ts +71 -0
- package/src/utils/string.ts +51 -0
- package/src/workers/bootstrap.ts +44 -0
- package/src/workers/memory-consolidation.worker.ts +318 -0
- package/src/workers/regular-chat-memory-digest.helpers.ts +100 -0
- package/src/workers/regular-chat-memory-digest.runner.ts +363 -0
- package/src/workers/regular-chat-memory-digest.worker.ts +22 -0
- package/src/workers/skill-extraction.runner.ts +331 -0
- package/src/workers/skill-extraction.worker.ts +22 -0
- package/src/workers/utils/repo-indexer-chunker.ts +331 -0
- package/src/workers/utils/repo-structure-extractor.ts +645 -0
- package/src/workers/utils/repomix-process-concurrency.ts +65 -0
- package/src/workers/utils/sandbox-error.ts +5 -0
- package/src/workers/worker-utils.ts +182 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Workstream table.
|
|
2
|
+
DEFINE TABLE IF NOT EXISTS workstream SCHEMAFULL;
|
|
3
|
+
DEFINE FIELD IF NOT EXISTS organizationId ON TABLE workstream TYPE record<organization>;
|
|
4
|
+
DEFINE FIELD IF NOT EXISTS userId ON TABLE workstream TYPE record<user>;
|
|
5
|
+
DEFINE FIELD IF NOT EXISTS agentId ON TABLE workstream TYPE option<string>;
|
|
6
|
+
DEFINE FIELD IF NOT EXISTS mode ON TABLE workstream TYPE string DEFAULT 'group';
|
|
7
|
+
DEFINE FIELD IF NOT EXISTS core ON TABLE workstream TYPE bool DEFAULT false;
|
|
8
|
+
DEFINE FIELD IF NOT EXISTS coreType ON TABLE workstream TYPE option<string>;
|
|
9
|
+
DEFINE FIELD IF NOT EXISTS title ON TABLE workstream TYPE option<string>;
|
|
10
|
+
DEFINE FIELD IF NOT EXISTS status ON TABLE workstream TYPE string DEFAULT 'regular';
|
|
11
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE workstream TYPE datetime DEFAULT time::now() READONLY;
|
|
12
|
+
DEFINE FIELD IF NOT EXISTS updatedAt ON TABLE workstream TYPE datetime VALUE time::now();
|
|
13
|
+
DEFINE FIELD IF NOT EXISTS memoryBlock ON TABLE workstream TYPE option<string>;
|
|
14
|
+
DEFINE FIELD IF NOT EXISTS memoryBlockSummary ON TABLE workstream TYPE option<string>;
|
|
15
|
+
DEFINE FIELD IF NOT EXISTS activeRunId ON TABLE workstream TYPE option<string>;
|
|
16
|
+
DEFINE FIELD IF NOT EXISTS chatSummary ON TABLE workstream TYPE option<string>;
|
|
17
|
+
DEFINE FIELD IF NOT EXISTS lastCompactedMessageId ON TABLE workstream TYPE option<string>;
|
|
18
|
+
DEFINE FIELD IF NOT EXISTS isCompacting ON TABLE workstream TYPE bool DEFAULT false;
|
|
19
|
+
DEFINE FIELD IF NOT EXISTS state ON TABLE workstream TYPE option<object> FLEXIBLE;
|
|
20
|
+
|
|
21
|
+
DEFINE INDEX IF NOT EXISTS workstreamOrgIdx ON TABLE workstream COLUMNS organizationId;
|
|
22
|
+
|
|
23
|
+
# Workstream Message table (AI SDK UIMessage persistence).
|
|
24
|
+
# parts uses OVERWRITE on the wildcard to override the implicit non-FLEXIBLE
|
|
25
|
+
# definition that array<object> creates — this is the only way to allow
|
|
26
|
+
# arbitrary nested object shapes inside the array on SCHEMAFULL tables.
|
|
27
|
+
DEFINE TABLE IF NOT EXISTS workstreamMessage SCHEMAFULL;
|
|
28
|
+
DEFINE FIELD IF NOT EXISTS workstreamId ON TABLE workstreamMessage TYPE record<workstream> REFERENCE ON DELETE CASCADE;
|
|
29
|
+
DEFINE FIELD IF NOT EXISTS messageId ON TABLE workstreamMessage TYPE string;
|
|
30
|
+
DEFINE FIELD IF NOT EXISTS role ON TABLE workstreamMessage TYPE string;
|
|
31
|
+
DEFINE FIELD IF NOT EXISTS parts ON TABLE workstreamMessage TYPE array<object> FLEXIBLE;
|
|
32
|
+
DEFINE FIELD OVERWRITE parts.* ON TABLE workstreamMessage TYPE object FLEXIBLE;
|
|
33
|
+
DEFINE FIELD IF NOT EXISTS metadata ON TABLE workstreamMessage TYPE option<object> FLEXIBLE;
|
|
34
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE workstreamMessage TYPE datetime DEFAULT time::now() READONLY;
|
|
35
|
+
DEFINE FIELD IF NOT EXISTS updatedAt ON TABLE workstreamMessage TYPE datetime VALUE time::now();
|
|
36
|
+
|
|
37
|
+
DEFINE INDEX IF NOT EXISTS workstreamMessageWorkstreamIdx ON TABLE workstreamMessage COLUMNS workstreamId;
|
|
38
|
+
DEFINE INDEX IF NOT EXISTS workstreamMessageWorkstreamCreatedIdx ON TABLE workstreamMessage COLUMNS workstreamId, createdAt;
|
|
39
|
+
DEFINE INDEX IF NOT EXISTS workstreamMessageWorkstreamMessageUniqueIdx ON TABLE workstreamMessage COLUMNS workstreamId, messageId UNIQUE;
|
|
40
|
+
|
|
41
|
+
# Workstream attachments.
|
|
42
|
+
DEFINE TABLE IF NOT EXISTS workstreamAttachment SCHEMAFULL;
|
|
43
|
+
DEFINE FIELD IF NOT EXISTS workstreamId ON TABLE workstreamAttachment TYPE record<workstream> REFERENCE ON DELETE CASCADE;
|
|
44
|
+
DEFINE FIELD IF NOT EXISTS messageId ON TABLE workstreamAttachment TYPE record<workstreamMessage> REFERENCE ON DELETE CASCADE;
|
|
45
|
+
DEFINE FIELD IF NOT EXISTS attachmentType ON TABLE workstreamAttachment TYPE string;
|
|
46
|
+
DEFINE FIELD IF NOT EXISTS name ON TABLE workstreamAttachment TYPE string;
|
|
47
|
+
DEFINE FIELD IF NOT EXISTS contentType ON TABLE workstreamAttachment TYPE string;
|
|
48
|
+
DEFINE FIELD IF NOT EXISTS storageKey ON TABLE workstreamAttachment TYPE option<string>;
|
|
49
|
+
DEFINE FIELD IF NOT EXISTS sizeBytes ON TABLE workstreamAttachment TYPE option<int>;
|
|
50
|
+
DEFINE FIELD IF NOT EXISTS url ON TABLE workstreamAttachment TYPE option<string>;
|
|
51
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE workstreamAttachment TYPE datetime DEFAULT time::now() READONLY;
|
|
52
|
+
DEFINE FIELD IF NOT EXISTS updatedAt ON TABLE workstreamAttachment TYPE datetime VALUE time::now();
|
|
53
|
+
|
|
54
|
+
DEFINE INDEX IF NOT EXISTS workstreamAttachmentWorkstreamIdx ON TABLE workstreamAttachment COLUMNS workstreamId;
|
|
55
|
+
DEFINE INDEX IF NOT EXISTS workstreamAttachmentMessageIdx ON TABLE workstreamAttachment COLUMNS messageId;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Memory tables for chat memory system.
|
|
2
|
+
DEFINE TABLE IF NOT EXISTS memory SCHEMAFULL;
|
|
3
|
+
DEFINE FIELD IF NOT EXISTS content ON TABLE memory TYPE string;
|
|
4
|
+
DEFINE FIELD IF NOT EXISTS embedding ON TABLE memory TYPE array<float>;
|
|
5
|
+
DEFINE FIELD IF NOT EXISTS hash ON TABLE memory TYPE string;
|
|
6
|
+
DEFINE FIELD IF NOT EXISTS scopeId ON TABLE memory TYPE string;
|
|
7
|
+
# memoryType: fact, preference, interaction, summary, user_request, entity, interest
|
|
8
|
+
DEFINE FIELD IF NOT EXISTS memoryType ON TABLE memory TYPE string;
|
|
9
|
+
-- Memory metadata evolves (orgId, sessionId, etc.). Keep it flexible.
|
|
10
|
+
DEFINE FIELD IF NOT EXISTS metadata ON TABLE memory TYPE object FLEXIBLE DEFAULT {};
|
|
11
|
+
# durability: core (business decisions, 0% decay), standard (general facts, 5% decay), ephemeral (preferences, 15% decay)
|
|
12
|
+
DEFINE FIELD IF NOT EXISTS durability ON TABLE memory TYPE string DEFAULT 'standard';
|
|
13
|
+
DEFINE FIELD IF NOT EXISTS importance ON TABLE memory TYPE float DEFAULT 1.0;
|
|
14
|
+
DEFINE FIELD IF NOT EXISTS accessCount ON TABLE memory TYPE int DEFAULT 0;
|
|
15
|
+
DEFINE FIELD IF NOT EXISTS lastAccessedAt ON TABLE memory TYPE option<datetime>;
|
|
16
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE memory TYPE datetime DEFAULT time::now() READONLY;
|
|
17
|
+
DEFINE FIELD IF NOT EXISTS updatedAt ON TABLE memory TYPE option<datetime>;
|
|
18
|
+
DEFINE FIELD IF NOT EXISTS validFrom ON TABLE memory TYPE datetime DEFAULT time::now();
|
|
19
|
+
DEFINE FIELD IF NOT EXISTS validUntil ON TABLE memory TYPE option<datetime>;
|
|
20
|
+
DEFINE FIELD IF NOT EXISTS archivedAt ON TABLE memory TYPE option<datetime>;
|
|
21
|
+
DEFINE FIELD IF NOT EXISTS needsReview ON TABLE memory TYPE bool DEFAULT false;
|
|
22
|
+
|
|
23
|
+
DEFINE TABLE IF NOT EXISTS memoryRelation SCHEMAFULL TYPE RELATION IN memory OUT memory;
|
|
24
|
+
# relationType: contradicts, supports, supersedes, caused_by, depends_on, part_of, implements
|
|
25
|
+
DEFINE FIELD IF NOT EXISTS relationType ON TABLE memoryRelation TYPE string;
|
|
26
|
+
DEFINE FIELD IF NOT EXISTS confidence ON TABLE memoryRelation TYPE float DEFAULT 1.0;
|
|
27
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE memoryRelation TYPE datetime DEFAULT time::now() READONLY;
|
|
28
|
+
|
|
29
|
+
DEFINE TABLE IF NOT EXISTS memoryHistory SCHEMAFULL;
|
|
30
|
+
DEFINE FIELD IF NOT EXISTS memoryId ON TABLE memoryHistory TYPE record<memory>;
|
|
31
|
+
DEFINE FIELD IF NOT EXISTS prevValue ON TABLE memoryHistory TYPE option<string>;
|
|
32
|
+
DEFINE FIELD IF NOT EXISTS newValue ON TABLE memoryHistory TYPE option<string>;
|
|
33
|
+
DEFINE FIELD IF NOT EXISTS event ON TABLE memoryHistory TYPE string;
|
|
34
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE memoryHistory TYPE datetime DEFAULT time::now() READONLY;
|
|
35
|
+
|
|
36
|
+
DEFINE ANALYZER IF NOT EXISTS memoryAnalyzer TOKENIZERS blank, class, punct FILTERS lowercase, snowball(english);
|
|
37
|
+
DEFINE INDEX IF NOT EXISTS memoryVectorIdx ON TABLE memory FIELDS embedding HNSW DIMENSION 1536 DIST COSINE TYPE F32;
|
|
38
|
+
DEFINE INDEX IF NOT EXISTS memoryContentFts ON TABLE memory FIELDS content FULLTEXT ANALYZER memoryAnalyzer BM25 HIGHLIGHTS;
|
|
39
|
+
DEFINE INDEX IF NOT EXISTS memoryScopeIdIdx ON TABLE memory COLUMNS scopeId;
|
|
40
|
+
DEFINE INDEX IF NOT EXISTS memoryHashIdx ON TABLE memory COLUMNS hash UNIQUE;
|
|
41
|
+
DEFINE INDEX IF NOT EXISTS memoryArchivedIdx ON TABLE memory COLUMNS archivedAt;
|
|
42
|
+
DEFINE INDEX IF NOT EXISTS memoryScopeTypeArchivedIdx ON TABLE memory COLUMNS scopeId, memoryType, archivedAt;
|
|
43
|
+
DEFINE INDEX IF NOT EXISTS memoryScopeTemporalIdx ON TABLE memory COLUMNS scopeId, archivedAt, validFrom, validUntil;
|
|
44
|
+
DEFINE INDEX IF NOT EXISTS memoryNeedsReviewIdx ON TABLE memory COLUMNS scopeId, needsReview, archivedAt, updatedAt;
|
|
45
|
+
DEFINE INDEX IF NOT EXISTS memoryTopLookupIdx ON TABLE memory COLUMNS scopeId, memoryType, durability, archivedAt, importance, accessCount, lastAccessedAt, createdAt;
|
|
46
|
+
DEFINE INDEX IF NOT EXISTS memoryRelationOutTypeIdx ON TABLE memoryRelation COLUMNS out, relationType;
|
|
47
|
+
DEFINE INDEX IF NOT EXISTS memoryRelationInTypeIdx ON TABLE memoryRelation COLUMNS in, relationType;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Execution plan runtime.
|
|
2
|
+
DEFINE TABLE IF NOT EXISTS plan SCHEMAFULL;
|
|
3
|
+
DEFINE FIELD IF NOT EXISTS organizationId ON TABLE plan TYPE record<organization>;
|
|
4
|
+
DEFINE FIELD IF NOT EXISTS workstreamId ON TABLE plan TYPE record<workstream> REFERENCE ON DELETE CASCADE;
|
|
5
|
+
DEFINE FIELD IF NOT EXISTS title ON TABLE plan TYPE string;
|
|
6
|
+
DEFINE FIELD IF NOT EXISTS objective ON TABLE plan TYPE string;
|
|
7
|
+
DEFINE FIELD IF NOT EXISTS status ON TABLE plan TYPE string;
|
|
8
|
+
DEFINE FIELD IF NOT EXISTS leadAgentId ON TABLE plan TYPE string;
|
|
9
|
+
DEFINE FIELD IF NOT EXISTS currentTaskId ON TABLE plan TYPE option<record<planTask>>;
|
|
10
|
+
DEFINE FIELD IF NOT EXISTS restartFromTaskId ON TABLE plan TYPE option<record<planTask>>;
|
|
11
|
+
DEFINE FIELD IF NOT EXISTS replacedPlanId ON TABLE plan TYPE option<record<plan>>;
|
|
12
|
+
DEFINE FIELD IF NOT EXISTS failureCount ON TABLE plan TYPE int DEFAULT 0;
|
|
13
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE plan TYPE datetime DEFAULT time::now() READONLY;
|
|
14
|
+
DEFINE FIELD IF NOT EXISTS updatedAt ON TABLE plan TYPE datetime VALUE time::now();
|
|
15
|
+
DEFINE FIELD IF NOT EXISTS startedAt ON TABLE plan TYPE option<datetime>;
|
|
16
|
+
DEFINE FIELD IF NOT EXISTS completedAt ON TABLE plan TYPE option<datetime>;
|
|
17
|
+
|
|
18
|
+
DEFINE INDEX IF NOT EXISTS planWorkstreamIdx ON TABLE plan COLUMNS workstreamId;
|
|
19
|
+
DEFINE INDEX IF NOT EXISTS planWorkstreamStatusIdx ON TABLE plan COLUMNS workstreamId, status;
|
|
20
|
+
|
|
21
|
+
DEFINE TABLE IF NOT EXISTS planTask SCHEMAFULL;
|
|
22
|
+
DEFINE FIELD IF NOT EXISTS planId ON TABLE planTask TYPE record<plan> REFERENCE ON DELETE CASCADE;
|
|
23
|
+
DEFINE FIELD IF NOT EXISTS organizationId ON TABLE planTask TYPE record<organization>;
|
|
24
|
+
DEFINE FIELD IF NOT EXISTS workstreamId ON TABLE planTask TYPE record<workstream>;
|
|
25
|
+
DEFINE FIELD IF NOT EXISTS position ON TABLE planTask TYPE int;
|
|
26
|
+
DEFINE FIELD IF NOT EXISTS title ON TABLE planTask TYPE string;
|
|
27
|
+
DEFINE FIELD IF NOT EXISTS rationale ON TABLE planTask TYPE string;
|
|
28
|
+
DEFINE FIELD IF NOT EXISTS kind ON TABLE planTask TYPE string;
|
|
29
|
+
DEFINE FIELD IF NOT EXISTS ownerType ON TABLE planTask TYPE string;
|
|
30
|
+
DEFINE FIELD IF NOT EXISTS ownerRef ON TABLE planTask TYPE string;
|
|
31
|
+
DEFINE FIELD IF NOT EXISTS status ON TABLE planTask TYPE string;
|
|
32
|
+
DEFINE FIELD IF NOT EXISTS resultStatus ON TABLE planTask TYPE string DEFAULT 'not-started';
|
|
33
|
+
DEFINE FIELD IF NOT EXISTS input ON TABLE planTask TYPE option<object | string> FLEXIBLE;
|
|
34
|
+
DEFINE FIELD IF NOT EXISTS outputSummary ON TABLE planTask TYPE option<string>;
|
|
35
|
+
DEFINE FIELD IF NOT EXISTS blockedReason ON TABLE planTask TYPE option<string>;
|
|
36
|
+
DEFINE FIELD IF NOT EXISTS externalRef ON TABLE planTask TYPE option<string>;
|
|
37
|
+
DEFINE FIELD IF NOT EXISTS retryCount ON TABLE planTask TYPE int DEFAULT 0;
|
|
38
|
+
DEFINE FIELD IF NOT EXISTS idempotencyKey ON TABLE planTask TYPE string;
|
|
39
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE planTask TYPE datetime DEFAULT time::now() READONLY;
|
|
40
|
+
DEFINE FIELD IF NOT EXISTS updatedAt ON TABLE planTask TYPE datetime VALUE time::now();
|
|
41
|
+
DEFINE FIELD IF NOT EXISTS startedAt ON TABLE planTask TYPE option<datetime>;
|
|
42
|
+
DEFINE FIELD IF NOT EXISTS completedAt ON TABLE planTask TYPE option<datetime>;
|
|
43
|
+
|
|
44
|
+
DEFINE INDEX IF NOT EXISTS planTaskPlanPositionIdx ON TABLE planTask COLUMNS planId, position;
|
|
45
|
+
DEFINE INDEX IF NOT EXISTS planTaskPlanStatusIdx ON TABLE planTask COLUMNS planId, status;
|
|
46
|
+
DEFINE INDEX IF NOT EXISTS planTaskIdempotencyIdx ON TABLE planTask COLUMNS idempotencyKey UNIQUE;
|
|
47
|
+
|
|
48
|
+
DEFINE TABLE IF NOT EXISTS planEvent SCHEMAFULL;
|
|
49
|
+
DEFINE FIELD IF NOT EXISTS planId ON TABLE planEvent TYPE record<plan> REFERENCE ON DELETE CASCADE;
|
|
50
|
+
DEFINE FIELD IF NOT EXISTS taskId ON TABLE planEvent TYPE option<record<planTask>>;
|
|
51
|
+
DEFINE FIELD IF NOT EXISTS eventType ON TABLE planEvent TYPE string;
|
|
52
|
+
DEFINE FIELD IF NOT EXISTS fromStatus ON TABLE planEvent TYPE option<string>;
|
|
53
|
+
DEFINE FIELD IF NOT EXISTS toStatus ON TABLE planEvent TYPE option<string>;
|
|
54
|
+
DEFINE FIELD IF NOT EXISTS message ON TABLE planEvent TYPE string;
|
|
55
|
+
DEFINE FIELD IF NOT EXISTS detail ON TABLE planEvent TYPE option<object> FLEXIBLE;
|
|
56
|
+
DEFINE FIELD IF NOT EXISTS emittedBy ON TABLE planEvent TYPE string;
|
|
57
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE planEvent TYPE datetime DEFAULT time::now() READONLY;
|
|
58
|
+
|
|
59
|
+
DEFINE INDEX IF NOT EXISTS planEventPlanIdx ON TABLE planEvent COLUMNS planId;
|
|
60
|
+
DEFINE INDEX IF NOT EXISTS planEventTaskIdx ON TABLE planEvent COLUMNS taskId;
|
|
61
|
+
DEFINE INDEX IF NOT EXISTS planEventTypeIdx ON TABLE planEvent COLUMNS planId, eventType;
|
|
62
|
+
DEFINE INDEX IF NOT EXISTS planEventTimeIdx ON TABLE planEvent COLUMNS planId, createdAt;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Learned skills table — stores reusable procedural knowledge extracted from conversations.
|
|
2
|
+
DEFINE TABLE IF NOT EXISTS learnedSkill SCHEMAFULL;
|
|
3
|
+
|
|
4
|
+
DEFINE FIELD IF NOT EXISTS name ON TABLE learnedSkill TYPE string;
|
|
5
|
+
DEFINE FIELD IF NOT EXISTS description ON TABLE learnedSkill TYPE string;
|
|
6
|
+
DEFINE FIELD IF NOT EXISTS instructions ON TABLE learnedSkill TYPE string;
|
|
7
|
+
DEFINE FIELD IF NOT EXISTS triggers ON TABLE learnedSkill TYPE array<string> DEFAULT [];
|
|
8
|
+
DEFINE FIELD IF NOT EXISTS tags ON TABLE learnedSkill TYPE array<string> DEFAULT [];
|
|
9
|
+
DEFINE FIELD IF NOT EXISTS examples ON TABLE learnedSkill TYPE array<string> DEFAULT [];
|
|
10
|
+
DEFINE FIELD IF NOT EXISTS version ON TABLE learnedSkill TYPE int DEFAULT 1;
|
|
11
|
+
DEFINE FIELD IF NOT EXISTS sourceType ON TABLE learnedSkill TYPE string;
|
|
12
|
+
DEFINE FIELD IF NOT EXISTS organizationId ON TABLE learnedSkill TYPE record<organization>;
|
|
13
|
+
DEFINE FIELD IF NOT EXISTS agentId ON TABLE learnedSkill TYPE option<string>;
|
|
14
|
+
DEFINE FIELD IF NOT EXISTS status ON TABLE learnedSkill TYPE string DEFAULT 'learned';
|
|
15
|
+
DEFINE FIELD IF NOT EXISTS confidence ON TABLE learnedSkill TYPE float DEFAULT 0.5;
|
|
16
|
+
DEFINE FIELD IF NOT EXISTS usageCount ON TABLE learnedSkill TYPE int DEFAULT 0;
|
|
17
|
+
DEFINE FIELD IF NOT EXISTS successCount ON TABLE learnedSkill TYPE int DEFAULT 0;
|
|
18
|
+
DEFINE FIELD IF NOT EXISTS supersedes ON TABLE learnedSkill TYPE option<record<learnedSkill>>;
|
|
19
|
+
DEFINE FIELD IF NOT EXISTS embedding ON TABLE learnedSkill TYPE array<float>;
|
|
20
|
+
DEFINE FIELD IF NOT EXISTS hash ON TABLE learnedSkill TYPE string;
|
|
21
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON TABLE learnedSkill TYPE datetime DEFAULT time::now() READONLY;
|
|
22
|
+
DEFINE FIELD IF NOT EXISTS updatedAt ON TABLE learnedSkill TYPE option<datetime>;
|
|
23
|
+
DEFINE FIELD IF NOT EXISTS lastUsedAt ON TABLE learnedSkill TYPE option<datetime>;
|
|
24
|
+
DEFINE FIELD IF NOT EXISTS archivedAt ON TABLE learnedSkill TYPE option<datetime>;
|
|
25
|
+
|
|
26
|
+
# Indexes
|
|
27
|
+
DEFINE ANALYZER IF NOT EXISTS learnedSkillAnalyzer TOKENIZERS blank, class, punct FILTERS lowercase, snowball(english);
|
|
28
|
+
DEFINE INDEX IF NOT EXISTS learnedSkillVectorIdx ON TABLE learnedSkill FIELDS embedding HNSW DIMENSION 1536 DIST COSINE TYPE F32;
|
|
29
|
+
DEFINE INDEX IF NOT EXISTS learnedSkillContentFts ON TABLE learnedSkill FIELDS description FULLTEXT ANALYZER learnedSkillAnalyzer BM25 HIGHLIGHTS;
|
|
30
|
+
DEFINE INDEX IF NOT EXISTS learnedSkillOrgIdx ON TABLE learnedSkill COLUMNS organizationId;
|
|
31
|
+
DEFINE INDEX IF NOT EXISTS learnedSkillStatusIdx ON TABLE learnedSkill COLUMNS organizationId, status, archivedAt;
|
|
32
|
+
DEFINE INDEX IF NOT EXISTS learnedSkillHashIdx ON TABLE learnedSkill COLUMNS hash UNIQUE;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Runtime bootstrap readiness state.
|
|
2
|
+
DEFINE TABLE IF NOT EXISTS runtimeBootstrap SCHEMAFULL;
|
|
3
|
+
DEFINE FIELD IF NOT EXISTS key ON TABLE runtimeBootstrap TYPE string;
|
|
4
|
+
DEFINE FIELD IF NOT EXISTS schemaFingerprint ON TABLE runtimeBootstrap TYPE string;
|
|
5
|
+
DEFINE FIELD IF NOT EXISTS readyAt ON TABLE runtimeBootstrap TYPE datetime;
|
|
6
|
+
DEFINE FIELD IF NOT EXISTS updatedAt ON TABLE runtimeBootstrap TYPE datetime VALUE time::now();
|
|
7
|
+
|
|
8
|
+
DEFINE INDEX IF NOT EXISTS runtimeBootstrapKeyUniqueIdx ON TABLE runtimeBootstrap COLUMNS key UNIQUE;
|
package/package.json
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lota-sdk/core",
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"src",
|
|
9
|
+
"infrastructure/schema"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"bun": "./src/index.ts",
|
|
14
|
+
"import": "./src/index.ts",
|
|
15
|
+
"types": "./src/index.ts"
|
|
16
|
+
},
|
|
17
|
+
"./ai/*": {
|
|
18
|
+
"bun": "./src/ai/*.ts",
|
|
19
|
+
"import": "./src/ai/*.ts",
|
|
20
|
+
"types": "./src/ai/*.ts"
|
|
21
|
+
},
|
|
22
|
+
"./bifrost": {
|
|
23
|
+
"bun": "./src/bifrost/bifrost.ts",
|
|
24
|
+
"import": "./src/bifrost/bifrost.ts",
|
|
25
|
+
"types": "./src/bifrost/bifrost.ts"
|
|
26
|
+
},
|
|
27
|
+
"./bifrost/*": {
|
|
28
|
+
"bun": "./src/bifrost/*.ts",
|
|
29
|
+
"import": "./src/bifrost/*.ts",
|
|
30
|
+
"types": "./src/bifrost/*.ts"
|
|
31
|
+
},
|
|
32
|
+
"./runtime/*": {
|
|
33
|
+
"bun": "./src/runtime/*.ts",
|
|
34
|
+
"import": "./src/runtime/*.ts",
|
|
35
|
+
"types": "./src/runtime/*.ts"
|
|
36
|
+
},
|
|
37
|
+
"./tools/*": {
|
|
38
|
+
"bun": "./src/tools/*.ts",
|
|
39
|
+
"import": "./src/tools/*.ts",
|
|
40
|
+
"types": "./src/tools/*.ts"
|
|
41
|
+
},
|
|
42
|
+
"./storage/*": {
|
|
43
|
+
"bun": "./src/storage/*.ts",
|
|
44
|
+
"import": "./src/storage/*.ts",
|
|
45
|
+
"types": "./src/storage/*.ts"
|
|
46
|
+
},
|
|
47
|
+
"./document/*": {
|
|
48
|
+
"bun": "./src/document/*.ts",
|
|
49
|
+
"import": "./src/document/*.ts",
|
|
50
|
+
"types": "./src/document/*.ts"
|
|
51
|
+
},
|
|
52
|
+
"./system-agents/*": {
|
|
53
|
+
"bun": "./src/system-agents/*.ts",
|
|
54
|
+
"import": "./src/system-agents/*.ts",
|
|
55
|
+
"types": "./src/system-agents/*.ts"
|
|
56
|
+
},
|
|
57
|
+
"./db/*": {
|
|
58
|
+
"bun": "./src/db/*.ts",
|
|
59
|
+
"import": "./src/db/*.ts",
|
|
60
|
+
"types": "./src/db/*.ts"
|
|
61
|
+
},
|
|
62
|
+
"./redis": {
|
|
63
|
+
"bun": "./src/redis/index.ts",
|
|
64
|
+
"import": "./src/redis/index.ts",
|
|
65
|
+
"types": "./src/redis/index.ts"
|
|
66
|
+
},
|
|
67
|
+
"./redis/*": {
|
|
68
|
+
"bun": "./src/redis/*.ts",
|
|
69
|
+
"import": "./src/redis/*.ts",
|
|
70
|
+
"types": "./src/redis/*.ts"
|
|
71
|
+
},
|
|
72
|
+
"./services/*": {
|
|
73
|
+
"bun": "./src/services/*.ts",
|
|
74
|
+
"import": "./src/services/*.ts",
|
|
75
|
+
"types": "./src/services/*.ts"
|
|
76
|
+
},
|
|
77
|
+
"./config/*": {
|
|
78
|
+
"bun": "./src/config/*.ts",
|
|
79
|
+
"import": "./src/config/*.ts",
|
|
80
|
+
"types": "./src/config/*.ts"
|
|
81
|
+
},
|
|
82
|
+
"./utils/*": {
|
|
83
|
+
"bun": "./src/utils/*.ts",
|
|
84
|
+
"import": "./src/utils/*.ts",
|
|
85
|
+
"types": "./src/utils/*.ts"
|
|
86
|
+
},
|
|
87
|
+
"./queues/*": {
|
|
88
|
+
"bun": "./src/queues/*.ts",
|
|
89
|
+
"import": "./src/queues/*.ts",
|
|
90
|
+
"types": "./src/queues/*.ts"
|
|
91
|
+
},
|
|
92
|
+
"./workers/*": {
|
|
93
|
+
"bun": "./src/workers/*.ts",
|
|
94
|
+
"import": "./src/workers/*.ts",
|
|
95
|
+
"types": "./src/workers/*.ts"
|
|
96
|
+
},
|
|
97
|
+
"./embeddings": {
|
|
98
|
+
"bun": "./src/embeddings/provider.ts",
|
|
99
|
+
"import": "./src/embeddings/provider.ts",
|
|
100
|
+
"types": "./src/embeddings/provider.ts"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"scripts": {
|
|
104
|
+
"lint": "node ../node_modules/oxlint/bin/oxlint --fix -c ../oxlint.config.ts src",
|
|
105
|
+
"format": "bunx oxfmt src",
|
|
106
|
+
"typecheck": "bunx tsgo --noEmit",
|
|
107
|
+
"test:unit": "bun test ../tests/unit/core"
|
|
108
|
+
},
|
|
109
|
+
"publishConfig": {
|
|
110
|
+
"access": "public",
|
|
111
|
+
"registry": "https://registry.npmjs.org/"
|
|
112
|
+
},
|
|
113
|
+
"dependencies": {
|
|
114
|
+
"@ai-sdk/openai": "^3.0.41",
|
|
115
|
+
"@logtape/logtape": "^2.0.4",
|
|
116
|
+
"@lota-sdk/shared": "0.1.0",
|
|
117
|
+
"@mendable/firecrawl-js": "^4.16.0",
|
|
118
|
+
"@surrealdb/node": "^3.0.3",
|
|
119
|
+
"ai": "^6.0.116",
|
|
120
|
+
"bullmq": "^5.71.0",
|
|
121
|
+
"hono": "^4.12.8",
|
|
122
|
+
"ioredis": "5.9.3",
|
|
123
|
+
"mammoth": "^1.12.0",
|
|
124
|
+
"pdf-parse": "^2.4.5",
|
|
125
|
+
"surrealdb": "^2.0.2",
|
|
126
|
+
"zod": "^4.3.6"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import type { ToolSet } from 'ai'
|
|
2
|
+
|
|
3
|
+
export interface SkillDefinition<TToolName extends string = string> {
|
|
4
|
+
name: string
|
|
5
|
+
description: string
|
|
6
|
+
instructions: string
|
|
7
|
+
tools: readonly TToolName[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface RuleDefinition {
|
|
11
|
+
name: string
|
|
12
|
+
instructions: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface PromptDefinition {
|
|
16
|
+
name: string
|
|
17
|
+
instructions: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ToolDefinition<TContext> {
|
|
21
|
+
name: string
|
|
22
|
+
create: (context: TContext) => ToolSet[string]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function defineSkill<const TToolName extends string>(definition: SkillDefinition<TToolName>) {
|
|
26
|
+
return definition
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function defineRule(definition: RuleDefinition) {
|
|
30
|
+
return definition
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function definePrompt(definition: PromptDefinition) {
|
|
34
|
+
return definition
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function cleanInstructions(value: string): string {
|
|
38
|
+
return value.trim()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function renderRuleInstructions(rules: readonly RuleDefinition[]): string {
|
|
42
|
+
const sections = rules.map((rule) => cleanInstructions(rule.instructions)).filter((value) => value.length > 0)
|
|
43
|
+
if (sections.length === 0) return ''
|
|
44
|
+
return ['<rules>', ...sections, '</rules>'].join('\n\n')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function renderSkillInstructions(skills: readonly SkillDefinition[]): string {
|
|
48
|
+
const sections = skills.map((skill) => cleanInstructions(skill.instructions)).filter((value) => value.length > 0)
|
|
49
|
+
if (sections.length === 0) return ''
|
|
50
|
+
return ['<skills>', ...sections, '</skills>'].join('\n\n')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** @lintignore */
|
|
54
|
+
export interface LearnedSkillEntry {
|
|
55
|
+
name: string
|
|
56
|
+
instructions: string
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function renderLearnedSkillInstructions(skills: readonly LearnedSkillEntry[]): string {
|
|
60
|
+
const sections = skills
|
|
61
|
+
.map((skill) => {
|
|
62
|
+
const instructions = cleanInstructions(skill.instructions)
|
|
63
|
+
if (!instructions) return ''
|
|
64
|
+
return `### ${skill.name}\n\n${instructions}`
|
|
65
|
+
})
|
|
66
|
+
.filter((value) => value.length > 0)
|
|
67
|
+
if (sections.length === 0) return ''
|
|
68
|
+
return [
|
|
69
|
+
'<learned-skills>',
|
|
70
|
+
'The following procedures were learned from previous interactions. Apply them when relevant.',
|
|
71
|
+
'',
|
|
72
|
+
...sections,
|
|
73
|
+
'</learned-skills>',
|
|
74
|
+
].join('\n\n')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const askingUserQuestionsSkillTools = ['userQuestions'] as const
|
|
78
|
+
|
|
79
|
+
export const askingUserQuestionsSkill = defineSkill({
|
|
80
|
+
name: 'asking-user-questions',
|
|
81
|
+
description: 'Ask structured clarification questions only when required to proceed safely or accurately.',
|
|
82
|
+
tools: askingUserQuestionsSkillTools,
|
|
83
|
+
instructions: `# asking-user-questions
|
|
84
|
+
|
|
85
|
+
## Description
|
|
86
|
+
|
|
87
|
+
Use this skill when an answer or action requires missing user input that cannot be inferred reliably.
|
|
88
|
+
|
|
89
|
+
## Details
|
|
90
|
+
|
|
91
|
+
<when-to-use>
|
|
92
|
+
- Requirements are ambiguous and different interpretations would change the outcome.
|
|
93
|
+
- A required identifier is missing (for example project/team/owner/issue reference).
|
|
94
|
+
- The user must choose between materially different options.
|
|
95
|
+
- You need explicit consent before a mutation or irreversible action.
|
|
96
|
+
- You need specific business context only the user can provide.
|
|
97
|
+
- The request is ambiguous and proceeding would produce low-quality output.
|
|
98
|
+
- You need approval or confirmation before taking a significant action.
|
|
99
|
+
</when-to-use>
|
|
100
|
+
|
|
101
|
+
<how-to-use>
|
|
102
|
+
Use the \`userQuestions\` tool to present structured questions. This renders an interactive form in the chat UI and
|
|
103
|
+
terminates the agent chain until the user responds. The user already sees this form, so do **not** restate the same
|
|
104
|
+
questions in plain text. Do **not** call any additional tools in the same response.
|
|
105
|
+
|
|
106
|
+
### Question types
|
|
107
|
+
|
|
108
|
+
- \`single-select\` — user picks one option from a list (with optional custom answer field)
|
|
109
|
+
- \`multi-select\` — user picks multiple options from a list (with optional custom answer field)
|
|
110
|
+
- \`input\` — user types a free-text answer
|
|
111
|
+
|
|
112
|
+
### Schema
|
|
113
|
+
|
|
114
|
+
\`\`\`json
|
|
115
|
+
{
|
|
116
|
+
"questions": [
|
|
117
|
+
{ "question": "What is your target market?", "type": "single-select", "options": ["B2B", "B2C", "Both"] },
|
|
118
|
+
{
|
|
119
|
+
"question": "Which features do you need?",
|
|
120
|
+
"type": "multi-select",
|
|
121
|
+
"options": ["Authentication", "REST API", "Admin Panel", "Analytics"]
|
|
122
|
+
},
|
|
123
|
+
{ "question": "What is your budget range?", "type": "input" }
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
\`\`\`
|
|
127
|
+
|
|
128
|
+
- \`options\` is a plain string array (no IDs needed).
|
|
129
|
+
- \`allowCustomAnswer\` (optional, defaults to \`true\` for select types) adds a free-text field alongside options.
|
|
130
|
+
- Do **not** generate additional text or tool calls after calling \`userQuestions\` (including repeating the questions as
|
|
131
|
+
plain text). Your turn is complete.
|
|
132
|
+
</how-to-use>
|
|
133
|
+
|
|
134
|
+
<do-not-use>
|
|
135
|
+
- Do not ask when reasonable defaults are already explicit in the user request.
|
|
136
|
+
- Do not ask for information that can be retrieved using available read tools.
|
|
137
|
+
- Do not ask broad discovery questions when one targeted question will unblock progress.
|
|
138
|
+
</do-not-use>`,
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
const researchSkillTools = ['researchTopic', 'fetchWebpage', 'inspectWebsite'] as const
|
|
142
|
+
|
|
143
|
+
export const researchSkill = defineSkill({
|
|
144
|
+
name: 'research',
|
|
145
|
+
description:
|
|
146
|
+
'Delegate research to a dedicated agent for gathering accurate, up-to-date information with source attribution and confidence assessment.',
|
|
147
|
+
tools: researchSkillTools,
|
|
148
|
+
instructions: `# research
|
|
149
|
+
|
|
150
|
+
## Description
|
|
151
|
+
|
|
152
|
+
Use for any task requiring external information gathering: market research, competitive analysis, technical evaluation,
|
|
153
|
+
fact verification, or source-backed answers. Delegates web research to a dedicated research agent.
|
|
154
|
+
|
|
155
|
+
## Details
|
|
156
|
+
|
|
157
|
+
<when-to-use>
|
|
158
|
+
- The user asks a question that requires current, external information beyond the agent's training data.
|
|
159
|
+
- Market sizing, competitor analysis, or industry trend research.
|
|
160
|
+
- Technical evaluation of tools, frameworks, vendors, or platforms.
|
|
161
|
+
- Fact-checking claims, statistics, or benchmarks before using them in deliverables.
|
|
162
|
+
- Gathering evidence to support or challenge a hypothesis from another skill.
|
|
163
|
+
|
|
164
|
+
Do NOT use when:
|
|
165
|
+
|
|
166
|
+
- The question can be answered from conversation context or organizational memory alone.
|
|
167
|
+
- The user is asking for coaching, strategy, or opinion (use a domain skill instead).
|
|
168
|
+
- The task is purely internal (roadmap prioritization, team dynamics, financial modeling from known data).
|
|
169
|
+
</when-to-use>
|
|
170
|
+
|
|
171
|
+
<how-to-research>
|
|
172
|
+
- Call \`researchTopic\` with a clear, specific research task description.
|
|
173
|
+
- For broad research, call 2-3 \`researchTopic\` instances **in parallel** with different focused tasks (e.g., one for market sizing, one for competitor analysis, one for pricing benchmarks).
|
|
174
|
+
- Each \`researchTopic\` call returns a synthesized markdown report with sources — you do not need to search or fetch pages yourself.
|
|
175
|
+
- Use \`fetchWebpage\` **only** when the user shares a specific URL they want you to read. Do not use it for general research.
|
|
176
|
+
- Use \`inspectWebsite\` when the user wants a structured analysis of a specific website or landing page. Give it the exact URL and what you need to learn from the page.
|
|
177
|
+
- When the user asks to refresh, re-run, or overwrite existing website extraction, call \`inspectWebsite\` with \`forceRefresh: true\`.
|
|
178
|
+
</how-to-research>
|
|
179
|
+
|
|
180
|
+
<startup-context>
|
|
181
|
+
- Time is the scarcest resource; research must be fast and decisive, not exhaustive.
|
|
182
|
+
- Early-stage decisions tolerate lower confidence thresholds; a directionally correct answer now beats a perfect answer next week.
|
|
183
|
+
- Prioritize sources that reveal market reality: pricing pages, job postings, SEC filings, G2/Capterra reviews, GitHub activity, and community forums over polished marketing content.
|
|
184
|
+
- Always contextualize findings to the startup's stage, segment, and constraints.
|
|
185
|
+
</startup-context>
|
|
186
|
+
|
|
187
|
+
<answering-style>
|
|
188
|
+
- Deliver findings directly; do not narrate the research process to the user.
|
|
189
|
+
- Lead with the answer or recommendation, then provide supporting evidence.
|
|
190
|
+
- State confidence level (high / medium / low) for each key claim based on source quality and corroboration.
|
|
191
|
+
- When sources conflict, present both sides and explain the discrepancy.
|
|
192
|
+
- Never mention internal tool names (researchTopic, fetchWebpage, inspectWebsite, skillDetails, memorySearch).
|
|
193
|
+
</answering-style>
|
|
194
|
+
|
|
195
|
+
<output-structure>
|
|
196
|
+
- Summary: 2-4 sentence bottom-line answer to the research question.
|
|
197
|
+
- Key Findings: Bulleted findings with inline source citations [URL] and confidence tags (high/medium/low).
|
|
198
|
+
- Comparison Table: (when applicable) structured comparison of alternatives, competitors, or options.
|
|
199
|
+
- Confidence Assessment: Overall confidence level with explanation of what drives it up or down.
|
|
200
|
+
- Gaps and Follow-ups: What remains unknown and what specific research would resolve it.
|
|
201
|
+
</output-structure>`,
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
export const generalRule = defineRule({
|
|
205
|
+
name: 'general',
|
|
206
|
+
instructions: `# General Rules
|
|
207
|
+
|
|
208
|
+
- Be concise and direct.
|
|
209
|
+
- Follow the user's request and constraints.
|
|
210
|
+
- Ask clarifying questions when necessary.
|
|
211
|
+
- Be formal and professional when tone is unclear.
|
|
212
|
+
- Avoid speculation; say when unsure.
|
|
213
|
+
- When the user provides durable organization URLs or product facts, persist them with the organization profile tools.
|
|
214
|
+
- Prefer actionable, ordered steps.`,
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
export const memr3Rule = defineRule({
|
|
218
|
+
name: 'memr3',
|
|
219
|
+
instructions: `# MemR3 Evidence-Gap Protocol
|
|
220
|
+
|
|
221
|
+
Use the MemR3 retrieval loop for every request.
|
|
222
|
+
|
|
223
|
+
## Evidence-Gap Tracker
|
|
224
|
+
|
|
225
|
+
- Maintain two explicit lists:
|
|
226
|
+
- **Evidence**: a fenced code block starting with \`evidence\`.
|
|
227
|
+
- **Gaps**: a fenced code block starting with \`gaps\`.
|
|
228
|
+
- Evidence must be grounded; never speculate or include missing info in the evidence block.
|
|
229
|
+
|
|
230
|
+
## What Counts As A Gap
|
|
231
|
+
|
|
232
|
+
Treat the \`gaps\` block as **specific, queryable blocking gaps only**: missing information that materially changes the
|
|
233
|
+
recommendation, action, or confidence level, or makes an answer unsafe/unreliable.
|
|
234
|
+
|
|
235
|
+
- Each gap should be atomic enough to resolve with one targeted retrieval query or one user question.
|
|
236
|
+
- If you can provide a useful answer with reasonable startup-stage assumptions and the remaining unknowns would not
|
|
237
|
+
materially change it, set \`gaps\` to \`- None\` and proceed.
|
|
238
|
+
- Non-blocking unknowns should be handled as:
|
|
239
|
+
- explicit assumptions in the answer, and/or
|
|
240
|
+
- 1-3 follow-up questions at the end (do not block the main recommendation).
|
|
241
|
+
|
|
242
|
+
## Retrieval Loop
|
|
243
|
+
|
|
244
|
+
1. **Recall**: Use internal knowledge and the current conversation.
|
|
245
|
+
2. **Retrieve**: If a retrieval tool is available, call it to fill gaps.
|
|
246
|
+
- Prefer \`memorySearch\` for stored memories (semantic retrieval + graph expansion).
|
|
247
|
+
- If retrieved memory context is already provided in-system for this turn and blocking gaps are already closed, you
|
|
248
|
+
may skip \`memorySearch\`.
|
|
249
|
+
- If any blocking gap remains after reviewing provided context, retrieval is mandatory.
|
|
250
|
+
- Use web tools only if you have them.
|
|
251
|
+
- If multiple gaps are independent, issue multiple tool calls concurrently in the same turn.
|
|
252
|
+
- For web research, call multiple \`researchTopic\` instances in parallel for different sub-questions.
|
|
253
|
+
3. **Reflect**: Update the evidence and gaps blocks.
|
|
254
|
+
- Remove resolved gaps.
|
|
255
|
+
- Split vague gaps into smaller, searchable gaps.
|
|
256
|
+
- Drop gaps that no longer matter because the answer is robust under explicit assumptions.
|
|
257
|
+
4. **Iterate**: If the gaps block still contains blocking items, issue targeted new queries in parallel and repeat.
|
|
258
|
+
- Keep queries short (5-15 tokens) and specific.
|
|
259
|
+
- Limit to 3 retrieve/reflect cycles unless the user explicitly asks for deeper research.
|
|
260
|
+
- Stop early once remaining unknowns are non-material; do not retrieve for completeness alone.
|
|
261
|
+
5. **Answer**: Answer once blocking gaps are \`None\`.
|
|
262
|
+
- If retrieval returns no useful evidence and the answer is still robust under stated assumptions, proceed and make
|
|
263
|
+
those assumptions explicit rather than stalling.
|
|
264
|
+
- Do not say "memory search yielded nothing" or mention tool names; translate it into plain-language uncertainty.
|
|
265
|
+
|
|
266
|
+
## Output Format
|
|
267
|
+
|
|
268
|
+
\`\`\`evidence
|
|
269
|
+
- ...
|
|
270
|
+
\`\`\`
|
|
271
|
+
|
|
272
|
+
\`\`\`gaps
|
|
273
|
+
- ... (or "None")
|
|
274
|
+
\`\`\`
|
|
275
|
+
|
|
276
|
+
- Provide your response using your normal response format.
|
|
277
|
+
- Never output raw tool payloads (JSON, object dumps, or memory IDs like \`memory:...\`) in the final answer; summarize
|
|
278
|
+
them in plain language.
|
|
279
|
+
- If blocking gaps remain after the loop, do not answer; ask for the missing information instead.`,
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
export const domainReasoningFallbackRule = defineRule({
|
|
283
|
+
name: 'domain-reasoning-fallback',
|
|
284
|
+
instructions: `# Domain Reasoning Fallback
|
|
285
|
+
|
|
286
|
+
Use this protocol when the question does **not** clearly match any available subdomain skill.
|
|
287
|
+
|
|
288
|
+
## Protocol
|
|
289
|
+
|
|
290
|
+
1. Restate the user’s goal in one sentence (what decision they’re trying to make).
|
|
291
|
+
2. Identify the core domain and the constraints that matter most (stage, runway, team size, time).
|
|
292
|
+
3. Separate **what is known** vs **what is uncertain**.
|
|
293
|
+
4. Apply first-principles reasoning from your role’s perspective:
|
|
294
|
+
- Generate 2-4 viable options (including “do nothing” when relevant).
|
|
295
|
+
- Compare trade-offs explicitly (speed vs quality, risk vs upside, cost vs impact).
|
|
296
|
+
- Call out irreversible decisions and how to de-risk them.
|
|
297
|
+
5. Make a clear recommendation with:
|
|
298
|
+
- Why this is the best option given startup constraints.
|
|
299
|
+
- The main risks and how to mitigate them.
|
|
300
|
+
- What you would measure to know it’s working.
|
|
301
|
+
6. If the answer depends on missing inputs, ask 1-3 targeted questions that would change the recommendation.
|
|
302
|
+
|
|
303
|
+
## Output Expectations
|
|
304
|
+
|
|
305
|
+
- Be concise and action-oriented.
|
|
306
|
+
- Prefer “good enough + iterate” over heavyweight process unless the decision is irreversible or high-risk.
|
|
307
|
+
- Use the agent’s normal response format sections (Decision, Rationale, Risks, Metrics, Next Steps).`,
|
|
308
|
+
})
|