@kelloggt/dsh-program-agents 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +90 -2
- package/cordis.patch.yml +5 -0
- package/dist/app/agents.d.ts +50 -0
- package/dist/app/agents.js +70 -0
- package/dist/app/agents.js.map +1 -0
- package/dist/app/conversations.d.ts +8 -0
- package/dist/app/conversations.js +26 -0
- package/dist/app/conversations.js.map +1 -0
- package/dist/app/endpoints.d.ts +36 -0
- package/dist/app/endpoints.js +162 -0
- package/dist/app/endpoints.js.map +1 -0
- package/dist/app/inbox.d.ts +61 -0
- package/dist/app/inbox.js +253 -0
- package/dist/app/inbox.js.map +1 -0
- package/dist/app/index.d.ts +70 -0
- package/dist/app/index.js +147 -0
- package/dist/app/index.js.map +1 -0
- package/dist/app/mailbox.d.ts +63 -0
- package/dist/app/mailbox.js +173 -0
- package/dist/app/mailbox.js.map +1 -0
- package/dist/app/models.d.ts +32 -0
- package/dist/app/models.js +13 -0
- package/dist/app/models.js.map +1 -0
- package/dist/app/server.d.ts +36 -0
- package/dist/app/server.js +233 -0
- package/dist/app/server.js.map +1 -0
- package/dist/app/stream-server.d.ts +9 -0
- package/dist/app/stream-server.js +77 -0
- package/dist/app/stream-server.js.map +1 -0
- package/dist/app/stream.d.ts +4 -0
- package/dist/app/stream.js +93 -0
- package/dist/app/stream.js.map +1 -0
- package/dist/app/tools.d.ts +16 -0
- package/dist/app/tools.js +24 -0
- package/dist/app/tools.js.map +1 -0
- package/dist/client/controller.d.ts +21 -0
- package/dist/client/controller.js +140 -0
- package/dist/client/controller.js.map +1 -0
- package/dist/client/index.d.ts +22 -0
- package/dist/client/index.js +14 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/model.d.ts +66 -0
- package/dist/client/model.js +147 -0
- package/dist/client/model.js.map +1 -0
- package/dist/client/models.d.ts +11 -0
- package/dist/client/models.js +27 -0
- package/dist/client/models.js.map +1 -0
- package/dist/client/transport.d.ts +64 -0
- package/dist/client/transport.js +141 -0
- package/dist/client/transport.js.map +1 -0
- package/dist/client/view.d.ts +19 -0
- package/dist/client/view.js +69 -0
- package/dist/client/view.js.map +1 -0
- package/dist/client.js +673 -0
- package/dist/conversations.d.ts +92 -0
- package/dist/conversations.js +6 -0
- package/dist/conversations.js.map +1 -0
- package/dist/endpoints.d.ts +48 -0
- package/dist/endpoints.js +43 -0
- package/dist/endpoints.js.map +1 -0
- package/dist/examples/dashboard.js +42 -0
- package/dist/examples/dynamic-server.js +27 -0
- package/dist/examples/inbox-worker.js +22 -0
- package/dist/examples/model-slots.js +19 -0
- package/dist/examples/standalone-supervisor.js +20 -0
- package/dist/host/adapter.d.ts +195 -0
- package/dist/host/adapter.js +630 -0
- package/dist/host/adapter.js.map +1 -0
- package/dist/host/agents.d.ts +35 -0
- package/dist/host/agents.js +222 -0
- package/dist/host/agents.js.map +1 -0
- package/dist/host/audit.d.ts +14 -0
- package/dist/host/audit.js +39 -0
- package/dist/host/audit.js.map +1 -0
- package/dist/host/catalog.d.ts +53 -0
- package/dist/host/catalog.js +116 -0
- package/dist/host/catalog.js.map +1 -0
- package/dist/host/contracts.d.ts +38 -0
- package/dist/host/contracts.js +2 -0
- package/dist/host/contracts.js.map +1 -0
- package/dist/host/conversations.d.ts +41 -0
- package/dist/host/conversations.js +324 -0
- package/dist/host/conversations.js.map +1 -0
- package/dist/host/events.d.ts +12 -0
- package/dist/host/events.js +106 -0
- package/dist/host/events.js.map +1 -0
- package/dist/host/http.d.ts +14 -0
- package/dist/host/http.js +30 -0
- package/dist/host/http.js.map +1 -0
- package/dist/host/index.d.ts +23 -0
- package/dist/host/index.js +86 -0
- package/dist/host/index.js.map +1 -0
- package/dist/host/installed-v10.js +27181 -0
- package/dist/host/installed-v11.js +27181 -0
- package/dist/host/installed-v12.js +27181 -0
- package/dist/host/installed-v13.js +27181 -0
- package/dist/host/installed-v2.js +27181 -0
- package/dist/host/installed-v3.js +27181 -0
- package/dist/host/installed-v4.js +27181 -0
- package/dist/host/installed-v5.js +27181 -0
- package/dist/host/installed-v6.js +27181 -0
- package/dist/host/installed-v7.js +27181 -0
- package/dist/host/installed-v8.js +27181 -0
- package/dist/host/installed-v9.js +27181 -0
- package/dist/host/mcp.d.ts +11 -0
- package/dist/host/mcp.js +42 -0
- package/dist/host/mcp.js.map +1 -0
- package/dist/host/models.d.ts +37 -0
- package/dist/host/models.js +141 -0
- package/dist/host/models.js.map +1 -0
- package/dist/host/operations.d.ts +22 -0
- package/dist/host/operations.js +72 -0
- package/dist/host/operations.js.map +1 -0
- package/dist/host/plugin.js +27181 -0
- package/dist/host/policies.d.ts +36 -0
- package/dist/host/policies.js +73 -0
- package/dist/host/policies.js.map +1 -0
- package/dist/host/requests.d.ts +57 -0
- package/dist/host/requests.js +353 -0
- package/dist/host/requests.js.map +1 -0
- package/dist/host/skills.d.ts +2 -0
- package/dist/host/skills.js +45 -0
- package/dist/host/skills.js.map +1 -0
- package/dist/host/tool-client.d.ts +19 -0
- package/dist/host/tool-client.js +62 -0
- package/dist/host/tool-client.js.map +1 -0
- package/dist/host/validation.d.ts +5 -0
- package/dist/host/validation.js +42 -0
- package/dist/host/validation.js.map +1 -0
- package/dist/mcp.d.ts +7 -0
- package/dist/mcp.js +2 -0
- package/dist/mcp.js.map +1 -0
- package/dist/models.d.ts +34 -0
- package/dist/models.js +53 -0
- package/dist/models.js.map +1 -0
- package/dist/monitoring/error-buffer.d.ts +89 -0
- package/dist/monitoring/error-buffer.js +355 -0
- package/dist/monitoring/error-buffer.js.map +1 -0
- package/dist/monitoring/fatal.d.ts +6 -0
- package/dist/monitoring/fatal.js +32 -0
- package/dist/monitoring/fatal.js.map +1 -0
- package/dist/monitoring/index.d.ts +7 -0
- package/dist/monitoring/index.js +8 -0
- package/dist/monitoring/index.js.map +1 -0
- package/dist/monitoring/logger.d.ts +45 -0
- package/dist/monitoring/logger.js +174 -0
- package/dist/monitoring/logger.js.map +1 -0
- package/dist/monitoring/schemas.d.ts +34 -0
- package/dist/monitoring/schemas.js +132 -0
- package/dist/monitoring/schemas.js.map +1 -0
- package/dist/monitoring/standard.d.ts +51 -0
- package/dist/monitoring/standard.js +140 -0
- package/dist/monitoring/standard.js.map +1 -0
- package/dist/monitoring/tailer.d.ts +41 -0
- package/dist/monitoring/tailer.js +210 -0
- package/dist/monitoring/tailer.js.map +1 -0
- package/dist/requests.d.ts +92 -0
- package/dist/requests.js +120 -0
- package/dist/requests.js.map +1 -0
- package/dist/runtime/bootstrap.d.ts +1 -0
- package/dist/runtime/bootstrap.js +25 -0
- package/dist/runtime/bootstrap.js.map +1 -0
- package/dist/runtime/definitions.d.ts +7 -0
- package/dist/runtime/definitions.js +138 -0
- package/dist/runtime/definitions.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/log-file.d.ts +24 -0
- package/dist/runtime/log-file.js +124 -0
- package/dist/runtime/log-file.js.map +1 -0
- package/dist/runtime/protocol.d.ts +60 -0
- package/dist/runtime/protocol.js +155 -0
- package/dist/runtime/protocol.js.map +1 -0
- package/dist/runtime/registry.d.ts +8 -0
- package/dist/runtime/registry.js +38 -0
- package/dist/runtime/registry.js.map +1 -0
- package/dist/runtime/supervisor.d.ts +74 -0
- package/dist/runtime/supervisor.js +881 -0
- package/dist/runtime/supervisor.js.map +1 -0
- package/dist/sdk/connection.d.ts +33 -0
- package/dist/sdk/connection.js +265 -0
- package/dist/sdk/connection.js.map +1 -0
- package/dist/sdk/index.d.ts +8 -0
- package/dist/sdk/index.js +2 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/supervision.d.ts +22 -0
- package/dist/supervision.js +32 -0
- package/dist/supervision.js.map +1 -0
- package/dist/types.d.ts +170 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docs/installation.md +37 -0
- package/docs/log-format.md +102 -0
- package/docs/publishing.md +45 -0
- package/docs/supervision.md +73 -0
- package/examples/dashboard.ts +31 -0
- package/examples/dsh-web-local.patch.yml +15 -0
- package/examples/dynamic-server.ts +13 -0
- package/examples/inbox-worker.ts +17 -0
- package/examples/model-slots.ts +12 -0
- package/examples/standalone-supervisor.ts +14 -0
- package/examples/watch-server.ts +12 -0
- package/package.json +134 -3
- package/schemas/dsh.http.request.v1.schema.json +14 -0
- package/schemas/dsh.program.error-batch.v1.schema.json +24 -0
- package/schemas/dsh.program.error.v1.schema.json +8 -0
- package/schemas/standard-log-record.v1.schema.json +26 -0
- package/skills/program-agents/SKILL.md +124 -0
- package/skills/program-agents/chat-sidebar.md +23 -0
- package/skills/program-agents/endpoints.md +92 -0
- package/skills/program-agents/inboxes.md +120 -0
- package/skills/program-agents/log-format.md +102 -0
- package/skills/program-agents/models.md +59 -0
- package/skills/program-agents/references/chat-sidebar/AgentSidebar.tsx +181 -0
- package/skills/program-agents/references/chat-sidebar/README.md +181 -0
- package/skills/program-agents/references/chat-sidebar/agent-sidebar.css +37 -0
- package/skills/program-agents/references/chat-sidebar/backend.ts +184 -0
- package/skills/program-agents/references/chat-sidebar/protocol.ts +214 -0
- package/skills/program-agents/schemas/dsh.http.request.v1.schema.json +14 -0
- package/skills/program-agents/schemas/dsh.program.error-batch.v1.schema.json +24 -0
- package/skills/program-agents/schemas/dsh.program.error.v1.schema.json +8 -0
- package/skills/program-agents/schemas/standard-log-record.v1.schema.json +26 -0
- package/skills/program-agents/ui-patterns.md +39 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, open, rename, stat, chmod } from 'node:fs/promises';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { errorFingerprint, isJson, isStandardLogRecord, MAX_LOG_LINE_BYTES, redact } from './standard.js';
|
|
5
|
+
import { defaultLogRegistry } from './schemas.js';
|
|
6
|
+
function positive(value, fallback, name) {
|
|
7
|
+
if (value === undefined)
|
|
8
|
+
return fallback;
|
|
9
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
10
|
+
throw new Error(`Invalid ${name}`);
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function normalizeError(error) {
|
|
14
|
+
if (!(error instanceof Error))
|
|
15
|
+
return error;
|
|
16
|
+
const result = { name: error.name, message: error.message };
|
|
17
|
+
if (error.stack)
|
|
18
|
+
result.stack = error.stack;
|
|
19
|
+
const code = error.code;
|
|
20
|
+
if (typeof code === 'string' || typeof code === 'number')
|
|
21
|
+
result.code = code;
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
class RotatingFile {
|
|
25
|
+
options;
|
|
26
|
+
bytes = 0;
|
|
27
|
+
day = '';
|
|
28
|
+
initialized = false;
|
|
29
|
+
path;
|
|
30
|
+
constructor(file, options) {
|
|
31
|
+
this.options = options;
|
|
32
|
+
this.path = resolve(file);
|
|
33
|
+
}
|
|
34
|
+
async write(line, now) {
|
|
35
|
+
if (!this.initialized) {
|
|
36
|
+
await mkdir(dirname(this.path), { recursive: true, ...(this.options.private ? { mode: 0o700 } : {}) });
|
|
37
|
+
try {
|
|
38
|
+
const s = await stat(this.path);
|
|
39
|
+
this.bytes = s.size;
|
|
40
|
+
this.day = s.mtime.toISOString().slice(0, 10);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (error.code !== 'ENOENT')
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
this.initialized = true;
|
|
47
|
+
}
|
|
48
|
+
const today = now.toISOString().slice(0, 10);
|
|
49
|
+
const length = Buffer.byteLength(line);
|
|
50
|
+
if (this.bytes && (this.bytes + length > positive(this.options.maxBytes, 10 * 1024 * 1024, 'maxBytes') || this.day !== today)) {
|
|
51
|
+
const count = positive(this.options.maxFiles, 5, 'maxFiles');
|
|
52
|
+
if (count === 1) {
|
|
53
|
+
const f = await open(this.path, 'w', this.options.private ? 0o600 : 0o666);
|
|
54
|
+
await f.close();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Every target is the resolved configured path plus a fixed numeric suffix.
|
|
58
|
+
for (let i = count - 2; i >= 0; i--) {
|
|
59
|
+
const from = i === 0 ? this.path : `${this.path}.${i}`;
|
|
60
|
+
const to = `${this.path}.${i + 1}`;
|
|
61
|
+
try {
|
|
62
|
+
await rename(from, to);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (error.code !== 'ENOENT')
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
this.bytes = 0;
|
|
71
|
+
}
|
|
72
|
+
const handle = await open(this.path, 'a', this.options.private ? 0o600 : 0o666);
|
|
73
|
+
try {
|
|
74
|
+
if (this.options.private)
|
|
75
|
+
await chmod(this.path, 0o600);
|
|
76
|
+
await handle.writeFile(line, 'utf8');
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
await handle.close();
|
|
80
|
+
}
|
|
81
|
+
this.bytes += length;
|
|
82
|
+
this.day = today;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Serialized writes respect stdout backpressure, with a bounded application queue. */
|
|
86
|
+
export class StructuredLogger {
|
|
87
|
+
options;
|
|
88
|
+
queue = Promise.resolve();
|
|
89
|
+
pendingBytes = 0;
|
|
90
|
+
failure;
|
|
91
|
+
closed = false;
|
|
92
|
+
file;
|
|
93
|
+
stdout;
|
|
94
|
+
constructor(options = {}) {
|
|
95
|
+
this.options = options;
|
|
96
|
+
positive(options.maxBytes, 10 * 1024 * 1024, 'maxBytes');
|
|
97
|
+
positive(options.maxFiles, 5, 'maxFiles');
|
|
98
|
+
positive(options.maxQueueBytes, 1024 * 1024, 'maxQueueBytes');
|
|
99
|
+
if (options.file && options.logsPath)
|
|
100
|
+
throw new Error('Use file or logsPath, not both');
|
|
101
|
+
const file = options.file ?? (options.logsPath ? resolve(options.logsPath, 'app-log.jsonl') : undefined);
|
|
102
|
+
if (file)
|
|
103
|
+
this.file = new RotatingFile(file, options);
|
|
104
|
+
this.stdout = options.stdout === false ? undefined : options.stdout && typeof options.stdout !== 'boolean' ? options.stdout : process.stdout;
|
|
105
|
+
}
|
|
106
|
+
debug(message, data, metadata) { return this.log('DEBUG', message, data, metadata); }
|
|
107
|
+
info(message, data, metadata) { return this.log('INFO', message, data, metadata); }
|
|
108
|
+
warn(message, data, metadata) { return this.log('WARNING', message, data, metadata); }
|
|
109
|
+
error(message, data, metadata) { return this.log('ERROR', message, data, metadata); }
|
|
110
|
+
log(level, message, data, metadata = {}) {
|
|
111
|
+
const record = { ...metadata, timestamp: metadata.timestamp ?? (this.options.clock?.() ?? new Date()).toISOString(), level, log_type: metadata.log_type ?? (level === 'ERROR' ? 'dsh.program.error.v1' : 'dsh.program.log.v1'), message };
|
|
112
|
+
if (data !== undefined)
|
|
113
|
+
record.data = data;
|
|
114
|
+
if (metadata.error)
|
|
115
|
+
record.error = normalizeError(metadata.error);
|
|
116
|
+
return this.record(record);
|
|
117
|
+
}
|
|
118
|
+
record(input) {
|
|
119
|
+
if (this.closed)
|
|
120
|
+
throw new Error('Logger is closed');
|
|
121
|
+
if (!isJson(input))
|
|
122
|
+
throw new Error('Log record must contain finite, bounded JSON values');
|
|
123
|
+
const record = redact(input);
|
|
124
|
+
record.event_id ??= randomUUID();
|
|
125
|
+
if (record.level === 'ERROR') {
|
|
126
|
+
record.error ??= { name: 'Error', message: record.message };
|
|
127
|
+
record.error.fingerprint = errorFingerprint(record);
|
|
128
|
+
}
|
|
129
|
+
if (!isStandardLogRecord(record, this.options.registry ?? defaultLogRegistry))
|
|
130
|
+
throw new Error('Invalid standard log record or registered payload');
|
|
131
|
+
const line = JSON.stringify(record) + '\n';
|
|
132
|
+
const size = Buffer.byteLength(line);
|
|
133
|
+
if (size > MAX_LOG_LINE_BYTES)
|
|
134
|
+
throw new Error('Log line exceeds 64 KiB');
|
|
135
|
+
if (this.pendingBytes + size > positive(this.options.maxQueueBytes, 1024 * 1024, 'maxQueueBytes'))
|
|
136
|
+
throw new Error('Log queue capacity exceeded; await flush()');
|
|
137
|
+
this.pendingBytes += size;
|
|
138
|
+
this.queue = this.queue.then(async () => {
|
|
139
|
+
try {
|
|
140
|
+
// File first: a blocked stdout must not prevent this record becoming durable.
|
|
141
|
+
if (this.file)
|
|
142
|
+
await this.file.write(line, this.options.clock?.() ?? new Date());
|
|
143
|
+
if (this.stdout)
|
|
144
|
+
await new Promise((yes, no) => {
|
|
145
|
+
const stream = this.stdout;
|
|
146
|
+
const onError = (error) => { stream.off('error', onError); no(error); };
|
|
147
|
+
stream.once('error', onError);
|
|
148
|
+
try {
|
|
149
|
+
stream.write(line, error => { stream.off('error', onError); error ? no(error) : yes(); });
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
stream.off('error', onError);
|
|
153
|
+
no(error);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
this.failure ??= error;
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
this.pendingBytes -= size;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
return record;
|
|
165
|
+
}
|
|
166
|
+
async flush() { await this.queue; if (this.failure) {
|
|
167
|
+
const error = this.failure;
|
|
168
|
+
this.failure = undefined;
|
|
169
|
+
throw error;
|
|
170
|
+
} }
|
|
171
|
+
async close() { this.closed = true; await this.flush(); }
|
|
172
|
+
}
|
|
173
|
+
export function createLogger(options = {}) { return new StructuredLogger(options); }
|
|
174
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/monitoring/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { JsonValue } from '../types.js';
|
|
2
|
+
/** Deliberately small JSON Schema subset; unsupported keywords fail registration. */
|
|
3
|
+
export interface PayloadSchema {
|
|
4
|
+
type?: 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null';
|
|
5
|
+
properties?: Record<string, PayloadSchema>;
|
|
6
|
+
required?: string[];
|
|
7
|
+
additionalProperties?: boolean | PayloadSchema;
|
|
8
|
+
items?: PayloadSchema;
|
|
9
|
+
enum?: JsonValue[];
|
|
10
|
+
const?: JsonValue;
|
|
11
|
+
oneOf?: PayloadSchema[];
|
|
12
|
+
minLength?: number;
|
|
13
|
+
maxLength?: number;
|
|
14
|
+
minimum?: number;
|
|
15
|
+
maximum?: number;
|
|
16
|
+
minItems?: number;
|
|
17
|
+
maxItems?: number;
|
|
18
|
+
pattern?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
$id?: string;
|
|
21
|
+
$schema?: string;
|
|
22
|
+
title?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class LogSchemaRegistry {
|
|
25
|
+
private readonly schemas;
|
|
26
|
+
register(logType: string, schema: PayloadSchema, options?: {
|
|
27
|
+
optional?: boolean;
|
|
28
|
+
}): this;
|
|
29
|
+
validate(logType: string, data: unknown): boolean;
|
|
30
|
+
get(logType: string): PayloadSchema | undefined;
|
|
31
|
+
}
|
|
32
|
+
export declare const errorBatchPayloadSchema: PayloadSchema;
|
|
33
|
+
export declare const httpRequestPayloadSchema: PayloadSchema;
|
|
34
|
+
export declare const defaultLogRegistry: LogSchemaRegistry;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const keywords = new Set(['type', 'properties', 'required', 'additionalProperties', 'items', 'enum', 'const', 'oneOf', 'minLength', 'maxLength', 'minimum', 'maximum', 'minItems', 'maxItems', 'pattern', 'description', '$id', '$schema', 'title']);
|
|
2
|
+
function canonical(value) {
|
|
3
|
+
if (Array.isArray(value))
|
|
4
|
+
return `[${value.map(canonical).join(',')}]`;
|
|
5
|
+
if (value && typeof value === 'object')
|
|
6
|
+
return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(',')}}`;
|
|
7
|
+
return JSON.stringify(value);
|
|
8
|
+
}
|
|
9
|
+
function checkSchema(schema, depth = 0) {
|
|
10
|
+
if (depth > 32 || !schema || typeof schema !== 'object' || Array.isArray(schema) || ![Object.prototype, null].includes(Object.getPrototypeOf(schema)))
|
|
11
|
+
throw new Error('Invalid payload schema');
|
|
12
|
+
for (const key of Object.keys(schema))
|
|
13
|
+
if (!keywords.has(key))
|
|
14
|
+
throw new Error(`Unsupported schema keyword: ${key}`);
|
|
15
|
+
if (schema.type !== undefined && !['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'].includes(schema.type))
|
|
16
|
+
throw new Error('Invalid schema type');
|
|
17
|
+
for (const key of ['minLength', 'maxLength', 'minItems', 'maxItems'])
|
|
18
|
+
if (schema[key] !== undefined && (!Number.isSafeInteger(schema[key]) || schema[key] < 0))
|
|
19
|
+
throw new Error(`Invalid schema ${key}`);
|
|
20
|
+
for (const key of ['minimum', 'maximum'])
|
|
21
|
+
if (schema[key] !== undefined && !Number.isFinite(schema[key]))
|
|
22
|
+
throw new Error(`Invalid schema ${key}`);
|
|
23
|
+
for (const key of ['description', 'pattern', '$id', '$schema', 'title'])
|
|
24
|
+
if (schema[key] !== undefined && typeof schema[key] !== 'string')
|
|
25
|
+
throw new Error(`Invalid schema ${key}`);
|
|
26
|
+
if (schema.required !== undefined && (!Array.isArray(schema.required) || !schema.required.every(x => typeof x === 'string')))
|
|
27
|
+
throw new Error('Invalid schema required');
|
|
28
|
+
if (schema.enum !== undefined && !Array.isArray(schema.enum))
|
|
29
|
+
throw new Error('Invalid schema enum');
|
|
30
|
+
const lossless = (value, level = 0) => level <= 32 && (value === null || typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' && Number.isFinite(value) || !!value && typeof value === 'object' && (Array.isArray(value) ? value.every(x => lossless(x, level + 1)) : [Object.prototype, null].includes(Object.getPrototypeOf(value)) && Object.values(value).every(x => lossless(x, level + 1))));
|
|
31
|
+
if (schema.enum && !lossless(schema.enum) || 'const' in schema && !lossless(schema.const))
|
|
32
|
+
throw new Error('Schema values must be bounded finite JSON');
|
|
33
|
+
if (schema.pattern)
|
|
34
|
+
new RegExp(schema.pattern);
|
|
35
|
+
if (schema.properties !== undefined && (!schema.properties || typeof schema.properties !== 'object' || Array.isArray(schema.properties)))
|
|
36
|
+
throw new Error('Invalid schema properties');
|
|
37
|
+
for (const child of Object.values(schema.properties ?? {}))
|
|
38
|
+
checkSchema(child, depth + 1);
|
|
39
|
+
if (schema.items !== undefined)
|
|
40
|
+
checkSchema(schema.items, depth + 1);
|
|
41
|
+
if (schema.additionalProperties !== undefined && typeof schema.additionalProperties !== 'boolean')
|
|
42
|
+
checkSchema(schema.additionalProperties, depth + 1);
|
|
43
|
+
if (schema.oneOf !== undefined && (!Array.isArray(schema.oneOf) || !schema.oneOf.length))
|
|
44
|
+
throw new Error('Invalid schema oneOf');
|
|
45
|
+
for (const child of schema.oneOf ?? [])
|
|
46
|
+
checkSchema(child, depth + 1);
|
|
47
|
+
}
|
|
48
|
+
function matches(value, schema) {
|
|
49
|
+
if (schema.oneOf && schema.oneOf.filter(s => matches(value, s)).length !== 1)
|
|
50
|
+
return false;
|
|
51
|
+
if ('const' in schema && canonical(value) !== canonical(schema.const))
|
|
52
|
+
return false;
|
|
53
|
+
if (schema.enum && !schema.enum.some(x => canonical(value) === canonical(x)))
|
|
54
|
+
return false;
|
|
55
|
+
if (schema.type) {
|
|
56
|
+
const valid = schema.type === 'null' ? value === null : schema.type === 'array' ? Array.isArray(value)
|
|
57
|
+
: schema.type === 'object' ? !!value && typeof value === 'object' && !Array.isArray(value)
|
|
58
|
+
: schema.type === 'integer' ? typeof value === 'number' && Number.isInteger(value)
|
|
59
|
+
: typeof value === schema.type;
|
|
60
|
+
if (!valid)
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
if (typeof value === 'string') {
|
|
64
|
+
if (schema.minLength !== undefined && value.length < schema.minLength || schema.maxLength !== undefined && value.length > schema.maxLength)
|
|
65
|
+
return false;
|
|
66
|
+
if (schema.pattern && !new RegExp(schema.pattern).test(value))
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
if (typeof value === 'number' && (!Number.isFinite(value) || schema.minimum !== undefined && value < schema.minimum || schema.maximum !== undefined && value > schema.maximum))
|
|
70
|
+
return false;
|
|
71
|
+
if (Array.isArray(value)) {
|
|
72
|
+
if (schema.minItems !== undefined && value.length < schema.minItems || schema.maxItems !== undefined && value.length > schema.maxItems)
|
|
73
|
+
return false;
|
|
74
|
+
if (schema.items && !value.every(x => matches(x, schema.items)))
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
else if (value && typeof value === 'object') {
|
|
78
|
+
const record = value;
|
|
79
|
+
if (schema.required?.some(key => !(key in record)))
|
|
80
|
+
return false;
|
|
81
|
+
for (const [key, child] of Object.entries(record)) {
|
|
82
|
+
const property = schema.properties && Object.hasOwn(schema.properties, key) ? schema.properties[key] : undefined;
|
|
83
|
+
if (property ? !matches(child, property) : schema.additionalProperties === false || typeof schema.additionalProperties === 'object' && !matches(child, schema.additionalProperties))
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
export class LogSchemaRegistry {
|
|
90
|
+
schemas = new Map();
|
|
91
|
+
register(logType, schema, options = {}) {
|
|
92
|
+
if (!/^[a-z][a-z0-9_-]*(?:\.[a-z][a-z0-9_-]*)+\.v[1-9][0-9]*$/.test(logType) || logType.length > 256)
|
|
93
|
+
throw new Error('Expected a versioned namespaced log_type');
|
|
94
|
+
checkSchema(schema);
|
|
95
|
+
const signature = canonical({ schema, optional: !!options.optional });
|
|
96
|
+
const prior = this.schemas.get(logType);
|
|
97
|
+
if (prior && prior.signature !== signature)
|
|
98
|
+
throw new Error(`Schema ${logType} is immutable; publish a new version`);
|
|
99
|
+
this.schemas.set(logType, { schema: JSON.parse(JSON.stringify(schema)), signature, optional: !!options.optional });
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
validate(logType, data) {
|
|
103
|
+
const registered = this.schemas.get(logType);
|
|
104
|
+
return !registered || data === undefined && registered.optional || matches(data, registered.schema);
|
|
105
|
+
}
|
|
106
|
+
get(logType) {
|
|
107
|
+
const schema = this.schemas.get(logType)?.schema;
|
|
108
|
+
return schema && JSON.parse(JSON.stringify(schema));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const sourceSchema = { type: 'object', properties: { path: { type: 'string' }, offset: { type: 'integer', minimum: 0 }, run: { oneOf: [{ type: 'string' }, { type: 'object', required: ['id', 'generation'], properties: { id: { type: 'string' }, generation: { type: 'integer', minimum: 0 } }, additionalProperties: false }] } }, additionalProperties: false };
|
|
112
|
+
export const errorBatchPayloadSchema = {
|
|
113
|
+
type: 'object', required: ['key', 'groups', 'count', 'range', 'dropped'], additionalProperties: true,
|
|
114
|
+
properties: {
|
|
115
|
+
key: { type: 'string' }, count: { type: 'integer', minimum: 1 }, dropped: { type: 'integer', minimum: 0 },
|
|
116
|
+
range: { type: 'object', required: ['first', 'last'], properties: { first: { type: 'string' }, last: { type: 'string' } }, additionalProperties: false },
|
|
117
|
+
groups: { type: 'array', minItems: 1, maxItems: 20, items: { type: 'object', required: ['fingerprint', 'count', 'sample', 'range'], additionalProperties: true, properties: {
|
|
118
|
+
fingerprint: { type: 'string' }, count: { type: 'integer', minimum: 1 }, sample: { type: 'object' },
|
|
119
|
+
range: { type: 'object', required: ['first', 'last'], properties: { first: { type: 'string' }, last: { type: 'string' } }, additionalProperties: false },
|
|
120
|
+
source: sourceSchema,
|
|
121
|
+
} } },
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
export const httpRequestPayloadSchema = {
|
|
125
|
+
type: 'object', required: ['method', 'path', 'status'], additionalProperties: true,
|
|
126
|
+
properties: { method: { type: 'string', minLength: 1, maxLength: 32 }, path: { type: 'string' }, status: { type: 'integer', minimum: 100, maximum: 599 }, duration_ms: { type: 'number', minimum: 0 } },
|
|
127
|
+
};
|
|
128
|
+
export const defaultLogRegistry = new LogSchemaRegistry()
|
|
129
|
+
.register('dsh.program.error.v1', { type: 'object', additionalProperties: true }, { optional: true })
|
|
130
|
+
.register('dsh.http.request.v1', httpRequestPayloadSchema)
|
|
131
|
+
.register('dsh.program.error-batch.v1', errorBatchPayloadSchema);
|
|
132
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/monitoring/schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { JsonValue } from '../types.js';
|
|
2
|
+
import { LogSchemaRegistry } from './schemas.js';
|
|
3
|
+
export type { JsonValue };
|
|
4
|
+
export declare const MAX_LOG_LINE_BYTES: number;
|
|
5
|
+
export declare const MAX_LOG_DEPTH = 32;
|
|
6
|
+
export declare const LOG_LEVELS: readonly ["DEBUG", "INFO", "WARNING", "ERROR"];
|
|
7
|
+
export type LogLevel = typeof LOG_LEVELS[number];
|
|
8
|
+
export interface StandardLogError {
|
|
9
|
+
name: string;
|
|
10
|
+
message: string;
|
|
11
|
+
stack?: string;
|
|
12
|
+
code?: string | number;
|
|
13
|
+
fingerprint?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Extensions are allowed, but must be bounded, finite JSON values. */
|
|
16
|
+
export interface StandardLogRecord {
|
|
17
|
+
timestamp: string;
|
|
18
|
+
level: LogLevel;
|
|
19
|
+
log_type: string;
|
|
20
|
+
message: string;
|
|
21
|
+
operation_id?: string;
|
|
22
|
+
event_id?: string;
|
|
23
|
+
error?: StandardLogError;
|
|
24
|
+
data?: JsonValue;
|
|
25
|
+
/** Advisory only: ERROR severity, not this flag, drives error monitoring. */
|
|
26
|
+
fatal?: boolean;
|
|
27
|
+
[extension: string]: unknown;
|
|
28
|
+
}
|
|
29
|
+
export declare const LOG_TYPE_PATTERN: RegExp;
|
|
30
|
+
export declare function isLogType(value: unknown): value is string;
|
|
31
|
+
/** Validate before serializing: JSON.stringify silently loses undefined/NaN/class values. */
|
|
32
|
+
export declare function isJson(value: unknown, depth?: number, seen?: Set<object>): value is JsonValue;
|
|
33
|
+
export declare function isStandardLogRecord(value: unknown, registry?: LogSchemaRegistry): value is StandardLogRecord;
|
|
34
|
+
/** Invalid/nonstandard/oversize lines are ignored, never interpreted as instructions. */
|
|
35
|
+
export declare function parseLogLine(line: string, registry?: LogSchemaRegistry): StandardLogRecord | undefined;
|
|
36
|
+
/** Stable across timestamps, stack positions, sources and stdout/file duplicates. */
|
|
37
|
+
export declare function errorFingerprint(record: StandardLogRecord): string;
|
|
38
|
+
/** Header objects are deliberately wholly redacted, rather than guessing safe headers. */
|
|
39
|
+
export declare function redact(value: JsonValue): JsonValue;
|
|
40
|
+
/** Useful to host stdout parsers too: bounded fragments, including oversize lines. */
|
|
41
|
+
export declare class JsonlDecoder {
|
|
42
|
+
private readonly onRecord;
|
|
43
|
+
private readonly registry;
|
|
44
|
+
private pending;
|
|
45
|
+
private skipping;
|
|
46
|
+
constructor(onRecord: (record: StandardLogRecord, endOffset: number) => void, registry?: LogSchemaRegistry);
|
|
47
|
+
push(chunk: Buffer | string, startOffset?: number): void;
|
|
48
|
+
reset(): void;
|
|
49
|
+
discardPartialLine(): void;
|
|
50
|
+
get pendingBytes(): number;
|
|
51
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { defaultLogRegistry } from './schemas.js';
|
|
3
|
+
export const MAX_LOG_LINE_BYTES = 64 * 1024;
|
|
4
|
+
export const MAX_LOG_DEPTH = 32;
|
|
5
|
+
export const LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR'];
|
|
6
|
+
export const LOG_TYPE_PATTERN = /^[a-z][a-z0-9_-]*(?:\.[a-z][a-z0-9_-]*)+\.v[1-9][0-9]*$/;
|
|
7
|
+
export function isLogType(value) {
|
|
8
|
+
return typeof value === 'string' && value.length <= 256 && LOG_TYPE_PATTERN.test(value);
|
|
9
|
+
}
|
|
10
|
+
/** Validate before serializing: JSON.stringify silently loses undefined/NaN/class values. */
|
|
11
|
+
export function isJson(value, depth = 0, seen = new Set()) {
|
|
12
|
+
if (depth > MAX_LOG_DEPTH)
|
|
13
|
+
return false;
|
|
14
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
15
|
+
return true;
|
|
16
|
+
if (typeof value === 'number')
|
|
17
|
+
return Number.isFinite(value);
|
|
18
|
+
if (typeof value !== 'object' || seen.has(value))
|
|
19
|
+
return false;
|
|
20
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
|
|
21
|
+
return false;
|
|
22
|
+
seen.add(value);
|
|
23
|
+
const valid = Array.isArray(value)
|
|
24
|
+
? Array.from({ length: value.length }, (_, i) => i in value && isJson(value[i], depth + 1, seen)).every(Boolean)
|
|
25
|
+
: Object.values(value).every(child => isJson(child, depth + 1, seen));
|
|
26
|
+
seen.delete(value);
|
|
27
|
+
return valid;
|
|
28
|
+
}
|
|
29
|
+
function object(value) {
|
|
30
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
function optionalString(o, key) {
|
|
33
|
+
return !(key in o) || typeof o[key] === 'string';
|
|
34
|
+
}
|
|
35
|
+
function validTimestamp(value) {
|
|
36
|
+
const match = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.\d{1,9})?(?:Z|([+-])(\d\d):(\d\d))$/.exec(value);
|
|
37
|
+
if (!match || !Number.isFinite(Date.parse(value)))
|
|
38
|
+
return false;
|
|
39
|
+
const [, year, month, day, hour, minute, second, , zoneHour, zoneMinute] = match;
|
|
40
|
+
const y = Number(year), m = Number(month), d = Number(day);
|
|
41
|
+
const leap = y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0);
|
|
42
|
+
const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
43
|
+
return m >= 1 && m <= 12 && d >= 1 && d <= days[m - 1] && Number(hour) < 24 && Number(minute) < 60 && Number(second) < 60 && (!zoneHour || Number(zoneHour) < 24 && Number(zoneMinute) < 60);
|
|
44
|
+
}
|
|
45
|
+
export function isStandardLogRecord(value, registry = defaultLogRegistry) {
|
|
46
|
+
if (!isJson(value) || !object(value))
|
|
47
|
+
return false;
|
|
48
|
+
if (typeof value.timestamp !== 'string' || !validTimestamp(value.timestamp))
|
|
49
|
+
return false;
|
|
50
|
+
if (!LOG_LEVELS.includes(value.level) || !isLogType(value.log_type) || typeof value.message !== 'string')
|
|
51
|
+
return false;
|
|
52
|
+
if (!optionalString(value, 'operation_id') || !optionalString(value, 'event_id'))
|
|
53
|
+
return false;
|
|
54
|
+
if ('fatal' in value && typeof value.fatal !== 'boolean')
|
|
55
|
+
return false;
|
|
56
|
+
if ('error' in value) {
|
|
57
|
+
const e = value.error;
|
|
58
|
+
if (!object(e) || typeof e.name !== 'string' || typeof e.message !== 'string' || !optionalString(e, 'stack') || !optionalString(e, 'fingerprint'))
|
|
59
|
+
return false;
|
|
60
|
+
if ('code' in e && typeof e.code !== 'string' && typeof e.code !== 'number')
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return registry.validate(value.log_type, value.data);
|
|
64
|
+
}
|
|
65
|
+
/** Invalid/nonstandard/oversize lines are ignored, never interpreted as instructions. */
|
|
66
|
+
export function parseLogLine(line, registry = defaultLogRegistry) {
|
|
67
|
+
if (typeof line !== 'string' || Buffer.byteLength(line, 'utf8') > MAX_LOG_LINE_BYTES)
|
|
68
|
+
return undefined;
|
|
69
|
+
try {
|
|
70
|
+
const value = JSON.parse(line);
|
|
71
|
+
return isStandardLogRecord(value, registry) ? value : undefined;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Stable across timestamps, stack positions, sources and stdout/file duplicates. */
|
|
78
|
+
export function errorFingerprint(record) {
|
|
79
|
+
return createHash('sha256').update(JSON.stringify([
|
|
80
|
+
record.log_type, record.message, record.error?.name ?? null,
|
|
81
|
+
record.error?.message ?? null, record.error?.code ?? null,
|
|
82
|
+
])).digest('hex');
|
|
83
|
+
}
|
|
84
|
+
const SECRET_KEYS = new Set(['authorization', 'proxyauthorization', 'cookie', 'setcookie', 'password', 'passwd', 'passphrase', 'secret', 'clientsecret', 'token', 'accesstoken', 'refreshtoken', 'idtoken', 'apikey', 'xapikey', 'privatekey', 'credentials', 'headers']);
|
|
85
|
+
/** Header objects are deliberately wholly redacted, rather than guessing safe headers. */
|
|
86
|
+
export function redact(value) {
|
|
87
|
+
if (Array.isArray(value))
|
|
88
|
+
return value.map(redact);
|
|
89
|
+
if (value && typeof value === 'object') {
|
|
90
|
+
const result = Object.create(null);
|
|
91
|
+
for (const [key, child] of Object.entries(value)) {
|
|
92
|
+
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
93
|
+
result[key] = SECRET_KEYS.has(normalized) || /(?:password|secret|token|apikey)$/.test(normalized) ? '[REDACTED]' : redact(child);
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
/** Useful to host stdout parsers too: bounded fragments, including oversize lines. */
|
|
100
|
+
export class JsonlDecoder {
|
|
101
|
+
onRecord;
|
|
102
|
+
registry;
|
|
103
|
+
pending = Buffer.alloc(0);
|
|
104
|
+
skipping = false;
|
|
105
|
+
constructor(onRecord, registry = defaultLogRegistry) {
|
|
106
|
+
this.onRecord = onRecord;
|
|
107
|
+
this.registry = registry;
|
|
108
|
+
}
|
|
109
|
+
push(chunk, startOffset = 0) {
|
|
110
|
+
const bytes = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
|
|
111
|
+
let start = 0;
|
|
112
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
113
|
+
if (bytes[i] !== 10)
|
|
114
|
+
continue;
|
|
115
|
+
if (!this.skipping) {
|
|
116
|
+
const fragment = bytes.subarray(start, i);
|
|
117
|
+
if (this.pending.length + fragment.length <= MAX_LOG_LINE_BYTES) {
|
|
118
|
+
const line = this.pending.length ? Buffer.concat([this.pending, fragment]) : fragment;
|
|
119
|
+
const record = parseLogLine(line.toString('utf8'), this.registry);
|
|
120
|
+
if (record)
|
|
121
|
+
this.onRecord(record, startOffset + i + 1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this.pending = Buffer.alloc(0);
|
|
125
|
+
this.skipping = false;
|
|
126
|
+
start = i + 1;
|
|
127
|
+
}
|
|
128
|
+
const rest = bytes.subarray(start);
|
|
129
|
+
if (!this.skipping && this.pending.length + rest.length <= MAX_LOG_LINE_BYTES)
|
|
130
|
+
this.pending = Buffer.concat([this.pending, rest]);
|
|
131
|
+
else {
|
|
132
|
+
this.pending = Buffer.alloc(0);
|
|
133
|
+
this.skipping = true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
reset() { this.pending = Buffer.alloc(0); this.skipping = false; }
|
|
137
|
+
discardPartialLine() { this.pending = Buffer.alloc(0); this.skipping = true; }
|
|
138
|
+
get pendingBytes() { return this.pending.length; }
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=standard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standard.js","sourceRoot":"","sources":["../../src/monitoring/standard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type StandardLogRecord } from './standard.js';
|
|
2
|
+
import type { LogPointer } from './error-buffer.js';
|
|
3
|
+
export interface LogTailerOptions {
|
|
4
|
+
logsPath: string;
|
|
5
|
+
onRecord: (record: StandardLogRecord, pointer: LogPointer) => unknown | Promise<unknown>;
|
|
6
|
+
/** Existing history is skipped by default. Newly created files always start at zero. */
|
|
7
|
+
readExisting?: boolean;
|
|
8
|
+
pollMs?: number;
|
|
9
|
+
run?: LogPointer['run'];
|
|
10
|
+
/** Optional durable completed-line cursor; ErrorBuffer event IDs dedup replay. */
|
|
11
|
+
cursorPath?: string;
|
|
12
|
+
onError?: (error: unknown) => void;
|
|
13
|
+
}
|
|
14
|
+
/** Bounded file reads, inode-aware rotation, truncation and partial-line handling. */
|
|
15
|
+
export declare class LogTailer {
|
|
16
|
+
private readonly options;
|
|
17
|
+
readonly ready: Promise<void>;
|
|
18
|
+
private path;
|
|
19
|
+
private handle?;
|
|
20
|
+
private identity?;
|
|
21
|
+
private offset;
|
|
22
|
+
private committed;
|
|
23
|
+
private cursor?;
|
|
24
|
+
private first;
|
|
25
|
+
private closed;
|
|
26
|
+
private timer?;
|
|
27
|
+
private work;
|
|
28
|
+
private decoder;
|
|
29
|
+
private records;
|
|
30
|
+
constructor(options: LogTailerOptions);
|
|
31
|
+
private report;
|
|
32
|
+
private start;
|
|
33
|
+
/** Exposed for deterministic shutdown/tests; overlapping polls serialize. */
|
|
34
|
+
poll(): Promise<void>;
|
|
35
|
+
private attach;
|
|
36
|
+
private readAvailable;
|
|
37
|
+
private persistCursor;
|
|
38
|
+
private tick;
|
|
39
|
+
close(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export { LogTailer as JsonlMonitor };
|