@aiwg/cli 2026.10.4 → 2026.10.6
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/agentic/code/addons/composition-engine/lib/runtime.mjs +1401 -0
- package/agentic/code/addons/composition-engine/lib/validator.mjs +513 -0
- package/agentic/code/addons/composition-engine/schemas/flow-graph.schema.json +372 -0
- package/agentic/code/providers/model-capabilities.v1.json +74 -50
- package/bin/aiwg.mjs +3 -1
- package/dist/src/artifacts/browser-export.js +1 -0
- package/dist/src/artifacts/citation-parser.js +8 -1
- package/dist/src/artifacts/cli.js +72 -9
- package/dist/src/artifacts/fortemi-core-query-adapter.js +2 -0
- package/dist/src/artifacts/fortemi-core-sync.js +26 -8
- package/dist/src/artifacts/graph-query.js +18 -8
- package/dist/src/artifacts/index-adapters.js +339 -0
- package/dist/src/artifacts/index-builder.js +146 -16
- package/dist/src/artifacts/index-files.js +15 -4
- package/dist/src/artifacts/index-preparation.js +91 -26
- package/dist/src/artifacts/index-reader.js +44 -0
- package/dist/src/artifacts/index-refresh.js +130 -56
- package/dist/src/artifacts/index-status.js +20 -5
- package/dist/src/artifacts/index-worker.mjs +9 -7
- package/dist/src/artifacts/memory-maintenance.js +503 -0
- package/dist/src/artifacts/prebuilt-relations.js +3 -1
- package/dist/src/artifacts/query-engine.js +263 -108
- package/dist/src/artifacts/relations-builder.js +2 -2
- package/dist/src/artifacts/source-graph.js +2 -2
- package/dist/src/artifacts/types.js +9 -1
- package/dist/src/cli/handlers/decision.js +19 -1
- package/dist/src/cli/handlers/guided-setup.js +470 -0
- package/dist/src/cli/handlers/help.js +2 -2
- package/dist/src/cli/handlers/housekeeper.js +1110 -0
- package/dist/src/cli/handlers/index.js +4 -2
- package/dist/src/cli/handlers/init.js +41 -6
- package/dist/src/cli/handlers/local-executor.js +5 -3
- package/dist/src/cli/handlers/mc.js +509 -53
- package/dist/src/cli/handlers/models.js +32 -2
- package/dist/src/cli/handlers/ralph-launcher.js +76 -4
- package/dist/src/cli/handlers/rules.js +1 -1
- package/dist/src/cli/handlers/script-runner.js +73 -2
- package/dist/src/cli/handlers/serve.js +5 -3
- package/dist/src/cli/handlers/sessions.js +40 -6
- package/dist/src/cli/handlers/setup.js +428 -1
- package/dist/src/cli/handlers/skill-lint.js +1 -1
- package/dist/src/cli/handlers/subcommands.js +118 -8
- package/dist/src/cli/handlers/use.js +279 -93
- package/dist/src/cli/handlers/workspace.js +3 -1
- package/dist/src/cli/prompt-utils.js +8 -0
- package/dist/src/cli/router.js +16 -1
- package/dist/src/config/aiwg-config.js +42 -0
- package/dist/src/config/cli.js +7 -3
- package/dist/src/config/decision-config.js +14 -1
- package/dist/src/config/native-sandbox-warnings.js +25 -0
- package/dist/src/contributors/validation.js +6 -5
- package/dist/src/decision/admission.js +7 -3
- package/dist/src/decision/benchmark.js +469 -0
- package/dist/src/decision/ledger.js +22 -3
- package/dist/src/decision/pricing.js +147 -0
- package/dist/src/decision/qualification/gate-evidence.js +18 -15
- package/dist/src/decision/qualification/load-staged.js +539 -0
- package/dist/src/decision/qualification/load.js +109 -33
- package/dist/src/decision/qualification/runner.js +5 -2
- package/dist/src/decision/review/service.js +6 -4
- package/dist/src/decision/review/validate.js +23 -2
- package/dist/src/decision/savings.js +8 -3
- package/dist/src/discovery/index.js +492 -0
- package/dist/src/discovery/interview.js +233 -0
- package/dist/src/discovery/plan-apply.js +571 -0
- package/dist/src/discovery/plan-store.js +171 -0
- package/dist/src/discovery/plan-types.js +2 -0
- package/dist/src/discovery/plan-validation.js +139 -0
- package/dist/src/discovery/types.js +2 -0
- package/dist/src/extensions/commands/definitions.js +49 -9
- package/dist/src/extensions/manifest.js +71 -44
- package/dist/src/extensions/project-local-discovery.js +1 -1
- package/dist/src/extensions/project-quickref.js +18 -17
- package/dist/src/extensions/validation.js +32 -29
- package/dist/src/housekeeper/daemon-config.js +148 -0
- package/dist/src/housekeeper/ipc.js +84 -0
- package/dist/src/housekeeper/lifecycle.js +148 -0
- package/dist/src/housekeeper/platform.js +35 -0
- package/dist/src/housekeeper/status.js +70 -0
- package/dist/src/housekeeper/units.js +114 -0
- package/dist/src/jobs/flow.js +22 -21
- package/dist/src/lint/rule-activation.js +20 -5
- package/dist/src/lint/runner.js +1 -1
- package/dist/src/mcp/cli.mjs +5 -6
- package/dist/src/mcp/config-file.mjs +6 -2
- package/dist/src/mcp/config-layers.mjs +23 -7
- package/dist/src/mcp/profiles.js +18 -31
- package/dist/src/mcp/profiles.mjs +18 -32
- package/dist/src/mcp/registry.js +7 -27
- package/dist/src/mcp/registry.mjs +7 -28
- package/dist/src/mcp/server.mjs +34 -1
- package/dist/src/mcp/tools/agentic-sandbox.mjs +8 -7
- package/dist/src/mcp/tools/command-run.mjs +3 -2
- package/dist/src/mcp/tools/decision.mjs +49 -48
- package/dist/src/mcp/tools/discovery.mjs +46 -21
- package/dist/src/mcp/tools/orchestration.mjs +22 -22
- package/dist/src/mcp/tools/subsystems.mjs +9 -8
- package/dist/src/mcp/tools/worker-invoke.mjs +17 -4
- package/dist/src/mcp/tools/writer-profiles.mjs +1 -1
- package/dist/src/memory/audit.js +719 -0
- package/dist/src/memory/canonical-context.js +392 -13
- package/dist/src/memory/canonical-maintenance.js +95 -0
- package/dist/src/memory/cli-result.js +22 -0
- package/dist/src/memory/cli.js +176 -0
- package/dist/src/memory/context-pack.js +57 -6
- package/dist/src/memory/cost.js +512 -0
- package/dist/src/memory/firewall-classification.d.mts +7 -0
- package/dist/src/memory/firewall-classification.mjs +32 -0
- package/dist/src/memory/index.js +8 -0
- package/dist/src/memory/line-maintenance.js +68 -0
- package/dist/src/memory/maintenance-cli.js +286 -0
- package/dist/src/memory/maintenance-contract.js +136 -0
- package/dist/src/memory/maintenance-index.js +18 -0
- package/dist/src/memory/maintenance-owner.js +2 -0
- package/dist/src/memory/maintenance-record.js +138 -0
- package/dist/src/memory/maintenance.js +254 -0
- package/dist/src/memory/provider-memory-adapter.js +154 -0
- package/dist/src/memory/recommend-cli.js +83 -0
- package/dist/src/memory/recommend.js +269 -0
- package/dist/src/memory/scheduled.js +81 -0
- package/dist/src/memory/taxonomy.js +44 -0
- package/dist/src/mission-protocol/codecs.js +19 -9
- package/dist/src/models/config-loader.js +11 -1
- package/dist/src/models/model-capabilities.v1.json +74 -50
- package/dist/src/models/provider-policy.js +125 -62
- package/dist/src/models/resolver.js +45 -8
- package/dist/src/models/worker-installation.d.mts +7 -0
- package/dist/src/models/worker-installation.mjs +169 -37
- package/dist/src/models/wrapper-route.js +1 -1
- package/dist/src/output-modes/registry.js +8 -7
- package/dist/src/plugin/metadata-validator.js +1 -1
- package/dist/src/providers/deploy-version.d.mts +1 -0
- package/dist/src/providers/deploy-version.mjs +17 -0
- package/dist/src/providers/provider-definitions.js +19 -16
- package/dist/src/providers/skill-ownership.d.mts +11 -2
- package/dist/src/providers/skill-ownership.mjs +35 -17
- package/dist/src/rules/activation.d.mts +11 -2
- package/dist/src/rules/activation.mjs +82 -6
- package/dist/src/rules/inventory.js +1 -1
- package/dist/src/rules/rule-frontmatter.schema.json +2 -0
- package/dist/src/schema/zod-validation.d.mts +6 -0
- package/dist/src/schema/zod-validation.mjs +50 -0
- package/dist/src/serve/executor-registry.js +297 -20
- package/dist/src/serve/executor-token.d.mts +1 -0
- package/dist/src/serve/executor-token.mjs +8 -0
- package/dist/src/serve/shared-host-scheduler.js +1102 -31
- package/dist/src/serve/worker-invocation.js +114 -15
- package/dist/src/sessions/adapters/claude.js +19 -18
- package/dist/src/sessions/adapters/codex.js +33 -19
- package/dist/src/sessions/adapters/copilot.js +14 -13
- package/dist/src/sessions/adapters/cursor.js +19 -18
- package/dist/src/sessions/adapters/deepseek-harness.js +9 -8
- package/dist/src/sessions/adapters/factory.js +11 -10
- package/dist/src/sessions/adapters/generic.js +32 -23
- package/dist/src/sessions/adapters/grokbot.js +35 -35
- package/dist/src/sessions/adapters/hermes.js +20 -19
- package/dist/src/sessions/adapters/muse.js +50 -49
- package/dist/src/sessions/adapters/omp.js +5 -4
- package/dist/src/sessions/adapters/openclaw.js +30 -29
- package/dist/src/sessions/adapters/opencode.js +26 -26
- package/dist/src/sessions/adapters/openhuman.js +24 -23
- package/dist/src/sessions/adapters/pi.js +5 -4
- package/dist/src/sessions/adapters/windsurf.js +8 -8
- package/dist/src/sessions/analytics.js +10 -9
- package/dist/src/sessions/batch-contracts.js +1 -1
- package/dist/src/sessions/batch-import.js +202 -2
- package/dist/src/sessions/candidates.js +7 -6
- package/dist/src/sessions/contracts.js +73 -54
- package/dist/src/sessions/coverage-preflight.js +26 -1
- package/dist/src/sessions/output-registration.js +11 -10
- package/dist/src/sessions/policy.js +18 -7
- package/dist/src/sessions/refresh.js +2 -3
- package/dist/src/sessions/repository.js +4 -2
- package/dist/src/sessions/workspace-discovery.js +92 -26
- package/dist/src/smiths/context-pipeline/aiwg-md.js +18 -1
- package/dist/src/smiths/context-pipeline/claude-hook.js +42 -6
- package/dist/src/smiths/context-pipeline/parallelism-section.js +72 -5
- package/dist/src/smiths/context-pipeline/workspace-context.js +106 -10
- package/dist/src/update/checker.d.mts +4 -0
- package/dist/src/update/checker.mjs +14 -0
- package/dist/src/writing/exemplar-selection.js +6 -6
- package/dist/src/writing/voice-evaluation.js +24 -23
- package/dist/src/writing/writer-migration.js +14 -13
- package/dist/src/writing/writer-profile.js +19 -18
- package/dist/src/writing/writing-brief.js +18 -17
- package/dist/src/writing/writing-receipt.js +47 -46
- package/package.json +5 -2
- package/schemas/decision/DecisionReview.schema.json +78 -1
- package/schemas/mission-v1.schema.json +3 -0
- package/tools/agents/deploy-agents.mjs +67 -39
- package/tools/agents/providers/antigravity.mjs +6 -1
- package/tools/agents/providers/base.mjs +19 -13
- package/tools/agents/providers/claude.mjs +1 -1
- package/tools/agents/providers/codex.mjs +50 -56
- package/tools/agents/providers/copilot.mjs +8 -2
- package/tools/agents/providers/cursor.mjs +1 -1
- package/tools/agents/providers/deepseek-harness.mjs +1 -1
- package/tools/agents/providers/factory.mjs +7 -1
- package/tools/agents/providers/grok-build.mjs +18 -2
- package/tools/agents/providers/grokbot.mjs +1 -1
- package/tools/agents/providers/hermes.mjs +7 -13
- package/tools/agents/providers/muse-hooks.mjs +21 -14
- package/tools/agents/providers/muse.mjs +7 -2
- package/tools/agents/providers/omp.mjs +28 -4
- package/tools/agents/providers/opencode.mjs +14 -5
- package/tools/agents/providers/openhuman.mjs +1 -1
- package/tools/agents/providers/pi.mjs +1 -1
- package/tools/agents/providers/provider-prepare-coordinator.mjs +29 -9
- package/tools/agents/providers/rule-delivery.mjs +263 -71
- package/tools/agents/providers/windsurf.mjs +7 -0
- package/tools/cli/workspace-status.mjs +5 -0
- package/tools/commands/deploy-prompts-codex.mjs +11 -8
- package/tools/ralph-external/lib/codex-adapter.mjs +6 -2
- package/tools/ralph-external/lib/muse-adapter.mjs +12 -2
- package/tools/ralph-external/lib/worker-health.mjs +1 -1
- package/tools/ralph-external/lib/worker-isolation.mjs +65 -9
- package/tools/ralph-external/process-monitor.mjs +7 -4
- package/tools/ralph-external/session-launcher.mjs +280 -32
- package/tools/skills/deploy-skills-codex.mjs +11 -7
- package/vscode-extension/schemas/aiwg.config.v1.json +11 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { integer, dateTime, number } from '../schema/zod-validation.mjs';
|
|
3
4
|
import { redactSessionText, redactSessionValue } from './policy.js';
|
|
4
5
|
export const SESSION_CONTRACT_VERSION = '1.0.0';
|
|
5
6
|
export const SESSION_PROVIDER_IDS = [
|
|
@@ -20,9 +21,18 @@ export const SessionRuntimeIdentitySchema = z.object({
|
|
|
20
21
|
canonicalRoot: z.string().nullable(),
|
|
21
22
|
diagnostics: z.array(z.string()),
|
|
22
23
|
});
|
|
24
|
+
export const SessionProviderScopeWarningSchema = z.object({
|
|
25
|
+
code: z.literal('CONFIGURED_PROVIDERS_OUTSIDE_SCOPE'),
|
|
26
|
+
configuredProviders: z.array(ExpectedSessionProviderSchema),
|
|
27
|
+
expectedProviders: z.array(ExpectedSessionProviderSchema),
|
|
28
|
+
missingProviders: z.array(ExpectedSessionProviderSchema),
|
|
29
|
+
message: z.string(),
|
|
30
|
+
});
|
|
23
31
|
export const SessionCoveragePreflightSchema = z.object({
|
|
24
32
|
expectedProviders: z.array(ExpectedSessionProviderSchema).min(1),
|
|
25
|
-
expectedProviderBasis: z.enum(['explicit', 'declared-default', 'legacy']),
|
|
33
|
+
expectedProviderBasis: z.enum(['explicit', 'workspace-config', 'declared-default', 'legacy']),
|
|
34
|
+
configuredProviders: z.array(ExpectedSessionProviderSchema).optional(),
|
|
35
|
+
scopeWarnings: z.array(SessionProviderScopeWarningSchema).optional(),
|
|
26
36
|
supportedProviders: z.array(ExpectedSessionProviderSchema),
|
|
27
37
|
runtime: SessionRuntimeIdentitySchema,
|
|
28
38
|
status: z.enum(['partial', 'complete']),
|
|
@@ -37,7 +47,7 @@ export const SessionCoveragePreflightSchema = z.object({
|
|
|
37
47
|
adapterVersion: z.string().nullable(),
|
|
38
48
|
supportedOperations: z.array(z.string()),
|
|
39
49
|
acquisitionModes: z.array(z.string()),
|
|
40
|
-
sourceCount:
|
|
50
|
+
sourceCount: integer().nonnegative(),
|
|
41
51
|
boundaries: z.array(z.string()),
|
|
42
52
|
remediation: z.string().nullable(),
|
|
43
53
|
})),
|
|
@@ -71,7 +81,7 @@ export const SessionErrorCodeSchema = z.enum([
|
|
|
71
81
|
]);
|
|
72
82
|
const VersionSchema = z.string().regex(/^\d+\.\d+\.\d+(?:[-+].+)?$/);
|
|
73
83
|
const DigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/);
|
|
74
|
-
const NativeExtensionsSchema = z.record(z.unknown()).superRefine((value, context) => {
|
|
84
|
+
const NativeExtensionsSchema = z.record(z.string(), z.unknown()).superRefine((value, context) => {
|
|
75
85
|
for (const key of Object.keys(value)) {
|
|
76
86
|
if (!key.startsWith('native.')) {
|
|
77
87
|
context.addIssue({ code: z.ZodIssueCode.custom, message: `native extension must use native.<provider>: ${key}` });
|
|
@@ -90,8 +100,8 @@ export const SessionSourceSchema = z.object({
|
|
|
90
100
|
disposition: CapabilityDispositionSchema,
|
|
91
101
|
operationalState: OperationalStateSchema,
|
|
92
102
|
consistency: ConsistencyStateSchema,
|
|
93
|
-
authorizedAt:
|
|
94
|
-
extensions: NativeExtensionsSchema.
|
|
103
|
+
authorizedAt: dateTime({ offset: true }),
|
|
104
|
+
extensions: NativeExtensionsSchema.prefault({}),
|
|
95
105
|
});
|
|
96
106
|
export const SessionEventSchema = z.object({
|
|
97
107
|
contractVersion: z.literal(SESSION_CONTRACT_VERSION),
|
|
@@ -100,7 +110,7 @@ export const SessionEventSchema = z.object({
|
|
|
100
110
|
sourceId: z.string().min(1),
|
|
101
111
|
importRunId: z.string().min(1),
|
|
102
112
|
nativeId: z.string().min(1).nullable(),
|
|
103
|
-
sequence:
|
|
113
|
+
sequence: integer().nonnegative(),
|
|
104
114
|
kind: z.string().min(1),
|
|
105
115
|
role: z.string().min(1).nullable(),
|
|
106
116
|
participant: z.string().min(1).nullable().default(null),
|
|
@@ -109,7 +119,7 @@ export const SessionEventSchema = z.object({
|
|
|
109
119
|
model: z.string().min(1).nullable().default(null),
|
|
110
120
|
entities: z.array(z.string().min(1)).default([]),
|
|
111
121
|
extractionState: z.string().min(1).nullable().default(null),
|
|
112
|
-
occurredAt:
|
|
122
|
+
occurredAt: dateTime({ offset: true }).nullable(),
|
|
113
123
|
activityBoundary: z.enum(['pause', 'resume', 'continuation', 'end']).nullable().default(null),
|
|
114
124
|
activityBoundaryBasis: z.string().min(1).nullable().default(null),
|
|
115
125
|
activityBoundaryConfidence: z.enum(['low', 'medium', 'high']).nullable().default(null),
|
|
@@ -123,8 +133,8 @@ export const SessionEventSchema = z.object({
|
|
|
123
133
|
digest: DigestSchema,
|
|
124
134
|
rawReference: z.object({
|
|
125
135
|
locatorClass: z.string().min(1),
|
|
126
|
-
offset:
|
|
127
|
-
sequence:
|
|
136
|
+
offset: integer().nonnegative().optional(),
|
|
137
|
+
sequence: integer().nonnegative().optional(),
|
|
128
138
|
}),
|
|
129
139
|
adapterVersion: VersionSchema,
|
|
130
140
|
consistency: ConsistencyStateSchema,
|
|
@@ -133,7 +143,7 @@ export const SessionEventSchema = z.object({
|
|
|
133
143
|
classes: z.array(z.string().min(1)),
|
|
134
144
|
}),
|
|
135
145
|
opaque: z.boolean().default(false),
|
|
136
|
-
extensions: NativeExtensionsSchema.
|
|
146
|
+
extensions: NativeExtensionsSchema.prefault({}),
|
|
137
147
|
});
|
|
138
148
|
export const SessionSchema = z.object({
|
|
139
149
|
contractVersion: z.literal(SESSION_CONTRACT_VERSION),
|
|
@@ -142,8 +152,8 @@ export const SessionSchema = z.object({
|
|
|
142
152
|
provider: CompatibleSessionProviderIdSchema,
|
|
143
153
|
nativeSessionId: z.string().min(1),
|
|
144
154
|
workspaceId: z.string().min(1),
|
|
145
|
-
startedAt:
|
|
146
|
-
updatedAt:
|
|
155
|
+
startedAt: dateTime({ offset: true }).nullable(),
|
|
156
|
+
updatedAt: dateTime({ offset: true }).nullable(),
|
|
147
157
|
consistency: ConsistencyStateSchema,
|
|
148
158
|
lifecycle: z.enum([
|
|
149
159
|
'active', 'inactive', 'paused', 'complete', 'interrupted', 'archived',
|
|
@@ -152,10 +162,10 @@ export const SessionSchema = z.object({
|
|
|
152
162
|
intent: z.object({
|
|
153
163
|
status: z.enum(['selected', 'absent', 'unknown']),
|
|
154
164
|
eventId: z.string().min(1).nullable(),
|
|
155
|
-
sequence:
|
|
165
|
+
sequence: integer().nonnegative().nullable(),
|
|
156
166
|
title: z.string().nullable(),
|
|
157
167
|
summary: z.string().nullable(),
|
|
158
|
-
}).
|
|
168
|
+
}).prefault({
|
|
159
169
|
status: 'unknown',
|
|
160
170
|
eventId: null,
|
|
161
171
|
sequence: null,
|
|
@@ -163,12 +173,12 @@ export const SessionSchema = z.object({
|
|
|
163
173
|
summary: null,
|
|
164
174
|
}),
|
|
165
175
|
sourceDigest: DigestSchema,
|
|
166
|
-
extensions: NativeExtensionsSchema.
|
|
176
|
+
extensions: NativeExtensionsSchema.prefault({}),
|
|
167
177
|
});
|
|
168
178
|
export const ImportCheckpointSchema = z.object({
|
|
169
179
|
cursor: z.string(),
|
|
170
|
-
recordsRead:
|
|
171
|
-
bytesRead:
|
|
180
|
+
recordsRead: integer().nonnegative(),
|
|
181
|
+
bytesRead: integer().nonnegative(),
|
|
172
182
|
checkpointVersion: z.literal('2').optional(),
|
|
173
183
|
positionKind: z.enum(['record-index', 'byte-offset', 'provider-native']).optional(),
|
|
174
184
|
sourceGeneration: z.string().min(1).optional(),
|
|
@@ -182,8 +192,8 @@ export const ImportCheckpointSchema = z.object({
|
|
|
182
192
|
'unchanged-replay',
|
|
183
193
|
'unverified',
|
|
184
194
|
]).optional(),
|
|
185
|
-
sourceSize:
|
|
186
|
-
sourceMtimeMs: z.
|
|
195
|
+
sourceSize: integer().nonnegative().optional(),
|
|
196
|
+
sourceMtimeMs: number().check(z.gte(0)).meta({ type: 'number', minimum: 0 }).optional(),
|
|
187
197
|
sourceFileIdentity: z.string().min(1).optional(),
|
|
188
198
|
prefixDigest: DigestSchema.optional(),
|
|
189
199
|
});
|
|
@@ -197,8 +207,8 @@ export const ImportRunSchema = z.object({
|
|
|
197
207
|
consistency: ConsistencyStateSchema,
|
|
198
208
|
status: z.enum(['running', 'committed', 'rolled-back', 'failed']),
|
|
199
209
|
checkpoint: ImportCheckpointSchema,
|
|
200
|
-
startedAt:
|
|
201
|
-
completedAt:
|
|
210
|
+
startedAt: dateTime({ offset: true }),
|
|
211
|
+
completedAt: dateTime({ offset: true }).nullable(),
|
|
202
212
|
errorCode: SessionErrorCodeSchema.nullable(),
|
|
203
213
|
});
|
|
204
214
|
export const ProvenanceEdgeSchema = z.object({
|
|
@@ -211,7 +221,7 @@ export const ProvenanceEdgeSchema = z.object({
|
|
|
211
221
|
fromId: z.string().min(1),
|
|
212
222
|
toId: z.string().min(1),
|
|
213
223
|
importRunId: z.string().min(1),
|
|
214
|
-
createdAt:
|
|
224
|
+
createdAt: dateTime({ offset: true }),
|
|
215
225
|
});
|
|
216
226
|
export const IntelligenceCandidateTypeSchema = z.enum([
|
|
217
227
|
'decision', 'requirement', 'constraint', 'preference', 'task', 'discovery',
|
|
@@ -222,29 +232,29 @@ export const CandidateSecurityWarningSchema = z.enum([
|
|
|
222
232
|
'instruction-like', 'structure-breaking', 'control-character', 'bidi-control',
|
|
223
233
|
'unicode-confusable', 'active-content', 'secret-bearing',
|
|
224
234
|
]);
|
|
225
|
-
export const CandidateSecuritySchema = z.
|
|
235
|
+
export const CandidateSecuritySchema = z.strictObject({
|
|
226
236
|
disposition: z.enum(['clear', 'suspicious']),
|
|
227
237
|
warnings: z.array(CandidateSecurityWarningSchema),
|
|
228
238
|
requiresAcknowledgement: z.boolean(),
|
|
229
239
|
acknowledged: z.boolean(),
|
|
230
240
|
policyVersion: VersionSchema,
|
|
231
|
-
})
|
|
232
|
-
export const IntelligenceCandidateSchema = z.
|
|
241
|
+
});
|
|
242
|
+
export const IntelligenceCandidateSchema = z.strictObject({
|
|
233
243
|
contractVersion: z.literal(SESSION_CONTRACT_VERSION),
|
|
234
244
|
candidateId: z.string().min(1),
|
|
235
|
-
version:
|
|
245
|
+
version: integer().positive(),
|
|
236
246
|
type: IntelligenceCandidateTypeSchema,
|
|
237
247
|
assertion: z.string().min(1),
|
|
238
248
|
subject: z.string().min(1).nullable(),
|
|
239
249
|
predicate: z.string().min(1).nullable(),
|
|
240
250
|
object: z.string().min(1).nullable(),
|
|
241
|
-
evidence: z.array(z.
|
|
251
|
+
evidence: z.array(z.strictObject({
|
|
242
252
|
eventId: z.string().min(1),
|
|
243
|
-
start:
|
|
244
|
-
end:
|
|
253
|
+
start: integer().nonnegative(),
|
|
254
|
+
end: integer().positive(),
|
|
245
255
|
quoteDigest: DigestSchema,
|
|
246
256
|
quote: z.string().min(1).optional(),
|
|
247
|
-
})
|
|
257
|
+
})).min(1),
|
|
248
258
|
confidence: z.number().min(0).max(1),
|
|
249
259
|
temporalScope: z.string().min(1),
|
|
250
260
|
projectScope: z.string().min(1),
|
|
@@ -253,7 +263,7 @@ export const IntelligenceCandidateSchema = z.object({
|
|
|
253
263
|
extractionPolicyVersion: VersionSchema,
|
|
254
264
|
model: z.string().min(1).nullable(),
|
|
255
265
|
sensitivity: z.enum(['none', 'sensitive']),
|
|
256
|
-
security: CandidateSecuritySchema.
|
|
266
|
+
security: CandidateSecuritySchema.prefault({
|
|
257
267
|
disposition: 'clear',
|
|
258
268
|
warnings: [],
|
|
259
269
|
requiresAcknowledgement: false,
|
|
@@ -265,8 +275,8 @@ export const IntelligenceCandidateSchema = z.object({
|
|
|
265
275
|
]),
|
|
266
276
|
conflictsWith: z.array(z.string().min(1)).default([]),
|
|
267
277
|
supersedes: z.array(z.string().min(1)).default([]),
|
|
268
|
-
createdAt:
|
|
269
|
-
}).
|
|
278
|
+
createdAt: dateTime({ offset: true }),
|
|
279
|
+
}).superRefine((candidate, context) => {
|
|
270
280
|
if (candidate.type === 'relationship'
|
|
271
281
|
&& (!candidate.subject || !candidate.predicate || !candidate.object)) {
|
|
272
282
|
context.addIssue({
|
|
@@ -275,11 +285,11 @@ export const IntelligenceCandidateSchema = z.object({
|
|
|
275
285
|
});
|
|
276
286
|
}
|
|
277
287
|
});
|
|
278
|
-
export const CandidateReviewReceiptSchema = z.
|
|
288
|
+
export const CandidateReviewReceiptSchema = z.strictObject({
|
|
279
289
|
contractVersion: z.literal(SESSION_CONTRACT_VERSION),
|
|
280
290
|
receiptId: z.string().min(1),
|
|
281
291
|
candidateId: z.string().min(1),
|
|
282
|
-
candidateVersion:
|
|
292
|
+
candidateVersion: integer().positive(),
|
|
283
293
|
fromState: z.enum([
|
|
284
294
|
'pending', 'accepted', 'rejected', 'deferred', 'promoted', 'superseded',
|
|
285
295
|
]),
|
|
@@ -290,18 +300,18 @@ export const CandidateReviewReceiptSchema = z.object({
|
|
|
290
300
|
reason: z.string().min(1),
|
|
291
301
|
securityWarnings: z.array(CandidateSecurityWarningSchema).default([]),
|
|
292
302
|
securityAcknowledged: z.boolean().default(false),
|
|
293
|
-
occurredAt:
|
|
294
|
-
})
|
|
295
|
-
export const PromotionReceiptSchema = z.
|
|
303
|
+
occurredAt: dateTime({ offset: true }),
|
|
304
|
+
});
|
|
305
|
+
export const PromotionReceiptSchema = z.strictObject({
|
|
296
306
|
contractVersion: z.literal(SESSION_CONTRACT_VERSION),
|
|
297
307
|
receiptId: z.string().min(1),
|
|
298
308
|
operationId: z.string().min(1),
|
|
299
309
|
candidateId: z.string().min(1),
|
|
300
|
-
candidateVersion:
|
|
310
|
+
candidateVersion: integer().positive(),
|
|
301
311
|
consumer: z.string().min(1),
|
|
302
312
|
destinationRef: z.string().min(1),
|
|
303
313
|
reviewer: z.string().min(1),
|
|
304
|
-
approvedAt:
|
|
314
|
+
approvedAt: dateTime({ offset: true }),
|
|
305
315
|
evidenceEventIds: z.array(z.string().min(1)).min(1),
|
|
306
316
|
conflictsWith: z.array(z.string().min(1)),
|
|
307
317
|
supersedes: z.array(z.string().min(1)),
|
|
@@ -309,27 +319,27 @@ export const PromotionReceiptSchema = z.object({
|
|
|
309
319
|
afterHash: DigestSchema,
|
|
310
320
|
dryRun: z.boolean(),
|
|
311
321
|
duplicate: z.boolean(),
|
|
312
|
-
})
|
|
313
|
-
export const DeletionReceiptSchema = z.
|
|
322
|
+
});
|
|
323
|
+
export const DeletionReceiptSchema = z.strictObject({
|
|
314
324
|
contractVersion: z.literal(SESSION_CONTRACT_VERSION),
|
|
315
325
|
receiptId: z.string().min(1),
|
|
316
326
|
operationId: z.string().min(1),
|
|
317
327
|
scopeClass: z.string().min(1),
|
|
318
|
-
counts: z.record(z.
|
|
328
|
+
counts: z.record(z.string(), integer().nonnegative()),
|
|
319
329
|
survivingDependentIds: z.array(z.string().min(1)),
|
|
320
330
|
actorClass: z.string().min(1),
|
|
321
331
|
reasonCode: z.string().min(1),
|
|
322
|
-
orphanCounts: z.record(z.
|
|
332
|
+
orphanCounts: z.record(z.string(), integer().nonnegative()),
|
|
323
333
|
outcome: z.enum(['preview', 'committed', 'failed']),
|
|
324
|
-
occurredAt:
|
|
325
|
-
})
|
|
326
|
-
export const PromotionDependencyDecisionSchema = z.
|
|
334
|
+
occurredAt: dateTime({ offset: true }),
|
|
335
|
+
});
|
|
336
|
+
export const PromotionDependencyDecisionSchema = z.strictObject({
|
|
327
337
|
dependentId: z.string().min(1),
|
|
328
338
|
action: z.enum([
|
|
329
339
|
'revoke', 'supersede', 'retain', 'origin_unavailable', 'delete', 'abort',
|
|
330
340
|
]),
|
|
331
341
|
basis: z.string().min(1),
|
|
332
|
-
})
|
|
342
|
+
});
|
|
333
343
|
export function assertSessionProviderId(value) {
|
|
334
344
|
const canonical = SESSION_PROVIDER_ALIASES[value] ?? value;
|
|
335
345
|
const parsed = SessionProviderIdSchema.safeParse(canonical);
|
|
@@ -364,7 +374,7 @@ function stableId(prefix, ...parts) {
|
|
|
364
374
|
return `${prefix}_${createHash('sha256').update(parts.join('\0')).digest('hex')}`;
|
|
365
375
|
}
|
|
366
376
|
export const SessionRejectionDetailSchema = z.union([
|
|
367
|
-
z.object({ limit: z.string(), configured:
|
|
377
|
+
z.object({ limit: z.string(), configured: number(), observed: number(),
|
|
368
378
|
setting: z.string().optional(), origin: z.enum(['flag', 'env', 'config', 'default']).optional() }),
|
|
369
379
|
z.object({ issues: z.array(z.object({ path: z.string(), code: z.string() })) }),
|
|
370
380
|
]);
|
|
@@ -381,16 +391,25 @@ export function assertSessionResourceLimit(limit, configured, observed) {
|
|
|
381
391
|
/** Extract schema locations and validator codes without messages or input values. */
|
|
382
392
|
export function schemaRejectionDetail(error) {
|
|
383
393
|
const issues = [];
|
|
384
|
-
const visit = (entries) => {
|
|
394
|
+
const visit = (entries, prefix = []) => {
|
|
385
395
|
for (const issue of entries) {
|
|
386
396
|
if (issues.length >= 20)
|
|
387
397
|
return;
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
398
|
+
const path = [...prefix, ...issue.path];
|
|
399
|
+
if (issue.code === 'invalid_union' && issue.errors.length === 0) {
|
|
400
|
+
issues.push({ path: path.join('.') || '<root>', code: 'invalid_union_discriminator' });
|
|
401
|
+
}
|
|
402
|
+
else if (issue.code === 'invalid_union') {
|
|
403
|
+
// Native union branches carry paths relative to their parent union.
|
|
404
|
+
for (const branch of issue.errors)
|
|
405
|
+
visit(branch, path);
|
|
391
406
|
}
|
|
392
407
|
else {
|
|
393
|
-
|
|
408
|
+
// Keep the published diagnostic codes stable across validator versions.
|
|
409
|
+
const code = issue.code === 'invalid_value'
|
|
410
|
+
? (issue.values.length === 1 ? 'invalid_literal' : 'invalid_enum_value')
|
|
411
|
+
: issue.code === 'invalid_format' ? 'invalid_string' : issue.code;
|
|
412
|
+
issues.push({ path: path.join('.') || '<root>', code });
|
|
394
413
|
}
|
|
395
414
|
}
|
|
396
415
|
};
|
|
@@ -19,6 +19,29 @@ export function expectedSessionProviders(values) {
|
|
|
19
19
|
}
|
|
20
20
|
return [...new Set(providers)].sort();
|
|
21
21
|
}
|
|
22
|
+
export function providerScopeWarnings(configured, expected, recorded = []) {
|
|
23
|
+
const configuredProviders = configured.length ? expectedSessionProviders(configured) : [];
|
|
24
|
+
const expectedProviders = expected.length ? expectedSessionProviders(expected) : [];
|
|
25
|
+
const missingProviders = configuredProviders.filter(provider => !expectedProviders.includes(provider));
|
|
26
|
+
const current = missingProviders.length ? [{
|
|
27
|
+
code: 'CONFIGURED_PROVIDERS_OUTSIDE_SCOPE', configuredProviders, expectedProviders, missingProviders,
|
|
28
|
+
message: `Configured providers outside discovery scope: ${missingProviders.join(', ')}. Rediscover or refresh with current workspace config; verify authorized roots before rebuilding.`,
|
|
29
|
+
}] : [];
|
|
30
|
+
return [...recorded, ...current].filter((warning, index, all) => all.findIndex(item => JSON.stringify(item) === JSON.stringify(warning)) === index);
|
|
31
|
+
}
|
|
32
|
+
/** Explicit scope applies once; maintenance combines current config with saved root grants. */
|
|
33
|
+
export function resolveSessionProviderScope(configured, explicit, authorized) {
|
|
34
|
+
const configuredProviders = configured.length ? expectedSessionProviders(configured) : [];
|
|
35
|
+
const values = [...configuredProviders, ...(authorized ?? [])];
|
|
36
|
+
const expectedProviders = expectedSessionProviders(explicit ?? (values.length ? values : SESSION_PROVIDER_IDS));
|
|
37
|
+
return {
|
|
38
|
+
expectedProviders,
|
|
39
|
+
expectedProviderBasis: explicit ? 'explicit' : configuredProviders.length ? 'workspace-config'
|
|
40
|
+
: authorized?.length ? 'explicit' : 'declared-default',
|
|
41
|
+
configuredProviders,
|
|
42
|
+
scopeWarnings: providerScopeWarnings(configuredProviders, expectedProviders),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
22
45
|
/** Resolve the code actually loaded, independently of cwd, AIWG_ROOT and corpus redirects. */
|
|
23
46
|
export function sessionRuntimeIdentity() {
|
|
24
47
|
const packageRoot = findPackageRoot(dirname(fileURLToPath(import.meta.url)));
|
|
@@ -103,6 +126,8 @@ export function coveragePreflight(options = {}) {
|
|
|
103
126
|
return SessionCoveragePreflightSchema.parse({
|
|
104
127
|
expectedProviders,
|
|
105
128
|
expectedProviderBasis: options.expectedProviderBasis ?? (options.expectedProviders ? 'explicit' : 'declared-default'),
|
|
129
|
+
...(options.configuredProviders ? { configuredProviders: options.configuredProviders } : {}),
|
|
130
|
+
...(options.scopeWarnings ? { scopeWarnings: options.scopeWarnings } : {}),
|
|
106
131
|
supportedProviders: adapters.map((adapter) => adapter.provider), runtime,
|
|
107
132
|
status: 'partial', unresolvedProviders: expectedProviders, ledger,
|
|
108
133
|
});
|
|
@@ -127,7 +152,7 @@ export function reconcileCoveragePreflight(preflight, sources) {
|
|
|
127
152
|
const runtimeGap = ['mismatch', 'stale', 'unknown'].includes(preflight.runtime.installationState);
|
|
128
153
|
return {
|
|
129
154
|
...preflight, ledger, unresolvedProviders,
|
|
130
|
-
status: unresolvedProviders.length > 0 || runtimeGap || preflight.expectedProviderBasis
|
|
155
|
+
status: unresolvedProviders.length > 0 || runtimeGap || !['explicit', 'workspace-config'].includes(preflight.expectedProviderBasis)
|
|
131
156
|
? 'partial' : 'complete',
|
|
132
157
|
};
|
|
133
158
|
}
|
|
@@ -2,34 +2,35 @@ import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameS
|
|
|
2
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import { dirname, relative, resolve, sep } from 'node:path';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
+
import { integer } from '../schema/zod-validation.mjs';
|
|
5
6
|
import { SessionContractError, sha256 } from './contracts.js';
|
|
6
7
|
const DigestSchema = z.string().regex(/^sha256:[0-9a-f]{64}$/);
|
|
7
8
|
const ReferenceSchema = z.string().min(1).max(512).refine(value => !/[\r\n\0]/.test(value), 'references must be single-line inert locators');
|
|
8
|
-
export const OutputSourceReferenceSchema = z.
|
|
9
|
+
export const OutputSourceReferenceSchema = z.strictObject({
|
|
9
10
|
kind: z.enum(['file', 'url', 'note', 'session', 'artifact', 'context-pack']),
|
|
10
11
|
ref: ReferenceSchema,
|
|
11
12
|
digest: DigestSchema.nullable().default(null),
|
|
12
|
-
span: z.
|
|
13
|
-
start:
|
|
14
|
-
end:
|
|
13
|
+
span: z.strictObject({
|
|
14
|
+
start: integer().nonnegative(),
|
|
15
|
+
end: integer().positive(),
|
|
15
16
|
quoteDigest: DigestSchema,
|
|
16
|
-
}).
|
|
17
|
-
}).
|
|
17
|
+
}).nullable().default(null),
|
|
18
|
+
}).superRefine((value, context) => {
|
|
18
19
|
if (value.span && value.span.end <= value.span.start) {
|
|
19
20
|
context.addIssue({ code: z.ZodIssueCode.custom, message: 'source span end must exceed start' });
|
|
20
21
|
}
|
|
21
22
|
});
|
|
22
|
-
export const OutputRegistrationRequestSchema = z.
|
|
23
|
+
export const OutputRegistrationRequestSchema = z.strictObject({
|
|
23
24
|
outputPath: z.string().min(1),
|
|
24
25
|
mediaType: z.string().min(1).max(128),
|
|
25
|
-
contextPack: z.
|
|
26
|
+
contextPack: z.strictObject({
|
|
26
27
|
id: ReferenceSchema,
|
|
27
28
|
digest: DigestSchema,
|
|
28
29
|
sources: z.array(OutputSourceReferenceSchema).min(1).max(256),
|
|
29
|
-
})
|
|
30
|
+
}),
|
|
30
31
|
supersedes: z.array(ReferenceSchema).max(128).default([]),
|
|
31
32
|
conflictsWith: z.array(ReferenceSchema).max(128).default([]),
|
|
32
|
-
})
|
|
33
|
+
});
|
|
33
34
|
/**
|
|
34
35
|
* Minimal incremental index sink. Each registration is independently atomic,
|
|
35
36
|
* discoverable, and replay-safe; corpus-wide index builders can consume these
|
|
@@ -56,20 +56,31 @@ async function safeRealpath(path, root = false) {
|
|
|
56
56
|
throw new SessionContractError('SOURCE_NOT_AUTHORIZED', root ? 'an authorized source root is inaccessible' : 'selected session source is inaccessible');
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
+
// Newline gaps are bounded and each repetition consumes a line break, keeping
|
|
60
|
+
// indentation scans disjoint even on large malformed records (#3273, #3404).
|
|
61
|
+
const VALUE_GAP = /[ \t]*(?:\r?\n[ \t]*){0,2}/.source;
|
|
62
|
+
const NEXT_LINE_GAP = /[ \t]*(?:\r?\n[ \t]*){1,2}/.source;
|
|
63
|
+
const QUOTED_VALUE = /"(?:\\[^\r\n]|[^"\\\r\n])+"|'(?:\\[^\r\n]|[^'\\\r\n])+'|`(?!`)(?:\\[^\r\n]|[^`\\\r\n])+`(?!`)/.source;
|
|
64
|
+
const GENERATED_VALUE = /(?=[A-Za-z0-9._~+/=-]*[0-9])(?=[A-Za-z0-9._~+/=-]*[A-Za-z])[A-Za-z0-9._~+/=-]{20,}/.source;
|
|
65
|
+
function assignmentPattern(key, separator, sameLineValue) {
|
|
66
|
+
// Only the next-line branch needs stronger evidence: quoted text or a long
|
|
67
|
+
// generated value. In particular, YAML lists and Markdown fences are prose.
|
|
68
|
+
return new RegExp(`\\b${key}[ \\t]*${separator}(?:${NEXT_LINE_GAP}(?:${QUOTED_VALUE}|${GENERATED_VALUE})|[ \\t]*(?:${QUOTED_VALUE}|${sameLineValue}))`, 'gi');
|
|
69
|
+
}
|
|
59
70
|
// Ambiguous token components are bounded; whitespace and key blocks use disjoint scans.
|
|
60
71
|
const SECRET_PATTERNS = [
|
|
61
|
-
['bearer-token',
|
|
62
|
-
['authorization',
|
|
63
|
-
['cookie',
|
|
64
|
-
['environment-assignment',
|
|
65
|
-
['credential',
|
|
72
|
+
['bearer-token', new RegExp(`\\bBearer(?:[ \\t]+|${NEXT_LINE_GAP})(?:${QUOTED_VALUE}|\\\\"[A-Za-z0-9._~+/=-]{12,}\\\\"|[A-Za-z0-9._~+/=-]{12,})`, 'gi')],
|
|
73
|
+
['authorization', new RegExp(`\\bAuthorization[ \\t]*:${VALUE_GAP}[^\\s][^\\r\\n]*`, 'gi')],
|
|
74
|
+
['cookie', new RegExp(`\\b(?:Cookie|Set-Cookie)[ \\t]*:${VALUE_GAP}[^\\s][^\\r\\n]*`, 'gi')],
|
|
75
|
+
['environment-assignment', assignmentPattern('(?:AWS_SECRET_ACCESS_KEY|[A-Z][A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|PASSWD|API_KEY))', '=', /[^\s]+/.source)],
|
|
76
|
+
['credential', assignmentPattern('(?:api[_-]?key|token|password|secret)', '[:=]', /["'`]?[^\s"'`,;]{6,}/.source)],
|
|
66
77
|
['credential', /^[ \t]*password[ \t]+[^\s]+[ \t]*$/gim],
|
|
67
78
|
// Space-separated values only when they look generated (20+ chars, letters and digits), so prose stays.
|
|
68
|
-
['credential',
|
|
79
|
+
['credential', new RegExp(`\\b(?:api[_-]?key|token|secret)[ \\t]+${GENERATED_VALUE}`, 'gi')],
|
|
69
80
|
['provider-token', /\b(?:sk-(?:ant-|proj-)?|[sr]k_(?:live|test)_|gh[pousr]_|github_pat_|glpat-|xai-|npm_|hf_|xox[baprs]-|AKIA|AIza)[A-Za-z0-9._~+/=-]{8,}/g],
|
|
70
81
|
['provider-token', /https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9_-]+\/[A-Za-z0-9_-]+\/[A-Za-z0-9_-]+/g],
|
|
71
82
|
['connection-string', /\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis):\/\/[^\s]+/gi],
|
|
72
|
-
['credential-url',
|
|
83
|
+
['credential-url', new RegExp(`\\bhttps?://${VALUE_GAP}[^/\\s:@]+:${VALUE_GAP}(?:${QUOTED_VALUE}|[^/\\s@]+)@${VALUE_GAP}[^\\s"'\x60<>\\\\]+`, 'gi')],
|
|
73
84
|
['fixture-credential', /\bredaction-canary-[A-Za-z0-9_-]+\b/gi],
|
|
74
85
|
['email', /\b[A-Z0-9._%+-]{1,64}@[A-Z0-9.-]{1,253}\.[A-Z]{2,63}\b/gi],
|
|
75
86
|
];
|
|
@@ -20,7 +20,7 @@ export function sessionRefreshAvailable() {
|
|
|
20
20
|
return false;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
/** Refresh
|
|
23
|
+
/** Refresh current configured scope within saved provider root grants. */
|
|
24
24
|
export async function refreshSessionCatalog(workspace, full, waitMs, signal, workspaceAliases = [], flags = {}) {
|
|
25
25
|
const canonicalWorkspace = realpathSync(workspace);
|
|
26
26
|
const config = await readAiwgConfig(canonicalWorkspace);
|
|
@@ -56,8 +56,7 @@ export async function refreshSessionCatalog(workspace, full, waitMs, signal, wor
|
|
|
56
56
|
const manifest = await discoverWorkspaceHistories({
|
|
57
57
|
workspace: canonicalWorkspace,
|
|
58
58
|
workspaceAliases: [workspace, ...workspaceAliases],
|
|
59
|
-
|
|
60
|
-
authorizedRoots,
|
|
59
|
+
refreshFrom: { ...previous, authorizedRoots },
|
|
61
60
|
registry: createSessionAdapterRegistry(limits),
|
|
62
61
|
exclude,
|
|
63
62
|
knownSources: previous.sources,
|
|
@@ -13,7 +13,7 @@ const VISIBLE_SESSION_PREDICATE = `s.lifecycle != 'tombstoned' AND EXISTS (
|
|
|
13
13
|
)`;
|
|
14
14
|
export class SessionRepository {
|
|
15
15
|
db;
|
|
16
|
-
constructor(path = ':memory:') {
|
|
16
|
+
constructor(path = ':memory:', options = {}) {
|
|
17
17
|
let Database;
|
|
18
18
|
try {
|
|
19
19
|
Database = requireFeaturePackage('better-sqlite3');
|
|
@@ -23,7 +23,9 @@ export class SessionRepository {
|
|
|
23
23
|
'run `aiwg features install sqlite`, then retry. If the native build fails, install ' +
|
|
24
24
|
'Python 3, make, and a C/C++ compiler supported by node-gyp.', { cause });
|
|
25
25
|
}
|
|
26
|
-
this.db = new Database(path);
|
|
26
|
+
this.db = new Database(path, options.readonly ? { readonly: true, fileMustExist: true } : undefined);
|
|
27
|
+
if (options.readonly)
|
|
28
|
+
return;
|
|
27
29
|
this.db.pragma('foreign_keys = ON');
|
|
28
30
|
this.db.pragma('journal_mode = WAL');
|
|
29
31
|
this.db.pragma('busy_timeout = 5000');
|