@vibeiao/sdk 0.1.29 → 0.1.31

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/README.md CHANGED
@@ -7,6 +7,20 @@ Agent-side tooling for discovery, payments, and marketing on VIBEIAO.
7
7
  The SDK expects a global `fetch`. If your agent runs on Node 18+, you’re fine.
8
8
  For Node 16 or older, pass a custom `fetcher` to `VibeClient` or polyfill `fetch`.
9
9
 
10
+ ## Human App Category Contract (Required)
11
+
12
+ For listings with `listingType = "human"`, category is a strict two-value contract:
13
+
14
+ - `SaaS`
15
+ - `Games`
16
+
17
+ Implementation rules:
18
+
19
+ - Use canonical values in payload/config (`SaaS` or `Games`).
20
+ - Do not use custom human categories (`Automation`, `Tool`, `Entertainment`, etc.).
21
+ - CLI/SDK normalize some aliases, but agents should still emit canonical values.
22
+ - API validation enforces this contract for human listings.
23
+
10
24
  ## Mandatory SDK Updates (Required Runtime Policy)
11
25
 
12
26
  Agents should not run stale SDK versions.
@@ -1,14 +1,92 @@
1
1
  import { SelfReliance, ResourceSnapshot, SelfRelianceState } from './selfReliance.js';
2
2
  import { SurvivalMode, SurvivalRecommendation } from './survivalPlaybook.js';
3
+ import { EscapeHatchDecision, EscapeHatchPolicy, EscapeHatchSnapshot } from './survivalEscapeHatch.js';
4
+ import { CompoundingMemoryUpgradeResult, CompoundingMemoryRequiredSetResult } from './compoundingMemory.js';
3
5
 
6
+ type AgentLoopEscapeHatchInput = {
7
+ snapshot: ResourceSnapshot;
8
+ survivalState: SelfRelianceState;
9
+ survivalMode: SurvivalMode;
10
+ timestamp: number;
11
+ };
12
+ type AgentLoopEscapeHatchConfig = {
13
+ /** Enable auto escape-hatch evaluation (default true, only in SURVIVE/BLINK). */
14
+ enabled?: boolean;
15
+ policy?: EscapeHatchPolicy;
16
+ resolveEnv?: (name: string) => string | undefined;
17
+ /**
18
+ * Optional mapper from loop context -> escape hatch snapshot.
19
+ * If omitted, a default mapper reads optional fields from snapshot.
20
+ */
21
+ buildSnapshot?: (input: AgentLoopEscapeHatchInput) => EscapeHatchSnapshot | null | undefined;
22
+ /** Called when an escape-hatch decision is produced. */
23
+ onDecision?: (decision: EscapeHatchDecision, input: AgentLoopEscapeHatchInput) => Promise<void> | void;
24
+ };
4
25
  type AgentLoopContext = {
5
26
  snapshot: ResourceSnapshot;
6
27
  survivalState: SelfRelianceState;
7
28
  survivalMode: SurvivalMode;
8
29
  survivalRecommendation: SurvivalRecommendation;
9
30
  survivalFormatted: string;
31
+ /** Deterministic block for planners/loggers: survival + escape-hatch decision (if present). */
32
+ survivalDecisionBlock: string;
33
+ /** Present when escape-hatch evaluation runs (SURVIVE/BLINK by default). */
34
+ escapeHatchDecision?: EscapeHatchDecision;
35
+ escapeHatchFormatted?: string;
36
+ /** Present when memory auto-upgrade is enabled in the loop. */
37
+ memoryUpgrade?: CompoundingMemoryUpgradeResult;
38
+ /** Present when required-set maintenance check runs (default daily). */
39
+ memoryRequiredSet?: CompoundingMemoryRequiredSetResult;
10
40
  timestamp: number;
11
41
  };
42
+ type AgentLoopMemoryConfig = {
43
+ /** Enable one-time memory scaffold upgrade. Default true. */
44
+ enabled?: boolean;
45
+ /** Workspace root for compounding memory files. Default current working directory ("."). */
46
+ root?: string;
47
+ /** Timezone for daily ledger date key. Default UTC. */
48
+ timeZone?: string;
49
+ /** Hook called after memory upgrade check completes. */
50
+ onUpgrade?: (result: CompoundingMemoryUpgradeResult) => Promise<void> | void;
51
+ /** Enable required-set maintenance checks (bounded working state + recall substrate + restore drill). Default true. */
52
+ requiredSetEnabled?: boolean;
53
+ /** Interval for required-set checks. Default 24h. */
54
+ requiredSetIntervalMs?: number;
55
+ /** Run required-set check on first loop cycle. Default true. */
56
+ requiredSetRunOnStart?: boolean;
57
+ /** Include backup+restore drill in required-set check. Default true. */
58
+ requiredSetRunRestoreDrill?: boolean;
59
+ /** Hook called when required-set check runs. */
60
+ onRequiredSet?: (result: CompoundingMemoryRequiredSetResult) => Promise<void> | void;
61
+ };
62
+ type AgentLoopDurabilityConfig = {
63
+ /** Enable durability-proxy writes from runtime loop. Default false. */
64
+ enabled?: boolean;
65
+ /** Durability-proxy base URL (e.g. http://127.0.0.1:8790). */
66
+ baseUrl: string;
67
+ /** Agent id registered in durability-proxy. */
68
+ agentId: string;
69
+ /** Agent token registered in durability-proxy. */
70
+ agentToken: string;
71
+ /** Optional timeout for durability-proxy calls. Default 8000ms. */
72
+ timeoutMs?: number;
73
+ /** Write checkpoint after each required-set run. Default true. */
74
+ checkpointOnRequiredSet?: boolean;
75
+ /** Write restore-drill outcome when required-set includes restore drill. Default true. */
76
+ reportRestoreDrill?: boolean;
77
+ /** Called when durability checkpoint is written. */
78
+ onCheckpointWritten?: (result: {
79
+ checkpointId?: string;
80
+ createdAt?: string;
81
+ checkedAt: string;
82
+ }) => Promise<void> | void;
83
+ /** Called when durability restore drill signal is written. */
84
+ onRestoreDrillReported?: (result: {
85
+ ok: boolean;
86
+ ts?: string;
87
+ checkedAt: string;
88
+ }) => Promise<void> | void;
89
+ };
12
90
  type AgentLoopHooks = {
13
91
  /** Called every cycle after snapshot is fetched and survival state is updated. */
14
92
  onCycle?: (ctx: AgentLoopContext) => Promise<void> | void;
@@ -33,13 +111,17 @@ type AgentLoopConfig = {
33
111
  /** Optional override for time source (tests). */
34
112
  now?: () => number;
35
113
  hooks?: AgentLoopHooks;
114
+ escapeHatch?: AgentLoopEscapeHatchConfig;
115
+ memory?: AgentLoopMemoryConfig;
116
+ durability?: AgentLoopDurabilityConfig;
36
117
  };
37
118
  /**
38
119
  * Create a closed-loop runner that:
39
120
  * 1) fetches a resource snapshot
40
121
  * 2) updates SelfReliance
41
122
  * 3) classifies survival mode + produces a playbook recommendation
42
- * 4) optionally runs reflection + action hooks
123
+ * 4) auto-evaluates escape hatch in SURVIVE/BLINK (guardrail decision block)
124
+ * 5) optionally runs reflection + action hooks
43
125
  *
44
126
  * Non-breaking by design: you choose what to do with the context.
45
127
  */
@@ -49,4 +131,4 @@ declare const createAgentLoop: (config: AgentLoopConfig) => {
49
131
  runOnce: () => Promise<void>;
50
132
  };
51
133
 
52
- export { type AgentLoopConfig, type AgentLoopContext, type AgentLoopHooks, createAgentLoop };
134
+ export { type AgentLoopConfig, type AgentLoopContext, type AgentLoopDurabilityConfig, type AgentLoopEscapeHatchConfig, type AgentLoopEscapeHatchInput, type AgentLoopHooks, type AgentLoopMemoryConfig, createAgentLoop };
package/dist/agentLoop.js CHANGED
@@ -1,8 +1,251 @@
1
1
  import {
2
- createAgentLoop
3
- } from "./chunk-7JT4JPEY.js";
4
- import "./chunk-M7DQTU5R.js";
5
- import "./chunk-JQE72P4C.js";
2
+ runCompoundingMemoryRequiredSet,
3
+ upgradeCompoundingMemorySystem
4
+ } from "./chunk-JJNRDU7F.js";
5
+ import {
6
+ createDurabilityProxyClient
7
+ } from "./chunk-PVCW4MAY.js";
8
+ import {
9
+ evaluateEscapeHatch,
10
+ formatEscapeHatchDecision
11
+ } from "./chunk-EBI7WT76.js";
12
+ import {
13
+ classifySurvivalMode,
14
+ formatSurvivalRecommendation,
15
+ getSurvivalRecommendation
16
+ } from "./chunk-JQE72P4C.js";
17
+ import {
18
+ createSelfRelianceMonitor
19
+ } from "./chunk-M7DQTU5R.js";
20
+
21
+ // src/agentLoop.ts
22
+ var asFiniteNumber = (value) => {
23
+ const n = typeof value === "number" ? value : Number(value);
24
+ return Number.isFinite(n) ? n : void 0;
25
+ };
26
+ var asBoolean = (value) => {
27
+ return typeof value === "boolean" ? value : void 0;
28
+ };
29
+ var defaultEscapeHatchSnapshotBuilder = (input) => {
30
+ const raw = input.snapshot;
31
+ return {
32
+ mode: input.survivalMode,
33
+ estimatedProvisionUsd: asFiniteNumber(raw.estimatedProvisionUsd),
34
+ currentReserveUsd: asFiniteNumber(raw.currentReserveUsd),
35
+ hasPreProvisionedProviderAccount: asBoolean(raw.hasPreProvisionedProviderAccount),
36
+ hasProviderApiKey: asBoolean(raw.hasProviderApiKey),
37
+ backupWrittenAtMs: asFiniteNumber(raw.backupWrittenAtMs),
38
+ restoreDrillPassedAtMs: asFiniteNumber(raw.restoreDrillPassedAtMs),
39
+ nowMs: input.timestamp
40
+ };
41
+ };
42
+ var createAgentLoop = (config) => {
43
+ const now = config.now ?? (() => Date.now());
44
+ const intervalMs = config.intervalMs ?? 6e4;
45
+ const guardAct = config.guardAct ?? true;
46
+ const hooks = config.hooks ?? {};
47
+ const memoryEnabled = config.memory?.enabled ?? true;
48
+ const memoryRoot = config.memory?.root ?? ".";
49
+ const memoryTimeZone = config.memory?.timeZone;
50
+ const requiredSetEnabled = config.memory?.requiredSetEnabled ?? true;
51
+ const requiredSetIntervalMs = Math.max(6e4, config.memory?.requiredSetIntervalMs ?? 24 * 60 * 60 * 1e3);
52
+ const requiredSetRunOnStart = config.memory?.requiredSetRunOnStart ?? true;
53
+ const requiredSetRunRestoreDrill = config.memory?.requiredSetRunRestoreDrill ?? true;
54
+ const durabilityEnabled = config.durability?.enabled ?? false;
55
+ const durabilityClient = durabilityEnabled ? createDurabilityProxyClient({
56
+ baseUrl: config.durability?.baseUrl || "",
57
+ agentId: config.durability?.agentId || "",
58
+ agentToken: config.durability?.agentToken || "",
59
+ timeoutMs: config.durability?.timeoutMs
60
+ }) : null;
61
+ const checkpointOnRequiredSet = config.durability?.checkpointOnRequiredSet ?? true;
62
+ const reportRestoreDrill = config.durability?.reportRestoreDrill ?? true;
63
+ let memoryUpgradePromise = null;
64
+ let memoryUpgradeHookFired = false;
65
+ let lastRequiredSetCheckAt = requiredSetRunOnStart ? 0 : now();
66
+ let lastRequiredSetResult = null;
67
+ let lastDurabilitySyncCheckedAt = null;
68
+ const ensureMemoryUpgrade = async () => {
69
+ if (!memoryEnabled) return null;
70
+ if (!memoryUpgradePromise) {
71
+ memoryUpgradePromise = upgradeCompoundingMemorySystem({
72
+ root: memoryRoot,
73
+ timeZone: memoryTimeZone
74
+ });
75
+ }
76
+ const result = await memoryUpgradePromise;
77
+ if (config.memory?.onUpgrade && !memoryUpgradeHookFired) {
78
+ memoryUpgradeHookFired = true;
79
+ await config.memory.onUpgrade(result);
80
+ }
81
+ return result;
82
+ };
83
+ const maybeRunRequiredSet = async (timestamp) => {
84
+ if (!memoryEnabled || !requiredSetEnabled) return null;
85
+ if (timestamp - lastRequiredSetCheckAt < requiredSetIntervalMs) {
86
+ return lastRequiredSetResult;
87
+ }
88
+ const result = await runCompoundingMemoryRequiredSet({
89
+ root: memoryRoot,
90
+ timeZone: memoryTimeZone,
91
+ runBackupRestoreDrill: requiredSetRunRestoreDrill
92
+ });
93
+ lastRequiredSetCheckAt = timestamp;
94
+ lastRequiredSetResult = result;
95
+ if (config.memory?.onRequiredSet) {
96
+ await config.memory.onRequiredSet(result);
97
+ }
98
+ return result;
99
+ };
100
+ const maybeSyncDurability = async (snapshot, memoryRequiredSet, timestamp) => {
101
+ if (!durabilityClient || !memoryRequiredSet) return;
102
+ if (lastDurabilitySyncCheckedAt === memoryRequiredSet.checkedAt) return;
103
+ const checkpointMeta = {
104
+ checkedAt: memoryRequiredSet.checkedAt,
105
+ requiredSetOk: memoryRequiredSet.ok,
106
+ workingStateBounded: memoryRequiredSet.workingState.bounded,
107
+ recallReady: memoryRequiredSet.recall.ok,
108
+ restoreDrillOk: memoryRequiredSet.restoreDrill?.ok ?? null
109
+ };
110
+ if (checkpointOnRequiredSet) {
111
+ const checkpointRes = await durabilityClient.writeCheckpoint(
112
+ {
113
+ kind: "compounding_memory_required_set",
114
+ checkedAt: memoryRequiredSet.checkedAt,
115
+ result: memoryRequiredSet
116
+ },
117
+ {
118
+ metadata: checkpointMeta
119
+ }
120
+ );
121
+ const createdAt = checkpointRes?.checkpoint?.createdAt || new Date(timestamp).toISOString();
122
+ const createdAtMs = Number(new Date(createdAt));
123
+ if (Number.isFinite(createdAtMs)) {
124
+ snapshot.backupWrittenAtMs = createdAtMs;
125
+ }
126
+ if (config.durability?.onCheckpointWritten) {
127
+ await config.durability.onCheckpointWritten({
128
+ checkpointId: checkpointRes?.checkpoint?.id,
129
+ createdAt: checkpointRes?.checkpoint?.createdAt,
130
+ checkedAt: memoryRequiredSet.checkedAt
131
+ });
132
+ }
133
+ if (reportRestoreDrill && memoryRequiredSet.restoreDrill) {
134
+ const drillRes = await durabilityClient.writeRestoreDrill(memoryRequiredSet.restoreDrill.ok, {
135
+ checkpointId: checkpointRes?.checkpoint?.id,
136
+ details: memoryRequiredSet.restoreDrill.ok ? "required_set_restore_drill_passed" : "required_set_restore_drill_failed"
137
+ });
138
+ if (memoryRequiredSet.restoreDrill.ok) {
139
+ snapshot.restoreDrillPassedAtMs = timestamp;
140
+ }
141
+ if (config.durability?.onRestoreDrillReported) {
142
+ await config.durability.onRestoreDrillReported({
143
+ ok: Boolean(drillRes?.drill?.ok),
144
+ ts: drillRes?.drill?.ts,
145
+ checkedAt: memoryRequiredSet.checkedAt
146
+ });
147
+ }
148
+ }
149
+ }
150
+ lastDurabilitySyncCheckedAt = memoryRequiredSet.checkedAt;
151
+ };
152
+ const runOnce = async () => {
153
+ try {
154
+ const memoryUpgrade = await ensureMemoryUpgrade();
155
+ const snapshot = await config.fetchSnapshot();
156
+ const timestamp = now();
157
+ const memoryRequiredSet = await maybeRunRequiredSet(timestamp);
158
+ await maybeSyncDurability(snapshot, memoryRequiredSet, timestamp);
159
+ const survivalState = config.survival.update({
160
+ ...snapshot,
161
+ updatedAt: snapshot.updatedAt ?? timestamp
162
+ });
163
+ const policy = config.survival.policy;
164
+ const survivalMode = classifySurvivalMode(survivalState, policy);
165
+ const survivalRecommendation = getSurvivalRecommendation(survivalMode);
166
+ const survivalFormatted = formatSurvivalRecommendation(survivalRecommendation);
167
+ let escapeHatchDecision;
168
+ let escapeHatchFormatted;
169
+ const escapeEnabled = config.escapeHatch?.enabled ?? true;
170
+ const shouldEvaluateEscapeHatch = escapeEnabled && (survivalMode === "SURVIVE" || survivalMode === "BLINK");
171
+ if (shouldEvaluateEscapeHatch) {
172
+ const input = {
173
+ snapshot,
174
+ survivalState,
175
+ survivalMode,
176
+ timestamp
177
+ };
178
+ const buildSnapshot = config.escapeHatch?.buildSnapshot ?? defaultEscapeHatchSnapshotBuilder;
179
+ const escapeSnapshot = buildSnapshot(input);
180
+ if (escapeSnapshot) {
181
+ escapeHatchDecision = evaluateEscapeHatch(
182
+ escapeSnapshot,
183
+ config.escapeHatch?.policy,
184
+ { resolveEnv: config.escapeHatch?.resolveEnv }
185
+ );
186
+ escapeHatchFormatted = formatEscapeHatchDecision(escapeHatchDecision);
187
+ if (config.escapeHatch?.onDecision) {
188
+ await config.escapeHatch.onDecision(escapeHatchDecision, input);
189
+ }
190
+ }
191
+ }
192
+ const survivalDecisionBlock = [survivalFormatted, escapeHatchFormatted].filter(Boolean).join("\n\n");
193
+ const ctx = {
194
+ snapshot,
195
+ survivalState,
196
+ survivalMode,
197
+ survivalRecommendation,
198
+ survivalFormatted,
199
+ survivalDecisionBlock,
200
+ escapeHatchDecision,
201
+ escapeHatchFormatted,
202
+ memoryUpgrade: memoryUpgrade ?? void 0,
203
+ memoryRequiredSet: memoryRequiredSet ?? void 0,
204
+ timestamp
205
+ };
206
+ if (hooks.onCycle) await hooks.onCycle(ctx);
207
+ if (hooks.onReflection) await hooks.onReflection(ctx);
208
+ if (hooks.onAct) {
209
+ if (guardAct) {
210
+ const allowed = await config.survival.guard();
211
+ if (allowed) {
212
+ await hooks.onAct(ctx);
213
+ }
214
+ } else {
215
+ await hooks.onAct(ctx);
216
+ }
217
+ }
218
+ } catch (err) {
219
+ const e = err instanceof Error ? err : new Error("agent_loop_failed");
220
+ if (hooks.onError) {
221
+ await hooks.onError(e);
222
+ }
223
+ }
224
+ };
225
+ const monitor = createSelfRelianceMonitor(config.survival, config.fetchSnapshot, {
226
+ intervalMs,
227
+ onUpdate: async (snapshot) => {
228
+ void snapshot;
229
+ }
230
+ });
231
+ let timer = null;
232
+ let stopped = false;
233
+ const start = async () => {
234
+ if (timer) return;
235
+ await runOnce();
236
+ if (stopped) return;
237
+ timer = setInterval(runOnce, intervalMs);
238
+ };
239
+ const stop = () => {
240
+ stopped = true;
241
+ if (timer) {
242
+ clearInterval(timer);
243
+ timer = null;
244
+ }
245
+ monitor.stop();
246
+ };
247
+ return { start, stop, runOnce };
248
+ };
6
249
  export {
7
250
  createAgentLoop
8
251
  };