@plainconceptsplatform/loop-task 2.6.0 → 2.8.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/LICENSE +1 -1
- package/README.md +31 -31
- package/dist/app/App.js +5 -1
- package/dist/app/Splash.js +19 -0
- package/dist/client/ipc.js +8 -1
- package/dist/client/project-commands.js +1 -1
- package/dist/core/command/command-runner.js +104 -7
- package/dist/core/command/stdout-capture-transform.js +57 -7
- package/dist/core/context/context-parser.js +81 -1
- package/dist/core/context/log-context.js +36 -1
- package/dist/core/context/opencode-json-parser.js +126 -0
- package/dist/core/context/template.js +18 -2
- package/dist/core/context/types.js +1 -0
- package/dist/core/loop/chain-executor.js +5 -1
- package/dist/core/loop/run-executor.js +6 -1
- package/dist/daemon/http/openapi.js +2 -2
- package/dist/daemon/index.js +15 -10
- package/dist/daemon/managers/project-manager.js +1 -1
- package/dist/daemon/telemetry/agent-integrations/claude-code-integration.js +6 -0
- package/dist/daemon/telemetry/agent-integrations/opencode-integration.js +176 -6
- package/dist/daemon/telemetry/agent-serve-manager.js +78 -0
- package/dist/daemon/telemetry/noop-telemetry-adapter.js +1 -0
- package/dist/daemon/telemetry/open-telemetry-adapter.js +101 -22
- package/dist/entry.js +0 -0
- package/dist/shared/i18n/en.json +1 -1
- package/package.json +118 -118
|
@@ -11,6 +11,10 @@ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
|
11
11
|
import { OTLPMetricExporter as OTLPMetricExporterGrpc } from "@opentelemetry/exporter-metrics-otlp-grpc";
|
|
12
12
|
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
13
13
|
import { trace, context, propagation, metrics, SpanStatusCode, SpanKind } from "@opentelemetry/api";
|
|
14
|
+
import { logs } from "@opentelemetry/api-logs";
|
|
15
|
+
import { LoggerProvider, SimpleLogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
16
|
+
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
17
|
+
import { OTLPLogExporter as OTLPLogExporterGrpc } from "@opentelemetry/exporter-logs-otlp-grpc";
|
|
14
18
|
import { daemonLog } from "../daemon-log.js";
|
|
15
19
|
class OtelSpan {
|
|
16
20
|
constructor(span, ctx, onEnd) {
|
|
@@ -79,9 +83,11 @@ export class OpenTelemetryAdapter {
|
|
|
79
83
|
constructor(settings) {
|
|
80
84
|
this.sdk = null;
|
|
81
85
|
this.tracerProvider = null;
|
|
86
|
+
this.loggerProvider = null;
|
|
82
87
|
this.settings = settings;
|
|
83
88
|
this.tracer = trace.getTracer("loop-task");
|
|
84
89
|
this.meter = metrics.getMeter("loop-task");
|
|
90
|
+
this.logger = logs.getLogger("loop-task");
|
|
85
91
|
this.status = {
|
|
86
92
|
enabled: settings.telemetryEnabled,
|
|
87
93
|
exporterConfigured: !!settings.telemetryEndpoint,
|
|
@@ -93,7 +99,12 @@ export class OpenTelemetryAdapter {
|
|
|
93
99
|
captureCommandOutput: settings.telemetryCaptureCommandOutput,
|
|
94
100
|
exporterState: this.resolveExporterState(settings),
|
|
95
101
|
};
|
|
96
|
-
|
|
102
|
+
if (settings.telemetryEnabled && settings.telemetryEndpoint) {
|
|
103
|
+
this.initializeSdk(settings);
|
|
104
|
+
}
|
|
105
|
+
// Initialize metric instruments AFTER SDK startup so they bind to the
|
|
106
|
+
// real MeterProvider, not the default no-op one. When the SDK is not
|
|
107
|
+
// initialized, these still work — they bind to the API-level no-op meter.
|
|
97
108
|
this.runCounter = this.meter.createCounter(METRIC_NAMES.RUNS);
|
|
98
109
|
this.runDurationHistogram = this.meter.createHistogram(METRIC_NAMES.RUN_DURATION);
|
|
99
110
|
this.taskCounter = this.meter.createCounter(METRIC_NAMES.TASKS);
|
|
@@ -109,9 +120,6 @@ export class OpenTelemetryAdapter {
|
|
|
109
120
|
this.agentCacheWriteTokensCounter = this.meter.createCounter(METRIC_NAMES.AGENT_CACHE_WRITE_TOKENS);
|
|
110
121
|
this.agentCostCounter = this.meter.createCounter(METRIC_NAMES.AGENT_COST);
|
|
111
122
|
this.failureCounter = this.meter.createCounter(METRIC_NAMES.FAILURES);
|
|
112
|
-
if (settings.telemetryEnabled && settings.telemetryEndpoint) {
|
|
113
|
-
this.initializeSdk(settings);
|
|
114
|
-
}
|
|
115
123
|
}
|
|
116
124
|
resolveExporterState(settings) {
|
|
117
125
|
if (!settings.telemetryEnabled)
|
|
@@ -162,7 +170,24 @@ export class OpenTelemetryAdapter {
|
|
|
162
170
|
instrumentations: [],
|
|
163
171
|
});
|
|
164
172
|
this.sdk.start();
|
|
173
|
+
// Re-obtain tracer and meter from the global API after SDK startup.
|
|
174
|
+
// The API now resolves to the real providers registered by NodeSDK.
|
|
165
175
|
this.tracer = trace.getTracer(settings.telemetryServiceName);
|
|
176
|
+
this.meter = metrics.getMeter(settings.telemetryServiceName);
|
|
177
|
+
// Initialize OTLP log exporter
|
|
178
|
+
const logsUrl = endpoint.endsWith("/v1/logs")
|
|
179
|
+
? endpoint
|
|
180
|
+
: `${endpoint}/v1/logs`;
|
|
181
|
+
const logExporter = isGrpc
|
|
182
|
+
? new OTLPLogExporterGrpc({ url: settings.telemetryEndpoint })
|
|
183
|
+
: new OTLPLogExporter({ url: logsUrl, headers });
|
|
184
|
+
const loggerProvider = new LoggerProvider({
|
|
185
|
+
resource,
|
|
186
|
+
processors: [new SimpleLogRecordProcessor({ exporter: logExporter })],
|
|
187
|
+
});
|
|
188
|
+
logs.setGlobalLoggerProvider(loggerProvider);
|
|
189
|
+
this.loggerProvider = loggerProvider;
|
|
190
|
+
this.logger = logs.getLogger(settings.telemetryServiceName);
|
|
166
191
|
this.status.exporterState = "configured";
|
|
167
192
|
daemonLog(`telemetry: SDK initialized, endpoint=${settings.telemetryEndpoint}`);
|
|
168
193
|
}
|
|
@@ -197,6 +222,24 @@ export class OpenTelemetryAdapter {
|
|
|
197
222
|
return "http/protobuf";
|
|
198
223
|
return this.settings.telemetryProtocol;
|
|
199
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Check if any agent serve sidecar is alive.
|
|
227
|
+
* When serve is alive, static OTEL config lives in the serve process
|
|
228
|
+
* and we skip per-task injection.
|
|
229
|
+
*/
|
|
230
|
+
checkServeAlive() {
|
|
231
|
+
try {
|
|
232
|
+
const integrations = getAgentIntegrations();
|
|
233
|
+
for (const integration of integrations) {
|
|
234
|
+
if (integration.isServeAlive?.())
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
200
243
|
startLoop(input) {
|
|
201
244
|
const span = this.tracer.startSpan(SPAN_NAMES.LOOP_RUN, { kind: SpanKind.SERVER });
|
|
202
245
|
span.setAttributes({
|
|
@@ -324,6 +367,20 @@ export class OpenTelemetryAdapter {
|
|
|
324
367
|
activeSpan.setAttribute("gen_ai.request.model", input.model);
|
|
325
368
|
}
|
|
326
369
|
}
|
|
370
|
+
logEvent(level, message, attributes) {
|
|
371
|
+
try {
|
|
372
|
+
const record = this.logger.emit({
|
|
373
|
+
body: message,
|
|
374
|
+
severityText: level,
|
|
375
|
+
attributes: attributes ?? {},
|
|
376
|
+
});
|
|
377
|
+
// Ensure the log record is flushed in a timely manner
|
|
378
|
+
void record;
|
|
379
|
+
}
|
|
380
|
+
catch (err) {
|
|
381
|
+
daemonLog(`telemetry: log emit failed: ${String(err)}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
327
384
|
prepareChildProcess(invocation, childContext, integrationOverride) {
|
|
328
385
|
const env = {};
|
|
329
386
|
const endpoint = this.resolveEndpoint();
|
|
@@ -337,25 +394,34 @@ export class OpenTelemetryAdapter {
|
|
|
337
394
|
env.TRACESTATE = childContext.traceState;
|
|
338
395
|
}
|
|
339
396
|
}
|
|
340
|
-
|
|
341
|
-
env
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
env.
|
|
397
|
+
// Check if an agent serve sidecar is alive — if so, static OTEL config
|
|
398
|
+
// lives in the serve process env and we skip per-task injection.
|
|
399
|
+
const serveAlive = this.checkServeAlive();
|
|
400
|
+
if (!serveAlive) {
|
|
401
|
+
env.OTEL_EXPORTER_OTLP_ENDPOINT = endpoint;
|
|
402
|
+
env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = endpoint;
|
|
403
|
+
env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = endpoint;
|
|
404
|
+
env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = endpoint;
|
|
405
|
+
env.OTEL_EXPORTER_OTLP_PROTOCOL = protocol;
|
|
406
|
+
env.OTEL_TRACES_EXPORTER = "otlp";
|
|
407
|
+
env.OTEL_METRICS_EXPORTER = "otlp";
|
|
408
|
+
env.OTEL_LOGS_EXPORTER = "otlp";
|
|
409
|
+
const authHeaders = process.env.OTEL_EXPORTER_OTLP_HEADERS
|
|
410
|
+
?? process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS;
|
|
411
|
+
if (authHeaders) {
|
|
412
|
+
env.OTEL_EXPORTER_OTLP_HEADERS = authHeaders;
|
|
413
|
+
}
|
|
414
|
+
const correlationAttrs = {
|
|
415
|
+
[CORRELATION_KEYS.RUN_ID]: childContext.runId,
|
|
416
|
+
[CORRELATION_KEYS.LOOP_ID]: childContext.loopId,
|
|
417
|
+
};
|
|
418
|
+
if (childContext.taskId)
|
|
419
|
+
correlationAttrs[CORRELATION_KEYS.TASK_ID] = childContext.taskId;
|
|
420
|
+
if (childContext.projectId)
|
|
421
|
+
correlationAttrs[CORRELATION_KEYS.PROJECT_ID] = childContext.projectId;
|
|
422
|
+
const mergedResourceAttrs = this.mergeResourceAttributes(process.env.OTEL_RESOURCE_ATTRIBUTES, correlationAttrs);
|
|
423
|
+
env.OTEL_RESOURCE_ATTRIBUTES = mergedResourceAttrs;
|
|
348
424
|
}
|
|
349
|
-
const correlationAttrs = {
|
|
350
|
-
[CORRELATION_KEYS.RUN_ID]: childContext.runId,
|
|
351
|
-
[CORRELATION_KEYS.LOOP_ID]: childContext.loopId,
|
|
352
|
-
};
|
|
353
|
-
if (childContext.taskId)
|
|
354
|
-
correlationAttrs[CORRELATION_KEYS.TASK_ID] = childContext.taskId;
|
|
355
|
-
if (childContext.projectId)
|
|
356
|
-
correlationAttrs[CORRELATION_KEYS.PROJECT_ID] = childContext.projectId;
|
|
357
|
-
const mergedResourceAttrs = this.mergeResourceAttributes(process.env.OTEL_RESOURCE_ATTRIBUTES, correlationAttrs);
|
|
358
|
-
env.OTEL_RESOURCE_ATTRIBUTES = mergedResourceAttrs;
|
|
359
425
|
// Apply agent-specific integrations when auto-instrumentation is enabled
|
|
360
426
|
let integrationId;
|
|
361
427
|
if (this.settings.telemetryAutoInstrumentAgents || integrationOverride) {
|
|
@@ -419,6 +485,9 @@ export class OpenTelemetryAdapter {
|
|
|
419
485
|
if (this.tracerProvider) {
|
|
420
486
|
flushes.push(this.tracerProvider.forceFlush());
|
|
421
487
|
}
|
|
488
|
+
if (this.loggerProvider) {
|
|
489
|
+
flushes.push(this.loggerProvider.forceFlush());
|
|
490
|
+
}
|
|
422
491
|
const sdkInternals = this.sdk;
|
|
423
492
|
if (typeof sdkInternals._meterProvider?.forceFlush === "function") {
|
|
424
493
|
flushes.push(sdkInternals._meterProvider.forceFlush());
|
|
@@ -450,6 +519,16 @@ export class OpenTelemetryAdapter {
|
|
|
450
519
|
}
|
|
451
520
|
this.tracerProvider = null;
|
|
452
521
|
}
|
|
522
|
+
if (this.loggerProvider) {
|
|
523
|
+
try {
|
|
524
|
+
await this.loggerProvider.forceFlush();
|
|
525
|
+
await this.loggerProvider.shutdown();
|
|
526
|
+
}
|
|
527
|
+
catch {
|
|
528
|
+
// best effort
|
|
529
|
+
}
|
|
530
|
+
this.loggerProvider = null;
|
|
531
|
+
}
|
|
453
532
|
if (!this.sdk)
|
|
454
533
|
return;
|
|
455
534
|
try {
|
package/dist/entry.js
CHANGED
|
File without changes
|
package/dist/shared/i18n/en.json
CHANGED
|
@@ -460,7 +460,7 @@
|
|
|
460
460
|
"project.wizard.directoryPrompt": "Working directory? (optional)",
|
|
461
461
|
"project.wizard.directoryHint": "Default directory for loops in this project. Leave blank to inherit",
|
|
462
462
|
"project.wizard.githubSourcePrompt": "GitHub Source? (optional)",
|
|
463
|
-
"project.wizard.githubSourceHint": "Repository in owner/repo format, e.g.
|
|
463
|
+
"project.wizard.githubSourceHint": "Repository in owner/repo format, e.g. PlainConceptsPlatform/loop-task",
|
|
464
464
|
"project.error.updateFailed": "Failed to update project",
|
|
465
465
|
"project.error.deleteFailed": "Failed to delete project",
|
|
466
466
|
"project.toastCreated": "Project \"{name}\" created",
|
package/package.json
CHANGED
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@plainconceptsplatform/loop-task",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Loop engineering toolkit. Run any command on a cadence, in the background, managed from a terminal board. Schedule tests, builds, syncs, or agent prompts.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"loop-task": "dist/entry.js"
|
|
8
|
-
},
|
|
9
|
-
"main": "dist/entry.js",
|
|
10
|
-
"files": [
|
|
11
|
-
"dist",
|
|
12
|
-
"README.md",
|
|
13
|
-
"LICENSE"
|
|
14
|
-
],
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@plainconceptsplatform/loop-task",
|
|
3
|
+
"version": "2.8.0",
|
|
4
|
+
"description": "Loop engineering toolkit. Run any command on a cadence, in the background, managed from a terminal board. Schedule tests, builds, syncs, or agent prompts.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"loop-task": "dist/entry.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/entry.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"cli",
|
|
17
|
+
"loop",
|
|
18
|
+
"loop-engineering",
|
|
19
|
+
"repeat",
|
|
20
|
+
"interval",
|
|
21
|
+
"schedule",
|
|
22
|
+
"timer",
|
|
23
|
+
"cron",
|
|
24
|
+
"automation",
|
|
25
|
+
"automations",
|
|
26
|
+
"devops",
|
|
27
|
+
"agent",
|
|
28
|
+
"ai-agent",
|
|
29
|
+
"coding-agent",
|
|
30
|
+
"agent-automation",
|
|
31
|
+
"claude-code",
|
|
32
|
+
"codex",
|
|
33
|
+
"opencode",
|
|
34
|
+
"background-tasks",
|
|
35
|
+
"scheduler"
|
|
36
|
+
],
|
|
37
|
+
"author": "Plain Concepts",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/PlainConceptsPlatform/loop-task.git"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/PlainConceptsPlatform/loop-task",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/PlainConceptsPlatform/loop-task/issues"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public",
|
|
49
|
+
"registry": "https://registry.npmjs.org/"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20.0.0"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
56
|
+
"@opentelemetry/api": "^1.9.1",
|
|
57
|
+
"@opentelemetry/api-logs": "^0.221.0",
|
|
58
|
+
"@opentelemetry/exporter-logs-otlp-grpc": "^0.221.0",
|
|
59
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.221.0",
|
|
60
|
+
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.221.0",
|
|
61
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.221.0",
|
|
62
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.221.0",
|
|
63
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.221.0",
|
|
64
|
+
"@opentelemetry/resources": "^2.10.0",
|
|
65
|
+
"@opentelemetry/sdk-logs": "^0.221.0",
|
|
66
|
+
"@opentelemetry/sdk-metrics": "^2.10.0",
|
|
67
|
+
"@opentelemetry/sdk-node": "^0.221.0",
|
|
68
|
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
69
|
+
"@opentelemetry/sdk-trace-node": "^2.10.0",
|
|
70
|
+
"@opentelemetry/semantic-conventions": "^1.43.0",
|
|
71
|
+
"commander": "^13.1.0",
|
|
72
|
+
"execa": "^9.6.0",
|
|
73
|
+
"ink": "^7.1.0",
|
|
74
|
+
"ink-combobox": "^0.2.0",
|
|
75
|
+
"ink-scroll-list": "^0.4.1",
|
|
76
|
+
"ink-select-input": "^6.2.0",
|
|
77
|
+
"ink-spinner": "^5.0.0",
|
|
78
|
+
"ink-text-input": "^6.0.0",
|
|
79
|
+
"inversify": "^8.1.1",
|
|
80
|
+
"inversify-hooks": "^4.0.0",
|
|
81
|
+
"js-yaml": "^5.2.2",
|
|
82
|
+
"ms": "^2.1.3",
|
|
83
|
+
"react": "^19.2.7",
|
|
84
|
+
"yaml": "^2.9.0",
|
|
85
|
+
"zod": "^4.4.3"
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@types/js-yaml": "^4.0.9",
|
|
89
|
+
"@types/ms": "^2.1.0",
|
|
90
|
+
"@types/node": "^22.15.0",
|
|
91
|
+
"@types/react": "^19.2.17",
|
|
92
|
+
"@vitest/coverage-v8": "^3.1.0",
|
|
93
|
+
"eslint": "^9.25.0",
|
|
94
|
+
"husky": "^9.1.7",
|
|
95
|
+
"ink-testing-library": "^4.0.0",
|
|
96
|
+
"tsx": "^4.19.0",
|
|
97
|
+
"typescript": "^5.8.0",
|
|
98
|
+
"typescript-eslint": "^8.30.0",
|
|
99
|
+
"vitest": "^3.1.0"
|
|
100
|
+
},
|
|
101
|
+
"scripts": {
|
|
102
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && node -e \"require('fs').copyFileSync('src/entry.js','dist/entry.js'); require('fs').copyFileSync('src/esm-loader.js','dist/esm-loader.js')\"",
|
|
103
|
+
"start": "node dist/entry.js",
|
|
104
|
+
"dev": "tsx src/cli.ts",
|
|
105
|
+
"dev:watch": "tsx --watch src/cli.ts",
|
|
106
|
+
"board": "node dist/entry.js",
|
|
107
|
+
"test": "vitest run --exclude '**/background-cli.test.ts'",
|
|
108
|
+
"test:all": "vitest run",
|
|
109
|
+
"test:watch": "vitest",
|
|
110
|
+
"test:coverage": "vitest run --coverage --exclude '**/background-cli.test.ts'",
|
|
111
|
+
"lint": "eslint src/ tests/",
|
|
112
|
+
"typecheck": "tsc --noEmit",
|
|
113
|
+
"release:dry": "npm publish --dry-run --access public",
|
|
114
|
+
"release": "npm publish --access public",
|
|
115
|
+
"visual-evidence": "tsx src/visual-evidence/cli.ts",
|
|
116
|
+
"visual-evidence:publish": "tsx src/visual-evidence/publish.ts",
|
|
117
|
+
"skills:mark-internal": "node scripts/mark-agent-skills-internal.mjs"
|
|
118
|
+
}
|
|
119
119
|
}
|