@evomap/evolver-core 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/algo/antiDistill.d.ts +35 -0
- package/dist/algo/antiDistill.js +167 -0
- package/dist/algo/bans.d.ts +6 -0
- package/dist/algo/bans.js +33 -0
- package/dist/algo/candidateAssembly.d.ts +65 -0
- package/dist/algo/candidateAssembly.js +196 -0
- package/dist/algo/capabilityCandidates.d.ts +38 -0
- package/dist/algo/capabilityCandidates.js +131 -0
- package/dist/algo/confidence.d.ts +106 -0
- package/dist/algo/confidence.js +196 -0
- package/dist/algo/cycleEngine.d.ts +143 -0
- package/dist/algo/cycleEngine.js +417 -0
- package/dist/algo/cycleFailureClassifier.d.ts +52 -0
- package/dist/algo/cycleFailureClassifier.js +104 -0
- package/dist/algo/epigenetics.d.ts +14 -0
- package/dist/algo/epigenetics.js +41 -0
- package/dist/algo/evolutionEvent.d.ts +23 -0
- package/dist/algo/evolutionEvent.js +24 -0
- package/dist/algo/exploration.d.ts +34 -0
- package/dist/algo/exploration.js +55 -0
- package/dist/algo/geneHealth.d.ts +24 -0
- package/dist/algo/geneHealth.js +16 -0
- package/dist/algo/geneIntake.d.ts +37 -0
- package/dist/algo/geneIntake.js +100 -0
- package/dist/algo/genePromotion.d.ts +48 -0
- package/dist/algo/genePromotion.js +53 -0
- package/dist/algo/geneSelection.d.ts +128 -0
- package/dist/algo/geneSelection.js +222 -0
- package/dist/algo/index.d.ts +18 -0
- package/dist/algo/index.js +18 -0
- package/dist/algo/mutation.d.ts +12 -0
- package/dist/algo/mutation.js +22 -0
- package/dist/algo/orchestrator.d.ts +65 -0
- package/dist/algo/orchestrator.js +63 -0
- package/dist/algo/solidify.d.ts +43 -0
- package/dist/algo/solidify.js +63 -0
- package/dist/algo/strategyPresets.d.ts +32 -0
- package/dist/algo/strategyPresets.js +61 -0
- package/dist/assetstore/index.d.ts +8 -0
- package/dist/assetstore/index.js +8 -0
- package/dist/assetstore/learningHistory.d.ts +25 -0
- package/dist/assetstore/learningHistory.js +38 -0
- package/dist/assetstore/localJsonl.d.ts +34 -0
- package/dist/assetstore/localJsonl.js +182 -0
- package/dist/assetstore/pendingSignals.d.ts +22 -0
- package/dist/assetstore/pendingSignals.js +171 -0
- package/dist/assetstore/provenance.d.ts +39 -0
- package/dist/assetstore/provenance.js +109 -0
- package/dist/assetstore/provider.d.ts +48 -0
- package/dist/assetstore/provider.js +36 -0
- package/dist/assetstore/remoteStub.d.ts +32 -0
- package/dist/assetstore/remoteStub.js +36 -0
- package/dist/assetstore/reviewFilter.d.ts +20 -0
- package/dist/assetstore/reviewFilter.js +44 -0
- package/dist/assetstore/reviewLedger.d.ts +55 -0
- package/dist/assetstore/reviewLedger.js +121 -0
- package/dist/benchmark/antiGeneBenchmark.d.ts +79 -0
- package/dist/benchmark/antiGeneBenchmark.js +241 -0
- package/dist/benchmark/antiGeneRollout.d.ts +80 -0
- package/dist/benchmark/antiGeneRollout.js +256 -0
- package/dist/benchmark/benchmark.d.ts +32 -0
- package/dist/benchmark/benchmark.js +26 -0
- package/dist/benchmark/evolutionThesisSolver.d.ts +25 -0
- package/dist/benchmark/evolutionThesisSolver.js +41 -0
- package/dist/benchmark/index.d.ts +5 -0
- package/dist/benchmark/index.js +5 -0
- package/dist/benchmark/thesis.d.ts +85 -0
- package/dist/benchmark/thesis.js +150 -0
- package/dist/bootstrap/envFingerprint.d.ts +45 -0
- package/dist/bootstrap/envFingerprint.js +72 -0
- package/dist/bootstrap/index.d.ts +2 -0
- package/dist/bootstrap/index.js +2 -0
- package/dist/bootstrap/selfEvolve.d.ts +36 -0
- package/dist/bootstrap/selfEvolve.js +26 -0
- package/dist/cycle/cycleTimeline.d.ts +35 -0
- package/dist/cycle/cycleTimeline.js +74 -0
- package/dist/cycle/index.d.ts +2 -0
- package/dist/cycle/index.js +2 -0
- package/dist/cycle/stateMachine.d.ts +6 -0
- package/dist/cycle/stateMachine.js +25 -0
- package/dist/daemon/cycleContext.d.ts +12 -0
- package/dist/daemon/cycleContext.js +13 -0
- package/dist/daemon/drain.d.ts +11 -0
- package/dist/daemon/drain.js +16 -0
- package/dist/daemon/guards.d.ts +87 -0
- package/dist/daemon/guards.js +142 -0
- package/dist/daemon/idempotency.d.ts +11 -0
- package/dist/daemon/idempotency.js +36 -0
- package/dist/daemon/idleScheduler.d.ts +55 -0
- package/dist/daemon/idleScheduler.js +181 -0
- package/dist/daemon/index.d.ts +8 -0
- package/dist/daemon/index.js +8 -0
- package/dist/daemon/stepRunner.d.ts +12 -0
- package/dist/daemon/stepRunner.js +31 -0
- package/dist/daemon/unhandledRejectionWindow.d.ts +21 -0
- package/dist/daemon/unhandledRejectionWindow.js +52 -0
- package/dist/daemon/watchdog.d.ts +11 -0
- package/dist/daemon/watchdog.js +14 -0
- package/dist/events/eventSchema.d.ts +132 -0
- package/dist/events/eventSchema.js +30 -0
- package/dist/events/eventStore.d.ts +32 -0
- package/dist/events/eventStore.js +137 -0
- package/dist/events/ingest.d.ts +34 -0
- package/dist/events/ingest.js +61 -0
- package/dist/events/paths.d.ts +22 -0
- package/dist/events/paths.js +44 -0
- package/dist/events/projectors.d.ts +9 -0
- package/dist/events/projectors.js +11 -0
- package/dist/events/public.d.ts +14 -0
- package/dist/events/public.js +8 -0
- package/dist/events/replayer.d.ts +26 -0
- package/dist/events/replayer.js +67 -0
- package/dist/events/reports.d.ts +90 -0
- package/dist/events/reports.js +244 -0
- package/dist/events/retention.d.ts +70 -0
- package/dist/events/retention.js +177 -0
- package/dist/events/sink.d.ts +5 -0
- package/dist/events/sink.js +1 -0
- package/dist/exec/autoExec.d.ts +137 -0
- package/dist/exec/autoExec.js +221 -0
- package/dist/exec/autonomousCycle.d.ts +48 -0
- package/dist/exec/autonomousCycle.js +78 -0
- package/dist/exec/claudeBridge.d.ts +112 -0
- package/dist/exec/claudeBridge.js +219 -0
- package/dist/exec/index.d.ts +9 -0
- package/dist/exec/index.js +11 -0
- package/dist/exec/openPrRegistry.d.ts +60 -0
- package/dist/exec/openPrRegistry.js +130 -0
- package/dist/exec/policy/blastRadius.d.ts +31 -0
- package/dist/exec/policy/blastRadius.js +67 -0
- package/dist/exec/policy/constraints.d.ts +26 -0
- package/dist/exec/policy/constraints.js +62 -0
- package/dist/exec/policy/destructive.d.ts +45 -0
- package/dist/exec/policy/destructive.js +108 -0
- package/dist/exec/policy/failureMode.d.ts +33 -0
- package/dist/exec/policy/failureMode.js +49 -0
- package/dist/exec/policy/index.d.ts +24 -0
- package/dist/exec/policy/index.js +30 -0
- package/dist/exec/policy/protectedPaths.d.ts +17 -0
- package/dist/exec/policy/protectedPaths.js +65 -0
- package/dist/exec/policyCheck.d.ts +2 -0
- package/dist/exec/policyCheck.js +7 -0
- package/dist/exec/prompt.d.ts +34 -0
- package/dist/exec/prompt.js +108 -0
- package/dist/exec/proofOfWork.d.ts +9 -0
- package/dist/exec/proofOfWork.js +11 -0
- package/dist/exec/runnerRegistry.d.ts +123 -0
- package/dist/exec/runnerRegistry.js +237 -0
- package/dist/exec/selfPr.d.ts +83 -0
- package/dist/exec/selfPr.js +104 -0
- package/dist/exec/selfPrObfuscation.d.ts +21 -0
- package/dist/exec/selfPrObfuscation.js +85 -0
- package/dist/hooks/hooks.d.ts +117 -0
- package/dist/hooks/hooks.js +89 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hub/assetCallLog.d.ts +43 -0
- package/dist/hub/assetCallLog.js +72 -0
- package/dist/hub/bindings.d.ts +28 -0
- package/dist/hub/bindings.js +90 -0
- package/dist/hub/capability.d.ts +278 -0
- package/dist/hub/capability.js +1 -0
- package/dist/hub/conversationDistiller.d.ts +88 -0
- package/dist/hub/conversationDistiller.js +264 -0
- package/dist/hub/fake.d.ts +45 -0
- package/dist/hub/fake.js +69 -0
- package/dist/hub/hubReview.d.ts +91 -0
- package/dist/hub/hubReview.js +106 -0
- package/dist/hub/index.d.ts +10 -0
- package/dist/hub/index.js +10 -0
- package/dist/hub/ingest.d.ts +15 -0
- package/dist/hub/ingest.js +15 -0
- package/dist/hub/questionGenerator.d.ts +59 -0
- package/dist/hub/questionGenerator.js +406 -0
- package/dist/hub/reuseDecision.d.ts +87 -0
- package/dist/hub/reuseDecision.js +127 -0
- package/dist/hub/sanitize.d.ts +52 -0
- package/dist/hub/sanitize.js +321 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +27 -0
- package/dist/mailbox/catalog.d.ts +17 -0
- package/dist/mailbox/catalog.js +53 -0
- package/dist/mailbox/daemon.d.ts +48 -0
- package/dist/mailbox/daemon.js +61 -0
- package/dist/mailbox/dispatch.d.ts +46 -0
- package/dist/mailbox/dispatch.js +62 -0
- package/dist/mailbox/envelope.d.ts +43 -0
- package/dist/mailbox/envelope.js +52 -0
- package/dist/mailbox/index.d.ts +8 -0
- package/dist/mailbox/index.js +8 -0
- package/dist/mailbox/ipcServer.d.ts +46 -0
- package/dist/mailbox/ipcServer.js +168 -0
- package/dist/mailbox/requestReply.d.ts +40 -0
- package/dist/mailbox/requestReply.js +77 -0
- package/dist/mailbox/store.d.ts +74 -0
- package/dist/mailbox/store.js +308 -0
- package/dist/mailbox/wake.d.ts +45 -0
- package/dist/mailbox/wake.js +60 -0
- package/dist/material/boundary.d.ts +7 -0
- package/dist/material/boundary.js +14 -0
- package/dist/material/consumer.d.ts +21 -0
- package/dist/material/consumer.js +52 -0
- package/dist/material/emit.d.ts +55 -0
- package/dist/material/emit.js +52 -0
- package/dist/material/factory.d.ts +27 -0
- package/dist/material/factory.js +25 -0
- package/dist/material/index.d.ts +8 -0
- package/dist/material/index.js +8 -0
- package/dist/material/materialStore.d.ts +24 -0
- package/dist/material/materialStore.js +76 -0
- package/dist/material/sampling.d.ts +21 -0
- package/dist/material/sampling.js +39 -0
- package/dist/material/sources.d.ts +25 -0
- package/dist/material/sources.js +33 -0
- package/dist/material/watermark.d.ts +21 -0
- package/dist/material/watermark.js +76 -0
- package/dist/observers/cursorRewriteObserver.d.ts +46 -0
- package/dist/observers/cursorRewriteObserver.js +103 -0
- package/dist/observers/distillObserver.d.ts +31 -0
- package/dist/observers/distillObserver.js +93 -0
- package/dist/observers/index.d.ts +5 -0
- package/dist/observers/index.js +5 -0
- package/dist/observers/observerBus.d.ts +44 -0
- package/dist/observers/observerBus.js +73 -0
- package/dist/observers/reflectionObserver.d.ts +31 -0
- package/dist/observers/reflectionObserver.js +124 -0
- package/dist/observers/valueDigestObserver.d.ts +50 -0
- package/dist/observers/valueDigestObserver.js +70 -0
- package/dist/ops/cleanup.d.ts +23 -0
- package/dist/ops/cleanup.js +68 -0
- package/dist/ops/health.d.ts +37 -0
- package/dist/ops/health.js +96 -0
- package/dist/ops/index.d.ts +7 -0
- package/dist/ops/index.js +7 -0
- package/dist/ops/recall.d.ts +65 -0
- package/dist/ops/recall.js +152 -0
- package/dist/ops/reuseOutcomes.d.ts +68 -0
- package/dist/ops/reuseOutcomes.js +126 -0
- package/dist/ops/savingsCore.d.ts +47 -0
- package/dist/ops/savingsCore.js +112 -0
- package/dist/ops/selfUpdate.d.ts +106 -0
- package/dist/ops/selfUpdate.js +294 -0
- package/dist/ops/valueLedger.d.ts +205 -0
- package/dist/ops/valueLedger.js +238 -0
- package/dist/ops/valueOutreach.d.ts +70 -0
- package/dist/ops/valueOutreach.js +244 -0
- package/dist/personality/drift.d.ts +45 -0
- package/dist/personality/drift.js +106 -0
- package/dist/personality/events.d.ts +25 -0
- package/dist/personality/events.js +37 -0
- package/dist/personality/evolveOps.d.ts +20 -0
- package/dist/personality/evolveOps.js +93 -0
- package/dist/personality/index.d.ts +11 -0
- package/dist/personality/index.js +11 -0
- package/dist/personality/mutate.d.ts +21 -0
- package/dist/personality/mutate.js +39 -0
- package/dist/personality/pivot.d.ts +23 -0
- package/dist/personality/pivot.js +22 -0
- package/dist/personality/prompt.d.ts +6 -0
- package/dist/personality/prompt.js +62 -0
- package/dist/personality/riskGate.d.ts +42 -0
- package/dist/personality/riskGate.js +80 -0
- package/dist/personality/schema.d.ts +255 -0
- package/dist/personality/schema.js +119 -0
- package/dist/personality/select.d.ts +46 -0
- package/dist/personality/select.js +71 -0
- package/dist/personality/stats.d.ts +46 -0
- package/dist/personality/stats.js +82 -0
- package/dist/personality/store.d.ts +35 -0
- package/dist/personality/store.js +92 -0
- package/dist/schema/common.d.ts +28 -0
- package/dist/schema/common.js +17 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/material.d.ts +201 -0
- package/dist/schema/material.js +50 -0
- package/dist/schema/problem.d.ts +160 -0
- package/dist/schema/problem.js +45 -0
- package/dist/schema/proofOfWork.d.ts +97 -0
- package/dist/schema/proofOfWork.js +9 -0
- package/dist/schema/signal.d.ts +41 -0
- package/dist/schema/signal.js +19 -0
- package/dist/shadow/index.d.ts +6 -0
- package/dist/shadow/index.js +6 -0
- package/dist/shadow/jsonlSink.d.ts +17 -0
- package/dist/shadow/jsonlSink.js +27 -0
- package/dist/shadow/redact.d.ts +11 -0
- package/dist/shadow/redact.js +18 -0
- package/dist/shadow/shadowHub.d.ts +12 -0
- package/dist/shadow/shadowHub.js +42 -0
- package/dist/shadow/shadowMailbox.d.ts +17 -0
- package/dist/shadow/shadowMailbox.js +25 -0
- package/dist/shadow/shadowStore.d.ts +18 -0
- package/dist/shadow/shadowStore.js +55 -0
- package/dist/shadow/sink.d.ts +37 -0
- package/dist/shadow/sink.js +18 -0
- package/dist/signals/cycleHistoryFromEvents.d.ts +11 -0
- package/dist/signals/cycleHistoryFromEvents.js +96 -0
- package/dist/signals/expand.d.ts +34 -0
- package/dist/signals/expand.js +125 -0
- package/dist/signals/extractor.d.ts +25 -0
- package/dist/signals/extractor.js +57 -0
- package/dist/signals/index.d.ts +6 -0
- package/dist/signals/index.js +6 -0
- package/dist/signals/metaSignals.d.ts +57 -0
- package/dist/signals/metaSignals.js +158 -0
- package/dist/signals/signalGate.d.ts +15 -0
- package/dist/signals/signalGate.js +40 -0
- package/dist/signals/traceSignals.d.ts +44 -0
- package/dist/signals/traceSignals.js +123 -0
- package/dist/signatures/classifier.d.ts +16 -0
- package/dist/signatures/classifier.js +29 -0
- package/dist/signatures/index.d.ts +2 -0
- package/dist/signatures/index.js +2 -0
- package/dist/signatures/signatures.d.ts +22 -0
- package/dist/signatures/signatures.js +42 -0
- package/dist/strategy/experiment.d.ts +48 -0
- package/dist/strategy/experiment.js +63 -0
- package/dist/strategy/index.d.ts +2 -0
- package/dist/strategy/index.js +2 -0
- package/dist/strategy/strategyPoint.d.ts +30 -0
- package/dist/strategy/strategyPoint.js +23 -0
- package/dist/trace/index.d.ts +2 -0
- package/dist/trace/index.js +2 -0
- package/dist/trace/trajectory.d.ts +82 -0
- package/dist/trace/trajectory.js +117 -0
- package/dist/trace/trajectoryExport.d.ts +237 -0
- package/dist/trace/trajectoryExport.js +1818 -0
- package/dist/trigger/budget.d.ts +16 -0
- package/dist/trigger/budget.js +20 -0
- package/dist/trigger/engine.d.ts +12 -0
- package/dist/trigger/engine.js +23 -0
- package/dist/trigger/index.d.ts +6 -0
- package/dist/trigger/index.js +6 -0
- package/dist/trigger/problemBuilder.d.ts +24 -0
- package/dist/trigger/problemBuilder.js +32 -0
- package/dist/trigger/trigger.d.ts +22 -0
- package/dist/trigger/trigger.js +27 -0
- package/dist/trigger/valueModel.d.ts +26 -0
- package/dist/trigger/valueModel.js +25 -0
- package/dist/trigger/wfq.d.ts +13 -0
- package/dist/trigger/wfq.js +25 -0
- package/dist/util/fileLock.d.ts +24 -0
- package/dist/util/fileLock.js +227 -0
- package/dist/util/index.d.ts +2 -0
- package/dist/util/index.js +2 -0
- package/dist/util/version.d.ts +12 -0
- package/dist/util/version.js +51 -0
- package/dist/verify/index.d.ts +4 -0
- package/dist/verify/index.js +4 -0
- package/dist/verify/rollback.d.ts +22 -0
- package/dist/verify/rollback.js +33 -0
- package/dist/verify/sandboxRunner.d.ts +39 -0
- package/dist/verify/sandboxRunner.js +116 -0
- package/dist/verify/sandboxedValidation.d.ts +35 -0
- package/dist/verify/sandboxedValidation.js +56 -0
- package/dist/verify/validation.d.ts +41 -0
- package/dist/verify/validation.js +85 -0
- package/dist/wire/canonicalize.golden.d.ts +23 -0
- package/dist/wire/canonicalize.golden.js +46 -0
- package/dist/wire/geneHints.d.ts +64 -0
- package/dist/wire/geneHints.js +100 -0
- package/dist/wire/index.d.ts +91 -0
- package/dist/wire/index.js +3 -0
- package/dist/wire/schemaGate.d.ts +11 -0
- package/dist/wire/schemaGate.js +49 -0
- package/dist/workflow/dsl.d.ts +54 -0
- package/dist/workflow/dsl.js +15 -0
- package/dist/workflow/engine.d.ts +30 -0
- package/dist/workflow/engine.js +94 -0
- package/dist/workflow/index.d.ts +2 -0
- package/dist/workflow/index.js +2 -0
- package/package.json +29 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import type { AssetRecord, AssetKind, SearchQuery, PutResult } from '../assetstore/provider.js';
|
|
2
|
+
import type { Envelope } from '../mailbox/envelope.js';
|
|
3
|
+
/** publish 投递回执. hub 侧做 gate(经济/治理/RBAC 全在 hub), core 只读 status+reason. */
|
|
4
|
+
export interface PublishReceipt {
|
|
5
|
+
/** hub 返回的回执 id(公版=AgentEvent/decision id; 私有=审计 id). */
|
|
6
|
+
receiptId: string;
|
|
7
|
+
/** hub gate 决议. quarantine 仅公版可能出现, core 当 rejected 的软态处理. */
|
|
8
|
+
status: 'accepted' | 'rejected' | 'quarantine';
|
|
9
|
+
/** rejected/quarantine 时的人读原因(core 不解释经济/治理语义, 原样回灌 Material). */
|
|
10
|
+
reason?: string;
|
|
11
|
+
/** hub 计算后的 asset_id(必须与 core normalizeForPut 逐字节一致, 命门, conformance 校验). */
|
|
12
|
+
assetId?: string;
|
|
13
|
+
/** bundle 发布: hub 返回的 bundle_id + 全资产 asset_id(实测公版 /a2a/publish 收 [Gene,Capsule,Event] 捆绑). */
|
|
14
|
+
bundleId?: string;
|
|
15
|
+
assetIds?: string[];
|
|
16
|
+
/** 终态标记: true=不可重试(reject/quarantine/402), SyncEngine 不得 incrementRetry(money-safety risk). */
|
|
17
|
+
terminal?: boolean;
|
|
18
|
+
/** M8-1: 公版经济侧只读回执(core 不解释经济语义, 仅透传供观测/UI). private hub 多为空. */
|
|
19
|
+
economic?: {
|
|
20
|
+
creditShortage?: boolean;
|
|
21
|
+
required?: number;
|
|
22
|
+
available?: number;
|
|
23
|
+
balanceKind?: 'user_balance' | 'node_balance';
|
|
24
|
+
gdiScore?: number;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** 资产查询. 复用 assetstore SearchQuery, 不发明第二套查询 DSL. */
|
|
28
|
+
export type HubQuery = SearchQuery;
|
|
29
|
+
/** task 子系统事件(订阅流元素). 公版含经济上下文(bounty/credit), 私有仅 workflow. */
|
|
30
|
+
export interface TaskEvent {
|
|
31
|
+
taskId: string;
|
|
32
|
+
type: string;
|
|
33
|
+
payload: unknown;
|
|
34
|
+
priority: 'high' | 'medium' | 'low';
|
|
35
|
+
createdAt: number;
|
|
36
|
+
}
|
|
37
|
+
/** Proactive Hub question that a runtime may submit for ecosystem help. */
|
|
38
|
+
export interface HubQuestion {
|
|
39
|
+
question: string;
|
|
40
|
+
amount?: number;
|
|
41
|
+
signals?: readonly string[];
|
|
42
|
+
}
|
|
43
|
+
/** Flexible receipt for hubs that turn submitted questions into tasks/bounties. */
|
|
44
|
+
export interface QuestionSubmitReceipt {
|
|
45
|
+
question?: string;
|
|
46
|
+
taskId?: string;
|
|
47
|
+
bountyId?: string;
|
|
48
|
+
error?: string;
|
|
49
|
+
raw?: unknown;
|
|
50
|
+
}
|
|
51
|
+
/** mailbox 通用事件. inbound 用 hub 原始 wire shape, 由 adapter 翻成 core Envelope 落 MailboxStore. */
|
|
52
|
+
export interface AgentEvent {
|
|
53
|
+
id: string;
|
|
54
|
+
type: string;
|
|
55
|
+
payload: unknown;
|
|
56
|
+
priority: 'high' | 'medium' | 'low';
|
|
57
|
+
cursor?: string;
|
|
58
|
+
createdAt: number;
|
|
59
|
+
refId?: string;
|
|
60
|
+
expiresAt?: number;
|
|
61
|
+
}
|
|
62
|
+
export interface MailboxPushOutcome {
|
|
63
|
+
id: string;
|
|
64
|
+
status: 'accepted' | 'failed';
|
|
65
|
+
reason?: string;
|
|
66
|
+
retryable?: boolean;
|
|
67
|
+
terminal?: boolean;
|
|
68
|
+
retryAfterMs?: number;
|
|
69
|
+
raw?: unknown;
|
|
70
|
+
}
|
|
71
|
+
export interface MailboxPushManyResult {
|
|
72
|
+
outcomes: MailboxPushOutcome[];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* mailbox.poll 结果. **焊入短轮询背压**(对应 hub issue #1195 的 next_poll_after_ms 提案):
|
|
76
|
+
* hub 给出建议的下次轮询间隔, SyncEngine 优先遵守(有事件→0/有 backlog→小, 空→大, 降载→更大),
|
|
77
|
+
* 缺省时回退 SyncEngine 默认节奏. 这让 adapter 对 hub 长轮询→短轮询迁移**零改动前向兼容**.
|
|
78
|
+
*/
|
|
79
|
+
export interface MailboxPollResult {
|
|
80
|
+
events: AgentEvent[];
|
|
81
|
+
/** hub 建议下次 poll 间隔 ms(#1195). 缺省=adapter 用默认节奏. */
|
|
82
|
+
nextPollAfterMs?: number;
|
|
83
|
+
/** 还有更多 backlog 未拉完 → adapter 应 drain 而非 idle(防限流饿死). */
|
|
84
|
+
hasMore?: boolean;
|
|
85
|
+
}
|
|
86
|
+
export type ReuseResultOutcome = 'success' | 'failed' | 'mismatched' | 'stale' | 'unsafe';
|
|
87
|
+
/** Reuse outcome report. Hub owns attribution, RBAC, and audit policy; runtime only forwards the claim. */
|
|
88
|
+
export interface ReuseResultReport {
|
|
89
|
+
assetId: string;
|
|
90
|
+
outcome: ReuseResultOutcome;
|
|
91
|
+
taskId?: string;
|
|
92
|
+
traceId?: string;
|
|
93
|
+
/** Deprecated compatibility field. A scalar without measurement metadata is self-reported and must not count as ROI. */
|
|
94
|
+
tokensSaved?: number;
|
|
95
|
+
timeSavedSeconds?: number;
|
|
96
|
+
reason?: string;
|
|
97
|
+
}
|
|
98
|
+
/** Reuse-result reporting is best-effort; failures must not break fetch or solve paths. */
|
|
99
|
+
export interface ReuseResultReceipt {
|
|
100
|
+
recorded: boolean;
|
|
101
|
+
reason?: string;
|
|
102
|
+
id?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Pre-publish dry-run result. The hub runs the same hub-side quality + content-safety
|
|
106
|
+
* gate as publish but stores nothing and charges no credits, so an agent can check a
|
|
107
|
+
* bundle before paying to publish. Proxy callers sanitize and leak-check before invoking
|
|
108
|
+
* hub validate, mirroring the publish path. A dry-run is never a dependency of a cycle,
|
|
109
|
+
* so the adapter degrades every failure (quality/safety reject, 5xx, network) to
|
|
110
|
+
* valid:false.
|
|
111
|
+
*/
|
|
112
|
+
export interface ValidateReceipt {
|
|
113
|
+
valid: boolean;
|
|
114
|
+
/** Human-readable rejection cause when valid:false (hub quality/safety reason, or transport error). */
|
|
115
|
+
reason?: string;
|
|
116
|
+
/** hub 原始 payload 透传(target_asset_id / content_safety_warning / privacy_guidance 等); core 不解释. */
|
|
117
|
+
raw?: unknown;
|
|
118
|
+
}
|
|
119
|
+
export type RecipeAssetType = 'Gene' | 'Capsule';
|
|
120
|
+
/** A recipe step references an owned Gene/Capsule asset by content id. */
|
|
121
|
+
export interface RecipeStep {
|
|
122
|
+
assetId: string;
|
|
123
|
+
assetType: RecipeAssetType;
|
|
124
|
+
position?: number;
|
|
125
|
+
}
|
|
126
|
+
/** Create a draft recipe; publishing is a separate explicit action. */
|
|
127
|
+
export interface RecipeCreateRequest {
|
|
128
|
+
title: string;
|
|
129
|
+
steps: readonly RecipeStep[];
|
|
130
|
+
description?: string;
|
|
131
|
+
pricePerExecution?: number;
|
|
132
|
+
currency?: string;
|
|
133
|
+
maxConcurrent?: number;
|
|
134
|
+
}
|
|
135
|
+
export interface RecipeReceipt {
|
|
136
|
+
recipeId?: string;
|
|
137
|
+
status?: string;
|
|
138
|
+
raw: unknown;
|
|
139
|
+
}
|
|
140
|
+
export interface RecipeFetchReceipt extends RecipeReceipt {
|
|
141
|
+
recipe?: unknown;
|
|
142
|
+
}
|
|
143
|
+
export interface RecipeExpressRequest {
|
|
144
|
+
inputPayload?: Record<string, unknown>;
|
|
145
|
+
}
|
|
146
|
+
export interface RecipeExpressionReceipt extends RecipeReceipt {
|
|
147
|
+
organismId?: string;
|
|
148
|
+
}
|
|
149
|
+
/** Optional Hub recipe/DNA capability. Core stays wire-agnostic; adapters own REST shape. */
|
|
150
|
+
export interface RecipeCapability {
|
|
151
|
+
create(request: RecipeCreateRequest): Promise<RecipeReceipt>;
|
|
152
|
+
publish(recipeId: string): Promise<RecipeReceipt>;
|
|
153
|
+
get(recipeId: string): Promise<RecipeFetchReceipt>;
|
|
154
|
+
express(recipeId: string, request?: RecipeExpressRequest): Promise<RecipeExpressionReceipt>;
|
|
155
|
+
}
|
|
156
|
+
export type HubCapabilityName = 'publish' | 'fetch' | 'search' | 'task' | 'mailbox' | 'auth' | 'audit' | 'air_gap' | 'tenant_isolation' | 'marketplace' | 'economy' | 'questions' | 'recipes';
|
|
157
|
+
/** hub 能力清单(可选). core 据此动态适配 UI/行为, "按需耦合". */
|
|
158
|
+
export interface HubManifest {
|
|
159
|
+
capabilities: HubCapabilityName[] | string[];
|
|
160
|
+
protocolVersion: string;
|
|
161
|
+
economyEnabled?: boolean;
|
|
162
|
+
authKinds?: CredentialKind[];
|
|
163
|
+
/** enterprise/public 差异表达为能力与策略, core 不分支判断 edition/repo. */
|
|
164
|
+
auditEnabled?: boolean;
|
|
165
|
+
airGap?: boolean;
|
|
166
|
+
tenantIsolation?: boolean;
|
|
167
|
+
marketplaceAccess?: boolean;
|
|
168
|
+
}
|
|
169
|
+
export type CredentialKind = 'oauth_device_token' | 'keypair' | 'enterprise_sso';
|
|
170
|
+
export type Credential = {
|
|
171
|
+
id: string;
|
|
172
|
+
kind: CredentialKind;
|
|
173
|
+
device?: string;
|
|
174
|
+
publicKey?: string;
|
|
175
|
+
expiresAt?: number;
|
|
176
|
+
refreshToken?: string;
|
|
177
|
+
} & ({
|
|
178
|
+
token: string;
|
|
179
|
+
} | {
|
|
180
|
+
privateKey: string;
|
|
181
|
+
});
|
|
182
|
+
/** 给一个待发请求加凭证/签名后的结果(adapter 注入 HTTP 层). */
|
|
183
|
+
export interface SignedRequest {
|
|
184
|
+
headers: Record<string, string>;
|
|
185
|
+
bodySignature?: string;
|
|
186
|
+
/** 注入请求体的凭证字段(gep-a2a: node_secret 走 body 而非 header — 实测 dev 契约). */
|
|
187
|
+
bodyFields?: Record<string, unknown>;
|
|
188
|
+
}
|
|
189
|
+
/** 待签请求的最小描述. */
|
|
190
|
+
export interface HttpRequestLike {
|
|
191
|
+
method: string;
|
|
192
|
+
path: string;
|
|
193
|
+
body?: string;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Pluggable auth. Example implementations: public OAuth device token / Ed25519 keypair / enterprise SSO (OIDC/LDAP).
|
|
197
|
+
* node_secret dual-track transition is wrapped by LegacyAuthShim. (The enterprise SSO impl lives in the enterprise repo; the public repo only defines the interface.)
|
|
198
|
+
*/
|
|
199
|
+
export interface AuthProvider {
|
|
200
|
+
kind: CredentialKind;
|
|
201
|
+
/** 首次认证: 浏览器 OAuth / device code flow / 无头 keypair. 持久化到 ~/.evomap. */
|
|
202
|
+
login(): Promise<Credential>;
|
|
203
|
+
/** 给请求加凭证/签名(每个出站 HTTP 调一次). 审计级动作必须 keypair 签 body. */
|
|
204
|
+
authenticate(req: HttpRequestLike): Promise<SignedRequest>;
|
|
205
|
+
/** 轮换. token 自动(提前 6h); keypair 用旧私钥签 revoke 后换新. */
|
|
206
|
+
rotate(): Promise<Credential>;
|
|
207
|
+
/** 撤销凭证(机器丢失/泄露). */
|
|
208
|
+
revoke(credentialId: string): Promise<void>;
|
|
209
|
+
}
|
|
210
|
+
export interface HubCapability {
|
|
211
|
+
/**
|
|
212
|
+
* 异步发布. 公版 /a2a/publish 收 **bundle**[Gene,Capsule,(EvolutionEvent)](一个 cycle 的产物一起发, +GDI);
|
|
213
|
+
* 传单资产=[asset]。core 已 normalizeForPut(算/校验 asset_id), hub 做经济/治理/质量 gate。
|
|
214
|
+
*/
|
|
215
|
+
publish(bundle: AssetRecord[]): Promise<PublishReceipt>;
|
|
216
|
+
/** 拉取资产. hub 侧排序/scope(公版 GDI, 私有 RBAC); core 不重排. */
|
|
217
|
+
fetch(query: HubQuery): Promise<AssetRecord[]>;
|
|
218
|
+
/** 搜索资产. 与 fetch 同 shape, 差异在 hub 侧召回策略. */
|
|
219
|
+
search(query: HubQuery): Promise<AssetRecord[]>;
|
|
220
|
+
/** 可选: 按 content-addressed asset_id 拉单个 full asset. private adapter/proxy 用它保证只 fetch 一个 winner. */
|
|
221
|
+
fetchAssetById?(assetId: string): Promise<AssetRecord | null>;
|
|
222
|
+
/** 可选: 报告某个资产被复用后的结果. PHub/enterprise adapter 实现; 不支持时 runtime 应明确降级. */
|
|
223
|
+
recordReuseResult?(report: ReuseResultReport): Promise<ReuseResultReceipt>;
|
|
224
|
+
/**
|
|
225
|
+
* 可选: 发布前 dry-run 校验(公版 POST /a2a/validate). 跑与 publish 相同的 hub 端质量门禁 + 内容安全扫描,
|
|
226
|
+
* 但不落库、不计费; 经由 Proxy 暴露时调用方需先执行与 publish 相同的客户端脱敏/泄漏拦截.
|
|
227
|
+
* 让 agent 在花 credits 发布前先确认. 不支持的 hub 不实现此方法; proxy/runtime 据此降级.
|
|
228
|
+
*/
|
|
229
|
+
validate?(bundle: AssetRecord[]): Promise<ValidateReceipt>;
|
|
230
|
+
/** task 子系统. 公版含经济(在 hub), 私有仅内部 workflow; core 两边同接口. */
|
|
231
|
+
task: {
|
|
232
|
+
claim(taskId: string): Promise<{
|
|
233
|
+
claimId: string;
|
|
234
|
+
}>;
|
|
235
|
+
complete(claimId: string, result: unknown): Promise<{
|
|
236
|
+
status: 'completed';
|
|
237
|
+
}>;
|
|
238
|
+
subscribe(filter: unknown): AsyncIterable<TaskEvent>;
|
|
239
|
+
};
|
|
240
|
+
/** Optional proactive question seam. Public Hub currently accepts these on /a2a/fetch payload.questions. */
|
|
241
|
+
questions?: {
|
|
242
|
+
submit(questions: readonly HubQuestion[]): Promise<QuestionSubmitReceipt[]>;
|
|
243
|
+
};
|
|
244
|
+
/** Optional recipe/DNA seam. Recipe creation is draft-first; publishing remains explicit. */
|
|
245
|
+
recipes?: RecipeCapability;
|
|
246
|
+
/** mailbox 队列. poll/ack/push/status 四端点解耦(公版 /a2a/mailbox/*). */
|
|
247
|
+
mailbox: {
|
|
248
|
+
poll(): Promise<MailboxPollResult>;
|
|
249
|
+
ack(eventId: string): Promise<void>;
|
|
250
|
+
push(event: AgentEvent): Promise<void>;
|
|
251
|
+
pushMany?(events: readonly AgentEvent[]): Promise<void | MailboxPushManyResult>;
|
|
252
|
+
status(): Promise<{
|
|
253
|
+
pending: number;
|
|
254
|
+
}>;
|
|
255
|
+
};
|
|
256
|
+
/** 可插拔认证. proxy 持唯一凭证代调; core 只经此签请求, 不碰密钥存储. */
|
|
257
|
+
auth: AuthProvider;
|
|
258
|
+
/** 可选: hub 广告支持的能力, core 动态适配. 缺省时 core 假设全能力在线. */
|
|
259
|
+
capabilities?(): Promise<HubManifest>;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* HubCapability 接到 core 两个 seam 的工厂(adapter 不直接 new Dispatcher):
|
|
263
|
+
* - asProxyHandler: 包成 Dispatcher.handlers.proxy(e: Envelope)=>Promise<unknown>, 按 e.type
|
|
264
|
+
* 路由到 publish / task 子系统 / mailbox.push; 抛错触发 store.fail() 重试.
|
|
265
|
+
* - asAssetTransport: 包成 assetstore RemoteTransport(put/get/search/list), 落库前 core normalizeForPut.
|
|
266
|
+
*/
|
|
267
|
+
export interface HubBindings {
|
|
268
|
+
asProxyHandler(): (e: Envelope) => Promise<unknown>;
|
|
269
|
+
asAssetTransport(): {
|
|
270
|
+
putRemote(record: AssetRecord): Promise<{
|
|
271
|
+
stored: boolean;
|
|
272
|
+
}>;
|
|
273
|
+
getRemote(assetId: string): Promise<AssetRecord | null>;
|
|
274
|
+
searchRemote(query: HubQuery): Promise<AssetRecord[]>;
|
|
275
|
+
listRemote(kind: AssetKind | undefined, limit: number): Promise<AssetRecord[]>;
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
export type { AssetRecord, AssetKind, SearchQuery, PutResult, Envelope };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { AssetRecord, AssetStoreProvider } from '../assetstore/provider.js';
|
|
2
|
+
export interface ConversationDistillInput {
|
|
3
|
+
title?: unknown;
|
|
4
|
+
name?: unknown;
|
|
5
|
+
summary?: unknown;
|
|
6
|
+
user_prompt?: unknown;
|
|
7
|
+
userPrompt?: unknown;
|
|
8
|
+
assistant_summary?: unknown;
|
|
9
|
+
assistantSummary?: unknown;
|
|
10
|
+
transcript?: unknown;
|
|
11
|
+
conversation?: unknown;
|
|
12
|
+
signals?: unknown;
|
|
13
|
+
strategy?: unknown;
|
|
14
|
+
steps?: unknown;
|
|
15
|
+
artifacts?: unknown;
|
|
16
|
+
outputs?: unknown;
|
|
17
|
+
files?: unknown;
|
|
18
|
+
validation?: unknown;
|
|
19
|
+
verification?: unknown;
|
|
20
|
+
execution?: unknown;
|
|
21
|
+
blast_radius?: unknown;
|
|
22
|
+
platform?: unknown;
|
|
23
|
+
host?: unknown;
|
|
24
|
+
model?: unknown;
|
|
25
|
+
thread_id?: unknown;
|
|
26
|
+
threadId?: unknown;
|
|
27
|
+
session_id?: unknown;
|
|
28
|
+
sessionId?: unknown;
|
|
29
|
+
min_score?: unknown;
|
|
30
|
+
minScore?: unknown;
|
|
31
|
+
persist?: unknown;
|
|
32
|
+
[k: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
interface NormalizedExecution {
|
|
35
|
+
status: 'success' | 'failed';
|
|
36
|
+
trace: Array<{
|
|
37
|
+
command: string;
|
|
38
|
+
exit: number;
|
|
39
|
+
summary?: string;
|
|
40
|
+
}>;
|
|
41
|
+
validation: string[];
|
|
42
|
+
blast_radius: {
|
|
43
|
+
files: number;
|
|
44
|
+
lines: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
interface NormalizedConversation {
|
|
48
|
+
text: string;
|
|
49
|
+
summary: string;
|
|
50
|
+
signals: string[];
|
|
51
|
+
strategy: string[];
|
|
52
|
+
artifacts: string[];
|
|
53
|
+
execution: NormalizedExecution;
|
|
54
|
+
platform: string;
|
|
55
|
+
model: string;
|
|
56
|
+
source_thread: string;
|
|
57
|
+
}
|
|
58
|
+
export interface QualityGate {
|
|
59
|
+
ok: boolean;
|
|
60
|
+
score: number;
|
|
61
|
+
threshold: number;
|
|
62
|
+
reasons: string[];
|
|
63
|
+
reason?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface ConversationDistillOptions {
|
|
66
|
+
persist?: boolean;
|
|
67
|
+
store?: AssetStoreProvider;
|
|
68
|
+
}
|
|
69
|
+
export type ConversationDistillResult = {
|
|
70
|
+
ok: false;
|
|
71
|
+
status: 'skipped';
|
|
72
|
+
reason: string;
|
|
73
|
+
quality?: QualityGate;
|
|
74
|
+
signals?: string[];
|
|
75
|
+
} | {
|
|
76
|
+
ok: true;
|
|
77
|
+
status: 'stored' | 'draft';
|
|
78
|
+
distill_id: string;
|
|
79
|
+
quality: QualityGate;
|
|
80
|
+
signals: string[];
|
|
81
|
+
gene: AssetRecord;
|
|
82
|
+
capsule: AssetRecord;
|
|
83
|
+
};
|
|
84
|
+
export declare function inferSignals(text: string, providedSignals?: unknown): string[];
|
|
85
|
+
export declare function evaluateGate(input: ConversationDistillInput, normalized: NormalizedConversation): QualityGate;
|
|
86
|
+
export declare function normalizeConversationInput(input: ConversationDistillInput): NormalizedConversation;
|
|
87
|
+
export declare function distillConversation(input: ConversationDistillInput, opts?: ConversationDistillOptions): Promise<ConversationDistillResult>;
|
|
88
|
+
export {};
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { redactString } from './sanitize.js';
|
|
3
|
+
import { SCHEMA_VERSION, computeAssetId } from '../wire/index.js';
|
|
4
|
+
const DEFAULT_SIGNALS = [
|
|
5
|
+
'conversation_distillation',
|
|
6
|
+
'reusable_capability',
|
|
7
|
+
'agent_self_evolution',
|
|
8
|
+
];
|
|
9
|
+
const SIGNAL_RULES = [
|
|
10
|
+
{ signal: 'conversation_distillation', re: /\b(distill|distillation|distilled|蒸馏|提炼|萃取)\b/i },
|
|
11
|
+
{ signal: 'gene_publish', re: /\b(gene|capsule|evomap|evolver|gep)\b|基因|胶囊/i },
|
|
12
|
+
{ signal: 'reusable_capability', re: /\b(reusable|repeatable|workflow|playbook|capability)\b|可复用|复用|能力|流程/i },
|
|
13
|
+
{ signal: 'visual_annotation', re: /\b(screenshot|annotat|mock|wireframe|playwright|visual)\b|截图|圈圈|标注|画图|飞书/i },
|
|
14
|
+
{ signal: 'frontend_polish', re: /\b(frontend|ui|ux|interaction|polish|mockup)\b|前端|交互|打磨|体验/i },
|
|
15
|
+
{ signal: 'proxy_sync', re: /\b(proxy|sync|mailbox|outbound|hub|asset_submit)\b|同步|队列|代理/i },
|
|
16
|
+
{ signal: 'plugin_integration', re: /\b(plugin|codex|claude|cursor|antigravity|workbuddy|hook|notify)\b|插件|钩子/i },
|
|
17
|
+
{ signal: 'test_verified', re: /\b(test|build|verify|passed|green)\b|测试|验证|通过/i },
|
|
18
|
+
];
|
|
19
|
+
function asRecord(v) {
|
|
20
|
+
return v && typeof v === 'object' && !Array.isArray(v) ? v : {};
|
|
21
|
+
}
|
|
22
|
+
function trimText(value, max) {
|
|
23
|
+
const text = redactString(String(value ?? '').replace(/\s+/g, ' ').trim());
|
|
24
|
+
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
25
|
+
}
|
|
26
|
+
function asArray(value) {
|
|
27
|
+
if (value === undefined || value === null || value === '')
|
|
28
|
+
return [];
|
|
29
|
+
return Array.isArray(value) ? value : [value];
|
|
30
|
+
}
|
|
31
|
+
function normalizeList(value, maxItems, maxLen) {
|
|
32
|
+
return asArray(value).map((item) => trimText(item, maxLen)).filter(Boolean).slice(0, maxItems);
|
|
33
|
+
}
|
|
34
|
+
function slugify(value) {
|
|
35
|
+
const raw = String(value || 'conversation-capability').toLowerCase();
|
|
36
|
+
const ascii = raw.replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').replace(/-{2,}/g, '-');
|
|
37
|
+
if (ascii.length >= 8)
|
|
38
|
+
return ascii.slice(0, 56).replace(/-+$/g, '');
|
|
39
|
+
const hash = createHash('sha1').update(raw, 'utf8').digest('hex').slice(0, 8);
|
|
40
|
+
return `conversation-capability-${hash}`;
|
|
41
|
+
}
|
|
42
|
+
function hashInput(input) {
|
|
43
|
+
return createHash('sha1').update(JSON.stringify(input ?? {}), 'utf8').digest('hex').slice(0, 10);
|
|
44
|
+
}
|
|
45
|
+
export function inferSignals(text, providedSignals) {
|
|
46
|
+
const found = new Set(normalizeList(providedSignals, 12, 64));
|
|
47
|
+
for (const rule of SIGNAL_RULES)
|
|
48
|
+
if (rule.re.test(text))
|
|
49
|
+
found.add(rule.signal);
|
|
50
|
+
if (found.size === 0)
|
|
51
|
+
for (const signal of DEFAULT_SIGNALS)
|
|
52
|
+
found.add(signal);
|
|
53
|
+
return [...found].slice(0, 12);
|
|
54
|
+
}
|
|
55
|
+
function inferCategory(signals, text) {
|
|
56
|
+
const hay = `${signals.join(' ')} ${text}`.toLowerCase();
|
|
57
|
+
if (/proxy|sync|auth|error|failure|bug|repair|修复|故障/.test(hay))
|
|
58
|
+
return 'repair';
|
|
59
|
+
if (/new|plugin|integration|feature|capability|能力|新增/.test(hay))
|
|
60
|
+
return 'innovate';
|
|
61
|
+
return 'optimize';
|
|
62
|
+
}
|
|
63
|
+
function normalizeBlastRadius(value) {
|
|
64
|
+
const r = asRecord(value);
|
|
65
|
+
return {
|
|
66
|
+
files: Number.isFinite(Number(r['files'])) ? Number(r['files']) : 0,
|
|
67
|
+
lines: Number.isFinite(Number(r['lines'])) ? Number(r['lines']) : 0,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function normalizePublishBlastRadius(value, artifactCount) {
|
|
71
|
+
return {
|
|
72
|
+
files: Math.max(1, Math.trunc(value.files || artifactCount || 1)),
|
|
73
|
+
lines: Math.max(1, Math.trunc(value.lines || 1)),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function capsuleContent(normalized) {
|
|
77
|
+
return redactString(JSON.stringify({
|
|
78
|
+
platform: normalized.platform,
|
|
79
|
+
source_thread: normalized.source_thread || null,
|
|
80
|
+
artifacts: normalized.artifacts,
|
|
81
|
+
excerpt: normalized.text.slice(0, 1200),
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
function normalizeExecution(input) {
|
|
85
|
+
const execution = asRecord(input.execution);
|
|
86
|
+
const validation = normalizeList(input.validation ?? input.verification ?? execution['validation'], 8, 180);
|
|
87
|
+
const trace = asArray(execution['trace']).map((item) => {
|
|
88
|
+
if (typeof item === 'string')
|
|
89
|
+
return { command: trimText(item, 180), exit: 0 };
|
|
90
|
+
const row = asRecord(item);
|
|
91
|
+
if (Object.keys(row).length === 0)
|
|
92
|
+
return null;
|
|
93
|
+
return {
|
|
94
|
+
command: trimText(row['command'] ?? row['cmd'] ?? row['name'] ?? 'validation', 180),
|
|
95
|
+
exit: Number.isInteger(row['exit']) ? Number(row['exit']) : (row['ok'] === false ? 1 : 0),
|
|
96
|
+
summary: trimText(row['summary'] ?? row['output'] ?? '', 240),
|
|
97
|
+
};
|
|
98
|
+
}).filter((row) => row !== null);
|
|
99
|
+
for (const cmd of validation)
|
|
100
|
+
if (!trace.some((t) => t.command === cmd))
|
|
101
|
+
trace.push({ command: cmd, exit: 0 });
|
|
102
|
+
const ok = execution['status'] === 'success' || execution['ok'] === true || validation.length > 0 || trace.some((t) => t.exit === 0);
|
|
103
|
+
return {
|
|
104
|
+
status: ok ? 'success' : 'failed',
|
|
105
|
+
trace,
|
|
106
|
+
validation,
|
|
107
|
+
blast_radius: normalizeBlastRadius(execution['blast_radius'] ?? input.blast_radius),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function buildStrategy(input) {
|
|
111
|
+
const explicit = normalizeList(input.strategy ?? input.steps, 10, 220);
|
|
112
|
+
if (explicit.length >= 3)
|
|
113
|
+
return explicit;
|
|
114
|
+
const artifacts = normalizeList(input.artifacts ?? input.outputs ?? input.files, 6, 160);
|
|
115
|
+
const strategy = explicit.slice();
|
|
116
|
+
strategy.push('Capture the user-visible trigger and the concrete workflow that solved it.');
|
|
117
|
+
strategy.push('Preserve evidence: commands, screenshots, documents, changed files, and validation results.');
|
|
118
|
+
if (artifacts.length > 0)
|
|
119
|
+
strategy.push('Link generated artifacts back to the reusable procedure before publishing.');
|
|
120
|
+
strategy.push('Sanitize secrets and local-only paths before persisting or submitting the asset.');
|
|
121
|
+
strategy.push('Queue the resulting Gene/Capsule through the local Proxy so Hub outages do not drop the learning.');
|
|
122
|
+
return strategy.slice(0, 10);
|
|
123
|
+
}
|
|
124
|
+
export function evaluateGate(input, normalized) {
|
|
125
|
+
let score = 0;
|
|
126
|
+
const reasons = [];
|
|
127
|
+
if (normalized.summary.length >= 40) {
|
|
128
|
+
score += 2;
|
|
129
|
+
reasons.push('summary');
|
|
130
|
+
}
|
|
131
|
+
if (normalized.strategy.length >= 3) {
|
|
132
|
+
score += 2;
|
|
133
|
+
reasons.push('strategy');
|
|
134
|
+
}
|
|
135
|
+
if (normalized.artifacts.length > 0) {
|
|
136
|
+
score += 1;
|
|
137
|
+
reasons.push('artifacts');
|
|
138
|
+
}
|
|
139
|
+
if (normalized.execution.validation.length > 0 || normalized.execution.trace.length > 0) {
|
|
140
|
+
score += 1;
|
|
141
|
+
reasons.push('validation');
|
|
142
|
+
}
|
|
143
|
+
if (/\b(gene|capsule|distill|reusable|evomap|evolver)\b|蒸馏|提炼|可复用|基因/i.test(normalized.text)) {
|
|
144
|
+
score += 2;
|
|
145
|
+
reasons.push('explicit_distill_signal');
|
|
146
|
+
}
|
|
147
|
+
const rawThreshold = Number(input.min_score ?? input.minScore ?? 5);
|
|
148
|
+
const threshold = Number.isFinite(rawThreshold) ? rawThreshold : 5;
|
|
149
|
+
if (score < threshold)
|
|
150
|
+
return { ok: false, score, threshold, reasons, reason: 'insufficient_reusable_signal' };
|
|
151
|
+
return { ok: true, score, threshold, reasons };
|
|
152
|
+
}
|
|
153
|
+
export function normalizeConversationInput(input) {
|
|
154
|
+
const sourceText = [
|
|
155
|
+
input.summary,
|
|
156
|
+
input.title,
|
|
157
|
+
input.user_prompt,
|
|
158
|
+
input.userPrompt,
|
|
159
|
+
input.assistant_summary,
|
|
160
|
+
input.assistantSummary,
|
|
161
|
+
input.transcript,
|
|
162
|
+
input.conversation,
|
|
163
|
+
].filter(Boolean).join('\n');
|
|
164
|
+
const text = trimText(sourceText, 8000);
|
|
165
|
+
const summary = trimText(input.summary ?? input.assistant_summary ?? input.assistantSummary ?? text, 300);
|
|
166
|
+
return {
|
|
167
|
+
text,
|
|
168
|
+
summary,
|
|
169
|
+
signals: inferSignals(text, input.signals),
|
|
170
|
+
strategy: buildStrategy(input),
|
|
171
|
+
artifacts: normalizeList(input.artifacts ?? input.outputs ?? input.files, 12, 240),
|
|
172
|
+
execution: normalizeExecution(input),
|
|
173
|
+
platform: trimText(input.platform ?? input.host ?? 'generic', 64),
|
|
174
|
+
model: trimText(input.model ?? '', 100) || 'unknown',
|
|
175
|
+
source_thread: trimText(input.thread_id ?? input.threadId ?? input.session_id ?? input.sessionId ?? '', 128),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
export async function distillConversation(input, opts = {}) {
|
|
179
|
+
if (!input || typeof input !== 'object' || Array.isArray(input))
|
|
180
|
+
return { ok: false, status: 'skipped', reason: 'input_object_required' };
|
|
181
|
+
const normalized = normalizeConversationInput(input);
|
|
182
|
+
if (!normalized.summary || normalized.summary.length < 20)
|
|
183
|
+
return { ok: false, status: 'skipped', reason: 'summary_required' };
|
|
184
|
+
const gate = evaluateGate(input, normalized);
|
|
185
|
+
if (!gate.ok)
|
|
186
|
+
return { ok: false, status: 'skipped', reason: gate.reason ?? 'insufficient_reusable_signal', quality: gate, signals: normalized.signals };
|
|
187
|
+
const slug = slugify(input.name ?? input.title ?? normalized.summary);
|
|
188
|
+
const fingerprint = hashInput({
|
|
189
|
+
summary: normalized.summary,
|
|
190
|
+
signals: normalized.signals,
|
|
191
|
+
strategy: normalized.strategy,
|
|
192
|
+
artifacts: normalized.artifacts,
|
|
193
|
+
});
|
|
194
|
+
const category = inferCategory(normalized.signals, normalized.text);
|
|
195
|
+
const gene = {
|
|
196
|
+
type: 'Gene',
|
|
197
|
+
schema_version: SCHEMA_VERSION,
|
|
198
|
+
id: `gene_conversation_${slug}_${fingerprint}`,
|
|
199
|
+
summary: normalized.summary,
|
|
200
|
+
category,
|
|
201
|
+
signals_match: normalized.signals,
|
|
202
|
+
preconditions: [
|
|
203
|
+
'A live agent conversation produced a repeatable workflow or capability.',
|
|
204
|
+
'The conversation includes enough evidence to reconstruct when and how to use it.',
|
|
205
|
+
],
|
|
206
|
+
strategy: normalized.strategy,
|
|
207
|
+
validation: normalized.execution.validation.length > 0 ? normalized.execution.validation : ['node --version'],
|
|
208
|
+
constraints: { max_files: 20, forbidden_paths: ['.git', 'node_modules', '.env'] },
|
|
209
|
+
_source: {
|
|
210
|
+
kind: 'conversation_distillation',
|
|
211
|
+
platform: normalized.platform,
|
|
212
|
+
source_thread: normalized.source_thread || null,
|
|
213
|
+
quality: gate,
|
|
214
|
+
distilled_at: new Date().toISOString(),
|
|
215
|
+
},
|
|
216
|
+
asset_id: '',
|
|
217
|
+
};
|
|
218
|
+
gene.asset_id = computeAssetId(gene) ?? '';
|
|
219
|
+
const capsule = {
|
|
220
|
+
type: 'Capsule',
|
|
221
|
+
schema_version: SCHEMA_VERSION,
|
|
222
|
+
id: `capsule_conversation_${slug}_${fingerprint}`,
|
|
223
|
+
trigger: normalized.signals,
|
|
224
|
+
gene: String(gene.id),
|
|
225
|
+
summary: normalized.summary,
|
|
226
|
+
confidence: Math.min(0.95, 0.5 + gate.score / 20),
|
|
227
|
+
blast_radius: normalizePublishBlastRadius(normalized.execution.blast_radius, normalized.artifacts.length),
|
|
228
|
+
outcome: { status: normalized.execution.status, score: normalized.execution.status === 'success' ? 0.82 : 0.35 },
|
|
229
|
+
source_type: 'conversation_distillation',
|
|
230
|
+
strategy: normalized.strategy,
|
|
231
|
+
execution_trace: normalized.execution.trace,
|
|
232
|
+
a2a: { eligible_to_broadcast: true },
|
|
233
|
+
content: capsuleContent(normalized),
|
|
234
|
+
diff: '',
|
|
235
|
+
reused_asset_id: '',
|
|
236
|
+
env_fingerprint: {
|
|
237
|
+
platform: normalized.platform,
|
|
238
|
+
source_thread: normalized.source_thread || null,
|
|
239
|
+
// Underlying LLM model, threaded from the originating client via input.model (resolved by
|
|
240
|
+
// detectModelName() in the node's OWN process). We deliberately do NOT sniff the local process.env
|
|
241
|
+
// here: distillConversation also runs inside the proxy daemon (proxyDaemon relays the wire body),
|
|
242
|
+
// whose env lacks the per-session model vars — sniffing there would mis-attribute the model (#219
|
|
243
|
+
// review). Falls back to 'unknown' when the caller supplied none. Lets the Hub attribute distilled
|
|
244
|
+
// capsules by model (by-model leaderboard / anti-sybil), like the skill2gep capsule's env_fingerprint.
|
|
245
|
+
model: normalized.model,
|
|
246
|
+
},
|
|
247
|
+
asset_id: '',
|
|
248
|
+
};
|
|
249
|
+
capsule.asset_id = computeAssetId(capsule) ?? '';
|
|
250
|
+
const persist = (opts.persist ?? input.persist) === true;
|
|
251
|
+
if (persist && opts.store) {
|
|
252
|
+
await opts.store.put(gene);
|
|
253
|
+
await opts.store.put(capsule);
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
ok: true,
|
|
257
|
+
status: persist && opts.store ? 'stored' : 'draft',
|
|
258
|
+
distill_id: fingerprint,
|
|
259
|
+
quality: gate,
|
|
260
|
+
signals: normalized.signals,
|
|
261
|
+
gene,
|
|
262
|
+
capsule,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { HubCapability, PublishReceipt, AgentEvent, TaskEvent, AuthProvider, HubQuery, AssetRecord } from './capability.js';
|
|
2
|
+
export interface FakeHubOptions {
|
|
3
|
+
/** 脚本化 publish gate: 返回 reject/quarantine 以测 PublishReceipt 终态路径. */
|
|
4
|
+
publishGate?: (asset: AssetRecord) => Pick<PublishReceipt, 'status' | 'reason' | 'terminal'>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* 内存 HubCapability(M6-1, 测试用). 复用 InMemoryTransport 思路, 但走完整 HubCapability 形状,
|
|
8
|
+
* 让 SyncEngine/LifecycleManager/bindings 不连真 hub 即可端到端测.
|
|
9
|
+
*/
|
|
10
|
+
export declare class FakeHubCapability implements HubCapability {
|
|
11
|
+
private readonly opts;
|
|
12
|
+
private readonly assets;
|
|
13
|
+
private readonly inbox;
|
|
14
|
+
private readonly acked;
|
|
15
|
+
readonly pushed: AgentEvent[];
|
|
16
|
+
readonly claims: Array<{
|
|
17
|
+
taskId: string;
|
|
18
|
+
claimId: string;
|
|
19
|
+
}>;
|
|
20
|
+
readonly completed: Array<{
|
|
21
|
+
claimId: string;
|
|
22
|
+
result: unknown;
|
|
23
|
+
}>;
|
|
24
|
+
readonly auth: AuthProvider;
|
|
25
|
+
nextPollAfterMs: number | undefined;
|
|
26
|
+
constructor(opts?: FakeHubOptions);
|
|
27
|
+
/** 测试注入: 排一条 inbound 事件供 poll 拉. */
|
|
28
|
+
seedInbound(e: AgentEvent): void;
|
|
29
|
+
publish(bundle: AssetRecord[]): Promise<PublishReceipt>;
|
|
30
|
+
fetch(query: HubQuery): Promise<AssetRecord[]>;
|
|
31
|
+
search(query: HubQuery): Promise<AssetRecord[]>;
|
|
32
|
+
task: {
|
|
33
|
+
claim: (taskId: string) => Promise<{
|
|
34
|
+
claimId: string;
|
|
35
|
+
}>;
|
|
36
|
+
complete: (claimId: string, result: unknown) => Promise<{
|
|
37
|
+
status: "completed";
|
|
38
|
+
}>;
|
|
39
|
+
subscribe: (filter: unknown) => AsyncIterable<TaskEvent>;
|
|
40
|
+
};
|
|
41
|
+
mailbox: HubCapability['mailbox'];
|
|
42
|
+
/** 测试断言用. */
|
|
43
|
+
isAcked(id: string): boolean;
|
|
44
|
+
publishedCount(): number;
|
|
45
|
+
}
|