@haaaiawd/second-nature 0.1.27 → 0.1.29
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/SKILL.md +35 -33
- package/agent-inner-guide.md +144 -124
- package/index.js +76 -1
- package/openclaw.plugin.json +2 -2
- package/package.json +2 -1
- package/runtime/cli/commands/connector-behavior.d.ts +20 -0
- package/runtime/cli/commands/connector-behavior.js +160 -0
- package/runtime/cli/commands/index.js +8 -0
- package/runtime/cli/index.js +9 -2
- package/runtime/cli/ops/manual-run-dispatcher.d.ts +79 -0
- package/runtime/cli/ops/manual-run-dispatcher.js +110 -0
- package/runtime/cli/ops/ops-router.d.ts +45 -4
- package/runtime/cli/ops/ops-router.js +543 -2
- package/runtime/cli/read-models/index.js +35 -18
- package/runtime/cli/read-models/types.d.ts +1 -0
- package/runtime/connectors/agent-network/agent-world/adapter.d.ts +1 -0
- package/runtime/connectors/agent-network/agent-world/adapter.js +2 -2
- package/runtime/connectors/base/contract.d.ts +4 -1
- package/runtime/connectors/base/contract.js +5 -1
- package/runtime/connectors/base/effect-commit-ledger-sqlite.d.ts +31 -0
- package/runtime/connectors/base/effect-commit-ledger-sqlite.js +86 -0
- package/runtime/connectors/base/failure-taxonomy.js +5 -0
- package/runtime/connectors/base/manifest-v7.d.ts +151 -0
- package/runtime/connectors/base/manifest-v7.js +170 -0
- package/runtime/connectors/base/manifest.d.ts +67 -77
- package/runtime/connectors/base/manifest.js +7 -7
- package/runtime/connectors/base/route-planner.js +11 -8
- package/runtime/connectors/base/structured-unavailable-reason.d.ts +59 -0
- package/runtime/connectors/base/structured-unavailable-reason.js +113 -0
- package/runtime/connectors/base/wet-probe-runner.d.ts +40 -0
- package/runtime/connectors/base/wet-probe-runner.js +132 -0
- package/runtime/connectors/manifest/manifest-schema.d.ts +4 -0
- package/runtime/connectors/manifest/manifest-schema.js +2 -0
- package/runtime/connectors/services/connector-executor-adapter.d.ts +1 -0
- package/runtime/connectors/services/connector-executor-adapter.js +132 -26
- package/runtime/core/second-nature/body/behavior-promotion/behavior-promotion-loop.d.ts +45 -0
- package/runtime/core/second-nature/body/behavior-promotion/behavior-promotion-loop.js +132 -0
- package/runtime/core/second-nature/body/circuit-breaker/circuit-breaker-manager.d.ts +60 -0
- package/runtime/core/second-nature/body/circuit-breaker/circuit-breaker-manager.js +174 -0
- package/runtime/core/second-nature/body/probe-signal-adapter.d.ts +38 -0
- package/runtime/core/second-nature/body/probe-signal-adapter.js +60 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-assembler.d.ts +51 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-assembler.js +129 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-context-scope.d.ts +30 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-context-scope.js +92 -0
- package/runtime/core/second-nature/body/tool-experience/experience-writer.d.ts +34 -0
- package/runtime/core/second-nature/body/tool-experience/experience-writer.js +67 -0
- package/runtime/core/second-nature/body/tool-experience/pain-signal-query.d.ts +37 -0
- package/runtime/core/second-nature/body/tool-experience/pain-signal-query.js +62 -0
- package/runtime/core/second-nature/heartbeat/decision-trace-emitter.d.ts +29 -0
- package/runtime/core/second-nature/heartbeat/decision-trace-emitter.js +28 -0
- package/runtime/core/second-nature/heartbeat/embodied-context-assembler.d.ts +54 -0
- package/runtime/core/second-nature/heartbeat/embodied-context-assembler.js +164 -0
- package/runtime/core/second-nature/heartbeat/goal-lifecycle-policy.d.ts +37 -0
- package/runtime/core/second-nature/heartbeat/goal-lifecycle-policy.js +61 -0
- package/runtime/core/second-nature/heartbeat/idle-curiosity-policy.d.ts +37 -0
- package/runtime/core/second-nature/heartbeat/idle-curiosity-policy.js +60 -0
- package/runtime/core/second-nature/heartbeat/index.d.ts +4 -0
- package/runtime/core/second-nature/heartbeat/index.js +5 -0
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle-v7.d.ts +63 -0
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle-v7.js +118 -0
- package/runtime/core/second-nature/orchestrator/downstream-intent-orchestrator.d.ts +41 -0
- package/runtime/core/second-nature/orchestrator/downstream-intent-orchestrator.js +43 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +2 -1
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +2 -0
- package/runtime/core/second-nature/orchestrator/hard-guard-evaluator.d.ts +31 -0
- package/runtime/core/second-nature/orchestrator/hard-guard-evaluator.js +102 -0
- package/runtime/core/second-nature/orchestrator/index.d.ts +5 -0
- package/runtime/core/second-nature/orchestrator/index.js +7 -0
- package/runtime/core/second-nature/quiet/claim-synthesizer.d.ts +53 -0
- package/runtime/core/second-nature/quiet/claim-synthesizer.js +153 -0
- package/runtime/core/second-nature/quiet/daily-diary-writer.d.ts +29 -0
- package/runtime/core/second-nature/quiet/daily-diary-writer.js +92 -0
- package/runtime/core/second-nature/quiet/index.d.ts +5 -0
- package/runtime/core/second-nature/quiet/index.js +5 -0
- package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +19 -12
- package/runtime/core/second-nature/types.d.ts +2 -0
- package/runtime/guidance/channel-feedback-ingestion-service.d.ts +88 -0
- package/runtime/guidance/channel-feedback-ingestion-service.js +231 -0
- package/runtime/guidance/guidance-draft-service.d.ts +60 -0
- package/runtime/guidance/guidance-draft-service.js +80 -0
- package/runtime/guidance/index.d.ts +3 -0
- package/runtime/guidance/index.js +3 -0
- package/runtime/guidance/outreach-draft-schema.d.ts +8 -8
- package/runtime/guidance/outreach-strategy-selector.d.ts +77 -0
- package/runtime/guidance/outreach-strategy-selector.js +211 -0
- package/runtime/observability/audit/append-only-audit-store.d.ts +20 -2
- package/runtime/observability/audit/append-only-audit-store.js +32 -6
- package/runtime/observability/audit/audit-envelope.d.ts +2 -1
- package/runtime/observability/audit/audit-envelope.js +8 -7
- package/runtime/observability/audit/audit-family-registry.json +66 -0
- package/runtime/observability/audit/family-registry.d.ts +43 -0
- package/runtime/observability/audit/family-registry.js +70 -0
- package/runtime/observability/index.d.ts +6 -1
- package/runtime/observability/index.js +6 -1
- package/runtime/observability/redaction/policy.d.ts +24 -3
- package/runtime/observability/redaction/policy.js +74 -0
- package/runtime/observability/services/heartbeat-digest-assembler.d.ts +152 -0
- package/runtime/observability/services/heartbeat-digest-assembler.js +248 -0
- package/runtime/observability/services/lived-experience-audit.js +6 -6
- package/runtime/observability/services/narrative-timeline-query-service.d.ts +136 -0
- package/runtime/observability/services/narrative-timeline-query-service.js +169 -0
- package/runtime/observability/services/restore-audit-service.d.ts +74 -0
- package/runtime/observability/services/restore-audit-service.js +79 -0
- package/runtime/observability/services/runtime-secret-anchor-view.d.ts +77 -0
- package/runtime/observability/services/runtime-secret-anchor-view.js +168 -0
- package/runtime/observability/services/self-health-snapshot.d.ts +92 -0
- package/runtime/observability/services/self-health-snapshot.js +251 -0
- package/runtime/shared/types/goal.d.ts +62 -0
- package/runtime/shared/types/goal.js +20 -0
- package/runtime/shared/types/index.d.ts +3 -0
- package/runtime/shared/types/index.js +3 -0
- package/runtime/shared/types/source-ref.d.ts +14 -0
- package/runtime/shared/types/source-ref.js +1 -0
- package/runtime/shared/types/v7-entities.d.ts +206 -0
- package/runtime/shared/types/v7-entities.js +27 -0
- package/runtime/storage/db/index.js +3 -0
- package/runtime/storage/db/migration-runner.d.ts +30 -0
- package/runtime/storage/db/migration-runner.js +93 -0
- package/runtime/storage/db/migrations/index.d.ts +5 -0
- package/runtime/storage/db/migrations/index.js +13 -0
- package/runtime/storage/db/migrations/v7-001-foundation.d.ts +13 -0
- package/runtime/storage/db/migrations/v7-001-foundation.js +144 -0
- package/runtime/storage/db/migrations/v7-002-effect-commit-ledger.d.ts +8 -0
- package/runtime/storage/db/migrations/v7-002-effect-commit-ledger.js +27 -0
- package/runtime/storage/db/migrations/v7-003-circuit-breaker.d.ts +7 -0
- package/runtime/storage/db/migrations/v7-003-circuit-breaker.js +26 -0
- package/runtime/storage/db/migrations/v7-004-behavior-promotion.d.ts +7 -0
- package/runtime/storage/db/migrations/v7-004-behavior-promotion.js +26 -0
- package/runtime/storage/db/schema/agent-goal.d.ts +38 -0
- package/runtime/storage/db/schema/agent-goal.js +2 -0
- package/runtime/storage/db/transaction-utils.d.ts +14 -0
- package/runtime/storage/db/transaction-utils.js +29 -0
- package/runtime/storage/db/write-queue.d.ts +38 -0
- package/runtime/storage/db/write-queue.js +97 -0
- package/runtime/storage/quiet/persist-quiet-artifact.js +2 -1
- package/runtime/storage/services/diary-dream-store.d.ts +35 -0
- package/runtime/storage/services/diary-dream-store.js +165 -0
- package/runtime/storage/services/embodied-context-state-port.d.ts +77 -0
- package/runtime/storage/services/embodied-context-state-port.js +115 -0
- package/runtime/storage/services/goal-lifecycle-store.d.ts +42 -0
- package/runtime/storage/services/goal-lifecycle-store.js +181 -0
- package/runtime/storage/services/history-digest-store.d.ts +33 -0
- package/runtime/storage/services/history-digest-store.js +140 -0
- package/runtime/storage/services/identity-profile-store.d.ts +25 -0
- package/runtime/storage/services/identity-profile-store.js +81 -0
- package/runtime/storage/services/interaction-snapshot-projector.d.ts +15 -0
- package/runtime/storage/services/interaction-snapshot-projector.js +35 -0
- package/runtime/storage/services/restore-snapshot-store.d.ts +52 -0
- package/runtime/storage/services/restore-snapshot-store.js +193 -0
- package/runtime/storage/services/runtime-secret-anchor-store.d.ts +26 -0
- package/runtime/storage/services/runtime-secret-anchor-store.js +82 -0
- package/runtime/storage/services/tool-experience-store.d.ts +25 -0
- package/runtime/storage/services/tool-experience-store.js +116 -0
- package/runtime/storage/services/write-validation-gate.d.ts +46 -0
- package/runtime/storage/services/write-validation-gate.js +200 -0
- package/workspace-ops-bridge.js +16 -1
|
@@ -55,19 +55,31 @@ function buildCredentialNextStep(status) {
|
|
|
55
55
|
return "verify_or_re_create_credential_then_re_import";
|
|
56
56
|
return undefined;
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
* T1.2.4: count persisted Quiet artifact JSON files under `.second-nature/quiet/{day}/`
|
|
60
|
-
* so `loadQuiet` / `loadDailyReport` can reflect Quiet artifacts in the read model.
|
|
61
|
-
*/
|
|
62
|
-
function countQuietArtifactsForDay(workspaceRoot, day) {
|
|
58
|
+
function classifyQuietArtifactsForDay(workspaceRoot, day) {
|
|
63
59
|
try {
|
|
64
60
|
const dir = path.join(workspaceRoot, ".second-nature", "quiet", day);
|
|
65
61
|
if (!fs.existsSync(dir))
|
|
66
|
-
return 0;
|
|
67
|
-
|
|
62
|
+
return { reportArtifacts: 0, emptyStateArtifacts: 0, totalArtifacts: 0 };
|
|
63
|
+
let reportArtifacts = 0;
|
|
64
|
+
let emptyStateArtifacts = 0;
|
|
65
|
+
let totalArtifacts = 0;
|
|
66
|
+
for (const file of fs.readdirSync(dir).filter((f) => f.endsWith(".json"))) {
|
|
67
|
+
totalArtifacts++;
|
|
68
|
+
try {
|
|
69
|
+
const raw = JSON.parse(fs.readFileSync(path.join(dir, file), "utf-8"));
|
|
70
|
+
if (raw.write?.kind === "empty_state")
|
|
71
|
+
emptyStateArtifacts++;
|
|
72
|
+
else
|
|
73
|
+
reportArtifacts++;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
reportArtifacts++;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { reportArtifacts, emptyStateArtifacts, totalArtifacts };
|
|
68
80
|
}
|
|
69
81
|
catch {
|
|
70
|
-
return 0;
|
|
82
|
+
return { reportArtifacts: 0, emptyStateArtifacts: 0, totalArtifacts: 0 };
|
|
71
83
|
}
|
|
72
84
|
}
|
|
73
85
|
/**
|
|
@@ -78,22 +90,26 @@ function countRecentQuietArtifacts(workspaceRoot, windowDays = 2) {
|
|
|
78
90
|
try {
|
|
79
91
|
const quietRoot = path.join(workspaceRoot, ".second-nature", "quiet");
|
|
80
92
|
if (!fs.existsSync(quietRoot))
|
|
81
|
-
return { totalArtifacts: 0, recentDays: [] };
|
|
93
|
+
return { totalArtifacts: 0, reportArtifacts: 0, emptyStateArtifacts: 0, recentDays: [] };
|
|
82
94
|
const now = Date.now();
|
|
83
95
|
const recentDays = [];
|
|
84
96
|
let total = 0;
|
|
97
|
+
let reports = 0;
|
|
98
|
+
let emptyStates = 0;
|
|
85
99
|
for (let i = 0; i < windowDays; i++) {
|
|
86
100
|
const d = new Date(now - i * 86400000).toISOString().slice(0, 10);
|
|
87
|
-
const count =
|
|
88
|
-
if (count > 0) {
|
|
101
|
+
const count = classifyQuietArtifactsForDay(workspaceRoot, d);
|
|
102
|
+
if (count.totalArtifacts > 0) {
|
|
89
103
|
recentDays.push(d);
|
|
90
|
-
total += count;
|
|
104
|
+
total += count.totalArtifacts;
|
|
105
|
+
reports += count.reportArtifacts;
|
|
106
|
+
emptyStates += count.emptyStateArtifacts;
|
|
91
107
|
}
|
|
92
108
|
}
|
|
93
|
-
return { totalArtifacts: total, recentDays };
|
|
109
|
+
return { totalArtifacts: total, reportArtifacts: reports, emptyStateArtifacts: emptyStates, recentDays };
|
|
94
110
|
}
|
|
95
111
|
catch {
|
|
96
|
-
return { totalArtifacts: 0, recentDays: [] };
|
|
112
|
+
return { totalArtifacts: 0, reportArtifacts: 0, emptyStateArtifacts: 0, recentDays: [] };
|
|
97
113
|
}
|
|
98
114
|
}
|
|
99
115
|
function mapRuntimeStatus(attempt) {
|
|
@@ -282,7 +298,7 @@ export function createCliReadModels(deps) {
|
|
|
282
298
|
// into the daily report sourceRefs so the read model reflects artifacts written by
|
|
283
299
|
// `persistQuietArtifactToWorkspace` (closes the canonical read/write gap for loadDailyReport).
|
|
284
300
|
const fsArtifactCount = deps.workspaceRoot
|
|
285
|
-
?
|
|
301
|
+
? classifyQuietArtifactsForDay(deps.workspaceRoot, day).reportArtifacts
|
|
286
302
|
: 0;
|
|
287
303
|
const report = bundle.dailyReports[0];
|
|
288
304
|
const existingSources = report?.sources ?? [];
|
|
@@ -314,15 +330,16 @@ export function createCliReadModels(deps) {
|
|
|
314
330
|
// journal path is empty.
|
|
315
331
|
const quietArtifacts = deps.workspaceRoot
|
|
316
332
|
? countRecentQuietArtifacts(deps.workspaceRoot, 2)
|
|
317
|
-
: { totalArtifacts: 0, recentDays: [] };
|
|
318
|
-
const totalSourceCount = bundle.sourceCount + quietArtifacts.
|
|
319
|
-
const totalReportCount = bundle.dailyReports.length + quietArtifacts.
|
|
333
|
+
: { totalArtifacts: 0, reportArtifacts: 0, emptyStateArtifacts: 0, recentDays: [] };
|
|
334
|
+
const totalSourceCount = bundle.sourceCount + quietArtifacts.reportArtifacts;
|
|
335
|
+
const totalReportCount = bundle.dailyReports.length + quietArtifacts.reportArtifacts;
|
|
320
336
|
return {
|
|
321
337
|
scope,
|
|
322
338
|
mode: totalSourceCount > 0 ? "quiet" : "unknown",
|
|
323
339
|
sourceCount: totalSourceCount,
|
|
324
340
|
reportCount: totalReportCount,
|
|
325
341
|
recentJournalCount: bundle.journalEntries.length,
|
|
342
|
+
emptyStateCount: quietArtifacts.emptyStateArtifacts,
|
|
326
343
|
};
|
|
327
344
|
},
|
|
328
345
|
async loadSession(sessionId) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export function createAgentWorldRunner(input) {
|
|
2
|
-
const { apiClient } = input;
|
|
2
|
+
const { apiClient, apiKey: configuredApiKey } = input;
|
|
3
3
|
return {
|
|
4
4
|
async run(plan, request) {
|
|
5
5
|
const started = Date.now();
|
|
6
6
|
try {
|
|
7
|
-
const apiKey = request.payload
|
|
7
|
+
const apiKey = configuredApiKey ?? request.payload.apiKey ?? "";
|
|
8
8
|
if (!apiKey) {
|
|
9
9
|
return {
|
|
10
10
|
platformId: request.platformId,
|
|
@@ -3,7 +3,9 @@ import { type FailureClass } from "./failure-taxonomy.js";
|
|
|
3
3
|
export declare const CHANNEL_TYPES: readonly ["api_rest", "api_rpc", "a2a", "mcp", "cli", "skill", "browser"];
|
|
4
4
|
export type ChannelType = (typeof CHANNEL_TYPES)[number];
|
|
5
5
|
export declare const CAPABILITY_INTENTS: readonly ["feed.read", "post.publish", "comment.reply", "notification.list", "message.send", "agent.register", "agent.heartbeat", "work.discover", "task.claim"];
|
|
6
|
-
export type
|
|
6
|
+
export type BuiltInCapabilityIntent = (typeof CAPABILITY_INTENTS)[number];
|
|
7
|
+
export type CapabilityIntent = BuiltInCapabilityIntent | (string & {});
|
|
8
|
+
export declare function isKnownCapabilityIntent(intent: string): intent is BuiltInCapabilityIntent;
|
|
7
9
|
export interface ConnectorRequest {
|
|
8
10
|
platformId: string;
|
|
9
11
|
intent: CapabilityIntent;
|
|
@@ -28,6 +30,7 @@ export interface ConnectorResult<T> {
|
|
|
28
30
|
data?: T;
|
|
29
31
|
failureClass?: FailureClass;
|
|
30
32
|
retryAfterMs?: number;
|
|
33
|
+
executionId?: string;
|
|
31
34
|
metadata: {
|
|
32
35
|
platformId: string;
|
|
33
36
|
channel: ChannelType;
|
|
@@ -20,9 +20,13 @@ export const CAPABILITY_INTENTS = [
|
|
|
20
20
|
"work.discover",
|
|
21
21
|
"task.claim",
|
|
22
22
|
];
|
|
23
|
+
export function isKnownCapabilityIntent(intent) {
|
|
24
|
+
return CAPABILITY_INTENTS.includes(intent);
|
|
25
|
+
}
|
|
26
|
+
const capabilityIntentSchema = z.string().min(1).regex(/^[a-zA-Z0-9_.:-]+$/);
|
|
23
27
|
const connectorRequestSchema = z.object({
|
|
24
28
|
platformId: z.string().min(1),
|
|
25
|
-
intent:
|
|
29
|
+
intent: capabilityIntentSchema,
|
|
26
30
|
payload: z.record(z.string(), z.unknown()),
|
|
27
31
|
preferredChannel: z.enum(CHANNEL_TYPES).optional(),
|
|
28
32
|
timeoutMs: z.number().int().positive().optional(),
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EffectCommitLedger SQLite implementation — T-CS.C.2
|
|
3
|
+
*
|
|
4
|
+
* Core logic: Persists effect-commit records to SQLite with idempotency-key
|
|
5
|
+
* uniqueness. On process restart, a previously committed key returns
|
|
6
|
+
* `{ existing: true, record: { ... } }`, enabling replay without side-effect.
|
|
7
|
+
*
|
|
8
|
+
* Implements `EffectCommitLedgerPort` from `./execution-policy.js`.
|
|
9
|
+
*
|
|
10
|
+
* Dependencies:
|
|
11
|
+
* - `StateDatabase` from `../../storage/db/index.js`
|
|
12
|
+
* - `EffectCommitLedgerPort` from `./execution-policy.js`
|
|
13
|
+
*
|
|
14
|
+
* Boundary:
|
|
15
|
+
* - idempotency_key is UNIQUE; duplicate insert attempts are caught and
|
|
16
|
+
* resolved to the existing record.
|
|
17
|
+
* - `markCommitted` is an extension beyond the port for use by execution
|
|
18
|
+
* adapters to transition state from `planned`/`dispatched` to `committed`.
|
|
19
|
+
*
|
|
20
|
+
* Test coverage: tests/unit/connectors/effect-commit-ledger-sqlite.test.ts
|
|
21
|
+
*/
|
|
22
|
+
import type { StateDatabase } from "../../storage/db/index.js";
|
|
23
|
+
import type { EffectCommitLedgerPort } from "./execution-policy.js";
|
|
24
|
+
export interface EffectCommitLedgerSQLite extends EffectCommitLedgerPort {
|
|
25
|
+
/** Transition an existing record to committed with an outcome ref. */
|
|
26
|
+
markCommitted(idempotencyKey: string, outcomeRef: string): Promise<{
|
|
27
|
+
ok: boolean;
|
|
28
|
+
previousState?: string;
|
|
29
|
+
}>;
|
|
30
|
+
}
|
|
31
|
+
export declare function createEffectCommitLedgerSQLite(database: StateDatabase): EffectCommitLedgerSQLite;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EffectCommitLedger SQLite implementation — T-CS.C.2
|
|
3
|
+
*
|
|
4
|
+
* Core logic: Persists effect-commit records to SQLite with idempotency-key
|
|
5
|
+
* uniqueness. On process restart, a previously committed key returns
|
|
6
|
+
* `{ existing: true, record: { ... } }`, enabling replay without side-effect.
|
|
7
|
+
*
|
|
8
|
+
* Implements `EffectCommitLedgerPort` from `./execution-policy.js`.
|
|
9
|
+
*
|
|
10
|
+
* Dependencies:
|
|
11
|
+
* - `StateDatabase` from `../../storage/db/index.js`
|
|
12
|
+
* - `EffectCommitLedgerPort` from `./execution-policy.js`
|
|
13
|
+
*
|
|
14
|
+
* Boundary:
|
|
15
|
+
* - idempotency_key is UNIQUE; duplicate insert attempts are caught and
|
|
16
|
+
* resolved to the existing record.
|
|
17
|
+
* - `markCommitted` is an extension beyond the port for use by execution
|
|
18
|
+
* adapters to transition state from `planned`/`dispatched` to `committed`.
|
|
19
|
+
*
|
|
20
|
+
* Test coverage: tests/unit/connectors/effect-commit-ledger-sqlite.test.ts
|
|
21
|
+
*/
|
|
22
|
+
import * as crypto from "node:crypto";
|
|
23
|
+
export function createEffectCommitLedgerSQLite(database) {
|
|
24
|
+
const { sqlite } = database;
|
|
25
|
+
return {
|
|
26
|
+
async getOrCreateIntentCommitRecord(input) {
|
|
27
|
+
// Try insert first; if UNIQUE conflict, read existing
|
|
28
|
+
const commitId = crypto.randomUUID();
|
|
29
|
+
const createdAt = new Date().toISOString();
|
|
30
|
+
try {
|
|
31
|
+
sqlite.run(`INSERT INTO effect_commit_ledger
|
|
32
|
+
(commit_id, idempotency_key, decision_id, intent_id, effect_class, status, created_at)
|
|
33
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
|
|
34
|
+
commitId,
|
|
35
|
+
input.idempotencyKey,
|
|
36
|
+
input.decisionId,
|
|
37
|
+
input.intentId,
|
|
38
|
+
input.effectClass,
|
|
39
|
+
"planned",
|
|
40
|
+
createdAt,
|
|
41
|
+
]);
|
|
42
|
+
return {
|
|
43
|
+
existing: false,
|
|
44
|
+
record: { id: commitId, state: "planned" },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
49
|
+
// SQLite UNIQUE constraint violation codes: 2067 (SQLITE_CONSTRAINT_UNIQUE)
|
|
50
|
+
if (msg.includes("UNIQUE constraint failed") || msg.includes("constraint")) {
|
|
51
|
+
const existingResult = sqlite.exec(`SELECT commit_id, status, outcome_ref
|
|
52
|
+
FROM effect_commit_ledger
|
|
53
|
+
WHERE idempotency_key = ?`, [input.idempotencyKey]);
|
|
54
|
+
if (existingResult.length > 0 &&
|
|
55
|
+
existingResult[0].values.length > 0) {
|
|
56
|
+
const cols = existingResult[0].columns;
|
|
57
|
+
const row = existingResult[0].values[0];
|
|
58
|
+
const get = (name) => row[cols.indexOf(name)];
|
|
59
|
+
return {
|
|
60
|
+
existing: true,
|
|
61
|
+
record: {
|
|
62
|
+
id: get("commit_id"),
|
|
63
|
+
state: get("status"),
|
|
64
|
+
outcomeRef: get("outcome_ref") ?? undefined,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
async markCommitted(idempotencyKey, outcomeRef) {
|
|
73
|
+
const currentResult = sqlite.exec(`SELECT status FROM effect_commit_ledger WHERE idempotency_key = ?`, [idempotencyKey]);
|
|
74
|
+
if (currentResult.length === 0 ||
|
|
75
|
+
currentResult[0].values.length === 0) {
|
|
76
|
+
return { ok: false };
|
|
77
|
+
}
|
|
78
|
+
const previousState = currentResult[0].values[0][0];
|
|
79
|
+
const committedAt = new Date().toISOString();
|
|
80
|
+
sqlite.run(`UPDATE effect_commit_ledger
|
|
81
|
+
SET status = ?, outcome_ref = ?, committed_at = ?
|
|
82
|
+
WHERE idempotency_key = ?`, ["committed", outcomeRef, committedAt, idempotencyKey]);
|
|
83
|
+
return { ok: true, previousState };
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
@@ -118,6 +118,11 @@ export function classifyFailure(error) {
|
|
|
118
118
|
class: "permanent_input_error",
|
|
119
119
|
retryable: RETRYABLE_BY_CLASS.permanent_input_error,
|
|
120
120
|
};
|
|
121
|
+
if (code === "unknown_platform" || code === "unknown_platform_change")
|
|
122
|
+
return {
|
|
123
|
+
class: "unknown_platform_change",
|
|
124
|
+
retryable: RETRYABLE_BY_CLASS.unknown_platform_change,
|
|
125
|
+
};
|
|
121
126
|
}
|
|
122
127
|
const status = record.status;
|
|
123
128
|
if (status === 429) {
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest v7 Schema + CapabilityContractRegistry v7 Extension — T-CS.C.1
|
|
3
|
+
*
|
|
4
|
+
* Core logic: Extends v6 manifest with v7 fields:
|
|
5
|
+
* - `probeConfig` (safeEndpoint, idempotencyClass)
|
|
6
|
+
* - `endpointMappings` (profilePath, claimPath, heartbeatPath)
|
|
7
|
+
* - `capabilityId` per capability (DR-001 fix)
|
|
8
|
+
*
|
|
9
|
+
* Zod strict validation with detailed error messages on registration failure.
|
|
10
|
+
*
|
|
11
|
+
* Dependencies:
|
|
12
|
+
* - Zod for schema validation
|
|
13
|
+
* - v6 `CapabilityContractRegistry` from `./manifest.js` as baseline
|
|
14
|
+
*
|
|
15
|
+
* Boundary:
|
|
16
|
+
* - `ConnectorManifestV7` is a superset of v6 manifest fields.
|
|
17
|
+
* - `CapabilityContractRegistryV7` wraps/extends the base registry with
|
|
18
|
+
* v7-specific lookups (`resolveCapabilityV7`, `getProbeConfig`,
|
|
19
|
+
* `getEndpointMapping`).
|
|
20
|
+
* - Registration failures return `{ ok: false; errors: string[] }` instead of
|
|
21
|
+
* throwing.
|
|
22
|
+
*
|
|
23
|
+
* Test coverage: tests/unit/connectors/manifest-v7-schema.test.ts
|
|
24
|
+
*/
|
|
25
|
+
import { z } from "zod";
|
|
26
|
+
export declare const IdempotencyClassSchema: z.ZodEnum<{
|
|
27
|
+
strict: "strict";
|
|
28
|
+
read_only: "read_only";
|
|
29
|
+
idempotent_write: "idempotent_write";
|
|
30
|
+
}>;
|
|
31
|
+
export type IdempotencyClass = z.infer<typeof IdempotencyClassSchema>;
|
|
32
|
+
export declare const ProbeConfigSchema: z.ZodObject<{
|
|
33
|
+
safeEndpoint: z.ZodString;
|
|
34
|
+
idempotencyClass: z.ZodEnum<{
|
|
35
|
+
strict: "strict";
|
|
36
|
+
read_only: "read_only";
|
|
37
|
+
idempotent_write: "idempotent_write";
|
|
38
|
+
}>;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
export type ProbeConfig = z.infer<typeof ProbeConfigSchema>;
|
|
41
|
+
export declare const EndpointMappingsSchema: z.ZodObject<{
|
|
42
|
+
profilePath: z.ZodOptional<z.ZodString>;
|
|
43
|
+
claimPath: z.ZodOptional<z.ZodString>;
|
|
44
|
+
heartbeatPath: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, z.core.$strip>;
|
|
46
|
+
export type EndpointMappings = z.infer<typeof EndpointMappingsSchema>;
|
|
47
|
+
export declare const V7CapabilitySchema: z.ZodObject<{
|
|
48
|
+
capabilityId: z.ZodString;
|
|
49
|
+
intent: z.ZodString;
|
|
50
|
+
description: z.ZodOptional<z.ZodString>;
|
|
51
|
+
probeConfig: z.ZodOptional<z.ZodObject<{
|
|
52
|
+
safeEndpoint: z.ZodString;
|
|
53
|
+
idempotencyClass: z.ZodEnum<{
|
|
54
|
+
strict: "strict";
|
|
55
|
+
read_only: "read_only";
|
|
56
|
+
idempotent_write: "idempotent_write";
|
|
57
|
+
}>;
|
|
58
|
+
}, z.core.$strip>>;
|
|
59
|
+
endpointMappings: z.ZodOptional<z.ZodObject<{
|
|
60
|
+
profilePath: z.ZodOptional<z.ZodString>;
|
|
61
|
+
claimPath: z.ZodOptional<z.ZodString>;
|
|
62
|
+
heartbeatPath: z.ZodOptional<z.ZodString>;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
export type V7Capability = z.infer<typeof V7CapabilitySchema>;
|
|
66
|
+
export declare const ConnectorManifestV7Schema: z.ZodObject<{
|
|
67
|
+
platformId: z.ZodString;
|
|
68
|
+
capabilities: z.ZodArray<z.ZodObject<{
|
|
69
|
+
capabilityId: z.ZodString;
|
|
70
|
+
intent: z.ZodString;
|
|
71
|
+
description: z.ZodOptional<z.ZodString>;
|
|
72
|
+
probeConfig: z.ZodOptional<z.ZodObject<{
|
|
73
|
+
safeEndpoint: z.ZodString;
|
|
74
|
+
idempotencyClass: z.ZodEnum<{
|
|
75
|
+
strict: "strict";
|
|
76
|
+
read_only: "read_only";
|
|
77
|
+
idempotent_write: "idempotent_write";
|
|
78
|
+
}>;
|
|
79
|
+
}, z.core.$strip>>;
|
|
80
|
+
endpointMappings: z.ZodOptional<z.ZodObject<{
|
|
81
|
+
profilePath: z.ZodOptional<z.ZodString>;
|
|
82
|
+
claimPath: z.ZodOptional<z.ZodString>;
|
|
83
|
+
heartbeatPath: z.ZodOptional<z.ZodString>;
|
|
84
|
+
}, z.core.$strip>>;
|
|
85
|
+
}, z.core.$strip>>;
|
|
86
|
+
channelPriority: z.ZodArray<z.ZodString>;
|
|
87
|
+
credentialTypes: z.ZodArray<z.ZodString>;
|
|
88
|
+
probeConfig: z.ZodOptional<z.ZodObject<{
|
|
89
|
+
safeEndpoint: z.ZodString;
|
|
90
|
+
idempotencyClass: z.ZodEnum<{
|
|
91
|
+
strict: "strict";
|
|
92
|
+
read_only: "read_only";
|
|
93
|
+
idempotent_write: "idempotent_write";
|
|
94
|
+
}>;
|
|
95
|
+
}, z.core.$strip>>;
|
|
96
|
+
endpointMappings: z.ZodOptional<z.ZodObject<{
|
|
97
|
+
profilePath: z.ZodOptional<z.ZodString>;
|
|
98
|
+
claimPath: z.ZodOptional<z.ZodString>;
|
|
99
|
+
heartbeatPath: z.ZodOptional<z.ZodString>;
|
|
100
|
+
}, z.core.$strip>>;
|
|
101
|
+
degradedChannels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
102
|
+
sourceRefPolicy: z.ZodOptional<z.ZodObject<{
|
|
103
|
+
minSourceRefs: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
rejectInlineSensitivePayload: z.ZodOptional<z.ZodBoolean>;
|
|
105
|
+
}, z.core.$strip>>;
|
|
106
|
+
}, z.core.$strip>;
|
|
107
|
+
export type ConnectorManifestV7 = z.infer<typeof ConnectorManifestV7Schema>;
|
|
108
|
+
export interface ManifestValidationResult {
|
|
109
|
+
ok: boolean;
|
|
110
|
+
errors: string[];
|
|
111
|
+
manifest?: ConnectorManifestV7;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Parse and validate a v7 manifest object.
|
|
115
|
+
* Returns detailed errors rather than throwing.
|
|
116
|
+
*/
|
|
117
|
+
export declare function validateManifestV7(input: unknown): ManifestValidationResult;
|
|
118
|
+
export interface ResolvedV7Capability {
|
|
119
|
+
platformId: string;
|
|
120
|
+
capabilityId: string;
|
|
121
|
+
intent: string;
|
|
122
|
+
probeConfig?: ProbeConfig;
|
|
123
|
+
endpointMappings?: EndpointMappings;
|
|
124
|
+
}
|
|
125
|
+
export declare class CapabilityContractRegistryV7 {
|
|
126
|
+
private readonly byPlatform;
|
|
127
|
+
/**
|
|
128
|
+
* Register a v7 manifest.
|
|
129
|
+
* Returns `{ ok: false, errors }` on validation failure;
|
|
130
|
+
* never throws for validation errors.
|
|
131
|
+
*/
|
|
132
|
+
register(manifest: unknown): ManifestValidationResult;
|
|
133
|
+
loadManifest(platformId: string): ConnectorManifestV7 | undefined;
|
|
134
|
+
listRegisteredPlatformIds(): string[];
|
|
135
|
+
/**
|
|
136
|
+
* Resolve a capability by its `capabilityId` (namespace optional).
|
|
137
|
+
* Supports `platformId:capabilityId` qualified form.
|
|
138
|
+
*/
|
|
139
|
+
resolveCapability(capabilityIdOrQualified: string): ResolvedV7Capability | undefined;
|
|
140
|
+
private _resolveOnPlatform;
|
|
141
|
+
getProbeConfig(platformId: string, capabilityId: string): ProbeConfig | undefined;
|
|
142
|
+
getEndpointMappings(platformId: string, capabilityId: string): EndpointMappings | undefined;
|
|
143
|
+
hasCapability(platformId: string, capabilityId: string): boolean;
|
|
144
|
+
listCapabilities(platformId: string): Array<{
|
|
145
|
+
capabilityId: string;
|
|
146
|
+
intent: string;
|
|
147
|
+
hasProbeConfig: boolean;
|
|
148
|
+
hasEndpointMappings: boolean;
|
|
149
|
+
}>;
|
|
150
|
+
}
|
|
151
|
+
export { ConnectorManifestV7Schema as ManifestV7Schema };
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest v7 Schema + CapabilityContractRegistry v7 Extension — T-CS.C.1
|
|
3
|
+
*
|
|
4
|
+
* Core logic: Extends v6 manifest with v7 fields:
|
|
5
|
+
* - `probeConfig` (safeEndpoint, idempotencyClass)
|
|
6
|
+
* - `endpointMappings` (profilePath, claimPath, heartbeatPath)
|
|
7
|
+
* - `capabilityId` per capability (DR-001 fix)
|
|
8
|
+
*
|
|
9
|
+
* Zod strict validation with detailed error messages on registration failure.
|
|
10
|
+
*
|
|
11
|
+
* Dependencies:
|
|
12
|
+
* - Zod for schema validation
|
|
13
|
+
* - v6 `CapabilityContractRegistry` from `./manifest.js` as baseline
|
|
14
|
+
*
|
|
15
|
+
* Boundary:
|
|
16
|
+
* - `ConnectorManifestV7` is a superset of v6 manifest fields.
|
|
17
|
+
* - `CapabilityContractRegistryV7` wraps/extends the base registry with
|
|
18
|
+
* v7-specific lookups (`resolveCapabilityV7`, `getProbeConfig`,
|
|
19
|
+
* `getEndpointMapping`).
|
|
20
|
+
* - Registration failures return `{ ok: false; errors: string[] }` instead of
|
|
21
|
+
* throwing.
|
|
22
|
+
*
|
|
23
|
+
* Test coverage: tests/unit/connectors/manifest-v7-schema.test.ts
|
|
24
|
+
*/
|
|
25
|
+
import { z } from "zod";
|
|
26
|
+
// ─── V7 Capability Schema ───────────────────────────────────────────────────
|
|
27
|
+
export const IdempotencyClassSchema = z.enum([
|
|
28
|
+
"read_only",
|
|
29
|
+
"idempotent_write",
|
|
30
|
+
"strict",
|
|
31
|
+
]);
|
|
32
|
+
export const ProbeConfigSchema = z.object({
|
|
33
|
+
safeEndpoint: z.string().min(1),
|
|
34
|
+
idempotencyClass: IdempotencyClassSchema,
|
|
35
|
+
});
|
|
36
|
+
export const EndpointMappingsSchema = z.object({
|
|
37
|
+
profilePath: z.string().min(1).optional(),
|
|
38
|
+
claimPath: z.string().min(1).optional(),
|
|
39
|
+
heartbeatPath: z.string().min(1).optional(),
|
|
40
|
+
});
|
|
41
|
+
export const V7CapabilitySchema = z.object({
|
|
42
|
+
capabilityId: z.string().min(1),
|
|
43
|
+
intent: z.string().min(1).regex(/^[a-zA-Z0-9_.:-]+$/),
|
|
44
|
+
description: z.string().optional(),
|
|
45
|
+
probeConfig: ProbeConfigSchema.optional(),
|
|
46
|
+
endpointMappings: EndpointMappingsSchema.optional(),
|
|
47
|
+
});
|
|
48
|
+
// ─── V7 Manifest Schema ─────────────────────────────────────────────────────
|
|
49
|
+
export const ConnectorManifestV7Schema = z.object({
|
|
50
|
+
platformId: z.string().min(1),
|
|
51
|
+
capabilities: z.array(V7CapabilitySchema).min(1),
|
|
52
|
+
channelPriority: z.array(z.string().min(1)).min(1),
|
|
53
|
+
credentialTypes: z.array(z.string().min(1)).min(1),
|
|
54
|
+
probeConfig: ProbeConfigSchema.optional(),
|
|
55
|
+
endpointMappings: EndpointMappingsSchema.optional(),
|
|
56
|
+
degradedChannels: z.array(z.string().min(1)).optional(),
|
|
57
|
+
sourceRefPolicy: z
|
|
58
|
+
.object({
|
|
59
|
+
minSourceRefs: z.number().int().min(0).optional(),
|
|
60
|
+
rejectInlineSensitivePayload: z.boolean().optional(),
|
|
61
|
+
})
|
|
62
|
+
.optional(),
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Parse and validate a v7 manifest object.
|
|
66
|
+
* Returns detailed errors rather than throwing.
|
|
67
|
+
*/
|
|
68
|
+
export function validateManifestV7(input) {
|
|
69
|
+
const parsed = ConnectorManifestV7Schema.safeParse(input);
|
|
70
|
+
if (!parsed.success) {
|
|
71
|
+
const errors = parsed.error.issues.map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`);
|
|
72
|
+
return { ok: false, errors };
|
|
73
|
+
}
|
|
74
|
+
return { ok: true, errors: [], manifest: parsed.data };
|
|
75
|
+
}
|
|
76
|
+
export class CapabilityContractRegistryV7 {
|
|
77
|
+
byPlatform = new Map();
|
|
78
|
+
/**
|
|
79
|
+
* Register a v7 manifest.
|
|
80
|
+
* Returns `{ ok: false, errors }` on validation failure;
|
|
81
|
+
* never throws for validation errors.
|
|
82
|
+
*/
|
|
83
|
+
register(manifest) {
|
|
84
|
+
const validation = validateManifestV7(manifest);
|
|
85
|
+
if (!validation.ok) {
|
|
86
|
+
return validation;
|
|
87
|
+
}
|
|
88
|
+
const parsed = validation.manifest;
|
|
89
|
+
// DR-001: capabilityId must be present on every capability
|
|
90
|
+
const missingIds = [];
|
|
91
|
+
for (const cap of parsed.capabilities) {
|
|
92
|
+
if (!cap.capabilityId || cap.capabilityId.trim().length === 0) {
|
|
93
|
+
missingIds.push(cap.intent);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (missingIds.length > 0) {
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
errors: missingIds.map((intent) => `capabilities: capabilityId missing for intent "${intent}"`),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
this.byPlatform.set(parsed.platformId, parsed);
|
|
103
|
+
return { ok: true, errors: [] };
|
|
104
|
+
}
|
|
105
|
+
loadManifest(platformId) {
|
|
106
|
+
return this.byPlatform.get(platformId);
|
|
107
|
+
}
|
|
108
|
+
listRegisteredPlatformIds() {
|
|
109
|
+
return [...this.byPlatform.keys()];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Resolve a capability by its `capabilityId` (namespace optional).
|
|
113
|
+
* Supports `platformId:capabilityId` qualified form.
|
|
114
|
+
*/
|
|
115
|
+
resolveCapability(capabilityIdOrQualified) {
|
|
116
|
+
const colonIndex = capabilityIdOrQualified.indexOf(":");
|
|
117
|
+
if (colonIndex >= 0) {
|
|
118
|
+
const platformId = capabilityIdOrQualified.slice(0, colonIndex);
|
|
119
|
+
const capabilityId = capabilityIdOrQualified.slice(colonIndex + 1);
|
|
120
|
+
return this._resolveOnPlatform(platformId, capabilityId);
|
|
121
|
+
}
|
|
122
|
+
// Search all platforms for first matching capabilityId
|
|
123
|
+
for (const platformId of this.byPlatform.keys()) {
|
|
124
|
+
const found = this._resolveOnPlatform(platformId, capabilityIdOrQualified);
|
|
125
|
+
if (found)
|
|
126
|
+
return found;
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
_resolveOnPlatform(platformId, capabilityIdOrIntent) {
|
|
131
|
+
const manifest = this.byPlatform.get(platformId);
|
|
132
|
+
if (!manifest)
|
|
133
|
+
return undefined;
|
|
134
|
+
// Match by capabilityId (exact) or intent (fallback)
|
|
135
|
+
const cap = manifest.capabilities.find((c) => c.capabilityId === capabilityIdOrIntent) ??
|
|
136
|
+
manifest.capabilities.find((c) => c.intent === capabilityIdOrIntent);
|
|
137
|
+
if (!cap)
|
|
138
|
+
return undefined;
|
|
139
|
+
return {
|
|
140
|
+
platformId,
|
|
141
|
+
capabilityId: cap.capabilityId,
|
|
142
|
+
intent: cap.intent,
|
|
143
|
+
probeConfig: cap.probeConfig ?? manifest.probeConfig,
|
|
144
|
+
endpointMappings: cap.endpointMappings ?? manifest.endpointMappings,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
getProbeConfig(platformId, capabilityId) {
|
|
148
|
+
const resolved = this._resolveOnPlatform(platformId, capabilityId);
|
|
149
|
+
return resolved?.probeConfig;
|
|
150
|
+
}
|
|
151
|
+
getEndpointMappings(platformId, capabilityId) {
|
|
152
|
+
const resolved = this._resolveOnPlatform(platformId, capabilityId);
|
|
153
|
+
return resolved?.endpointMappings;
|
|
154
|
+
}
|
|
155
|
+
hasCapability(platformId, capabilityId) {
|
|
156
|
+
return this._resolveOnPlatform(platformId, capabilityId) !== undefined;
|
|
157
|
+
}
|
|
158
|
+
listCapabilities(platformId) {
|
|
159
|
+
const manifest = this.byPlatform.get(platformId);
|
|
160
|
+
if (!manifest)
|
|
161
|
+
return [];
|
|
162
|
+
return manifest.capabilities.map((cap) => ({
|
|
163
|
+
capabilityId: cap.capabilityId,
|
|
164
|
+
intent: cap.intent,
|
|
165
|
+
hasProbeConfig: !!cap.probeConfig || !!manifest.probeConfig,
|
|
166
|
+
hasEndpointMappings: !!cap.endpointMappings || !!manifest.endpointMappings,
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
export { ConnectorManifestV7Schema as ManifestV7Schema };
|