@lazyingart/agent-web 0.1.40

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.
Files changed (42) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +438 -0
  3. package/docs/architecture.md +503 -0
  4. package/package.json +43 -0
  5. package/src/aginti-adapter.js +602 -0
  6. package/src/chat-context.js +1020 -0
  7. package/src/chat-migrations.js +947 -0
  8. package/src/chat-store.js +3308 -0
  9. package/src/cli.js +134 -0
  10. package/src/cloud-server.js +2043 -0
  11. package/src/contracts.js +103 -0
  12. package/src/deterministic-context-summarizer.js +254 -0
  13. package/src/direct-chat-capability-limits.js +66 -0
  14. package/src/direct-chat-contract.js +3 -0
  15. package/src/errors.js +50 -0
  16. package/src/http-contract.js +592 -0
  17. package/src/index.js +88 -0
  18. package/src/localllm-connector.js +667 -0
  19. package/src/migrations.js +231 -0
  20. package/src/operator-health.js +184 -0
  21. package/src/password-verifier.js +131 -0
  22. package/src/service-config.js +547 -0
  23. package/src/service.js +408 -0
  24. package/src/sqlite-health.js +83 -0
  25. package/src/storage-path.js +130 -0
  26. package/src/store.js +914 -0
  27. package/src/validation.js +181 -0
  28. package/src/vision-attachment.js +404 -0
  29. package/src/web/aginti-client.js +552 -0
  30. package/src/web/aginti-protocol.js +1146 -0
  31. package/src/web/asset-map.js +462 -0
  32. package/src/web/browser-app.js +6491 -0
  33. package/src/web/cloud-session-client.js +427 -0
  34. package/src/web/direct-chat-client.js +1482 -0
  35. package/src/web/index.js +10 -0
  36. package/src/web/presentation-state.js +107 -0
  37. package/src/web/pwa-assets.js +854 -0
  38. package/src/web/pwa-update-handoff-store.js +179 -0
  39. package/src/web/safe-rendering.js +836 -0
  40. package/src/web/vision-image-client.js +546 -0
  41. package/src/web/vision-image-sanitizer.js +168 -0
  42. package/src/web/web-release.js +28 -0
@@ -0,0 +1,10 @@
1
+ export * from "./aginti-client.js";
2
+ export * from "./aginti-protocol.js";
3
+ export * from "./asset-map.js";
4
+ export * from "./browser-app.js";
5
+ export * from "./cloud-session-client.js";
6
+ export * from "./direct-chat-client.js";
7
+ export * from "./presentation-state.js";
8
+ export * from "./pwa-assets.js";
9
+ export * from "./safe-rendering.js";
10
+ export * from "./web-release.js";
@@ -0,0 +1,107 @@
1
+ import {
2
+ assertVerifiedAgentEvent,
3
+ initialEventCursor,
4
+ validateRunId,
5
+ validateThreadId,
6
+ } from "./aginti-protocol.js";
7
+
8
+ const TERMINAL_STATUS = Object.freeze({
9
+ "run.completed": "completed",
10
+ "run.failed": "failed",
11
+ "run.cancelled": "cancelled",
12
+ });
13
+ const TERMINAL_RUN_STATUS = new Set(Object.values(TERMINAL_STATUS));
14
+
15
+ function copyCursor(value) {
16
+ const initial = initialEventCursor();
17
+ if (value === undefined) return initial;
18
+ if (value === null || typeof value !== "object" || Array.isArray(value)
19
+ || !Number.isSafeInteger(value.seq) || value.seq < 0
20
+ || typeof value.hash !== "string" || !/^[a-f0-9]{64}$/u.test(value.hash)
21
+ || Object.keys(value).some((key) => !["seq", "hash"].includes(key))) {
22
+ throw new TypeError("presentation cursor is invalid");
23
+ }
24
+ if (value.seq === 0 && value.hash !== initial.hash) throw new TypeError("initial presentation cursor hash must be zero");
25
+ return Object.freeze({ seq: value.seq, hash: value.hash });
26
+ }
27
+
28
+ function freezeArray(value) {
29
+ return Object.freeze(value.map((item) => Object.freeze({ ...item })));
30
+ }
31
+
32
+ /*
33
+ * A run projection is deliberately disposable presentation state. It never
34
+ * creates work, compacts context, chooses tools, or synthesizes artifacts.
35
+ * Reloading it from AgInTi's authoritative replay must always be safe.
36
+ */
37
+ export function createRunPresentation({ runId, threadId, cursor } = {}) {
38
+ validateRunId(runId);
39
+ validateThreadId(threadId);
40
+ let delivery = copyCursor(cursor);
41
+ let status = "starting";
42
+ let terminalStatus = null;
43
+ let output = "";
44
+ let outputComplete = false;
45
+ let plan = [];
46
+ let compaction = null;
47
+ const tools = new Map();
48
+ const artifacts = new Map();
49
+
50
+ function snapshot() {
51
+ return Object.freeze({
52
+ authority: "aginti",
53
+ authoritative: false,
54
+ runId,
55
+ threadId,
56
+ cursor: delivery,
57
+ status,
58
+ terminalStatus,
59
+ output,
60
+ outputComplete,
61
+ plan: freezeArray(plan),
62
+ compaction: compaction === null ? null : Object.freeze({ ...compaction }),
63
+ tools: freezeArray([...tools.values()]),
64
+ artifacts: Object.freeze([...artifacts.values()]),
65
+ });
66
+ }
67
+
68
+ function apply(value) {
69
+ const event = assertVerifiedAgentEvent(value);
70
+ if (event.runId !== runId || event.threadId !== threadId) throw new TypeError("event does not belong to this presentation");
71
+ if (event.seq !== delivery.seq + 1 || event.previousHash !== delivery.hash) throw new TypeError("event is not contiguous with this presentation");
72
+ if (terminalStatus !== null) throw new TypeError("event arrived after the terminal run event");
73
+ delivery = Object.freeze({ seq: event.seq, hash: event.hash });
74
+ if (event.type === "run.status") {
75
+ // A status payload is presentation progress only. Completion authority is
76
+ // carried exclusively by the hash-chained terminal event below.
77
+ if (!TERMINAL_RUN_STATUS.has(event.payload.status)) status = event.payload.status;
78
+ }
79
+ else if (event.type === "plan.updated") plan = event.payload.steps.map((step) => ({ ...step }));
80
+ else if (event.type === "context.compacted") compaction = { ...event.payload };
81
+ else if (event.type.startsWith("tool.")) {
82
+ tools.set(event.payload.callId, {
83
+ callId: event.payload.callId,
84
+ label: event.payload.publicLabel,
85
+ summary: event.payload.publicSummary,
86
+ at: event.payload.at,
87
+ state: event.type.slice("tool.".length),
88
+ });
89
+ } else if (event.type === "output.delta") {
90
+ if (outputComplete) throw new TypeError("output delta arrived after output.completed");
91
+ output += event.payload.text;
92
+ if (output.length > 32_000) throw new TypeError("presentation output exceeded 32000 characters");
93
+ } else if (event.type === "output.completed") outputComplete = true;
94
+ else if (event.type === "artifact.created" || event.type === "artifact.updated") {
95
+ if (event.type === "artifact.updated" && !artifacts.has(event.payload.artifact.id)) {
96
+ throw new TypeError("artifact.updated arrived before artifact.created");
97
+ }
98
+ artifacts.set(event.payload.artifact.id, event.payload.artifact);
99
+ } else if (Object.hasOwn(TERMINAL_STATUS, event.type)) {
100
+ status = TERMINAL_STATUS[event.type];
101
+ terminalStatus = status;
102
+ }
103
+ return snapshot();
104
+ }
105
+
106
+ return Object.freeze({ apply, snapshot });
107
+ }