@aiwg/cli 2026.9.3 → 2026.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/THIRD_PARTY_NOTICES.md +16 -0
- package/agentic/code/providers/capability-matrix.yaml +45 -3
- package/agentic/code/providers/deepseek-harness/README.md +8 -0
- package/agentic/code/providers/deepseek-harness/aiwg.cordis.patch.yml +10 -0
- package/agentic/code/providers/model-capabilities.v1.json +11 -0
- package/agentic/code/providers/model-catalog.v1.json +8 -0
- package/bin/aiwg.mjs +1 -0
- package/dist/src/api/index.d.ts +14 -0
- package/dist/src/api/index.js +14 -0
- package/dist/src/artifacts/corpus-tools/source-types.js +1 -0
- package/dist/src/artifacts/index-files.js +17 -2
- package/dist/src/artifacts/repair.js +55 -6
- package/dist/src/catalog/cli.js +21 -7
- package/dist/src/catalog/cli.mjs +22 -7
- package/dist/src/cli/agent-spawn.js +10 -1
- package/dist/src/cli/handlers/artifacts.js +22 -3
- package/dist/src/cli/handlers/help.js +3 -0
- package/dist/src/cli/handlers/index.js +5 -1
- package/dist/src/cli/handlers/models.js +2 -2
- package/dist/src/cli/handlers/output-mode.js +1 -1
- package/dist/src/cli/handlers/runtime-info.js +1 -1
- package/dist/src/cli/handlers/sessions.js +55 -15
- package/dist/src/cli/handlers/steward.js +1 -1
- package/dist/src/cli/handlers/subcommands.js +5 -0
- package/dist/src/cli/handlers/use.js +37 -0
- package/dist/src/cli/handlers/writer-profile.js +110 -0
- package/dist/src/cli/handlers/writing.js +122 -0
- package/dist/src/cli/router.js +5 -1
- package/dist/src/config/project-artifacts-runtime.mjs +33 -1
- package/dist/src/config/project-artifacts.js +1 -1
- package/dist/src/dataset/fortemi-dataset-execution.d.ts +23 -0
- package/dist/src/dataset/fortemi-dataset-execution.js +158 -0
- package/dist/src/dataset/fortemi-live-qualification.d.ts +4 -2
- package/dist/src/dataset/fortemi-live-qualification.js +20 -21
- package/dist/src/dataset/fortemi-run-receipt.d.ts +44 -0
- package/dist/src/dataset/fortemi-run-receipt.js +74 -0
- package/dist/src/dataset/index.d.ts +2 -0
- package/dist/src/dataset/index.js +2 -0
- package/dist/src/extensions/commands/definitions.js +24 -0
- package/dist/src/extensions/manifest.js +3 -0
- package/dist/src/mcp/server.mjs +2 -0
- package/dist/src/mcp/tools/writer-profiles.mjs +40 -0
- package/dist/src/models/model-capabilities.v1.json +11 -0
- package/dist/src/models/model-catalog.v1.json +8 -0
- package/dist/src/models/provider-policy.js +1 -1
- package/dist/src/network-analysis/analyzer.js +667 -0
- package/dist/src/network-analysis/citations.js +107 -0
- package/dist/src/network-analysis/forensics.js +132 -0
- package/dist/src/network-analysis/governance.js +216 -0
- package/dist/src/network-analysis/index.js +10 -0
- package/dist/src/network-analysis/probe.js +405 -0
- package/dist/src/network-analysis/recipes.js +88 -0
- package/dist/src/network-analysis/research.js +181 -0
- package/dist/src/network-analysis/termshark.js +252 -0
- package/dist/src/network-analysis/verification.js +171 -0
- package/dist/src/output-modes/registry.js +37 -6
- package/dist/src/output-modes/runtime.js +164 -28
- package/dist/src/providers/capability-matrix.yaml +45 -3
- package/dist/src/providers/provider-definitions.js +49 -0
- package/dist/src/providers/provider-inventory.js +1 -0
- package/dist/src/providers/transformation-receipt.js +3 -2
- package/dist/src/sessions/adapters/deepseek-harness.js +178 -0
- package/dist/src/sessions/batch-import.js +7 -0
- package/dist/src/sessions/contracts.js +2 -1
- package/dist/src/sessions/index.js +1 -0
- package/dist/src/sessions/workspace-discovery.js +5 -1
- package/dist/src/skills/deployer.js +6 -6
- package/dist/src/smiths/context-pipeline/workspace-context.js +7 -0
- package/dist/src/writing/channel-packs.js +13 -0
- package/dist/src/writing/contextual-diagnostics.js +142 -0
- package/dist/src/writing/example-generator.js +7 -6
- package/dist/src/writing/exemplar-selection.js +186 -0
- package/dist/src/writing/fidelity.js +61 -0
- package/dist/src/writing/validation-engine.js +32 -15
- package/dist/src/writing/voice-evaluation.js +301 -0
- package/dist/src/writing/voice-revision.js +201 -0
- package/dist/src/writing/writer-migration.js +216 -0
- package/dist/src/writing/writer-profile-legacy.js +145 -0
- package/dist/src/writing/writer-profile-store.js +117 -0
- package/dist/src/writing/writer-profile.js +222 -0
- package/dist/src/writing/writing-brief.js +166 -0
- package/dist/src/writing/writing-channels.js +63 -0
- package/dist/src/writing/writing-consumer.js +39 -0
- package/dist/src/writing/writing-receipt.js +266 -0
- package/package.json +1 -1
- package/schemas/dataset/fortemi-live-qualification-receipt.v2.schema.json +196 -0
- package/schemas/dataset/fortemi-run-receipt/validation-1.0.1/authority.json +12 -0
- package/schemas/dataset/fortemi-run-receipt/validation-1.0.1/run-receipt.schema.json +819 -0
- package/tools/agents/deploy-agents.mjs +7 -3
- package/tools/agents/providers/antigravity.mjs +1 -1
- package/tools/agents/providers/base.mjs +3 -2
- package/tools/agents/providers/deepseek-harness.mjs +66 -0
- package/tools/agents/providers/hermes.mjs +1 -1
- package/tools/agents/providers/openhuman.mjs +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, realpathSync, statSync, } from 'node:fs';
|
|
2
2
|
import { dirname, isAbsolute, resolve, } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, CODEX_ADAPTER_VERSION, CodexSessionAdapter, COPILOT_ADAPTER_VERSION, CopilotSessionAdapter, CURSOR_ADAPTER_VERSION, CursorSessionAdapter, FACTORY_ADAPTER_VERSION, FactorySessionAdapter, HERMES_ADAPTER_VERSION, HermesSessionAdapter, OPENCODE_ADAPTER_VERSION, OpenCodeSessionAdapter, OPENCLAW_ADAPTER_VERSION, OpenClawSessionAdapter, OPENHUMAN_ADAPTER_VERSION, OpenHumanSessionAdapter, PI_ADAPTER_VERSION, PiSessionAdapter, OmpSessionAdapter, OMP_ADAPTER_VERSION, WARP_ADAPTER_VERSION, WarpSessionAdapter, DEVIN_DESKTOP_ADAPTER_VERSION, DevinDesktopSessionAdapter, CandidateExtractionService, GENERIC_ADAPTER_VERSION, GenericSessionInterchangeAdapter, IncrementalSessionImporter, ImportLeaseContentionError, FilesystemMemoryDestination, FilesystemPromotionDispositionCoordinator, MemoryPromotionGateway, SESSION_CONTRACT_VERSION, SESSION_PROVIDER_IDS, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, defaultDiscoveryManifestPath, discoverWorkspaceHistories, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, } from '../../sessions/index.js';
|
|
4
|
+
import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, CODEX_ADAPTER_VERSION, CodexSessionAdapter, COPILOT_ADAPTER_VERSION, CopilotSessionAdapter, CURSOR_ADAPTER_VERSION, CursorSessionAdapter, FACTORY_ADAPTER_VERSION, FactorySessionAdapter, HERMES_ADAPTER_VERSION, HermesSessionAdapter, OPENCODE_ADAPTER_VERSION, OpenCodeSessionAdapter, OPENCLAW_ADAPTER_VERSION, OpenClawSessionAdapter, OPENHUMAN_ADAPTER_VERSION, OpenHumanSessionAdapter, PI_ADAPTER_VERSION, PiSessionAdapter, DEEPSEEK_HARNESS_ADAPTER_VERSION, DeepSeekHarnessSessionAdapter, OmpSessionAdapter, OMP_ADAPTER_VERSION, WARP_ADAPTER_VERSION, WarpSessionAdapter, DEVIN_DESKTOP_ADAPTER_VERSION, DevinDesktopSessionAdapter, CandidateExtractionService, GENERIC_ADAPTER_VERSION, GenericSessionInterchangeAdapter, IncrementalSessionImporter, ImportLeaseContentionError, FilesystemMemoryDestination, FilesystemPromotionDispositionCoordinator, MemoryPromotionGateway, SESSION_CONTRACT_VERSION, SESSION_PROVIDER_IDS, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, defaultDiscoveryManifestPath, discoverWorkspaceHistories, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, } from '../../sessions/index.js';
|
|
5
5
|
const JSON_CONTRACT_VERSION = '1.0.0';
|
|
6
6
|
async function createLineMemoryPromotionDestination(projectRoot, manifestPath) {
|
|
7
7
|
const modulePath = resolve(dirname(manifestPath), 'commands', 'line-memory.mjs');
|
|
@@ -55,6 +55,7 @@ Options:
|
|
|
55
55
|
--provider-home <path> Override the provider home root (testing/portable homes)
|
|
56
56
|
--codex-root <path> Explicitly authorize a shared Codex sessions/export root
|
|
57
57
|
--omp-root <path> Explicitly authorize an OMP profile sessions root
|
|
58
|
+
--dsh-root <path> Explicitly authorize a DeepSeek Harness sessions root
|
|
58
59
|
--confirm, --yes Confirm a persistent discovered batch import
|
|
59
60
|
--lock-wait-ms <n> Maximum import-lease wait (default 5000)
|
|
60
61
|
--inactivity-threshold <duration> Historical inactivity threshold (default 24h)
|
|
@@ -63,13 +64,39 @@ Options:
|
|
|
63
64
|
--consumer <id> Select a named memory consumer for promotion
|
|
64
65
|
--workspace <id>, --tag <tag>, --limit <n>, --cursor <n>
|
|
65
66
|
--page-size <n> Extraction scan page size (default 250, maximum 500)
|
|
66
|
-
--max-documents <n> Explicit extraction safety limit; returns a partial receipt
|
|
67
|
+
--max-documents <n> Explicit extraction safety limit; returns a partial receipt
|
|
68
|
+
|
|
69
|
+
Search filters:
|
|
70
|
+
--date-from <rfc3339>, --date-to <rfc3339>
|
|
71
|
+
--participant <actor>, --model <id>, --role <role>, --tool <name>
|
|
72
|
+
--entity <entity>, --sensitivity <class>, --extraction-state <state>
|
|
73
|
+
--control-events exclude|include|only (default: exclude)
|
|
74
|
+
Query syntax: FTS5 terms, quoted phrases, prefixes, AND/OR/NOT
|
|
75
|
+
Follow the opaque nextCursor with the same query and filters
|
|
76
|
+
|
|
77
|
+
Analytics / forensics:
|
|
78
|
+
--session <id>, --date-from <rfc3339>, --date-to <rfc3339>
|
|
79
|
+
--actor <id>, --participant <id>, --tool <name>, --status <status>
|
|
80
|
+
--provider <id>, --tag <tag>, --sensitivity <class>, --extraction-state <state>
|
|
81
|
+
--group-by tool|session|provider, --limit <1..5000>
|
|
82
|
+
--authorize-forensics Required for each authorized forensic invocation
|
|
83
|
+
--markdown Render a sanitized forensic timeline table`;
|
|
84
|
+
function printHelp(ctx, exitCode = EXIT.ok) {
|
|
85
|
+
if (ctx.args.includes('--json'))
|
|
86
|
+
emit(envelope('sessions.help', 'ok', { usage: HELP }, null));
|
|
87
|
+
else
|
|
88
|
+
console.log(HELP);
|
|
89
|
+
return { exitCode };
|
|
90
|
+
}
|
|
67
91
|
export const sessionsHandler = {
|
|
68
92
|
id: 'sessions',
|
|
69
93
|
name: 'Sessions',
|
|
70
94
|
description: 'Manage the normalized session catalog (the singular `session` command remains the launcher)',
|
|
71
95
|
category: 'project',
|
|
72
96
|
aliases: [],
|
|
97
|
+
async help(ctx) {
|
|
98
|
+
return printHelp(ctx);
|
|
99
|
+
},
|
|
73
100
|
async execute(ctx) {
|
|
74
101
|
const json = ctx.args.includes('--json');
|
|
75
102
|
let parsed;
|
|
@@ -86,11 +113,8 @@ export const sessionsHandler = {
|
|
|
86
113
|
return { exitCode: normalized.exitCode, message: normalized.error.message };
|
|
87
114
|
}
|
|
88
115
|
if (!parsed.command || parsed.flags.has('--help') || parsed.flags.has('-h')) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
else
|
|
92
|
-
console.log(HELP);
|
|
93
|
-
return { exitCode: parsed.command ? EXIT.ok : EXIT.usage };
|
|
116
|
+
const explicitHelp = parsed.flags.has('--help') || parsed.flags.has('-h');
|
|
117
|
+
return printHelp(ctx, explicitHelp ? EXIT.ok : EXIT.usage);
|
|
94
118
|
}
|
|
95
119
|
try {
|
|
96
120
|
const result = await executeCommand(ctx, parsed);
|
|
@@ -623,7 +647,7 @@ async function importSource(ctx, args) {
|
|
|
623
647
|
if (provider !== 'generic' && provider !== 'claude' && provider !== 'codex'
|
|
624
648
|
&& provider !== 'copilot' && provider !== 'cursor' && provider !== 'factory'
|
|
625
649
|
&& provider !== 'hermes' && provider !== 'opencode' && provider !== 'openclaw'
|
|
626
|
-
&& provider !== 'openhuman' && provider !== 'pi' && provider !== 'omp' && provider !== 'warp' && provider !== 'devin-desktop') {
|
|
650
|
+
&& provider !== 'openhuman' && provider !== 'pi' && provider !== 'omp' && provider !== 'deepseek-harness' && provider !== 'warp' && provider !== 'devin-desktop') {
|
|
627
651
|
throw new CliError('UNSUPPORTED_OPERATION', `session import is not implemented for ${provider}`, EXIT.unsupported);
|
|
628
652
|
}
|
|
629
653
|
const sourceId = requiredValue(args, '--source-id');
|
|
@@ -641,9 +665,10 @@ async function importSource(ctx, args) {
|
|
|
641
665
|
const isOpenHuman = provider === 'openhuman';
|
|
642
666
|
const isPi = provider === 'pi';
|
|
643
667
|
const isOmp = provider === 'omp';
|
|
668
|
+
const isDsh = provider === 'deepseek-harness';
|
|
644
669
|
const isWarp = provider === 'warp';
|
|
645
670
|
const isDevinDesktop = provider === 'devin-desktop';
|
|
646
|
-
const adapter = isOmp ? new OmpSessionAdapter() : isClaude
|
|
671
|
+
const adapter = isDsh ? new DeepSeekHarnessSessionAdapter() : isOmp ? new OmpSessionAdapter() : isClaude
|
|
647
672
|
? new ClaudeSessionAdapter()
|
|
648
673
|
: isCodex
|
|
649
674
|
? new CodexSessionAdapter()
|
|
@@ -668,7 +693,7 @@ async function importSource(ctx, args) {
|
|
|
668
693
|
: isDevinDesktop
|
|
669
694
|
? new DevinDesktopSessionAdapter()
|
|
670
695
|
: new GenericSessionInterchangeAdapter();
|
|
671
|
-
const locatorClass = isOmp ? 'omp-session-v3-jsonl' : isClaude
|
|
696
|
+
const locatorClass = isDsh ? 'deepseek-harness-session-v2-jsonl' : isOmp ? 'omp-session-v3-jsonl' : isClaude
|
|
672
697
|
? (input.endsWith('.hooks.jsonl') ? 'claude-hook-jsonl' : 'claude-transcript-jsonl')
|
|
673
698
|
: isCodex
|
|
674
699
|
? (input.endsWith('.app-server.jsonl') ? 'codex-app-server-jsonl' : 'codex-rollout-jsonl')
|
|
@@ -700,7 +725,7 @@ async function importSource(ctx, args) {
|
|
|
700
725
|
const probe = await adapter.inspect(selectedSource);
|
|
701
726
|
const source = SessionSourceSchema.parse({
|
|
702
727
|
contractVersion: SESSION_CONTRACT_VERSION, sourceId, provider,
|
|
703
|
-
providerProfile: isOmp ? 'native-title-slot-v3' : isClaude
|
|
728
|
+
providerProfile: isDsh ? 'native-session-v2-jsonl' : isOmp ? 'native-title-slot-v3' : isClaude
|
|
704
729
|
? 'documented-local-jsonl'
|
|
705
730
|
: isCodex
|
|
706
731
|
? 'app-server-v2-rollout-fallback'
|
|
@@ -724,7 +749,7 @@ async function importSource(ctx, args) {
|
|
|
724
749
|
? 'opt-in-cascade-transcript-hook'
|
|
725
750
|
: 'manual-interchange',
|
|
726
751
|
locatorClass, redactedLocator: redactSourceLocator(input),
|
|
727
|
-
adapterVersion: isOmp ? OMP_ADAPTER_VERSION : isClaude
|
|
752
|
+
adapterVersion: isDsh ? DEEPSEEK_HARNESS_ADAPTER_VERSION : isOmp ? OMP_ADAPTER_VERSION : isClaude
|
|
728
753
|
? CLAUDE_ADAPTER_VERSION
|
|
729
754
|
: isCodex
|
|
730
755
|
? CODEX_ADAPTER_VERSION
|
|
@@ -751,11 +776,11 @@ async function importSource(ctx, args) {
|
|
|
751
776
|
disposition: isWarp
|
|
752
777
|
? 'manual-only'
|
|
753
778
|
: isClaude || isCodex || isCopilot || isCursor || isFactory || isHermes
|
|
754
|
-
|| isOpenCode || isOpenClaw || isOpenHuman || isDevinDesktop || isOmp
|
|
779
|
+
|| isOpenCode || isOpenClaw || isOpenHuman || isDevinDesktop || isOmp || isDsh || isPi
|
|
755
780
|
? 'implemented' : 'manual-only',
|
|
756
781
|
operationalState: probe.operationalState,
|
|
757
782
|
consistency: probe.consistency, authorizedAt: new Date().toISOString(),
|
|
758
|
-
extensions: isOmp ? { 'native.omp': {} } : isClaude
|
|
783
|
+
extensions: isDsh ? { 'native.deepseek-harness': {} } : isOmp ? { 'native.omp': {} } : isClaude
|
|
759
784
|
? { 'native.claude': {} }
|
|
760
785
|
: isCodex
|
|
761
786
|
? { 'native.codex': {} }
|
|
@@ -821,6 +846,8 @@ async function discoverWorkspace(ctx, args) {
|
|
|
821
846
|
: undefined,
|
|
822
847
|
ompRoot: args.values.has('--omp-root')
|
|
823
848
|
? resolve(ctx.cwd, args.values.get('--omp-root')) : undefined,
|
|
849
|
+
dshRoot: args.values.has('--dsh-root')
|
|
850
|
+
? resolve(ctx.cwd, args.values.get('--dsh-root')) : undefined,
|
|
824
851
|
codexRoot: args.values.has('--codex-root')
|
|
825
852
|
? resolve(ctx.cwd, args.values.get('--codex-root'))
|
|
826
853
|
: undefined,
|
|
@@ -1029,6 +1056,19 @@ function providerDisposition(provider) {
|
|
|
1029
1056
|
},
|
|
1030
1057
|
};
|
|
1031
1058
|
}
|
|
1059
|
+
if (provider === 'deepseek-harness') {
|
|
1060
|
+
return {
|
|
1061
|
+
provider, disposition: 'implemented', operationalState: 'available',
|
|
1062
|
+
supportedOperations: ['discover', 'inspect', 'stream'], acquisitionModes: ['jsonl'],
|
|
1063
|
+
reasonCode: null,
|
|
1064
|
+
remediation: 'Authorize an explicit DeepSeek Harness raw JSONL sessions root. Compressed .zstd histories must be exported as raw JSONL first.',
|
|
1065
|
+
evidence: {
|
|
1066
|
+
adapterVersion: DEEPSEEK_HARNESS_ADAPTER_VERSION,
|
|
1067
|
+
verifiedAt: '2026-09-05',
|
|
1068
|
+
documentation: 'https://github.com/deepseek-ai/deepseek-harness/tree/main/packages/session/session-persistence-jsonl',
|
|
1069
|
+
},
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1032
1072
|
if (provider === 'pi') {
|
|
1033
1073
|
return {
|
|
1034
1074
|
provider, disposition: 'implemented', operationalState: 'available',
|
|
@@ -1138,7 +1178,7 @@ function parseArgs(argv) {
|
|
|
1138
1178
|
'--entity', '--sensitivity', '--extraction-state', '--page-size', '--max-documents',
|
|
1139
1179
|
'--state', '--reviewer', '--reason', '--policy-version', '--min-confidence',
|
|
1140
1180
|
'--consumer', '--actor-class', '--reason-code', '--dependent-action', '--basis',
|
|
1141
|
-
'--manifest', '--provider-home', '--codex-root', '--omp-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1181
|
+
'--manifest', '--provider-home', '--codex-root', '--omp-root', '--dsh-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1142
1182
|
'--inactivity-threshold',
|
|
1143
1183
|
'--control-events',
|
|
1144
1184
|
'--session', '--status', '--actor', '--group-by',
|
|
@@ -206,7 +206,7 @@ async function handleSteward(args, ctx) {
|
|
|
206
206
|
aiwg steward permissions migrate --apply Back up and atomically normalize config
|
|
207
207
|
|
|
208
208
|
Providers:
|
|
209
|
-
antigravity (agy), claude-code, codex, copilot, cursor, factory, opencode, pi, omp, warp, windsurf, hermes, openclaw
|
|
209
|
+
antigravity (agy), claude-code, codex, copilot, cursor, deepseek-harness (dsh), factory, opencode, pi, omp, warp, windsurf, hermes, openclaw
|
|
210
210
|
|
|
211
211
|
Features:
|
|
212
212
|
cron, agent_teams, tasks, mcp, behaviors, mission_control, daemon
|
|
@@ -173,6 +173,11 @@ export const catalogHandler = {
|
|
|
173
173
|
description: "Model catalog commands (list, info, search)",
|
|
174
174
|
category: "catalog",
|
|
175
175
|
aliases: [],
|
|
176
|
+
async help() {
|
|
177
|
+
const { printCatalogHelp } = await import("../../catalog/cli.mjs");
|
|
178
|
+
printCatalogHelp();
|
|
179
|
+
return { exitCode: 0 };
|
|
180
|
+
},
|
|
176
181
|
async execute(ctx) {
|
|
177
182
|
try {
|
|
178
183
|
// Dynamic import to avoid loading catalog dependencies unless needed
|
|
@@ -249,6 +249,36 @@ function resolveFrameworkDir(framework) {
|
|
|
249
249
|
* aiwg-dev is contributor-only tooling — not for end users.
|
|
250
250
|
*/
|
|
251
251
|
export const USE_ALL_DISALLOW = new Set(['aiwg-dev']);
|
|
252
|
+
/** Full-framework setup requires the corpus omitted by the lightweight CLI. */
|
|
253
|
+
async function bundledSetupPrerequisiteMessage(frameworkRoot) {
|
|
254
|
+
let packageName;
|
|
255
|
+
try {
|
|
256
|
+
packageName = JSON.parse(await fs.readFile(path.join(frameworkRoot, 'package.json'), 'utf8')).name;
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
// Embedded callers and source fixtures need not have package metadata.
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
if (packageName !== '@aiwg/cli')
|
|
263
|
+
return undefined;
|
|
264
|
+
const hasCorpus = (await Promise.all(['frameworks', 'addons'].map(async (kind) => {
|
|
265
|
+
try {
|
|
266
|
+
return (await fs.stat(path.join(frameworkRoot, 'agentic/code', kind))).isDirectory();
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}))).every(Boolean);
|
|
272
|
+
if (hasCorpus)
|
|
273
|
+
return undefined;
|
|
274
|
+
return [
|
|
275
|
+
'Bundled framework setup requires the full aiwg package. This @aiwg/cli installation does not include framework and addon sources.',
|
|
276
|
+
'Replace the lightweight global package, then rerun your setup command:',
|
|
277
|
+
' npm uninstall -g @aiwg/cli',
|
|
278
|
+
' npm install -g aiwg',
|
|
279
|
+
'@aiwg/cli can still query signed web resources and deploy external project-local bundles.',
|
|
280
|
+
].join('\n');
|
|
281
|
+
}
|
|
252
282
|
/**
|
|
253
283
|
* Discover all addon names from the filesystem, minus the disallow list.
|
|
254
284
|
*/
|
|
@@ -2306,6 +2336,13 @@ export class UseHandler {
|
|
|
2306
2336
|
if (framework === 'cockpit') {
|
|
2307
2337
|
return installCockpit(ctx, remainingArgs);
|
|
2308
2338
|
}
|
|
2339
|
+
// Check before auto-init, global staging, or deployment can alter a project.
|
|
2340
|
+
// Web lookup does not materialize the corpus required by bundled setup.
|
|
2341
|
+
if (VALID_FRAMEWORKS.includes(framework)) {
|
|
2342
|
+
const prerequisite = await bundledSetupPrerequisiteMessage(ctx.frameworkRoot || await getFrameworkRoot());
|
|
2343
|
+
if (prerequisite)
|
|
2344
|
+
return { exitCode: 1, message: prerequisite };
|
|
2345
|
+
}
|
|
2309
2346
|
// Structured logger for this invocation. Records go to both stderr (if
|
|
2310
2347
|
// verbose level) and ~/.aiwg/logs/aiwg-YYYY-MM-DD.jsonl with full
|
|
2311
2348
|
// provenance (invocation_id, aiwg_version, git_sha, etc.). #925.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { WriterProfileStore } from '../../writing/writer-profile-store.js';
|
|
4
|
+
import { compileWriterProfile, exportWriterProfile, inspectWriterProfile, revokeWriterSample } from '../../writing/writer-profile.js';
|
|
5
|
+
function argumentsFor(args) {
|
|
6
|
+
const positional = [];
|
|
7
|
+
const flags = {};
|
|
8
|
+
for (let i = 0; i < args.length; i++) {
|
|
9
|
+
const arg = args[i];
|
|
10
|
+
if (!arg.startsWith('--')) {
|
|
11
|
+
positional.push(arg);
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (!['--scope', '--output', '--revision', '--mode'].includes(arg) || flags[arg] !== undefined)
|
|
15
|
+
throw new Error('Unknown or duplicate writer-profile option');
|
|
16
|
+
const value = args[++i];
|
|
17
|
+
if (!value || value.startsWith('--'))
|
|
18
|
+
throw new Error('Missing writer-profile option value');
|
|
19
|
+
flags[arg] = value;
|
|
20
|
+
}
|
|
21
|
+
const scope = flags['--scope'] ?? 'project';
|
|
22
|
+
if (scope !== 'project' && scope !== 'user')
|
|
23
|
+
throw new Error('Scope must be project or user');
|
|
24
|
+
return { positional, flags, scope };
|
|
25
|
+
}
|
|
26
|
+
async function execute(ctx) {
|
|
27
|
+
const { positional: [action, id, extra, ...rest], flags, scope } = argumentsFor(ctx.args);
|
|
28
|
+
if (rest.length)
|
|
29
|
+
throw new Error('Too many writer-profile arguments');
|
|
30
|
+
const store = new WriterProfileStore({ cwd: ctx.cwd, scope });
|
|
31
|
+
let result;
|
|
32
|
+
const revision = () => {
|
|
33
|
+
const raw = flags['--revision'];
|
|
34
|
+
if (raw === undefined || !/^(0|[1-9]\d*)$/.test(raw) || !Number.isSafeInteger(Number(raw)))
|
|
35
|
+
throw new Error('A nonnegative --revision is required');
|
|
36
|
+
return Number(raw);
|
|
37
|
+
};
|
|
38
|
+
const destination = () => {
|
|
39
|
+
if (!flags['--output'])
|
|
40
|
+
throw new Error('--output is required; profile content is never printed');
|
|
41
|
+
return path.resolve(ctx.cwd, flags['--output']);
|
|
42
|
+
};
|
|
43
|
+
if (ctx.dryRun)
|
|
44
|
+
return { exitCode: 1, message: 'writer-profile does not support dry-run; use inspect before changing a profile' };
|
|
45
|
+
if (action === 'list' && !id)
|
|
46
|
+
result = await store.list();
|
|
47
|
+
else if (action === 'import' && id && !extra) {
|
|
48
|
+
const input = JSON.parse(await readFile(path.resolve(ctx.cwd, id), 'utf8'));
|
|
49
|
+
result = inspectWriterProfile(await store.save(input, revision()));
|
|
50
|
+
}
|
|
51
|
+
else if (action === 'inspect' && id && !extra)
|
|
52
|
+
result = inspectWriterProfile(await store.read(id));
|
|
53
|
+
else if (action === 'version' && id && !extra) {
|
|
54
|
+
const profile = await store.read(id);
|
|
55
|
+
result = { schemaVersion: profile.schemaVersion, version: profile.version, revision: profile.revision };
|
|
56
|
+
}
|
|
57
|
+
else if (action === 'delete' && id && !extra) {
|
|
58
|
+
await store.delete(id, revision());
|
|
59
|
+
result = { deleted: true };
|
|
60
|
+
}
|
|
61
|
+
else if (action === 'revoke' && id && extra) {
|
|
62
|
+
const profile = await store.read(id);
|
|
63
|
+
result = inspectWriterProfile(await store.save(revokeWriterSample(profile, extra), revision()));
|
|
64
|
+
}
|
|
65
|
+
else if ((action === 'export' || action === 'compile') && id && !extra) {
|
|
66
|
+
const file = destination();
|
|
67
|
+
const profile = await store.read(id);
|
|
68
|
+
let output;
|
|
69
|
+
if (action === 'compile') {
|
|
70
|
+
const compiled = compileWriterProfile(profile);
|
|
71
|
+
output = compiled.profile;
|
|
72
|
+
result = { written: true, fallback: compiled.fallback, diagnostics: compiled.diagnostics, activated: false };
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const mode = flags['--mode'] ?? 'shared';
|
|
76
|
+
if (mode !== 'shared' && mode !== 'private')
|
|
77
|
+
throw new Error('Export mode must be shared or private');
|
|
78
|
+
output = exportWriterProfile(profile, mode);
|
|
79
|
+
result = { written: true, mode };
|
|
80
|
+
}
|
|
81
|
+
await writeFile(file, JSON.stringify(output, null, 2) + '\n', { mode: 0o600, flag: 'wx' });
|
|
82
|
+
}
|
|
83
|
+
else
|
|
84
|
+
throw new Error('Invalid writer-profile command; see aiwg writer-profile --help');
|
|
85
|
+
return { exitCode: 0, rawOutput: true, message: JSON.stringify(result, null, 2) };
|
|
86
|
+
}
|
|
87
|
+
export const writerProfileHandler = {
|
|
88
|
+
id: 'writer-profile', name: 'Writer Profiles', description: 'Manage opt-in author-controlled writer profile sidecars', category: 'project', aliases: [],
|
|
89
|
+
async help() {
|
|
90
|
+
return { exitCode: 0, rawOutput: true, message: [
|
|
91
|
+
'aiwg writer-profile list|inspect <id>|version <id> [--scope project|user]',
|
|
92
|
+
'aiwg writer-profile import <sidecar.json> --revision 0 [--scope project|user]',
|
|
93
|
+
'aiwg writer-profile import <updated.json> --revision <current> [--scope project|user]',
|
|
94
|
+
'aiwg writer-profile export <id> --output <new-file> [--mode shared|private] [--scope project|user]',
|
|
95
|
+
'aiwg writer-profile compile <id> --output <new-file> [--scope project|user]',
|
|
96
|
+
'aiwg writer-profile revoke <id> <sample-id> --revision <current> [--scope project|user]',
|
|
97
|
+
'aiwg writer-profile delete <id> --revision <current> [--scope project|user]',
|
|
98
|
+
'Import and compile do not select an output mode. Export destinations must not exist.',
|
|
99
|
+
].join('\n') };
|
|
100
|
+
},
|
|
101
|
+
async execute(ctx) {
|
|
102
|
+
try {
|
|
103
|
+
return await execute(ctx);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return { exitCode: 1, message: 'Writer profile operation failed. Check the command, schema, file permissions and current revision; sample content is omitted.' };
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=writer-profile.js.map
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { parseWritingBrief, prepareWritingBrief, applyProofreadCorrections, writingBriefHash } from '../../writing/writing-brief.js';
|
|
5
|
+
import { assessWritingFidelity } from '../../writing/fidelity.js';
|
|
6
|
+
import { WriterProfileStore } from '../../writing/writer-profile-store.js';
|
|
7
|
+
import { compileWriterProfile } from '../../writing/writer-profile.js';
|
|
8
|
+
import { createWritingReceipt, writeWritingReceipt } from '../../writing/writing-receipt.js';
|
|
9
|
+
import { resolveOutputModes } from '../../output-modes/registry.js';
|
|
10
|
+
import { resolveProjectAiwgDirForWrite } from '../../config/project-artifacts.js';
|
|
11
|
+
import { readAiwgConfig } from '../../config/aiwg-config.js';
|
|
12
|
+
import { resolveArtifactOutputs, recordArtifactOutputProvenance } from '../../artifacts/output-policy.js';
|
|
13
|
+
async function execute(ctx) {
|
|
14
|
+
const [action, ...args] = ctx.args;
|
|
15
|
+
if (!['plan', 'proofread'].includes(action))
|
|
16
|
+
throw new Error('Expected writing plan or proofread');
|
|
17
|
+
const flags = {};
|
|
18
|
+
const corrections = [];
|
|
19
|
+
for (let index = 0; index < args.length; index++) {
|
|
20
|
+
const key = args[index], value = args[++index];
|
|
21
|
+
if (!['--brief', '--profile', '--channel', '--output', '--correction'].includes(key) || !value || value.startsWith('--'))
|
|
22
|
+
throw new Error('Invalid writing command option');
|
|
23
|
+
if (key === '--correction')
|
|
24
|
+
corrections.push(value);
|
|
25
|
+
else {
|
|
26
|
+
if (flags[key])
|
|
27
|
+
throw new Error('Duplicate writing command option');
|
|
28
|
+
flags[key] = value;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (!flags['--brief'] || !flags['--profile'])
|
|
32
|
+
throw new Error('--brief and --profile are required');
|
|
33
|
+
const channel = flags['--channel'] ?? 'engineering';
|
|
34
|
+
if (!['article', 'social', 'email', 'engineering', 'conversation'].includes(channel))
|
|
35
|
+
throw new Error('Unknown writing channel');
|
|
36
|
+
const brief = parseWritingBrief(JSON.parse(await readFile(path.resolve(ctx.cwd, flags['--brief']), 'utf8')));
|
|
37
|
+
const resolved = await resolveOutputModes(ctx.cwd, ctx.frameworkRoot, [`writer-${flags['--profile']}`]);
|
|
38
|
+
const selected = resolved.modes.find(mode => mode.id === `writer-${flags['--profile']}`);
|
|
39
|
+
if (!selected || !['project', 'user'].includes(selected.source))
|
|
40
|
+
throw new Error('A stored writer sidecar is required');
|
|
41
|
+
const profile = await new WriterProfileStore({ cwd: ctx.cwd, scope: selected.source }).read(flags['--profile']);
|
|
42
|
+
const compiled = compileWriterProfile(profile);
|
|
43
|
+
let selectedCorrections = [];
|
|
44
|
+
let output;
|
|
45
|
+
let extension;
|
|
46
|
+
let validators;
|
|
47
|
+
if (action === 'plan') {
|
|
48
|
+
if (corrections.length)
|
|
49
|
+
throw new Error('Correction selection is only valid for proofreading');
|
|
50
|
+
output = JSON.stringify(prepareWritingBrief(brief, { profileId: profile.id, channel: channel }), null, 2) + '\n';
|
|
51
|
+
extension = 'json';
|
|
52
|
+
validators = [{ id: 'writing-brief-schema', version: '1', outcome: 'pass' }];
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
if (brief.operation !== 'proofread-only')
|
|
56
|
+
throw new Error('Proofreading requires a proofread-only brief');
|
|
57
|
+
selectedCorrections = corrections.length ? corrections : brief.permissions.corrections.map(correction => correction.id);
|
|
58
|
+
const result = applyProofreadCorrections(brief, selectedCorrections);
|
|
59
|
+
if (!result.valid)
|
|
60
|
+
throw new Error('Authorized corrections require review');
|
|
61
|
+
const original = brief.inputs.find(input => input.id === brief.sourceInputId).text;
|
|
62
|
+
const selectedBrief = { ...brief, permissions: { ...brief.permissions, corrections: brief.permissions.corrections.filter(correction => selectedCorrections.includes(correction.id)) } };
|
|
63
|
+
const fidelity = assessWritingFidelity(original, result.text, selectedBrief);
|
|
64
|
+
if (fidelity.outcome === 'fail')
|
|
65
|
+
throw new Error('Proofreading fidelity guard rejected the result');
|
|
66
|
+
output = result.text;
|
|
67
|
+
extension = 'txt';
|
|
68
|
+
validators = [{ id: 'authorized-proofread-corrections', version: '1', outcome: 'pass' }];
|
|
69
|
+
if (fidelity.outcome === 'pass')
|
|
70
|
+
validators.push({ id: 'conservative-literal-review', version: '1', outcome: 'pass' });
|
|
71
|
+
}
|
|
72
|
+
const config = await readAiwgConfig(ctx.cwd);
|
|
73
|
+
const destinations = resolveArtifactOutputs({ project: config?.artifact_outputs, supportedDestinations: ['local-file'], explicitDestinations: flags['--output'] ? ['local-file'] : [] });
|
|
74
|
+
if (flags['--output'] && !destinations.presentations.includes('local-file'))
|
|
75
|
+
throw new Error('Local presentation export is disabled by project artifact policy');
|
|
76
|
+
if (ctx.dryRun)
|
|
77
|
+
return { exitCode: 0, rawOutput: true, message: JSON.stringify({ valid: true, action, writes: false, selected: resolved.modes.map(mode => mode.id), modelExecution: 'none' }) };
|
|
78
|
+
const id = `wr-${randomUUID()}`;
|
|
79
|
+
const root = resolveProjectAiwgDirForWrite(ctx.cwd);
|
|
80
|
+
const canonical = path.join(root, 'writing', 'outputs', `${id}.${extension}`);
|
|
81
|
+
const receipt = createWritingReceipt({
|
|
82
|
+
id, operation: brief.operation,
|
|
83
|
+
profile: { id: profile.id, version: profile.version, revision: profile.revision, cacheEpoch: profile.cacheEpoch, compiledModeSha256: writingBriefHash(JSON.stringify(compiled.profile)), fallback: compiled.fallback },
|
|
84
|
+
modes: resolved.modes.map(({ source: _source, sourcePath: _sourcePath, scope: _scope, ...mode }) => ({ id: mode.id, version: mode.version, profileSha256: writingBriefHash(JSON.stringify(mode)) })),
|
|
85
|
+
state: { selected: resolved.modes.map(mode => mode.id), delivered: [], applied: [], validated: [], deliveredTo: 'none', fallback: 'none' },
|
|
86
|
+
operationConfig: { action: action, correctionIds: selectedCorrections, channel: channel },
|
|
87
|
+
modelPrompt: { execution: 'none', promptSha256: writingBriefHash(JSON.stringify(brief)) },
|
|
88
|
+
inputs: [{ id: 'brief', role: 'brief', sha256: writingBriefHash(JSON.stringify(brief)) }, ...brief.inputs.map(input => ({ id: `input-${writingBriefHash(input.id)}`, role: input.kind, sha256: input.sha256 }))],
|
|
89
|
+
output: { sha256: writingBriefHash(output), path: canonical },
|
|
90
|
+
budget: { limit: 0, used: 0, unit: 'tokens', measurement: 'exact', tokenizerId: 'no-model-call', tokenizerVersion: '1' },
|
|
91
|
+
fallback: { applied: false }, validators, authorAcceptance: { status: 'pending' },
|
|
92
|
+
});
|
|
93
|
+
await mkdir(path.dirname(canonical), { recursive: true, mode: 0o700 });
|
|
94
|
+
await writeFile(canonical, output, { flag: 'wx', mode: 0o600 });
|
|
95
|
+
const recorded = await writeWritingReceipt(ctx.cwd, receipt);
|
|
96
|
+
let presentation;
|
|
97
|
+
if (flags['--output']) {
|
|
98
|
+
presentation = path.resolve(ctx.cwd, flags['--output']);
|
|
99
|
+
await writeFile(presentation, output, { flag: 'wx', mode: 0o600 });
|
|
100
|
+
await recordArtifactOutputProvenance(root, { canonicalPath: canonical, presentationDestination: 'local-file', presentationReference: presentation, authority: 'explicit-task' });
|
|
101
|
+
}
|
|
102
|
+
return { exitCode: 0, rawOutput: true, message: JSON.stringify({ canonical, receipt: recorded.path, presentation, action, selected: resolved.modes.map(mode => mode.id), appliedModes: [], modelExecution: 'none', publicationApproval: false }) };
|
|
103
|
+
}
|
|
104
|
+
export const writingHandler = {
|
|
105
|
+
id: 'writing', name: 'Writing', description: 'Prepare grounded writing plans and apply authorized proofreading corrections', category: 'project', aliases: [],
|
|
106
|
+
async help() {
|
|
107
|
+
return { exitCode: 0, rawOutput: true, message: [
|
|
108
|
+
'aiwg writing plan --brief <brief.json> --profile <id> [--channel article|social|email|engineering|conversation] [--output <new-file>]',
|
|
109
|
+
'aiwg writing proofread --brief <brief.json> --profile <id> [--correction <id>]... [--output <new-file>]',
|
|
110
|
+
'Proofreading applies listed author-authorized corrections (all by default), without a model or voice rewrite.',
|
|
111
|
+
'Canonical output and a receipt are written first. Optional local exports require a new file and project-policy allowance.',
|
|
112
|
+
'Mode selections are inspected; this command does not claim provider response interception or publication approval.',
|
|
113
|
+
].join('\n') };
|
|
114
|
+
},
|
|
115
|
+
async execute(ctx) { try {
|
|
116
|
+
return await execute(ctx);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return { exitCode: 1, message: 'Writing operation failed. Check the brief, profile, correction IDs, output destination and artifact policy. Private source text is omitted; any completed canonical artifacts remain available.' };
|
|
120
|
+
} },
|
|
121
|
+
};
|
|
122
|
+
//# sourceMappingURL=writing.js.map
|
package/dist/src/cli/router.js
CHANGED
|
@@ -77,7 +77,11 @@ export function getHookRegistry() {
|
|
|
77
77
|
export async function run(args, options = {}) {
|
|
78
78
|
const started = process.hrtime.bigint();
|
|
79
79
|
const registry = await initRouter();
|
|
80
|
-
|
|
80
|
+
// Normalize `help <command>` into the same non-executing help path.
|
|
81
|
+
const routedArgs = args[0] === 'help' && args[1] && !args[1].startsWith('-')
|
|
82
|
+
? [args[1], ...args.slice(2), '--help']
|
|
83
|
+
: args;
|
|
84
|
+
const [rawCommand, ...commandArgs] = routedArgs;
|
|
81
85
|
// No command - show help
|
|
82
86
|
if (!rawCommand) {
|
|
83
87
|
const helpHandler = registry.handlerMap.get('help');
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { homedir } from 'os';
|
|
9
|
-
import { existsSync, readFileSync } from 'fs';
|
|
9
|
+
import { existsSync, readFileSync, statSync } from 'fs';
|
|
10
10
|
import { isAbsolute, join, resolve } from 'path';
|
|
11
11
|
|
|
12
12
|
export const DEFAULT_PROJECT_AIWG_DIR = '.aiwg';
|
|
@@ -75,10 +75,42 @@ export function resolveProjectControlDir(projectDir) {
|
|
|
75
75
|
return resolve(projectDir, DEFAULT_PROJECT_AIWG_DIR);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
export function isProjectArtifactRootExternal(projectDir, env = process.env) {
|
|
79
|
+
return resolve(resolveProjectAiwgDir(projectDir, env)) !== resolve(resolveProjectControlDir(projectDir));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Resolve an artifact root for a payload write. Default local mode may create
|
|
84
|
+
* `.aiwg`; an explicitly external root must already be mounted/attached so a
|
|
85
|
+
* disconnected mount cannot be silently replaced by a new local directory.
|
|
86
|
+
*/
|
|
87
|
+
export function resolveProjectAiwgDirForWrite(projectDir, env = process.env) {
|
|
88
|
+
const artifactRoot = resolveProjectAiwgDir(projectDir, env);
|
|
89
|
+
if (isProjectArtifactRootExternal(projectDir, env)) {
|
|
90
|
+
let available = false;
|
|
91
|
+
try {
|
|
92
|
+
available = existsSync(artifactRoot) && statSync(artifactRoot).isDirectory();
|
|
93
|
+
} catch {
|
|
94
|
+
available = false;
|
|
95
|
+
}
|
|
96
|
+
if (!available) {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Configured external AIWG artifact root is unavailable: ${artifactRoot}. ` +
|
|
99
|
+
'Reconnect or attach the external corpus; AIWG will not fall back to repository-local .aiwg payload.',
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return artifactRoot;
|
|
104
|
+
}
|
|
105
|
+
|
|
78
106
|
export function projectAiwgPath(projectDir, ...segments) {
|
|
79
107
|
return join(resolveProjectAiwgDir(projectDir), ...segments);
|
|
80
108
|
}
|
|
81
109
|
|
|
110
|
+
export function projectAiwgWritePath(projectDir, ...segments) {
|
|
111
|
+
return join(resolveProjectAiwgDirForWrite(projectDir), ...segments);
|
|
112
|
+
}
|
|
113
|
+
|
|
82
114
|
export function projectControlPath(projectDir, ...segments) {
|
|
83
115
|
return join(resolveProjectControlDir(projectDir), ...segments);
|
|
84
116
|
}
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* override for the project-local `.aiwg/` artifact root. Keep that contract
|
|
6
6
|
* centralized so callers do not hardcode `<project>/.aiwg`.
|
|
7
7
|
*/
|
|
8
|
-
export { AIWG_ARTIFACTS_PATH_ENV, DEFAULT_PROJECT_AIWG_DIR, PROJECT_AIWG_LOCATION_FILE, expandProjectArtifactPath, parseProjectArtifactLocation, projectAiwgPath, projectControlPath, readProjectArtifactLocation, resolveProjectAiwgDir, resolveProjectControlDir, } from './project-artifacts-runtime.mjs';
|
|
8
|
+
export { AIWG_ARTIFACTS_PATH_ENV, DEFAULT_PROJECT_AIWG_DIR, PROJECT_AIWG_LOCATION_FILE, expandProjectArtifactPath, parseProjectArtifactLocation, projectAiwgPath, projectAiwgWritePath, projectControlPath, readProjectArtifactLocation, resolveProjectAiwgDir, resolveProjectAiwgDirForWrite, resolveProjectControlDir, isProjectArtifactRootExternal, } from './project-artifacts-runtime.mjs';
|
|
9
9
|
export { PROJECT_CONTROL_PLANE_FILES, auditProjectArtifactHealth, } from './project-artifacts-health.mjs';
|
|
10
10
|
//# sourceMappingURL=project-artifacts.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { McpClientLike } from "../storage/backends/fortemi.js";
|
|
2
|
+
import { type FortemiDatasetRunReceipt } from "./fortemi-run-receipt.js";
|
|
3
|
+
export declare const FORTEMI_DATASET_EXECUTION_TOOL = "manage_dataset_execution";
|
|
4
|
+
export declare function fortemiDatasetRequestDigest(request: Record<string, unknown>): string;
|
|
5
|
+
/** MCP transport binding; receipt verification is implemented independently in AIWG. */
|
|
6
|
+
export declare class FortemiDatasetExecutionClient {
|
|
7
|
+
private readonly client;
|
|
8
|
+
private readonly runs;
|
|
9
|
+
constructor(client: McpClientLike);
|
|
10
|
+
private call;
|
|
11
|
+
capabilities(): Promise<Record<string, unknown>>;
|
|
12
|
+
preview(request: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
13
|
+
/** The caller must approve the exact digest returned by read-only preview. */
|
|
14
|
+
execute(request: Record<string, unknown>, approvedRequestDigest: string): Promise<FortemiDatasetRunReceipt>;
|
|
15
|
+
private verifyResult;
|
|
16
|
+
private knownRun;
|
|
17
|
+
retry(runId: string, action?: "retry" | "resume"): Promise<FortemiDatasetRunReceipt>;
|
|
18
|
+
status(runId: string): Promise<Record<string, unknown>>;
|
|
19
|
+
checkpoint(runId: string): Promise<Record<string, unknown>>;
|
|
20
|
+
cancel(runId: string): Promise<Record<string, unknown>>;
|
|
21
|
+
archive(runId: string): Promise<Record<string, unknown>>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=fortemi-dataset-execution.d.ts.map
|