@yeaft/webchat-agent 1.0.599 → 1.0.601
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/local-runtime/version.json +1 -1
- package/local-runtime/web/app.bundle.js +141 -127
- package/local-runtime/web/app.bundle.js.gz +0 -0
- package/local-runtime/web/index.html +2 -2
- package/local-runtime/web/style.bundle.css +1 -1
- package/local-runtime/web/style.bundle.css.gz +0 -0
- package/package.json +1 -1
- package/yeaft/config.js +4 -0
- package/yeaft/person/capabilities.js +26 -14
- package/yeaft/person/contracts.js +7 -6
- package/yeaft/person/native-tools.js +143 -0
- package/yeaft/person/repository.js +47 -4
- package/yeaft/person/runtime.js +43 -15
- package/yeaft/person/service.js +18 -5
- package/yeaft/person/sqlite-repository.js +3 -1
- package/yeaft/person/sqlite-store.js +42 -5
|
@@ -93,6 +93,8 @@ export class SqlitePersonRepository {
|
|
|
93
93
|
async append(episode, kind, data) { return this.request('append', [episode, kind, data]); }
|
|
94
94
|
async startCall(episode, data) { return this.request('startCall', [episode, data]); }
|
|
95
95
|
async finalizeCall(episode, data) { return this.request('finalizeCall', [episode, data]); }
|
|
96
|
+
async startCapability(episode, data) { return this.request('startCapability', [episode, data]); }
|
|
97
|
+
async finalizeCapability(episode, data) { return this.request('finalizeCapability', [episode, data]); }
|
|
96
98
|
async createdCapabilities(episode) { return this.request('createdCapabilities', [episode]); }
|
|
97
99
|
async saveCreatedCapability(episode, input) { return this.request('saveCreatedCapability', [episode, validateCreatedCapability(input)]); }
|
|
98
100
|
async episodeAttachments(episode) { return this.request('episodeAttachments', [episode]); }
|
|
@@ -104,7 +106,7 @@ export class SqlitePersonRepository {
|
|
|
104
106
|
async settings(ownerId, settings) { return this.request('settings', [ownerId, settings]); }
|
|
105
107
|
async list(ownerId, collection, options, filter) { return this.request('list', [ownerId, collection, options, filter]); }
|
|
106
108
|
async snapshot(ownerId) { return this.request('snapshot', [ownerId]); }
|
|
107
|
-
async inspect(ownerId, options) { return this.request('inspect', [ownerId, options]); }
|
|
109
|
+
async inspect(ownerId, options, nativeToolIds) { return this.request('inspect', [ownerId, options, nativeToolIds]); }
|
|
108
110
|
async search(ownerId, options) { return this.request('search', [ownerId, options]); }
|
|
109
111
|
/** Ascending durable journal, scoped before paging. Empty pages retain after. */
|
|
110
112
|
async searchChanges(ownerId, options) { return this.request('searchChanges', [ownerId, options]); }
|
|
@@ -49,7 +49,7 @@ const publicOutput = (output, failed) => {
|
|
|
49
49
|
: { text: output.text, bytes: retainedBytes, complete: true, usage, stopReason };
|
|
50
50
|
};
|
|
51
51
|
const READS = new Set(['receipt', 'inspect', 'search', 'getPerson', 'context', 'recall', 'list', 'searchChanges', 'resolveMemories', 'createdCapabilities', 'episodeAttachments']);
|
|
52
|
-
const WRITES = new Set(['open', 'recover', 'admit', 'heartbeat', 'append', 'startCall', 'finalizeCall', 'commit', 'finish', 'cancel', 'settings', 'snapshot', 'saveCreatedCapability']);
|
|
52
|
+
const WRITES = new Set(['open', 'recover', 'admit', 'heartbeat', 'append', 'startCall', 'finalizeCall', 'startCapability', 'finalizeCapability', 'commit', 'finish', 'cancel', 'settings', 'snapshot', 'saveCreatedCapability']);
|
|
53
53
|
const memoryKind = kind => { if (!['messages', 'concepts'].includes(kind)) fail('INVALID_REQUEST'); return kind; };
|
|
54
54
|
const boundedLimit = (limit, max = 100) => { if (!Number.isSafeInteger(limit) || limit < 1 || limit > max) fail('INVALID_REQUEST'); return limit; };
|
|
55
55
|
const sequence = value => {
|
|
@@ -256,7 +256,7 @@ export class SqlitePersonStore {
|
|
|
256
256
|
}
|
|
257
257
|
append(episode, kind, data) {
|
|
258
258
|
// Call proof/publication events are emitted only by their transactional methods.
|
|
259
|
-
if (['call_started', 'call_output', 'call_failed', 'capability_created'].includes(kind)) fail('INVALID_REQUEST');
|
|
259
|
+
if (['call_started', 'call_output', 'call_failed', 'capability_created', 'capability_finalized'].includes(kind)) fail('INVALID_REQUEST');
|
|
260
260
|
const p = this.own(episode);
|
|
261
261
|
const record = this.one('episodes', this.episodeScope(episode), ' AND id = ?', [episode.id]);
|
|
262
262
|
if (!record || record.status !== 'running') fail('STALE');
|
|
@@ -268,7 +268,7 @@ export class SqlitePersonStore {
|
|
|
268
268
|
startCall(episode, data) {
|
|
269
269
|
const p = this.own(episode), scope = this.episodeScope(episode);
|
|
270
270
|
const record = this.one('episodes', scope, ' AND id = ?', [episode.id]);
|
|
271
|
-
if (!record || record.status !== 'running' || record.openCall) fail('STALE');
|
|
271
|
+
if (!record || record.status !== 'running' || record.openCall || record.openCapability) fail('STALE');
|
|
272
272
|
p.writeSerial++; this.put('persons', p);
|
|
273
273
|
record.openCall = { callId: data.callId, requested: data.requested, effective: data.effective, ...(data.manifest ? { manifest: data.manifest } : {}) };
|
|
274
274
|
this.put('episodes', record);
|
|
@@ -292,6 +292,43 @@ export class SqlitePersonStore {
|
|
|
292
292
|
});
|
|
293
293
|
return live;
|
|
294
294
|
}
|
|
295
|
+
startCapability(episode, data) {
|
|
296
|
+
const p = this.own(episode), scope = this.episodeScope(episode);
|
|
297
|
+
const record = this.one('episodes', scope, ' AND id = ?', [episode.id]);
|
|
298
|
+
const proof = this.one('traces', scope, " AND json_extract(record, '$.episodeId') = ? AND json_extract(record, '$.kind') = 'call_output' AND json_extract(record, '$.callId') = ? AND json_extract(record, '$.output.complete') = 1", [episode.id, data.callId]);
|
|
299
|
+
if (!record || record.status !== 'running' || record.openCall || record.openCapability || !proof) fail('STALE');
|
|
300
|
+
const prior = this.one('traces', scope, " AND json_extract(record, '$.episodeId') = ? AND json_extract(record, '$.kind') = 'capability_started' AND json_extract(record, '$.callId') = ?", [episode.id, data.callId]);
|
|
301
|
+
if (prior) fail('STALE');
|
|
302
|
+
record.openCapability = { ...data, invocationHash: digest(data.capability) };
|
|
303
|
+
this.put('episodes', record);
|
|
304
|
+
p.writeSerial++; this.put('persons', p);
|
|
305
|
+
return this.trace(episode.ownerId, episode.id, 'capability_started', data);
|
|
306
|
+
}
|
|
307
|
+
/** Original started invocation only; consuming this slot never restores cognitive authority. */
|
|
308
|
+
finalizeCapability(episode, { callId, capability, result, code = null, terminalCode = null }) {
|
|
309
|
+
const scope = this.episodeScope(episode), record = this.one('episodes', scope, ' AND id = ?', [episode.id]);
|
|
310
|
+
if (!record || record.workerId !== episode.workerId || record.epoch !== episode.epoch ||
|
|
311
|
+
record.baseStateVersion !== episode.baseStateVersion || record.controlVersion !== episode.controlVersion || record.inputWatermark !== episode.inputWatermark ||
|
|
312
|
+
record.openCapability?.callId !== callId || record.openCapability.invocationHash !== digest(capability) ||
|
|
313
|
+
!['running', 'cancelled', 'interrupted', 'failed'].includes(record.status)) return false;
|
|
314
|
+
const p = record.status === 'running' && this.fenced(episode);
|
|
315
|
+
const live = Boolean(p && !terminalCode);
|
|
316
|
+
const started = record.openCapability;
|
|
317
|
+
const failed = Boolean(code || result?.ok === false);
|
|
318
|
+
const outcome = failed ? 'capability_failed' : 'capability_result';
|
|
319
|
+
const data = { callId, ...(started.capabilityManifest ? { capabilityManifest: started.capabilityManifest } : {}),
|
|
320
|
+
...(failed ? { capabilityId: started.capability.id, code: code || result.code } : { capability: started.capability }),
|
|
321
|
+
...(result !== undefined ? { result } : {}) };
|
|
322
|
+
delete record.openCapability; this.put('episodes', record);
|
|
323
|
+
if (live) {
|
|
324
|
+
const experience = recordCapabilityExperience(p.capabilityExperience, record, outcome, data, this.now.toISOString());
|
|
325
|
+
if (experience) { p.capabilityExperience = experience; this.put('persons', p); }
|
|
326
|
+
}
|
|
327
|
+
this.trace(episode.ownerId, episode.id, live ? outcome : 'capability_finalized', { ...data,
|
|
328
|
+
...(!live ? { capability: started.capability, workerId: record.workerId, outcome, afterTerminal: true, accepted: false,
|
|
329
|
+
terminalCode: terminalCode || record.terminalCode || 'STALE' } : {}) });
|
|
330
|
+
return live;
|
|
331
|
+
}
|
|
295
332
|
createdCapabilities(episode) {
|
|
296
333
|
this.own(episode);
|
|
297
334
|
return this.rows('created_capabilities', this.episodeScope(episode), ' ORDER BY id ASC LIMIT 32').map(publicDoc);
|
|
@@ -392,11 +429,11 @@ export class SqlitePersonStore {
|
|
|
392
429
|
if (Object.keys(settings).length) this.trace(ownerId, null, 'settings', { settings: settingsView(p.settings), ...(name !== undefined ? { name: p.name } : {}) });
|
|
393
430
|
return { settings: settingsView(p.settings), person: this.personView(p) };
|
|
394
431
|
}
|
|
395
|
-
inspect(ownerId, options) {
|
|
432
|
+
inspect(ownerId, options, nativeToolIds) {
|
|
396
433
|
const { section, cursor, limit } = inspectRequest(options);
|
|
397
434
|
this.getPerson(ownerId);
|
|
398
435
|
const scope = this.scope(ownerId);
|
|
399
|
-
if (section === 'skills') return inspectCapabilities(this.rows('created_capabilities', scope, ' ORDER BY id ASC LIMIT 32'), { cursor, limit });
|
|
436
|
+
if (section === 'skills') return inspectCapabilities(this.rows('created_capabilities', scope, ' ORDER BY id ASC LIMIT 32'), { cursor, limit }, nativeToolIds);
|
|
400
437
|
const records = this.rows('concepts', scope, ' AND (? IS NULL OR id > ?) ORDER BY id ASC LIMIT ?', [cursor, cursor, limit + 1]);
|
|
401
438
|
return inspectionPage(records, limit, 'id', conceptView);
|
|
402
439
|
}
|