@entrorove/skill 0.1.6 → 0.1.21

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/releases.json CHANGED
@@ -1,4 +1,94 @@
1
1
  [
2
+ {
3
+ "version": "0.1.21",
4
+ "date": "2026-10-04",
5
+ "zh": "更新了本地执行闸门与预算。",
6
+ "en": "Updated local execution gates and budgets."
7
+ },
8
+ {
9
+ "version": "0.1.20",
10
+ "date": "2026-10-04",
11
+ "zh": "更新了本地状态并发锁、本地执行闸门与预算、执行与链路台账。",
12
+ "en": "Updated local state concurrency lock, local execution gates and budgets, execution and chain ledger."
13
+ },
14
+ {
15
+ "version": "0.1.19",
16
+ "date": "2026-10-04",
17
+ "zh": "更新了安装包配置、自动版本与更新日志、本地状态并发锁、本地执行闸门与预算、预算续期确认、本地任务路由。",
18
+ "en": "Updated package configuration, automatic versioning and changelog, local state concurrency lock, local execution gates and budgets, budget renewal confirmation, local task routing."
19
+ },
20
+ {
21
+ "version": "0.1.18",
22
+ "date": "2026-10-04",
23
+ "zh": "更新了冻结计划执行器。",
24
+ "en": "Updated frozen plan runner."
25
+ },
26
+ {
27
+ "version": "0.1.17",
28
+ "date": "2026-10-04",
29
+ "zh": "更新了本地执行命令、冻结计划执行器。",
30
+ "en": "Updated local execution command, frozen plan runner."
31
+ },
32
+ {
33
+ "version": "0.1.16",
34
+ "date": "2026-10-04",
35
+ "zh": "更新了远端恢复客户端。",
36
+ "en": "Updated remote recovery client."
37
+ },
38
+ {
39
+ "version": "0.1.15",
40
+ "date": "2026-10-04",
41
+ "zh": "更新了IDE 工作流程说明。",
42
+ "en": "Updated IDE workflow instructions."
43
+ },
44
+ {
45
+ "version": "0.1.14",
46
+ "date": "2026-10-02",
47
+ "zh": "更新了本地执行闸门与预算。",
48
+ "en": "Updated local execution gates and budgets."
49
+ },
50
+ {
51
+ "version": "0.1.13",
52
+ "date": "2026-10-02",
53
+ "zh": "更新了执行与链路台账、预算续期确认、本地任务路由。",
54
+ "en": "Updated execution and chain ledger, budget renewal confirmation, local task routing."
55
+ },
56
+ {
57
+ "version": "0.1.12",
58
+ "date": "2026-10-02",
59
+ "zh": "更新了远端恢复客户端。",
60
+ "en": "Updated remote recovery client."
61
+ },
62
+ {
63
+ "version": "0.1.11",
64
+ "date": "2026-10-02",
65
+ "zh": "更新了本地执行闸门与预算。",
66
+ "en": "Updated local execution gates and budgets."
67
+ },
68
+ {
69
+ "version": "0.1.10",
70
+ "date": "2026-10-02",
71
+ "zh": "更新了本地执行闸门与预算。",
72
+ "en": "Updated local execution gates and budgets."
73
+ },
74
+ {
75
+ "version": "0.1.9",
76
+ "date": "2026-10-02",
77
+ "zh": "更新了自动版本与更新日志、本地执行闸门与预算、证据与回执验签、执行与链路台账、冻结计划执行器。",
78
+ "en": "Updated automatic versioning and changelog, local execution gates and budgets, evidence and receipt verification, execution and chain ledger, frozen plan runner."
79
+ },
80
+ {
81
+ "version": "0.1.8",
82
+ "date": "2026-10-02",
83
+ "zh": "恢复本地执行层与质量闭环:快照隔离、签名写入、预算、协作、验证回执、公式和任务路由。",
84
+ "en": "Restored the local execution and quality workflow: snapshots, signed writes, budgets, coordination, receipts, formulas, and task routing."
85
+ },
86
+ {
87
+ "version": "0.1.7",
88
+ "date": "2026-10-02",
89
+ "zh": "恢复统一技能全集、本地执行层与安全复制流程。",
90
+ "en": "Restored the complete unified skill set, local execution layer, and secure copy flow."
91
+ },
2
92
  {
3
93
  "version": "0.1.6",
4
94
  "date": "2026-09-29",
@@ -0,0 +1,91 @@
1
+ import { createHash } from 'node:crypto';
2
+
3
+ export const apiUrl = 'https://entrorove.com/api/skill/invoke';
4
+
5
+ function canonical(value) {
6
+ if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;
7
+ if (value && typeof value === 'object') {
8
+ return `{${Object.keys(value).sort().map(key => `${JSON.stringify(key)}:${canonical(value[key])}`).join(',')}}`;
9
+ }
10
+ return JSON.stringify(value);
11
+ }
12
+
13
+ function requestId(operation, input) {
14
+ return createHash('sha256').update(operation + canonical(input)).digest('hex');
15
+ }
16
+
17
+ export function buildInvocation(operation, input) {
18
+ if (!['capabilities', 'task-describe', 'message-route', 'message-accept', 'task-resume', 'start', 'continue'].includes(operation)) throw new Error('Invalid entrorove operation');
19
+ if (!input || typeof input !== 'object' || Array.isArray(input)) throw new Error('Input must be a JSON object');
20
+ const id = requestId(operation, input);
21
+ return { url: apiUrl, requestId: id, body: { schemaVersion: 'entrorove.skill.request/2.0', requestId: id, operation, input } };
22
+ }
23
+
24
+ async function readResponse(response, label) {
25
+ try { return await response.json(); } catch { throw new Error(`Invalid ${label} response`); }
26
+ }
27
+
28
+ function preTlsRetryable(error) {
29
+ const code = error?.cause?.code ?? error?.code;
30
+ return ['ECONNRESET', 'ECONNREFUSED', 'EAI_AGAIN', 'ENETUNREACH', 'ENETDOWN',
31
+ 'EHOSTUNREACH', 'ETIMEDOUT', 'ECONNABORTED', 'UND_ERR_CONNECT_TIMEOUT'].includes(code);
32
+ }
33
+
34
+ async function readOnlyGet(url, headers, label) {
35
+ let last;
36
+ for (let attempt = 0; attempt < 3; attempt += 1) {
37
+ try {
38
+ return await fetch(url, { method: 'GET', redirect: 'error', signal: AbortSignal.timeout(15_000), headers });
39
+ } catch (error) {
40
+ last = error;
41
+ if (!preTlsRetryable(error) || attempt === 2) break;
42
+ }
43
+ }
44
+ throw new Error(`Unable to read ${label}; ${last instanceof Error ? last.message : 'network error'}`);
45
+ }
46
+
47
+ export async function invokeRemote(data, dependencies) {
48
+ const { install, agreementAccepted, agreementRequired, readCredential, home, apiOrigin } = dependencies;
49
+ await install();
50
+ if (!await agreementAccepted(home)) {
51
+ process.stdout.write(JSON.stringify(agreementRequired(home)) + '\n');
52
+ process.exitCode = 2;
53
+ return;
54
+ }
55
+ const call = buildInvocation(data.operation, data.input);
56
+ const token = await readCredential(home);
57
+ let response;
58
+ try {
59
+ response = await fetch(call.url, {
60
+ method: 'POST', redirect: 'error', signal: AbortSignal.timeout(135_000),
61
+ headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
62
+ body: JSON.stringify(call.body),
63
+ });
64
+ } catch {
65
+ throw new Error(`Invocation outcome is unknown; requestId=${call.requestId}. Do not automatically resend this request.`);
66
+ }
67
+ const result = await readResponse(response, 'invocation');
68
+ if (!result || !result.output || result.output.requestId !== call.requestId) {
69
+ throw new Error(`Invalid entrorove response; requestId=${call.requestId}`);
70
+ }
71
+ process.stdout.write(JSON.stringify(result) + '\n');
72
+ if (!response.ok || result.output.status === 'blocked' || result.output.status === 'failed'
73
+ || result.output.status === 'incomplete') process.exitCode = 2;
74
+ }
75
+
76
+ export async function queryStatus(requestId, dependencies) {
77
+ if (typeof requestId !== 'string' || !/^[a-f0-9]{64}$/.test(requestId)) throw new Error('status requires a sha256 requestId');
78
+ const token = await dependencies.readCredential(dependencies.home);
79
+ const response = await readOnlyGet(`${dependencies.apiOrigin()}/api/skill/status/${encodeURIComponent(requestId)}`, { authorization: `Bearer ${token}` }, 'status')
80
+ const result = await readResponse(response, 'status');
81
+ if (!response.ok) throw new Error(`entrorove status failed: HTTP ${response.status}; requestId=${requestId}`);
82
+ process.stdout.write(JSON.stringify(result) + '\n');
83
+ }
84
+
85
+ export async function queryFlows(dependencies) {
86
+ const token = await dependencies.readCredential(dependencies.home);
87
+ const response = await readOnlyGet(`${dependencies.apiOrigin()}/api/skill/flows`, { authorization: `Bearer ${token}` }, 'flow list')
88
+ const result = await readResponse(response, 'flow list');
89
+ if (!response.ok) throw new Error(`entrorove flow list failed: HTTP ${response.status}`);
90
+ process.stdout.write(JSON.stringify(result) + '\n');
91
+ }