@method-ai-hq/sdk 0.0.0-stage → 0.14.3
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/LICENSE +21 -0
- package/README.md +23 -2
- package/dist/packages/contracts/src/identity.d.ts +16 -0
- package/dist/packages/contracts/src/identity.js +41 -0
- package/dist/packages/contracts/src/method-package.d.ts +71 -0
- package/dist/packages/contracts/src/method-package.js +22 -0
- package/dist/packages/method-document/src/conversion-report.d.ts +138 -0
- package/dist/packages/method-document/src/conversion-report.js +23 -0
- package/dist/packages/sdk/examples/daily-briefing/README.md +31 -0
- package/dist/packages/sdk/examples/daily-briefing/TASK.md +3 -0
- package/dist/packages/sdk/examples/daily-briefing/approved-report.md +138 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_artifacts.py +39 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_check_inputs.py +47 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_files.py +31 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_manifest.py +23 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_markdown.py +67 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_progress.py +18 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_render.py +71 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_sessions.py +37 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_times.py +158 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_validation.py +101 -0
- package/dist/packages/sdk/examples/daily-briefing/briefing_website.py +215 -0
- package/dist/packages/sdk/examples/daily-briefing/checks.json +19 -0
- package/dist/packages/sdk/examples/daily-briefing/daily-briefing.method +158 -0
- package/dist/packages/sdk/examples/daily-briefing/inputs.json +1 -0
- package/dist/packages/sdk/examples/daily-briefing/package-lock.json +10 -0
- package/dist/packages/sdk/examples/daily-briefing/package.json +4 -0
- package/dist/packages/sdk/examples/daily-briefing/pyproject.toml +8 -0
- package/dist/packages/sdk/examples/daily-briefing/reader/reader.css +35 -0
- package/dist/packages/sdk/examples/daily-briefing/reader/reader.js +42 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/context.json +1 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/documents/document-001.md +219 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/media.json +1 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/metadata/documents.json +39 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0001.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0002.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0003.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0004.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0005.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0006.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0007.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0008.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0009.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0010.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0011.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0012.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0013.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0014.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0015.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0016.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0017.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0018.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0019.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0020.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0021.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0022.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0023.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0024.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0025.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0026.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0027.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/records/chatgpt-0028.json +49 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/sessions.json +1 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/timeline.jsonl +28 -0
- package/dist/packages/sdk/examples/daily-briefing/sample/untimed.jsonl +0 -0
- package/dist/packages/sdk/examples/daily-briefing/sample-output.zip +0 -0
- package/dist/packages/sdk/examples/daily-briefing/sample-report.md +51 -0
- package/dist/packages/sdk/examples/daily-briefing/uv.lock +128 -0
- package/dist/packages/sdk/examples/daily-briefing/vendor/marked-LICENSE.md +44 -0
- package/dist/packages/sdk/examples/daily-briefing/vendor/marked.mjs +77 -0
- package/dist/packages/sdk/examples/files.json +126 -0
- package/dist/packages/sdk/examples/message-routing/README.md +23 -0
- package/dist/packages/sdk/examples/message-routing/TASK.md +5 -0
- package/dist/packages/sdk/examples/message-routing/choose-destination.mjs +10 -0
- package/dist/packages/sdk/examples/message-routing/create-ticket.mjs +15 -0
- package/dist/packages/sdk/examples/message-routing/inputs.json +1 -0
- package/dist/packages/sdk/examples/message-routing/message-routing.method +45 -0
- package/dist/packages/sdk/examples/message-routing/result.fixture.json +6 -0
- package/dist/packages/sdk/examples/message-routing/routing.mjs +29 -0
- package/dist/packages/sdk/examples/message-routing/routing.test.mjs +27 -0
- package/dist/packages/sdk/examples/message-routing/ticket.method +88 -0
- package/dist/packages/sdk/examples/message-routing/ticket.test.mjs +64 -0
- package/dist/packages/sdk/examples/notes-summary/README.md +23 -0
- package/dist/packages/sdk/examples/notes-summary/TASK.md +3 -0
- package/dist/packages/sdk/examples/notes-summary/cases/dates-in-decisions/case.json +36 -0
- package/dist/packages/sdk/examples/notes-summary/cases/dates-in-decisions/examples.json +16 -0
- package/dist/packages/sdk/examples/notes-summary/cases/dates-in-decisions/files/0 +10 -0
- package/dist/packages/sdk/examples/notes-summary/cases/dates-in-decisions/recording.json +195 -0
- package/dist/packages/sdk/examples/notes-summary/notes/2026-10-05-standup.md +4 -0
- package/dist/packages/sdk/examples/notes-summary/notes/2026-10-07-planning.md +3 -0
- package/dist/packages/sdk/examples/notes-summary/notes-summary.method +54 -0
- package/dist/packages/sdk/examples/notes-summary/out/.keep +0 -0
- package/dist/packages/sdk/examples/notes-summary/read-notes.mjs +4 -0
- package/dist/packages/sdk/examples/notes-summary/save.mjs +7 -0
- package/dist/packages/sdk/examples/outbound-management/README.md +119 -0
- package/dist/packages/sdk/examples/outbound-management/TASK.md +5 -0
- package/dist/packages/sdk/examples/outbound-management/check_plan.py +16 -0
- package/dist/packages/sdk/examples/outbound-management/check_sources.py +14 -0
- package/dist/packages/sdk/examples/outbound-management/crm.py +153 -0
- package/dist/packages/sdk/examples/outbound-management/crm_test.py +141 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/README.md +15 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/crm.json +54 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/day-1/messages.json +29 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/day-2/messages.json +38 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/observations.json +12 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/plan.json +69 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/receipt.json +1 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/state.json +99 -0
- package/dist/packages/sdk/examples/outbound-management/fixtures/tasks.md +16 -0
- package/dist/packages/sdk/examples/outbound-management/inputs.json +4 -0
- package/dist/packages/sdk/examples/outbound-management/outbound.method +277 -0
- package/dist/packages/sdk/examples/outbound-management/read_crm.py +4 -0
- package/dist/packages/sdk/examples/outbound-management/save_day.py +4 -0
- package/dist/packages/sdk/examples/outbound-management/starter/crm.json +11 -0
- package/dist/packages/sdk/examples/social-briefing/README.md +41 -0
- package/dist/packages/sdk/examples/social-briefing/TASK.md +5 -0
- package/dist/packages/sdk/examples/social-briefing/inputs.json +5 -0
- package/dist/packages/sdk/examples/social-briefing/result.fixture.json +14 -0
- package/dist/packages/sdk/examples/social-briefing/social-briefing.method +110 -0
- package/dist/packages/sdk/examples/support-triage/README.md +77 -0
- package/dist/packages/sdk/examples/support-triage/TASK.md +3 -0
- package/dist/packages/sdk/examples/support-triage/cases/double-charge-to-billing/case.json +40 -0
- package/dist/packages/sdk/examples/support-triage/cases/double-charge-to-billing/recording.json +460 -0
- package/dist/packages/sdk/examples/support-triage/fake-helpdesk.mjs +38 -0
- package/dist/packages/sdk/examples/support-triage/helpdesk.mjs +33 -0
- package/dist/packages/sdk/examples/support-triage/inputs.json +1 -0
- package/dist/packages/sdk/examples/support-triage/read-ticket.mjs +8 -0
- package/dist/packages/sdk/examples/support-triage/route.mjs +4 -0
- package/dist/packages/sdk/examples/support-triage/sample-tickets.json +5 -0
- package/dist/packages/sdk/examples/support-triage/set-ticket.mjs +9 -0
- package/dist/packages/sdk/examples/support-triage/support-triage.method +165 -0
- package/dist/packages/sdk/examples/support-triage/triage.mjs +38 -0
- package/dist/packages/sdk/examples/support-triage/triage.test.mjs +68 -0
- package/dist/packages/sdk/observers/mail.delivery/fetch.mjs +87 -0
- package/dist/packages/sdk/observers/mail.delivery/fixtures/bounce-by-recipient.json +1 -0
- package/dist/packages/sdk/observers/mail.delivery/fixtures/bounce.json +1 -0
- package/dist/packages/sdk/observers/mail.delivery/fixtures/delayed.json +1 -0
- package/dist/packages/sdk/observers/mail.delivery/fixtures/delivered.json +1 -0
- package/dist/packages/sdk/observers/mail.delivery/fixtures/empty.json +1 -0
- package/dist/packages/sdk/observers/mail.delivery/fixtures/other-message.json +1 -0
- package/dist/packages/sdk/observers/mail.delivery/judge.mjs +13 -0
- package/dist/packages/sdk/observers/mail.delivery/observer.json +14 -0
- package/dist/packages/sdk/package.json +232 -0
- package/dist/packages/sdk/src/authoring-example.d.ts +91 -0
- package/dist/packages/sdk/src/authoring-example.js +50 -0
- package/dist/packages/sdk/src/authoring-instructions.d.ts +20 -0
- package/dist/packages/sdk/src/authoring-instructions.js +151 -0
- package/dist/packages/sdk/src/authoring-prompt.d.ts +2 -0
- package/dist/packages/sdk/src/authoring-prompt.js +8 -0
- package/dist/packages/sdk/src/authoring.d.ts +10 -0
- package/dist/packages/sdk/src/authoring.js +287 -0
- package/dist/packages/sdk/src/bindings.d.ts +4 -0
- package/dist/packages/sdk/src/bindings.js +124 -0
- package/dist/packages/sdk/src/bridge.d.ts +2 -0
- package/dist/packages/sdk/src/bridge.js +23 -0
- package/dist/packages/sdk/src/browser-runtime/pyproject.toml +5 -0
- package/dist/packages/sdk/src/browser-runtime/tools.json +189 -0
- package/dist/packages/sdk/src/browser-runtime/uv.lock +3894 -0
- package/dist/packages/sdk/src/browser-service.py +127 -0
- package/dist/packages/sdk/src/browser.d.ts +38 -0
- package/dist/packages/sdk/src/browser.js +203 -0
- package/dist/packages/sdk/src/capabilities.d.ts +13 -0
- package/dist/packages/sdk/src/capabilities.js +68 -0
- package/dist/packages/sdk/src/classification-client.d.ts +4 -0
- package/dist/packages/sdk/src/classification-client.js +27 -0
- package/dist/packages/sdk/src/cloud.d.ts +23 -0
- package/dist/packages/sdk/src/cloud.js +43 -0
- package/dist/packages/sdk/src/computer-settings.d.ts +28 -0
- package/dist/packages/sdk/src/computer-settings.js +57 -0
- package/dist/packages/sdk/src/connect.d.ts +47 -0
- package/dist/packages/sdk/src/connect.js +203 -0
- package/dist/packages/sdk/src/current-inspection.d.ts +3 -0
- package/dist/packages/sdk/src/current-inspection.js +146 -0
- package/dist/packages/sdk/src/current-runtime.d.ts +14 -0
- package/dist/packages/sdk/src/current-runtime.js +167 -0
- package/dist/packages/sdk/src/doctor.d.ts +17 -0
- package/dist/packages/sdk/src/doctor.js +68 -0
- package/dist/packages/sdk/src/executable.d.ts +2 -0
- package/dist/packages/sdk/src/executable.js +22 -0
- package/dist/packages/sdk/src/explain-effects.d.ts +32 -0
- package/dist/packages/sdk/src/explain-effects.js +192 -0
- package/dist/packages/sdk/src/explain.d.ts +115 -0
- package/dist/packages/sdk/src/explain.js +441 -0
- package/dist/packages/sdk/src/files.d.ts +9 -0
- package/dist/packages/sdk/src/files.js +50 -0
- package/dist/packages/sdk/src/guard-keys.d.ts +5 -0
- package/dist/packages/sdk/src/guard-keys.js +42 -0
- package/dist/packages/sdk/src/hosted-models.d.ts +49 -0
- package/dist/packages/sdk/src/hosted-models.js +81 -0
- package/dist/packages/sdk/src/improve.d.ts +55 -0
- package/dist/packages/sdk/src/improve.js +159 -0
- package/dist/packages/sdk/src/index.d.ts +13 -0
- package/dist/packages/sdk/src/index.js +13 -0
- package/dist/packages/sdk/src/inspect.d.ts +6 -0
- package/dist/packages/sdk/src/inspect.js +17 -0
- package/dist/packages/sdk/src/link.d.ts +12 -0
- package/dist/packages/sdk/src/link.js +53 -0
- package/dist/packages/sdk/src/local-cli.d.ts +24 -0
- package/dist/packages/sdk/src/local-cli.js +146 -0
- package/dist/packages/sdk/src/local-setup.d.ts +15 -0
- package/dist/packages/sdk/src/local-setup.js +42 -0
- package/dist/packages/sdk/src/method-client.d.ts +30 -0
- package/dist/packages/sdk/src/method-client.js +250 -0
- package/dist/packages/sdk/src/method-files.d.ts +29 -0
- package/dist/packages/sdk/src/method-files.js +93 -0
- package/dist/packages/sdk/src/method-help.d.ts +19 -0
- package/dist/packages/sdk/src/method-help.js +404 -0
- package/dist/packages/sdk/src/method-issues.d.ts +86 -0
- package/dist/packages/sdk/src/method-issues.js +192 -0
- package/dist/packages/sdk/src/method-sync.d.ts +46 -0
- package/dist/packages/sdk/src/method-sync.js +293 -0
- package/dist/packages/sdk/src/method.d.ts +5 -0
- package/dist/packages/sdk/src/method.js +359 -0
- package/dist/packages/sdk/src/model-checks.d.ts +96 -0
- package/dist/packages/sdk/src/model-checks.js +181 -0
- package/dist/packages/sdk/src/outbox.d.ts +120 -0
- package/dist/packages/sdk/src/outbox.js +297 -0
- package/dist/packages/sdk/src/own-model-key.d.ts +22 -0
- package/dist/packages/sdk/src/own-model-key.js +76 -0
- package/dist/packages/sdk/src/prepare.d.ts +24 -0
- package/dist/packages/sdk/src/prepare.js +245 -0
- package/dist/packages/sdk/src/process.d.ts +15 -0
- package/dist/packages/sdk/src/process.js +107 -0
- package/dist/packages/sdk/src/production.d.ts +182 -0
- package/dist/packages/sdk/src/production.js +284 -0
- package/dist/packages/sdk/src/progress.d.ts +12 -0
- package/dist/packages/sdk/src/progress.js +48 -0
- package/dist/packages/sdk/src/proposals.d.ts +73 -0
- package/dist/packages/sdk/src/proposals.js +284 -0
- package/dist/packages/sdk/src/quality.d.ts +82 -0
- package/dist/packages/sdk/src/quality.js +294 -0
- package/dist/packages/sdk/src/result-files.d.ts +5 -0
- package/dist/packages/sdk/src/result-files.js +149 -0
- package/dist/packages/sdk/src/result-transfer.d.ts +21 -0
- package/dist/packages/sdk/src/result-transfer.js +37 -0
- package/dist/packages/sdk/src/run-data.d.ts +11 -0
- package/dist/packages/sdk/src/run-data.js +80 -0
- package/dist/packages/sdk/src/run-method.d.ts +2 -0
- package/dist/packages/sdk/src/run-method.js +2 -0
- package/dist/packages/sdk/src/run-saved.d.ts +5 -0
- package/dist/packages/sdk/src/run-saved.js +138 -0
- package/dist/packages/sdk/src/run-worker.d.ts +6 -0
- package/dist/packages/sdk/src/run-worker.js +131 -0
- package/dist/packages/sdk/src/secrets.d.ts +37 -0
- package/dist/packages/sdk/src/secrets.js +196 -0
- package/dist/packages/sdk/src/update.d.ts +5 -0
- package/dist/packages/sdk/src/update.js +39 -0
- package/dist/packages/sdk/src/versions.d.ts +58 -0
- package/dist/packages/sdk/src/versions.js +144 -0
- package/dist/packages/sdk/src/worker.d.ts +120 -0
- package/dist/packages/sdk/src/worker.js +443 -0
- package/dist/packages/workflow-language/src/execution.d.ts +1 -0
- package/dist/packages/workflow-language/src/execution.js +1 -0
- package/dist/packages/workflow-language/src/inspection.d.ts +990 -0
- package/dist/packages/workflow-language/src/inspection.js +130 -0
- package/dist/packages/workflow-language/src/result-files.d.ts +160 -0
- package/dist/packages/workflow-language/src/result-files.js +67 -0
- package/dist/packages/workflow-language/src/schema.d.ts +207 -0
- package/dist/packages/workflow-language/src/schema.js +56 -0
- package/dist/packages/workflow-language/src/validate.d.ts +11 -0
- package/dist/packages/workflow-language/src/validate.js +77 -0
- package/package.json +230 -4
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
4
|
+
import { versionIdFor } from '../../contracts/src/identity.js';
|
|
5
|
+
import { loadWorkflow, parseDocumentValue, serializeWorkflow } from '../../workflow-language/src/validate.js';
|
|
6
|
+
import { buildPackage } from './method-files.js';
|
|
7
|
+
import { authoringPath, readDocument } from './authoring.js';
|
|
8
|
+
import { Outbox, lastSaved, savedVersions } from './outbox.js';
|
|
9
|
+
export const methodIdPattern = /^wf_[a-f0-9]{32}$/;
|
|
10
|
+
/** A new account Method ID, made on this computer. The first save of this ID creates the Method. */
|
|
11
|
+
export const newMethodId = () => `wf_${randomBytes(16).toString('hex')}`;
|
|
12
|
+
export { versionIdFor };
|
|
13
|
+
/** The Method without its `id:` line: the content that a version holds. */
|
|
14
|
+
export function methodContent(document) { const { id: _id, ...content } = document; return content; }
|
|
15
|
+
const newerFormat = (format) => typeof format === 'string' && /^method\/3\.[0-3]$/.test(format) ? 'method/3.4' : format;
|
|
16
|
+
/**
|
|
17
|
+
* Write `id: METHOD_ID` as the second line of a Method file (after `format:`), and declare method/3.4, the format that
|
|
18
|
+
* has `id`. A JSON file stays JSON. The rest of the file is unchanged.
|
|
19
|
+
*/
|
|
20
|
+
export function writeMethodId(file, id) {
|
|
21
|
+
if (!methodIdPattern.test(id))
|
|
22
|
+
throw Error('Use a Method ID: wf_ and 32 lowercase hexadecimal characters.');
|
|
23
|
+
const path = authoringPath(file), text = readFileSync(path, 'utf8');
|
|
24
|
+
let next;
|
|
25
|
+
if (/^\s*\{/.test(text)) {
|
|
26
|
+
const { format, id: _old, ...rest } = JSON.parse(text);
|
|
27
|
+
next = JSON.stringify({ format: newerFormat(format), id, ...rest }, null, /\n {2}"/.test(text) ? 2 : undefined) + (text.endsWith('\n') ? '\n' : '');
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const lines = text.split('\n').filter(line => !/^id:/.test(line));
|
|
31
|
+
const at = lines.findIndex(line => /^format:/.test(line));
|
|
32
|
+
if (at < 0) {
|
|
33
|
+
const document = parseDocumentValue(text);
|
|
34
|
+
next = serializeWorkflow({ format: newerFormat(document?.format), id, ...methodContent(document) });
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
lines[at] = lines[at].replace(/method\/3\.[0-3]\b/, 'method/3.4');
|
|
38
|
+
lines.splice(at + 1, 0, `id: ${id}`);
|
|
39
|
+
next = lines.join('\n');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const temporary = `${path}.${process.pid}.tmp`;
|
|
43
|
+
try {
|
|
44
|
+
writeFileSync(temporary, next, { mode: 0o600, flag: 'wx' });
|
|
45
|
+
renameSync(temporary, path);
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
if (existsSync(temporary))
|
|
49
|
+
unlinkSync(temporary);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** The file's Method ID; writes a new one when the file has none. */
|
|
53
|
+
export function ensureMethodId(file) {
|
|
54
|
+
const id = readDocument(file).id;
|
|
55
|
+
if (id !== undefined) {
|
|
56
|
+
if (typeof id !== 'string' || !methodIdPattern.test(id))
|
|
57
|
+
throw Error(`The id: line of ${file} is not a Method ID. Run method new-id ${file}.`);
|
|
58
|
+
return id;
|
|
59
|
+
}
|
|
60
|
+
// The id: line needs format 3.4. A file that 3.4 refuses stays unchanged and is not saved; the run continues.
|
|
61
|
+
const original = readFileSync(authoringPath(file), 'utf8');
|
|
62
|
+
const created = newMethodId();
|
|
63
|
+
writeMethodId(file, created);
|
|
64
|
+
try {
|
|
65
|
+
loadWorkflow(methodContent(readDocument(file)));
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
writeFileSync(authoringPath(file), original, { mode: 0o600 });
|
|
69
|
+
throw Error(`Saving writes an id: line, which needs format method/3.4, and 3.4 finds: ${error.message} Fix it, then run again to save.`);
|
|
70
|
+
}
|
|
71
|
+
return created;
|
|
72
|
+
}
|
|
73
|
+
/** Name the steps that differ from the previous version. */
|
|
74
|
+
function changeReason(before, after) {
|
|
75
|
+
if (!before)
|
|
76
|
+
return 'Created with Method CLI.';
|
|
77
|
+
const ids = [...new Set([...Object.keys(before?.steps ?? {}), ...Object.keys(after.steps)])];
|
|
78
|
+
const changed = ids.filter(id => !isDeepStrictEqual(before?.steps?.[id], after.steps[id]));
|
|
79
|
+
return changed.length ? `Changed ${changed.join(', ')}.` : 'Changed the Method outside its steps.';
|
|
80
|
+
}
|
|
81
|
+
/** The Method ID and version ID of a file's current content, computed on this computer; undefined without an id: line. */
|
|
82
|
+
export async function currentVersion(file) {
|
|
83
|
+
const document = readDocument(file);
|
|
84
|
+
if (typeof document.id !== 'string' || !methodIdPattern.test(document.id))
|
|
85
|
+
return undefined;
|
|
86
|
+
const { pack } = await buildPackage(file, loadWorkflow(methodContent(document)));
|
|
87
|
+
return { method_id: document.id, version_id: versionIdFor(document.id, pack.digest) };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Prepare the save of the current file. It sends no request: it computes the version ID from the content and, when
|
|
91
|
+
* this computer has not saved that version yet, puts the files and the version save in the outbox.
|
|
92
|
+
*/
|
|
93
|
+
export async function prepareVersion(client, outbox, file, reason) {
|
|
94
|
+
const id = ensureMethodId(file);
|
|
95
|
+
const workflow = loadWorkflow(methodContent(readDocument(file)));
|
|
96
|
+
const { pack, sources, tooLarge } = await buildPackage(file, workflow);
|
|
97
|
+
const versionId = versionIdFor(id, pack.digest);
|
|
98
|
+
const url = `${client.server}/methods/${id}?version=${versionId}`;
|
|
99
|
+
if (savedVersions(client.server)[versionId])
|
|
100
|
+
return { method_id: id, version_id: versionId, url, unchanged: true, workflow };
|
|
101
|
+
const previous = lastSaved(client.server, id);
|
|
102
|
+
if (tooLarge.length)
|
|
103
|
+
process.stderr.write(`Not saved with this version (over 20 MB each; they stay on this computer): ${tooLarge.join(', ')}\n`);
|
|
104
|
+
for (const f of pack.files)
|
|
105
|
+
outbox.add({ kind: 'file', server: client.server, sha256: f.sha256, size: f.size }, sources[f.sha256]);
|
|
106
|
+
outbox.add({ kind: 'version', server: client.server, method_id: id, version_id: versionId, file: authoringPath(file), body: {
|
|
107
|
+
workflow, package: pack, ...(previous && previous.version_id !== versionId ? { parent_version_id: previous.version_id } : {}),
|
|
108
|
+
reason: reason ?? changeReason(previous?.workflow, workflow),
|
|
109
|
+
} });
|
|
110
|
+
return { method_id: id, version_id: versionId, url, unchanged: false, workflow };
|
|
111
|
+
}
|
|
112
|
+
/** The one line a run prints about its version. */
|
|
113
|
+
export function savedLine(client, outbox, version) {
|
|
114
|
+
const known = savedVersions(client.server)[version.version_id];
|
|
115
|
+
if (known)
|
|
116
|
+
return `Saved as version ${known.version_number}: ${version.url}`;
|
|
117
|
+
const failure = outbox.failure(version.version_id);
|
|
118
|
+
return failure ? `Not saved to your Method account: ${failure}` : 'Will save when online.';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Publish the current file: save its version (waiting for the upload, with no fixed time limit), check the cases,
|
|
122
|
+
* then mark that version published with the reason.
|
|
123
|
+
*/
|
|
124
|
+
export async function publish(client, file, reason, accepted = []) {
|
|
125
|
+
if (accepted.length && !reason)
|
|
126
|
+
throw Error('Give --reason with --accept-failing-case. The reason is saved with the published version.');
|
|
127
|
+
const { startBackgroundExplain, waitForExplain } = await import('./explain.js');
|
|
128
|
+
await waitForExplain(file);
|
|
129
|
+
// Only errors block a publish; the open warnings and notes are listed with the result.
|
|
130
|
+
const { publishIssues } = await import('./method-issues.js');
|
|
131
|
+
const issues = await publishIssues(client, file);
|
|
132
|
+
const outbox = new Outbox(client);
|
|
133
|
+
const version = await prepareVersion(client, outbox, file, reason);
|
|
134
|
+
await outbox.drain();
|
|
135
|
+
if (!await outbox.whenSaved(version.version_id))
|
|
136
|
+
throw Error(`${outbox.failure(version.version_id) ?? 'Method cannot be reached, so the version is not uploaded yet.'} Nothing was published. Run method publish again.`);
|
|
137
|
+
const gate = await (await import('./quality.js')).caseGate(authoringPath(file), accepted, reason);
|
|
138
|
+
const publishReason = [reason ?? 'Published.', gate.line].filter(Boolean).join(' ');
|
|
139
|
+
const published = await client.request(`/api/cli/methods/${encodeURIComponent(version.method_id)}/versions/${encodeURIComponent(version.version_id)}/publish`, 'POST', { reason: publishReason });
|
|
140
|
+
// Script cards never hold up a publish: cards that a run did not make yet are made in the background.
|
|
141
|
+
startBackgroundExplain(file, version.workflow, version.version_id, client.server);
|
|
142
|
+
return { workflow_id: version.method_id, version_id: version.version_id, version_number: published.version_number ?? savedVersions(client.server)[version.version_id]?.version_number,
|
|
143
|
+
url: version.url, unchanged: version.unchanged, ...(gate.line ? { cases: gate.line } : {}), ...issues, published_at: published.published_at, publish_reason: published.publish_reason };
|
|
144
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { MethodClient } from "./method-client.js";
|
|
2
|
+
import type { ServiceApi } from "./production.js";
|
|
3
|
+
type Answer = {
|
|
4
|
+
outputs: Record<string, unknown>;
|
|
5
|
+
} | {
|
|
6
|
+
sealed: string;
|
|
7
|
+
};
|
|
8
|
+
export type Claim = {
|
|
9
|
+
run_id: string;
|
|
10
|
+
method_id: string;
|
|
11
|
+
version_id: string;
|
|
12
|
+
inputs: Record<string, unknown>;
|
|
13
|
+
sealed_inputs?: string;
|
|
14
|
+
lease_id: string;
|
|
15
|
+
lease_ms: number;
|
|
16
|
+
attempt: number;
|
|
17
|
+
run_data: "account" | "device";
|
|
18
|
+
/** The run waited for answers before. */
|
|
19
|
+
resume?: boolean;
|
|
20
|
+
snapshot?: boolean;
|
|
21
|
+
/** Answers by STEP:ITERATION, opened by the worker before the executor runs. */
|
|
22
|
+
answers?: Record<string, Answer>;
|
|
23
|
+
};
|
|
24
|
+
/** A question of an ask step: STEP:ITERATION, the question text, and the JSON Schema of the answer. */
|
|
25
|
+
export type Question = {
|
|
26
|
+
step: string;
|
|
27
|
+
question: string;
|
|
28
|
+
form: Record<string, unknown>;
|
|
29
|
+
};
|
|
30
|
+
export type Outcome = {
|
|
31
|
+
status: "succeeded" | "failed" | "cancelled";
|
|
32
|
+
result?: unknown;
|
|
33
|
+
error?: {
|
|
34
|
+
code?: string;
|
|
35
|
+
message: string;
|
|
36
|
+
};
|
|
37
|
+
retryable?: boolean;
|
|
38
|
+
} | {
|
|
39
|
+
status: "waiting";
|
|
40
|
+
question: Question;
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
};
|
|
43
|
+
export type Executor = (claim: Claim, context: {
|
|
44
|
+
directory: string;
|
|
45
|
+
runDir: string;
|
|
46
|
+
signal: AbortSignal;
|
|
47
|
+
api: ServiceApi;
|
|
48
|
+
}) => Promise<Outcome>;
|
|
49
|
+
export type WorkerResult = {
|
|
50
|
+
run_id: string;
|
|
51
|
+
method_id: string;
|
|
52
|
+
version_id: string;
|
|
53
|
+
status: "succeeded" | "failed" | "cancelled";
|
|
54
|
+
run_data: Claim["run_data"];
|
|
55
|
+
result?: unknown;
|
|
56
|
+
error?: {
|
|
57
|
+
code?: string;
|
|
58
|
+
message: string;
|
|
59
|
+
};
|
|
60
|
+
run_dir: string;
|
|
61
|
+
};
|
|
62
|
+
export type WorkerOptions = {
|
|
63
|
+
/** Claim only runs of these Methods. Default: every Method of the organization. A Set may grow while the worker runs. */
|
|
64
|
+
methods?: string[] | Set<string>;
|
|
65
|
+
/** Runs at the same time in this worker. Default 1. */
|
|
66
|
+
concurrency?: number;
|
|
67
|
+
workerId?: string;
|
|
68
|
+
/** How long one claim request waits on the server. Default 25 s; 0 polls. */
|
|
69
|
+
waitMs?: number;
|
|
70
|
+
/** Called with each finished run before the server marks it finished. A device run's result exists only here. */
|
|
71
|
+
onResult?: (result: WorkerResult) => void | Promise<void>;
|
|
72
|
+
/** Called when a run starts to wait for an answer, after the server has the question. */
|
|
73
|
+
onWaiting?: (run: {
|
|
74
|
+
run_id: string;
|
|
75
|
+
method_id: string;
|
|
76
|
+
question: Question;
|
|
77
|
+
}) => void | Promise<void>;
|
|
78
|
+
onError?: (error: Error) => void;
|
|
79
|
+
/** Where run folders are kept. Default ~/.cache/method/worker. A claim of the same run resumes its folder. */
|
|
80
|
+
directory?: string;
|
|
81
|
+
execute?: Executor;
|
|
82
|
+
};
|
|
83
|
+
export declare class ProductionWorker {
|
|
84
|
+
readonly api: ServiceApi;
|
|
85
|
+
readonly options: WorkerOptions;
|
|
86
|
+
readonly id: string;
|
|
87
|
+
done: Promise<void>;
|
|
88
|
+
private readonly stopping;
|
|
89
|
+
private readonly active;
|
|
90
|
+
private cancelActive;
|
|
91
|
+
constructor(api: ServiceApi, options?: WorkerOptions);
|
|
92
|
+
get running(): boolean;
|
|
93
|
+
start(): this;
|
|
94
|
+
/** Stop claiming. Running runs finish, unless cancel is true: then they stop and go back to the queue. */
|
|
95
|
+
stop(options?: {
|
|
96
|
+
cancel?: boolean;
|
|
97
|
+
}): Promise<void>;
|
|
98
|
+
private report;
|
|
99
|
+
private loop;
|
|
100
|
+
private handle;
|
|
101
|
+
private send;
|
|
102
|
+
/** Open sealed inputs and answers with this worker's credential. */
|
|
103
|
+
private open;
|
|
104
|
+
/** Save the run folder, report the question, and let go of the run. */
|
|
105
|
+
private wait;
|
|
106
|
+
/** Get the saved run folder. It goes back to the path it had, when this computer can write there, so the run can resume. */
|
|
107
|
+
private restore;
|
|
108
|
+
}
|
|
109
|
+
/** The run folder as gzip JSON: its own path and each file. */
|
|
110
|
+
export declare function packFolder(dir: string): Buffer;
|
|
111
|
+
export declare function unpackFolder(packed: Uint8Array, fallback: string): string;
|
|
112
|
+
/** The last question the runtime asked in a run folder: the human.required event. */
|
|
113
|
+
export declare function lastQuestion(dir: string): Question | null;
|
|
114
|
+
/** Run a claim with `method run METHOD_ID --version VERSION_ID` in a child process, then read its summary. */
|
|
115
|
+
export declare function cliExecutor(options?: {
|
|
116
|
+
command?: string[];
|
|
117
|
+
}): Executor;
|
|
118
|
+
/** `method worker` and `method keys`. */
|
|
119
|
+
export declare function productionCommand(args: string[], clientFactory: (server: string) => MethodClient): Promise<void>;
|
|
120
|
+
export {};
|