@dsh-enhanced/assistant-growth-driver 0.1.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +200 -0
- package/cordis.patch.yml +3 -0
- package/lib/config.d.ts +122 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +207 -0
- package/lib/config.js.map +1 -0
- package/lib/deposit.d.ts +53 -0
- package/lib/deposit.d.ts.map +1 -0
- package/lib/deposit.js +55 -0
- package/lib/deposit.js.map +1 -0
- package/lib/growth-agent.d.ts +63 -0
- package/lib/growth-agent.d.ts.map +1 -0
- package/lib/growth-agent.js +563 -0
- package/lib/growth-agent.js.map +1 -0
- package/lib/index.d.ts +73 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +427 -0
- package/lib/index.js.map +1 -0
- package/lib/source-edits.d.ts +22 -0
- package/lib/source-edits.d.ts.map +1 -0
- package/lib/source-edits.js +77 -0
- package/lib/source-edits.js.map +1 -0
- package/lib/source-port.d.ts +139 -0
- package/lib/source-port.d.ts.map +1 -0
- package/lib/source-port.js +31 -0
- package/lib/source-port.js.map +1 -0
- package/lib/usage-runtime.d.ts +58 -0
- package/lib/usage-runtime.d.ts.map +1 -0
- package/lib/usage-runtime.js +258 -0
- package/lib/usage-runtime.js.map +1 -0
- package/lib/usage-store.d.ts +49 -0
- package/lib/usage-store.d.ts.map +1 -0
- package/lib/usage-store.js +121 -0
- package/lib/usage-store.js.map +1 -0
- package/lib/version.d.ts +2 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +2 -0
- package/lib/version.js.map +1 -0
- package/package.json +142 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Context, Service } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
3
|
+
import { Config, normalizeConfig, type AssistantGrowthDriverConfig } from './config.js';
|
|
4
|
+
import { type GrowthAgentRunResult } from './growth-agent.js';
|
|
5
|
+
import { version } from './version.js';
|
|
6
|
+
export declare const name = "dsh-enhanced-assistant-growth-driver";
|
|
7
|
+
export { version, Config, normalizeConfig };
|
|
8
|
+
export type { AssistantGrowthDriverConfig } from './config.js';
|
|
9
|
+
export type { GrowthAuthority } from './deposit.js';
|
|
10
|
+
/**
|
|
11
|
+
* Outcome of the owner-anchored workflow track in one wake. This track is
|
|
12
|
+
* purely Host-local (Delivery re-reads Goals and writes a paused candidate; no
|
|
13
|
+
* model call), so it is reported separately from the model-driven skill track.
|
|
14
|
+
* `stopped` is non-null when a fail-closed Delivery/Goals condition halted the
|
|
15
|
+
* track before the rate limit was reached.
|
|
16
|
+
*/
|
|
17
|
+
export interface OwnerAnchoredWakeSummary {
|
|
18
|
+
readonly considered: number;
|
|
19
|
+
readonly attempted: number;
|
|
20
|
+
readonly recorded: number;
|
|
21
|
+
readonly replayed: number;
|
|
22
|
+
readonly abstained: number;
|
|
23
|
+
readonly stopped: string | null;
|
|
24
|
+
}
|
|
25
|
+
export interface GrowthWakeHealth {
|
|
26
|
+
readonly lastWakeAt: number | null;
|
|
27
|
+
readonly outcome: 'never-run' | 'ran' | 'skipped' | 'failed';
|
|
28
|
+
readonly reason: string | null;
|
|
29
|
+
readonly run: GrowthAgentRunResult | null;
|
|
30
|
+
readonly ownerAnchored?: OwnerAnchoredWakeSummary | undefined;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Opt-in, fail-closed periodic growth driver. Every wake:
|
|
34
|
+
* 1. re-anchors the frozen configured owner scope against Delivery;
|
|
35
|
+
* 2. freezes the conversation's model (or explicit fixed override), applying
|
|
36
|
+
* supplier-specific credential/contract checks only to that supplier;
|
|
37
|
+
* 3. optionally reserves an owner-configured background budget;
|
|
38
|
+
* 4. runs ONE bounded background agent that may only read history and
|
|
39
|
+
* propose a paused skill candidate through Host re-verification.
|
|
40
|
+
* Any failed precondition skips the wake with a health reason: the driver
|
|
41
|
+
* never changes route, never falls back to another model and never self-enables.
|
|
42
|
+
*/
|
|
43
|
+
export declare class AssistantGrowthDriverService extends Service {
|
|
44
|
+
#private;
|
|
45
|
+
static Config: import("@deepseek-ai/schemastery").default<AssistantGrowthDriverConfig>;
|
|
46
|
+
static inject: string[];
|
|
47
|
+
constructor(ctx: Context, input?: AssistantGrowthDriverConfig);
|
|
48
|
+
health: () => GrowthWakeHealth;
|
|
49
|
+
usageHealth: () => {
|
|
50
|
+
enabled: boolean;
|
|
51
|
+
connected: boolean;
|
|
52
|
+
lastScanAt: number | null;
|
|
53
|
+
lastError: string | null;
|
|
54
|
+
counts: Readonly<Record<string, number>>;
|
|
55
|
+
} | {
|
|
56
|
+
enabled: boolean;
|
|
57
|
+
connected: false;
|
|
58
|
+
};
|
|
59
|
+
/** Run one wake immediately (also used by tests / an explicit Host trigger). */
|
|
60
|
+
wake: (input?: {
|
|
61
|
+
sourceAgent?: Agent;
|
|
62
|
+
}) => Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
export declare function apply(ctx: Context, input?: AssistantGrowthDriverConfig): void;
|
|
65
|
+
declare const _default: {
|
|
66
|
+
name: string;
|
|
67
|
+
Config: import("@deepseek-ai/schemastery").default<AssistantGrowthDriverConfig>;
|
|
68
|
+
inject: string[];
|
|
69
|
+
apply: typeof apply;
|
|
70
|
+
version: string;
|
|
71
|
+
};
|
|
72
|
+
export default _default;
|
|
73
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,KAAK,EAAE,KAAK,EAAkB,MAAM,wBAAwB,CAAA;AAMnE,OAAO,EAAE,MAAM,EAAuB,eAAe,EAAE,KAAK,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAE5G,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAItC,eAAO,MAAM,IAAI,yCAAyC,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAA;AAC3C,YAAY,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAC9D,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAA;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,GAAG,EAAE,oBAAoB,GAAG,IAAI,CAAA;IAIzC,QAAQ,CAAC,aAAa,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAA;CAC9D;AAuBD;;;;;;;;;;GAUG;AACH,qBAAa,4BAA6B,SAAQ,OAAO;;IACvD,MAAM,CAAC,MAAM,0EAAS;IACtB,MAAM,CAAC,MAAM,WAAsH;gBAUvH,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,2BAAgC;IAuGjE,MAAM,QAAO,gBAAgB,CAAgB;IAC7C,WAAW;;;;;;;;;MAAmG;IAgB9G,gFAAgF;IAChF,IAAI,GAAI,QAAO;QAAE,WAAW,CAAC,EAAE,KAAK,CAAA;KAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAQ1D;CAsOF;AAMD,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,2BAAgC,GAAG,IAAI,CAEjF;;;;;;;;AAED,wBAA4F"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { Context, Service } from '@deepseek-ai/cordis';
|
|
3
|
+
import { credentialRef } from '@deepseek-ai/dsh-credentials';
|
|
4
|
+
import { ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
5
|
+
import { Config, DEFAULT_API_KEY_ENV, normalizeConfig } from './config.js';
|
|
6
|
+
import { mintGrowthAuthority } from './deposit.js';
|
|
7
|
+
import { runGrowthAgent } from './growth-agent.js';
|
|
8
|
+
import { version } from './version.js';
|
|
9
|
+
import { UsageLearningRuntime } from './usage-runtime.js';
|
|
10
|
+
export const name = 'dsh-enhanced-assistant-growth-driver';
|
|
11
|
+
export { version, Config, normalizeConfig };
|
|
12
|
+
/**
|
|
13
|
+
* cordis 4.0.2 hands cross-plugin service consumers a traceable Proxy whose
|
|
14
|
+
* shadow-method trap rebinds `this` to a second Proxy; ES #private brand
|
|
15
|
+
* checks then throw ("Cannot read private member … from an object whose class
|
|
16
|
+
* did not declare it"). The library exposes the raw instance through
|
|
17
|
+
* Symbol.for('cordis.original') on every traceable Proxy; plain-object mocks
|
|
18
|
+
* have no such marker and pass through unchanged.
|
|
19
|
+
*/
|
|
20
|
+
const CORDIS_ORIGINAL = Symbol.for('cordis.original');
|
|
21
|
+
function unwrapService(service) {
|
|
22
|
+
return service?.[CORDIS_ORIGINAL] ?? service;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Opt-in, fail-closed periodic growth driver. Every wake:
|
|
26
|
+
* 1. re-anchors the frozen configured owner scope against Delivery;
|
|
27
|
+
* 2. freezes the conversation's model (or explicit fixed override), applying
|
|
28
|
+
* supplier-specific credential/contract checks only to that supplier;
|
|
29
|
+
* 3. optionally reserves an owner-configured background budget;
|
|
30
|
+
* 4. runs ONE bounded background agent that may only read history and
|
|
31
|
+
* propose a paused skill candidate through Host re-verification.
|
|
32
|
+
* Any failed precondition skips the wake with a health reason: the driver
|
|
33
|
+
* never changes route, never falls back to another model and never self-enables.
|
|
34
|
+
*/
|
|
35
|
+
export class AssistantGrowthDriverService extends Service {
|
|
36
|
+
static Config = Config;
|
|
37
|
+
static inject = ['assistantGoals', 'assistantSkills', 'assistantPolicy', 'assistantDelivery', 'agents', 'sessions', 'tools', 'llm'];
|
|
38
|
+
#config;
|
|
39
|
+
#flight;
|
|
40
|
+
#active = true;
|
|
41
|
+
#abort = new AbortController();
|
|
42
|
+
#sourceBinding;
|
|
43
|
+
#health = { lastWakeAt: null, outcome: 'never-run', reason: null, run: null };
|
|
44
|
+
#usage;
|
|
45
|
+
constructor(ctx, input = {}) {
|
|
46
|
+
super(ctx, 'assistantGrowthDriver');
|
|
47
|
+
this.#config = normalizeConfig(input);
|
|
48
|
+
ctx.effect(() => {
|
|
49
|
+
const timer = this.#config.enabled && this.#config.intervalMs > 0
|
|
50
|
+
? setInterval(() => { void this.wake().catch(() => undefined); }, this.#config.intervalMs) : undefined;
|
|
51
|
+
timer?.unref?.();
|
|
52
|
+
return async () => {
|
|
53
|
+
this.#active = false;
|
|
54
|
+
if (timer !== undefined)
|
|
55
|
+
clearInterval(timer);
|
|
56
|
+
this.#abort.abort(new Error('assistant-growth-driver: disposed'));
|
|
57
|
+
await this.#flight;
|
|
58
|
+
};
|
|
59
|
+
}, 'assistant-growth-driver.runtime');
|
|
60
|
+
if (this.#config.usageLearning.enabled) {
|
|
61
|
+
ctx.inject(['assistantEvaluation', 'assistantAutomations'], usageCtx => {
|
|
62
|
+
const usage = new UsageLearningRuntime(this.#config, {
|
|
63
|
+
evaluation: usageCtx.assistantEvaluation, automations: usageCtx.assistantAutomations,
|
|
64
|
+
delivery: usageCtx.assistantDelivery, review: input => this.#reviewUsage(input),
|
|
65
|
+
});
|
|
66
|
+
usageCtx.effect(() => async () => {
|
|
67
|
+
if (this.#usage === usage)
|
|
68
|
+
this.#usage = undefined;
|
|
69
|
+
await usage.close();
|
|
70
|
+
}, 'assistant-growth-driver.usage-learning');
|
|
71
|
+
this.#usage = usage;
|
|
72
|
+
usage.start();
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (this.#config.pluginSourceProposals.enabled) {
|
|
76
|
+
// Optional provider lives in a nested injection. Its generation owns the
|
|
77
|
+
// source capability and cancellation; the outer driver remains usable
|
|
78
|
+
// when the control plane is absent or is being replaced.
|
|
79
|
+
ctx.inject(['pluginControlPlane'], sourceCtx => {
|
|
80
|
+
const abort = new AbortController();
|
|
81
|
+
const current = () => {
|
|
82
|
+
abort.signal.throwIfAborted();
|
|
83
|
+
return sourceCtx.get('pluginControlPlane');
|
|
84
|
+
};
|
|
85
|
+
const provider = current();
|
|
86
|
+
const durable = this.#config.pluginSourceProposals.preparationMode === 'durable';
|
|
87
|
+
// Bind API seams, not this generation's availability. Automations can
|
|
88
|
+
// appear after the control plane: canEnqueueSource then changes from
|
|
89
|
+
// false to true without a control-plane reload.
|
|
90
|
+
const seamsPresent = durable
|
|
91
|
+
? typeof provider.canEnqueueSource === 'function' && typeof provider.enqueueSourceJob === 'function' && typeof provider.inspectSourceJob === 'function'
|
|
92
|
+
: typeof provider.canPrepareSource === 'function' && typeof provider.prepareModifySourcePlan === 'function';
|
|
93
|
+
if (!seamsPresent || typeof provider.inspectSource !== 'function')
|
|
94
|
+
return;
|
|
95
|
+
const binding = {
|
|
96
|
+
signal: abort.signal,
|
|
97
|
+
recordTaskFailure: (source) => {
|
|
98
|
+
const live = current();
|
|
99
|
+
if (typeof live.recordOwnerTaskFailureGap !== 'function')
|
|
100
|
+
throw new Error('control plane owner task gap API unavailable');
|
|
101
|
+
return live.recordOwnerTaskFailureGap(source);
|
|
102
|
+
},
|
|
103
|
+
available: () => {
|
|
104
|
+
try {
|
|
105
|
+
const live = current();
|
|
106
|
+
return durable ? live.canEnqueueSource?.() === true : live.canPrepareSource?.() === true;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
port: {
|
|
113
|
+
listOpenGaps: () => current().gaps(50),
|
|
114
|
+
inspectSource: async (input) => {
|
|
115
|
+
const signal = AbortSignal.any([input.signal, abort.signal, this.#abort.signal]);
|
|
116
|
+
return current().inspectSource({ ...input, signal,
|
|
117
|
+
assertCurrent: () => { signal.throwIfAborted(); current(); input.assertCurrent(); },
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
prepareModifySourcePlan: async (input) => {
|
|
121
|
+
const signal = AbortSignal.any([input.signal, abort.signal, this.#abort.signal]);
|
|
122
|
+
return current().prepareModifySourcePlan({ ...input, signal,
|
|
123
|
+
assertCurrent: () => { signal.throwIfAborted(); current(); input.assertCurrent(); },
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
enqueueSourceJob: async (input) => {
|
|
127
|
+
const signal = AbortSignal.any([input.signal, abort.signal, this.#abort.signal]);
|
|
128
|
+
// Do not add route/configuration/timeout fields here. The
|
|
129
|
+
// control-plane durable authority owns those independently.
|
|
130
|
+
return current().enqueueSourceJob({ ...input, signal,
|
|
131
|
+
assertCurrent: () => { signal.throwIfAborted(); current(); input.assertCurrent(); },
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
inspectSourceJob: (input) => current().inspectSourceJob(input),
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
this.#sourceBinding = binding;
|
|
138
|
+
sourceCtx.effect(() => () => {
|
|
139
|
+
abort.abort(new Error('assistant-growth-driver: source provider changed'));
|
|
140
|
+
if (this.#sourceBinding === binding)
|
|
141
|
+
this.#sourceBinding = undefined;
|
|
142
|
+
}, 'assistant-growth-driver.source-provider');
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Cordis traces public service calls through a proxy. Bind these entry points
|
|
147
|
+
// to the owning instance so private state and the wake's Fiber stay intact.
|
|
148
|
+
health = () => this.#health;
|
|
149
|
+
usageHealth = () => this.#usage?.health() ?? { enabled: this.#config.usageLearning.enabled, connected: false };
|
|
150
|
+
async #reviewUsage(input) {
|
|
151
|
+
// Unlike timer nudges, a durable job must run its own frozen source, never
|
|
152
|
+
// coalesce onto an unrelated manual wake and report that wake as its result.
|
|
153
|
+
while (this.#flight !== undefined) {
|
|
154
|
+
await this.#flight;
|
|
155
|
+
input.assertCurrent();
|
|
156
|
+
}
|
|
157
|
+
input.assertCurrent();
|
|
158
|
+
let outcome = 'unknown';
|
|
159
|
+
const flight = this.#runWake({ usage: input }).then(() => {
|
|
160
|
+
outcome = this.#health.outcome === 'ran' && this.#health.run?.outcome === 'succeeded' ? 'reviewed' : 'unknown';
|
|
161
|
+
}).finally(() => { if (this.#flight === flight)
|
|
162
|
+
this.#flight = undefined; });
|
|
163
|
+
this.#flight = flight;
|
|
164
|
+
await flight;
|
|
165
|
+
return outcome;
|
|
166
|
+
}
|
|
167
|
+
/** Run one wake immediately (also used by tests / an explicit Host trigger). */
|
|
168
|
+
wake = (input = {}) => {
|
|
169
|
+
if (!this.#active || !this.#config.enabled)
|
|
170
|
+
return Promise.resolve();
|
|
171
|
+
// Coalesce explicit and timer wakes onto the same bounded run. Queueing
|
|
172
|
+
// timer ticks would build an unbounded backlog when a build is slow.
|
|
173
|
+
if (this.#flight !== undefined)
|
|
174
|
+
return this.#flight;
|
|
175
|
+
const flight = this.#runWake(input).finally(() => { if (this.#flight === flight)
|
|
176
|
+
this.#flight = undefined; });
|
|
177
|
+
this.#flight = flight;
|
|
178
|
+
return flight;
|
|
179
|
+
};
|
|
180
|
+
async #resolveCredential(provider) {
|
|
181
|
+
const env = this.#config.apiKeyEnv ?? (provider === 'super-relay' ? DEFAULT_API_KEY_ENV : null);
|
|
182
|
+
// Other adapters own their credentials; do not require a Super Relay key
|
|
183
|
+
// merely because the growth plugin happens to be installed.
|
|
184
|
+
if (env === null)
|
|
185
|
+
return true;
|
|
186
|
+
const credentials = this.ctx.get('credentials', false);
|
|
187
|
+
const resolved = credentials === undefined ? undefined : (await credentials.resolve(credentialRef(env)))?.value;
|
|
188
|
+
const key = resolved ?? process.env[env];
|
|
189
|
+
return typeof key === 'string' && key.length > 0;
|
|
190
|
+
}
|
|
191
|
+
async #runWake(input) {
|
|
192
|
+
const wakeId = input.usage?.id ?? `growth-wake-${Date.now()}-${randomUUID()}`;
|
|
193
|
+
const startedAt = Date.now();
|
|
194
|
+
const config = this.#config;
|
|
195
|
+
if (!config.scope) {
|
|
196
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'skipped', reason: 'missing-scope', run: null };
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const delivery = unwrapService(this.ctx.get('assistantDelivery'));
|
|
200
|
+
const policy = unwrapService(this.ctx.get('assistantPolicy', false));
|
|
201
|
+
const goals = unwrapService(this.ctx.get('assistantGoals'));
|
|
202
|
+
const skills = unwrapService(this.ctx.get('assistantSkills'));
|
|
203
|
+
// ---- preflight (no network, no agent) ----
|
|
204
|
+
let authority;
|
|
205
|
+
try {
|
|
206
|
+
authority = mintGrowthAuthority(delivery, config.scope, startedAt + config.maxDurationMs);
|
|
207
|
+
if (input.usage) {
|
|
208
|
+
const base = authority, usage = input.usage;
|
|
209
|
+
authority = Object.freeze({ ...base, assertCurrent() { base.assertCurrent(); usage.assertCurrent(); } });
|
|
210
|
+
authority.assertCurrent();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'skipped', reason: `missing-binding:${errorMessage(error)}`, run: null };
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
let model;
|
|
218
|
+
let modelFailure;
|
|
219
|
+
try {
|
|
220
|
+
const selected = input.usage?.model ?? (config.provider !== null && config.model !== null
|
|
221
|
+
? { provider: config.provider, model: config.model,
|
|
222
|
+
...(config.reasoningEffort === null ? {} : { reasoningEffort: config.reasoningEffort }) }
|
|
223
|
+
: delivery.inspectOwnerModelSelection({ authorityId: config.scope.ownerRouteId,
|
|
224
|
+
principalId: config.scope.principalId, workspace: config.scope.workspace,
|
|
225
|
+
agentPreset: config.scope.preset,
|
|
226
|
+
...(input.sourceAgent === undefined ? {} : { sourceAgent: input.sourceAgent }) }));
|
|
227
|
+
if (!selected.provider || !selected.model)
|
|
228
|
+
throw new Error('owner model selection is unavailable');
|
|
229
|
+
model = Object.freeze({ provider: selected.provider, model: selected.model,
|
|
230
|
+
...(selected.reasoningEffort === undefined ? {} : { reasoningEffort: ReasoningEffortId(selected.reasoningEffort) }) });
|
|
231
|
+
authority.assertCurrent();
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
modelFailure = errorMessage(error);
|
|
235
|
+
}
|
|
236
|
+
// Owner-anchored workflow learning is a separate, purely Host-local track.
|
|
237
|
+
// It needs only the anchored owner authority and performs no model/network
|
|
238
|
+
// call, so it runs before the super-relay credential/budget gates. Failure
|
|
239
|
+
// here never blocks the model-driven skill track below.
|
|
240
|
+
let ownerAnchored;
|
|
241
|
+
if (config.workflowOwnerAnchored.enabled) {
|
|
242
|
+
ownerAnchored = await this.#runOwnerAnchoredTrack({
|
|
243
|
+
startedAt, authority, goals, delivery: delivery,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
if (model === undefined || modelFailure !== undefined) {
|
|
247
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'skipped', reason: `missing-model:${modelFailure ?? 'unavailable'}`, run: null, ownerAnchored };
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
if (model.provider === 'super-relay') {
|
|
252
|
+
const { assertCurrentContract } = await import('@dsh-enhanced/assistant-super-relay-budget');
|
|
253
|
+
assertCurrentContract();
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'skipped', reason: `contract-expired:${errorMessage(error)}`, run: null, ownerAnchored };
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (!await this.#resolveCredential(model.provider)) {
|
|
261
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'skipped', reason: 'missing-credential', run: null, ownerAnchored };
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (policy === undefined) {
|
|
265
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'skipped', reason: 'missing-policy', run: null, ownerAnchored };
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
let reservationId;
|
|
269
|
+
let reservationSettled = false;
|
|
270
|
+
let agentSubmitted = false;
|
|
271
|
+
if (input.usage === undefined && config.budgetId !== null && config.budgetAmount !== null) {
|
|
272
|
+
try {
|
|
273
|
+
const reservation = policy.reserve({
|
|
274
|
+
budgetId: config.budgetId,
|
|
275
|
+
subject: { kind: 'background', id: wakeId, workspace: config.scope.workspace, principal: config.scope.principalId },
|
|
276
|
+
amount: config.budgetAmount,
|
|
277
|
+
idempotencyKey: `growth-budget:${wakeId}`,
|
|
278
|
+
});
|
|
279
|
+
if (reservation.status !== 'reserved') {
|
|
280
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'skipped', reason: `budget:${reservation.status}`, run: null, ownerAnchored };
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
reservationId = reservation.reservationId;
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'skipped', reason: `budget:${errorMessage(error)}`, run: null, ownerAnchored };
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
agentSubmitted = true;
|
|
292
|
+
const bound = this.#sourceBinding;
|
|
293
|
+
const source = bound !== undefined && bound.available() ? bound : undefined;
|
|
294
|
+
let sourcePort = source?.port;
|
|
295
|
+
if (source && input.usage) {
|
|
296
|
+
const usage = input.usage;
|
|
297
|
+
const ownGaps = () => {
|
|
298
|
+
usage.assertCurrent();
|
|
299
|
+
return usage.source.canonical.objective?.status === 'not-achieved'
|
|
300
|
+
? [source.recordTaskFailure(usage.source)] : [];
|
|
301
|
+
};
|
|
302
|
+
// Persist the exact failure before submitting the model; neither a
|
|
303
|
+
// model assertion nor an operator's global gap is a prerequisite.
|
|
304
|
+
ownGaps();
|
|
305
|
+
const assertGap = (gapId) => {
|
|
306
|
+
if (!ownGaps().some(gap => gap.id === gapId && gap.status === 'open' && gap.candidateId === undefined)) {
|
|
307
|
+
throw new Error('source gap is not the current task failure');
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
sourcePort = { ...source.port, listOpenGaps: ownGaps,
|
|
311
|
+
prepareModifySourcePlan: request => { assertGap(request.gapId); return source.port.prepareModifySourcePlan(request); },
|
|
312
|
+
enqueueSourceJob: request => { assertGap(request.gapId); return source.port.enqueueSourceJob(request); },
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
const run = await runGrowthAgent(this.ctx, { wakeId, authority, config, model, goals, skills,
|
|
316
|
+
...(sourcePort === undefined ? {} : { sourcePlane: sourcePort }),
|
|
317
|
+
...(input.usage === undefined ? {} : { feedback: input.usage.source }),
|
|
318
|
+
signal: AbortSignal.any([this.#abort.signal, ...(source === undefined ? [] : [source.signal]),
|
|
319
|
+
...(input.usage === undefined ? [] : [input.usage.signal])]),
|
|
320
|
+
});
|
|
321
|
+
if (reservationId !== undefined) {
|
|
322
|
+
policy.finalize(reservationId, config.budgetAmount);
|
|
323
|
+
reservationSettled = true;
|
|
324
|
+
}
|
|
325
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'ran', reason: run.outcome, run, ownerAnchored };
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
if (reservationId !== undefined && !reservationSettled) {
|
|
329
|
+
// The agent factory may already have submitted a request: charge the
|
|
330
|
+
// reservation conservatively rather than release potentially-spent budget.
|
|
331
|
+
try {
|
|
332
|
+
if (agentSubmitted)
|
|
333
|
+
policy.finalize(reservationId, config.budgetAmount);
|
|
334
|
+
else
|
|
335
|
+
policy.release(reservationId);
|
|
336
|
+
}
|
|
337
|
+
catch { /* leave the reservation ledger state visible for the owner */ }
|
|
338
|
+
}
|
|
339
|
+
this.#health = { lastWakeAt: startedAt, outcome: 'failed', reason: errorMessage(error), run: null, ownerAnchored };
|
|
340
|
+
this.ctx.logger.warn(`assistant-growth-driver: wake ${wakeId} failed: ${errorMessage(error)}`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* The owner-anchored workflow track. It only enumerates recently completed
|
|
345
|
+
* owner goals and asks Delivery to independently re-verify and (if the goal
|
|
346
|
+
* honestly reduces to one no-tool agent turn) record a paused candidate. The
|
|
347
|
+
* driver passes ONLY a locator plus the bounded authority — never a prompt,
|
|
348
|
+
* steps or an acceptance verdict — and it never approves, activates or
|
|
349
|
+
* installs anything. A goal that fails the owner-root/achieved evidence bar
|
|
350
|
+
* is skipped; an infrastructure, policy, authority or live-route mismatch
|
|
351
|
+
* fails closed and halts the track for this wake.
|
|
352
|
+
*/
|
|
353
|
+
async #runOwnerAnchoredTrack(input) {
|
|
354
|
+
const trackConfig = this.#config.workflowOwnerAnchored;
|
|
355
|
+
const summary = {
|
|
356
|
+
considered: 0, attempted: 0, recorded: 0, replayed: 0, abstained: 0, stopped: null,
|
|
357
|
+
};
|
|
358
|
+
let records;
|
|
359
|
+
try {
|
|
360
|
+
records = input.goals.inspectOwnerGoals(input.authority.scope, 50);
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
return { ...summary, stopped: `inspect:${errorMessage(error)}` };
|
|
364
|
+
}
|
|
365
|
+
const cutoff = input.startedAt - trackConfig.lookbackMs;
|
|
366
|
+
// Coarse discovery filter only; the whole-goal succeeded/quiescent/achieved
|
|
367
|
+
// and owner-root checks are Delivery's single source of truth at commit.
|
|
368
|
+
const candidates = records.filter(record => record.native.phase === 'complete' && record.updatedAt >= cutoff);
|
|
369
|
+
const mutable = { ...summary };
|
|
370
|
+
mutable.considered = candidates.length;
|
|
371
|
+
for (const record of candidates) {
|
|
372
|
+
if (mutable.attempted >= trackConfig.maxCommitsPerWake)
|
|
373
|
+
break;
|
|
374
|
+
try {
|
|
375
|
+
// Re-anchor before every commit: a revoked/rebound owner route or a
|
|
376
|
+
// principal generation change aborts the rest of the track.
|
|
377
|
+
input.authority.assertCurrent();
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
mutable.stopped = `authority:${errorMessage(error)}`;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
// Every locator field comes from the anchored authority (never from the
|
|
384
|
+
// enumerated record or a caller-supplied prompt); only the per-goal
|
|
385
|
+
// sessionId/goalId identify which owner success to re-verify.
|
|
386
|
+
const { principalId, workspace, preset } = input.authority.scope;
|
|
387
|
+
const locator = {
|
|
388
|
+
ownerRouteId: input.authority.ownerRouteId,
|
|
389
|
+
principalId,
|
|
390
|
+
workspace,
|
|
391
|
+
preset,
|
|
392
|
+
sessionId: record.native.sessionId,
|
|
393
|
+
goalId: record.id,
|
|
394
|
+
};
|
|
395
|
+
mutable.attempted += 1;
|
|
396
|
+
try {
|
|
397
|
+
const result = await input.delivery.commitOwnerAnchoredWorkflowTrace({ locator, authority: input.authority });
|
|
398
|
+
if (result.outcome === 'abstained')
|
|
399
|
+
mutable.abstained += 1;
|
|
400
|
+
else if (result.replayed)
|
|
401
|
+
mutable.replayed += 1;
|
|
402
|
+
else
|
|
403
|
+
mutable.recorded += 1;
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
const code = error?.code;
|
|
407
|
+
const message = errorMessage(error);
|
|
408
|
+
if (code === 'runtime-unavailable' || code === 'policy-denied' || code === 'runtime-conflict'
|
|
409
|
+
|| /live owner route|owner route changed|authority expired/u.test(message)) {
|
|
410
|
+
mutable.stopped = `${typeof code === 'string' ? code : 'error'}:${message}`;
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
// Otherwise this completed goal is merely not learnable right now
|
|
414
|
+
// (no current achieved receipt, not owner-root, etc.); keep scanning.
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return Object.freeze(mutable);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function errorMessage(error) {
|
|
421
|
+
return error instanceof Error ? error.message : String(error);
|
|
422
|
+
}
|
|
423
|
+
export function apply(ctx, input = {}) {
|
|
424
|
+
new AssistantGrowthDriverService(ctx, input);
|
|
425
|
+
}
|
|
426
|
+
export default { name, Config, inject: AssistantGrowthDriverService.inject, apply, version };
|
|
427
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAKxD,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,eAAe,EAAoC,MAAM,aAAa,CAAA;AAC5G,OAAO,EAAE,mBAAmB,EAAiD,MAAM,cAAc,CAAA;AACjG,OAAO,EAAE,cAAc,EAA6B,MAAM,mBAAmB,CAAA;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,OAAO,EAAE,oBAAoB,EAAiD,MAAM,oBAAoB,CAAA;AAExG,MAAM,CAAC,MAAM,IAAI,GAAG,sCAAsC,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAA;AAuC3C;;;;;;;GAOG;AACH,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;AACrD,SAAS,aAAa,CAAI,OAAU;IAClC,OAAQ,OAAwD,EAAE,CAAC,eAAe,CAAC,IAAI,OAAO,CAAA;AAChG,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,4BAA6B,SAAQ,OAAO;IACvD,MAAM,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,MAAM,CAAC,MAAM,GAAG,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;IAE1H,OAAO,CAAoC;IACpD,OAAO,CAA2B;IAClC,OAAO,GAAG,IAAI,CAAA;IACL,MAAM,GAAG,IAAI,eAAe,EAAE,CAAA;IACvC,cAAc,CAAyK;IACvL,OAAO,GAAqB,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAA;IAC/F,MAAM,CAAkC;IAExC,YAAY,GAAY,EAAE,QAAqC,EAAE;QAC/D,KAAK,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAA;QACnC,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;QACrC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE;YACd,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,GAAG,CAAC;gBAC/D,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;YACvG,KAAK,EAAE,KAAK,EAAE,EAAE,CAAA;YAChB,OAAO,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;gBACpB,IAAI,KAAK,KAAK,SAAS;oBAAE,aAAa,CAAC,KAAK,CAAC,CAAA;gBAC7C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAA;gBACjE,MAAM,IAAI,CAAC,OAAO,CAAA;YACpB,CAAC,CAAA;QACH,CAAC,EAAE,iCAAiC,CAAC,CAAA;QACrC,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;YACvC,GAAG,CAAC,MAAM,CAAC,CAAC,qBAAqB,EAAE,sBAAsB,CAAC,EAAE,QAAQ,CAAC,EAAE;gBACrE,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,EAAE;oBACnD,UAAU,EAAE,QAAQ,CAAC,mBAAmB,EAAE,WAAW,EAAE,QAAQ,CAAC,oBAAoB;oBACpF,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;iBAChF,CAAC,CAAA;gBACF,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE;oBAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK;wBAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;oBAClD,MAAM,KAAK,CAAC,KAAK,EAAE,CAAA;gBACrB,CAAC,EAAE,wCAAwC,CAAC,CAAA;gBAC5C,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;gBACnB,KAAK,CAAC,KAAK,EAAE,CAAA;YACf,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,OAAO,EAAE,CAAC;YAC/C,yEAAyE;YACzE,sEAAsE;YACtE,yDAAyD;YACzD,GAAG,CAAC,MAAM,CAAC,CAAC,oBAA6B,CAAC,EAAE,SAAS,CAAC,EAAE;gBACtD,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAA;gBAOnC,MAAM,OAAO,GAAG,GAAkB,EAAE;oBAClC,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;oBAC7B,OAAO,SAAS,CAAC,GAAG,CAAC,oBAA6B,CAA6B,CAAA;gBACjF,CAAC,CAAA;gBACD,MAAM,QAAQ,GAAG,OAAO,EAAE,CAAA;gBAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,eAAe,KAAK,SAAS,CAAA;gBAChF,sEAAsE;gBACtE,qEAAqE;gBACrE,gDAAgD;gBAChD,MAAM,YAAY,GAAG,OAAO;oBAC1B,CAAC,CAAC,OAAO,QAAQ,CAAC,gBAAgB,KAAK,UAAU,IAAI,OAAO,QAAQ,CAAC,gBAAgB,KAAK,UAAU,IAAI,OAAO,QAAQ,CAAC,gBAAgB,KAAK,UAAU;oBACvJ,CAAC,CAAC,OAAO,QAAQ,CAAC,gBAAgB,KAAK,UAAU,IAAI,OAAO,QAAQ,CAAC,uBAAuB,KAAK,UAAU,CAAA;gBAC7G,IAAI,CAAC,YAAY,IAAI,OAAO,QAAQ,CAAC,aAAa,KAAK,UAAU;oBAAE,OAAM;gBACzE,MAAM,OAAO,GAAG;oBACd,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,iBAAiB,EAAE,CAAC,MAAmC,EAAE,EAAE;wBACzD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;wBACtB,IAAI,OAAO,IAAI,CAAC,yBAAyB,KAAK,UAAU;4BAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;wBACzH,OAAO,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAA;oBAC/C,CAAC;oBACD,SAAS,EAAE,GAAG,EAAE;wBACd,IAAI,CAAC;4BACH,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;4BACtB,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,KAAK,IAAI,CAAA;wBAC1F,CAAC;wBAAC,MAAM,CAAC;4BAAC,OAAO,KAAK,CAAA;wBAAC,CAAC;oBAC1B,CAAC;oBACD,IAAI,EAAE;wBACJ,YAAY,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;wBACtC,aAAa,EAAE,KAAK,EAAE,KAA4D,EAAE,EAAE;4BACpF,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;4BAChF,OAAO,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM;gCAC/C,aAAa,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAA,CAAC,CAAC;6BACnF,CAAC,CAAA;wBACJ,CAAC;wBACD,uBAAuB,EAAE,KAAK,EAAE,KAAsE,EAAE,EAAE;4BACxG,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;4BAChF,OAAO,OAAO,EAAE,CAAC,uBAAuB,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM;gCACzD,aAAa,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAA,CAAC,CAAC;6BACnF,CAAC,CAAA;wBACJ,CAAC;wBACD,gBAAgB,EAAE,KAAK,EAAE,KAA+D,EAAE,EAAE;4BAC1F,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;4BAChF,0DAA0D;4BAC1D,4DAA4D;4BAC5D,OAAO,OAAO,EAAE,CAAC,gBAAgB,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM;gCAClD,aAAa,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAA,CAAC,CAAC;6BACnF,CAAC,CAAA;wBACJ,CAAC;wBACD,gBAAgB,EAAE,CAAC,KAA+D,EAAE,EAAE,CACpF,OAAO,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC;qBACJ;iBAClC,CAAA;gBACD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAA;gBAC7B,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE;oBAC1B,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC,CAAA;oBAC1E,IAAI,IAAI,CAAC,cAAc,KAAK,OAAO;wBAAE,IAAI,CAAC,cAAc,GAAG,SAAS,CAAA;gBACtE,CAAC,EAAE,yCAAyC,CAAC,CAAA;YAC/C,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,4EAA4E;IAC5E,MAAM,GAAG,GAAqB,EAAE,CAAC,IAAI,CAAC,OAAO,CAAA;IAC7C,WAAW,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;IAE9G,KAAK,CAAC,YAAY,CAAC,KAAuB;QACxC,2EAA2E;QAC3E,6EAA6E;QAC7E,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAAC,MAAM,IAAI,CAAC,OAAO,CAAC;YAAC,KAAK,CAAC,aAAa,EAAE,CAAA;QAAC,CAAC;QAChF,KAAK,CAAC,aAAa,EAAE,CAAA;QACrB,IAAI,OAAO,GAAsB,SAAS,CAAA;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACvD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;QAChH,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;YAAE,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA,CAAC,CAAC,CAAC,CAAA;QAC3E,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,MAAM,MAAM,CAAA;QACZ,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,gFAAgF;IAChF,IAAI,GAAG,CAAC,QAAiC,EAAE,EAAiB,EAAE;QAC5D,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QACpE,wEAAwE;QACxE,qEAAqE;QACrE,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,OAAO,CAAA;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;YAAE,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA,CAAC,CAAC,CAAC,CAAA;QAC5G,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IAED,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QAC/F,yEAAyE;QACzE,4DAA4D;QAC5D,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;QAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,aAAsB,EAAE,KAAK,CAAkC,CAAA;QAChG,MAAM,QAAQ,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAA;QAC/G,MAAM,GAAG,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACxC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAA;IAClD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAwD;QACrE,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,eAAe,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,EAAE,CAAA;QAC7E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAA;QAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,IAAI,EAAE,CAAA;YAChG,OAAM;QACR,CAAC;QACD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAA6H,CAAA;QAC7L,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,iBAA0B,EAAE,KAAK,CAAC,CAAuB,CAAA;QACnG,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAyB,CAAC,CAAuG,CAAA;QAC1K,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,iBAA0B,CAAC,CAA+I,CAAA;QAEpN,6CAA6C;QAC7C,IAAI,SAAS,CAAA;QACb,IAAI,CAAC;YACH,SAAS,GAAG,mBAAmB,CAAC,QAAyC,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,CAAA;YAC1H,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,MAAM,IAAI,GAAG,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;gBAC3C,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAA,CAAC,CAAC,EAAE,CAAC,CAAA;gBACvG,SAAS,CAAC,aAAa,EAAE,CAAA;YAC3B,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAA;YACzH,OAAM;QACR,CAAC;QACD,IAAI,KAA2C,CAAA;QAC/C,IAAI,YAAgC,CAAA;QACpC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;gBACvF,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK;oBAChD,GAAG,CAAC,MAAM,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC,EAAE;gBAC3F,CAAC,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY;oBAC5E,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS;oBACxE,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;oBAChC,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACtF,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;YAClG,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACxE,GAAG,CAAC,QAAQ,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,iBAAiB,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YACxH,SAAS,CAAC,aAAa,EAAE,CAAA;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;QAAC,CAAC;QACtD,2EAA2E;QAC3E,2EAA2E;QAC3E,2EAA2E;QAC3E,wDAAwD;QACxD,IAAI,aAAmD,CAAA;QACvD,IAAI,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,CAAC;YACzC,aAAa,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC;gBAChD,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAyC;aACjF,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YACtD,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,YAAY,IAAI,aAAa,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;YAChJ,OAAM;QACR,CAAC;QACD,IAAI,CAAC;YACH,IAAI,KAAK,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;gBACrC,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,4CAA4C,CAAC,CAAA;gBAC5F,qBAAqB,EAAE,CAAA;YACzB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,oBAAoB,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;YACzI,OAAM;QACR,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,oBAAoB,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;YACpH,OAAM;QACR,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;YAChH,OAAM;QACR,CAAC;QAED,IAAI,aAAiC,CAAA;QACrC,IAAI,kBAAkB,GAAG,KAAK,CAAA;QAC9B,IAAI,cAAc,GAAG,KAAK,CAAA;QAC1B,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1F,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC;oBACjC,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,OAAO,EAAE,EAAE,IAAI,EAAE,YAAqB,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE;oBAC5H,MAAM,EAAE,MAAM,CAAC,YAAY;oBAC3B,cAAc,EAAE,iBAAiB,MAAM,EAAE;iBAC1C,CAAC,CAAA;gBACF,IAAI,WAAW,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;oBACtC,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,WAAW,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;oBAC9H,OAAM;gBACR,CAAC;gBACD,aAAa,GAAG,WAAW,CAAC,aAAa,CAAA;YAC3C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;gBAC/H,OAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,CAAC;YACH,cAAc,GAAG,IAAI,CAAA;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAA;YACjC,MAAM,MAAM,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;YAC3E,IAAI,UAAU,GAAG,MAAM,EAAE,IAAI,CAAA;YAC7B,IAAI,MAAM,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;gBACzB,MAAM,OAAO,GAAG,GAA+B,EAAE;oBAC/C,KAAK,CAAC,aAAa,EAAE,CAAA;oBACrB,OAAO,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,KAAK,cAAc;wBAChE,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;gBACnD,CAAC,CAAA;gBACD,mEAAmE;gBACnE,kEAAkE;gBAClE,OAAO,EAAE,CAAA;gBACT,MAAM,SAAS,GAAG,CAAC,KAAa,EAAQ,EAAE;oBACxC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,EAAE,CAAC;wBACvG,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;oBAC/D,CAAC;gBACH,CAAC,CAAA;gBACD,UAAU,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO;oBAClD,uBAAuB,EAAE,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAA,CAAC,CAAC;oBACrH,gBAAgB,EAAE,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA,CAAC,CAAC;iBACxG,CAAA;YACH,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM;gBAC1F,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;gBAChE,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACtE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBAC3F,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;aAC/D,CAAC,CAAA;YACF,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,YAAa,CAAC,CAAC;gBAAC,kBAAkB,GAAG,IAAI,CAAA;YAAC,CAAC;YACpH,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,CAAA;QACnG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,aAAa,KAAK,SAAS,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACvD,qEAAqE;gBACrE,2EAA2E;gBAC3E,IAAI,CAAC;oBACH,IAAI,cAAc;wBAAE,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,YAAa,CAAC,CAAA;;wBACnE,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;gBACpC,CAAC;gBAAC,MAAM,CAAC,CAAC,8DAA8D,CAAC,CAAC;YAC5E,CAAC;YACD,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;YAClH,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,MAAM,YAAY,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAChG,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,sBAAsB,CAAC,KAK5B;QACC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAA;QACtD,MAAM,OAAO,GAA6B;YACxC,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI;SACnF,CAAA;QACD,IAAI,OAAsC,CAAA;QAC1C,IAAI,CAAC;YACH,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QACpE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,WAAW,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,CAAA;QAClE,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,GAAG,WAAW,CAAC,UAAU,CAAA;QACvD,4EAA4E;QAC5E,yEAAyE;QACzE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CACzC,MAAM,CAAC,MAAM,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,CAAA;QACnE,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,CAAA;QAC9B,OAAO,CAAC,UAAU,GAAG,UAAU,CAAC,MAAM,CAAA;QACtC,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;YAChC,IAAI,OAAO,CAAC,SAAS,IAAI,WAAW,CAAC,iBAAiB;gBAAE,MAAK;YAC7D,IAAI,CAAC;gBACH,oEAAoE;gBACpE,4DAA4D;gBAC5D,KAAK,CAAC,SAAS,CAAC,aAAa,EAAE,CAAA;YACjC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,OAAO,GAAG,aAAa,YAAY,CAAC,KAAK,CAAC,EAAE,CAAA;gBACpD,MAAK;YACP,CAAC;YACD,wEAAwE;YACxE,oEAAoE;YACpE,8DAA8D;YAC9D,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAA;YAChE,MAAM,OAAO,GAAoC;gBAC/C,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,YAAY;gBAC1C,WAAW;gBACX,SAAS;gBACT,MAAM;gBACN,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS;gBAClC,MAAM,EAAE,MAAM,CAAC,EAAE;aAClB,CAAA;YACD,OAAO,CAAC,SAAS,IAAI,CAAC,CAAA;YACtB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,gCAAgC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;gBAC7G,IAAI,MAAM,CAAC,OAAO,KAAK,WAAW;oBAAE,OAAO,CAAC,SAAS,IAAI,CAAC,CAAA;qBACrD,IAAI,MAAM,CAAC,QAAQ;oBAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAA;;oBAC1C,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAA;YAC5B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,GAAI,KAA4B,EAAE,IAAI,CAAA;gBAChD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;gBACnC,IAAI,IAAI,KAAK,qBAAqB,IAAI,IAAI,KAAK,eAAe,IAAI,IAAI,KAAK,kBAAkB;uBACxF,yDAAyD,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC7E,OAAO,CAAC,OAAO,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,EAAE,CAAA;oBAC3E,MAAK;gBACP,CAAC;gBACD,kEAAkE;gBAClE,sEAAsE;YACxE,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC/B,CAAC;;AAGH,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC/D,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,QAAqC,EAAE;IACzE,IAAI,4BAA4B,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AAC9C,CAAC;AAED,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,4BAA4B,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GrowthSourcePreparedFile } from './source-port.js';
|
|
2
|
+
export declare const MAX_SOURCE_FILES = 64;
|
|
3
|
+
export declare const MAX_SOURCE_FILE_BYTES = 65536;
|
|
4
|
+
export declare const MAX_SOURCE_TOTAL_BYTES = 262144;
|
|
5
|
+
export interface SourceEdit {
|
|
6
|
+
readonly path: string;
|
|
7
|
+
readonly before: string;
|
|
8
|
+
readonly after: string;
|
|
9
|
+
}
|
|
10
|
+
export interface SourceEditSnapshot {
|
|
11
|
+
readonly paths: ReadonlySet<string>;
|
|
12
|
+
readonly read: ReadonlyMap<string, string>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Expand bounded exact-literal edits against the original committed read cache.
|
|
16
|
+
* The returned files remain the control-plane's existing full-file contract.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveSourcePreparation(input: {
|
|
19
|
+
readonly files?: readonly GrowthSourcePreparedFile[];
|
|
20
|
+
readonly edits?: readonly SourceEdit[];
|
|
21
|
+
}, snapshot: SourceEditSnapshot, validPath: (path: string) => boolean): readonly GrowthSourcePreparedFile[];
|
|
22
|
+
//# sourceMappingURL=source-edits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-edits.d.ts","sourceRoot":"","sources":["../src/source-edits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAEhE,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAClC,eAAO,MAAM,qBAAqB,QAAS,CAAA;AAC3C,eAAO,MAAM,sBAAsB,SAAU,CAAA;AAE7C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACnC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC3C;AAYD;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,EACvG,QAAQ,EAAE,kBAAkB,EAC5B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GACnC,SAAS,wBAAwB,EAAE,CAoDrC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export const MAX_SOURCE_FILES = 64;
|
|
2
|
+
export const MAX_SOURCE_FILE_BYTES = 65_536;
|
|
3
|
+
export const MAX_SOURCE_TOTAL_BYTES = 262_144;
|
|
4
|
+
function bytes(value) {
|
|
5
|
+
return Buffer.byteLength(value, 'utf8');
|
|
6
|
+
}
|
|
7
|
+
function soleOccurrence(text, needle) {
|
|
8
|
+
const first = text.indexOf(needle);
|
|
9
|
+
if (first < 0 || text.indexOf(needle, first + 1) >= 0)
|
|
10
|
+
return -1;
|
|
11
|
+
return first;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Expand bounded exact-literal edits against the original committed read cache.
|
|
15
|
+
* The returned files remain the control-plane's existing full-file contract.
|
|
16
|
+
*/
|
|
17
|
+
export function resolveSourcePreparation(input, snapshot, validPath) {
|
|
18
|
+
const { files, edits } = input;
|
|
19
|
+
if ((files !== undefined && !Array.isArray(files)) || (edits !== undefined && !Array.isArray(edits))) {
|
|
20
|
+
throw new Error('source preparation files and edits must be arrays');
|
|
21
|
+
}
|
|
22
|
+
if ((files?.length ?? 0) + (edits?.length ?? 0) === 0) {
|
|
23
|
+
throw new Error('source preparation requires nonempty files or edits');
|
|
24
|
+
}
|
|
25
|
+
const fullFiles = files ?? [];
|
|
26
|
+
const exactEdits = edits ?? [];
|
|
27
|
+
if (fullFiles.length + exactEdits.length > MAX_SOURCE_FILES)
|
|
28
|
+
throw new Error('source proposal operations exceed bounds');
|
|
29
|
+
const fullPaths = new Set();
|
|
30
|
+
for (const file of fullFiles) {
|
|
31
|
+
if (file === null || typeof file.path !== 'string' || typeof file.content !== 'string'
|
|
32
|
+
|| !validPath(file.path) || bytes(file.content) > MAX_SOURCE_FILE_BYTES)
|
|
33
|
+
throw new Error('source files exceed proposal bounds');
|
|
34
|
+
if (fullPaths.has(file.path))
|
|
35
|
+
throw new Error('source preparation has duplicate full-file paths');
|
|
36
|
+
fullPaths.add(file.path);
|
|
37
|
+
if (snapshot.paths.has(file.path) && !snapshot.read.has(file.path))
|
|
38
|
+
throw new Error('existing source files must be read before replacement');
|
|
39
|
+
}
|
|
40
|
+
const byPath = new Map();
|
|
41
|
+
for (const edit of exactEdits) {
|
|
42
|
+
if (edit === null || typeof edit.path !== 'string' || typeof edit.before !== 'string' || typeof edit.after !== 'string'
|
|
43
|
+
|| !validPath(edit.path) || edit.before.length === 0 || bytes(edit.before) > MAX_SOURCE_FILE_BYTES || bytes(edit.after) > MAX_SOURCE_FILE_BYTES) {
|
|
44
|
+
throw new Error('source edits exceed proposal bounds');
|
|
45
|
+
}
|
|
46
|
+
if (fullPaths.has(edit.path))
|
|
47
|
+
throw new Error('source preparation files and edits must target disjoint paths');
|
|
48
|
+
const original = snapshot.read.get(edit.path);
|
|
49
|
+
if (original === undefined || !snapshot.paths.has(edit.path))
|
|
50
|
+
throw new Error('source edits require an already-read existing source file');
|
|
51
|
+
const start = soleOccurrence(original, edit.before);
|
|
52
|
+
if (start < 0)
|
|
53
|
+
throw new Error('source edit anchor must have one exact literal occurrence in the original read content');
|
|
54
|
+
const intervals = byPath.get(edit.path) ?? [];
|
|
55
|
+
intervals.push({ start, end: start + edit.before.length, after: edit.after });
|
|
56
|
+
byPath.set(edit.path, intervals);
|
|
57
|
+
}
|
|
58
|
+
const resolved = [...fullFiles];
|
|
59
|
+
for (const [path, intervals] of byPath) {
|
|
60
|
+
const ascending = [...intervals].sort((left, right) => left.start - right.start);
|
|
61
|
+
for (let index = 1; index < ascending.length; index += 1) {
|
|
62
|
+
if (ascending[index - 1].end > ascending[index].start)
|
|
63
|
+
throw new Error('source edits overlap in the original read content');
|
|
64
|
+
}
|
|
65
|
+
let content = snapshot.read.get(path);
|
|
66
|
+
for (const interval of ascending.reverse())
|
|
67
|
+
content = content.slice(0, interval.start) + interval.after + content.slice(interval.end);
|
|
68
|
+
if (bytes(content) > MAX_SOURCE_FILE_BYTES)
|
|
69
|
+
throw new Error('resolved source file exceeds proposal bounds');
|
|
70
|
+
resolved.push({ path, content });
|
|
71
|
+
}
|
|
72
|
+
if (resolved.length === 0 || resolved.length > MAX_SOURCE_FILES || resolved.reduce((sum, file) => sum + bytes(file.content), 0) > MAX_SOURCE_TOTAL_BYTES) {
|
|
73
|
+
throw new Error('resolved source files exceed proposal bounds');
|
|
74
|
+
}
|
|
75
|
+
return resolved;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=source-edits.js.map
|