lingxios 1.0.0
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 +54 -0
- package/db/schema.sql +306 -0
- package/dist/src/app/artifacts.d.ts +8 -0
- package/dist/src/app/artifacts.js +114 -0
- package/dist/src/app/artifacts.js.map +1 -0
- package/dist/src/app/doctor.d.ts +22 -0
- package/dist/src/app/doctor.js +44 -0
- package/dist/src/app/doctor.js.map +1 -0
- package/dist/src/app/index.d.ts +123 -0
- package/dist/src/app/index.js +291 -0
- package/dist/src/app/index.js.map +1 -0
- package/dist/src/app/input.d.ts +22 -0
- package/dist/src/app/input.js +60 -0
- package/dist/src/app/input.js.map +1 -0
- package/dist/src/app/recover-wait.d.ts +5 -0
- package/dist/src/app/recover-wait.js +59 -0
- package/dist/src/app/recover-wait.js.map +1 -0
- package/dist/src/app/resources.d.ts +5 -0
- package/dist/src/app/resources.js +9 -0
- package/dist/src/app/resources.js.map +1 -0
- package/dist/src/app/storage.d.ts +2 -0
- package/dist/src/app/storage.js +41 -0
- package/dist/src/app/storage.js.map +1 -0
- package/dist/src/cli/doctor.d.ts +2 -0
- package/dist/src/cli/doctor.js +20 -0
- package/dist/src/cli/doctor.js.map +1 -0
- package/dist/src/cli/eval.d.ts +2 -0
- package/dist/src/cli/eval.js +44 -0
- package/dist/src/cli/eval.js.map +1 -0
- package/dist/src/config.d.ts +22 -0
- package/dist/src/config.js +56 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/context/attachments.d.ts +10 -0
- package/dist/src/context/attachments.js +18 -0
- package/dist/src/context/attachments.js.map +1 -0
- package/dist/src/context/document-text.d.ts +1 -0
- package/dist/src/context/document-text.js +29 -0
- package/dist/src/context/document-text.js.map +1 -0
- package/dist/src/context/document-worker.d.ts +1 -0
- package/dist/src/context/document-worker.js +62 -0
- package/dist/src/context/document-worker.js.map +1 -0
- package/dist/src/context/evidence.d.ts +19 -0
- package/dist/src/context/evidence.js +37 -0
- package/dist/src/context/evidence.js.map +1 -0
- package/dist/src/context/request.d.ts +21 -0
- package/dist/src/context/request.js +32 -0
- package/dist/src/context/request.js.map +1 -0
- package/dist/src/context/research-evidence.d.ts +4 -0
- package/dist/src/context/research-evidence.js +24 -0
- package/dist/src/context/research-evidence.js.map +1 -0
- package/dist/src/context/resource-checks.d.ts +7 -0
- package/dist/src/context/resource-checks.js +15 -0
- package/dist/src/context/resource-checks.js.map +1 -0
- package/dist/src/context/task-contract.d.ts +11 -0
- package/dist/src/context/task-contract.js +23 -0
- package/dist/src/context/task-contract.js.map +1 -0
- package/dist/src/context/text.d.ts +2 -0
- package/dist/src/context/text.js +7 -0
- package/dist/src/context/text.js.map +1 -0
- package/dist/src/control-plane/http-server.d.ts +22 -0
- package/dist/src/control-plane/http-server.js +196 -0
- package/dist/src/control-plane/http-server.js.map +1 -0
- package/dist/src/control-plane/memory-store.d.ts +71 -0
- package/dist/src/control-plane/memory-store.js +389 -0
- package/dist/src/control-plane/memory-store.js.map +1 -0
- package/dist/src/control-plane/pg-store.d.ts +62 -0
- package/dist/src/control-plane/pg-store.js +386 -0
- package/dist/src/control-plane/pg-store.js.map +1 -0
- package/dist/src/control-plane/service.d.ts +52 -0
- package/dist/src/control-plane/service.js +630 -0
- package/dist/src/control-plane/service.js.map +1 -0
- package/dist/src/control-plane/stores.d.ts +184 -0
- package/dist/src/control-plane/stores.js +19 -0
- package/dist/src/control-plane/stores.js.map +1 -0
- package/dist/src/errors.d.ts +66 -0
- package/dist/src/errors.js +102 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/eval/calibration.d.ts +16 -0
- package/dist/src/eval/calibration.js +28 -0
- package/dist/src/eval/calibration.js.map +1 -0
- package/dist/src/eval/index.d.ts +40 -0
- package/dist/src/eval/index.js +40 -0
- package/dist/src/eval/index.js.map +1 -0
- package/dist/src/eval/review.d.ts +20 -0
- package/dist/src/eval/review.js +49 -0
- package/dist/src/eval/review.js.map +1 -0
- package/dist/src/host/http-client.d.ts +48 -0
- package/dist/src/host/http-client.js +127 -0
- package/dist/src/host/http-client.js.map +1 -0
- package/dist/src/host/port.d.ts +26 -0
- package/dist/src/host/port.js +2 -0
- package/dist/src/host/port.js.map +1 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/integrations/lingxiloop/actions.d.ts +25 -0
- package/dist/src/integrations/lingxiloop/actions.js +77 -0
- package/dist/src/integrations/lingxiloop/actions.js.map +1 -0
- package/dist/src/integrations/lingxiloop/app.d.ts +167 -0
- package/dist/src/integrations/lingxiloop/app.js +434 -0
- package/dist/src/integrations/lingxiloop/app.js.map +1 -0
- package/dist/src/integrations/lingxiloop/approvals.d.ts +148 -0
- package/dist/src/integrations/lingxiloop/approvals.js +540 -0
- package/dist/src/integrations/lingxiloop/approvals.js.map +1 -0
- package/dist/src/integrations/lingxiloop/attachments.d.ts +8 -0
- package/dist/src/integrations/lingxiloop/attachments.js +38 -0
- package/dist/src/integrations/lingxiloop/attachments.js.map +1 -0
- package/dist/src/integrations/lingxiloop/calendar-approvals.d.ts +21 -0
- package/dist/src/integrations/lingxiloop/calendar-approvals.js +126 -0
- package/dist/src/integrations/lingxiloop/calendar-approvals.js.map +1 -0
- package/dist/src/integrations/lingxiloop/calendar-writes.d.ts +15 -0
- package/dist/src/integrations/lingxiloop/calendar-writes.js +79 -0
- package/dist/src/integrations/lingxiloop/calendar-writes.js.map +1 -0
- package/dist/src/integrations/lingxiloop/calendar.d.ts +19 -0
- package/dist/src/integrations/lingxiloop/calendar.js +43 -0
- package/dist/src/integrations/lingxiloop/calendar.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas-events.d.ts +7 -0
- package/dist/src/integrations/lingxiloop/canvas-events.js +53 -0
- package/dist/src/integrations/lingxiloop/canvas-events.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas-summary.d.ts +5 -0
- package/dist/src/integrations/lingxiloop/canvas-summary.js +52 -0
- package/dist/src/integrations/lingxiloop/canvas-summary.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas-work-report.d.ts +12 -0
- package/dist/src/integrations/lingxiloop/canvas-work-report.js +120 -0
- package/dist/src/integrations/lingxiloop/canvas-work-report.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas-work.d.ts +11 -0
- package/dist/src/integrations/lingxiloop/canvas-work.js +306 -0
- package/dist/src/integrations/lingxiloop/canvas-work.js.map +1 -0
- package/dist/src/integrations/lingxiloop/canvas.d.ts +12 -0
- package/dist/src/integrations/lingxiloop/canvas.js +79 -0
- package/dist/src/integrations/lingxiloop/canvas.js.map +1 -0
- package/dist/src/integrations/lingxiloop/chat.d.ts +11 -0
- package/dist/src/integrations/lingxiloop/chat.js +46 -0
- package/dist/src/integrations/lingxiloop/chat.js.map +1 -0
- package/dist/src/integrations/lingxiloop/document-approvals.d.ts +21 -0
- package/dist/src/integrations/lingxiloop/document-approvals.js +75 -0
- package/dist/src/integrations/lingxiloop/document-approvals.js.map +1 -0
- package/dist/src/integrations/lingxiloop/document-content.d.ts +80 -0
- package/dist/src/integrations/lingxiloop/document-content.js +195 -0
- package/dist/src/integrations/lingxiloop/document-content.js.map +1 -0
- package/dist/src/integrations/lingxiloop/document-writes.d.ts +8 -0
- package/dist/src/integrations/lingxiloop/document-writes.js +49 -0
- package/dist/src/integrations/lingxiloop/document-writes.js.map +1 -0
- package/dist/src/integrations/lingxiloop/documents.d.ts +22 -0
- package/dist/src/integrations/lingxiloop/documents.js +38 -0
- package/dist/src/integrations/lingxiloop/documents.js.map +1 -0
- package/dist/src/integrations/lingxiloop/event-outbox.d.ts +5 -0
- package/dist/src/integrations/lingxiloop/event-outbox.js +47 -0
- package/dist/src/integrations/lingxiloop/event-outbox.js.map +1 -0
- package/dist/src/integrations/lingxiloop/index.d.ts +3 -0
- package/dist/src/integrations/lingxiloop/index.js +3 -0
- package/dist/src/integrations/lingxiloop/index.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning-attempts.d.ts +13 -0
- package/dist/src/integrations/lingxiloop/learning-attempts.js +58 -0
- package/dist/src/integrations/lingxiloop/learning-attempts.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning-evaluation.d.ts +8 -0
- package/dist/src/integrations/lingxiloop/learning-evaluation.js +64 -0
- package/dist/src/integrations/lingxiloop/learning-evaluation.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning-evidence.d.ts +7 -0
- package/dist/src/integrations/lingxiloop/learning-evidence.js +88 -0
- package/dist/src/integrations/lingxiloop/learning-evidence.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning-missions.d.ts +18 -0
- package/dist/src/integrations/lingxiloop/learning-missions.js +95 -0
- package/dist/src/integrations/lingxiloop/learning-missions.js.map +1 -0
- package/dist/src/integrations/lingxiloop/learning.d.ts +22 -0
- package/dist/src/integrations/lingxiloop/learning.js +150 -0
- package/dist/src/integrations/lingxiloop/learning.js.map +1 -0
- package/dist/src/integrations/lingxiloop/memory.d.ts +14 -0
- package/dist/src/integrations/lingxiloop/memory.js +133 -0
- package/dist/src/integrations/lingxiloop/memory.js.map +1 -0
- package/dist/src/integrations/lingxiloop/polls.d.ts +9 -0
- package/dist/src/integrations/lingxiloop/polls.js +47 -0
- package/dist/src/integrations/lingxiloop/polls.js.map +1 -0
- package/dist/src/integrations/lingxiloop/presentations.d.ts +11 -0
- package/dist/src/integrations/lingxiloop/presentations.js +34 -0
- package/dist/src/integrations/lingxiloop/presentations.js.map +1 -0
- package/dist/src/integrations/lingxiloop/questionnaire.d.ts +21 -0
- package/dist/src/integrations/lingxiloop/questionnaire.js +57 -0
- package/dist/src/integrations/lingxiloop/questionnaire.js.map +1 -0
- package/dist/src/integrations/lingxiloop/research.d.ts +19 -0
- package/dist/src/integrations/lingxiloop/research.js +20 -0
- package/dist/src/integrations/lingxiloop/research.js.map +1 -0
- package/dist/src/integrations/lingxiloop/routines.d.ts +91 -0
- package/dist/src/integrations/lingxiloop/routines.js +198 -0
- package/dist/src/integrations/lingxiloop/routines.js.map +1 -0
- package/dist/src/integrations/lingxiloop/service-contracts.d.ts +1045 -0
- package/dist/src/integrations/lingxiloop/service-contracts.js +2 -0
- package/dist/src/integrations/lingxiloop/service-contracts.js.map +1 -0
- package/dist/src/integrations/lingxiloop/teacher-context.d.ts +32 -0
- package/dist/src/integrations/lingxiloop/teacher-context.js +25 -0
- package/dist/src/integrations/lingxiloop/teacher-context.js.map +1 -0
- package/dist/src/integrations/lingxiloop/teacher-digest.d.ts +13 -0
- package/dist/src/integrations/lingxiloop/teacher-digest.js +152 -0
- package/dist/src/integrations/lingxiloop/teacher-digest.js.map +1 -0
- package/dist/src/integrations/lingxiloop/teacher-preview.d.ts +22 -0
- package/dist/src/integrations/lingxiloop/teacher-preview.js +41 -0
- package/dist/src/integrations/lingxiloop/teacher-preview.js.map +1 -0
- package/dist/src/integrations/lingxiloop/teacher.d.ts +24 -0
- package/dist/src/integrations/lingxiloop/teacher.js +224 -0
- package/dist/src/integrations/lingxiloop/teacher.js.map +1 -0
- package/dist/src/kernel/manager.d.ts +52 -0
- package/dist/src/kernel/manager.js +407 -0
- package/dist/src/kernel/manager.js.map +1 -0
- package/dist/src/logging.d.ts +21 -0
- package/dist/src/logging.js +54 -0
- package/dist/src/logging.js.map +1 -0
- package/dist/src/memory/evidence.d.ts +6 -0
- package/dist/src/memory/evidence.js +43 -0
- package/dist/src/memory/evidence.js.map +1 -0
- package/dist/src/memory/processor.d.ts +3 -0
- package/dist/src/memory/processor.js +66 -0
- package/dist/src/memory/processor.js.map +1 -0
- package/dist/src/memory/semantic.d.ts +19 -0
- package/dist/src/memory/semantic.js +93 -0
- package/dist/src/memory/semantic.js.map +1 -0
- package/dist/src/memory/store.d.ts +20 -0
- package/dist/src/memory/store.js +34 -0
- package/dist/src/memory/store.js.map +1 -0
- package/dist/src/memory/synthesis.d.ts +24 -0
- package/dist/src/memory/synthesis.js +138 -0
- package/dist/src/memory/synthesis.js.map +1 -0
- package/dist/src/metrics.d.ts +43 -0
- package/dist/src/metrics.js +130 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/model/driver.d.ts +60 -0
- package/dist/src/model/driver.js +2 -0
- package/dist/src/model/driver.js.map +1 -0
- package/dist/src/model/embeddings.d.ts +24 -0
- package/dist/src/model/embeddings.js +97 -0
- package/dist/src/model/embeddings.js.map +1 -0
- package/dist/src/model/openai.d.ts +45 -0
- package/dist/src/model/openai.js +340 -0
- package/dist/src/model/openai.js.map +1 -0
- package/dist/src/outcome/assessment.d.ts +16 -0
- package/dist/src/outcome/assessment.js +45 -0
- package/dist/src/outcome/assessment.js.map +1 -0
- package/dist/src/outcome/content-check.d.ts +19 -0
- package/dist/src/outcome/content-check.js +44 -0
- package/dist/src/outcome/content-check.js.map +1 -0
- package/dist/src/outcome/envelope.d.ts +34 -0
- package/dist/src/outcome/envelope.js +42 -0
- package/dist/src/outcome/envelope.js.map +1 -0
- package/dist/src/protocol/constants.d.ts +25 -0
- package/dist/src/protocol/constants.js +26 -0
- package/dist/src/protocol/constants.js.map +1 -0
- package/dist/src/protocol/kernel-wire.d.ts +74 -0
- package/dist/src/protocol/kernel-wire.js +2 -0
- package/dist/src/protocol/kernel-wire.js.map +1 -0
- package/dist/src/protocol/outcome.d.ts +16 -0
- package/dist/src/protocol/outcome.js +14 -0
- package/dist/src/protocol/outcome.js.map +1 -0
- package/dist/src/protocol/types.d.ts +266 -0
- package/dist/src/protocol/types.js +19 -0
- package/dist/src/protocol/types.js.map +1 -0
- package/dist/src/research/address.d.ts +2 -0
- package/dist/src/research/address.js +32 -0
- package/dist/src/research/address.js.map +1 -0
- package/dist/src/research/fetch.d.ts +7 -0
- package/dist/src/research/fetch.js +83 -0
- package/dist/src/research/fetch.js.map +1 -0
- package/dist/src/research/index.d.ts +26 -0
- package/dist/src/research/index.js +109 -0
- package/dist/src/research/index.js.map +1 -0
- package/dist/src/runtime/compaction.d.ts +41 -0
- package/dist/src/runtime/compaction.js +86 -0
- package/dist/src/runtime/compaction.js.map +1 -0
- package/dist/src/runtime/corrections.d.ts +20 -0
- package/dist/src/runtime/corrections.js +27 -0
- package/dist/src/runtime/corrections.js.map +1 -0
- package/dist/src/runtime/policy.d.ts +42 -0
- package/dist/src/runtime/policy.js +91 -0
- package/dist/src/runtime/policy.js.map +1 -0
- package/dist/src/runtime/resource-refresh.d.ts +8 -0
- package/dist/src/runtime/resource-refresh.js +37 -0
- package/dist/src/runtime/resource-refresh.js.map +1 -0
- package/dist/src/runtime/runtime.d.ts +51 -0
- package/dist/src/runtime/runtime.js +804 -0
- package/dist/src/runtime/runtime.js.map +1 -0
- package/dist/src/runtime/tool.d.ts +13 -0
- package/dist/src/runtime/tool.js +42 -0
- package/dist/src/runtime/tool.js.map +1 -0
- package/dist/src/ui/index.d.ts +27 -0
- package/dist/src/ui/index.js +54 -0
- package/dist/src/ui/index.js.map +1 -0
- package/dist/src/versions.d.ts +9 -0
- package/dist/src/versions.js +11 -0
- package/dist/src/versions.js.map +1 -0
- package/dist/src/worker/index.d.ts +3 -0
- package/dist/src/worker/index.js +57 -0
- package/dist/src/worker/index.js.map +1 -0
- package/dist/src/worker/main.d.ts +2 -0
- package/dist/src/worker/main.js +9 -0
- package/dist/src/worker/main.js.map +1 -0
- package/dist/src/worker/worker.d.ts +45 -0
- package/dist/src/worker/worker.js +154 -0
- package/dist/src/worker/worker.js.map +1 -0
- package/kernel/runner.py +507 -0
- package/package.json +83 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/** A persisted report records an agent finding, not proof that the user's goal is satisfied. */
|
|
3
|
+
export async function submitCanvasWorkReport(db, services, work, args, canvasId, projectId, requestVersion, assignmentVersion) {
|
|
4
|
+
const api = services.canvas.orchestration;
|
|
5
|
+
if (Buffer.byteLength(JSON.stringify(args)) > 32_768)
|
|
6
|
+
throw new Error('Canvas report input exceeds 32768 bytes');
|
|
7
|
+
const bounded = (value, name, max = 4000) => {
|
|
8
|
+
if (typeof value !== 'string' || !value.trim() || value.length > max)
|
|
9
|
+
throw new Error(`invalid report ${name}`);
|
|
10
|
+
return value.trim();
|
|
11
|
+
};
|
|
12
|
+
const strings = (value, name) => {
|
|
13
|
+
if (!Array.isArray(value) || value.length > 32)
|
|
14
|
+
throw new Error(`invalid report ${name}`);
|
|
15
|
+
return value.map(item => bounded(item, name));
|
|
16
|
+
};
|
|
17
|
+
const finding = bounded(args['finding'], 'finding', 16_000);
|
|
18
|
+
const confidence = args['confidence'];
|
|
19
|
+
if (typeof confidence !== 'number' || !Number.isFinite(confidence) || confidence < 0 || confidence > 1)
|
|
20
|
+
throw new Error('invalid report confidence');
|
|
21
|
+
const unresolved = strings(args['unresolved'] ?? [], 'unresolved');
|
|
22
|
+
const checks = strings(args['disconfirmingChecks'] ?? [], 'disconfirmingChecks');
|
|
23
|
+
const nextStep = args['nextStep'] === undefined ? null : bounded(args['nextStep'], 'nextStep');
|
|
24
|
+
const inputRefs = args['evidenceRefs'];
|
|
25
|
+
if (!Array.isArray(inputRefs) || inputRefs.length > 64)
|
|
26
|
+
throw new Error('invalid report evidenceRefs');
|
|
27
|
+
let refs = inputRefs;
|
|
28
|
+
const reporter = work.kind === 'canvas_summary';
|
|
29
|
+
const assignment = reporter ? { id: null, execution_role: 'reporter', verifies_assignment_id: null } : (await db.query(`SELECT id,execution_role,verifies_assignment_id FROM canvas_agent_assignments
|
|
30
|
+
WHERE id=$1 AND canvas_id=$2 AND agent_id=$3 AND work_id=$4 FOR UPDATE`, [work.meta?.['assignmentId'], canvasId, work.agentId, work.id])).rows[0];
|
|
31
|
+
if (!assignment || !['specialist', 'verifier', 'reporter'].includes(String(assignment['execution_role'])))
|
|
32
|
+
throw new Error('report requires the current specialist, verifier or reporter work');
|
|
33
|
+
const consumed = args['consumedReportIds'] === undefined ? [] : strings(args['consumedReportIds'], 'consumedReportIds');
|
|
34
|
+
const conflicts = args['conflictResolution'] ?? [];
|
|
35
|
+
if (!Array.isArray(conflicts) || conflicts.length > 32)
|
|
36
|
+
throw new Error('invalid report conflictResolution');
|
|
37
|
+
if (reporter) {
|
|
38
|
+
if (!consumed.length || new Set(consumed).size !== consumed.length)
|
|
39
|
+
throw new Error('reporter must consume persisted reports');
|
|
40
|
+
const available = (await db.query('SELECT id,assignment_id FROM canvas_assignment_reports WHERE canvas_id=$1 AND company_id=$2 FOR SHARE', [canvasId, work.tenantId])).rows;
|
|
41
|
+
if (consumed.some(id => !available.some(row => row['id'] === id))
|
|
42
|
+
|| available.some(row => row['assignment_id'] !== null && !consumed.includes(String(row['id']))))
|
|
43
|
+
throw new Error('reporter must consume every current assignment report in this Canvas');
|
|
44
|
+
refs = [...refs, ...consumed.map(id => ({ kind: 'report', id }))];
|
|
45
|
+
if (new Set(refs.map(ref => JSON.stringify([ref?.kind, ref?.id]))).size > 64)
|
|
46
|
+
throw new Error('report evidence reference capacity exceeded');
|
|
47
|
+
}
|
|
48
|
+
else if (consumed.length || conflicts.length)
|
|
49
|
+
throw new Error('only reporter work may consume reports or resolve conflicts');
|
|
50
|
+
let verifiesReportId = null, verdict = null;
|
|
51
|
+
if (assignment['execution_role'] === 'verifier') {
|
|
52
|
+
verifiesReportId = bounded(args['verifiesReportId'], 'verifiesReportId', 240);
|
|
53
|
+
if (!['supported', 'rejected', 'inconclusive'].includes(String(args['verdict'])))
|
|
54
|
+
throw new Error('invalid verifier verdict');
|
|
55
|
+
verdict = String(args['verdict']);
|
|
56
|
+
if (!checks.length)
|
|
57
|
+
throw new Error('verifier must record disconfirming checks');
|
|
58
|
+
const source = await db.query(`SELECT id FROM canvas_assignment_reports WHERE id=$1 AND company_id=$2
|
|
59
|
+
AND canvas_id=$3 AND assignment_id=$4 AND author_agent_id<>$5 AND execution_role='specialist' FOR SHARE`, [verifiesReportId, work.tenantId, canvasId, assignment['verifies_assignment_id'], work.agentId]);
|
|
60
|
+
if (source.rows.length !== 1)
|
|
61
|
+
throw new Error('verifier report must target its assigned builder report');
|
|
62
|
+
}
|
|
63
|
+
else if (args['verifiesReportId'] !== undefined || args['verdict'] !== undefined || checks.length)
|
|
64
|
+
throw new Error('only verifier reports may set verification fields');
|
|
65
|
+
const permissions = api.createPermissionService(db, { lockDependencies: true });
|
|
66
|
+
const sourceEvidenceIds = [];
|
|
67
|
+
const seen = new Set();
|
|
68
|
+
for (const ref of refs) {
|
|
69
|
+
if (!ref || typeof ref !== 'object' || Array.isArray(ref) || Object.keys(ref).some(key => !['kind', 'id'].includes(key)))
|
|
70
|
+
throw new Error('invalid report evidence reference');
|
|
71
|
+
const id = bounded(ref.id, 'evidence id', 240), kind = ref.kind;
|
|
72
|
+
const key = JSON.stringify([kind, id]);
|
|
73
|
+
if (seen.has(key))
|
|
74
|
+
continue;
|
|
75
|
+
seen.add(key);
|
|
76
|
+
let observed;
|
|
77
|
+
if (kind === 'frame') {
|
|
78
|
+
observed = (await db.query('SELECT id,revision FROM canvas_frames WHERE id=$1 AND canvas_id=$2 FOR SHARE', [id, canvasId])).rows[0];
|
|
79
|
+
}
|
|
80
|
+
else if (kind === 'report') {
|
|
81
|
+
observed = (await db.query('SELECT id,evidence_id FROM canvas_assignment_reports WHERE id=$1 AND canvas_id=$2 AND company_id=$3 FOR SHARE', [id, canvasId, work.tenantId])).rows[0];
|
|
82
|
+
}
|
|
83
|
+
else if (kind === 'document') {
|
|
84
|
+
await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId, action: 'document:read', resource: { type: 'document', id } });
|
|
85
|
+
observed = (await db.query(`SELECT id,updated_at FROM documents WHERE id=$1 AND company_id=$2 AND project_id=$3
|
|
86
|
+
AND (conversation_id IS NULL OR conversation_id=$4) FOR SHARE`, [id, work.tenantId, projectId, work.sessionId])).rows[0];
|
|
87
|
+
}
|
|
88
|
+
else if (kind === 'source') {
|
|
89
|
+
await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId, action: 'knowledge:read', resource: { type: 'knowledge_source', id } });
|
|
90
|
+
observed = (await db.query('SELECT id,updated_at FROM knowledge_sources WHERE id=$1 AND company_id=$2 AND project_id=$3 AND deleted_at IS NULL FOR SHARE', [id, work.tenantId, projectId])).rows[0];
|
|
91
|
+
}
|
|
92
|
+
else if (kind === 'attempt') {
|
|
93
|
+
await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId, action: 'learning:read', resource: { type: 'project', id: projectId } });
|
|
94
|
+
observed = (await db.query('SELECT id,created_at FROM learning_attempts WHERE id=$1 AND company_id=$2 AND project_id=$3 AND learner_id=$4 FOR SHARE', [id, work.tenantId, projectId, work.principalId])).rows[0];
|
|
95
|
+
}
|
|
96
|
+
else
|
|
97
|
+
throw new Error('report evidence kind must be frame, report, document, source or attempt');
|
|
98
|
+
if (!observed)
|
|
99
|
+
throw new Error('report evidence is not observable in the authorized Canvas scope');
|
|
100
|
+
const observation = JSON.stringify(observed);
|
|
101
|
+
const evidenceId = 'evidence-' + createHash('sha256').update(JSON.stringify([work.tenantId, projectId, kind, id, observation])).digest('hex');
|
|
102
|
+
await api.createEvidenceRecordInTransaction(db, { id: evidenceId, companyId: work.tenantId, projectId,
|
|
103
|
+
level: 'L1', derivation: 'OBSERVED', kind: 'CANVAS_SOURCE_REFERENCE', data: { sourceKind: kind, sourceId: id, observation }, createdBy: { type: 'SYSTEM' } });
|
|
104
|
+
sourceEvidenceIds.push(evidenceId);
|
|
105
|
+
}
|
|
106
|
+
const reportId = 'report-' + createHash('sha256').update(JSON.stringify([work.id, requestVersion, assignmentVersion, 'learning_report_v1'])).digest('hex').slice(0, 28);
|
|
107
|
+
const evidenceId = `evidence-${reportId}`;
|
|
108
|
+
await api.createEvidenceWithLinksInTransaction(db, { id: evidenceId, companyId: work.tenantId, projectId,
|
|
109
|
+
level: 'L2', derivation: 'OBSERVED', kind: 'CANVAS_REPORT', data: { reportId, canvasId, assignmentId: String(assignment['id']), executionRole: String(assignment['execution_role']), workId: work.id, requestVersion: String(requestVersion), assignmentVersion: String(assignmentVersion) },
|
|
110
|
+
createdBy: { type: 'AGENT', id: work.agentId } }, sourceEvidenceIds.map(targetId => ({ relation: 'DERIVED_FROM', targetLevel: 'L1', targetKind: 'EVIDENCE_RECORD', targetId })));
|
|
111
|
+
// Preserve historical reports and their evidence/verification links; only the current projection owns assignment_id.
|
|
112
|
+
if (assignment['id'])
|
|
113
|
+
await db.query('UPDATE canvas_assignment_reports SET assignment_id=NULL WHERE assignment_id=$1 AND id<>$2', [assignment['id'], reportId]);
|
|
114
|
+
await db.query(`INSERT INTO canvas_assignment_reports(id,company_id,canvas_id,assignment_id,author_agent_id,execution_role,
|
|
115
|
+
finding,evidence_id,source_evidence_ids,confidence,unresolved,next_step,verifies_report_id,disconfirming_checks,verdict,consumed_report_ids,conflict_resolution)
|
|
116
|
+
VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10,$11::jsonb,$12,$13,$14::jsonb,$15,$16::jsonb,$17::jsonb)`, [reportId, work.tenantId, canvasId, assignment['id'], work.agentId, assignment['execution_role'], finding, evidenceId,
|
|
117
|
+
JSON.stringify(sourceEvidenceIds), confidence, JSON.stringify(unresolved), nextStep, verifiesReportId, JSON.stringify(checks), verdict, JSON.stringify(consumed), JSON.stringify(conflicts)]);
|
|
118
|
+
return { reportId, assignmentId: assignment['id'], evidenceId, sourceEvidenceIds, verdict, unresolved };
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=canvas-work-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-work-report.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/canvas-work-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type SqlPool, type SqlQueryable } from '../../control-plane/pg-store.js';
|
|
2
|
+
import type { HostAction, HostActionResult, WorkItem } from '../../protocol/types.js';
|
|
3
|
+
import type { LingxiLoopServices } from './service-contracts.js';
|
|
4
|
+
export declare const CANVAS_WORK_METHODS: readonly ["start_workspace", "stop_workspace", "assign", "steer_assignment", "stop_assignment", "submit_report", "handoff"];
|
|
5
|
+
type Services = Pick<LingxiLoopServices, 'canvas'>;
|
|
6
|
+
/** Domain assignments and durable execution belong to one transaction; no old work table is used. */
|
|
7
|
+
export declare function executeCanvasWork(database: SqlPool, services: Services, work: Omit<WorkItem, 'leaseToken'>, action: HostAction): Promise<HostActionResult>;
|
|
8
|
+
export declare function assertCanvasWorker(database: SqlQueryable, work: Omit<WorkItem, 'leaseToken'>): Promise<Record<string, unknown>>;
|
|
9
|
+
/** Restart-safe projection of package work into domain assignment state, followed by dependency release. */
|
|
10
|
+
export declare function reconcileCanvasWork(database: SqlPool, services: Services): Promise<void>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { withTransaction } from '../../control-plane/pg-store.js';
|
|
3
|
+
import { submitCanvasWorkReport } from './canvas-work-report.js';
|
|
4
|
+
import { queueCanvasAssignments, queueCanvasReports, queueCanvasActivity, queueCanvasWorkspace } from './canvas-events.js';
|
|
5
|
+
import { assertCanvasSummary, reconcileCanvasSummary } from './canvas-summary.js';
|
|
6
|
+
export const CANVAS_WORK_METHODS = ['start_workspace', 'stop_workspace', 'assign', 'steer_assignment', 'stop_assignment', 'submit_report', 'handoff'];
|
|
7
|
+
function text(value, name, limit = 240) {
|
|
8
|
+
if (typeof value !== 'string' || !value.trim() || value.length > limit)
|
|
9
|
+
throw new Error(`invalid ${name}`);
|
|
10
|
+
return value.trim();
|
|
11
|
+
}
|
|
12
|
+
function membersOf(value) {
|
|
13
|
+
if (!Array.isArray(value) || !value.length || value.length > 32)
|
|
14
|
+
throw new Error('members requires 1 to 32 assignments');
|
|
15
|
+
const members = value.map(item => {
|
|
16
|
+
if (!item || typeof item !== 'object' || Array.isArray(item)
|
|
17
|
+
|| Object.keys(item).some(key => !['agentId', 'assignment', 'dependsOnAgentIds', 'executionRole', 'verifiesAgentId'].includes(key)))
|
|
18
|
+
throw new Error('invalid Canvas member');
|
|
19
|
+
const dependencies = item.dependsOnAgentIds ?? [];
|
|
20
|
+
if (!Array.isArray(dependencies) || dependencies.length > 32)
|
|
21
|
+
throw new Error('invalid Canvas dependencies');
|
|
22
|
+
const role = item.executionRole ?? 'specialist';
|
|
23
|
+
if (role !== 'specialist' && role !== 'verifier')
|
|
24
|
+
throw new Error('invalid Canvas execution role');
|
|
25
|
+
return { agentId: text(item.agentId, 'agentId'), assignment: text(item.assignment, 'assignment', 4000),
|
|
26
|
+
dependsOnAgentIds: [...new Set(dependencies.map(id => text(id, 'dependency')))], executionRole: role,
|
|
27
|
+
...(item.verifiesAgentId !== undefined ? { verifiesAgentId: text(item.verifiesAgentId, 'verifiesAgentId') } : {}) };
|
|
28
|
+
});
|
|
29
|
+
if (new Set(members.map(item => item.agentId)).size !== members.length)
|
|
30
|
+
throw new Error('Canvas members must be unique');
|
|
31
|
+
for (const member of members) {
|
|
32
|
+
if (member.executionRole === 'verifier') {
|
|
33
|
+
if (!member.verifiesAgentId || member.verifiesAgentId === member.agentId)
|
|
34
|
+
throw new Error('verifier requires a different builder');
|
|
35
|
+
if (!member.dependsOnAgentIds.includes(member.verifiesAgentId))
|
|
36
|
+
member.dependsOnAgentIds.push(member.verifiesAgentId);
|
|
37
|
+
}
|
|
38
|
+
else if (member.verifiesAgentId)
|
|
39
|
+
throw new Error('only verifiers may specify a builder');
|
|
40
|
+
}
|
|
41
|
+
return members;
|
|
42
|
+
}
|
|
43
|
+
/** Domain assignments and durable execution belong to one transaction; no old work table is used. */
|
|
44
|
+
export async function executeCanvasWork(database, services, work, action) {
|
|
45
|
+
const api = services.canvas?.orchestration;
|
|
46
|
+
if (!api || !work.principalId || !CANVAS_WORK_METHODS.some(method => action.action === `canvas.${method}`))
|
|
47
|
+
throw new Error('Canvas orchestration is unavailable');
|
|
48
|
+
const handoff = action.action === 'canvas.handoff';
|
|
49
|
+
const start = action.action === 'canvas.start_workspace', stop = action.action === 'canvas.stop_workspace';
|
|
50
|
+
const assign = action.action === 'canvas.assign' || handoff || start;
|
|
51
|
+
const report = action.action === 'canvas.submit_report';
|
|
52
|
+
const allowed = start ? ['title', 'goal', 'members'] : stop ? [] : handoff ? ['toAgentId', 'task', 'context', 'frameIds'] : assign ? ['members'] : report ? ['finding', 'evidenceRefs', 'confidence', 'unresolved', 'nextStep', 'verifiesReportId', 'disconfirmingChecks', 'verdict', 'consumedReportIds', 'conflictResolution'] : action.action === 'canvas.steer_assignment' ? ['agentId', 'text'] : ['agentId'];
|
|
53
|
+
if (Object.keys(action.args).some(key => !allowed.includes(key)))
|
|
54
|
+
throw new Error('unknown Canvas work argument');
|
|
55
|
+
const members = assign ? membersOf(handoff ? [{ agentId: action.args['toAgentId'], assignment: action.args['task'] }] : action.args['members']) : [];
|
|
56
|
+
const targetId = handoff ? members[0].agentId : assign || report || stop ? undefined : text(action.args['agentId'], 'agentId');
|
|
57
|
+
const handoffContext = handoff && action.args['context'] !== undefined ? text(action.args['context'], 'context', 8000) : '';
|
|
58
|
+
const frameInput = handoff ? action.args['frameIds'] ?? [] : [];
|
|
59
|
+
if (!Array.isArray(frameInput) || frameInput.length > 32)
|
|
60
|
+
throw new Error('invalid handoff frameIds');
|
|
61
|
+
const frameIds = [...new Set(frameInput.map(id => text(id, 'frameId')))];
|
|
62
|
+
const handoffInstruction = handoff ? JSON.stringify({ task: members[0].assignment, context: handoffContext, frameIds }) : undefined;
|
|
63
|
+
const steer = handoffInstruction ?? (action.action === 'canvas.steer_assignment' ? text(action.args['text'], 'text', 4000) : undefined);
|
|
64
|
+
return withTransaction(database, async (client) => {
|
|
65
|
+
await client.query("SET LOCAL lock_timeout='5s'");
|
|
66
|
+
await client.query("SET LOCAL statement_timeout='10s'");
|
|
67
|
+
const live = await client.query(`SELECT w.meta,w.steer_inputs FROM lingxios.agent_work_items w
|
|
68
|
+
JOIN lingxios.agent_action_intents i ON i.idempotency_key=$3
|
|
69
|
+
WHERE w.id=$1 AND w.fence=$2 AND w.status='leased' AND w.lease_expires_at>NOW()
|
|
70
|
+
AND w.cancel_requested_at IS NULL AND w.preempt_requested_at IS NULL AND w.tenant_id=$4 AND w.principal_id=$5
|
|
71
|
+
AND w.agent_id=$6 AND w.session_id=$7 AND i.intent->>'workId'=w.id
|
|
72
|
+
AND i.intent->'action'->>'action'=$8 AND i.intent->'action'->'args'=$9::jsonb
|
|
73
|
+
AND (i.intent->>'requestVersion')::integer=jsonb_array_length(w.steer_inputs)+1
|
|
74
|
+
FOR UPDATE OF w`, [work.id, work.fence, action.idempotencyKey, work.tenantId, work.principalId,
|
|
75
|
+
work.agentId, work.sessionId, action.action, JSON.stringify(action.args)]);
|
|
76
|
+
if (live.rows.length !== 1)
|
|
77
|
+
throw new Error('Canvas action requires the current live intent');
|
|
78
|
+
const permissions = api.createPermissionService(client, { lockDependencies: true });
|
|
79
|
+
await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
|
|
80
|
+
action: 'conversation:read', resource: { type: 'conversation', id: work.sessionId } });
|
|
81
|
+
let canvas = (await client.query(`SELECT c.id,c.project_id,c.status FROM canvases c
|
|
82
|
+
WHERE c.company_id=$1 AND c.conversation_id=$2 FOR UPDATE`, [work.tenantId, work.sessionId])).rows[0];
|
|
83
|
+
if (start) {
|
|
84
|
+
if (canvas)
|
|
85
|
+
throw new Error('conversation already has a Canvas; inspect it before assigning work');
|
|
86
|
+
await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
|
|
87
|
+
action: 'conversation:write', resource: { type: 'conversation', id: work.sessionId } });
|
|
88
|
+
const id = 'canvas-' + createHash('sha256').update(action.idempotencyKey).digest('hex').slice(0, 28);
|
|
89
|
+
const created = await api.insertAgentWorkspace(client, { id, companyId: work.tenantId, conversationId: work.sessionId,
|
|
90
|
+
initiatorAgentId: work.agentId, authorizationUserId: work.principalId, triggerClientMsgNo: work.triggerRef,
|
|
91
|
+
title: text(action.args['title'], 'title', 200), goal: text(action.args['goal'], 'goal', 16_000) });
|
|
92
|
+
if (!created || created.id !== id)
|
|
93
|
+
throw new Error('Canvas changed concurrently; read it before retrying');
|
|
94
|
+
canvas = created;
|
|
95
|
+
}
|
|
96
|
+
const summary = report && work.kind === 'canvas_summary';
|
|
97
|
+
if (!canvas || (stop ? !['active', 'summarizing', 'stopped'].includes(String(canvas['status'])) : canvas['status'] !== (summary ? 'summarizing' : 'active')) || !canvas['project_id'])
|
|
98
|
+
throw new Error('an active current Canvas with a project is required');
|
|
99
|
+
// Native reports may be written while summarizing; frame-write state checks apply to active canvases.
|
|
100
|
+
// Authorize the same project/member write policy on the locked conversation, then assert the reporter job below.
|
|
101
|
+
await permissions.assertCan({ actorUserId: work.principalId, companyId: work.tenantId,
|
|
102
|
+
action: 'canvas:write', resource: { type: summary || stop ? 'conversation' : 'canvas', id: summary || stop ? work.sessionId : String(canvas['id']) } });
|
|
103
|
+
const ids = [...new Set([work.agentId, ...members.map(item => item.agentId), ...(targetId ? [targetId] : [])])];
|
|
104
|
+
const eligible = await client.query(`SELECT p.id FROM participants p
|
|
105
|
+
JOIN im_channel_bindings b ON b.company_id=p.company_id AND b.channel_id=$3
|
|
106
|
+
WHERE p.company_id=$1 AND p.id=ANY($2::text[]) AND p.kind='agent' AND p.departed_at IS NULL
|
|
107
|
+
AND p.capabilities @> '["canvas"]'::jsonb AND b.profile->'members' ? p.id
|
|
108
|
+
AND NOT EXISTS(SELECT 1 FROM learning_project_teacher_agents t WHERE t.company_id=p.company_id AND t.agent_id=p.id)
|
|
109
|
+
FOR SHARE OF p,b`, [work.tenantId, ids, work.sessionId]);
|
|
110
|
+
if (eligible.rows.length !== ids.length)
|
|
111
|
+
throw new Error('Canvas agents must be active members with the Canvas capability');
|
|
112
|
+
const existing = (await client.query('SELECT * FROM canvas_agent_assignments WHERE canvas_id=$1 FOR UPDATE', [canvas['id']])).rows;
|
|
113
|
+
const sourceAssignment = handoff ? existing.find(row => row['agent_id'] === work.agentId && row['work_id'] === work.id) : undefined;
|
|
114
|
+
if (handoff) {
|
|
115
|
+
if (targetId === work.agentId || !sourceAssignment || !['queued', 'working', 'waiting'].includes(String(sourceAssignment['status'])))
|
|
116
|
+
throw new Error('handoff requires the current Canvas worker and a different target');
|
|
117
|
+
const frames = await client.query('SELECT id FROM canvas_frames WHERE canvas_id=$1 AND id=ANY($2::text[]) FOR SHARE', [canvas['id'], frameIds]);
|
|
118
|
+
if (frames.rows.length !== frameIds.length)
|
|
119
|
+
throw new Error('handoff frames must belong to the current Canvas');
|
|
120
|
+
}
|
|
121
|
+
let value;
|
|
122
|
+
if (stop) {
|
|
123
|
+
await client.query("UPDATE canvases SET status='stopped',completed_at=COALESCE(completed_at,NOW()),updated_at=NOW() WHERE id=$1", [canvas['id']]);
|
|
124
|
+
await client.query(`UPDATE lingxios.agent_work_items SET cancel_requested_at=COALESCE(cancel_requested_at,NOW()),
|
|
125
|
+
status=CASE WHEN status='queued' THEN 'cancelled' ELSE status END,updated_at=NOW()
|
|
126
|
+
WHERE tenant_id=$1 AND meta->>'canvasId'=$2 AND kind IN ('canvas_worker','canvas_summary') AND status IN ('queued','leased')`, [work.tenantId, canvas['id']]);
|
|
127
|
+
await client.query("UPDATE canvas_agent_assignments SET status='cancelled',error='Workspace stopped by request',completed_at=NOW(),updated_at=NOW() WHERE canvas_id=$1 AND status NOT IN ('completed','failed','cancelled')", [canvas['id']]);
|
|
128
|
+
await queueCanvasWorkspace(client, String(canvas['id']));
|
|
129
|
+
value = { canvasId: canvas['id'], status: 'stopped' };
|
|
130
|
+
}
|
|
131
|
+
else if (report) {
|
|
132
|
+
if (summary)
|
|
133
|
+
await assertCanvasSummary(client, work);
|
|
134
|
+
else
|
|
135
|
+
await assertCanvasWorker(client, work);
|
|
136
|
+
value = await submitCanvasWorkReport(client, services, work, action.args, String(canvas['id']), String(canvas['project_id']), live.rows[0]['steer_inputs'].length + 1, Number(live.rows[0]['meta']['assignmentVersion'] ?? 1));
|
|
137
|
+
await queueCanvasReports(client, String(canvas['id']));
|
|
138
|
+
}
|
|
139
|
+
else if (assign && !(handoff && existing.some(row => row['agent_id'] === targetId))) {
|
|
140
|
+
if (existing.length + members.length > 32)
|
|
141
|
+
throw new Error('Canvas assignment capacity is 32 agents');
|
|
142
|
+
if (members.some(member => existing.some(row => row['agent_id'] === member.agentId)))
|
|
143
|
+
throw new Error('agent is already assigned to this Canvas');
|
|
144
|
+
api.assertCanvasDependencyDAG(members, new Set(existing.map(row => String(row['agent_id']))));
|
|
145
|
+
const used = new Set(existing.map(row => String(row['color'])));
|
|
146
|
+
const assignments = new Map(existing.map(row => [String(row['agent_id']), String(row['id'])]));
|
|
147
|
+
for (const member of members)
|
|
148
|
+
assignments.set(member.agentId, 'assignment-' + createHash('sha256').update(`${canvas['id']}:${member.agentId}`).digest('hex').slice(0, 28));
|
|
149
|
+
const created = [];
|
|
150
|
+
const meta = live.rows[0]['meta'];
|
|
151
|
+
if (typeof meta?.['text'] !== 'string')
|
|
152
|
+
throw new Error('Canvas delegation requires the captured original request');
|
|
153
|
+
for (const [offset, member] of members.entries()) {
|
|
154
|
+
const assignmentId = assignments.get(member.agentId);
|
|
155
|
+
const taskRef = 'canvas-work-' + createHash('sha256').update(assignmentId).digest('hex').slice(0, 28);
|
|
156
|
+
const area = api.canvasWorkArea(existing.length + offset), color = api.canvasAgentColor(member.agentId, used);
|
|
157
|
+
used.add(color);
|
|
158
|
+
const blocked = member.dependsOnAgentIds.length > 0;
|
|
159
|
+
await client.query(`INSERT INTO canvas_agent_assignments
|
|
160
|
+
(id,canvas_id,agent_id,assignment,color,status,work_x,work_y,work_width,work_height,work_id,execution_role)
|
|
161
|
+
VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12)`, [assignmentId, canvas['id'], member.agentId,
|
|
162
|
+
member.assignment, color, blocked ? 'blocked' : 'queued', area.x, area.y, area.width, area.height, taskRef, member.executionRole]);
|
|
163
|
+
await client.query(`INSERT INTO lingxios.agent_work_items
|
|
164
|
+
(id,tenant_id,agent_id,session_id,thread_id,principal_id,kind,lane,trigger_ref,priority,available_at,meta,steer_inputs)
|
|
165
|
+
VALUES($1,$2,$3,$4,$5,$6,'canvas_worker','collaboration',$7,180,CASE WHEN $8 THEN 'infinity'::timestamptz ELSE NOW() END,$9::jsonb,$10::jsonb)`, [taskRef, work.tenantId, member.agentId, work.sessionId, work.threadId ?? work.triggerRef, work.principalId, work.triggerRef, blocked,
|
|
166
|
+
JSON.stringify({ text: meta['text'], authorName: meta['authorName'], attachments: meta['attachments'], canvasId: canvas['id'], assignmentId,
|
|
167
|
+
assignment: member.assignment, assignmentVersion: 1, ...(handoffInstruction ? { assignmentSteers: [{ id: action.idempotencyKey, agentId: work.agentId, text: handoffInstruction }] } : {}),
|
|
168
|
+
executionRole: member.executionRole, parentWorkId: work.id,
|
|
169
|
+
parentRequestVersion: live.rows[0]['steer_inputs'].length + 1,
|
|
170
|
+
parentActionKey: action.idempotencyKey }), JSON.stringify(live.rows[0]['steer_inputs'])]);
|
|
171
|
+
created.push({ agentId: member.agentId, assignmentId, taskRef, waitingForDependencies: blocked });
|
|
172
|
+
}
|
|
173
|
+
for (const member of members) {
|
|
174
|
+
if (member.verifiesAgentId) {
|
|
175
|
+
const target = assignments.get(member.verifiesAgentId);
|
|
176
|
+
if (!target)
|
|
177
|
+
throw new Error('verifier target must belong to this Canvas');
|
|
178
|
+
await client.query('UPDATE canvas_agent_assignments SET verifies_assignment_id=$2 WHERE id=$1', [assignments.get(member.agentId), target]);
|
|
179
|
+
}
|
|
180
|
+
for (const dependency of member.dependsOnAgentIds)
|
|
181
|
+
await client.query(`INSERT INTO canvas_assignment_dependencies(assignment_id,depends_on_assignment_id) VALUES($1,$2)`, [assignments.get(member.agentId), assignments.get(dependency)]);
|
|
182
|
+
}
|
|
183
|
+
value = { canvasId: canvas['id'], assignments: created };
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
const assignment = existing.find(row => row['agent_id'] === targetId);
|
|
187
|
+
if (!assignment || !['queued', 'blocked', 'working', 'waiting'].includes(String(assignment['status'])))
|
|
188
|
+
throw new Error('active Canvas assignment not found');
|
|
189
|
+
const child = await client.query(`SELECT id,meta FROM lingxios.agent_work_items WHERE id=$1 AND tenant_id=$2
|
|
190
|
+
AND session_id=$3 AND principal_id=$4 AND kind='canvas_worker' AND meta->>'assignmentId'=$5
|
|
191
|
+
AND status IN ('queued','leased') FOR UPDATE`, [assignment['work_id'], work.tenantId, work.sessionId, work.principalId, assignment['id']]);
|
|
192
|
+
if (child.rows.length !== 1)
|
|
193
|
+
throw new Error('current recoverable Canvas work was not found');
|
|
194
|
+
if (steer) {
|
|
195
|
+
const meta = child.rows[0]['meta'];
|
|
196
|
+
const instructions = meta['assignmentSteers'] ?? [];
|
|
197
|
+
if (!Array.isArray(instructions) || instructions.length >= 16)
|
|
198
|
+
throw new Error('Canvas assignment instruction capacity reached');
|
|
199
|
+
const nextInstructions = [...instructions, { id: action.idempotencyKey, agentId: work.agentId, text: steer }];
|
|
200
|
+
if (Buffer.byteLength(JSON.stringify(nextInstructions)) > 64_000)
|
|
201
|
+
throw new Error('Canvas collaborator instructions exceed 64000 bytes');
|
|
202
|
+
await client.query(`UPDATE lingxios.agent_work_items SET meta=$2::jsonb,
|
|
203
|
+
preempt_requested_at=CASE WHEN status='leased' THEN NOW() ELSE preempt_requested_at END,updated_at=NOW() WHERE id=$1`, [assignment['work_id'], JSON.stringify({ ...meta, assignmentVersion: Number(meta['assignmentVersion'] ?? 1) + 1,
|
|
204
|
+
assignmentSteers: nextInstructions })]);
|
|
205
|
+
await client.query('UPDATE canvas_agent_assignments SET assignment=$2,updated_at=NOW() WHERE id=$1', [assignment['id'], steer]);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
await client.query(`UPDATE lingxios.agent_work_items SET cancel_requested_at=NOW(),
|
|
209
|
+
status=CASE WHEN status='queued' THEN 'cancelled' ELSE status END,updated_at=NOW() WHERE id=$1`, [assignment['work_id']]);
|
|
210
|
+
await client.query("UPDATE canvas_agent_assignments SET status='cancelled',error='Stopped by request',completed_at=NOW(),updated_at=NOW() WHERE id=$1", [assignment['id']]);
|
|
211
|
+
}
|
|
212
|
+
value = { assignmentId: assignment['id'], taskRef: assignment['work_id'], status: steer ? 'steered' : 'cancel_requested' };
|
|
213
|
+
}
|
|
214
|
+
if (handoff) {
|
|
215
|
+
const activityId = 'activity-' + createHash('sha256').update(action.idempotencyKey).digest('hex').slice(0, 32);
|
|
216
|
+
const detail = { fromAgentId: work.agentId, toAgentId: targetId, sourceAssignmentId: sourceAssignment['id'], task: members[0].assignment, context: handoffContext, frameIds };
|
|
217
|
+
await client.query(`INSERT INTO canvas_activity(id,canvas_id,frame_id,actor_id,actor_kind,action,detail)
|
|
218
|
+
VALUES($1,$2,$3,$4,'agent','handoff',$5::jsonb)`, [activityId, canvas['id'], sourceAssignment['active_frame_id'], work.agentId, JSON.stringify(detail)]);
|
|
219
|
+
await queueCanvasActivity(client, String(canvas['id']), activityId);
|
|
220
|
+
value = { ...value, activityId };
|
|
221
|
+
}
|
|
222
|
+
await queueCanvasAssignments(client, services, canvas['id'], existing);
|
|
223
|
+
if (start)
|
|
224
|
+
await queueCanvasWorkspace(client, String(canvas['id']));
|
|
225
|
+
const result = { ok: true, value };
|
|
226
|
+
const recorded = await client.query('INSERT INTO lingxios.agent_action_ledger(idempotency_key,result) VALUES($1,$2::jsonb) ON CONFLICT DO NOTHING RETURNING idempotency_key', [action.idempotencyKey, JSON.stringify(result)]);
|
|
227
|
+
if (recorded.rows.length !== 1)
|
|
228
|
+
throw new Error('Canvas action receipt already exists');
|
|
229
|
+
return result;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
export async function assertCanvasWorker(database, work) {
|
|
233
|
+
const { rows } = await database.query(`SELECT a.assignment,a.execution_role FROM canvas_agent_assignments a
|
|
234
|
+
JOIN canvases c ON c.id=a.canvas_id JOIN lingxios.agent_work_items w ON w.id=a.work_id
|
|
235
|
+
WHERE a.id=$1 AND a.agent_id=$2 AND c.id=$3 AND c.company_id=$4 AND c.conversation_id=$5
|
|
236
|
+
AND c.status='active' AND w.id=$6 AND w.principal_id=$7 AND a.status IN ('queued','working','waiting')
|
|
237
|
+
AND NOT EXISTS(SELECT 1 FROM canvas_assignment_dependencies d JOIN canvas_agent_assignments p ON p.id=d.depends_on_assignment_id
|
|
238
|
+
WHERE d.assignment_id=a.id AND p.status<>'completed')`, [work.meta?.['assignmentId'], work.agentId, work.meta?.['canvasId'], work.tenantId, work.sessionId, work.id, work.principalId]);
|
|
239
|
+
if (rows.length !== 1)
|
|
240
|
+
throw new Error('Canvas assignment is no longer runnable');
|
|
241
|
+
return rows[0];
|
|
242
|
+
}
|
|
243
|
+
/** Restart-safe projection of package work into domain assignment state, followed by dependency release. */
|
|
244
|
+
export async function reconcileCanvasWork(database, services) {
|
|
245
|
+
return withTransaction(database, async (client) => {
|
|
246
|
+
await client.query("SET LOCAL lock_timeout='5s'");
|
|
247
|
+
await client.query("SET LOCAL statement_timeout='10s'");
|
|
248
|
+
const canvases = await client.query(`SELECT c.id FROM canvases c WHERE EXISTS(
|
|
249
|
+
SELECT 1 FROM canvas_agent_assignments a JOIN lingxios.agent_work_items w ON w.id=a.work_id
|
|
250
|
+
WHERE a.canvas_id=c.id AND w.kind='canvas_worker' AND w.tenant_id=c.company_id
|
|
251
|
+
AND w.meta->>'assignmentId'=a.id AND a.status IN ('queued','blocked','working','waiting'))
|
|
252
|
+
OR (c.status='summarizing' AND EXISTS(SELECT 1 FROM lingxios.agent_work_items w WHERE w.kind='canvas_summary' AND w.tenant_id=c.company_id AND w.meta->>'canvasId'=c.id))
|
|
253
|
+
ORDER BY c.updated_at LIMIT 32 FOR UPDATE OF c SKIP LOCKED`);
|
|
254
|
+
for (const canvas of canvases.rows) {
|
|
255
|
+
const id = canvas['id'];
|
|
256
|
+
const previous = (await client.query('SELECT * FROM canvas_agent_assignments WHERE canvas_id=$1', [id])).rows;
|
|
257
|
+
await client.query(`UPDATE lingxios.agent_work_items w SET cancel_requested_at=COALESCE(w.cancel_requested_at,NOW()),
|
|
258
|
+
status=CASE WHEN w.status='queued' THEN 'cancelled' ELSE w.status END,updated_at=NOW()
|
|
259
|
+
FROM canvas_agent_assignments a,canvases c WHERE a.canvas_id=$1 AND c.id=a.canvas_id
|
|
260
|
+
AND w.id=a.work_id AND w.kind='canvas_worker' AND w.tenant_id=c.company_id AND w.meta->>'assignmentId'=a.id
|
|
261
|
+
AND w.status IN ('queued','leased') AND (c.status<>'active' OR a.status='cancelled')`, [id]);
|
|
262
|
+
await client.query(`UPDATE canvas_agent_assignments a SET
|
|
263
|
+
status=CASE WHEN w.status='cancelled' OR w.cancel_requested_at IS NOT NULL THEN 'cancelled'
|
|
264
|
+
WHEN w.status='failed' THEN 'failed'
|
|
265
|
+
WHEN w.status='completed' AND w.goal_outcome->>'status' IN ('awaiting_input','awaiting_approval') THEN 'waiting'
|
|
266
|
+
WHEN w.status='completed' AND r.id IS NOT NULL THEN 'completed'
|
|
267
|
+
WHEN w.status='completed' THEN 'failed'
|
|
268
|
+
WHEN w.status='leased' THEN 'working' ELSE a.status END,
|
|
269
|
+
result=CASE WHEN w.status='completed' THEN w.result_text ELSE a.result END,
|
|
270
|
+
error=CASE WHEN w.status='failed' THEN w.error
|
|
271
|
+
WHEN w.status='completed' AND COALESCE(w.goal_outcome->>'status','') NOT IN ('awaiting_input','awaiting_approval') AND r.id IS NULL
|
|
272
|
+
THEN 'Canvas worker ended without a persisted assignment report' ELSE a.error END,
|
|
273
|
+
completed_at=CASE WHEN w.status IN ('failed','cancelled') OR w.cancel_requested_at IS NOT NULL
|
|
274
|
+
OR (w.status='completed' AND COALESCE(w.goal_outcome->>'status','') NOT IN ('awaiting_input','awaiting_approval'))
|
|
275
|
+
THEN COALESCE(a.completed_at,NOW()) ELSE NULL END,updated_at=NOW()
|
|
276
|
+
FROM lingxios.agent_work_items w LEFT JOIN canvas_assignment_reports r ON r.assignment_id=w.meta->>'assignmentId'
|
|
277
|
+
AND r.author_agent_id=w.agent_id AND r.company_id=w.tenant_id AND EXISTS (
|
|
278
|
+
SELECT 1 FROM evidence_records e WHERE e.id=r.evidence_id AND e.company_id=w.tenant_id
|
|
279
|
+
AND e.data->>'workId'=w.id AND e.data->>'requestVersion'=(jsonb_array_length(w.steer_inputs)+1)::text)
|
|
280
|
+
AND EXISTS (SELECT 1 FROM evidence_records e WHERE e.id=r.evidence_id
|
|
281
|
+
AND e.data->>'assignmentVersion'=COALESCE(w.meta->>'assignmentVersion','1'))
|
|
282
|
+
WHERE a.canvas_id=$1 AND a.work_id=w.id AND w.kind='canvas_worker' AND w.meta->>'assignmentId'=a.id
|
|
283
|
+
AND a.status IN ('queued','blocked','working','waiting')`, [id]);
|
|
284
|
+
await client.query(`WITH RECURSIVE stopped(id) AS (
|
|
285
|
+
SELECT a.id FROM canvas_agent_assignments a WHERE a.canvas_id=$1 AND a.status IN ('failed','cancelled')
|
|
286
|
+
UNION SELECT d.assignment_id FROM canvas_assignment_dependencies d JOIN stopped s ON s.id=d.depends_on_assignment_id)
|
|
287
|
+
UPDATE canvas_agent_assignments a SET status='cancelled',error='Canvas dependency failed or was cancelled',completed_at=NOW(),updated_at=NOW()
|
|
288
|
+
WHERE a.canvas_id=$1 AND a.status='blocked' AND a.id IN (SELECT id FROM stopped)`, [id]);
|
|
289
|
+
await client.query(`UPDATE lingxios.agent_work_items w SET status='cancelled',cancel_requested_at=NOW(),updated_at=NOW()
|
|
290
|
+
FROM canvas_agent_assignments a WHERE a.canvas_id=$1 AND a.work_id=w.id AND a.status='cancelled'
|
|
291
|
+
AND w.kind='canvas_worker' AND w.meta->>'assignmentId'=a.id AND w.status='queued'`, [id]);
|
|
292
|
+
await client.query(`UPDATE canvas_agent_assignments a SET status='queued',updated_at=NOW()
|
|
293
|
+
WHERE a.canvas_id=$1 AND a.status='blocked' AND NOT EXISTS (
|
|
294
|
+
SELECT 1 FROM canvas_assignment_dependencies d JOIN canvas_agent_assignments p ON p.id=d.depends_on_assignment_id
|
|
295
|
+
WHERE d.assignment_id=a.id AND (p.status<>'completed' OR NOT EXISTS(
|
|
296
|
+
SELECT 1 FROM canvas_assignment_reports r WHERE r.assignment_id=p.id AND r.author_agent_id=p.agent_id)))`, [id]);
|
|
297
|
+
await client.query(`UPDATE lingxios.agent_work_items w SET available_at=NOW(),updated_at=NOW()
|
|
298
|
+
FROM canvas_agent_assignments a WHERE a.canvas_id=$1 AND a.work_id=w.id AND a.status='queued'
|
|
299
|
+
AND w.kind='canvas_worker' AND w.meta->>'assignmentId'=a.id AND w.status='queued' AND w.available_at='infinity'::timestamptz`, [id]);
|
|
300
|
+
await client.query('UPDATE canvases SET updated_at=NOW() WHERE id=$1', [id]);
|
|
301
|
+
await queueCanvasAssignments(client, services, id, previous);
|
|
302
|
+
await reconcileCanvasSummary(client, String(id));
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=canvas-work.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-work.js","sourceRoot":"","sources":["../../../../src/integrations/lingxiloop/canvas-work.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HostAction, WorkItem } from '../../protocol/types.js';
|
|
2
|
+
import type { LingxiLoopServices } from './service-contracts.js';
|
|
3
|
+
export declare const CANVAS_METHODS: {
|
|
4
|
+
readonly current: readonly [];
|
|
5
|
+
readonly available_agents: readonly [];
|
|
6
|
+
readonly add_comment: readonly ["body", "frameId"];
|
|
7
|
+
readonly create_frame: readonly ["frame"];
|
|
8
|
+
readonly update_frame: readonly ["frameId", "patch"];
|
|
9
|
+
readonly append_content: readonly ["frameId", "content"];
|
|
10
|
+
readonly delete_frame: readonly ["frameId"];
|
|
11
|
+
};
|
|
12
|
+
export declare function executeCanvas(work: Omit<WorkItem, 'leaseToken'>, action: HostAction, services: Pick<LingxiLoopServices, 'canvas' | 'permissionService'>): Promise<unknown>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { nativeWork } from './actions.js';
|
|
2
|
+
export const CANVAS_METHODS = { current: [], available_agents: [], add_comment: ['body', 'frameId'], create_frame: ['frame'], update_frame: ['frameId', 'patch'], append_content: ['frameId', 'content'], delete_frame: ['frameId'] };
|
|
3
|
+
export async function executeCanvas(work, action, services) {
|
|
4
|
+
const api = services.canvas;
|
|
5
|
+
const method = action.action.slice('canvas.'.length);
|
|
6
|
+
if (!api || !action.action.startsWith('canvas.') || !Object.hasOwn(CANVAS_METHODS, method))
|
|
7
|
+
throw new Error('unsupported canvas action');
|
|
8
|
+
const allowed = CANVAS_METHODS[method];
|
|
9
|
+
if (Object.keys(action.args).some(key => !allowed.includes(key)))
|
|
10
|
+
throw new Error(method === 'current' ? 'canvas.current accepts no arguments' : 'unknown canvas argument');
|
|
11
|
+
const native = nativeWork(work);
|
|
12
|
+
// The native snapshot reader does not authorize its actor argument.
|
|
13
|
+
await services.permissionService.assertCan({ actorUserId: native.authorizationUserId, companyId: native.companyId,
|
|
14
|
+
action: 'conversation:read', resource: { type: 'conversation', id: native.channelId } });
|
|
15
|
+
if (method === 'available_agents') {
|
|
16
|
+
await services.permissionService.assertCan({ actorUserId: native.authorizationUserId, companyId: native.companyId,
|
|
17
|
+
action: 'agent:read', resource: { type: 'conversation', id: native.channelId } });
|
|
18
|
+
return api.listCanvasAvailableAgents(native.companyId);
|
|
19
|
+
}
|
|
20
|
+
const snapshot = await api.getConversationCanvas(native.companyId, native.channelId, native.authorizationUserId);
|
|
21
|
+
if (method === 'current')
|
|
22
|
+
return snapshot;
|
|
23
|
+
if (!snapshot || typeof snapshot !== 'object' || !('id' in snapshot) || typeof snapshot.id !== 'string'
|
|
24
|
+
|| !snapshot.id.trim() || !('companyId' in snapshot) || snapshot.companyId !== native.companyId
|
|
25
|
+
|| !('conversationId' in snapshot) || snapshot.conversationId !== native.channelId)
|
|
26
|
+
throw new Error('current conversation canvas not found');
|
|
27
|
+
if (method === 'add_comment') {
|
|
28
|
+
const comment = api.canvasCommentRequestSchema.parse({ ...action.args, canvasId: snapshot.id });
|
|
29
|
+
if (comment.frameId && (!('frames' in snapshot) || !Array.isArray(snapshot.frames)
|
|
30
|
+
|| !snapshot.frames.some(frame => frame && typeof frame === 'object' && frame.id === comment.frameId)))
|
|
31
|
+
throw new Error('frame is outside the current conversation canvas');
|
|
32
|
+
await services.permissionService.assertCan({ actorUserId: native.authorizationUserId, companyId: native.companyId,
|
|
33
|
+
action: 'canvas:write', resource: comment.frameId ? { type: 'canvas_frame', id: comment.frameId } : { type: 'canvas', id: snapshot.id } });
|
|
34
|
+
return api.addCanvasComment({ companyId: native.companyId, actorId: native.agentId, actorKind: 'agent',
|
|
35
|
+
canvasId: snapshot.id, body: comment.body, ...(comment.frameId ? { frameId: comment.frameId } : {}) });
|
|
36
|
+
}
|
|
37
|
+
if (method === 'update_frame' || method === 'append_content' || method === 'delete_frame') {
|
|
38
|
+
const frameId = action.args['frameId'], patch = action.args['patch'];
|
|
39
|
+
if (typeof frameId !== 'string' || !frameId.trim() || frameId.length > 2000)
|
|
40
|
+
throw new Error('frameId must be non-empty');
|
|
41
|
+
if (!('frames' in snapshot) || !Array.isArray(snapshot.frames)
|
|
42
|
+
|| !snapshot.frames.some(frame => frame && typeof frame === 'object' && frame.id === frameId))
|
|
43
|
+
throw new Error('frame is outside the current conversation canvas');
|
|
44
|
+
if (method === 'delete_frame') {
|
|
45
|
+
await services.permissionService.assertCan({ actorUserId: native.authorizationUserId, companyId: native.companyId,
|
|
46
|
+
action: 'canvas:write', resource: { type: 'canvas_frame', id: frameId } });
|
|
47
|
+
return api.deleteCanvasFrame({ companyId: native.companyId, actorId: native.agentId, actorKind: 'agent', frameId });
|
|
48
|
+
}
|
|
49
|
+
if (method === 'append_content') {
|
|
50
|
+
const content = action.args['content'];
|
|
51
|
+
if (typeof content !== 'string' || !content.length || Buffer.byteLength(content, 'utf8') > 64 * 1024)
|
|
52
|
+
throw new Error('append content must contain 1 to 65536 UTF-8 bytes');
|
|
53
|
+
await services.permissionService.assertCan({ actorUserId: native.authorizationUserId, companyId: native.companyId,
|
|
54
|
+
action: 'canvas:write', resource: { type: 'canvas_frame', id: frameId } });
|
|
55
|
+
return api.appendCanvasFrameContent({ companyId: native.companyId, actorId: native.agentId, actorKind: 'agent', frameId, content });
|
|
56
|
+
}
|
|
57
|
+
if (!patch || typeof patch !== 'object' || Array.isArray(patch))
|
|
58
|
+
throw new Error('patch must be an object');
|
|
59
|
+
const checked = api.canvasFrameUpdateRequestSchema.parse(patch);
|
|
60
|
+
if (!Number.isSafeInteger(checked['baseRevision']) || Number(checked['baseRevision']) < 0)
|
|
61
|
+
throw new Error('baseRevision is required for frame updates');
|
|
62
|
+
if (!Object.keys(checked).some(key => key !== 'baseRevision'))
|
|
63
|
+
throw new Error('frame update requires changed fields');
|
|
64
|
+
await services.permissionService.assertCan({ actorUserId: native.authorizationUserId, companyId: native.companyId,
|
|
65
|
+
action: 'canvas:write', resource: { type: 'canvas_frame', id: frameId } });
|
|
66
|
+
return api.updateCanvasFrame({ companyId: native.companyId, actorId: native.agentId, actorKind: 'agent', frameId, patch: checked });
|
|
67
|
+
}
|
|
68
|
+
const frame = action.args['frame'];
|
|
69
|
+
if (!frame || typeof frame !== 'object' || Array.isArray(frame))
|
|
70
|
+
throw new Error('frame must be an object');
|
|
71
|
+
if (Object.hasOwn(frame, 'canvasId'))
|
|
72
|
+
throw new Error('canvasId is supplied by the package');
|
|
73
|
+
const checked = api.canvasFrameCreateRequestSchema.parse({ ...frame, canvasId: snapshot.id });
|
|
74
|
+
await services.permissionService.assertCan({ actorUserId: native.authorizationUserId, companyId: native.companyId,
|
|
75
|
+
action: 'canvas:write', resource: { type: 'canvas', id: snapshot.id } });
|
|
76
|
+
return api.createCanvasFrame({ companyId: native.companyId, actorId: native.agentId, actorKind: 'agent',
|
|
77
|
+
idempotencyKey: action.idempotencyKey, canvasId: snapshot.id, frame: checked });
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=canvas.js.map
|