@haaaiawd/second-nature 0.1.38 → 0.1.39
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/agent-inner-guide.md +18 -0
- package/index.js +1270 -1262
- package/openclaw.plugin.json +29 -29
- package/package.json +55 -55
- package/runtime/cli/ops/heartbeat-surface.d.ts +75 -60
- package/runtime/cli/ops/heartbeat-surface.js +97 -83
- package/runtime/cli/ops/ops-router.js +1428 -1282
- package/runtime/cli/ops/workspace-heartbeat-runner.js +236 -191
- package/runtime/core/second-nature/guidance/apply-guidance.d.ts +12 -10
- package/runtime/core/second-nature/guidance/apply-guidance.js +15 -10
- package/runtime/core/second-nature/guidance/user-reply-continuity.d.ts +50 -50
- package/runtime/core/second-nature/guidance/user-reply-continuity.js +89 -80
- package/runtime/core/second-nature/runtime/service-entry.d.ts +39 -36
- package/runtime/core/second-nature/runtime/service-entry.js +44 -45
- package/runtime/dream/dream-engine.d.ts +14 -0
- package/runtime/dream/dream-engine.js +306 -0
- package/runtime/dream/dream-input-loader.d.ts +37 -0
- package/runtime/dream/dream-input-loader.js +155 -0
- package/runtime/dream/dream-scheduler.d.ts +75 -0
- package/runtime/dream/dream-scheduler.js +131 -0
- package/runtime/dream/index.d.ts +16 -0
- package/runtime/dream/index.js +14 -0
- package/runtime/dream/insight-extractor.d.ts +32 -0
- package/runtime/dream/insight-extractor.js +135 -0
- package/runtime/dream/memory-consolidator.d.ts +45 -0
- package/runtime/dream/memory-consolidator.js +140 -0
- package/runtime/dream/narrative-update-proposal.d.ts +34 -0
- package/runtime/dream/narrative-update-proposal.js +83 -0
- package/runtime/dream/output-validator.d.ts +20 -0
- package/runtime/dream/output-validator.js +110 -0
- package/runtime/dream/redaction-gate.d.ts +31 -0
- package/runtime/dream/redaction-gate.js +109 -0
- package/runtime/dream/relationship-update-proposal.d.ts +27 -0
- package/runtime/dream/relationship-update-proposal.js +119 -0
- package/runtime/dream/sampler.d.ts +30 -0
- package/runtime/dream/sampler.js +65 -0
- package/runtime/dream/types.d.ts +187 -0
- package/runtime/dream/types.js +11 -0
- package/runtime/guidance/fallback.js +20 -17
- package/runtime/guidance/guidance-assembler.js +76 -74
- package/runtime/guidance/output-guard.d.ts +13 -10
- package/runtime/guidance/output-guard.js +53 -29
- package/runtime/guidance/template-registry.d.ts +20 -16
- package/runtime/guidance/template-registry.js +123 -82
- package/runtime/guidance/types.d.ts +98 -84
- package/runtime/observability/projections/guidance-audit.js +38 -35
|
@@ -1,191 +1,236 @@
|
|
|
1
|
-
import { runHeartbeatCycle } from "../../core/second-nature/heartbeat/run-heartbeat-cycle.js";
|
|
2
|
-
import { loadLifeEvidenceSnapshot } from "../../storage/snapshots/life-evidence-snapshot.js";
|
|
3
|
-
import { createAgentGoalStore } from "../../storage/goal/agent-goal-store.js";
|
|
4
|
-
import { createNarrativeStateStore } from "../../storage/narrative/narrative-state-store.js";
|
|
5
|
-
import { createRelationshipMemoryStore } from "../../storage/relationship/relationship-memory-store.js";
|
|
6
|
-
import { createIdentityProfileStore } from "../../storage/services/identity-profile-store.js";
|
|
7
|
-
import { generateHeartbeatDigest, } from "../../observability/services/heartbeat-digest-assembler.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
let
|
|
21
|
-
let
|
|
22
|
-
let
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
let
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
let
|
|
74
|
-
let
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
1
|
+
import { runHeartbeatCycle } from "../../core/second-nature/heartbeat/run-heartbeat-cycle.js";
|
|
2
|
+
import { loadLifeEvidenceSnapshot } from "../../storage/snapshots/life-evidence-snapshot.js";
|
|
3
|
+
import { createAgentGoalStore } from "../../storage/goal/agent-goal-store.js";
|
|
4
|
+
import { createNarrativeStateStore } from "../../storage/narrative/narrative-state-store.js";
|
|
5
|
+
import { createRelationshipMemoryStore } from "../../storage/relationship/relationship-memory-store.js";
|
|
6
|
+
import { createIdentityProfileStore } from "../../storage/services/identity-profile-store.js";
|
|
7
|
+
import { generateHeartbeatDigest, } from "../../observability/services/heartbeat-digest-assembler.js";
|
|
8
|
+
import { createHistoryDigestStore } from "../../storage/services/history-digest-store.js";
|
|
9
|
+
export async function loadSnapshotInputsForWorkspaceHeartbeat(readModels, options = {}) {
|
|
10
|
+
const status = await readModels.loadStatus();
|
|
11
|
+
const mode = status.rhythm.mode === "unknown" ? "active" : status.rhythm.mode;
|
|
12
|
+
// CH-15-03: quietEnabledBridge should reflect whether the quiet *execution path* is wired
|
|
13
|
+
// (workspaceRoot available), not whether the last observed rhythm decision was "quiet".
|
|
14
|
+
// status.quiet.mode is typically "unknown" until a Quiet artifact has been persisted, which
|
|
15
|
+
// means binding to it would permanently suppress the quiet window — the opposite of intent.
|
|
16
|
+
// We instead enable the bridge whenever workspaceRoot is provided (same condition as
|
|
17
|
+
// `createWorkspaceHeartbeatRunner` uses for injecting quietWorkflow).
|
|
18
|
+
const quietEnabledBridge = !!options.workspaceRoot;
|
|
19
|
+
// T2.2.2: Load life evidence from state DB when available so SnapshotInputs carries real refs.
|
|
20
|
+
let lifeEvidenceRefs;
|
|
21
|
+
let platformEventCount;
|
|
22
|
+
let workEventCount;
|
|
23
|
+
let lifeEvidenceEmptyReason;
|
|
24
|
+
if (options.state && options.workspaceRoot) {
|
|
25
|
+
try {
|
|
26
|
+
const snapshot = await loadLifeEvidenceSnapshot(options.state, options.workspaceRoot, { limit: 50 },
|
|
27
|
+
// Skip repair gate here — runner is called inside a live cycle; gate ran at startup.
|
|
28
|
+
{ runRepairGate: false });
|
|
29
|
+
lifeEvidenceRefs = snapshot.evidenceRefs.map((ref) => ({
|
|
30
|
+
id: ref.id,
|
|
31
|
+
kind: ref.kind,
|
|
32
|
+
uri: ref.uri,
|
|
33
|
+
}));
|
|
34
|
+
platformEventCount = snapshot.platformEvents.length;
|
|
35
|
+
workEventCount = snapshot.workEvents.length;
|
|
36
|
+
if (snapshot.empty) {
|
|
37
|
+
// L-01: Currently snapshot only exposes `empty` boolean.
|
|
38
|
+
// Future: if snapshot adds `emptyReason` (e.g. "redacted_only"), map it here.
|
|
39
|
+
lifeEvidenceEmptyReason = "no_sources";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// If evidence load fails, signal state_unavailable rather than crashing the cycle.
|
|
44
|
+
lifeEvidenceRefs = [];
|
|
45
|
+
platformEventCount = 0;
|
|
46
|
+
workEventCount = 0;
|
|
47
|
+
lifeEvidenceEmptyReason = "state_unavailable";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// No state wired — record that life evidence wasn't loaded so guards can reason honestly.
|
|
52
|
+
lifeEvidenceEmptyReason = "state_unavailable";
|
|
53
|
+
}
|
|
54
|
+
// T2.1.4: Load accepted goals from state DB when available.
|
|
55
|
+
// M-03: typed as GoalContext to avoid coupling to the full AgentGoal schema.
|
|
56
|
+
let acceptedGoals;
|
|
57
|
+
let acceptedGoalsLoadError;
|
|
58
|
+
if (options.state) {
|
|
59
|
+
try {
|
|
60
|
+
const goalStore = createAgentGoalStore(options.state);
|
|
61
|
+
acceptedGoals = await goalStore.listAgentGoals({
|
|
62
|
+
statuses: ["accepted"],
|
|
63
|
+
limit: 20,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
acceptedGoals = [];
|
|
68
|
+
acceptedGoalsLoadError = err instanceof Error ? err.message : String(err);
|
|
69
|
+
// H-05: Distinguish "load failed" from "no goals" for observability.
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// CR-02: Load narrative state and relationship memory when state is available.
|
|
73
|
+
let narrativeState;
|
|
74
|
+
let relationshipMemory;
|
|
75
|
+
let identity;
|
|
76
|
+
if (options.state) {
|
|
77
|
+
try {
|
|
78
|
+
const narrativeStore = createNarrativeStateStore(options.state);
|
|
79
|
+
narrativeState = (await narrativeStore.loadNarrativeState()) ?? undefined;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Narrative state is optional; failure should not block the cycle.
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const relationshipStore = createRelationshipMemoryStore(options.state);
|
|
86
|
+
relationshipMemory = (await relationshipStore.loadRelationshipMemory()) ?? undefined;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Relationship memory is optional; failure should not block the cycle.
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const identityStore = createIdentityProfileStore(options.state);
|
|
93
|
+
const identityResult = await identityStore.loadIdentityProfile("default");
|
|
94
|
+
if (identityResult.status === "loaded" && identityResult.profile) {
|
|
95
|
+
identity = identityResult.profile;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Identity is optional; failure should not block the cycle.
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
mode,
|
|
104
|
+
currentWindowId: status.rhythm.windowId ?? "workspace-default",
|
|
105
|
+
pendingObligations: [],
|
|
106
|
+
recentOutreachHashes: [],
|
|
107
|
+
deniedIntents: [],
|
|
108
|
+
budgets: { socialUsed: 0, socialLimit: 5 },
|
|
109
|
+
awaitingUserInput: false,
|
|
110
|
+
quietEnabledBridge,
|
|
111
|
+
deliveryCapability: { target: "none" },
|
|
112
|
+
lifeEvidenceRefs,
|
|
113
|
+
platformEventCount,
|
|
114
|
+
workEventCount,
|
|
115
|
+
lifeEvidenceEmptyReason,
|
|
116
|
+
acceptedGoals,
|
|
117
|
+
acceptedGoalsLoadError,
|
|
118
|
+
narrativeState,
|
|
119
|
+
relationshipMemory,
|
|
120
|
+
affordanceMap: options.affordanceMap,
|
|
121
|
+
identity,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export function createWorkspaceHeartbeatRunner(readModels, options = {}) {
|
|
125
|
+
// T1.2.4: inject quietWorkflow dep when workspaceRoot is set so quiet/reflection intents
|
|
126
|
+
// can trigger runSourceBackedQuiet and persist artifacts to disk.
|
|
127
|
+
const quietEnabled = options.workspaceRoot && options.enableQuietWorkflow !== false;
|
|
128
|
+
// T2.1.5: when state DB is wired, create a NarrativeStateStore for heartbeat updates.
|
|
129
|
+
const narrativeStateStore = options.state
|
|
130
|
+
? createNarrativeStateStore(options.state)
|
|
131
|
+
: undefined;
|
|
132
|
+
return async (signal) => {
|
|
133
|
+
const cycle = await runHeartbeatCycle({
|
|
134
|
+
signal,
|
|
135
|
+
runtimeAvailable: true,
|
|
136
|
+
deps: {
|
|
137
|
+
loadSnapshotInputs: () => loadSnapshotInputsForWorkspaceHeartbeat(readModels, {
|
|
138
|
+
state: options.state,
|
|
139
|
+
workspaceRoot: options.workspaceRoot,
|
|
140
|
+
affordanceMap: options.affordanceMap,
|
|
141
|
+
}),
|
|
142
|
+
// T1.2.4: pass quietWorkflow dep so runSourceBackedQuiet can persist artifacts.
|
|
143
|
+
quietWorkflow: quietEnabled
|
|
144
|
+
? {
|
|
145
|
+
workspaceRoot: options.workspaceRoot,
|
|
146
|
+
// v7 T-V7C.C.3: pass Dream schedule port so Quiet completion triggers Dream.
|
|
147
|
+
dreamSchedulePort: options.dreamSchedulePort,
|
|
148
|
+
}
|
|
149
|
+
: undefined,
|
|
150
|
+
connectorExecutor: options.connectorExecutor,
|
|
151
|
+
narrativeStateStore,
|
|
152
|
+
// T3.3.1: pass state + workspaceRoot so connector effects can write life evidence.
|
|
153
|
+
state: options.state,
|
|
154
|
+
workspaceRoot: options.workspaceRoot,
|
|
155
|
+
// T2.4.1: pass registry so planner resolves platform-specific intents.
|
|
156
|
+
connectorRegistry: options.connectorRegistry,
|
|
157
|
+
// v7 T-V7C.C.2: pass experience writer for heartbeat connector attempts.
|
|
158
|
+
experienceWriter: options.experienceWriter,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
if (options.runtimeRecorder) {
|
|
162
|
+
try {
|
|
163
|
+
await options.runtimeRecorder.recordHeartbeatCycle({ cycle, signal });
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// T1.2.3: recorder must never break the heartbeat surface response.
|
|
167
|
+
// Failure here means status simply remains at its previous aggregate; the
|
|
168
|
+
// cycle outcome itself is still returned to the caller.
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// v7 T-V7C.C.3 / T-V7C.C.6: After each cycle, attempt HeartbeatDigest generation
|
|
172
|
+
// and persist to heartbeat_digest table so the digest index actually grows.
|
|
173
|
+
// Only runs inside the designated UTC digest window hour, or on every cycle when
|
|
174
|
+
// digestWindowHour is unset (test / always-on mode).
|
|
175
|
+
if (options.digestOpts) {
|
|
176
|
+
const { assemblerDeps, digestWindowHour } = options.digestOpts;
|
|
177
|
+
const nowHour = new Date().getUTCHours();
|
|
178
|
+
const inDigestWindow = digestWindowHour === undefined || nowHour === digestWindowHour;
|
|
179
|
+
if (inDigestWindow) {
|
|
180
|
+
try {
|
|
181
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
182
|
+
const assembledDigest = await generateHeartbeatDigest(date, assemblerDeps);
|
|
183
|
+
// v7 T-V7C.C.6: Persist assembled digest to heartbeat_digest table when state DB is wired.
|
|
184
|
+
if (options.state) {
|
|
185
|
+
const digestStore = createHistoryDigestStore(options.state);
|
|
186
|
+
await digestStore.writeHeartbeatDigest(toStoreDigest(assembledDigest));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
// Digest generation / persistence must not break the heartbeat cycle response.
|
|
191
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
192
|
+
console.warn(`[workspace-heartbeat-runner] Digest generation/persistence failed: ${msg}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return cycle;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Bridge: converts the assembler-facing HeartbeatDigest into the storage-facing
|
|
201
|
+
* HeartbeatDigest (shared/types/v7-entities.ts) so it can be written to heartbeat_digest.
|
|
202
|
+
*
|
|
203
|
+
* The two shapes diverge by design: assembler is an audit-aggregate rich view;
|
|
204
|
+
* store is a flattened day-keyed row. Mapping is lossy but sufficient for growth.
|
|
205
|
+
*/
|
|
206
|
+
function toStoreDigest(d) {
|
|
207
|
+
return {
|
|
208
|
+
digestId: `digest:${d.date}:${Date.now()}`,
|
|
209
|
+
day: d.date,
|
|
210
|
+
connectorSummary: d.connectorSummary.map((c) => ({
|
|
211
|
+
platformId: c.platformId,
|
|
212
|
+
status: c.blockedCount > 0
|
|
213
|
+
? "blocked"
|
|
214
|
+
: c.circuitOpenCount > 0
|
|
215
|
+
? "blocked"
|
|
216
|
+
: c.failureCount > 0
|
|
217
|
+
? "degraded"
|
|
218
|
+
: "ok",
|
|
219
|
+
attemptCount: c.successCount + c.failureCount + c.blockedCount,
|
|
220
|
+
})),
|
|
221
|
+
goalSummary: [
|
|
222
|
+
{ kind: "new", activeCount: d.goalSummary.newGoals },
|
|
223
|
+
{ kind: "completed", activeCount: d.goalSummary.completedGoals },
|
|
224
|
+
{ kind: "expired", activeCount: d.goalSummary.expiredGoals },
|
|
225
|
+
{ kind: "replaced", activeCount: d.goalSummary.replacedGoals },
|
|
226
|
+
{ kind: "active", activeCount: d.goalSummary.activeGoals },
|
|
227
|
+
].filter((g) => g.activeCount > 0),
|
|
228
|
+
quietCount: d.quietDreamSummary.quietRuns,
|
|
229
|
+
dreamCount: d.quietDreamSummary.dreamRuns,
|
|
230
|
+
breakerSummary: d.healthSummary.circuitBreakerChanges > 0
|
|
231
|
+
? [{ connectorId: "aggregate", state: "changed" }]
|
|
232
|
+
: [],
|
|
233
|
+
healthStatus: d.healthSummary.auditChainHealthy ? "ok" : "degraded",
|
|
234
|
+
createdAt: d.generatedAt,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type { GuidanceFallback, GuidancePayload } from "../../../guidance/index.js";
|
|
2
|
-
export interface AppliedGuidanceContext {
|
|
3
|
-
source: "guidance_payload" | "minimal_fallback";
|
|
4
|
-
sceneType: string;
|
|
5
|
-
atmosphereText?: string;
|
|
6
|
-
impulseTexts: string[];
|
|
7
|
-
personaRationales: string[];
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import type { GuidanceFallback, GuidancePayload } from "../../../guidance/index.js";
|
|
2
|
+
export interface AppliedGuidanceContext {
|
|
3
|
+
source: "guidance_payload" | "minimal_fallback";
|
|
4
|
+
sceneType: string;
|
|
5
|
+
atmosphereText?: string;
|
|
6
|
+
impulseTexts: string[];
|
|
7
|
+
personaRationales: string[];
|
|
8
|
+
/** @deprecated Use expressionConstraints. Kept for backward compatibility. */
|
|
9
|
+
outputConstraints: string[];
|
|
10
|
+
expressionConstraints: string[];
|
|
11
|
+
}
|
|
12
|
+
export declare function applyGuidance(input: GuidancePayload | GuidanceFallback): AppliedGuidanceContext;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
export function applyGuidance(input) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
export function applyGuidance(input) {
|
|
2
|
+
const isMinimal = "minimal" in input && input.minimal;
|
|
3
|
+
const boundaryConstraints = input.expressionBoundary?.constraints
|
|
4
|
+
?? input.outputGuard?.constraints
|
|
5
|
+
?? [];
|
|
6
|
+
return {
|
|
7
|
+
source: isMinimal ? "minimal_fallback" : "guidance_payload",
|
|
8
|
+
sceneType: input.scene.sceneType,
|
|
9
|
+
atmosphereText: input.atmosphere?.text,
|
|
10
|
+
impulseTexts: input.impulses.map((item) => item.text),
|
|
11
|
+
personaRationales: input.personaReinforcement.map((item) => item.rationale),
|
|
12
|
+
outputConstraints: input.outputGuard?.constraints ?? [],
|
|
13
|
+
expressionConstraints: boundaryConstraints,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Reply Light Continuity Contract
|
|
3
|
-
*
|
|
4
|
-
* Per T6.1.1: Provides very light continuity guidance for direct user replies.
|
|
5
|
-
* This is separate from the platform `reply` scene - it only provides
|
|
6
|
-
* lightweight persona continuity and tone consistency for user-facing chat.
|
|
7
|
-
*
|
|
8
|
-
* Key differences from platform `reply` scene:
|
|
9
|
-
* - No platform-specific impulses
|
|
10
|
-
* - No comment/reply formatting constraints
|
|
11
|
-
* - Only persona continuity and minimal tone guidance
|
|
12
|
-
* - Does not enter the reply scene impulse system
|
|
13
|
-
*/
|
|
14
|
-
import type { GuidanceFallback, GuidancePayload } from "../../../guidance/index.js";
|
|
15
|
-
import type { PersonaCandidate } from "../../../guidance/index.js";
|
|
16
|
-
/**
|
|
17
|
-
* Scene context for user reply - uses a distinct scene type
|
|
18
|
-
* to avoid confusion with platform reply scene.
|
|
19
|
-
*/
|
|
20
|
-
export declare const USER_REPLY_SCENE_TYPE: "user_reply";
|
|
21
|
-
export type UserReplySceneType = typeof USER_REPLY_SCENE_TYPE;
|
|
22
|
-
/**
|
|
23
|
-
* Build very light continuity guidance for direct user replies.
|
|
24
|
-
*
|
|
25
|
-
* Returns a minimal guidance payload with:
|
|
26
|
-
* - Light atmosphere (continuity-focused)
|
|
27
|
-
* - NO impulses (unlike platform reply scene)
|
|
28
|
-
* - Optional persona reinforcement (1-2 snippets max)
|
|
29
|
-
* - Minimal
|
|
30
|
-
*/
|
|
31
|
-
export declare function buildLightReplyContinuity(input: {
|
|
32
|
-
replyContext: {
|
|
33
|
-
recentTone?: string;
|
|
34
|
-
lastInteractionSummary?: string;
|
|
35
|
-
};
|
|
36
|
-
personaCandidates?: PersonaCandidate[];
|
|
37
|
-
}): Promise<GuidancePayload | GuidanceFallback>;
|
|
38
|
-
/**
|
|
39
|
-
* Check if an input should be classified as direct user reply.
|
|
40
|
-
*
|
|
41
|
-
* Classification criteria:
|
|
42
|
-
* - Trigger source is user_reply
|
|
43
|
-
* - Not a platform comment/reply
|
|
44
|
-
* - Not an explicit task delegation
|
|
45
|
-
*/
|
|
46
|
-
export declare function isDirectUserReply(input: {
|
|
47
|
-
triggerSource: string;
|
|
48
|
-
isPlatformReply: boolean;
|
|
49
|
-
isExplicitTask: boolean;
|
|
50
|
-
}): boolean;
|
|
1
|
+
/**
|
|
2
|
+
* User Reply Light Continuity Contract
|
|
3
|
+
*
|
|
4
|
+
* Per T6.1.1: Provides very light continuity guidance for direct user replies.
|
|
5
|
+
* This is separate from the platform `reply` scene - it only provides
|
|
6
|
+
* lightweight persona continuity and tone consistency for user-facing chat.
|
|
7
|
+
*
|
|
8
|
+
* Key differences from platform `reply` scene:
|
|
9
|
+
* - No platform-specific impulses
|
|
10
|
+
* - No comment/reply formatting constraints
|
|
11
|
+
* - Only persona continuity and minimal tone guidance
|
|
12
|
+
* - Does not enter the reply scene impulse system
|
|
13
|
+
*/
|
|
14
|
+
import type { GuidanceFallback, GuidancePayload } from "../../../guidance/index.js";
|
|
15
|
+
import type { PersonaCandidate } from "../../../guidance/index.js";
|
|
16
|
+
/**
|
|
17
|
+
* Scene context for user reply - uses a distinct scene type
|
|
18
|
+
* to avoid confusion with platform reply scene.
|
|
19
|
+
*/
|
|
20
|
+
export declare const USER_REPLY_SCENE_TYPE: "user_reply";
|
|
21
|
+
export type UserReplySceneType = typeof USER_REPLY_SCENE_TYPE;
|
|
22
|
+
/**
|
|
23
|
+
* Build very light continuity guidance for direct user replies.
|
|
24
|
+
*
|
|
25
|
+
* Returns a minimal guidance payload with:
|
|
26
|
+
* - Light atmosphere (continuity-focused)
|
|
27
|
+
* - NO impulses (unlike platform reply scene)
|
|
28
|
+
* - Optional persona reinforcement (1-2 snippets max)
|
|
29
|
+
* - Minimal expression boundary (tone consistency only)
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildLightReplyContinuity(input: {
|
|
32
|
+
replyContext: {
|
|
33
|
+
recentTone?: string;
|
|
34
|
+
lastInteractionSummary?: string;
|
|
35
|
+
};
|
|
36
|
+
personaCandidates?: PersonaCandidate[];
|
|
37
|
+
}): Promise<GuidancePayload | GuidanceFallback>;
|
|
38
|
+
/**
|
|
39
|
+
* Check if an input should be classified as direct user reply.
|
|
40
|
+
*
|
|
41
|
+
* Classification criteria:
|
|
42
|
+
* - Trigger source is user_reply
|
|
43
|
+
* - Not a platform comment/reply
|
|
44
|
+
* - Not an explicit task delegation
|
|
45
|
+
*/
|
|
46
|
+
export declare function isDirectUserReply(input: {
|
|
47
|
+
triggerSource: string;
|
|
48
|
+
isPlatformReply: boolean;
|
|
49
|
+
isExplicitTask: boolean;
|
|
50
|
+
}): boolean;
|