@higher.archi/boe 1.0.26 → 1.0.28
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/engines/decay/compiler.d.ts +11 -0
- package/dist/engines/decay/compiler.d.ts.map +1 -0
- package/dist/engines/decay/compiler.js +216 -0
- package/dist/engines/decay/compiler.js.map +1 -0
- package/dist/engines/decay/engine.d.ts +48 -0
- package/dist/engines/decay/engine.d.ts.map +1 -0
- package/dist/engines/decay/engine.js +90 -0
- package/dist/engines/decay/engine.js.map +1 -0
- package/dist/engines/decay/index.d.ts +9 -0
- package/dist/engines/decay/index.d.ts.map +1 -0
- package/dist/engines/decay/index.js +21 -0
- package/dist/engines/decay/index.js.map +1 -0
- package/dist/engines/decay/strategy.d.ts +19 -0
- package/dist/engines/decay/strategy.d.ts.map +1 -0
- package/dist/engines/decay/strategy.js +284 -0
- package/dist/engines/decay/strategy.js.map +1 -0
- package/dist/engines/decay/types.d.ts +148 -0
- package/dist/engines/decay/types.d.ts.map +1 -0
- package/dist/engines/decay/types.js +39 -0
- package/dist/engines/decay/types.js.map +1 -0
- package/dist/engines/negotiation/compiler.d.ts +11 -0
- package/dist/engines/negotiation/compiler.d.ts.map +1 -0
- package/dist/engines/negotiation/compiler.js +177 -0
- package/dist/engines/negotiation/compiler.js.map +1 -0
- package/dist/engines/negotiation/engine.d.ts +46 -0
- package/dist/engines/negotiation/engine.d.ts.map +1 -0
- package/dist/engines/negotiation/engine.js +88 -0
- package/dist/engines/negotiation/engine.js.map +1 -0
- package/dist/engines/negotiation/index.d.ts +8 -0
- package/dist/engines/negotiation/index.d.ts.map +1 -0
- package/dist/engines/negotiation/index.js +17 -0
- package/dist/engines/negotiation/index.js.map +1 -0
- package/dist/engines/negotiation/strategy.d.ts +18 -0
- package/dist/engines/negotiation/strategy.d.ts.map +1 -0
- package/dist/engines/negotiation/strategy.js +439 -0
- package/dist/engines/negotiation/strategy.js.map +1 -0
- package/dist/engines/negotiation/types.d.ts +179 -0
- package/dist/engines/negotiation/types.d.ts.map +1 -0
- package/dist/engines/negotiation/types.js +10 -0
- package/dist/engines/negotiation/types.js.map +1 -0
- package/dist/engines/sentiment/engine.d.ts +25 -1
- package/dist/engines/sentiment/engine.d.ts.map +1 -1
- package/dist/engines/sentiment/engine.js +119 -0
- package/dist/engines/sentiment/engine.js.map +1 -1
- package/dist/engines/sentiment/index.d.ts +1 -1
- package/dist/engines/sentiment/index.d.ts.map +1 -1
- package/dist/engines/sentiment/index.js.map +1 -1
- package/dist/engines/sentiment/strategy.d.ts +2 -0
- package/dist/engines/sentiment/strategy.d.ts.map +1 -1
- package/dist/engines/sentiment/strategy.js +7 -8
- package/dist/engines/sentiment/strategy.js.map +1 -1
- package/dist/engines/sentiment/types.d.ts +9 -0
- package/dist/engines/sentiment/types.d.ts.map +1 -1
- package/dist/engines/sentiment/types.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/engines/decay/compiler.ts +276 -0
- package/src/engines/decay/engine.ts +119 -0
- package/src/engines/decay/index.ts +42 -0
- package/src/engines/decay/strategy.ts +400 -0
- package/src/engines/decay/types.ts +221 -0
- package/src/engines/negotiation/compiler.ts +229 -0
- package/src/engines/negotiation/engine.ts +117 -0
- package/src/engines/negotiation/index.ts +42 -0
- package/src/engines/negotiation/strategy.ts +587 -0
- package/src/engines/negotiation/types.ts +244 -0
- package/src/engines/sentiment/engine.ts +157 -1
- package/src/engines/sentiment/index.ts +2 -1
- package/src/engines/sentiment/strategy.ts +12 -9
- package/src/engines/sentiment/types.ts +10 -0
- package/src/index.ts +70 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Negotiation Engine Types
|
|
3
|
+
*
|
|
4
|
+
* Two-party negotiation engine that analyzes zones of possible agreement,
|
|
5
|
+
* plans concession strategies, and optimizes deal packages across
|
|
6
|
+
* multiple dimensions.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { SemanticPriority } from '../utility/types';
|
|
10
|
+
|
|
11
|
+
// ========================================
|
|
12
|
+
// Semantic Types
|
|
13
|
+
// ========================================
|
|
14
|
+
|
|
15
|
+
/** Negotiation algorithm to use */
|
|
16
|
+
export type NegotiationStrategy = 'zopa-analysis' | 'concession-planning' | 'package-optimization';
|
|
17
|
+
|
|
18
|
+
/** Concession aggressiveness style */
|
|
19
|
+
export type ConcessionStyle = 'aggressive' | 'moderate' | 'collaborative';
|
|
20
|
+
|
|
21
|
+
/** Outcome of a negotiation analysis */
|
|
22
|
+
export type DealOutcome = 'agreed' | 'no-zopa' | 'batna-preferred';
|
|
23
|
+
|
|
24
|
+
/** Whether higher or lower values are preferred for a dimension */
|
|
25
|
+
export type DimensionDirection = 'higher-is-better' | 'lower-is-better';
|
|
26
|
+
|
|
27
|
+
// ========================================
|
|
28
|
+
// Dimension & Party Types
|
|
29
|
+
// ========================================
|
|
30
|
+
|
|
31
|
+
/** A single negotiable dimension (e.g. price, delivery time) */
|
|
32
|
+
export type NegotiationDimension = {
|
|
33
|
+
id: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
unit?: string;
|
|
36
|
+
direction: DimensionDirection;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** A party's position on a single dimension */
|
|
40
|
+
export type PartyPosition = {
|
|
41
|
+
dimensionId: string;
|
|
42
|
+
ideal: number;
|
|
43
|
+
acceptable: number;
|
|
44
|
+
walkaway: number;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** A negotiating party with positions across all dimensions */
|
|
48
|
+
export type PartyProfile = {
|
|
49
|
+
id: string;
|
|
50
|
+
name?: string;
|
|
51
|
+
positions: PartyPosition[];
|
|
52
|
+
batna?: number;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** Weight function mapping a dimension to its importance for a party */
|
|
56
|
+
export type ValueFunction = {
|
|
57
|
+
dimensionId: string;
|
|
58
|
+
weight: number | SemanticPriority;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// ========================================
|
|
62
|
+
// Compiled Dimension & Party Types
|
|
63
|
+
// ========================================
|
|
64
|
+
|
|
65
|
+
/** Compiled value function with resolved numeric weight */
|
|
66
|
+
export type CompiledValueFunction = {
|
|
67
|
+
dimensionId: string;
|
|
68
|
+
weight: number; // normalized to sum to 1.0 per party
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/** Compiled party profile with resolved weights */
|
|
72
|
+
export type CompiledPartyProfile = {
|
|
73
|
+
id: string;
|
|
74
|
+
name?: string;
|
|
75
|
+
positions: PartyPosition[];
|
|
76
|
+
batna?: number;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// ========================================
|
|
80
|
+
// Strategy-Specific Config Types
|
|
81
|
+
// ========================================
|
|
82
|
+
|
|
83
|
+
export type ZopaAnalysisConfig = {
|
|
84
|
+
resolution?: number; // default: 100
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export type ConcessionPlanningConfig = {
|
|
88
|
+
style?: ConcessionStyle; // default: 'moderate'
|
|
89
|
+
rounds?: number; // default: 5
|
|
90
|
+
startingPosition?: 'ideal' | 'midpoint'; // default: 'ideal'
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export type PackageOptimizationConfig = {
|
|
94
|
+
sampleSize?: number; // default: 1000
|
|
95
|
+
objectiveWeights?: {
|
|
96
|
+
closeProb: number;
|
|
97
|
+
margin: number;
|
|
98
|
+
}; // default: { closeProb: 0.6, margin: 0.4 }
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// ========================================
|
|
102
|
+
// Source RuleSet Types (Discriminated Union)
|
|
103
|
+
// ========================================
|
|
104
|
+
|
|
105
|
+
type NegotiationRuleSetBase = {
|
|
106
|
+
id: string;
|
|
107
|
+
name?: string;
|
|
108
|
+
mode: 'negotiation';
|
|
109
|
+
dimensions: NegotiationDimension[];
|
|
110
|
+
parties: [PartyProfile, PartyProfile];
|
|
111
|
+
valueWeights: Record<string, ValueFunction[]>;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/** ZOPA analysis: compute zones of possible agreement per dimension */
|
|
115
|
+
export type ZopaAnalysisRuleSet = NegotiationRuleSetBase & {
|
|
116
|
+
strategy: 'zopa-analysis';
|
|
117
|
+
config?: ZopaAnalysisConfig;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/** Concession planning: simulate round-by-round concession trajectories */
|
|
121
|
+
export type ConcessionPlanningRuleSet = NegotiationRuleSetBase & {
|
|
122
|
+
strategy: 'concession-planning';
|
|
123
|
+
config?: ConcessionPlanningConfig;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/** Package optimization: find optimal deal packages within the ZOPA */
|
|
127
|
+
export type PackageOptimizationRuleSet = NegotiationRuleSetBase & {
|
|
128
|
+
strategy: 'package-optimization';
|
|
129
|
+
config?: PackageOptimizationConfig;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export type NegotiationRuleSet =
|
|
133
|
+
| ZopaAnalysisRuleSet
|
|
134
|
+
| ConcessionPlanningRuleSet
|
|
135
|
+
| PackageOptimizationRuleSet;
|
|
136
|
+
|
|
137
|
+
// ========================================
|
|
138
|
+
// Compiled RuleSet Types
|
|
139
|
+
// ========================================
|
|
140
|
+
|
|
141
|
+
type CompiledNegotiationRuleSetBase = {
|
|
142
|
+
id: string;
|
|
143
|
+
name?: string;
|
|
144
|
+
mode: 'negotiation';
|
|
145
|
+
dimensions: NegotiationDimension[];
|
|
146
|
+
parties: [CompiledPartyProfile, CompiledPartyProfile];
|
|
147
|
+
valueWeights: Record<string, CompiledValueFunction[]>;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export type CompiledZopaAnalysisRuleSet = CompiledNegotiationRuleSetBase & {
|
|
151
|
+
strategy: 'zopa-analysis';
|
|
152
|
+
config: {
|
|
153
|
+
resolution: number;
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export type CompiledConcessionPlanningRuleSet = CompiledNegotiationRuleSetBase & {
|
|
158
|
+
strategy: 'concession-planning';
|
|
159
|
+
config: {
|
|
160
|
+
style: ConcessionStyle;
|
|
161
|
+
rounds: number;
|
|
162
|
+
startingPosition: 'ideal' | 'midpoint';
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export type CompiledPackageOptimizationRuleSet = CompiledNegotiationRuleSetBase & {
|
|
167
|
+
strategy: 'package-optimization';
|
|
168
|
+
config: {
|
|
169
|
+
sampleSize: number;
|
|
170
|
+
objectiveWeights: {
|
|
171
|
+
closeProb: number;
|
|
172
|
+
margin: number;
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export type CompiledNegotiationRuleSet =
|
|
178
|
+
| CompiledZopaAnalysisRuleSet
|
|
179
|
+
| CompiledConcessionPlanningRuleSet
|
|
180
|
+
| CompiledPackageOptimizationRuleSet;
|
|
181
|
+
|
|
182
|
+
// ========================================
|
|
183
|
+
// Result Types
|
|
184
|
+
// ========================================
|
|
185
|
+
|
|
186
|
+
/** Range of agreement for a single dimension */
|
|
187
|
+
export type ZopaRange = {
|
|
188
|
+
dimensionId: string;
|
|
189
|
+
lower: number;
|
|
190
|
+
upper: number;
|
|
191
|
+
size: number;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/** A single round's concession step for one party */
|
|
195
|
+
export type ConcessionStep = {
|
|
196
|
+
round: number;
|
|
197
|
+
partyId: string;
|
|
198
|
+
offers: Record<string, number>;
|
|
199
|
+
totalValue: number;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/** A candidate deal package */
|
|
203
|
+
export type PackageCandidate = {
|
|
204
|
+
dimensions: Record<string, number>;
|
|
205
|
+
partyAValue: number;
|
|
206
|
+
partyBValue: number;
|
|
207
|
+
closeProbability: number;
|
|
208
|
+
marginScore: number;
|
|
209
|
+
compositeScore: number;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/** Full negotiation result */
|
|
213
|
+
export type NegotiationResult = {
|
|
214
|
+
outcome: DealOutcome;
|
|
215
|
+
zopa?: {
|
|
216
|
+
ranges: ZopaRange[];
|
|
217
|
+
hasAgreement: boolean;
|
|
218
|
+
zopaVolume: number;
|
|
219
|
+
};
|
|
220
|
+
concessionPlan?: {
|
|
221
|
+
steps: ConcessionStep[];
|
|
222
|
+
convergenceRound?: number;
|
|
223
|
+
finalDeal?: Record<string, number>;
|
|
224
|
+
};
|
|
225
|
+
recommendedPackage?: PackageCandidate;
|
|
226
|
+
allPackages?: PackageCandidate[];
|
|
227
|
+
batnaComparison: Record<string, {
|
|
228
|
+
dealValue: number;
|
|
229
|
+
batnaValue: number;
|
|
230
|
+
surplus: number;
|
|
231
|
+
}>;
|
|
232
|
+
strategy: NegotiationStrategy;
|
|
233
|
+
executionTimeMs: number;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// ========================================
|
|
237
|
+
// Runtime Types
|
|
238
|
+
// ========================================
|
|
239
|
+
|
|
240
|
+
/** Runtime options for negotiation execution */
|
|
241
|
+
export type NegotiationOptions = {
|
|
242
|
+
onStep?: (step: ConcessionStep) => void;
|
|
243
|
+
onPackage?: (candidate: PackageCandidate) => void;
|
|
244
|
+
};
|
|
@@ -25,14 +25,40 @@ import {
|
|
|
25
25
|
import type {
|
|
26
26
|
CompiledSentimentRuleSet,
|
|
27
27
|
SentimentOptions,
|
|
28
|
-
SentimentResult
|
|
28
|
+
SentimentResult,
|
|
29
|
+
SentimentStrategy,
|
|
30
|
+
IngestResult,
|
|
31
|
+
AspectResult
|
|
29
32
|
} from './types';
|
|
33
|
+
import { resolveSentimentLabel } from './types';
|
|
30
34
|
|
|
31
35
|
import { SentimentExecutor } from './strategy';
|
|
32
36
|
|
|
37
|
+
function round(value: number, decimals: number): number {
|
|
38
|
+
const factor = Math.pow(10, decimals);
|
|
39
|
+
return Math.round(value * factor) / factor;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Internal accumulator for streaming ingest */
|
|
43
|
+
type StreamState = {
|
|
44
|
+
ruleSetId: string;
|
|
45
|
+
strategy: SentimentStrategy;
|
|
46
|
+
compoundSum: number;
|
|
47
|
+
count: number;
|
|
48
|
+
posTokens: number;
|
|
49
|
+
negTokens: number;
|
|
50
|
+
neuTokens: number;
|
|
51
|
+
totalTokens: number;
|
|
52
|
+
/** Per-aspect accumulators (aspect-based only) */
|
|
53
|
+
aspectAccumulators: Map<string, { compoundSum: number; count: number }>;
|
|
54
|
+
/** Last computed aggregate result (without item-specific fields) */
|
|
55
|
+
lastResult: SentimentResult | null;
|
|
56
|
+
};
|
|
57
|
+
|
|
33
58
|
export class SentimentEngine {
|
|
34
59
|
private wm: WorkingMemory;
|
|
35
60
|
private strategy: SentimentExecutor;
|
|
61
|
+
private _stream: StreamState | null = null;
|
|
36
62
|
|
|
37
63
|
constructor(workingMemory?: WorkingMemory) {
|
|
38
64
|
this.wm = workingMemory ?? new WorkingMemory();
|
|
@@ -108,6 +134,136 @@ export class SentimentEngine {
|
|
|
108
134
|
return this.strategy.run(ruleSet, this.wm, options);
|
|
109
135
|
}
|
|
110
136
|
|
|
137
|
+
// ========================================
|
|
138
|
+
// Streaming Ingest
|
|
139
|
+
// ========================================
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Score a single text incrementally without touching working memory.
|
|
143
|
+
*
|
|
144
|
+
* Each call scores the provided text, updates a running accumulator,
|
|
145
|
+
* and returns both the individual score and the current aggregate.
|
|
146
|
+
* The compiled ruleset must stay the same across calls (matched by id).
|
|
147
|
+
* Call `resetStream()` to start a new stream.
|
|
148
|
+
*
|
|
149
|
+
* @param text - Raw text to score
|
|
150
|
+
* @param ruleSet - Compiled sentiment ruleset
|
|
151
|
+
* @param options - Runtime options (onToken callback)
|
|
152
|
+
* @returns IngestResult with item-level and aggregate scores
|
|
153
|
+
*/
|
|
154
|
+
ingest(
|
|
155
|
+
text: string,
|
|
156
|
+
ruleSet: CompiledSentimentRuleSet,
|
|
157
|
+
options: SentimentOptions = {}
|
|
158
|
+
): IngestResult {
|
|
159
|
+
// Initialize or validate stream state
|
|
160
|
+
if (!this._stream || this._stream.ruleSetId !== ruleSet.id) {
|
|
161
|
+
this._stream = {
|
|
162
|
+
ruleSetId: ruleSet.id,
|
|
163
|
+
strategy: ruleSet.strategy,
|
|
164
|
+
compoundSum: 0,
|
|
165
|
+
count: 0,
|
|
166
|
+
posTokens: 0,
|
|
167
|
+
negTokens: 0,
|
|
168
|
+
neuTokens: 0,
|
|
169
|
+
totalTokens: 0,
|
|
170
|
+
aspectAccumulators: new Map(),
|
|
171
|
+
lastResult: null
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Score just this text
|
|
176
|
+
const itemResult = this.strategy.scoreText(ruleSet, text, options);
|
|
177
|
+
|
|
178
|
+
// Update running accumulators
|
|
179
|
+
const s = this._stream;
|
|
180
|
+
s.compoundSum += itemResult.compound;
|
|
181
|
+
s.count++;
|
|
182
|
+
|
|
183
|
+
// Update token proportion accumulators
|
|
184
|
+
const itemTokenTotal = itemResult.tokens?.length
|
|
185
|
+
?? itemResult.sentences?.reduce((n, sent) => n + sent.tokens.length, 0)
|
|
186
|
+
?? itemResult.aspects?.reduce((n, a) => n + a.sentences.reduce((m, sent) => m + sent.tokens.length, 0), 0)
|
|
187
|
+
?? 0;
|
|
188
|
+
|
|
189
|
+
if (itemTokenTotal > 0) {
|
|
190
|
+
s.posTokens += Math.round(itemResult.positive * itemTokenTotal);
|
|
191
|
+
s.negTokens += Math.round(itemResult.negative * itemTokenTotal);
|
|
192
|
+
s.neuTokens += Math.round(itemResult.neutral * itemTokenTotal);
|
|
193
|
+
s.totalTokens += itemTokenTotal;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Update aspect accumulators if aspect-based
|
|
197
|
+
if (itemResult.aspects) {
|
|
198
|
+
for (const aspect of itemResult.aspects) {
|
|
199
|
+
if (aspect.sentences.length === 0) continue;
|
|
200
|
+
let acc = s.aspectAccumulators.get(aspect.aspect);
|
|
201
|
+
if (!acc) {
|
|
202
|
+
acc = { compoundSum: 0, count: 0 };
|
|
203
|
+
s.aspectAccumulators.set(aspect.aspect, acc);
|
|
204
|
+
}
|
|
205
|
+
acc.compoundSum += aspect.compound;
|
|
206
|
+
acc.count++;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Compute aggregate
|
|
211
|
+
const aggCompound = round(s.compoundSum / s.count, 4);
|
|
212
|
+
const aggPositive = s.totalTokens > 0 ? round(s.posTokens / s.totalTokens, 4) : 0;
|
|
213
|
+
const aggNegative = s.totalTokens > 0 ? round(s.negTokens / s.totalTokens, 4) : 0;
|
|
214
|
+
const aggNeutral = s.totalTokens > 0 ? round(s.neuTokens / s.totalTokens, 4) : 0;
|
|
215
|
+
|
|
216
|
+
// Build aggregate aspect results if applicable
|
|
217
|
+
let aggAspects: AspectResult[] | undefined;
|
|
218
|
+
if (s.aspectAccumulators.size > 0) {
|
|
219
|
+
aggAspects = [];
|
|
220
|
+
for (const [aspect, acc] of s.aspectAccumulators) {
|
|
221
|
+
const aspectCompound = round(acc.compoundSum / acc.count, 4);
|
|
222
|
+
aggAspects.push({
|
|
223
|
+
aspect,
|
|
224
|
+
compound: aspectCompound,
|
|
225
|
+
label: resolveSentimentLabel(aspectCompound),
|
|
226
|
+
sentences: []
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const aggregate: SentimentResult = {
|
|
232
|
+
compound: aggCompound,
|
|
233
|
+
label: resolveSentimentLabel(aggCompound),
|
|
234
|
+
positive: aggPositive,
|
|
235
|
+
negative: aggNegative,
|
|
236
|
+
neutral: aggNeutral,
|
|
237
|
+
aspects: aggAspects,
|
|
238
|
+
strategy: ruleSet.strategy,
|
|
239
|
+
executionTimeMs: itemResult.executionTimeMs
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
s.lastResult = aggregate;
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
...aggregate,
|
|
246
|
+
itemCompound: itemResult.compound,
|
|
247
|
+
itemLabel: itemResult.label,
|
|
248
|
+
totalIngested: s.count
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Get the current streaming aggregate without ingesting new text.
|
|
254
|
+
* Returns null if no texts have been ingested yet.
|
|
255
|
+
*/
|
|
256
|
+
getStreamResult(): SentimentResult | null {
|
|
257
|
+
return this._stream?.lastResult ?? null;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Reset the streaming accumulator. Does not affect working memory.
|
|
262
|
+
*/
|
|
263
|
+
resetStream(): void {
|
|
264
|
+
this._stream = null;
|
|
265
|
+
}
|
|
266
|
+
|
|
111
267
|
// ========================================
|
|
112
268
|
// Utility Methods
|
|
113
269
|
// ========================================
|
|
@@ -291,23 +291,26 @@ export class SentimentExecutor {
|
|
|
291
291
|
const texts = extractTexts(facts);
|
|
292
292
|
const fullText = texts.join(' ');
|
|
293
293
|
|
|
294
|
-
|
|
294
|
+
return this.scoreText(ruleSet, fullText, options, startTime);
|
|
295
|
+
}
|
|
295
296
|
|
|
297
|
+
/** Score a single text string directly (no WorkingMemory involved) */
|
|
298
|
+
scoreText(
|
|
299
|
+
ruleSet: CompiledSentimentRuleSet,
|
|
300
|
+
text: string,
|
|
301
|
+
options: SentimentOptions = {},
|
|
302
|
+
startTime: number = performance.now()
|
|
303
|
+
): SentimentResult {
|
|
296
304
|
switch (ruleSet.strategy) {
|
|
297
305
|
case 'token-level':
|
|
298
|
-
|
|
299
|
-
break;
|
|
306
|
+
return this.runTokenLevel(ruleSet, text, options, startTime);
|
|
300
307
|
case 'document-level':
|
|
301
|
-
|
|
302
|
-
break;
|
|
308
|
+
return this.runDocumentLevel(ruleSet, text, options, startTime);
|
|
303
309
|
case 'aspect-based':
|
|
304
|
-
|
|
305
|
-
break;
|
|
310
|
+
return this.runAspectBased(ruleSet, text, options, startTime);
|
|
306
311
|
default:
|
|
307
312
|
throw new Error(`Unknown sentiment strategy: '${(ruleSet as any).strategy}'`);
|
|
308
313
|
}
|
|
309
|
-
|
|
310
|
-
return result;
|
|
311
314
|
}
|
|
312
315
|
|
|
313
316
|
// ========================================
|
|
@@ -176,6 +176,16 @@ export type SentimentOptions = {
|
|
|
176
176
|
onToken?: (token: TokenScore) => void;
|
|
177
177
|
};
|
|
178
178
|
|
|
179
|
+
/** Result from ingest() -- includes both the individual text score and the running aggregate */
|
|
180
|
+
export type IngestResult = SentimentResult & {
|
|
181
|
+
/** Compound score for just the ingested text (not the aggregate) */
|
|
182
|
+
itemCompound: number;
|
|
183
|
+
/** Label for just the ingested text */
|
|
184
|
+
itemLabel: SentimentLabel;
|
|
185
|
+
/** Total number of texts ingested so far */
|
|
186
|
+
totalIngested: number;
|
|
187
|
+
};
|
|
188
|
+
|
|
179
189
|
// ========================================
|
|
180
190
|
// Resolver Functions
|
|
181
191
|
// ========================================
|
package/src/index.ts
CHANGED
|
@@ -32,6 +32,8 @@ export { UtilityEngine } from './engines/utility';
|
|
|
32
32
|
export { PricingEngine } from './engines/pricing';
|
|
33
33
|
export { EnsembleEngine } from './engines/ensemble';
|
|
34
34
|
export { SentimentEngine } from './engines/sentiment';
|
|
35
|
+
export { NegotiationEngine } from './engines/negotiation';
|
|
36
|
+
export { DecayEngine } from './engines/decay';
|
|
35
37
|
|
|
36
38
|
// ========================================
|
|
37
39
|
// Core Types & Utilities
|
|
@@ -512,9 +514,76 @@ export type {
|
|
|
512
514
|
SentenceResult,
|
|
513
515
|
AspectResult,
|
|
514
516
|
SentimentResult,
|
|
515
|
-
SentimentOptions
|
|
517
|
+
SentimentOptions,
|
|
518
|
+
IngestResult
|
|
516
519
|
} from './engines/sentiment';
|
|
517
520
|
|
|
521
|
+
// Negotiation
|
|
522
|
+
export {
|
|
523
|
+
NegotiationExecutor,
|
|
524
|
+
compileNegotiationRuleSet,
|
|
525
|
+
negotiationStrategy
|
|
526
|
+
} from './engines/negotiation';
|
|
527
|
+
export type {
|
|
528
|
+
NegotiationStrategy,
|
|
529
|
+
ConcessionStyle,
|
|
530
|
+
DealOutcome,
|
|
531
|
+
DimensionDirection,
|
|
532
|
+
NegotiationDimension,
|
|
533
|
+
PartyPosition,
|
|
534
|
+
PartyProfile,
|
|
535
|
+
ValueFunction,
|
|
536
|
+
CompiledValueFunction,
|
|
537
|
+
CompiledPartyProfile,
|
|
538
|
+
ZopaAnalysisConfig,
|
|
539
|
+
ConcessionPlanningConfig,
|
|
540
|
+
PackageOptimizationConfig,
|
|
541
|
+
ZopaAnalysisRuleSet,
|
|
542
|
+
ConcessionPlanningRuleSet,
|
|
543
|
+
PackageOptimizationRuleSet,
|
|
544
|
+
NegotiationRuleSet,
|
|
545
|
+
CompiledZopaAnalysisRuleSet,
|
|
546
|
+
CompiledConcessionPlanningRuleSet,
|
|
547
|
+
CompiledPackageOptimizationRuleSet,
|
|
548
|
+
CompiledNegotiationRuleSet,
|
|
549
|
+
ZopaRange,
|
|
550
|
+
ConcessionStep,
|
|
551
|
+
PackageCandidate,
|
|
552
|
+
NegotiationResult,
|
|
553
|
+
NegotiationOptions
|
|
554
|
+
} from './engines/negotiation';
|
|
555
|
+
|
|
556
|
+
// Decay
|
|
557
|
+
export {
|
|
558
|
+
DecayExecutor,
|
|
559
|
+
compileDecayRuleSet,
|
|
560
|
+
decayStrategy,
|
|
561
|
+
URGENCY_THRESHOLDS,
|
|
562
|
+
resolveUrgencyTier
|
|
563
|
+
} from './engines/decay';
|
|
564
|
+
export type {
|
|
565
|
+
DecayStrategy,
|
|
566
|
+
UrgencyTier,
|
|
567
|
+
ReEngagementEffect,
|
|
568
|
+
DecayAggregation,
|
|
569
|
+
DecayDimension,
|
|
570
|
+
CompiledDecayDimension,
|
|
571
|
+
ReEngagementRule,
|
|
572
|
+
SingleDimensionDecayRuleSet,
|
|
573
|
+
MultiDimensionDecayRuleSet,
|
|
574
|
+
EventDrivenDecayRuleSet,
|
|
575
|
+
DecayRuleSet,
|
|
576
|
+
CompiledSingleDimensionDecayRuleSet,
|
|
577
|
+
CompiledMultiDimensionDecayRuleSet,
|
|
578
|
+
CompiledEventDrivenDecayRuleSet,
|
|
579
|
+
CompiledDecayRuleSet,
|
|
580
|
+
DimensionDecayResult,
|
|
581
|
+
ReEngagementEvent,
|
|
582
|
+
EntityDecayResult,
|
|
583
|
+
DecayResult,
|
|
584
|
+
DecayOptions
|
|
585
|
+
} from './engines/decay';
|
|
586
|
+
|
|
518
587
|
// ========================================
|
|
519
588
|
// Utility Functions (from old modules, re-exported for convenience)
|
|
520
589
|
// ========================================
|