@evomap/evolver-core 2.0.0-beta.9 → 2.0.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/candidateAssembly.d.ts +7 -2
- package/dist/algo/candidateAssembly.js +81 -13
- package/dist/algo/capabilityCandidates.js +10 -0
- package/dist/algo/cycleEngine.d.ts +23 -2
- package/dist/algo/cycleEngine.js +236 -36
- package/dist/algo/exploration.d.ts +7 -0
- package/dist/algo/exploration.js +16 -3
- package/dist/algo/geneHealth.d.ts +2 -2
- package/dist/algo/geneHealth.js +5 -4
- package/dist/algo/geneSelection.d.ts +63 -5
- package/dist/algo/geneSelection.js +330 -30
- package/dist/algo/index.d.ts +2 -0
- package/dist/algo/index.js +2 -0
- package/dist/algo/orchestrator.d.ts +8 -1
- package/dist/algo/orchestrator.js +15 -3
- package/dist/algo/publishEligibility.d.ts +34 -0
- package/dist/algo/publishEligibility.js +52 -0
- package/dist/algo/ucb1.d.ts +53 -0
- package/dist/algo/ucb1.js +156 -0
- package/dist/assetstore/assetSidecarRecords.d.ts +7 -2
- package/dist/assetstore/assetSidecarRecords.js +238 -0
- package/dist/assetstore/assetSidecarRecovery.js +2 -2
- package/dist/assetstore/assetStoreHealth.d.ts +6 -0
- package/dist/assetstore/assetStoreHealth.js +56 -14
- package/dist/assetstore/assetStoreStorage.d.ts +1 -1
- package/dist/assetstore/assetStoreStorage.js +27 -9
- package/dist/assetstore/assetSyncLedger.d.ts +86 -0
- package/dist/assetstore/assetSyncLedger.js +683 -4
- package/dist/assetstore/index.d.ts +1 -0
- package/dist/assetstore/index.js +1 -0
- package/dist/assetstore/localAssetStoreSnapshot.d.ts +51 -0
- package/dist/assetstore/localAssetStoreSnapshot.js +329 -0
- package/dist/assetstore/localJsonl.d.ts +4 -2
- package/dist/assetstore/localJsonl.js +89 -9
- package/dist/assetstore/provenance.d.ts +80 -4
- package/dist/assetstore/provenance.js +313 -5
- package/dist/assetstore/provider.d.ts +58 -1
- package/dist/assetstore/provider.js +97 -6
- package/dist/benchmark/antiGeneBenchmark.d.ts +2 -0
- package/dist/benchmark/antiGeneBenchmark.js +4 -3
- package/dist/benchmark/antiGeneRollout.d.ts +2 -0
- package/dist/benchmark/antiGeneRollout.js +4 -3
- package/dist/benchmark/index.d.ts +2 -1
- package/dist/benchmark/index.js +2 -1
- package/dist/benchmark/selectionFlatAbstention.d.ts +152 -0
- package/dist/benchmark/selectionFlatAbstention.js +481 -0
- package/dist/bootstrap/envFingerprint.d.ts +9 -0
- package/dist/bootstrap/envFingerprint.js +5 -0
- package/dist/bootstrap/index.d.ts +2 -1
- package/dist/bootstrap/index.js +2 -1
- package/dist/bootstrap/v1EnvCompat.d.ts +111 -0
- package/dist/bootstrap/v1EnvCompat.js +280 -0
- package/dist/events/eventArchive.d.ts +2 -0
- package/dist/events/eventArchive.js +13 -3
- package/dist/events/eventSchema.d.ts +7 -7
- package/dist/events/eventStore.d.ts +2 -0
- package/dist/events/eventStore.js +5 -1
- package/dist/events/ingest.d.ts +1 -0
- package/dist/events/ingest.js +1 -0
- package/dist/events/paths.d.ts +3 -1
- package/dist/events/paths.js +4 -0
- package/dist/events/public.d.ts +2 -2
- package/dist/events/public.js +2 -2
- package/dist/events/reports.d.ts +2 -0
- package/dist/events/reports.js +4 -0
- package/dist/exec/autoExec.d.ts +43 -2
- package/dist/exec/autoExec.js +76 -9
- package/dist/exec/autonomousCycle.d.ts +22 -4
- package/dist/exec/autonomousCycle.js +64 -13
- package/dist/exec/claudeBridge.d.ts +32 -7
- package/dist/exec/claudeBridge.js +281 -29
- package/dist/exec/prompt.js +5 -1
- package/dist/exec/runnerRegistry.d.ts +68 -26
- package/dist/exec/runnerRegistry.js +307 -72
- package/dist/exec/selfPr.js +1 -7
- package/dist/feedback/envelope.d.ts +61 -0
- package/dist/feedback/envelope.js +168 -0
- package/dist/feedback/index.d.ts +1 -0
- package/dist/feedback/index.js +1 -0
- package/dist/hooks/hooks.js +1 -0
- package/dist/hub/assetCallLog.d.ts +35 -1
- package/dist/hub/assetCallLog.js +124 -1
- package/dist/hub/bindings.d.ts +8 -1
- package/dist/hub/bindings.js +17 -6
- package/dist/hub/capability.d.ts +90 -3
- package/dist/hub/fake.d.ts +2 -2
- package/dist/hub/fake.js +1 -1
- package/dist/hub/questionGenerator.d.ts +5 -1
- package/dist/hub/questionGenerator.js +8 -6
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -1
- package/dist/mailbox/dispatch.d.ts +1 -1
- package/dist/mailbox/dispatch.js +22 -6
- package/dist/mailbox/envelope.d.ts +7 -1
- package/dist/mailbox/envelope.js +9 -2
- package/dist/mailbox/ipcServer.d.ts +10 -2
- package/dist/mailbox/ipcServer.js +163 -13
- package/dist/mailbox/store.d.ts +89 -3
- package/dist/mailbox/store.js +895 -41
- package/dist/ops/evolutionGraphProjection.d.ts +20 -0
- package/dist/ops/evolutionGraphProjection.js +315 -0
- package/dist/ops/index.d.ts +2 -1
- package/dist/ops/index.js +2 -1
- package/dist/ops/selfUpdate.d.ts +8 -0
- package/dist/ops/selfUpdate.js +24 -8
- package/dist/personality/schema.d.ts +16 -16
- package/dist/schema/evolutionGraph.d.ts +784 -0
- package/dist/schema/evolutionGraph.js +187 -0
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.js +1 -0
- package/dist/schema/signal.d.ts +3 -3
- package/dist/schema/signal.js +1 -1
- package/dist/signals/curriculum.d.ts +55 -0
- package/dist/signals/curriculum.js +202 -0
- package/dist/signals/cycleHistoryFromEvents.js +17 -8
- package/dist/signals/expand.d.ts +15 -1
- package/dist/signals/expand.js +169 -1
- package/dist/signals/extractor.d.ts +2 -2
- package/dist/signals/extractor.js +31 -6
- package/dist/signals/index.d.ts +3 -1
- package/dist/signals/index.js +3 -1
- package/dist/signals/metaSignals.d.ts +4 -0
- package/dist/signals/metaSignals.js +42 -0
- package/dist/signals/signalGate.js +1 -1
- package/dist/signals/taskDomain.d.ts +22 -0
- package/dist/signals/taskDomain.js +43 -0
- package/dist/strategy/constraintAblation.js +115 -369
- package/dist/strategy/constraintAblationPredicates.d.ts +31 -0
- package/dist/strategy/constraintAblationPredicates.js +339 -0
- package/dist/trace/index.d.ts +3 -1
- package/dist/trace/index.js +3 -1
- package/dist/trace/learningTrace.d.ts +209 -0
- package/dist/trace/learningTrace.js +276 -0
- package/dist/trace/proxyTurns.d.ts +31 -0
- package/dist/trace/proxyTurns.js +137 -0
- package/dist/verify/sandboxRunner.d.ts +28 -0
- package/dist/verify/sandboxRunner.js +218 -19
- package/dist/verify/sandboxedValidation.d.ts +9 -0
- package/dist/verify/sandboxedValidation.js +113 -13
- package/dist/verify/validation.d.ts +11 -1
- package/dist/verify/validation.js +31 -0
- package/package.json +5 -2
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
export const PRIORITY_AXES = Object.freeze([
|
|
2
|
+
'task_success',
|
|
3
|
+
'user_preference',
|
|
4
|
+
'quality',
|
|
5
|
+
'safety',
|
|
6
|
+
'cost',
|
|
7
|
+
'latency',
|
|
8
|
+
'other',
|
|
9
|
+
]);
|
|
10
|
+
export const LABELS = Object.freeze(['positive', 'negative', 'mixed', 'neutral']);
|
|
11
|
+
export const ATTENTION_LEVELS = Object.freeze(['full', 'limited', 'skimmed', 'unknown']);
|
|
12
|
+
export const EVIDENCE_KINDS = Object.freeze([
|
|
13
|
+
'evolution_event',
|
|
14
|
+
'evolution_outcome',
|
|
15
|
+
'user_override',
|
|
16
|
+
'review',
|
|
17
|
+
'turn',
|
|
18
|
+
'external',
|
|
19
|
+
]);
|
|
20
|
+
export function clamp01(value) {
|
|
21
|
+
const n = Number(value);
|
|
22
|
+
if (!Number.isFinite(n))
|
|
23
|
+
return 0.5;
|
|
24
|
+
if (n < 0)
|
|
25
|
+
return 0;
|
|
26
|
+
if (n > 1)
|
|
27
|
+
return 1;
|
|
28
|
+
return n;
|
|
29
|
+
}
|
|
30
|
+
export function labelFromScalar(value) {
|
|
31
|
+
const scalar = clamp01(value);
|
|
32
|
+
if (scalar >= 0.6)
|
|
33
|
+
return 'positive';
|
|
34
|
+
if (scalar <= 0.4)
|
|
35
|
+
return 'negative';
|
|
36
|
+
return 'mixed';
|
|
37
|
+
}
|
|
38
|
+
export function normalizeAttention(input) {
|
|
39
|
+
const record = asRecord(input);
|
|
40
|
+
if (!record)
|
|
41
|
+
return { level: 'unknown' };
|
|
42
|
+
const attention = {
|
|
43
|
+
level: enumValue(record['level'], ATTENTION_LEVELS, 'unknown'),
|
|
44
|
+
};
|
|
45
|
+
const observedItems = nonNegativeInteger(record['observed_items']);
|
|
46
|
+
const elapsedMs = nonNegativeInteger(record['elapsed_ms']);
|
|
47
|
+
if (observedItems !== null)
|
|
48
|
+
attention.observed_items = observedItems;
|
|
49
|
+
if (elapsedMs !== null)
|
|
50
|
+
attention.elapsed_ms = elapsedMs;
|
|
51
|
+
return attention;
|
|
52
|
+
}
|
|
53
|
+
export function evidenceRef(kind, id, options = {}) {
|
|
54
|
+
const ref = {
|
|
55
|
+
kind: enumValue(kind, EVIDENCE_KINDS, 'external'),
|
|
56
|
+
id: String(id ?? '').trim() || 'unknown',
|
|
57
|
+
};
|
|
58
|
+
if (typeof options.summary === 'string' && options.summary.trim()) {
|
|
59
|
+
ref.summary = options.summary.trim();
|
|
60
|
+
}
|
|
61
|
+
return ref;
|
|
62
|
+
}
|
|
63
|
+
export function normalizeEvidenceRef(input) {
|
|
64
|
+
const record = asRecord(input);
|
|
65
|
+
if (!record)
|
|
66
|
+
return evidenceRef('external', 'unknown');
|
|
67
|
+
return evidenceRef(record['kind'], record['id'], { summary: record['summary'] });
|
|
68
|
+
}
|
|
69
|
+
export function envelopeUncertainty(scalar, attentionLevel, indecision, conflict) {
|
|
70
|
+
const normalizedScalar = clamp01(scalar);
|
|
71
|
+
const ambiguity = 1 - Math.abs(normalizedScalar - 0.5) * 2;
|
|
72
|
+
const attentionPenalty = {
|
|
73
|
+
full: 0,
|
|
74
|
+
limited: 0.15,
|
|
75
|
+
skimmed: 0.30,
|
|
76
|
+
unknown: 0.20,
|
|
77
|
+
};
|
|
78
|
+
return clamp01(0.10
|
|
79
|
+
+ 0.30 * ambiguity
|
|
80
|
+
+ attentionPenalty[attentionLevel]
|
|
81
|
+
+ (indecision ? 0.25 : 0)
|
|
82
|
+
+ (conflict ? 0.35 : 0));
|
|
83
|
+
}
|
|
84
|
+
export function fromScalarFeedback(options = {}) {
|
|
85
|
+
const input = options ?? {};
|
|
86
|
+
const scalar = clamp01(input.scalar);
|
|
87
|
+
const label = labelFromScalar(scalar);
|
|
88
|
+
const indecision = Boolean(input.indecision) || label === 'mixed';
|
|
89
|
+
const conflict = Boolean(input.conflict);
|
|
90
|
+
const evaluatorAttention = normalizeAttention(input.evaluator_attention ?? input.evaluatorAttention);
|
|
91
|
+
const priorityAxis = enumValue(input.priority_axis ?? input.priorityAxis, PRIORITY_AXES, 'task_success');
|
|
92
|
+
const evidence = input.evidence_ref ?? input.evidenceRef ?? evidenceRef('external', 'unknown');
|
|
93
|
+
return {
|
|
94
|
+
priority_axis: priorityAxis,
|
|
95
|
+
label,
|
|
96
|
+
scalar,
|
|
97
|
+
indecision,
|
|
98
|
+
conflict,
|
|
99
|
+
evaluator_attention: evaluatorAttention,
|
|
100
|
+
evidence_ref: normalizeEvidenceRef(evidence),
|
|
101
|
+
uncertainty: envelopeUncertainty(scalar, evaluatorAttention.level, indecision, conflict),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function fromOutcomeScalar(outcome, options = {}) {
|
|
105
|
+
const record = asRecord(outcome);
|
|
106
|
+
if (!record)
|
|
107
|
+
return null;
|
|
108
|
+
const scalar = record['user_override'] ?? record['score'];
|
|
109
|
+
if (scalar === null || scalar === undefined)
|
|
110
|
+
return null;
|
|
111
|
+
return fromScalarFeedback({ ...options, scalar });
|
|
112
|
+
}
|
|
113
|
+
export function withConflict(envelope) {
|
|
114
|
+
const evaluatorAttention = normalizeAttention(envelope.evaluator_attention);
|
|
115
|
+
return {
|
|
116
|
+
...envelope,
|
|
117
|
+
conflict: true,
|
|
118
|
+
evaluator_attention: evaluatorAttention,
|
|
119
|
+
uncertainty: envelopeUncertainty(envelope.scalar, evaluatorAttention.level, envelope.indecision, true),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function withIndecision(envelope) {
|
|
123
|
+
const evaluatorAttention = normalizeAttention(envelope.evaluator_attention);
|
|
124
|
+
return {
|
|
125
|
+
...envelope,
|
|
126
|
+
indecision: true,
|
|
127
|
+
evaluator_attention: evaluatorAttention,
|
|
128
|
+
uncertainty: envelopeUncertainty(envelope.scalar, evaluatorAttention.level, true, envelope.conflict),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export function aggregateFeedbackEnvelopes(envelopes) {
|
|
132
|
+
const list = Array.isArray(envelopes) ? envelopes.filter(Boolean) : [];
|
|
133
|
+
if (list.length === 0)
|
|
134
|
+
return { dominant_label: null, uncertainty: 1, sample_count: 0 };
|
|
135
|
+
const sampleCount = list.length;
|
|
136
|
+
const meanUncertainty = list.reduce((sum, envelope) => sum + clamp01(envelope.uncertainty), 0) / sampleCount;
|
|
137
|
+
const hasPositive = list.some((envelope) => envelope.label === 'positive');
|
|
138
|
+
const hasNegative = list.some((envelope) => envelope.label === 'negative');
|
|
139
|
+
const hasConflict = list.some((envelope) => envelope.conflict) || (hasPositive && hasNegative);
|
|
140
|
+
const hasIndecision = list.some((envelope) => envelope.indecision || envelope.label === 'mixed' || envelope.label === 'neutral');
|
|
141
|
+
const hasLowAttention = list.some((envelope) => normalizeAttention(envelope.evaluator_attention).level !== 'full');
|
|
142
|
+
const uncertainty = clamp01(meanUncertainty
|
|
143
|
+
+ (hasConflict ? 0.25 : 0)
|
|
144
|
+
+ (hasIndecision ? 0.10 : 0)
|
|
145
|
+
+ (hasLowAttention ? 0.10 : 0));
|
|
146
|
+
let dominantLabel = null;
|
|
147
|
+
if (!hasConflict && !hasLowAttention && uncertainty < 0.5) {
|
|
148
|
+
if (hasPositive)
|
|
149
|
+
dominantLabel = 'positive';
|
|
150
|
+
else if (hasNegative)
|
|
151
|
+
dominantLabel = 'negative';
|
|
152
|
+
}
|
|
153
|
+
return { dominant_label: dominantLabel, uncertainty, sample_count: sampleCount };
|
|
154
|
+
}
|
|
155
|
+
function enumValue(value, allowed, fallback) {
|
|
156
|
+
return typeof value === 'string' && allowed.includes(value)
|
|
157
|
+
? value
|
|
158
|
+
: fallback;
|
|
159
|
+
}
|
|
160
|
+
function nonNegativeInteger(value) {
|
|
161
|
+
const n = Number(value);
|
|
162
|
+
return Number.isFinite(n) ? Math.max(0, Math.floor(n)) : null;
|
|
163
|
+
}
|
|
164
|
+
function asRecord(value) {
|
|
165
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
166
|
+
? value
|
|
167
|
+
: null;
|
|
168
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './envelope.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './envelope.js';
|
package/dist/hooks/hooks.js
CHANGED
|
@@ -69,6 +69,7 @@ export function composeSessionStartWithRecap(base, recapCtx, estimateTokensOrOpt
|
|
|
69
69
|
export function signalsFromToolUse(event) {
|
|
70
70
|
const turn = {
|
|
71
71
|
toolName: event.toolName,
|
|
72
|
+
...(event.toolResult ? { toolResult: event.toolResult } : {}),
|
|
72
73
|
...(event.isError && event.toolResult ? { errorMessage: event.toolResult } : {}),
|
|
73
74
|
...(event.text ? { text: event.text } : {}),
|
|
74
75
|
isMeta: false,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export type AssetCallAction = 'hub_search_hit' | 'hub_search_miss' | 'asset_reuse' | 'asset_reference' | 'asset_publish' | 'asset_publish_skip' | 'hub_review_submitted' | 'hub_review_rejected' | 'hub_review_failed';
|
|
1
|
+
export type AssetCallAction = 'hub_search_hit' | 'hub_search_miss' | 'asset_reuse' | 'asset_reference' | 'asset_publish' | 'asset_publish_skip' | 'asset_inject' | 'asset_inject_shadow' | 'hub_review_submitted' | 'hub_review_rejected' | 'hub_review_failed';
|
|
2
|
+
export type TokensSavedBasis = 'measured' | 'cost_index' | 'estimated_blast_radius' | 'estimated_default';
|
|
2
3
|
export interface AssetCallEntry {
|
|
3
4
|
run_id?: string | null;
|
|
4
5
|
action: AssetCallAction;
|
|
@@ -10,6 +11,9 @@ export interface AssetCallEntry {
|
|
|
10
11
|
mode?: 'direct' | 'reference';
|
|
11
12
|
signals?: readonly string[];
|
|
12
13
|
reason?: string;
|
|
14
|
+
tokens_saved?: number | null;
|
|
15
|
+
tokens_saved_basis?: TokensSavedBasis | null;
|
|
16
|
+
tokens_spent?: number | null;
|
|
13
17
|
extra?: Record<string, unknown>;
|
|
14
18
|
}
|
|
15
19
|
export interface AssetCallRecord extends AssetCallEntry {
|
|
@@ -30,6 +34,32 @@ export interface CallLogSummary {
|
|
|
30
34
|
by_action: Record<string, number>;
|
|
31
35
|
entries: AssetCallRecord[];
|
|
32
36
|
}
|
|
37
|
+
export interface AssetReuseAttribution {
|
|
38
|
+
asset_id: string;
|
|
39
|
+
source_node_id: string | null;
|
|
40
|
+
chain_id: string | null;
|
|
41
|
+
reuse: number;
|
|
42
|
+
reference: number;
|
|
43
|
+
tokens_saved: number;
|
|
44
|
+
}
|
|
45
|
+
export interface ReuseAttributionSummary {
|
|
46
|
+
total_reuse: number;
|
|
47
|
+
total_reference: number;
|
|
48
|
+
total_tokens_saved: number;
|
|
49
|
+
by_asset: AssetReuseAttribution[];
|
|
50
|
+
}
|
|
51
|
+
export interface ReuseSavingsMetric {
|
|
52
|
+
tokens_saved: number;
|
|
53
|
+
tokens_saved_basis: TokensSavedBasis;
|
|
54
|
+
}
|
|
55
|
+
/** Measured derivation cost carried by an asset (or by a Hub wrapper's payload). */
|
|
56
|
+
export declare function assetDerivationTokenCost(asset: unknown): number | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Attribute savings without inventing a measured value: asset telemetry wins, then this node's publish-cost
|
|
59
|
+
* index, then the savings-core blast/default estimator. Reference reuse applies the same fractional discount
|
|
60
|
+
* to measured and estimated costs.
|
|
61
|
+
*/
|
|
62
|
+
export declare function reuseSavingsForAsset(asset: unknown, mode: 'direct' | 'reference', indexedTokenCost?: unknown): ReuseSavingsMetric;
|
|
33
63
|
export declare class AssetCallLog {
|
|
34
64
|
private readonly path;
|
|
35
65
|
private readonly now;
|
|
@@ -40,4 +70,8 @@ export declare class AssetCallLog {
|
|
|
40
70
|
read(opts?: ReadOpts): AssetCallRecord[];
|
|
41
71
|
/** Totals + per-action counts (for CLI / observability). */
|
|
42
72
|
summarize(opts?: ReadOpts): CallLogSummary;
|
|
73
|
+
/** Local-only attribution rollup over reuse/reference audit rows. */
|
|
74
|
+
reuseAttributionSummary(opts?: ReadOpts): ReuseAttributionSummary;
|
|
75
|
+
/** Later valid publish rows win; malformed/non-positive costs never erase a prior measurement. */
|
|
76
|
+
assetCostIndex(opts?: ReadOpts): Record<string, number>;
|
|
43
77
|
}
|
package/dist/hub/assetCallLog.js
CHANGED
|
@@ -5,6 +5,69 @@
|
|
|
5
5
|
// or fails an evolution. The log path is injected so it's testable without a real home dir.
|
|
6
6
|
import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
7
7
|
import { dirname } from 'node:path';
|
|
8
|
+
import { REUSE_ESTIMATOR, reuseEstimate } from '../ops/savingsCore.js';
|
|
9
|
+
function objectRecord(value) {
|
|
10
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
11
|
+
? value
|
|
12
|
+
: undefined;
|
|
13
|
+
}
|
|
14
|
+
function nonEmptyString(value) {
|
|
15
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
16
|
+
}
|
|
17
|
+
function positiveNumber(value, coerceLegacy = false) {
|
|
18
|
+
const number = typeof value === 'number' ? value : coerceLegacy ? Number(value) : Number.NaN;
|
|
19
|
+
return Number.isFinite(number) && number > 0 ? number : undefined;
|
|
20
|
+
}
|
|
21
|
+
function nestedAssetRecord(asset) {
|
|
22
|
+
const direct = objectRecord(asset);
|
|
23
|
+
return { ...(direct ? { direct } : {}), ...(objectRecord(direct?.['payload']) ? { payload: objectRecord(direct?.['payload']) } : {}) };
|
|
24
|
+
}
|
|
25
|
+
/** Measured derivation cost carried by an asset (or by a Hub wrapper's payload). */
|
|
26
|
+
export function assetDerivationTokenCost(asset) {
|
|
27
|
+
const records = nestedAssetRecord(asset);
|
|
28
|
+
for (const record of [records.direct, records.payload]) {
|
|
29
|
+
const derivation = objectRecord(record?.['derivation_tokens']);
|
|
30
|
+
const total = positiveNumber(derivation?.['total_tokens']);
|
|
31
|
+
if (total !== undefined)
|
|
32
|
+
return total;
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
function assetBlastRadiusLines(asset) {
|
|
37
|
+
const records = nestedAssetRecord(asset);
|
|
38
|
+
for (const record of [records.direct, records.payload]) {
|
|
39
|
+
const blast = objectRecord(record?.['blast_radius']);
|
|
40
|
+
const lines = positiveNumber(blast?.['lines']);
|
|
41
|
+
if (lines !== undefined)
|
|
42
|
+
return lines;
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Attribute savings without inventing a measured value: asset telemetry wins, then this node's publish-cost
|
|
48
|
+
* index, then the savings-core blast/default estimator. Reference reuse applies the same fractional discount
|
|
49
|
+
* to measured and estimated costs.
|
|
50
|
+
*/
|
|
51
|
+
export function reuseSavingsForAsset(asset, mode, indexedTokenCost) {
|
|
52
|
+
const measured = assetDerivationTokenCost(asset);
|
|
53
|
+
const indexed = measured === undefined ? positiveNumber(indexedTokenCost) : undefined;
|
|
54
|
+
const cost = measured ?? indexed;
|
|
55
|
+
if (cost !== undefined) {
|
|
56
|
+
return {
|
|
57
|
+
tokens_saved: Math.round(mode === 'reference' ? cost * REUSE_ESTIMATOR.reference_saving_fraction : cost),
|
|
58
|
+
tokens_saved_basis: measured !== undefined ? 'measured' : 'cost_index',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const estimated = reuseEstimate(assetBlastRadiusLines(asset), mode);
|
|
62
|
+
return { tokens_saved: estimated.tokens_saved, tokens_saved_basis: estimated.basis };
|
|
63
|
+
}
|
|
64
|
+
function isAssetCallRecord(value) {
|
|
65
|
+
const record = objectRecord(value);
|
|
66
|
+
return record !== undefined
|
|
67
|
+
&& typeof record['timestamp'] === 'string'
|
|
68
|
+
&& typeof record['action'] === 'string'
|
|
69
|
+
&& record['action'].length > 0;
|
|
70
|
+
}
|
|
8
71
|
export class AssetCallLog {
|
|
9
72
|
path;
|
|
10
73
|
now;
|
|
@@ -33,7 +96,9 @@ export class AssetCallLog {
|
|
|
33
96
|
if (!line)
|
|
34
97
|
continue;
|
|
35
98
|
try {
|
|
36
|
-
|
|
99
|
+
const parsed = JSON.parse(line);
|
|
100
|
+
if (isAssetCallRecord(parsed))
|
|
101
|
+
entries.push(parsed);
|
|
37
102
|
}
|
|
38
103
|
catch { /* skip corrupt */ }
|
|
39
104
|
}
|
|
@@ -69,4 +134,62 @@ export class AssetCallLog {
|
|
|
69
134
|
}
|
|
70
135
|
return { total_entries: entries.length, unique_assets: assets.size, unique_runs: runs.size, by_action: byAction, entries };
|
|
71
136
|
}
|
|
137
|
+
/** Local-only attribution rollup over reuse/reference audit rows. */
|
|
138
|
+
reuseAttributionSummary(opts = {}) {
|
|
139
|
+
const entries = this.read(opts).filter((entry) => entry.action === 'asset_reuse' || entry.action === 'asset_reference');
|
|
140
|
+
const byAsset = new Map();
|
|
141
|
+
let totalTokensSaved = 0;
|
|
142
|
+
let totalReuse = 0;
|
|
143
|
+
let totalReference = 0;
|
|
144
|
+
for (const entry of entries) {
|
|
145
|
+
const id = nonEmptyString(entry.asset_id) ?? '(unknown)';
|
|
146
|
+
let aggregate = byAsset.get(id);
|
|
147
|
+
if (!aggregate) {
|
|
148
|
+
aggregate = {
|
|
149
|
+
asset_id: id,
|
|
150
|
+
source_node_id: nonEmptyString(entry.source_node_id) ?? null,
|
|
151
|
+
chain_id: nonEmptyString(entry.chain_id) ?? null,
|
|
152
|
+
reuse: 0,
|
|
153
|
+
reference: 0,
|
|
154
|
+
tokens_saved: 0,
|
|
155
|
+
};
|
|
156
|
+
byAsset.set(id, aggregate);
|
|
157
|
+
}
|
|
158
|
+
if (entry.action === 'asset_reuse') {
|
|
159
|
+
aggregate.reuse += 1;
|
|
160
|
+
totalReuse += 1;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
aggregate.reference += 1;
|
|
164
|
+
totalReference += 1;
|
|
165
|
+
}
|
|
166
|
+
const tokensSaved = positiveNumber(entry['tokens_saved'], true);
|
|
167
|
+
if (tokensSaved !== undefined) {
|
|
168
|
+
aggregate.tokens_saved += tokensSaved;
|
|
169
|
+
totalTokensSaved += tokensSaved;
|
|
170
|
+
}
|
|
171
|
+
aggregate.source_node_id ??= nonEmptyString(entry.source_node_id) ?? null;
|
|
172
|
+
aggregate.chain_id ??= nonEmptyString(entry.chain_id) ?? null;
|
|
173
|
+
}
|
|
174
|
+
const byAssetRows = [...byAsset.values()].sort((left, right) => (right.reuse + right.reference) - (left.reuse + left.reference));
|
|
175
|
+
return {
|
|
176
|
+
total_reuse: totalReuse,
|
|
177
|
+
total_reference: totalReference,
|
|
178
|
+
total_tokens_saved: totalTokensSaved,
|
|
179
|
+
by_asset: byAssetRows,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** Later valid publish rows win; malformed/non-positive costs never erase a prior measurement. */
|
|
183
|
+
assetCostIndex(opts = {}) {
|
|
184
|
+
const costs = new Map();
|
|
185
|
+
for (const entry of this.read(opts)) {
|
|
186
|
+
if (entry.action !== 'asset_publish')
|
|
187
|
+
continue;
|
|
188
|
+
const assetId = nonEmptyString(entry.asset_id);
|
|
189
|
+
const tokensSpent = positiveNumber(entry['tokens_spent'], true);
|
|
190
|
+
if (assetId && tokensSpent !== undefined)
|
|
191
|
+
costs.set(assetId, tokensSpent);
|
|
192
|
+
}
|
|
193
|
+
return Object.fromEntries(costs);
|
|
194
|
+
}
|
|
72
195
|
}
|
package/dist/hub/bindings.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HubCapability, HubBindings } from './capability.js';
|
|
1
|
+
import type { HubCapability, HubBindings, PublishReceipt } from './capability.js';
|
|
2
2
|
import { type LeakCheckMode } from './sanitize.js';
|
|
3
3
|
/** publish 回执非 accepted → 抛此错; SyncEngine 据 terminal 决定是否重试. */
|
|
4
4
|
export declare class PublishRejectedError extends Error {
|
|
@@ -19,6 +19,13 @@ export interface HubBindingsOptions {
|
|
|
19
19
|
mode?: LeakCheckMode;
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Internal publish-handler result. `submittedAssetIds` identifies the exact sanitized
|
|
24
|
+
* content sent to the Hub, even when the Hub's accepted receipt omits asset ids.
|
|
25
|
+
*/
|
|
26
|
+
export interface PublishDispatchResult extends PublishReceipt {
|
|
27
|
+
submittedAssetIds?: string[];
|
|
28
|
+
}
|
|
22
29
|
/**
|
|
23
30
|
* 把 HubCapability 接到 core 两 seam(M6-1):
|
|
24
31
|
* - asProxyHandler: Dispatcher.handlers.proxy — 按 envelope.type 路由到 hub. 抛错→store.fail()重试;
|
package/dist/hub/bindings.js
CHANGED
|
@@ -37,14 +37,18 @@ export function makeHubBindings(cap, options = {}) {
|
|
|
37
37
|
const sanEnabled = sanCfg.enabled ?? true;
|
|
38
38
|
const sanEnv = sanCfg.env ?? (typeof process !== 'undefined' ? process.env : {});
|
|
39
39
|
/** Single publish chokepoint: sanitize (on by default) → strict + leak found → refuse (terminal, not retryable) → cap.publish the redacted bundle. */
|
|
40
|
-
const publishSanitized = (bundle) => {
|
|
40
|
+
const publishSanitized = async (bundle, publishOptions) => {
|
|
41
41
|
if (!sanEnabled)
|
|
42
|
-
return cap.publish(bundle);
|
|
42
|
+
return publishOptions ? cap.publish(bundle, publishOptions) : cap.publish(bundle);
|
|
43
43
|
const r = sanitizeBundle(bundle, { env: sanEnv, ...(sanCfg.mode ? { mode: sanCfg.mode } : {}) });
|
|
44
44
|
if (r.blocked) {
|
|
45
45
|
throw new PublishRejectedError('leak_blocked', true, `sensitive data detected before publish, refused (not retryable): ${summarizeLeaks(r.leaks)}`);
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
const receipt = publishOptions
|
|
48
|
+
? await cap.publish(r.bundle, publishOptions)
|
|
49
|
+
: await cap.publish(r.bundle);
|
|
50
|
+
const submittedAssetIds = contentAssetIds(r.bundle);
|
|
51
|
+
return submittedAssetIds ? { ...receipt, submittedAssetIds } : receipt;
|
|
48
52
|
};
|
|
49
53
|
return {
|
|
50
54
|
asProxyHandler() {
|
|
@@ -54,9 +58,10 @@ export function makeHubBindings(cap, options = {}) {
|
|
|
54
58
|
// payload 可为 bundle {assets:[...]} 或单资产; 统一成 bundle 数组发.
|
|
55
59
|
const p = e.payload;
|
|
56
60
|
const bundle = Array.isArray(p.assets) ? p.assets : [p];
|
|
57
|
-
const r = await publishSanitized(bundle);
|
|
58
|
-
if (r.status !== 'accepted')
|
|
59
|
-
throw new PublishRejectedError(r.status, r.terminal ?? true, r.reason);
|
|
61
|
+
const r = await publishSanitized(bundle, { idempotencyKey: e.idempotencyKey });
|
|
62
|
+
if (r.status !== 'accepted') {
|
|
63
|
+
throw new PublishRejectedError(r.rejection?.code ?? r.status, r.terminal ?? true, r.reason, r.rejection?.retryAfterMs);
|
|
64
|
+
}
|
|
60
65
|
return r;
|
|
61
66
|
}
|
|
62
67
|
case 'task_claim': {
|
|
@@ -98,6 +103,12 @@ export function makeHubBindings(cap, options = {}) {
|
|
|
98
103
|
},
|
|
99
104
|
};
|
|
100
105
|
}
|
|
106
|
+
function contentAssetIds(bundle) {
|
|
107
|
+
const ids = bundle.map((asset) => asset.asset_id);
|
|
108
|
+
return ids.every((id) => typeof id === 'string' && /^sha256:[a-f0-9]{64}$/i.test(id))
|
|
109
|
+
? ids
|
|
110
|
+
: undefined;
|
|
111
|
+
}
|
|
101
112
|
function firstString(...values) {
|
|
102
113
|
for (const value of values) {
|
|
103
114
|
if (typeof value !== 'string')
|
package/dist/hub/capability.d.ts
CHANGED
|
@@ -16,6 +16,11 @@ export interface PublishReceipt {
|
|
|
16
16
|
assetIds?: string[];
|
|
17
17
|
/** 终态标记: true=不可重试(reject/quarantine/402), SyncEngine 不得 incrementRetry(money-safety risk). */
|
|
18
18
|
terminal?: boolean;
|
|
19
|
+
/** Adapter-owned structured rejection metadata; callers must not infer policy from free-form `reason`. */
|
|
20
|
+
rejection?: {
|
|
21
|
+
code: 'invalid_request' | 'credit_shortage' | 'node_unauthorized' | 'not_found' | 'duplicate' | 'invalid_payload' | 'cooldown' | 'hub_rejected';
|
|
22
|
+
retryAfterMs?: number;
|
|
23
|
+
};
|
|
19
24
|
/** M8-1: 公版经济侧只读回执(core 不解释经济语义, 仅透传供观测/UI). private hub 多为空. */
|
|
20
25
|
economic?: {
|
|
21
26
|
creditShortage?: boolean;
|
|
@@ -25,6 +30,10 @@ export interface PublishReceipt {
|
|
|
25
30
|
gdiScore?: number;
|
|
26
31
|
};
|
|
27
32
|
}
|
|
33
|
+
export interface PublishOptions {
|
|
34
|
+
/** Stable, non-blank per logical publish so adapters can make transport retries idempotent. */
|
|
35
|
+
idempotencyKey?: string;
|
|
36
|
+
}
|
|
28
37
|
/** 资产查询. 复用 assetstore SearchQuery, 不发明第二套查询 DSL. */
|
|
29
38
|
export type HubQuery = SearchQuery;
|
|
30
39
|
/** task 子系统事件(订阅流元素). 公版含经济上下文(bounty/credit), 私有仅 workflow. */
|
|
@@ -111,6 +120,75 @@ export interface ReuseResultReceipt {
|
|
|
111
120
|
reason?: string;
|
|
112
121
|
id?: string;
|
|
113
122
|
}
|
|
123
|
+
export type LearningAssetType = 'memory' | 'skill' | 'playbook' | 'eval';
|
|
124
|
+
export type LearningAssetStatus = 'pending_review' | 'active' | 'disabled' | 'stale' | 'archived';
|
|
125
|
+
export type LearningAssetEffectiveStatus = LearningAssetStatus | 'expired';
|
|
126
|
+
export type LearningAssetUsageOutcome = ReuseResultOutcome;
|
|
127
|
+
export interface LearningAssetOwner {
|
|
128
|
+
node_id?: string | null;
|
|
129
|
+
user_id?: string | null;
|
|
130
|
+
org_id?: string | null;
|
|
131
|
+
workspace_id?: string | null;
|
|
132
|
+
}
|
|
133
|
+
/** Hub-owned learning asset record. Core keeps it opaque; adapters own wire shape and auth. */
|
|
134
|
+
export interface LearningAssetRecord {
|
|
135
|
+
asset_id: string;
|
|
136
|
+
type: LearningAssetType;
|
|
137
|
+
source_packet_id?: string;
|
|
138
|
+
scope?: string[];
|
|
139
|
+
owner?: LearningAssetOwner;
|
|
140
|
+
title?: string;
|
|
141
|
+
summary?: string;
|
|
142
|
+
confidence?: number;
|
|
143
|
+
last_used_at?: string | null;
|
|
144
|
+
usage_count?: number;
|
|
145
|
+
success_count?: number;
|
|
146
|
+
success_rate?: number;
|
|
147
|
+
expires_at?: string | null;
|
|
148
|
+
conflicts_with?: string[];
|
|
149
|
+
status?: LearningAssetStatus;
|
|
150
|
+
effective_status?: LearningAssetEffectiveStatus;
|
|
151
|
+
status_reason?: string;
|
|
152
|
+
provenance?: Record<string, unknown>;
|
|
153
|
+
payload?: Record<string, unknown>;
|
|
154
|
+
created_at?: string | null;
|
|
155
|
+
updated_at?: string | null;
|
|
156
|
+
[k: string]: unknown;
|
|
157
|
+
}
|
|
158
|
+
export interface LearningAssetListOptions {
|
|
159
|
+
type?: LearningAssetType;
|
|
160
|
+
scope?: readonly string[];
|
|
161
|
+
status?: LearningAssetStatus | readonly LearningAssetStatus[];
|
|
162
|
+
includeExpired?: boolean;
|
|
163
|
+
includePayload?: boolean;
|
|
164
|
+
limit?: number;
|
|
165
|
+
}
|
|
166
|
+
export interface LearningAssetListResult {
|
|
167
|
+
assets: LearningAssetRecord[];
|
|
168
|
+
limit: number;
|
|
169
|
+
reason?: string;
|
|
170
|
+
}
|
|
171
|
+
export interface LearningAssetUsageReport {
|
|
172
|
+
assetId?: string;
|
|
173
|
+
usedAssetIds?: readonly string[];
|
|
174
|
+
outcome: LearningAssetUsageOutcome;
|
|
175
|
+
score?: number;
|
|
176
|
+
sourceEventId: string;
|
|
177
|
+
reason?: string;
|
|
178
|
+
}
|
|
179
|
+
export interface LearningAssetUsageResultRow {
|
|
180
|
+
asset_id: string;
|
|
181
|
+
recorded: boolean;
|
|
182
|
+
duplicated?: boolean;
|
|
183
|
+
error?: string;
|
|
184
|
+
[k: string]: unknown;
|
|
185
|
+
}
|
|
186
|
+
/** Learning-asset usage reporting is best-effort; failures must not break runtime solve paths. */
|
|
187
|
+
export interface LearningAssetUsageReceipt {
|
|
188
|
+
recorded: boolean;
|
|
189
|
+
reason?: string;
|
|
190
|
+
results: LearningAssetUsageResultRow[];
|
|
191
|
+
}
|
|
114
192
|
/**
|
|
115
193
|
* Pre-publish dry-run result. The hub runs the same hub-side quality + content-safety
|
|
116
194
|
* gate as publish but stores nothing and charges no credits, so an agent can check a
|
|
@@ -141,6 +219,10 @@ export interface RecipeCreateRequest {
|
|
|
141
219
|
pricePerExecution?: number;
|
|
142
220
|
currency?: string;
|
|
143
221
|
maxConcurrent?: number;
|
|
222
|
+
idempotencyKey?: string;
|
|
223
|
+
}
|
|
224
|
+
export interface RecipePublishOptions {
|
|
225
|
+
idempotencyKey?: string;
|
|
144
226
|
}
|
|
145
227
|
export interface RecipeReceipt {
|
|
146
228
|
recipeId?: string;
|
|
@@ -159,11 +241,11 @@ export interface RecipeExpressionReceipt extends RecipeReceipt {
|
|
|
159
241
|
/** Optional Hub recipe/DNA capability. Core stays wire-agnostic; adapters own REST shape. */
|
|
160
242
|
export interface RecipeCapability {
|
|
161
243
|
create(request: RecipeCreateRequest): Promise<RecipeReceipt>;
|
|
162
|
-
publish(recipeId: string): Promise<RecipeReceipt>;
|
|
244
|
+
publish(recipeId: string, options?: RecipePublishOptions): Promise<RecipeReceipt>;
|
|
163
245
|
get(recipeId: string): Promise<RecipeFetchReceipt>;
|
|
164
246
|
express(recipeId: string, request?: RecipeExpressRequest): Promise<RecipeExpressionReceipt>;
|
|
165
247
|
}
|
|
166
|
-
export type HubCapabilityName = 'publish' | 'fetch' | 'search' | 'task' | 'mailbox' | 'auth' | 'audit' | 'air_gap' | 'tenant_isolation' | 'marketplace' | 'economy' | 'questions' | 'recipes' | 'agent_directory';
|
|
248
|
+
export type HubCapabilityName = 'publish' | 'fetch' | 'search' | 'task' | 'mailbox' | 'auth' | 'audit' | 'air_gap' | 'tenant_isolation' | 'marketplace' | 'economy' | 'questions' | 'recipes' | 'agent_directory' | 'learning_assets';
|
|
167
249
|
/** hub 能力清单(可选). core 据此动态适配 UI/行为, "按需耦合". */
|
|
168
250
|
export interface HubManifest {
|
|
169
251
|
capabilities: HubCapabilityName[] | string[];
|
|
@@ -201,6 +283,7 @@ export interface HttpRequestLike {
|
|
|
201
283
|
method: string;
|
|
202
284
|
path: string;
|
|
203
285
|
body?: string;
|
|
286
|
+
signal?: AbortSignal;
|
|
204
287
|
}
|
|
205
288
|
/**
|
|
206
289
|
* Pluggable auth. Example implementations: public OAuth device token / Ed25519 keypair / enterprise SSO (OIDC/LDAP).
|
|
@@ -222,7 +305,7 @@ export interface HubCapability {
|
|
|
222
305
|
* 异步发布. 公版 /a2a/publish 收 **bundle**[Gene,Capsule,(EvolutionEvent)](一个 cycle 的产物一起发, +GDI);
|
|
223
306
|
* 传单资产=[asset]。core 已 normalizeForPut(算/校验 asset_id), hub 做经济/治理/质量 gate。
|
|
224
307
|
*/
|
|
225
|
-
publish(bundle: AssetRecord[]): Promise<PublishReceipt>;
|
|
308
|
+
publish(bundle: AssetRecord[], options?: PublishOptions): Promise<PublishReceipt>;
|
|
226
309
|
/** 拉取资产. hub 侧排序/scope(公版 GDI, 私有 RBAC); core 不重排. */
|
|
227
310
|
fetch(query: HubQuery): Promise<AssetRecord[]>;
|
|
228
311
|
/** 搜索资产. 与 fetch 同 shape, 差异在 hub 侧召回策略. */
|
|
@@ -231,6 +314,10 @@ export interface HubCapability {
|
|
|
231
314
|
fetchAssetById?(assetId: string): Promise<AssetRecord | null>;
|
|
232
315
|
/** 可选: 报告某个资产被复用后的结果. PHub/enterprise adapter 实现; 不支持时 runtime 应明确降级. */
|
|
233
316
|
recordReuseResult?(report: ReuseResultReport): Promise<ReuseResultReceipt>;
|
|
317
|
+
/** 可选: 列出 hub 端 runtime learning assets. Missing means the adapter does not support this MVP surface. */
|
|
318
|
+
listLearningAssets?(options?: LearningAssetListOptions): Promise<LearningAssetListResult>;
|
|
319
|
+
/** 可选: 上报 learning asset 使用结果. Best-effort; failures must never break solve paths. */
|
|
320
|
+
recordLearningAssetUsage?(report: LearningAssetUsageReport): Promise<LearningAssetUsageReceipt>;
|
|
234
321
|
/**
|
|
235
322
|
* 可选: 发布前 dry-run 校验(公版 POST /a2a/validate). 跑与 publish 相同的 hub 端质量门禁 + 内容安全扫描,
|
|
236
323
|
* 但不落库、不计费; 经由 Proxy 暴露时调用方需先执行与 publish 相同的客户端脱敏/泄漏拦截.
|
package/dist/hub/fake.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HubCapability, PublishReceipt, AgentEvent, TaskEvent, AuthProvider, HubQuery, AssetRecord, TaskCompleteContext } from './capability.js';
|
|
1
|
+
import type { HubCapability, PublishReceipt, AgentEvent, TaskEvent, AuthProvider, HubQuery, AssetRecord, TaskCompleteContext, PublishOptions } from './capability.js';
|
|
2
2
|
export interface FakeHubOptions {
|
|
3
3
|
/** 脚本化 publish gate: 返回 reject/quarantine 以测 PublishReceipt 终态路径. */
|
|
4
4
|
publishGate?: (asset: AssetRecord) => Pick<PublishReceipt, 'status' | 'reason' | 'terminal'>;
|
|
@@ -28,7 +28,7 @@ export declare class FakeHubCapability implements HubCapability {
|
|
|
28
28
|
constructor(opts?: FakeHubOptions);
|
|
29
29
|
/** 测试注入: 排一条 inbound 事件供 poll 拉. */
|
|
30
30
|
seedInbound(e: AgentEvent): void;
|
|
31
|
-
publish(bundle: AssetRecord[]): Promise<PublishReceipt>;
|
|
31
|
+
publish(bundle: AssetRecord[], _options?: PublishOptions): Promise<PublishReceipt>;
|
|
32
32
|
fetch(query: HubQuery): Promise<AssetRecord[]>;
|
|
33
33
|
search(query: HubQuery): Promise<AssetRecord[]>;
|
|
34
34
|
task: {
|
package/dist/hub/fake.js
CHANGED
|
@@ -26,7 +26,7 @@ export class FakeHubCapability {
|
|
|
26
26
|
}
|
|
27
27
|
/** 测试注入: 排一条 inbound 事件供 poll 拉. */
|
|
28
28
|
seedInbound(e) { this.inbox.push(e); }
|
|
29
|
-
async publish(bundle) {
|
|
29
|
+
async publish(bundle, _options) {
|
|
30
30
|
const assetIds = bundle.map((a) => computeAssetId(a));
|
|
31
31
|
const gate = this.opts.publishGate?.(bundle[0] ?? {}) ?? { status: 'accepted' };
|
|
32
32
|
if (gate.status === 'accepted')
|
|
@@ -54,6 +54,10 @@ export interface QuestionGenerationResult {
|
|
|
54
54
|
state: QuestionGeneratorState;
|
|
55
55
|
changed: boolean;
|
|
56
56
|
}
|
|
57
|
-
export
|
|
57
|
+
export interface TopicKeywordOptions {
|
|
58
|
+
minOccurrences?: number;
|
|
59
|
+
preserveSourceOrder?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export declare function extractTopicKeywords(transcript: string | undefined, memory: string | undefined, max?: number, opts?: TopicKeywordOptions): string[];
|
|
58
62
|
export declare function generateQuestions(input?: GenerateQuestionsInput): QuestionGenerationResult;
|
|
59
63
|
export declare function generateUrgentQuestions(input?: GenerateUrgentQuestionsInput): QuestionGenerationResult;
|