@inneranimalmedia/agentsam-sdk 2.6.3 → 2.6.4
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/AGENTSAM.md +6 -0
- package/README.md +16 -1
- package/bin/agentsam +16 -1
- package/docs/BRAND_INTELLIGENCE.md +1 -1
- package/docs/architecture/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
- package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
- package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
- package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
- package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
- package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
- package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
- package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
- package/docs/architecture/SAM_KERNEL.md +181 -0
- package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
- package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
- package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
- package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -0
- package/migrations/d1/0010_portable_tickets_memory.sql +140 -0
- package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
- package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
- package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
- package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
- package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
- package/migrations/d1/0013_identity_oauth_states.sql +15 -0
- package/migrations/d1/0014_auth_event_log.sql +20 -0
- package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
- package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -0
- package/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
- package/package.json +19 -4
- package/packages/agentsam-contracts/src/errors.ts +16 -0
- package/packages/agentsam-errors/src/envelope.js +53 -0
- package/packages/agentsam-errors/src/index.js +1 -0
- package/packages/agentsam-errors/src/recovery.js +301 -0
- package/packages/agentsam-knowledge/src/providers/index.js +18 -6
- package/packages/connectors/cloudflare/src/routes.js +9 -0
- package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +11 -2
- package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
- package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
- package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
- package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -0
- package/packages/identity/package.json +2 -2
- package/packages/identity/src/adapters/cloudflare-d1/index.js +122 -22
- package/packages/identity/src/adapters/sqlite/index.js +319 -0
- package/packages/identity/src/app/verify-app.js +95 -0
- package/packages/identity/src/contracts/identity-store.js +115 -0
- package/packages/identity/src/contracts/route-ids.js +30 -0
- package/packages/identity/src/contracts/route-projection.js +218 -0
- package/packages/identity/src/contracts/routes.js +11 -0
- package/packages/identity/src/core/browser-paths.js +4 -5
- package/packages/identity/src/core/constants.js +13 -8
- package/packages/identity/src/core/session-policy.js +32 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +10 -10
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
- package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
- package/packages/identity/src/index.js +25 -0
- package/packages/identity/src/oauth/README.md +10 -4
- package/packages/identity/src/oauth/credentials.js +20 -13
- package/packages/identity/src/oauth/finalize-inbound.js +1 -1
- package/packages/identity/src/oauth/iam-platform.js +8 -7
- package/packages/identity/src/oauth/redirect-paths.js +27 -36
- package/packages/identity/src/server/identity-service.js +30 -13
- package/packages/identity/src/server/mount-policy.js +30 -0
- package/packages/identity/src/server/post-auth.js +79 -0
- package/packages/identity/src/server/worker-router.js +104 -72
- package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
- package/packages/identity/tests/iam-provider.test.mjs +1 -1
- package/packages/identity/tests/identity-service.test.mjs +36 -5
- package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
- package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
- package/packages/identity/tests/session-routes-policy.test.mjs +21 -0
- package/packages/theme-church-site/package.json +2 -1
- package/packages/theme-church-site/src/index.js +1 -0
- package/packages/theme-companions-site/package.json +2 -1
- package/packages/theme-companions-site/src/index.js +1 -0
- package/packages/theme-floors-site/package.json +2 -1
- package/packages/theme-floors-site/src/index.js +1 -0
- package/packages/theme-fuelnfree-site/package.json +2 -1
- package/packages/theme-fuelnfree-site/src/index.js +1 -0
- package/packages/theme-handyman-site/package.json +2 -1
- package/packages/theme-handyman-site/src/index.js +1 -0
- package/packages/theme-insurance-site/package.json +2 -1
- package/packages/theme-insurance-site/src/index.js +1 -0
- package/packages/theme-shinshu-site/package.json +2 -1
- package/packages/theme-shinshu-site/src/index.js +1 -0
- package/protocol/apps/agentsam.app.v1.schema.json +51 -0
- package/protocol/brand/brandpack.v1.schema.json +43 -0
- package/protocol/credentials/issue.v1.schema.json +38 -0
- package/protocol/database/connection.v1.schema.json +41 -0
- package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
- package/protocol/errors/error-envelope.schema.json +135 -1
- package/protocol/errors/recovery.v1.schema.json +50 -0
- package/protocol/runtime/workspace-fs.v1.schema.json +71 -0
- package/protocol/sam/activity.v1.schema.json +48 -0
- package/protocol/sam/answer.v1.schema.json +35 -0
- package/protocol/sam/calibration.v1.schema.json +21 -0
- package/protocol/sam/decision-receipt.v1.schema.json +29 -0
- package/protocol/sam/evaluation.v1.schema.json +19 -0
- package/protocol/sam/operation.schema.json +66 -0
- package/protocol/sam/outcome.v1.schema.json +36 -0
- package/protocol/sam/question.v1.schema.json +26 -0
- package/protocol/sam/registry.seed.json +153 -0
- package/protocol/sam/result.schema.json +53 -0
- package/protocol/sam/state.v1.schema.json +23 -0
- package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
- package/protocol/skills/agentsam.skill.v1.schema.json +57 -0
- package/protocol/ui/icon-registry.mjs +226 -0
- package/protocol/ui/icon.v1.schema.json +51 -0
- package/skills/README.md +22 -9
- package/skills/agentsam-codebaseindex/SKILL.md +225 -0
- package/skills/catalog.json +14 -0
- package/src/cli/command-catalog.js +130 -0
- package/src/cli/dispatch.js +48 -0
- package/src/cli.js +43 -1
- package/src/commands/api-key.js +244 -0
- package/src/commands/app.js +60 -28
- package/src/commands/brand.js +17 -19
- package/src/commands/codebaseindex.js +688 -0
- package/src/commands/env.js +152 -25
- package/src/commands/go.js +366 -53
- package/src/commands/interaction-clack.js +115 -0
- package/src/commands/models.js +1 -1
- package/src/commands/providers.js +62 -14
- package/src/commands/shell.js +43 -2
- package/src/commands/skill.js +248 -0
- package/src/commands/skills.js +1 -1
- package/src/commands/start-local.js +4 -0
- package/src/commands/whoami.js +90 -18
- package/src/go/build.js +229 -39
- package/src/go/cloudflare.js +506 -105
- package/src/go/container.js +120 -0
- package/src/go/contract.js +9 -4
- package/src/go/discover.js +149 -33
- package/src/go/index.js +15 -3
- package/src/go/native-probe-runner.mjs +119 -0
- package/src/go/{registry.js → official-registry.js} +64 -7
- package/src/go/official-release.js +10 -0
- package/src/go/receipts.js +77 -10
- package/src/go/verify.js +9 -2
- package/src/index.js +27 -0
- package/src/indexing/ingest/discover-models.js +298 -0
- package/src/indexing/ingest/inventory.js +243 -0
- package/src/indexing/ingest/job-graph.js +181 -0
- package/src/indexing/ingest/materials.js +210 -0
- package/src/lib/provider-credentials.js +63 -21
- package/src/lib/slash-commands.js +1 -0
- package/src/local-fs/capability.js +121 -0
- package/src/local-fs/freshness.js +75 -0
- package/src/local-fs/index.js +385 -0
- package/src/local-fs/paths.js +100 -0
- package/src/local-pty/server.js +295 -19
- package/src/mcp/client.js +2 -2
- package/src/models/ai-access-onboarding.js +112 -0
- package/src/models/discovery.js +10 -2
- package/src/models/inventory-core.js +9 -1
- package/src/sam/activity/index.js +183 -0
- package/src/sam/client.js +252 -0
- package/src/sam/decision/calibration.js +109 -0
- package/src/sam/decision/confidence.js +126 -0
- package/src/sam/decision/evaluate.js +157 -0
- package/src/sam/decision/evaluators/deterministic.js +341 -0
- package/src/sam/decision/evaluators/heuristic.js +61 -0
- package/src/sam/decision/evaluators/select.js +50 -0
- package/src/sam/decision/evaluators/semantic.js +149 -0
- package/src/sam/decision/hierarchical.js +61 -0
- package/src/sam/decision/index.js +53 -0
- package/src/sam/decision/policy.js +86 -0
- package/src/sam/decision/questions.js +120 -0
- package/src/sam/decision/receipt.js +148 -0
- package/src/sam/decision/state.js +117 -0
- package/src/sam/decision/types.js +22 -0
- package/src/sam/decision/validate.js +200 -0
- package/src/sam/define.js +51 -0
- package/src/sam/index.js +65 -0
- package/src/sam/operations/brand-scan.js +62 -0
- package/src/sam/operations/cad-blender-inspect.js +36 -0
- package/src/sam/operations/codebaseindex-ingest.js +49 -0
- package/src/sam/operations/decision-evaluate.js +59 -0
- package/src/sam/operations/planning-astar.js +77 -0
- package/src/sam/operations/planning-goap.js +60 -0
- package/src/sam/operations/repository-inspect.js +72 -0
- package/src/sam/operations/security-scan.js +33 -0
- package/src/sam/operations/terminal-exec.js +29 -0
- package/src/sam/planning/astar.js +311 -0
- package/src/sam/planning/goap.js +177 -0
- package/src/sam/planning/index.js +21 -0
- package/src/sam/planning/state.js +84 -0
- package/src/sam/registry.js +48 -0
- package/src/sam/result.js +77 -0
- package/src/sam/seed.js +44 -0
- package/src/sam/types.js +91 -0
- package/src/skills/catalog.js +64 -0
- package/src/skills/content-resolver.js +124 -0
- package/src/skills/hosted-store.js +37 -0
- package/src/skills/index.js +29 -64
- package/src/skills/interaction.js +102 -0
- package/src/skills/local-store.js +228 -0
- package/src/skills/manifest.js +104 -0
- package/src/skills/metrics.js +31 -0
- package/src/skills/registry.js +184 -0
- package/src/skills/runtime.js +287 -0
- package/src/skills/slash.js +44 -0
- package/src/ui/cli/help.js +94 -101
- package/test/cli/api-key-env-whoami.test.mjs +129 -0
- package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
- package/test/cli/go.test.mjs +62 -5
- package/test/cli/skill-npm-and-env.test.mjs +52 -0
- package/test/cli/wireframes-go-registry.test.mjs +87 -2
- package/test/go/build-source-identity.test.mjs +31 -0
- package/test/go/cloudflare-probe.test.mjs +274 -10
- package/test/go/distribution.test.mjs +28 -0
- package/test/integration/ai-access-onboarding.test.mjs +47 -0
- package/test/integration/cli-help.test.mjs +1 -1
- package/test/integration/cms-site-tenancy-contract.test.mjs +6 -6
- package/test/integration/codebaseindex-ingest.test.mjs +166 -0
- package/test/integration/icon-registry.test.mjs +67 -0
- package/test/integration/ingest-discover-models.test.mjs +30 -0
- package/test/integration/install-script.test.mjs +12 -9
- package/test/integration/local-fs.test.mjs +113 -0
- package/test/integration/provider-env-cli.test.mjs +2 -1
- package/test/integration/sam-activity-recovery.test.mjs +147 -0
- package/test/integration/sam-decision.test.mjs +584 -0
- package/test/integration/sam-kernel.test.mjs +99 -0
- package/test/integration/sam-planning-astar.test.mjs +279 -0
- package/test/integration/skill-runtime.test.mjs +240 -0
- package/test/integration/studio-fs-pty-e2e.test.mjs +294 -0
- package/test/models.test.mjs +14 -7
- package/test/shell.test.mjs +4 -4
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared SAM decision state — minimal projection for a question set.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createHash } from 'node:crypto';
|
|
6
|
+
import { DECISION_STATE_SCHEMA } from './types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {object} [partial]
|
|
10
|
+
* @returns {object}
|
|
11
|
+
*/
|
|
12
|
+
export function buildDecisionState(partial = {}) {
|
|
13
|
+
const state = {
|
|
14
|
+
schema: DECISION_STATE_SCHEMA,
|
|
15
|
+
intent: partial.intent ?? null,
|
|
16
|
+
goal: partial.goal ?? null,
|
|
17
|
+
repository: partial.repository
|
|
18
|
+
? {
|
|
19
|
+
repository_id: partial.repository.repository_id ?? null,
|
|
20
|
+
root: partial.repository.root ?? null,
|
|
21
|
+
branch: partial.repository.branch ?? null,
|
|
22
|
+
dirty: partial.repository.dirty ?? null,
|
|
23
|
+
merkle_root: partial.repository.merkle_root ?? null,
|
|
24
|
+
}
|
|
25
|
+
: null,
|
|
26
|
+
code: partial.code
|
|
27
|
+
? {
|
|
28
|
+
relevant_nodes: Array.isArray(partial.code.relevant_nodes) ? [...partial.code.relevant_nodes] : [],
|
|
29
|
+
dependency_nodes: Array.isArray(partial.code.dependency_nodes) ? [...partial.code.dependency_nodes] : [],
|
|
30
|
+
affected_packages: Array.isArray(partial.code.affected_packages) ? [...partial.code.affected_packages] : [],
|
|
31
|
+
}
|
|
32
|
+
: null,
|
|
33
|
+
runtime: partial.runtime
|
|
34
|
+
? {
|
|
35
|
+
terminal_lanes: partial.runtime.terminal_lanes ?? null,
|
|
36
|
+
connection_health: partial.runtime.connection_health ?? null,
|
|
37
|
+
capabilities: Array.isArray(partial.runtime.capabilities) ? [...partial.runtime.capabilities] : [],
|
|
38
|
+
}
|
|
39
|
+
: null,
|
|
40
|
+
tools: partial.tools ?? null,
|
|
41
|
+
skills: partial.skills ?? null,
|
|
42
|
+
models: partial.models ?? null,
|
|
43
|
+
constraints: partial.constraints
|
|
44
|
+
? {
|
|
45
|
+
budget: partial.constraints.budget ?? null,
|
|
46
|
+
latency: partial.constraints.latency ?? null,
|
|
47
|
+
approval: partial.constraints.approval ?? null,
|
|
48
|
+
security: partial.constraints.security ?? null,
|
|
49
|
+
production_write: partial.constraints.production_write ?? null,
|
|
50
|
+
isolation_required: partial.constraints.isolation_required ?? null,
|
|
51
|
+
requires_local_files: partial.constraints.requires_local_files ?? null,
|
|
52
|
+
}
|
|
53
|
+
: null,
|
|
54
|
+
evidence: Array.isArray(partial.evidence) ? [...partial.evidence] : [],
|
|
55
|
+
history: partial.history ?? null,
|
|
56
|
+
metadata: partial.metadata && typeof partial.metadata === 'object' ? { ...partial.metadata } : {},
|
|
57
|
+
facts: partial.facts && typeof partial.facts === 'object' ? { ...partial.facts } : {},
|
|
58
|
+
};
|
|
59
|
+
return Object.freeze(deepFreezeShallow(state));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Stable hash of decision state for receipts.
|
|
64
|
+
* @param {object} state
|
|
65
|
+
*/
|
|
66
|
+
export function hashDecisionState(state) {
|
|
67
|
+
return createHash('sha256').update(stableStringify(state)).digest('hex');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Project only the keys needed for a question set (does not mutate input).
|
|
72
|
+
* @param {object} state
|
|
73
|
+
* @param {string[]} paths
|
|
74
|
+
*/
|
|
75
|
+
export function projectState(state, paths = []) {
|
|
76
|
+
if (!paths.length) return buildDecisionState(state);
|
|
77
|
+
const out = { schema: DECISION_STATE_SCHEMA, facts: {}, evidence: [], metadata: {} };
|
|
78
|
+
for (const p of paths) {
|
|
79
|
+
const value = getPath(state, p);
|
|
80
|
+
if (value !== undefined) setPath(out, p, value);
|
|
81
|
+
}
|
|
82
|
+
if (state.evidence) out.evidence = [...state.evidence];
|
|
83
|
+
return buildDecisionState({ ...state, ...out });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function getPath(obj, dotted) {
|
|
87
|
+
const parts = String(dotted).split('.');
|
|
88
|
+
let cur = obj;
|
|
89
|
+
for (const part of parts) {
|
|
90
|
+
if (cur == null || typeof cur !== 'object') return undefined;
|
|
91
|
+
cur = cur[part];
|
|
92
|
+
}
|
|
93
|
+
return cur;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function setPath(obj, dotted, value) {
|
|
97
|
+
const parts = String(dotted).split('.');
|
|
98
|
+
let cur = obj;
|
|
99
|
+
for (let i = 0; i < parts.length - 1; i += 1) {
|
|
100
|
+
const p = parts[i];
|
|
101
|
+
if (cur[p] == null || typeof cur[p] !== 'object') cur[p] = {};
|
|
102
|
+
cur = cur[p];
|
|
103
|
+
}
|
|
104
|
+
cur[parts[parts.length - 1]] = value;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function deepFreezeShallow(value) {
|
|
108
|
+
if (!value || typeof value !== 'object') return value;
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function stableStringify(value) {
|
|
113
|
+
if (value === null || typeof value !== 'object') return JSON.stringify(value);
|
|
114
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;
|
|
115
|
+
const keys = Object.keys(value).sort();
|
|
116
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(',')}}`;
|
|
117
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SAM decision contracts — Systematic Autonomous Machinery.
|
|
3
|
+
* choose / score / check — AgentSam-native, no vendor terminology.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const DECISION_STATE_SCHEMA = 'agentsam.decision-state.v1';
|
|
7
|
+
export const DECISION_QUESTION_SCHEMA = 'agentsam.decision-question.v1';
|
|
8
|
+
export const DECISION_ANSWER_SCHEMA = 'agentsam.decision-answer.v1';
|
|
9
|
+
export const DECISION_EVALUATION_SCHEMA = 'agentsam.decision-evaluation.v1';
|
|
10
|
+
export const DECISION_RECEIPT_SCHEMA = 'agentsam.decision-receipt.v1';
|
|
11
|
+
export const DECISION_OUTCOME_SCHEMA = 'agentsam.decision-outcome.v1';
|
|
12
|
+
export const DECISION_CALIBRATION_SCHEMA = 'agentsam.decision-calibration.v1';
|
|
13
|
+
|
|
14
|
+
/** @typedef {'choose'|'score'|'check'} QuestionType */
|
|
15
|
+
/** @typedef {'deterministic'|'heuristic'|'graph'|'semantic'|'calibrated-statistical'} EvaluatorKind */
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Confidence semantics:
|
|
19
|
+
* - confidence_estimate / support: raw evaluator concentration or proposition support
|
|
20
|
+
* - probabilities: ONLY when evaluator has a defined probabilistic interpretation
|
|
21
|
+
* - calibrated_probability: ONLY after empirical calibration with calibration_id
|
|
22
|
+
*/
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Question builders + validation for choose / score / check.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { DECISION_QUESTION_SCHEMA } from './types.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {object} def
|
|
9
|
+
*/
|
|
10
|
+
export function defineChoose(def) {
|
|
11
|
+
return validateQuestion({
|
|
12
|
+
schema: DECISION_QUESTION_SCHEMA,
|
|
13
|
+
id: def.id,
|
|
14
|
+
type: 'choose',
|
|
15
|
+
version: def.version ?? 1,
|
|
16
|
+
instructions: def.instructions ?? null,
|
|
17
|
+
criteria: def.criteria ?? null,
|
|
18
|
+
options: def.options,
|
|
19
|
+
evaluator_hint: def.evaluator_hint ?? null,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {object} def
|
|
25
|
+
*/
|
|
26
|
+
export function defineScore(def) {
|
|
27
|
+
return validateQuestion({
|
|
28
|
+
schema: DECISION_QUESTION_SCHEMA,
|
|
29
|
+
id: def.id,
|
|
30
|
+
type: 'score',
|
|
31
|
+
version: def.version ?? 1,
|
|
32
|
+
instructions: def.instructions ?? null,
|
|
33
|
+
criteria: def.criteria ?? null,
|
|
34
|
+
levels: def.levels,
|
|
35
|
+
evaluator_hint: def.evaluator_hint ?? null,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {object} def
|
|
41
|
+
*/
|
|
42
|
+
export function defineCheck(def) {
|
|
43
|
+
return validateQuestion({
|
|
44
|
+
schema: DECISION_QUESTION_SCHEMA,
|
|
45
|
+
id: def.id,
|
|
46
|
+
type: 'check',
|
|
47
|
+
version: def.version ?? 1,
|
|
48
|
+
instructions: def.instructions ?? null,
|
|
49
|
+
criteria: def.criteria ?? null,
|
|
50
|
+
evaluator_hint: def.evaluator_hint ?? null,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Fail-closed validation.
|
|
56
|
+
* @param {object} question
|
|
57
|
+
*/
|
|
58
|
+
export function validateQuestion(question) {
|
|
59
|
+
if (!question || typeof question !== 'object') {
|
|
60
|
+
throw fail('invalid_question', 'question must be an object');
|
|
61
|
+
}
|
|
62
|
+
if (typeof question.id !== 'string' || !question.id.trim()) {
|
|
63
|
+
throw fail('invalid_question_id', 'question.id is required');
|
|
64
|
+
}
|
|
65
|
+
if (!['choose', 'score', 'check'].includes(question.type)) {
|
|
66
|
+
throw fail('invalid_question_type', `unsupported type: ${question.type}`);
|
|
67
|
+
}
|
|
68
|
+
if (question.instructions != null && !isAllowedInstructions(question.instructions)) {
|
|
69
|
+
throw fail('invalid_instructions', 'instructions must be string|object|array|null');
|
|
70
|
+
}
|
|
71
|
+
if (question.criteria != null && !isAllowedCriteria(question.criteria)) {
|
|
72
|
+
throw fail('invalid_criteria', 'criteria must be string|object|array|null');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (question.type === 'choose') {
|
|
76
|
+
const options = normalizeOptions(question.options, question.criteria);
|
|
77
|
+
if (!options.length) {
|
|
78
|
+
throw fail('choose_options_required', 'choose requires a finite options set');
|
|
79
|
+
}
|
|
80
|
+
return Object.freeze({
|
|
81
|
+
...question,
|
|
82
|
+
schema: DECISION_QUESTION_SCHEMA,
|
|
83
|
+
options,
|
|
84
|
+
version: question.version ?? 1,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (question.type === 'score') {
|
|
89
|
+
const levels = normalizeLevels(question.levels ?? question.criteria);
|
|
90
|
+
if (levels.length < 2) {
|
|
91
|
+
throw fail('score_levels_required', 'score requires an ordered levels list (>=2)');
|
|
92
|
+
}
|
|
93
|
+
// Ensure strictly ordered by numeric index (and unique)
|
|
94
|
+
const seen = new Set();
|
|
95
|
+
for (let i = 0; i < levels.length; i += 1) {
|
|
96
|
+
if (seen.has(levels[i].index)) {
|
|
97
|
+
throw fail('score_levels_unordered', 'score levels must have unique strictly increasing indexes');
|
|
98
|
+
}
|
|
99
|
+
seen.add(levels[i].index);
|
|
100
|
+
if (i > 0 && !(levels[i].index > levels[i - 1].index)) {
|
|
101
|
+
throw fail('score_levels_unordered', 'score levels must be strictly increasing');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return Object.freeze({
|
|
105
|
+
...question,
|
|
106
|
+
schema: DECISION_QUESTION_SCHEMA,
|
|
107
|
+
levels,
|
|
108
|
+
version: question.version ?? 1,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// check — single proposition; do not smuggle multi-dimensional scoring
|
|
113
|
+
return Object.freeze({
|
|
114
|
+
...question,
|
|
115
|
+
schema: DECISION_QUESTION_SCHEMA,
|
|
116
|
+
version: question.version ?? 1,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {object[]} questions
|
|
122
|
+
*/
|
|
123
|
+
export function validateQuestionBatch(questions) {
|
|
124
|
+
if (!Array.isArray(questions) || !questions.length) {
|
|
125
|
+
throw fail('empty_batch', 'questions must be a non-empty array');
|
|
126
|
+
}
|
|
127
|
+
const ids = new Set();
|
|
128
|
+
const validated = questions.map((q) => validateQuestion(q));
|
|
129
|
+
for (const q of validated) {
|
|
130
|
+
if (ids.has(q.id)) throw fail('duplicate_question_id', `duplicate question id: ${q.id}`);
|
|
131
|
+
ids.add(q.id);
|
|
132
|
+
}
|
|
133
|
+
return validated;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function normalizeOptions(options, criteria) {
|
|
137
|
+
if (Array.isArray(options)) {
|
|
138
|
+
return options.map((o) => {
|
|
139
|
+
if (typeof o === 'string') return o;
|
|
140
|
+
if (o && typeof o === 'object' && typeof o.id === 'string') return o.id;
|
|
141
|
+
throw fail('invalid_option', 'choose options must be strings or {id}');
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (criteria && typeof criteria === 'object' && !Array.isArray(criteria)) {
|
|
145
|
+
return Object.keys(criteria);
|
|
146
|
+
}
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function normalizeLevels(levels) {
|
|
151
|
+
if (Array.isArray(levels)) {
|
|
152
|
+
return levels.map((level, i) => {
|
|
153
|
+
if (typeof level === 'string') return { index: i, label: level };
|
|
154
|
+
if (level && typeof level === 'object') {
|
|
155
|
+
const index = Number(level.index ?? level.value ?? i);
|
|
156
|
+
if (!Number.isFinite(index)) throw fail('invalid_level_index', 'level index must be numeric');
|
|
157
|
+
return {
|
|
158
|
+
index,
|
|
159
|
+
label: String(level.label ?? level.description ?? `level_${index}`),
|
|
160
|
+
description: level.description ?? null,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
throw fail('invalid_level', 'score level must be string or object');
|
|
164
|
+
}).sort((a, b) => a.index - b.index);
|
|
165
|
+
}
|
|
166
|
+
if (levels && typeof levels === 'object') {
|
|
167
|
+
return Object.keys(levels)
|
|
168
|
+
.map((k) => {
|
|
169
|
+
const index = Number(k);
|
|
170
|
+
if (!Number.isFinite(index)) throw fail('invalid_level_key', 'object level keys must be numeric');
|
|
171
|
+
const v = levels[k];
|
|
172
|
+
return {
|
|
173
|
+
index,
|
|
174
|
+
label: typeof v === 'string' ? v : String(v?.label ?? k),
|
|
175
|
+
description: typeof v === 'object' ? v.description ?? null : null,
|
|
176
|
+
};
|
|
177
|
+
})
|
|
178
|
+
.sort((a, b) => a.index - b.index);
|
|
179
|
+
}
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function isAllowedInstructions(value) {
|
|
184
|
+
return (
|
|
185
|
+
value === null
|
|
186
|
+
|| typeof value === 'string'
|
|
187
|
+
|| Array.isArray(value)
|
|
188
|
+
|| (typeof value === 'object')
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function isAllowedCriteria(value) {
|
|
193
|
+
return isAllowedInstructions(value);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function fail(code, message) {
|
|
197
|
+
const err = new Error(message);
|
|
198
|
+
err.code = code;
|
|
199
|
+
return err;
|
|
200
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {import('./types.js').SamOperationDef} def
|
|
3
|
+
* @returns {import('./types.js').SamOperationDef}
|
|
4
|
+
*/
|
|
5
|
+
export function defineSamOperation(def) {
|
|
6
|
+
if (!def || typeof def !== 'object') {
|
|
7
|
+
throw new TypeError('defineSamOperation requires an operation definition object');
|
|
8
|
+
}
|
|
9
|
+
if (typeof def.id !== 'string' || !def.id.includes('.')) {
|
|
10
|
+
throw new TypeError('defineSamOperation: id must be a dotted operation id (e.g. brand.scan)');
|
|
11
|
+
}
|
|
12
|
+
if (typeof def.handler !== 'function') {
|
|
13
|
+
throw new TypeError(`defineSamOperation(${def.id}): handler must be a function`);
|
|
14
|
+
}
|
|
15
|
+
if (!def.module || !def.action) {
|
|
16
|
+
throw new TypeError(`defineSamOperation(${def.id}): module and action are required`);
|
|
17
|
+
}
|
|
18
|
+
if (!def.execution?.lanes?.length || !def.execution.model || !def.execution.network || !def.execution.sideEffects) {
|
|
19
|
+
throw new TypeError(`defineSamOperation(${def.id}): execution.{lanes,model,network,sideEffects} required`);
|
|
20
|
+
}
|
|
21
|
+
if (!def.risk) {
|
|
22
|
+
throw new TypeError(`defineSamOperation(${def.id}): risk is required`);
|
|
23
|
+
}
|
|
24
|
+
if (!def.summary) {
|
|
25
|
+
throw new TypeError(`defineSamOperation(${def.id}): summary is required`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const skill = typeof def.skill === 'string'
|
|
29
|
+
? { id: def.skill, help: true }
|
|
30
|
+
: def.skill === null
|
|
31
|
+
? null
|
|
32
|
+
: (def.skill || undefined);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
...def,
|
|
36
|
+
version: def.version ?? 1,
|
|
37
|
+
status: def.status ?? 'stable',
|
|
38
|
+
purpose: def.purpose || def.description || def.summary,
|
|
39
|
+
outcome: def.outcome || undefined,
|
|
40
|
+
accepts: Array.isArray(def.accepts) ? [...def.accepts] : [],
|
|
41
|
+
phases: Array.isArray(def.phases) ? [...def.phases] : [],
|
|
42
|
+
artifacts: Array.isArray(def.artifacts) ? [...def.artifacts] : [],
|
|
43
|
+
skill,
|
|
44
|
+
execution: {
|
|
45
|
+
embedding: 'never',
|
|
46
|
+
provider_spend: def.execution.model === 'never' ? 'none' : 'possible',
|
|
47
|
+
...def.execution,
|
|
48
|
+
lanes: [...def.execution.lanes],
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
package/src/sam/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SAM — Systematic Autonomous Machinery
|
|
3
|
+
*
|
|
4
|
+
* AgentSam = product / SDK / CLI
|
|
5
|
+
* SAM = execution architecture underneath AgentSam
|
|
6
|
+
* sam = conventional AgentSamClient variable (machinery, not a person)
|
|
7
|
+
*
|
|
8
|
+
* @see docs/architecture/SAM_KERNEL.md
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export { SAM_RESULT_SCHEMA, SAM_EXPANSION } from './types.js';
|
|
12
|
+
export { defineSamOperation } from './define.js';
|
|
13
|
+
export {
|
|
14
|
+
registerSamOperation,
|
|
15
|
+
getSamOperation,
|
|
16
|
+
listSamOperations,
|
|
17
|
+
toSamOperationCard,
|
|
18
|
+
clearSamRegistryForTests,
|
|
19
|
+
} from './registry.js';
|
|
20
|
+
export { buildSamResult, hashJson } from './result.js';
|
|
21
|
+
export { AgentSamClient, createAgentSamClient } from './client.js';
|
|
22
|
+
export { ensureSeedOperations, SEED_OPERATIONS, resetSeedFlagForTests } from './seed.js';
|
|
23
|
+
export {
|
|
24
|
+
planAStar,
|
|
25
|
+
planGoap,
|
|
26
|
+
ASTAR_ENGINE,
|
|
27
|
+
GOAP_ENGINE,
|
|
28
|
+
stableStateKey,
|
|
29
|
+
cloneState,
|
|
30
|
+
applyEffects,
|
|
31
|
+
goalSatisfied,
|
|
32
|
+
preconditionsMet,
|
|
33
|
+
} from './planning/index.js';
|
|
34
|
+
export {
|
|
35
|
+
evaluate as evaluateDecisions,
|
|
36
|
+
evaluateDependentStages,
|
|
37
|
+
buildDecisionState,
|
|
38
|
+
defineChoose,
|
|
39
|
+
defineScore,
|
|
40
|
+
defineCheck,
|
|
41
|
+
applyDecisionPolicy,
|
|
42
|
+
composeUtility,
|
|
43
|
+
createDecisionReceipt,
|
|
44
|
+
appendOutcome,
|
|
45
|
+
attachAction,
|
|
46
|
+
QUESTION_REGISTRY,
|
|
47
|
+
getRegisteredQuestion,
|
|
48
|
+
brierScore,
|
|
49
|
+
logLoss,
|
|
50
|
+
expectedCalibrationError,
|
|
51
|
+
hierarchicalChoose,
|
|
52
|
+
beamRetain,
|
|
53
|
+
createSemanticEvaluator,
|
|
54
|
+
DECISION_STATE_SCHEMA,
|
|
55
|
+
DECISION_RECEIPT_SCHEMA,
|
|
56
|
+
} from './decision/index.js';
|
|
57
|
+
export {
|
|
58
|
+
createActivityEvent,
|
|
59
|
+
createActivityStore,
|
|
60
|
+
activityFromDecision,
|
|
61
|
+
ACTIVITY_SCHEMA,
|
|
62
|
+
ACTIVITY_PHASES,
|
|
63
|
+
ACTIVITY_EVENTS,
|
|
64
|
+
DECISION_ACTIVITY_LABELS,
|
|
65
|
+
} from './activity/index.js';
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { defineSamOperation } from '../define.js';
|
|
2
|
+
import { repositorySnapshot } from '../../capabilities/index.js';
|
|
3
|
+
import { brandScan } from '../../../packages/agentsam-brand/src/index.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Brand intelligence — evidence-backed BrandPack candidate chain (scan remains read-only).
|
|
7
|
+
* Preview/export are separate operations with local_write side effects.
|
|
8
|
+
*/
|
|
9
|
+
export const brandScanOp = defineSamOperation({
|
|
10
|
+
id: 'brand.scan',
|
|
11
|
+
version: 1,
|
|
12
|
+
module: 'brand',
|
|
13
|
+
action: 'scan',
|
|
14
|
+
summary: 'Audit materials into evidence-backed brand intelligence.',
|
|
15
|
+
purpose:
|
|
16
|
+
'Audit a repository and supplied materials into evidence-backed brand intelligence.',
|
|
17
|
+
outcome:
|
|
18
|
+
'Produce a BrandPack candidate describing observed brand assets, tokens, typography, themes, components, layouts, URLs, content references, conflicts and normalization opportunities.',
|
|
19
|
+
description:
|
|
20
|
+
'Deterministic evidence extraction over repository.snapshot authority — tokens, assets, typography, components, conflicts. Does not mutate the source tree.',
|
|
21
|
+
skill: { id: 'agentsam-app-fundamentals', help: true },
|
|
22
|
+
accepts: [
|
|
23
|
+
'repository', 'directory', 'html', 'css', 'javascript', 'typescript',
|
|
24
|
+
'image', 'svg', 'archive', 'glb', 'gltf', 'text',
|
|
25
|
+
],
|
|
26
|
+
phases: [
|
|
27
|
+
'inventory',
|
|
28
|
+
'evidence',
|
|
29
|
+
'brand-observation',
|
|
30
|
+
'normalization',
|
|
31
|
+
'theme-proposal',
|
|
32
|
+
'brandpack',
|
|
33
|
+
],
|
|
34
|
+
execution: {
|
|
35
|
+
lanes: ['local', 'remote', 'sandbox'],
|
|
36
|
+
model: 'optional',
|
|
37
|
+
embedding: 'never',
|
|
38
|
+
network: 'optional',
|
|
39
|
+
sideEffects: 'none',
|
|
40
|
+
provider_spend: 'possible',
|
|
41
|
+
},
|
|
42
|
+
risk: 'read_only',
|
|
43
|
+
capabilities: ['brand.scan', 'repository.snapshot'],
|
|
44
|
+
artifacts: ['brandpack.candidate', 'brand.evidence', 'theme.proposal'],
|
|
45
|
+
preview: { available: true, operation: 'brand.preview' },
|
|
46
|
+
cli: { command: [['brand', 'scan']] },
|
|
47
|
+
docs: { section: 'Brand', examples: ['brand-scan-basic'] },
|
|
48
|
+
status: 'stable',
|
|
49
|
+
async handler(input = {}, ctx = {}) {
|
|
50
|
+
const root = typeof input === 'string'
|
|
51
|
+
? input
|
|
52
|
+
: (input.root || input.cwd || ctx.cwd || process.cwd());
|
|
53
|
+
const snapshot = input.snapshot
|
|
54
|
+
|| await repositorySnapshot({ cwd: root, churnDays: 30 });
|
|
55
|
+
return brandScan({
|
|
56
|
+
cwd: root,
|
|
57
|
+
snapshot,
|
|
58
|
+
maxFiles: input.maxFiles,
|
|
59
|
+
onEvent: input.onEvent,
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineSamOperation } from '../define.js';
|
|
2
|
+
import { blenderInspect } from '../../lib/cad/blender.js';
|
|
3
|
+
|
|
4
|
+
export const cadBlenderInspectOp = defineSamOperation({
|
|
5
|
+
id: 'cad.blender.inspect',
|
|
6
|
+
version: 1,
|
|
7
|
+
module: 'cad',
|
|
8
|
+
action: 'blender.inspect',
|
|
9
|
+
summary: 'Inspect an existing Blender source (.blend).',
|
|
10
|
+
description: 'Host-tool inspect via Blender binary; no model spend. Requires blender on PATH or blenderBin.',
|
|
11
|
+
execution: {
|
|
12
|
+
lanes: ['local', 'remote', 'sandbox'],
|
|
13
|
+
model: 'never',
|
|
14
|
+
network: 'none',
|
|
15
|
+
sideEffects: 'none',
|
|
16
|
+
},
|
|
17
|
+
risk: 'read_only',
|
|
18
|
+
capabilities: ['cad.blender.inspect'],
|
|
19
|
+
cli: { command: [['cad', 'blender', 'inspect']] },
|
|
20
|
+
docs: { section: 'CAD' },
|
|
21
|
+
status: 'stable',
|
|
22
|
+
async handler(input = {}, ctx = {}) {
|
|
23
|
+
const source = input.source || input.input || input.path;
|
|
24
|
+
if (!source) {
|
|
25
|
+
throw Object.assign(new Error('cad.blender.inspect requires source/input'), {
|
|
26
|
+
code: 'sam_invalid_input',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return blenderInspect({
|
|
30
|
+
input: source,
|
|
31
|
+
blenderBin: input.blenderBin,
|
|
32
|
+
timeoutSeconds: input.timeoutSeconds,
|
|
33
|
+
cwd: input.cwd || input.root || ctx.cwd || process.cwd(),
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { defineSamOperation } from '../define.js';
|
|
2
|
+
import { runCodebaseindexIngest } from '../../commands/codebaseindex.js';
|
|
3
|
+
|
|
4
|
+
export const codebaseindexIngestOp = defineSamOperation({
|
|
5
|
+
id: 'codebaseindex.ingest',
|
|
6
|
+
version: 1,
|
|
7
|
+
module: 'codebaseindex',
|
|
8
|
+
action: 'ingest',
|
|
9
|
+
summary: 'Inventory-first ingest into the knowledge / code-intelligence spine.',
|
|
10
|
+
purpose:
|
|
11
|
+
'Acquire materials, inventory the environment, confirm scope, resolve embed/storage lanes, dry-run, then index.',
|
|
12
|
+
outcome:
|
|
13
|
+
'A verified knowledge generation (and optional vectors) with job graph, inventory, and receipt — usable by search/agents without re-learning the product for cloud later.',
|
|
14
|
+
skill: { id: 'agentsam-codebaseindex', help: true },
|
|
15
|
+
accepts: [
|
|
16
|
+
'directory', 'archive', 'html', 'image', 'glb', 'code', 'document', 'repository',
|
|
17
|
+
],
|
|
18
|
+
phases: [
|
|
19
|
+
'material.stage',
|
|
20
|
+
'inventory.classify',
|
|
21
|
+
'scope.resolve',
|
|
22
|
+
'profile.resolve',
|
|
23
|
+
'lane.resolve',
|
|
24
|
+
'plan.dry_run',
|
|
25
|
+
'index.execute',
|
|
26
|
+
'generation.verify',
|
|
27
|
+
],
|
|
28
|
+
execution: {
|
|
29
|
+
lanes: ['local', 'remote', 'platform'],
|
|
30
|
+
model: 'optional',
|
|
31
|
+
embedding: 'optional',
|
|
32
|
+
network: 'optional',
|
|
33
|
+
sideEffects: 'local_write',
|
|
34
|
+
provider_spend: 'possible',
|
|
35
|
+
},
|
|
36
|
+
risk: 'write',
|
|
37
|
+
capabilities: ['knowledge.index', 'knowledge.search', 'repository.snapshot'],
|
|
38
|
+
artifacts: [
|
|
39
|
+
'inventory.v1',
|
|
40
|
+
'codebaseindex.job.graph.v1',
|
|
41
|
+
'knowledge.generation',
|
|
42
|
+
],
|
|
43
|
+
cli: { command: [['codebaseindex'], ['ingest']] },
|
|
44
|
+
docs: { section: 'Codebaseindex', examples: ['codebaseindex-ingest-wizard'] },
|
|
45
|
+
status: 'stable',
|
|
46
|
+
async handler(input = {}, ctx = {}) {
|
|
47
|
+
return runCodebaseindexIngest(input, ctx);
|
|
48
|
+
},
|
|
49
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { defineSamOperation } from '../define.js';
|
|
2
|
+
import { evaluate } from '../decision/evaluate.js';
|
|
3
|
+
import { getRegisteredQuestion, listRegisteredQuestions } from '../decision/questions.js';
|
|
4
|
+
|
|
5
|
+
export const decisionEvaluateOp = defineSamOperation({
|
|
6
|
+
id: 'decision.evaluate',
|
|
7
|
+
version: 1,
|
|
8
|
+
module: 'decision',
|
|
9
|
+
action: 'evaluate',
|
|
10
|
+
summary: 'Evaluate choose/score/check questions against a SAM decision state.',
|
|
11
|
+
purpose:
|
|
12
|
+
'Run a batch of independent typed decision questions against one explicit state.',
|
|
13
|
+
outcome:
|
|
14
|
+
'Return answers, routing, policy result, and an optional decision receipt (/why-compatible).',
|
|
15
|
+
description:
|
|
16
|
+
'Systematic Autonomous Machinery decision layer. Prefer deterministic evaluators; semantic evaluators never invent calibrated probabilities.',
|
|
17
|
+
skill: { id: 'agentsam-app-fundamentals', help: true },
|
|
18
|
+
execution: {
|
|
19
|
+
lanes: ['local', 'remote', 'sandbox'],
|
|
20
|
+
model: 'optional',
|
|
21
|
+
embedding: 'never',
|
|
22
|
+
network: 'optional',
|
|
23
|
+
sideEffects: 'none',
|
|
24
|
+
provider_spend: 'possible',
|
|
25
|
+
},
|
|
26
|
+
risk: 'read_only',
|
|
27
|
+
capabilities: ['decision.evaluate', 'planning.goap'],
|
|
28
|
+
artifacts: ['decision.evaluation', 'decision.receipt'],
|
|
29
|
+
cli: { command: [] },
|
|
30
|
+
docs: { section: 'Decision', examples: ['decision-evaluate-terminal'] },
|
|
31
|
+
status: 'stable',
|
|
32
|
+
async handler(input = {}, ctx = {}) {
|
|
33
|
+
const questions = Array.isArray(input.questions)
|
|
34
|
+
? input.questions.map((q) => {
|
|
35
|
+
if (typeof q === 'string') return getRegisteredQuestion(q, input.overrides?.[q] || {});
|
|
36
|
+
if (q && typeof q === 'object' && typeof q.id === 'string' && !q.type) {
|
|
37
|
+
return getRegisteredQuestion(q.id, q);
|
|
38
|
+
}
|
|
39
|
+
return q;
|
|
40
|
+
})
|
|
41
|
+
: listRegisteredQuestions().slice(0, 0);
|
|
42
|
+
|
|
43
|
+
if (!questions.length) {
|
|
44
|
+
const err = new Error('decision.evaluate requires questions[]');
|
|
45
|
+
err.code = 'invalid_input';
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return evaluate({
|
|
50
|
+
state: input.state || {},
|
|
51
|
+
questions,
|
|
52
|
+
policy: input.policy || {},
|
|
53
|
+
receipt: input.receipt !== false,
|
|
54
|
+
action: input.action,
|
|
55
|
+
evaluators: input.evaluators,
|
|
56
|
+
signal: ctx.signal,
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
});
|