@plotday/twister 0.61.0 → 0.63.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/dist/connector.d.ts +14 -0
- package/dist/connector.d.ts.map +1 -1
- package/dist/connector.js +14 -0
- package/dist/connector.js.map +1 -1
- package/dist/docs/assets/hierarchy.js +1 -1
- package/dist/docs/assets/search.js +1 -1
- package/dist/docs/classes/index.Connector.html +47 -26
- package/dist/docs/classes/index.FileNotFoundError.html +1 -1
- package/dist/docs/classes/index.Files.html +1 -1
- package/dist/docs/classes/index.Imap.html +1 -1
- package/dist/docs/classes/index.Options.html +1 -1
- package/dist/docs/classes/index.Smtp.html +1 -1
- package/dist/docs/classes/tool.ITool.html +1 -1
- package/dist/docs/classes/tool.Tool.html +17 -7
- package/dist/docs/classes/tools_ai.AI.html +1 -1
- package/dist/docs/classes/tools_callbacks.Callbacks.html +1 -1
- package/dist/docs/classes/tools_integrations.Integrations.html +1 -1
- package/dist/docs/classes/tools_network.Network.html +1 -1
- package/dist/docs/classes/tools_plot.Plot.html +1 -1
- package/dist/docs/classes/tools_store.Store.html +1 -1
- package/dist/docs/classes/tools_tasks.Tasks.html +40 -14
- package/dist/docs/classes/tools_twists.Twists.html +1 -1
- package/dist/docs/classes/twist.Twist.html +21 -11
- package/dist/docs/documents/Built-in_Tools.html +15 -13
- package/dist/docs/documents/Runtime_Environment.html +7 -5
- package/dist/docs/hierarchy.html +1 -1
- package/dist/docs/media/AGENTS.md +23 -19
- package/dist/llm-docs/connector.d.ts +1 -1
- package/dist/llm-docs/connector.d.ts.map +1 -1
- package/dist/llm-docs/connector.js +1 -1
- package/dist/llm-docs/connector.js.map +1 -1
- package/dist/llm-docs/tool.d.ts +1 -1
- package/dist/llm-docs/tool.d.ts.map +1 -1
- package/dist/llm-docs/tool.js +1 -1
- package/dist/llm-docs/tool.js.map +1 -1
- package/dist/llm-docs/tools/tasks.d.ts +1 -1
- package/dist/llm-docs/tools/tasks.d.ts.map +1 -1
- package/dist/llm-docs/tools/tasks.js +1 -1
- package/dist/llm-docs/tools/tasks.js.map +1 -1
- package/dist/llm-docs/twist.d.ts +1 -1
- package/dist/llm-docs/twist.d.ts.map +1 -1
- package/dist/llm-docs/twist.js +1 -1
- package/dist/llm-docs/twist.js.map +1 -1
- package/dist/tool.d.ts +16 -0
- package/dist/tool.d.ts.map +1 -1
- package/dist/tool.js +15 -0
- package/dist/tool.js.map +1 -1
- package/dist/tools/tasks.d.ts +58 -12
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js.map +1 -1
- package/dist/twist.d.ts +16 -0
- package/dist/twist.d.ts.map +1 -1
- package/dist/twist.js +15 -0
- package/dist/twist.js.map +1 -1
- package/dist/utils/markdown-html.d.ts +15 -0
- package/dist/utils/markdown-html.d.ts.map +1 -0
- package/dist/utils/markdown-html.js +35 -0
- package/dist/utils/markdown-html.js.map +1 -0
- package/package.json +7 -1
- package/src/connector.ts +15 -0
- package/src/llm-docs/connector.ts +1 -1
- package/src/llm-docs/tool.ts +1 -1
- package/src/llm-docs/tools/tasks.ts +1 -1
- package/src/llm-docs/twist.ts +1 -1
- package/src/tool.ts +20 -0
- package/src/tools/tasks.ts +61 -12
- package/src/twist.ts +20 -0
- package/src/utils/markdown-html.ts +40 -0
package/src/tools/tasks.ts
CHANGED
|
@@ -134,18 +134,19 @@ export abstract class Tasks extends ITool {
|
|
|
134
134
|
abstract cancelAllTasks(): Promise<void>;
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
* Schedules a **singleton** task identified by `key`: scheduling
|
|
138
|
-
* that already has a pending task atomically cancels the existing
|
|
139
|
-
* replaces it. At most one scheduled task per `key` is ever live.
|
|
140
|
-
*
|
|
141
|
-
* Use this for
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
137
|
+
* Schedules a **one-shot singleton** task identified by `key`: scheduling
|
|
138
|
+
* under a key that already has a pending task atomically cancels the existing
|
|
139
|
+
* one and replaces it. At most one scheduled task per `key` is ever live.
|
|
140
|
+
*
|
|
141
|
+
* Use this for **one-shot keyed deferred work** — a single future task whose
|
|
142
|
+
* pending occurrence should be atomically replaced if re-scheduled (e.g.
|
|
143
|
+
* a deferred cleanup, a one-time expiry action, a single future send).
|
|
144
|
+
*
|
|
145
|
+
* For **recurring/self-renewing jobs** (watch renewals, polling loops,
|
|
146
|
+
* periodic syncs, self-heal checks), use {@link scheduleRecurring} instead.
|
|
147
|
+
* It owns the cadence on the platform side, so the chain survives dropped
|
|
148
|
+
* runs, suspensions, and deploys without the callback needing to reschedule
|
|
149
|
+
* itself.
|
|
149
150
|
*
|
|
150
151
|
* Replacement is atomic on the server, so concurrent executions racing to
|
|
151
152
|
* schedule the same key converge on a single task rather than leaking.
|
|
@@ -184,4 +185,52 @@ export abstract class Tasks extends ITool {
|
|
|
184
185
|
*/
|
|
185
186
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
186
187
|
abstract cancelScheduledTask(key: string): Promise<void>;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Schedules a **durable recurring** task identified by `key`. Unlike
|
|
191
|
+
* {@link scheduleTask} (one-shot, deleted when it fires), a recurring task's
|
|
192
|
+
* next occurrence is owned by the platform: the runtime re-arms it every
|
|
193
|
+
* `intervalMs` automatically, so the chain survives a dropped queue message,
|
|
194
|
+
* a suspension, a deploy/eviction, or a callback that throws before it could
|
|
195
|
+
* reschedule. The callback just does the work, idempotently — it does NOT
|
|
196
|
+
* need to reschedule itself.
|
|
197
|
+
*
|
|
198
|
+
* `intervalMs` is a **safety ceiling** (the maximum gap between fires). For
|
|
199
|
+
* data-dependent cadence (e.g. renew 24h before a provider-returned expiry),
|
|
200
|
+
* pass `firstRunAt` for the precise next fire and re-call `scheduleRecurring`
|
|
201
|
+
* with the same key on each run to keep tightening it; the ceiling guarantees
|
|
202
|
+
* the chain still fires if a run is lost. `firstRunAt` can pull the next fire
|
|
203
|
+
* earlier than the ceiling but never later.
|
|
204
|
+
*
|
|
205
|
+
* Recurring tasks are keyed/singleton: re-scheduling under the same key
|
|
206
|
+
* atomically replaces the pending occurrence (one live task per key). Tear
|
|
207
|
+
* down with {@link cancelScheduledTask}.
|
|
208
|
+
*
|
|
209
|
+
* @param key - Stable identifier, scoped to what it maintains, e.g.
|
|
210
|
+
* `` `watch-renewal:${folderId}` `` or `"mailbox-self-heal"`.
|
|
211
|
+
* @param callback - Callback created with `this.callback()`.
|
|
212
|
+
* @param options.intervalMs - Safety-ceiling cadence in milliseconds.
|
|
213
|
+
* @param options.firstRunAt - Optional precise time for the next fire
|
|
214
|
+
* (clamped to no later than now + intervalMs).
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* // Fixed cadence (self-heal, polling): register once, never reschedule.
|
|
219
|
+
* const cb = await this.callback(this.selfHealCheck);
|
|
220
|
+
* await this.scheduleRecurring("mailbox-self-heal", cb, { intervalMs: 60 * 60 * 1000 });
|
|
221
|
+
*
|
|
222
|
+
* // Variable cadence (watch renewal): precise firstRunAt + safety ceiling.
|
|
223
|
+
* const renew = await this.callback(this.renewWatch, folderId);
|
|
224
|
+
* await this.scheduleRecurring(`watch-renewal:${folderId}`, renew, {
|
|
225
|
+
* intervalMs: 3.5 * 24 * 60 * 60 * 1000, // ceiling: half the 7-day watch
|
|
226
|
+
* firstRunAt: new Date(expiry.getTime() - 24 * 60 * 60 * 1000),
|
|
227
|
+
* });
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
231
|
+
abstract scheduleRecurring(
|
|
232
|
+
key: string,
|
|
233
|
+
callback: Callback,
|
|
234
|
+
options: { intervalMs: number; firstRunAt?: Date }
|
|
235
|
+
): Promise<void>;
|
|
187
236
|
}
|
package/src/twist.ts
CHANGED
|
@@ -327,6 +327,26 @@ export abstract class Twist<TSelf> {
|
|
|
327
327
|
return this.tools.tasks.cancelScheduledTask(key);
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
/**
|
|
331
|
+
* Schedules a durable recurring task under a stable key. The platform
|
|
332
|
+
* re-arms the task every `intervalMs` automatically — the callback does NOT
|
|
333
|
+
* need to reschedule itself. Re-scheduling under the same key atomically
|
|
334
|
+
* replaces the pending occurrence (at most one live task per key). Tear down
|
|
335
|
+
* with {@link cancelScheduledTask}. See {@link Tasks.scheduleRecurring}.
|
|
336
|
+
*
|
|
337
|
+
* @param key - Stable identifier, e.g. `"mailbox-self-heal"`
|
|
338
|
+
* @param callback - Callback token created with `this.callback()`
|
|
339
|
+
* @param options.intervalMs - Safety-ceiling cadence in milliseconds
|
|
340
|
+
* @param options.firstRunAt - Optional precise time for the next fire
|
|
341
|
+
*/
|
|
342
|
+
protected async scheduleRecurring(
|
|
343
|
+
key: string,
|
|
344
|
+
callback: Callback,
|
|
345
|
+
options: { intervalMs: number; firstRunAt?: Date }
|
|
346
|
+
): Promise<void> {
|
|
347
|
+
return this.tools.tasks.scheduleRecurring(key, callback, options);
|
|
348
|
+
}
|
|
349
|
+
|
|
330
350
|
/**
|
|
331
351
|
* Called when the twist is installed by a user.
|
|
332
352
|
*
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render Plot Markdown note content to HTML, for connectors that send the
|
|
3
|
+
* note out to a system whose native format is HTML email (Gmail, Outlook
|
|
4
|
+
* Mail). Kept separate from {@link markdownToPlainText} so connectors that
|
|
5
|
+
* only need the plain-text path don't pull the Markdown parser into their
|
|
6
|
+
* bundle (`sideEffects: false` lets the unused module tree-shake away).
|
|
7
|
+
*/
|
|
8
|
+
import { marked } from "marked";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Convert Markdown to an HTML fragment suitable for an email body.
|
|
12
|
+
*
|
|
13
|
+
* - Plot mentions `[Name](#@UUID)` render as plain `@Name` text rather than a
|
|
14
|
+
* broken link to the internal `#@UUID` href.
|
|
15
|
+
* - GitHub-flavoured Markdown is enabled, and single newlines become `<br>`
|
|
16
|
+
* (`breaks: true`) so a message reads the way the author wrote it — the same
|
|
17
|
+
* convention chat-style products (Slack, GitHub comments) use.
|
|
18
|
+
*
|
|
19
|
+
* Returns an HTML fragment (e.g. `<p>…</p>`), not a full document; the caller
|
|
20
|
+
* wraps it for its transport (a `text/html` MIME part, a Graph `body`, etc.).
|
|
21
|
+
* Empty/blank input yields an empty string.
|
|
22
|
+
*/
|
|
23
|
+
export function markdownToHtml(markdown: string | null | undefined): string {
|
|
24
|
+
if (!markdown || markdown.trim() === "") return "";
|
|
25
|
+
|
|
26
|
+
// Render mentions as "@Name" text before parsing so marked doesn't emit an
|
|
27
|
+
// anchor pointing at the internal "#@UUID" href.
|
|
28
|
+
const withMentions = markdown.replace(
|
|
29
|
+
/\[([^\]]+)\]\(#@[^)]+\)/g,
|
|
30
|
+
(_m, name: string) => `@${name}`
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const html = marked.parse(withMentions, {
|
|
34
|
+
async: false,
|
|
35
|
+
gfm: true,
|
|
36
|
+
breaks: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return (html as string).trim();
|
|
40
|
+
}
|