@xopcai/xopc 0.0.435 → 0.0.436
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/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{index-8xLWo0Tt.js → index-C4moZbZv.js} +1 -1
- package/dist/gateway/static/root/index.html +1 -1
- package/dist/package.js +1 -1
- package/dist/src/agent/tool-manuals/computer.d.ts +1 -1
- package/dist/src/agent/tool-manuals/computer.js +1 -1
- package/dist/src/computer/broker.d.ts +3 -0
- package/dist/src/computer/broker.js +19 -9
- package/dist/src/computer/diagnostics.d.ts +340 -0
- package/dist/src/computer/diagnostics.js +4 -0
- package/dist/src/computer/errors.d.ts +340 -0
- package/dist/src/computer/errors.js +121 -4
- package/dist/src/computer/evaluation.d.ts +186 -0
- package/dist/src/computer/model-adapter.js +47 -20
- package/dist/src/computer/runtime.d.ts +170 -0
- package/dist/src/computer/runtime.js +36 -8
- package/dist/src/computer/stability-diagnostics.d.ts +23 -0
- package/dist/src/computer/stability-diagnostics.js +71 -0
- package/dist/src/computer/validation-diagnostics.d.ts +9 -0
- package/dist/src/computer/validation-diagnostics.js +54 -0
- package/dist/src/gateway/service.js +4 -4
- package/dist/src/home-intelligence/host.js +2 -2
- package/dist/src/realtime/runtime.js +13 -5
- package/dist/src/realtime/writer.d.ts +7 -0
- package/dist/src/realtime/writer.js +96 -30
- package/package.json +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ComputerTarget } from '@xopcai/computer-control-contract';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import type { ComputerDiagnosticSchema, ComputerStabilitySchema } from './errors.js';
|
|
4
|
+
type Stability = z.infer<typeof ComputerStabilitySchema>;
|
|
5
|
+
type Snapshot = {
|
|
6
|
+
target: ComputerTarget;
|
|
7
|
+
summary: string;
|
|
8
|
+
stateDigest: string;
|
|
9
|
+
imageWidth: number;
|
|
10
|
+
imageHeight: number;
|
|
11
|
+
};
|
|
12
|
+
/** Compare privately; retain only fixed change categories and bounded element positions, never values or hashes. */
|
|
13
|
+
export declare class ComputerStabilityTracker {
|
|
14
|
+
private readonly stage;
|
|
15
|
+
private readonly action?;
|
|
16
|
+
private readonly changes;
|
|
17
|
+
private readonly indices;
|
|
18
|
+
constructor(stage: Stability['stage'], action?: Stability['action']);
|
|
19
|
+
deadline(): void;
|
|
20
|
+
compare(before: Snapshot, after: Snapshot): void;
|
|
21
|
+
diagnostic(errorCode: string, samples: number): z.infer<typeof ComputerDiagnosticSchema>;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
//#region src/computer/stability-diagnostics.ts
|
|
3
|
+
/** Compare privately; retain only fixed change categories and bounded element positions, never values or hashes. */
|
|
4
|
+
var ComputerStabilityTracker = class {
|
|
5
|
+
changes = /* @__PURE__ */ new Set();
|
|
6
|
+
indices = /* @__PURE__ */ new Set();
|
|
7
|
+
constructor(stage, action) {
|
|
8
|
+
this.stage = stage;
|
|
9
|
+
this.action = action;
|
|
10
|
+
}
|
|
11
|
+
deadline() {
|
|
12
|
+
this.changes.add("deadline");
|
|
13
|
+
}
|
|
14
|
+
compare(before, after) {
|
|
15
|
+
const a = before.target, b = after.target;
|
|
16
|
+
if (a.appId !== b.appId || a.pid !== b.pid || a.processIdentity !== b.processIdentity || a.windowId !== b.windowId) this.changes.add("window_identity");
|
|
17
|
+
if (a.geometryRevision !== b.geometryRevision || a.width !== b.width || a.height !== b.height) this.changes.add("window_geometry");
|
|
18
|
+
if (before.imageWidth !== after.imageWidth || before.imageHeight !== after.imageHeight) this.changes.add("image_dimensions");
|
|
19
|
+
if (before.summary !== after.summary) try {
|
|
20
|
+
const left = JSON.parse(before.summary), right = JSON.parse(after.summary);
|
|
21
|
+
const ae = Array.isArray(left.elements) ? left.elements : [], be = Array.isArray(right.elements) ? right.elements : [];
|
|
22
|
+
if (ae.length !== be.length) this.changes.add("accessibility_structure");
|
|
23
|
+
if (left.text !== right.text) this.changes.add("accessibility_text");
|
|
24
|
+
const groups = {
|
|
25
|
+
accessibility_structure: [
|
|
26
|
+
"role",
|
|
27
|
+
"ref",
|
|
28
|
+
"depth",
|
|
29
|
+
"parent_index"
|
|
30
|
+
],
|
|
31
|
+
accessibility_text: [
|
|
32
|
+
"label",
|
|
33
|
+
"value",
|
|
34
|
+
"value_description"
|
|
35
|
+
],
|
|
36
|
+
accessibility_state: [
|
|
37
|
+
"enabled",
|
|
38
|
+
"selected",
|
|
39
|
+
"keyboardFocused",
|
|
40
|
+
"inputAllowed",
|
|
41
|
+
"semanticActions",
|
|
42
|
+
"in_web_content"
|
|
43
|
+
],
|
|
44
|
+
accessibility_geometry: ["bounds", "frame"]
|
|
45
|
+
};
|
|
46
|
+
for (let i = 0; i < Math.max(ae.length, be.length); i++) {
|
|
47
|
+
if (JSON.stringify(ae[i]) !== JSON.stringify(be[i]) && this.indices.size < 8 && i <= 16384) this.indices.add(i);
|
|
48
|
+
for (const [category, fields] of Object.entries(groups)) if (fields.some((field) => JSON.stringify(ae[i]?.[field]) !== JSON.stringify(be[i]?.[field]))) this.changes.add(category);
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
this.changes.add("accessibility_structure");
|
|
52
|
+
}
|
|
53
|
+
if (before.stateDigest !== after.stateDigest && before.summary === after.summary && JSON.stringify(a) === JSON.stringify(b) && before.imageWidth === after.imageWidth && before.imageHeight === after.imageHeight) this.changes.add("visual_or_unexposed_state");
|
|
54
|
+
}
|
|
55
|
+
diagnostic(errorCode, samples) {
|
|
56
|
+
return {
|
|
57
|
+
errorCode,
|
|
58
|
+
phase: this.stage === "initial_capture" ? "observe" : "dispatch",
|
|
59
|
+
diagnosticId: randomUUID(),
|
|
60
|
+
stability: {
|
|
61
|
+
stage: this.stage,
|
|
62
|
+
samples,
|
|
63
|
+
...this.action ? { action: this.action } : {},
|
|
64
|
+
changes: [...this.changes],
|
|
65
|
+
changedElementIndices: [...this.indices]
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
//#endregion
|
|
71
|
+
export { ComputerStabilityTracker };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ComputerValidationSchema } from './errors.js';
|
|
3
|
+
type Validation = z.infer<typeof ComputerValidationSchema>;
|
|
4
|
+
/** Project only allowlisted metadata; Zod messages, values and arbitrary property names may contain private data. */
|
|
5
|
+
export declare function modelValidation(value: unknown, stage: Validation['stage'], error?: unknown, failure?: {
|
|
6
|
+
path: (string | number)[];
|
|
7
|
+
code: Validation['issues'][number]['code'];
|
|
8
|
+
}): Validation;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ComputerValidationSchema } from "./errors.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/computer/validation-diagnostics.ts
|
|
4
|
+
const Field = ComputerValidationSchema.shape.issues.element.shape.path.element;
|
|
5
|
+
const Action = ComputerValidationSchema.shape.action;
|
|
6
|
+
const Code = ComputerValidationSchema.shape.issues.element.shape.code;
|
|
7
|
+
function actionName(value) {
|
|
8
|
+
if (!value || typeof value !== "object") return "unknown";
|
|
9
|
+
const node = value;
|
|
10
|
+
return Action.safeParse(typeof node.action === "string" ? node.action : node.kind).data ?? "unknown";
|
|
11
|
+
}
|
|
12
|
+
/** Project only allowlisted metadata; Zod messages, values and arbitrary property names may contain private data. */
|
|
13
|
+
function modelValidation(value, stage, error, failure) {
|
|
14
|
+
const root = value && typeof value === "object" ? value : {};
|
|
15
|
+
const payload = root.arguments && typeof root.arguments === "object" ? root.arguments : root;
|
|
16
|
+
const proposal = payload.proposal && typeof payload.proposal === "object" ? payload.proposal : payload;
|
|
17
|
+
const action = actionName(typeof proposal.action === "object" ? proposal.action : proposal);
|
|
18
|
+
const issues = [];
|
|
19
|
+
const append = (path, code) => {
|
|
20
|
+
if (issues.length >= 4) return;
|
|
21
|
+
let node = value;
|
|
22
|
+
let nestedAction = action;
|
|
23
|
+
for (const part of path) {
|
|
24
|
+
if (!node || typeof node !== "object") break;
|
|
25
|
+
node = node[part];
|
|
26
|
+
const candidate = actionName(node);
|
|
27
|
+
if (candidate !== "unknown") nestedAction = candidate;
|
|
28
|
+
}
|
|
29
|
+
issues.push({
|
|
30
|
+
path: path.slice(0, 10).map((part) => Field.safeParse(part).data ?? "unknown_field"),
|
|
31
|
+
code: Code.safeParse(code).data ?? "invalid_value",
|
|
32
|
+
action: nestedAction
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const branchScore = (list) => list.length + list.filter((issue) => issue.code === "invalid_value" && ["kind", "action"].includes(String(issue.path.at(-1)))).length * 100;
|
|
36
|
+
const visit = (list, prefix = []) => {
|
|
37
|
+
for (const issue of list) if (issue.code === "invalid_union" && issue.errors.length) visit([...issue.errors].sort((a, b) => branchScore(a) - branchScore(b))[0], [...prefix, ...issue.path]);
|
|
38
|
+
else if (issue.code === "unrecognized_keys") for (const key of issue.keys) append([
|
|
39
|
+
...prefix,
|
|
40
|
+
...issue.path,
|
|
41
|
+
key
|
|
42
|
+
], issue.code);
|
|
43
|
+
else append([...prefix, ...issue.path], issue.code);
|
|
44
|
+
};
|
|
45
|
+
if (error instanceof z.ZodError) visit(error.issues);
|
|
46
|
+
if (failure) append(failure.path, failure.code);
|
|
47
|
+
return {
|
|
48
|
+
action,
|
|
49
|
+
stage,
|
|
50
|
+
issues
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { modelValidation };
|
|
@@ -103,10 +103,6 @@ import { DiscussionSealer } from "../discussions/sealer.js";
|
|
|
103
103
|
import "../discussions/index.js";
|
|
104
104
|
import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
|
|
105
105
|
import "../endpoint-tools/index.js";
|
|
106
|
-
import { HomeCapabilityPreflightService } from "../home-intelligence/capability-preflight.js";
|
|
107
|
-
import { HomeAdviceGenerator } from "../home-intelligence/generator.js";
|
|
108
|
-
import { HomeIntelligenceHost } from "../home-intelligence/host.js";
|
|
109
|
-
import { HomeSnapshotBuilder } from "../home-intelligence/snapshot.js";
|
|
110
106
|
import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
|
|
111
107
|
import { prepareAutomationAgentSession } from "./automation-agent-session.js";
|
|
112
108
|
import { deliverAutomationCompletion } from "./automation-completion-delivery.js";
|
|
@@ -170,6 +166,10 @@ import { TaskMainUpdateDecisionService } from "../tasks/task-main-update-decisio
|
|
|
170
166
|
import { selectTaskMainUpdateAttempt, submitAndConfirmTaskMainUpdate } from "../tasks/task-main-update-input.js";
|
|
171
167
|
import { checkAppContextAccess, prepareAppContext } from "./service/app-context-access.js";
|
|
172
168
|
import { applyAutomaticVoiceLanguage, inferProductLanguageFromEnvironment, initializeVoiceDefaults } from "../voice/language-profile.js";
|
|
169
|
+
import { HomeAdviceGenerator } from "../home-intelligence/generator.js";
|
|
170
|
+
import { HomeIntelligenceHost } from "../home-intelligence/host.js";
|
|
171
|
+
import { HomeSnapshotBuilder } from "../home-intelligence/snapshot.js";
|
|
172
|
+
import { HomeCapabilityPreflightService } from "../home-intelligence/capability-preflight.js";
|
|
173
173
|
import crypto from "node:crypto";
|
|
174
174
|
//#region src/gateway/service.ts
|
|
175
175
|
init_session_repository();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { HomeAdviceBudgetExceededError, isHomeProseLocalized } from "./generator.js";
|
|
3
4
|
import { homePatternKey } from "./strategy.js";
|
|
5
|
+
import { HomeAdvicePolicy } from "./policy.js";
|
|
4
6
|
import { HomeIntelligenceRepository } from "./repository.js";
|
|
5
7
|
import { HomeOpportunityApplicationService } from "./application-service.js";
|
|
6
|
-
import { HomeAdvicePolicy } from "./policy.js";
|
|
7
|
-
import { HomeAdviceBudgetExceededError, isHomeProseLocalized } from "./generator.js";
|
|
8
8
|
import { buildHomeOpportunityNotification } from "./notification.js";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
10
|
//#region src/home-intelligence/host.ts
|
|
@@ -195,15 +195,23 @@ var RealtimeRuntime = class {
|
|
|
195
195
|
const output = item.view === "compact" ? compactRunEvent(event) : event;
|
|
196
196
|
if (output) writer.enqueue(output);
|
|
197
197
|
});
|
|
198
|
-
subscriptions.set(item.topic, handle);
|
|
199
198
|
writer.enqueue(serverMessage("realtime.subscribed", {
|
|
200
199
|
topic: item.topic,
|
|
201
200
|
cursor: handle.cursor
|
|
202
201
|
}), "critical");
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
202
|
+
const cancelReplay = writer.enqueueReplay((function* () {
|
|
203
|
+
for (const message of handle.initial) {
|
|
204
|
+
const output = item.view === "compact" ? compactRunEvent(message) : message;
|
|
205
|
+
if (output) yield output;
|
|
206
|
+
}
|
|
207
|
+
})());
|
|
208
|
+
subscriptions.set(item.topic, {
|
|
209
|
+
...handle,
|
|
210
|
+
unsubscribe: () => {
|
|
211
|
+
cancelReplay();
|
|
212
|
+
handle.unsubscribe();
|
|
213
|
+
}
|
|
214
|
+
});
|
|
207
215
|
}
|
|
208
216
|
return true;
|
|
209
217
|
};
|
|
@@ -8,8 +8,15 @@ export declare class RealtimeSocketWriter {
|
|
|
8
8
|
private sending;
|
|
9
9
|
private closed;
|
|
10
10
|
private retryTimer?;
|
|
11
|
+
private stallTimer?;
|
|
11
12
|
constructor(socket: WebSocket);
|
|
12
13
|
enqueue(message: ServerRealtimeMessage, priority?: 'critical' | 'normal'): boolean;
|
|
14
|
+
/** Serialize replay only as the socket drains; live messages stay behind the replay. */
|
|
15
|
+
enqueueReplay(messages: Iterable<ServerRealtimeMessage>): () => void;
|
|
13
16
|
close(): void;
|
|
17
|
+
private fail;
|
|
18
|
+
private serialize;
|
|
19
|
+
private watchForStall;
|
|
20
|
+
private next;
|
|
14
21
|
private flush;
|
|
15
22
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
1
3
|
//#region src/realtime/writer.ts
|
|
4
|
+
init_logger();
|
|
5
|
+
const log = createLogger("RealtimeSocketWriter");
|
|
2
6
|
const SOFT_BUFFERED_BYTES = 512 * 1024;
|
|
3
|
-
const
|
|
4
|
-
const MAX_QUEUED_BYTES =
|
|
7
|
+
const MAX_EVENT_BYTES = 2 * 1024 * 1024;
|
|
8
|
+
const MAX_QUEUED_BYTES = 16 * 1024 * 1024;
|
|
9
|
+
const DELIVERY_STALL_MS = 15e3;
|
|
5
10
|
var RealtimeSocketWriter = class {
|
|
6
11
|
critical = [];
|
|
7
12
|
normal = [];
|
|
@@ -9,80 +14,141 @@ var RealtimeSocketWriter = class {
|
|
|
9
14
|
sending = false;
|
|
10
15
|
closed = false;
|
|
11
16
|
retryTimer;
|
|
17
|
+
stallTimer;
|
|
12
18
|
constructor(socket) {
|
|
13
19
|
this.socket = socket;
|
|
14
20
|
}
|
|
15
21
|
enqueue(message, priority = "normal") {
|
|
16
22
|
if (this.closed || this.socket.readyState !== 1) return false;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
data = JSON.stringify(message);
|
|
20
|
-
} catch {
|
|
21
|
-
this.socket.close(1011, "Realtime message serialization failed");
|
|
22
|
-
this.close();
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
const item = {
|
|
26
|
-
data,
|
|
27
|
-
bytes: Buffer.byteLength(data)
|
|
28
|
-
};
|
|
29
|
-
if (item.bytes > MAX_QUEUED_BYTES) {
|
|
30
|
-
this.socket.close(1009, "Realtime event exceeds delivery limit");
|
|
31
|
-
this.close();
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
23
|
+
const item = this.serialize(message);
|
|
24
|
+
if (!item) return false;
|
|
34
25
|
if (this.queuedBytes + item.bytes > MAX_QUEUED_BYTES) {
|
|
35
|
-
this.
|
|
36
|
-
|
|
26
|
+
this.fail(4413, "Realtime delivery queue limit exceeded", {
|
|
27
|
+
eventBytes: item.bytes,
|
|
28
|
+
...message.kind === "realtime.event" ? {
|
|
29
|
+
topic: message.payload.topic,
|
|
30
|
+
event: message.payload.event
|
|
31
|
+
} : {}
|
|
32
|
+
});
|
|
37
33
|
return false;
|
|
38
34
|
}
|
|
39
35
|
this.queuedBytes += item.bytes;
|
|
40
36
|
(priority === "critical" ? this.critical : this.normal).push(item);
|
|
41
37
|
this.flush();
|
|
42
|
-
return
|
|
38
|
+
return !this.closed;
|
|
39
|
+
}
|
|
40
|
+
/** Serialize replay only as the socket drains; live messages stay behind the replay. */
|
|
41
|
+
enqueueReplay(messages) {
|
|
42
|
+
if (this.closed || this.socket.readyState !== 1) return () => {};
|
|
43
|
+
const item = { iterator: messages[Symbol.iterator]() };
|
|
44
|
+
this.normal.push(item);
|
|
45
|
+
this.flush();
|
|
46
|
+
return () => {
|
|
47
|
+
const index = this.normal.indexOf(item);
|
|
48
|
+
if (index >= 0) this.normal.splice(index, 1);
|
|
49
|
+
item.iterator.return?.();
|
|
50
|
+
};
|
|
43
51
|
}
|
|
44
52
|
close() {
|
|
45
53
|
if (this.closed) return;
|
|
46
54
|
this.closed = true;
|
|
47
55
|
if (this.retryTimer) clearTimeout(this.retryTimer);
|
|
56
|
+
if (this.stallTimer) clearTimeout(this.stallTimer);
|
|
48
57
|
this.retryTimer = void 0;
|
|
58
|
+
this.stallTimer = void 0;
|
|
59
|
+
for (const item of this.normal) if ("iterator" in item) item.iterator.return?.();
|
|
49
60
|
this.critical.length = 0;
|
|
50
61
|
this.normal.length = 0;
|
|
51
62
|
this.queuedBytes = 0;
|
|
52
63
|
}
|
|
64
|
+
fail(code, reason, fields = {}) {
|
|
65
|
+
log.warn({
|
|
66
|
+
...fields,
|
|
67
|
+
code,
|
|
68
|
+
queuedBytes: this.queuedBytes,
|
|
69
|
+
bufferedBytes: this.socket.bufferedAmount,
|
|
70
|
+
pendingItems: this.normal.length + this.critical.length
|
|
71
|
+
}, reason);
|
|
72
|
+
this.close();
|
|
73
|
+
this.socket.close(code, reason);
|
|
74
|
+
}
|
|
75
|
+
serialize(message) {
|
|
76
|
+
let data;
|
|
77
|
+
try {
|
|
78
|
+
data = JSON.stringify(message);
|
|
79
|
+
} catch {
|
|
80
|
+
this.fail(1011, "Realtime message serialization failed");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const bytes = Buffer.byteLength(data);
|
|
84
|
+
if (bytes > MAX_EVENT_BYTES) {
|
|
85
|
+
this.fail(1009, "Realtime event exceeds delivery limit", {
|
|
86
|
+
eventBytes: bytes,
|
|
87
|
+
...message.kind === "realtime.event" ? {
|
|
88
|
+
topic: message.payload.topic,
|
|
89
|
+
event: message.payload.event
|
|
90
|
+
} : {}
|
|
91
|
+
});
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
data,
|
|
96
|
+
bytes
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
watchForStall() {
|
|
100
|
+
if (!this.stallTimer) this.stallTimer = setTimeout(() => this.fail(4413, "Realtime delivery stalled"), DELIVERY_STALL_MS);
|
|
101
|
+
}
|
|
102
|
+
next() {
|
|
103
|
+
const critical = this.critical.shift();
|
|
104
|
+
if (critical) return critical;
|
|
105
|
+
while (this.normal.length) {
|
|
106
|
+
const head = this.normal[0];
|
|
107
|
+
if (!("iterator" in head)) return this.normal.shift();
|
|
108
|
+
const next = head.iterator.next();
|
|
109
|
+
if (next.done) {
|
|
110
|
+
this.normal.shift();
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const item = this.serialize(next.value);
|
|
114
|
+
if (item) this.queuedBytes += item.bytes;
|
|
115
|
+
return item;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
53
118
|
flush() {
|
|
54
119
|
if (this.closed || this.sending || this.socket.readyState !== 1) return;
|
|
55
|
-
if (this.socket.bufferedAmount >
|
|
56
|
-
this.
|
|
57
|
-
this.close();
|
|
120
|
+
if (this.socket.bufferedAmount > MAX_QUEUED_BYTES) {
|
|
121
|
+
this.fail(4413, "Realtime socket buffer limit exceeded");
|
|
58
122
|
return;
|
|
59
123
|
}
|
|
60
124
|
if (this.socket.bufferedAmount > SOFT_BUFFERED_BYTES) {
|
|
125
|
+
this.watchForStall();
|
|
61
126
|
if (!this.retryTimer) this.retryTimer = setTimeout(() => {
|
|
62
127
|
this.retryTimer = void 0;
|
|
63
128
|
this.flush();
|
|
64
129
|
}, 10);
|
|
65
130
|
return;
|
|
66
131
|
}
|
|
67
|
-
const item = this.
|
|
132
|
+
const item = this.next();
|
|
68
133
|
if (!item) return;
|
|
69
134
|
this.sending = true;
|
|
135
|
+
this.watchForStall();
|
|
70
136
|
try {
|
|
71
137
|
this.socket.send(item.data, (error) => {
|
|
72
138
|
if (this.closed) return;
|
|
73
139
|
this.sending = false;
|
|
74
140
|
this.queuedBytes -= item.bytes;
|
|
141
|
+
if (this.stallTimer) clearTimeout(this.stallTimer);
|
|
142
|
+
this.stallTimer = void 0;
|
|
75
143
|
if (error) {
|
|
76
|
-
this.
|
|
77
|
-
this.close();
|
|
144
|
+
this.fail(1011, "Realtime delivery failed");
|
|
78
145
|
return;
|
|
79
146
|
}
|
|
80
147
|
this.flush();
|
|
81
148
|
});
|
|
82
149
|
} catch {
|
|
83
150
|
this.sending = false;
|
|
84
|
-
this.
|
|
85
|
-
this.socket.close(1011, "Realtime delivery failed");
|
|
151
|
+
this.fail(1011, "Realtime delivery failed");
|
|
86
152
|
}
|
|
87
153
|
}
|
|
88
154
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xopcai/xopc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.436",
|
|
4
4
|
"description": "An open-source AI assistant for work and everyday life. Remembers context and helps you get things done. Local-first, on a computer you choose.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|