@sapiom/agent-core 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/dist/cjs/analytics.d.ts +4 -0
- package/dist/cjs/analytics.js +97 -0
- package/dist/cjs/check.d.ts +1 -0
- package/dist/cjs/check.js +7 -4
- package/dist/cjs/deploy.js +26 -0
- package/dist/cjs/link.js +23 -0
- package/dist/cjs/local/run-local.js +7 -0
- package/dist/cjs/run.js +23 -0
- package/dist/esm/analytics.d.ts +4 -0
- package/dist/esm/analytics.js +59 -0
- package/dist/esm/check.d.ts +1 -0
- package/dist/esm/check.js +8 -5
- package/dist/esm/deploy.js +26 -0
- package/dist/esm/link.js +23 -0
- package/dist/esm/local/run-local.js +7 -0
- package/dist/esm/run.js +23 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/templates/coding-pause/.claude/skills/sapiom-agent-authoring/SKILL.md +408 -0
- package/templates/coding-pause/AGENTS.md +4 -2
- package/templates/default/.claude/skills/sapiom-agent-authoring/SKILL.md +408 -0
- package/templates/default/AGENTS.md +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# @sapiom/orchestration-core
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d661d57: Emit workflow lifecycle usage analytics from the agent package family via `@sapiom/analytics-core` (source `"agent"`).
|
|
8
|
+
|
|
9
|
+
- `@sapiom/agent-core`: `link` / `deploy` / `run` emit one `workflow.link` / `workflow.deploy` / `workflow.run` event each, carrying metadata only — workflow name/id, duration, status, and a machine-readable error code on failure (never inputs, outputs, or error messages). The emitter is constructed lazily at the operation call boundary; `GatewayClient` stays env-free. `runLocal` emits the runtime's step lifecycle events flagged `local: true`.
|
|
10
|
+
- `@sapiom/agent-runtime`: `AgentRunnerCore` accepts an optional `analytics` sink (new `RuntimeAnalytics` host interface — a structural `track()` method, no new dependency) and emits `step.start` / `step.complete` / `step.error` with step name, attempt, and timing. No sink → no events, byte-for-byte previous behavior.
|
|
11
|
+
|
|
12
|
+
Telemetry ships dark: without a collector endpoint configured (`SAPIOM_ANALYTICS_ENDPOINT`) every `track` is a silent no-op — zero network calls, zero disk writes. Opt out any time with `SAPIOM_TELEMETRY_DISABLED=1` or `DO_NOT_TRACK=1`. Emission is synchronous enqueue-only and can never change an operation's behavior, results, or errors — collector outages included.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [3f25008]
|
|
17
|
+
- Updated dependencies [55462b3]
|
|
18
|
+
- Updated dependencies [d661d57]
|
|
19
|
+
- Updated dependencies [aee376a]
|
|
20
|
+
- @sapiom/analytics-core@0.2.0
|
|
21
|
+
- @sapiom/agent-runtime@0.4.0
|
|
22
|
+
- @sapiom/tools@0.17.0
|
|
23
|
+
- @sapiom/agent@0.6.2
|
|
24
|
+
|
|
25
|
+
## 0.8.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- 3dfbd10: Ship the `sapiom-agent-authoring` skill with every scaffold, and finish the MCP
|
|
30
|
+
instructions rename.
|
|
31
|
+
|
|
32
|
+
- New canonical skill (`agent-core/skills/sapiom-agent-authoring/SKILL.md`) with a
|
|
33
|
+
task-shape trigger ("automate a multi-step / scheduled / deployable task"), the full
|
|
34
|
+
authoring guide (`defineAgent`, directives, pause/resume, stubs), and a bootstrap
|
|
35
|
+
step for agents whose client doesn't have the sapiom-dev MCP yet.
|
|
36
|
+
- Both scaffold templates ship it at `.claude/skills/sapiom-agent-authoring/` (auto-loads
|
|
37
|
+
as a project skill in Claude Code) and `AGENTS.md` points to it, so every scaffolded
|
|
38
|
+
project self-documents. A sync test keeps template copies identical to the canonical.
|
|
39
|
+
- `@sapiom/mcp`'s bundled instructions fallback rewritten to the agents/models
|
|
40
|
+
vocabulary (the rename left it on the old text), thinned to lifecycle + canonical
|
|
41
|
+
rules + pointers — deep guidance lives in the skill/AGENTS.md/docs.
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- 020139a: `check()` now recognizes workflow definitions authored against the pre-rename SDK: `@sapiom/agent` exports `isLegacyOrchestrationDefinition`/`LEGACY_ORCHESTRATION_DEFINITION_BRAND` (the `Symbol.for('sapiom.orchestration.definition')` brand the old `defineOrchestration` attached), and `@sapiom/agent-core`'s `check()` accepts either brand in its export detection — the definition shape is unchanged by the rename, so manifests build identically. `check()` also gains a `typecheck` option (default `true`): pass `typecheck: false` to skip the project's `tsc --noEmit` when only the manifest/graph is needed (esbuild still surfaces bundle-level breakage).
|
|
46
|
+
- Updated dependencies [020139a]
|
|
47
|
+
- @sapiom/agent@0.6.1
|
|
48
|
+
|
|
3
49
|
## 0.7.0
|
|
4
50
|
|
|
5
51
|
### Minor Changes
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type SapiomAnalytics } from "@sapiom/analytics-core";
|
|
2
|
+
export declare function getOrchestrationAnalytics(): SapiomAnalytics;
|
|
3
|
+
export declare function resetOrchestrationAnalyticsForTesting(): void;
|
|
4
|
+
export declare function telemetryErrorCode(err: unknown): string;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getOrchestrationAnalytics = getOrchestrationAnalytics;
|
|
37
|
+
exports.resetOrchestrationAnalyticsForTesting = resetOrchestrationAnalyticsForTesting;
|
|
38
|
+
exports.telemetryErrorCode = telemetryErrorCode;
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const node_url_1 = require("node:url");
|
|
42
|
+
const analytics_core_1 = require("@sapiom/analytics-core");
|
|
43
|
+
const errors_js_1 = require("./errors.js");
|
|
44
|
+
function resolveModuleDir() {
|
|
45
|
+
if (typeof __dirname !== "undefined")
|
|
46
|
+
return __dirname;
|
|
47
|
+
try {
|
|
48
|
+
const metaUrl = eval("import.meta.url");
|
|
49
|
+
if (typeof metaUrl === "string")
|
|
50
|
+
return path.dirname((0, node_url_1.fileURLToPath)(metaUrl));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
}
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
function readOwnVersion() {
|
|
57
|
+
try {
|
|
58
|
+
const moduleDir = resolveModuleDir();
|
|
59
|
+
for (const levelsUp of ["..", path.join("..", "..")]) {
|
|
60
|
+
const candidate = path.join(moduleDir, levelsUp, "package.json");
|
|
61
|
+
if (!fs.existsSync(candidate))
|
|
62
|
+
continue;
|
|
63
|
+
const parsed = JSON.parse(fs.readFileSync(candidate, "utf8"));
|
|
64
|
+
if (parsed.name === "@sapiom/agent-core" &&
|
|
65
|
+
typeof parsed.version === "string") {
|
|
66
|
+
return parsed.version;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
}
|
|
72
|
+
return "0.0.0";
|
|
73
|
+
}
|
|
74
|
+
let instance = null;
|
|
75
|
+
function getOrchestrationAnalytics() {
|
|
76
|
+
if (instance === null) {
|
|
77
|
+
instance = (0, analytics_core_1.createAnalytics)({
|
|
78
|
+
source: "agent",
|
|
79
|
+
sdkName: "@sapiom/agent-core",
|
|
80
|
+
sdkVersion: readOwnVersion(),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return instance;
|
|
84
|
+
}
|
|
85
|
+
function resetOrchestrationAnalyticsForTesting() {
|
|
86
|
+
const previous = instance;
|
|
87
|
+
instance = null;
|
|
88
|
+
if (previous)
|
|
89
|
+
void previous.shutdown();
|
|
90
|
+
}
|
|
91
|
+
function telemetryErrorCode(err) {
|
|
92
|
+
if (err instanceof errors_js_1.AgentOperationError)
|
|
93
|
+
return err.code;
|
|
94
|
+
if (err instanceof Error)
|
|
95
|
+
return err.name;
|
|
96
|
+
return "UnknownError";
|
|
97
|
+
}
|
package/dist/cjs/check.d.ts
CHANGED
package/dist/cjs/check.js
CHANGED
|
@@ -76,9 +76,11 @@ async function check(opts) {
|
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
const warnings = [];
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
if (opts.typecheck !== false) {
|
|
80
|
+
const typecheckSkip = runTypecheck(sourceDir);
|
|
81
|
+
if (typecheckSkip)
|
|
82
|
+
warnings.push(typecheckSkip);
|
|
83
|
+
}
|
|
82
84
|
const tmp = (0, node_fs_1.mkdtempSync)(node_path_1.default.join((0, node_os_1.tmpdir)(), 'sapiom-check-'));
|
|
83
85
|
const bundlePath = node_path_1.default.join(tmp, 'definition.mjs');
|
|
84
86
|
try {
|
|
@@ -103,8 +105,9 @@ async function check(opts) {
|
|
|
103
105
|
const mod = await Promise.resolve(`${`file://${bundlePath}?t=${Date.now()}`}`).then(s => __importStar(require(s)));
|
|
104
106
|
const defs = [];
|
|
105
107
|
for (const value of Object.values(mod)) {
|
|
106
|
-
if ((0, agent_1.isAgentDefinition)(value) && !defs.includes(value))
|
|
108
|
+
if (((0, agent_1.isAgentDefinition)(value) || (0, agent_1.isLegacyOrchestrationDefinition)(value)) && !defs.includes(value)) {
|
|
107
109
|
defs.push(value);
|
|
110
|
+
}
|
|
108
111
|
}
|
|
109
112
|
if (defs.length === 0) {
|
|
110
113
|
throw new errors_js_1.AgentOperationError({
|
package/dist/cjs/deploy.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.deploy = deploy;
|
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
8
|
const node_os_1 = require("node:os");
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const analytics_js_1 = require("./analytics.js");
|
|
10
11
|
const bundle_js_1 = require("./bundle.js");
|
|
11
12
|
const errors_js_1 = require("./errors.js");
|
|
12
13
|
const git_js_1 = require("./git.js");
|
|
@@ -15,6 +16,31 @@ const POLL_DELAYS_MS = [1000, 2000, 3000, 5000, 5000, 8000, 10000];
|
|
|
15
16
|
const POLL_BUDGET_MS = 300000;
|
|
16
17
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
18
|
async function deploy(opts, client) {
|
|
19
|
+
const startedAt = Date.now();
|
|
20
|
+
try {
|
|
21
|
+
const result = await deployOperation(opts, client);
|
|
22
|
+
(0, analytics_js_1.getOrchestrationAnalytics)().track('workflow.deploy', {
|
|
23
|
+
workflow_id: opts.definitionId,
|
|
24
|
+
branch: opts.branch ?? 'main',
|
|
25
|
+
build_run_id: result.buildRunId,
|
|
26
|
+
build_status: result.status,
|
|
27
|
+
status: 'success',
|
|
28
|
+
duration_ms: Date.now() - startedAt,
|
|
29
|
+
});
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
(0, analytics_js_1.getOrchestrationAnalytics)().track('workflow.deploy', {
|
|
34
|
+
workflow_id: opts.definitionId,
|
|
35
|
+
branch: opts.branch ?? 'main',
|
|
36
|
+
status: 'error',
|
|
37
|
+
error_code: (0, analytics_js_1.telemetryErrorCode)(err),
|
|
38
|
+
duration_ms: Date.now() - startedAt,
|
|
39
|
+
});
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function deployOperation(opts, client) {
|
|
18
44
|
const { projectDir, definitionId, branch = 'main' } = opts;
|
|
19
45
|
(0, git_js_1.assertDeployable)(projectDir);
|
|
20
46
|
const { code, dependencies } = await (0, bundle_js_1.bundleForDeploy)(projectDir);
|
package/dist/cjs/link.js
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.link = link;
|
|
4
|
+
const analytics_js_1 = require("./analytics.js");
|
|
4
5
|
const errors_js_1 = require("./errors.js");
|
|
5
6
|
async function link(opts, client) {
|
|
7
|
+
const startedAt = Date.now();
|
|
8
|
+
try {
|
|
9
|
+
const result = await linkOperation(opts, client);
|
|
10
|
+
(0, analytics_js_1.getOrchestrationAnalytics)().track('workflow.link', {
|
|
11
|
+
workflow_id: result.definitionId,
|
|
12
|
+
workflow_name: result.name,
|
|
13
|
+
status: 'success',
|
|
14
|
+
duration_ms: Date.now() - startedAt,
|
|
15
|
+
});
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
(0, analytics_js_1.getOrchestrationAnalytics)().track('workflow.link', {
|
|
20
|
+
workflow_name: opts.name,
|
|
21
|
+
status: 'error',
|
|
22
|
+
error_code: (0, analytics_js_1.telemetryErrorCode)(err),
|
|
23
|
+
duration_ms: Date.now() - startedAt,
|
|
24
|
+
});
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function linkOperation(opts, client) {
|
|
6
29
|
const list = await client.get('/definitions');
|
|
7
30
|
let def = list.find((d) => d.name === opts.name || d.slug === opts.name);
|
|
8
31
|
if (!def) {
|
|
@@ -9,6 +9,7 @@ exports.runLocalFromDir = runLocalFromDir;
|
|
|
9
9
|
const node_fs_1 = require("node:fs");
|
|
10
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
11
11
|
const agent_runtime_1 = require("@sapiom/agent-runtime");
|
|
12
|
+
const analytics_js_1 = require("../analytics.js");
|
|
12
13
|
const errors_js_1 = require("../errors.js");
|
|
13
14
|
const dispatcher_js_1 = require("./dispatcher.js");
|
|
14
15
|
const load_js_1 = require("./load.js");
|
|
@@ -39,10 +40,16 @@ async function runLocal(opts) {
|
|
|
39
40
|
const dispatcher = new dispatcher_js_1.LocalStubDispatcher(opts.definition, stubs);
|
|
40
41
|
const signals = new Map();
|
|
41
42
|
dispatcher.setSignals(signals);
|
|
43
|
+
const analytics = (0, analytics_js_1.getOrchestrationAnalytics)();
|
|
42
44
|
const core = new agent_runtime_1.AgentRunnerCore({
|
|
43
45
|
store,
|
|
44
46
|
dispatcher,
|
|
45
47
|
observer: agent_runtime_1.NOOP_OBSERVER,
|
|
48
|
+
analytics: {
|
|
49
|
+
track(eventType, data) {
|
|
50
|
+
analytics.track(eventType, { ...data, local: true });
|
|
51
|
+
},
|
|
52
|
+
},
|
|
46
53
|
});
|
|
47
54
|
dispatcher.setCore(core);
|
|
48
55
|
dispatcher.setMaxAttempts(max);
|
package/dist/cjs/run.js
CHANGED
|
@@ -2,8 +2,31 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.run = run;
|
|
4
4
|
exports.parseJsonInput = parseJsonInput;
|
|
5
|
+
const analytics_js_1 = require("./analytics.js");
|
|
5
6
|
const errors_js_1 = require("./errors.js");
|
|
6
7
|
async function run(opts, client) {
|
|
8
|
+
const startedAt = Date.now();
|
|
9
|
+
try {
|
|
10
|
+
const result = await runOperation(opts, client);
|
|
11
|
+
(0, analytics_js_1.getOrchestrationAnalytics)().track('workflow.run', {
|
|
12
|
+
workflow_id: opts.definitionId,
|
|
13
|
+
execution_id: result.executionId,
|
|
14
|
+
status: 'success',
|
|
15
|
+
duration_ms: Date.now() - startedAt,
|
|
16
|
+
});
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
(0, analytics_js_1.getOrchestrationAnalytics)().track('workflow.run', {
|
|
21
|
+
workflow_id: opts.definitionId,
|
|
22
|
+
status: 'error',
|
|
23
|
+
error_code: (0, analytics_js_1.telemetryErrorCode)(err),
|
|
24
|
+
duration_ms: Date.now() - startedAt,
|
|
25
|
+
});
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function runOperation(opts, client) {
|
|
7
30
|
const { definitionId, input = {} } = opts;
|
|
8
31
|
const res = await client.post('/executions', { definitionId, input });
|
|
9
32
|
const executionId = res.executionId ?? res.id;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type SapiomAnalytics } from "@sapiom/analytics-core";
|
|
2
|
+
export declare function getOrchestrationAnalytics(): SapiomAnalytics;
|
|
3
|
+
export declare function resetOrchestrationAnalyticsForTesting(): void;
|
|
4
|
+
export declare function telemetryErrorCode(err: unknown): string;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { createAnalytics } from "@sapiom/analytics-core";
|
|
5
|
+
import { AgentOperationError } from "./errors.js";
|
|
6
|
+
function resolveModuleDir() {
|
|
7
|
+
if (typeof __dirname !== "undefined")
|
|
8
|
+
return __dirname;
|
|
9
|
+
try {
|
|
10
|
+
const metaUrl = eval("import.meta.url");
|
|
11
|
+
if (typeof metaUrl === "string")
|
|
12
|
+
return path.dirname(fileURLToPath(metaUrl));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
}
|
|
16
|
+
return "";
|
|
17
|
+
}
|
|
18
|
+
function readOwnVersion() {
|
|
19
|
+
try {
|
|
20
|
+
const moduleDir = resolveModuleDir();
|
|
21
|
+
for (const levelsUp of ["..", path.join("..", "..")]) {
|
|
22
|
+
const candidate = path.join(moduleDir, levelsUp, "package.json");
|
|
23
|
+
if (!fs.existsSync(candidate))
|
|
24
|
+
continue;
|
|
25
|
+
const parsed = JSON.parse(fs.readFileSync(candidate, "utf8"));
|
|
26
|
+
if (parsed.name === "@sapiom/agent-core" &&
|
|
27
|
+
typeof parsed.version === "string") {
|
|
28
|
+
return parsed.version;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
}
|
|
34
|
+
return "0.0.0";
|
|
35
|
+
}
|
|
36
|
+
let instance = null;
|
|
37
|
+
export function getOrchestrationAnalytics() {
|
|
38
|
+
if (instance === null) {
|
|
39
|
+
instance = createAnalytics({
|
|
40
|
+
source: "agent",
|
|
41
|
+
sdkName: "@sapiom/agent-core",
|
|
42
|
+
sdkVersion: readOwnVersion(),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return instance;
|
|
46
|
+
}
|
|
47
|
+
export function resetOrchestrationAnalyticsForTesting() {
|
|
48
|
+
const previous = instance;
|
|
49
|
+
instance = null;
|
|
50
|
+
if (previous)
|
|
51
|
+
void previous.shutdown();
|
|
52
|
+
}
|
|
53
|
+
export function telemetryErrorCode(err) {
|
|
54
|
+
if (err instanceof AgentOperationError)
|
|
55
|
+
return err.code;
|
|
56
|
+
if (err instanceof Error)
|
|
57
|
+
return err.name;
|
|
58
|
+
return "UnknownError";
|
|
59
|
+
}
|
package/dist/esm/check.d.ts
CHANGED
package/dist/esm/check.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createHash } from 'node:crypto';
|
|
|
3
3
|
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
-
import { assertValidGraph, buildManifest, isAgentDefinition, agentManifestSchema } from '@sapiom/agent';
|
|
6
|
+
import { assertValidGraph, buildManifest, isAgentDefinition, isLegacyOrchestrationDefinition, agentManifestSchema, } from '@sapiom/agent';
|
|
7
7
|
import * as esbuild from 'esbuild';
|
|
8
8
|
import { AgentOperationError } from './errors.js';
|
|
9
9
|
function runTypecheck(sourceDir) {
|
|
@@ -37,9 +37,11 @@ export async function check(opts) {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
const warnings = [];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
if (opts.typecheck !== false) {
|
|
41
|
+
const typecheckSkip = runTypecheck(sourceDir);
|
|
42
|
+
if (typecheckSkip)
|
|
43
|
+
warnings.push(typecheckSkip);
|
|
44
|
+
}
|
|
43
45
|
const tmp = mkdtempSync(path.join(tmpdir(), 'sapiom-check-'));
|
|
44
46
|
const bundlePath = path.join(tmp, 'definition.mjs');
|
|
45
47
|
try {
|
|
@@ -64,8 +66,9 @@ export async function check(opts) {
|
|
|
64
66
|
const mod = await import(`file://${bundlePath}?t=${Date.now()}`);
|
|
65
67
|
const defs = [];
|
|
66
68
|
for (const value of Object.values(mod)) {
|
|
67
|
-
if (isAgentDefinition(value) && !defs.includes(value))
|
|
69
|
+
if ((isAgentDefinition(value) || isLegacyOrchestrationDefinition(value)) && !defs.includes(value)) {
|
|
68
70
|
defs.push(value);
|
|
71
|
+
}
|
|
69
72
|
}
|
|
70
73
|
if (defs.length === 0) {
|
|
71
74
|
throw new AgentOperationError({
|
package/dist/esm/deploy.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { tmpdir } from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { getOrchestrationAnalytics, telemetryErrorCode } from './analytics.js';
|
|
4
5
|
import { bundleForDeploy } from './bundle.js';
|
|
5
6
|
import { AgentOperationError } from './errors.js';
|
|
6
7
|
import { assertDeployable, pushSynthesizedTree } from './git.js';
|
|
@@ -9,6 +10,31 @@ const POLL_DELAYS_MS = [1000, 2000, 3000, 5000, 5000, 8000, 10000];
|
|
|
9
10
|
const POLL_BUDGET_MS = 300000;
|
|
10
11
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
11
12
|
export async function deploy(opts, client) {
|
|
13
|
+
const startedAt = Date.now();
|
|
14
|
+
try {
|
|
15
|
+
const result = await deployOperation(opts, client);
|
|
16
|
+
getOrchestrationAnalytics().track('workflow.deploy', {
|
|
17
|
+
workflow_id: opts.definitionId,
|
|
18
|
+
branch: opts.branch ?? 'main',
|
|
19
|
+
build_run_id: result.buildRunId,
|
|
20
|
+
build_status: result.status,
|
|
21
|
+
status: 'success',
|
|
22
|
+
duration_ms: Date.now() - startedAt,
|
|
23
|
+
});
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
getOrchestrationAnalytics().track('workflow.deploy', {
|
|
28
|
+
workflow_id: opts.definitionId,
|
|
29
|
+
branch: opts.branch ?? 'main',
|
|
30
|
+
status: 'error',
|
|
31
|
+
error_code: telemetryErrorCode(err),
|
|
32
|
+
duration_ms: Date.now() - startedAt,
|
|
33
|
+
});
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function deployOperation(opts, client) {
|
|
12
38
|
const { projectDir, definitionId, branch = 'main' } = opts;
|
|
13
39
|
assertDeployable(projectDir);
|
|
14
40
|
const { code, dependencies } = await bundleForDeploy(projectDir);
|
package/dist/esm/link.js
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
|
+
import { getOrchestrationAnalytics, telemetryErrorCode } from './analytics.js';
|
|
1
2
|
import { AgentOperationError } from './errors.js';
|
|
2
3
|
export async function link(opts, client) {
|
|
4
|
+
const startedAt = Date.now();
|
|
5
|
+
try {
|
|
6
|
+
const result = await linkOperation(opts, client);
|
|
7
|
+
getOrchestrationAnalytics().track('workflow.link', {
|
|
8
|
+
workflow_id: result.definitionId,
|
|
9
|
+
workflow_name: result.name,
|
|
10
|
+
status: 'success',
|
|
11
|
+
duration_ms: Date.now() - startedAt,
|
|
12
|
+
});
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
getOrchestrationAnalytics().track('workflow.link', {
|
|
17
|
+
workflow_name: opts.name,
|
|
18
|
+
status: 'error',
|
|
19
|
+
error_code: telemetryErrorCode(err),
|
|
20
|
+
duration_ms: Date.now() - startedAt,
|
|
21
|
+
});
|
|
22
|
+
throw err;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function linkOperation(opts, client) {
|
|
3
26
|
const list = await client.get('/definitions');
|
|
4
27
|
let def = list.find((d) => d.name === opts.name || d.slug === opts.name);
|
|
5
28
|
if (!def) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { DEFAULT_MAX_ATTEMPTS_PER_STEP, InMemoryExecutionStore, NOOP_OBSERVER, AgentRunnerCore, } from "@sapiom/agent-runtime";
|
|
4
|
+
import { getOrchestrationAnalytics } from "../analytics.js";
|
|
4
5
|
import { AgentOperationError } from "../errors.js";
|
|
5
6
|
import { LocalStubDispatcher } from "./dispatcher.js";
|
|
6
7
|
import { loadDefinition } from "./load.js";
|
|
@@ -31,10 +32,16 @@ export async function runLocal(opts) {
|
|
|
31
32
|
const dispatcher = new LocalStubDispatcher(opts.definition, stubs);
|
|
32
33
|
const signals = new Map();
|
|
33
34
|
dispatcher.setSignals(signals);
|
|
35
|
+
const analytics = getOrchestrationAnalytics();
|
|
34
36
|
const core = new AgentRunnerCore({
|
|
35
37
|
store,
|
|
36
38
|
dispatcher,
|
|
37
39
|
observer: NOOP_OBSERVER,
|
|
40
|
+
analytics: {
|
|
41
|
+
track(eventType, data) {
|
|
42
|
+
analytics.track(eventType, { ...data, local: true });
|
|
43
|
+
},
|
|
44
|
+
},
|
|
38
45
|
});
|
|
39
46
|
dispatcher.setCore(core);
|
|
40
47
|
dispatcher.setMaxAttempts(max);
|
package/dist/esm/run.js
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
|
+
import { getOrchestrationAnalytics, telemetryErrorCode } from './analytics.js';
|
|
1
2
|
import { AgentOperationError } from './errors.js';
|
|
2
3
|
export async function run(opts, client) {
|
|
4
|
+
const startedAt = Date.now();
|
|
5
|
+
try {
|
|
6
|
+
const result = await runOperation(opts, client);
|
|
7
|
+
getOrchestrationAnalytics().track('workflow.run', {
|
|
8
|
+
workflow_id: opts.definitionId,
|
|
9
|
+
execution_id: result.executionId,
|
|
10
|
+
status: 'success',
|
|
11
|
+
duration_ms: Date.now() - startedAt,
|
|
12
|
+
});
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
getOrchestrationAnalytics().track('workflow.run', {
|
|
17
|
+
workflow_id: opts.definitionId,
|
|
18
|
+
status: 'error',
|
|
19
|
+
error_code: telemetryErrorCode(err),
|
|
20
|
+
duration_ms: Date.now() - startedAt,
|
|
21
|
+
});
|
|
22
|
+
throw err;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function runOperation(opts, client) {
|
|
3
26
|
const { definitionId, input = {} } = opts;
|
|
4
27
|
const res = await client.post('/executions', { definitionId, input });
|
|
5
28
|
const executionId = res.executionId ?? res.id;
|