@fastagent-sh/fastagent 0.28.0 → 0.30.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/README.md +10 -4
- package/dist/atomic-write.d.ts +4 -5
- package/dist/atomic-write.js +4 -5
- package/dist/authoring.d.ts +32 -15
- package/dist/authoring.js +147 -127
- package/dist/channels/agentcore-protocol.d.ts +8 -3
- package/dist/channels/agentcore-protocol.js +3 -1
- package/dist/channels/agentcore-service.d.ts +1 -0
- package/dist/channels/agentcore-service.js +14 -4
- package/dist/channels/agentcore.d.ts +9 -0
- package/dist/channels/agentcore.js +29 -4
- package/dist/channels/context.d.ts +2 -0
- package/dist/channels/context.js +5 -1
- package/dist/channels/feishu/feishu-api.d.ts +3 -1
- package/dist/channels/feishu/feishu-api.js +4 -0
- package/dist/channels/feishu/feishu.d.ts +0 -3
- package/dist/channels/feishu/feishu.js +10 -10
- package/dist/channels/feishu/register-app.d.ts +2 -0
- package/dist/channels/feishu/register-app.js +4 -6
- package/dist/channels/feishu/scaffold/channel.ts +32 -34
- package/dist/channels/feishu/scaffold/feishu-send.ts +5 -5
- package/dist/channels/feishu/scaffold/feishu-threads.ts +3 -3
- package/dist/channels/feishu/setup-mode.d.ts +2 -12
- package/dist/channels/feishu/setup-mode.js +2 -22
- package/dist/channels/feishu/setup.d.ts +12 -0
- package/dist/channels/feishu/setup.js +197 -0
- package/dist/channels/kit/abortable.d.ts +8 -0
- package/dist/channels/kit/abortable.js +22 -0
- package/dist/channels/lark/lark.d.ts +0 -3
- package/dist/channels/lark/lark.js +0 -5
- package/dist/channels/lark/scaffold/channel.ts +33 -35
- package/dist/channels/lark/scaffold/lark-send.ts +5 -5
- package/dist/channels/lark/scaffold/lark-threads.ts +3 -3
- package/dist/channels/lark/setup.d.ts +9 -0
- package/dist/channels/lark/setup.js +57 -0
- package/dist/channels/setup.d.ts +112 -0
- package/dist/channels/setup.js +31 -0
- package/dist/channels/slack/history.js +1 -1
- package/dist/channels/slack/manifest.d.ts +17 -7
- package/dist/channels/slack/manifest.js +12 -16
- package/dist/channels/slack/scaffold/channel.ts +44 -30
- package/dist/channels/slack/scaffold/slack-send.ts +8 -8
- package/dist/channels/slack/scaffold/slack-threads.ts +4 -4
- package/dist/channels/slack/setup.d.ts +7 -0
- package/dist/channels/slack/setup.js +119 -0
- package/dist/channels/slack/slack-api.d.ts +2 -0
- package/dist/channels/slack/slack-api.js +4 -0
- package/dist/channels/slack/slack.d.ts +21 -2
- package/dist/channels/slack/slack.js +398 -338
- package/dist/channels/slack/socket.d.ts +57 -0
- package/dist/channels/slack/socket.js +305 -0
- package/dist/channels/telegram/polling.d.ts +27 -0
- package/dist/channels/telegram/polling.js +105 -0
- package/dist/channels/telegram/scaffold/channel.ts +52 -32
- package/dist/channels/telegram/scaffold/telegram-send.ts +9 -9
- package/dist/channels/telegram/setup.d.ts +2 -0
- package/dist/channels/telegram/setup.js +42 -0
- package/dist/channels/telegram/telegram-api.d.ts +27 -1
- package/dist/channels/telegram/telegram-api.js +7 -6
- package/dist/channels/telegram/telegram.d.ts +11 -3
- package/dist/channels/telegram/telegram.js +184 -157
- package/dist/channels/wait-health.js +1 -1
- package/dist/channels/webhook-evidence.d.ts +11 -0
- package/dist/channels/webhook-evidence.js +71 -0
- package/dist/channels/webhooks.d.ts +37 -0
- package/dist/channels/webhooks.js +70 -0
- package/dist/child-env.d.ts +16 -0
- package/dist/child-env.js +30 -0
- package/dist/cli/box-login.js +4 -1
- package/dist/cli/channel-app.d.ts +3 -0
- package/dist/cli/channel-app.js +35 -0
- package/dist/cli/channel-setup.d.ts +38 -0
- package/dist/cli/channel-setup.js +195 -0
- package/dist/cli/commands/add.d.ts +6 -14
- package/dist/cli/commands/add.js +45 -310
- package/dist/cli/commands/auth.js +8 -2
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.js +16 -0
- package/dist/cli/commands/channels.d.ts +19 -0
- package/dist/cli/commands/channels.js +230 -0
- package/dist/cli/commands/content.d.ts +7 -3
- package/dist/cli/commands/content.js +16 -10
- package/dist/cli/commands/deploy/agentcore.js +55 -23
- package/dist/cli/commands/deploy/channel-apps.d.ts +17 -0
- package/dist/cli/commands/deploy/channel-apps.js +30 -0
- package/dist/cli/commands/deploy/docker.js +32 -65
- package/dist/cli/commands/deploy/fly.js +28 -12
- package/dist/cli/commands/deploy/railway.js +38 -13
- package/dist/cli/commands/deploy/secrets-step.d.ts +19 -0
- package/dist/cli/commands/deploy/secrets-step.js +66 -0
- package/dist/cli/commands/deploy/shared.d.ts +16 -5
- package/dist/cli/commands/deploy/shared.js +25 -8
- package/dist/cli/commands/deploy.js +53 -67
- package/dist/cli/commands/dev.d.ts +2 -0
- package/dist/cli/commands/dev.js +15 -3
- package/dist/cli/commands/env.js +1 -1
- package/dist/cli/commands/info.d.ts +2 -0
- package/dist/cli/commands/info.js +63 -24
- package/dist/cli/commands/init.js +3 -1
- package/dist/cli/commands/invoke.d.ts +2 -0
- package/dist/cli/commands/invoke.js +20 -7
- package/dist/cli/commands/login.d.ts +0 -7
- package/dist/cli/commands/login.js +22 -10
- package/dist/cli/commands/logout.js +1 -1
- package/dist/cli/commands/mcp.d.ts +12 -0
- package/dist/cli/commands/mcp.js +164 -0
- package/dist/cli/commands/models.js +3 -2
- package/dist/cli/commands/schedules.d.ts +4 -2
- package/dist/cli/commands/schedules.js +14 -10
- package/dist/cli/commands/secrets.d.ts +14 -0
- package/dist/cli/commands/secrets.js +213 -0
- package/dist/cli/commands/start.d.ts +14 -14
- package/dist/cli/commands/start.js +46 -60
- package/dist/cli/content-view.d.ts +4 -6
- package/dist/cli/content-view.js +5 -11
- package/dist/cli/first-run-channels.d.ts +3 -0
- package/dist/cli/first-run-channels.js +63 -0
- package/dist/cli/instance.d.ts +41 -0
- package/dist/cli/instance.js +155 -0
- package/dist/cli/invoke-stream.d.ts +5 -2
- package/dist/cli/invoke-stream.js +7 -2
- package/dist/cli/program.js +339 -108
- package/dist/cli/serve.d.ts +4 -5
- package/dist/cli/serve.js +4 -7
- package/dist/cli/shared.d.ts +11 -2
- package/dist/cli/shared.js +32 -19
- package/dist/cli/ticket.js +50 -6
- package/dist/content/declare.d.ts +31 -37
- package/dist/content/declare.js +59 -60
- package/dist/content/file.d.ts +23 -12
- package/dist/content/file.js +48 -35
- package/dist/content/git.d.ts +0 -10
- package/dist/content/git.js +5 -39
- package/dist/content/resolve.d.ts +18 -22
- package/dist/content/resolve.js +32 -66
- package/dist/content/source.d.ts +7 -8
- package/dist/content/source.js +10 -28
- package/dist/credentials-page.d.ts +26 -0
- package/dist/credentials-page.js +185 -0
- package/dist/declared-secrets.d.ts +10 -3
- package/dist/declared-secrets.js +8 -4
- package/dist/deploy/agentcore/destroy.d.ts +4 -1
- package/dist/deploy/agentcore/destroy.js +26 -2
- package/dist/deploy/agentcore/forwarder.js +1 -1
- package/dist/deploy/agentcore/plan.d.ts +7 -21
- package/dist/deploy/agentcore/plan.js +47 -49
- package/dist/deploy/agentcore/run.d.ts +18 -10
- package/dist/deploy/agentcore/run.js +93 -70
- package/dist/deploy/agentcore/runtime-secrets.d.ts +7 -0
- package/dist/deploy/agentcore/runtime-secrets.js +108 -0
- package/dist/deploy/agentcore/shell.js +12 -19
- package/dist/deploy/agentcore/sigv4.d.ts +7 -0
- package/dist/deploy/agentcore/sigv4.js +15 -0
- package/dist/deploy/agentcore/slr.d.ts +18 -0
- package/dist/deploy/agentcore/slr.js +27 -0
- package/dist/deploy/agentcore/store.d.ts +7 -0
- package/dist/deploy/agentcore/store.js +115 -0
- package/dist/deploy/api.d.ts +14 -14
- package/dist/deploy/api.js +26 -24
- package/dist/deploy/box-shell.d.ts +3 -1
- package/dist/deploy/build-context.d.ts +4 -4
- package/dist/deploy/build-context.js +11 -11
- package/dist/deploy/channel-ingress.d.ts +35 -9
- package/dist/deploy/channel-ingress.js +119 -22
- package/dist/deploy/container.d.ts +35 -10
- package/dist/deploy/container.js +80 -39
- package/dist/deploy/delivered-text.d.ts +13 -0
- package/dist/deploy/delivered-text.js +86 -0
- package/dist/deploy/docker/plan.d.ts +7 -8
- package/dist/deploy/docker/plan.js +31 -52
- package/dist/deploy/docker/run.d.ts +18 -43
- package/dist/deploy/docker/run.js +57 -79
- package/dist/deploy/file-store.d.ts +2 -0
- package/dist/deploy/file-store.js +17 -0
- package/dist/deploy/fly/plan.d.ts +3 -2
- package/dist/deploy/fly/plan.js +20 -9
- package/dist/deploy/fly/run.d.ts +18 -22
- package/dist/deploy/fly/run.js +25 -44
- package/dist/deploy/fly/store.d.ts +12 -0
- package/dist/deploy/fly/store.js +83 -0
- package/dist/deploy/hosts.d.ts +1 -2
- package/dist/deploy/hosts.js +1 -2
- package/dist/deploy/preflight.d.ts +18 -5
- package/dist/deploy/preflight.js +135 -63
- package/dist/deploy/railway/ignore.d.ts +8 -0
- package/dist/deploy/railway/ignore.js +57 -0
- package/dist/deploy/railway/plan.d.ts +1 -2
- package/dist/deploy/railway/plan.js +8 -6
- package/dist/deploy/railway/run.d.ts +21 -15
- package/dist/deploy/railway/run.js +32 -78
- package/dist/deploy/railway/store.d.ts +29 -0
- package/dist/deploy/railway/store.js +143 -0
- package/dist/deploy/runner.d.ts +5 -2
- package/dist/deploy/runner.js +4 -3
- package/dist/deploy/secret-store.d.ts +63 -0
- package/dist/deploy/secret-store.js +98 -0
- package/dist/deploy/secrets.d.ts +29 -46
- package/dist/deploy/secrets.js +49 -122
- package/dist/deploy/workspace.d.ts +6 -12
- package/dist/deploy/workspace.js +18 -94
- package/dist/dev-supervisor.js +6 -7
- package/dist/environment/declare.js +3 -2
- package/dist/environment/mise.d.ts +3 -1
- package/dist/environment/mise.js +4 -2
- package/dist/feishu.d.ts +1 -1
- package/dist/feishu.js +1 -1
- package/dist/harnesses/models/catalog.d.ts +1 -0
- package/dist/harnesses/models/catalog.js +1 -2
- package/dist/harnesses/models/environment.d.ts +7 -2
- package/dist/harnesses/models/environment.js +9 -5
- package/dist/harnesses/models/host.d.ts +0 -7
- package/dist/harnesses/models/host.js +10 -1
- package/dist/harnesses/models/login.d.ts +0 -8
- package/dist/harnesses/models/login.js +5 -4
- package/dist/harnesses/models/models.d.ts +7 -2
- package/dist/harnesses/models/models.js +28 -4
- package/dist/harnesses/pi-durable/agent.js +59 -38
- package/dist/harnesses/pi-durable/build.d.ts +12 -0
- package/dist/harnesses/pi-durable/build.js +270 -0
- package/dist/harnesses/pi-durable/built.d.ts +24 -0
- package/dist/harnesses/pi-durable/built.js +136 -0
- package/dist/harnesses/pi-durable/config.d.ts +81 -0
- package/dist/harnesses/pi-durable/config.js +266 -0
- package/dist/harnesses/pi-durable/define.d.ts +63 -13
- package/dist/harnesses/pi-durable/define.js +23 -2
- package/dist/harnesses/pi-durable/definition.d.ts +72 -0
- package/dist/harnesses/pi-durable/definition.js +143 -0
- package/dist/harnesses/pi-durable/events.d.ts +4 -3
- package/dist/harnesses/pi-durable/events.js +179 -136
- package/dist/harnesses/pi-durable/execution-env.d.ts +17 -0
- package/dist/harnesses/pi-durable/execution-env.js +11 -0
- package/dist/harnesses/pi-durable/mcp.d.ts +3 -0
- package/dist/harnesses/pi-durable/mcp.js +32 -0
- package/dist/harnesses/pi-durable/open.d.ts +36 -38
- package/dist/harnesses/pi-durable/open.js +97 -150
- package/dist/harnesses/pi-durable/reads.d.ts +0 -1
- package/dist/harnesses/pi-durable/reads.js +1 -3
- package/dist/harnesses/pi-durable/registry.d.ts +4 -6
- package/dist/harnesses/pi-durable/registry.js +29 -26
- package/dist/harnesses/pi-durable/release.d.ts +2 -2
- package/dist/harnesses/pi-durable/release.js +10 -7
- package/dist/harnesses/pi-durable/serve.d.ts +95 -15
- package/dist/harnesses/pi-durable/serve.js +151 -59
- package/dist/harnesses/pi-durable/sessions.js +15 -12
- package/dist/harnesses/pi-durable/text-sources.d.ts +30 -0
- package/dist/harnesses/pi-durable/text-sources.js +55 -0
- package/dist/harnesses/pi-durable/text.d.ts +16 -4
- package/dist/harnesses/pi-durable/text.js +115 -59
- package/dist/harnesses/pi-durable/wake.js +8 -8
- package/dist/http/client.js +9 -3
- package/dist/http/server.d.ts +1 -1
- package/dist/http/server.js +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.js +8 -1
- package/dist/instance-name.d.ts +7 -0
- package/dist/instance-name.js +26 -0
- package/dist/lark.d.ts +1 -1
- package/dist/lark.js +1 -1
- package/dist/locked-file.d.ts +2 -2
- package/dist/locked-file.js +8 -3
- package/dist/mcp/auth.d.ts +22 -0
- package/dist/mcp/auth.js +180 -0
- package/dist/mcp/client.d.ts +15 -0
- package/dist/mcp/client.js +179 -0
- package/dist/mcp/config.d.ts +86 -0
- package/dist/mcp/config.js +225 -0
- package/dist/mcp/grants.d.ts +4 -0
- package/dist/mcp/grants.js +132 -0
- package/dist/mcp/host.d.ts +19 -0
- package/dist/mcp/host.js +128 -0
- package/dist/mcp/network.d.ts +12 -0
- package/dist/mcp/network.js +150 -0
- package/dist/mcp/sign-in.d.ts +2 -0
- package/dist/mcp/sign-in.js +204 -0
- package/dist/mcp-api.d.ts +107 -0
- package/dist/mcp-api.js +10 -0
- package/dist/paths.d.ts +22 -8
- package/dist/paths.js +44 -11
- package/dist/runtime-websocket.d.ts +14 -0
- package/dist/runtime-websocket.js +39 -0
- package/dist/scaffold/add-channel.d.ts +9 -16
- package/dist/scaffold/add-channel.js +13 -83
- package/dist/scaffold/templates/env.example +4 -5
- package/dist/scaffold/templates/fastagent.config.ts +20 -14
- package/dist/scaffold/templates/gitignore +9 -6
- package/dist/scaffold/templates.d.ts +6 -2
- package/dist/scaffold/templates.js +7 -2
- package/dist/scaffold/vendor-skill.js +4 -2
- package/dist/service.d.ts +44 -6
- package/dist/service.js +110 -10
- package/dist/serving-command.d.ts +10 -0
- package/dist/serving-command.js +1 -0
- package/dist/setup-page.d.ts +51 -0
- package/dist/setup-page.js +149 -0
- package/dist/slack.d.ts +1 -1
- package/dist/slack.js +1 -1
- package/dist/strip-edges.d.ts +10 -0
- package/dist/strip-edges.js +22 -0
- package/dist/telegram.d.ts +1 -1
- package/dist/telegram.js +1 -1
- package/dist/tunnel.d.ts +0 -1
- package/dist/tunnel.js +2 -8
- package/dist/value-file.d.ts +12 -6
- package/dist/value-file.js +36 -25
- package/dist/version.d.ts +7 -1
- package/dist/version.js +9 -3
- package/package.json +8 -6
- package/dist/channels/lark/onboard.d.ts +0 -36
- package/dist/channels/lark/onboard.js +0 -56
- package/dist/channels/slack/config-api.d.ts +0 -69
- package/dist/channels/slack/config-api.js +0 -162
- package/dist/channels/slack/onboard.d.ts +0 -40
- package/dist/channels/slack/onboard.js +0 -136
- package/dist/channels/slack/onboarding-state.d.ts +0 -31
- package/dist/channels/slack/onboarding-state.js +0 -64
- package/dist/channels/slack/register-webhook.d.ts +0 -12
- package/dist/channels/slack/register-webhook.js +0 -67
- package/dist/channels/slack/setup-server.d.ts +0 -32
- package/dist/channels/slack/setup-server.js +0 -201
- package/dist/cli/add-feishu.d.ts +0 -50
- package/dist/cli/add-feishu.js +0 -367
- package/dist/cli/add-slack.d.ts +0 -18
- package/dist/cli/add-slack.js +0 -216
- package/dist/harnesses/pi-durable/parked.d.ts +0 -18
- package/dist/harnesses/pi-durable/parked.js +0 -27
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The definition's text (architecture.md §3), read for each request so an
|
|
3
|
-
* `SYSTEM.md` and `AGENTS.md` as prompt sections, `skills/` as Agent Skills
|
|
4
|
-
*
|
|
2
|
+
* The definition's text (architecture.md §3) and the instance's (agent-artifact.md §4.2), read for each request so an
|
|
3
|
+
* edit takes effect on the next answer: `SYSTEM.md` and `AGENTS.md` as prompt sections, `skills/` as Agent Skills
|
|
4
|
+
* (agentskills.io) and `prompts/` as prompt templates, each with the files and directories the instance adds
|
|
5
|
+
* (text-sources.ts). A skill is loaded as pi does it: the prompt lists each one's name, description and location, the model
|
|
5
6
|
* reads its `SKILL.md` when a task matches, and `/skill:<name>` loads it into the message.
|
|
6
7
|
*/
|
|
7
8
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
@@ -9,7 +10,7 @@ import { basename, join } from "node:path";
|
|
|
9
10
|
import { section } from "@earendil-works/pi-durable";
|
|
10
11
|
import { parse as parseYaml } from "yaml";
|
|
11
12
|
import { log } from "../../log.js";
|
|
12
|
-
import {
|
|
13
|
+
import { NOUN, declareText, programText, whatIs } from "./text-sources.js";
|
|
13
14
|
const FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
14
15
|
const SKILL_NAME = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
15
16
|
/** A file's YAML frontmatter and its body. A file without frontmatter is all body. */
|
|
@@ -49,14 +50,37 @@ function directories(dir) {
|
|
|
49
50
|
}
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Whether a source is there to read as `kind`: one an instance declared that has gone, or become what its kind is not,
|
|
55
|
+
* is reported, not read as empty.
|
|
56
|
+
*/
|
|
57
|
+
function present({ path, declaredBy }, kind) {
|
|
58
|
+
const found = whatIs(path);
|
|
59
|
+
if (found === NOUN[kind] || (found !== undefined && declaredBy === undefined))
|
|
60
|
+
return true;
|
|
61
|
+
if (declaredBy !== undefined) {
|
|
62
|
+
report(`${path}: ${declaredBy} declares it, and ${found === undefined ? "it is gone" : `it is a ${found} now`}`);
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const collisionOf = (kind, name, taken, file, byInstance) => `${kind} "${name}" is declared by ${taken} and ${file}` +
|
|
67
|
+
(byInstance ? `: an instance adds to the program's ${kind}s and does not replace them — name it otherwise` : "");
|
|
68
|
+
/** The skills in `sources`: `<dir>/<name>/SKILL.md`. One that breaks the specification is reported and skipped. */
|
|
69
|
+
function loadSkills(sources, collide) {
|
|
55
70
|
const skills = [];
|
|
71
|
+
for (const source of sources) {
|
|
72
|
+
if (present(source, "skills"))
|
|
73
|
+
readSkillsOf(source, skills, collide);
|
|
74
|
+
}
|
|
75
|
+
return skills;
|
|
76
|
+
}
|
|
77
|
+
/** The skills of one directory, added to `skills`. */
|
|
78
|
+
function readSkillsOf(source, skills, collide) {
|
|
79
|
+
const root = source.path;
|
|
56
80
|
for (const entry of directories(root)) {
|
|
57
81
|
const baseDir = join(root, entry);
|
|
58
82
|
const filePath = join(baseDir, "SKILL.md");
|
|
59
|
-
const label =
|
|
83
|
+
const label = filePath;
|
|
60
84
|
if (!existsSync(filePath))
|
|
61
85
|
continue;
|
|
62
86
|
let fields;
|
|
@@ -77,8 +101,10 @@ export function readSkills(agentDir) {
|
|
|
77
101
|
report(`${label}: "description" must be a text of at most 1024 characters`);
|
|
78
102
|
continue;
|
|
79
103
|
}
|
|
80
|
-
|
|
81
|
-
|
|
104
|
+
const taken = skills.find((skill) => skill.name === name);
|
|
105
|
+
if (taken !== undefined) {
|
|
106
|
+
const byInstance = source.declaredBy !== undefined;
|
|
107
|
+
collide(collisionOf("skill", name, taken.filePath, filePath, byInstance), byInstance);
|
|
82
108
|
continue;
|
|
83
109
|
}
|
|
84
110
|
skills.push({
|
|
@@ -89,29 +115,53 @@ export function readSkills(agentDir) {
|
|
|
89
115
|
disableModelInvocation: fields["disable-model-invocation"] === true,
|
|
90
116
|
});
|
|
91
117
|
}
|
|
92
|
-
return skills;
|
|
93
118
|
}
|
|
94
|
-
/** The
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
/** The skills the agent offers, reported and skipped as above. */
|
|
120
|
+
export const readSkills = (sources) => loadSkills(sources, report);
|
|
121
|
+
/** The prompt templates in `sources`: `<dir>/<name>.md`, a `description` in the frontmatter and the body as the text. */
|
|
122
|
+
function loadTemplates(sources, collide) {
|
|
123
|
+
const templates = [];
|
|
124
|
+
const files = new Map();
|
|
125
|
+
for (const source of sources) {
|
|
126
|
+
if (!present(source, "prompts"))
|
|
127
|
+
continue;
|
|
128
|
+
for (const entry of readdirSync(source.path).sort()) {
|
|
129
|
+
if (!entry.endsWith(".md"))
|
|
130
|
+
continue;
|
|
131
|
+
const file = join(source.path, entry);
|
|
132
|
+
const name = entry.slice(0, -3);
|
|
133
|
+
const taken = files.get(name);
|
|
134
|
+
if (taken !== undefined) {
|
|
135
|
+
const byInstance = source.declaredBy !== undefined;
|
|
136
|
+
collide(collisionOf("prompt template", name, taken, file, byInstance), byInstance);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const { fields, body } = frontmatter(readFileSync(file, "utf8"), file);
|
|
141
|
+
const description = typeof fields.description === "string" ? fields.description : undefined;
|
|
142
|
+
templates.push({ name, ...(description === undefined ? {} : { description }), body });
|
|
143
|
+
files.set(name, file);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
report(`${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
147
|
+
}
|
|
113
148
|
}
|
|
114
|
-
}
|
|
149
|
+
}
|
|
150
|
+
return templates;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The instance's text as it will be read: declared, and refused when an instance entry takes a name the program (or an
|
|
154
|
+
* earlier instance entry) has. Called at open; what goes wrong afterwards is reported as each message reads it.
|
|
155
|
+
*/
|
|
156
|
+
export function openText(dir, instance) {
|
|
157
|
+
const text = declareText(dir, instance);
|
|
158
|
+
const refuse = (problem, byInstance) => {
|
|
159
|
+
if (byInstance)
|
|
160
|
+
throw new Error(`${instance?.label}: ${problem}`);
|
|
161
|
+
};
|
|
162
|
+
loadSkills(text.skills, refuse);
|
|
163
|
+
loadTemplates(text.prompts, refuse);
|
|
164
|
+
return text;
|
|
115
165
|
}
|
|
116
166
|
/** Arguments as a shell splits them: by whitespace, with `"…"` or `'…'` keeping one argument together. */
|
|
117
167
|
export function parseArguments(text) {
|
|
@@ -170,14 +220,14 @@ function loadedSkill(skill, args) {
|
|
|
170
220
|
return args.trim() === "" ? block : `${block}\n\n${args.trim()}`;
|
|
171
221
|
}
|
|
172
222
|
/** What a Caller may offer as `/<name>`: the prompt templates, then `skill:<name>` for each skill. */
|
|
173
|
-
export function readCommands(
|
|
223
|
+
export function readCommands(text) {
|
|
174
224
|
return [
|
|
175
|
-
...
|
|
225
|
+
...loadTemplates(text.prompts, report).map((template) => ({
|
|
176
226
|
name: template.name,
|
|
177
227
|
...(template.description === undefined ? {} : { description: template.description }),
|
|
178
228
|
expand: (args) => expandTemplate(template.body, parseArguments(args)),
|
|
179
229
|
})),
|
|
180
|
-
...readSkills(
|
|
230
|
+
...readSkills(text.skills).map((skill) => ({
|
|
181
231
|
name: `skill:${skill.name}`,
|
|
182
232
|
description: skill.description,
|
|
183
233
|
expand: (args) => loadedSkill(skill, args),
|
|
@@ -217,39 +267,44 @@ const fileText = (path) => {
|
|
|
217
267
|
const text = readFileSync(path, "utf8").trim();
|
|
218
268
|
return text === "" ? undefined : text;
|
|
219
269
|
};
|
|
270
|
+
/** The instance's files of instructions, in the order it declared them. */
|
|
271
|
+
function instructionsText(sources) {
|
|
272
|
+
const texts = sources.filter((source) => present(source, "instructions")).flatMap(({ path }) => fileText(path) ?? []);
|
|
273
|
+
return texts.length === 0 ? undefined : texts.join("\n\n");
|
|
274
|
+
}
|
|
220
275
|
/**
|
|
221
276
|
* The prompt the definition contributes: `SYSTEM.md` as written, `AGENTS.md` as project context, the skills, where it
|
|
222
|
-
* works, and, deployed, what of a change it makes to itself lasts. `wake`: the agent has the wake tool
|
|
277
|
+
* works, and, deployed, what of a change it makes to itself lasts. `wake`: the agent has the wake tool; `runsAs` says
|
|
278
|
+
* whether it is deployed, and where.
|
|
223
279
|
*/
|
|
224
280
|
export function definitionSections(agentDir, content, options) {
|
|
281
|
+
const text = options.text ?? programText(agentDir);
|
|
225
282
|
return [
|
|
226
283
|
section("system", () => fileText(join(agentDir, "SYSTEM.md")), { tag: false }),
|
|
227
284
|
section("project_context", () => fileText(join(agentDir, "AGENTS.md"))),
|
|
228
|
-
section("
|
|
229
|
-
section("
|
|
230
|
-
section("
|
|
285
|
+
section("instance_context", () => instructionsText(text.instructions)),
|
|
286
|
+
section("skills", () => skillsPrompt(readSkills(text.skills))),
|
|
287
|
+
section("content", () => contentSection({ agentDir, workdir: options.workdir ?? agentDir, content })),
|
|
288
|
+
section("self_change", () => options.runsAs.deployed ? selfChangeSection(options.wake, options.runsAs.agentcore) : undefined),
|
|
231
289
|
];
|
|
232
290
|
}
|
|
233
291
|
/**
|
|
234
292
|
* What takes effect when, and the agent's own path to a new capability, are the same on every host; how long the
|
|
235
293
|
* storage lives is the host's answer: AgentCore's managed mount is reset by every deploy, so telling that agent to keep
|
|
236
|
-
* work
|
|
237
|
-
*
|
|
238
|
-
*
|
|
294
|
+
* work in its directory would name a location its next deploy erases; elsewhere the directory is the host's storage,
|
|
295
|
+
* which every deployment keeps. Its definition is the image's either way, so the sentence says where a capability that
|
|
296
|
+
* should outlast a deployment has to go.
|
|
239
297
|
*/
|
|
240
|
-
function selfChangeSection(wake) {
|
|
241
|
-
const
|
|
242
|
-
? "Every deployment of a new version resets this host's storage entirely"
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
`SYSTEM.md, AGENTS.md, skills
|
|
247
|
-
`
|
|
248
|
-
`
|
|
249
|
-
`
|
|
250
|
-
`your definition's skills/ directory, with any script it needs run through bash. It lasts until the next ` +
|
|
251
|
-
`deployment replaces that directory, so a capability that should outlast it belongs in the author's release: ` +
|
|
252
|
-
`propose it to them.` +
|
|
298
|
+
function selfChangeSection(wake, agentcore) {
|
|
299
|
+
const storage = agentcore
|
|
300
|
+
? "Every deployment of a new version resets this host's storage entirely, your directory with it, so anything " +
|
|
301
|
+
"that must outlive a deployment belongs in an external system (a git remote, an issue tracker, a database)."
|
|
302
|
+
: "Your directory is this host's storage and survives deployments of a new version.";
|
|
303
|
+
return (`Your directory survives restarts, including uncommitted work; /tmp does not. ${storage} ` +
|
|
304
|
+
`Your definition (SYSTEM.md, AGENTS.md, skills/, prompts/, src/ and the configuration) is the author's release, ` +
|
|
305
|
+
`read as it was built from where it is installed: a copy of it you make in your directory is not read. A tool you install ` +
|
|
306
|
+
`yourself (apt-get, npm install -g) belongs to this machine and is gone when its container is replaced. A ` +
|
|
307
|
+
`capability that should outlast a deployment belongs in the author's release: propose it to them.` +
|
|
253
308
|
// Named only when it has the tool: naming a tool the model does not have invites calls to it.
|
|
254
309
|
(wake ? " To schedule your own follow-up work, use the wake tool." : ""));
|
|
255
310
|
}
|
|
@@ -257,8 +312,6 @@ function selfChangeSection(wake) {
|
|
|
257
312
|
function contentKind(c) {
|
|
258
313
|
if (c.kind !== "github")
|
|
259
314
|
return "a directory on this machine";
|
|
260
|
-
if (!c.clone)
|
|
261
|
-
return `a checkout of github ${c.repo} on this machine`;
|
|
262
315
|
// Brought up to date in place at each start where git can do so without touching the agent's work; what the agent
|
|
263
316
|
// changes stays, and reaches anyone else only when pushed. The declared ref is what it follows, not a claim about
|
|
264
317
|
// where it is: a clone the agent moved elsewhere is left there.
|
|
@@ -270,9 +323,12 @@ function contentKind(c) {
|
|
|
270
323
|
* with its location and where a change there goes. A result written where it does not last is how knowledge gets
|
|
271
324
|
* lost, so the agent is told which is which.
|
|
272
325
|
*/
|
|
273
|
-
function contentSection({ agentDir, content }) {
|
|
274
|
-
const own =
|
|
275
|
-
`
|
|
326
|
+
function contentSection({ agentDir, workdir, content, }) {
|
|
327
|
+
const own = workdir === agentDir
|
|
328
|
+
? `Your working directory, ${agentDir}, is your own directory: it holds your definition, and files you create ` +
|
|
329
|
+
`land there unless you put them elsewhere.`
|
|
330
|
+
: `Your working directory, ${workdir}, is your own directory: files you create land there unless you put them ` +
|
|
331
|
+
`elsewhere. Your definition is in ${agentDir}, which you read and do not change.`;
|
|
276
332
|
if (content.length === 0)
|
|
277
333
|
return `${own} Nothing else is declared for you: you work only in your own directory.`;
|
|
278
334
|
const line = (c) => `- ${c.name}: ${c.location} (${contentKind(c)})${c.description !== undefined ? ` ${c.description}` : ""}`;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* the instance's state (schedule/wakeups.ts), which the scheduler fires. A pair over one store: a definition that
|
|
4
4
|
* defines either name gets neither.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { num, obj, opt, str, union } from "@earendil-works/pi-schema";
|
|
7
7
|
import { defineExtension, defineTool } from "@earendil-works/pi-durable";
|
|
8
8
|
import { addWakeup, parseDelayMs, removeWakeup } from "../../schedule/wakeups.js";
|
|
9
9
|
import { sessionIdOf } from "./ids.js";
|
|
@@ -32,13 +32,13 @@ export function wakeExtension(stateRoot, options = {}) {
|
|
|
32
32
|
"same conversation with `prompt` as its instruction, tagged with the wake-up's id so you can tell it from a " +
|
|
33
33
|
"user's, and you keep the full context of this conversation. Its plain reply is delivered to no one: to " +
|
|
34
34
|
"reach a person it must call a delivery tool (a channel's send tool), as a scheduled job does.",
|
|
35
|
-
parameters:
|
|
36
|
-
in:
|
|
35
|
+
parameters: obj({
|
|
36
|
+
in: opt(union([str(), num()], {
|
|
37
37
|
description: 'one-shot delay: a duration string with a unit ("30m" / "2h" / "1d"), or a number of seconds',
|
|
38
38
|
})),
|
|
39
|
-
cron:
|
|
40
|
-
tz:
|
|
41
|
-
prompt:
|
|
39
|
+
cron: opt(str({ description: 'recurring: a 5-field cron expression (e.g. "0 9 * * *")' })),
|
|
40
|
+
tz: opt(str({ description: 'IANA timezone for `cron` (default "UTC")' })),
|
|
41
|
+
prompt: str({
|
|
42
42
|
minLength: 1,
|
|
43
43
|
description: "the instruction for the woken message (it arrives in this same conversation)",
|
|
44
44
|
}),
|
|
@@ -73,8 +73,8 @@ export function wakeExtension(stateRoot, options = {}) {
|
|
|
73
73
|
name: "unwake",
|
|
74
74
|
description: "Cancel one of YOUR pending wake-ups (one-shot or recurring) by the id `wake` returned. Use it when a " +
|
|
75
75
|
"scheduled follow-up is no longer needed, especially to stop a recurring wake once its job is done.",
|
|
76
|
-
parameters:
|
|
77
|
-
id:
|
|
76
|
+
parameters: obj({
|
|
77
|
+
id: str({ minLength: 1, description: "the wake-up id (returned by `wake`)" }),
|
|
78
78
|
}),
|
|
79
79
|
execute: async (args, api, context) => {
|
|
80
80
|
const session = await sessionIdOf(api, context);
|
package/dist/http/client.js
CHANGED
|
@@ -48,9 +48,15 @@ const reasonOf = (error) => error.reason;
|
|
|
48
48
|
const unsent = (error) => ["EncodeError", "InvalidUrlError"].includes(reasonOf(error)?._tag ?? "");
|
|
49
49
|
const said = (error) => (error instanceof Error ? error.message : String(error));
|
|
50
50
|
/** What stopped a request that left, said for a Caller. */
|
|
51
|
-
const whatFailed = (baseUrl, error) =>
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
const whatFailed = (baseUrl, error) => {
|
|
52
|
+
if (reasonOf(error)?._tag === "TransportError")
|
|
53
|
+
return `could not reach the agent at ${baseUrl}: ${said(error)}`;
|
|
54
|
+
const answered = `the agent at ${baseUrl} answered what this client cannot read: ${said(error)}`;
|
|
55
|
+
// A serve mounts the API only while it holds a key (SPEC §9.6): a host that is up and has none answers 404 here.
|
|
56
|
+
return reasonOf(error)?.response?.status === 404
|
|
57
|
+
? `${answered} (a deployment serves no Agent API without a FASTAGENT_API_KEY, and AgentCore serves none)`
|
|
58
|
+
: answered;
|
|
59
|
+
};
|
|
54
60
|
/**
|
|
55
61
|
* A read's failure, and a write's other than a send's: a refusal as the agent answered it; one that could not get
|
|
56
62
|
* through or met a server's error may be sent again, since repeating any request but a send does no harm (§7);
|
package/dist/http/server.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare function apiTurnedOff(config: {
|
|
|
11
11
|
api?: boolean;
|
|
12
12
|
};
|
|
13
13
|
}): boolean;
|
|
14
|
-
export declare const API_TURNED_OFF = "
|
|
14
|
+
export declare const API_TURNED_OFF = "the configuration says http.api: false";
|
|
15
15
|
export declare function apiKeysFrom(value: string | undefined): string[];
|
|
16
16
|
export interface ApiHandler {
|
|
17
17
|
fetch: ChannelHandler;
|
package/dist/http/server.js
CHANGED
|
@@ -26,7 +26,7 @@ export const API_KEY_VARIABLE = "FASTAGENT_API_KEY";
|
|
|
26
26
|
export function apiTurnedOff(config) {
|
|
27
27
|
return config.http?.api === false;
|
|
28
28
|
}
|
|
29
|
-
export const API_TURNED_OFF = "
|
|
29
|
+
export const API_TURNED_OFF = "the configuration says http.api: false";
|
|
30
30
|
export function apiKeysFrom(value) {
|
|
31
31
|
return (value ?? "")
|
|
32
32
|
.split(",")
|
package/dist/index.d.ts
CHANGED
|
@@ -5,17 +5,24 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export type { Agent, AgentErrorData, AgentInfo, CompactOptions, ContentPart, CreateSessionOptions, EntriesOptions, Entry, ErrorCode, Json, ListOptions, Message, MessageKey, MessageStatus, MessageStreamEvent, ModelRef, Page, SendRequest, Session, SessionChanges, SessionEvent, SessionSettings, SessionStatus, ThinkingLevel, Tokens, Usage, WaitOptions, } from "./agent-api.ts";
|
|
7
7
|
export { AgentError, LIMITS, hasEnded } from "./agent-api.ts";
|
|
8
|
-
export { openAgent, type LocalAgent, type OpenAgentOptions, type ServeAgentOptions, } from "./harnesses/pi-durable/serve.ts";
|
|
8
|
+
export { openAgent, type InstanceLocation, type LocalAgent, type OpenAgentOptions, type ServeAgentOptions, } from "./harnesses/pi-durable/serve.ts";
|
|
9
9
|
export type { Service } from "./service.ts";
|
|
10
|
-
export { ContentNameError, addContent, createAgent, listContent, removeContent, type ContentEdit, type CreatedAgent, } from "./authoring.ts";
|
|
10
|
+
export { ContentNameError, addContent, createAgent, listContent, removeContent, type ContentEdit, type ContentScope, type CreatedAgent, } from "./authoring.ts";
|
|
11
11
|
export type { ContentAddition, SourceOptions } from "./content/source.ts";
|
|
12
12
|
export { readContentSource } from "./content/source.ts";
|
|
13
|
-
export type {
|
|
13
|
+
export type { ContentEntry } from "./content/declare.ts";
|
|
14
14
|
export type { ResolvedContent } from "./content/resolve.ts";
|
|
15
15
|
export { SignInCancelled, type Credential, type CredentialStore, type ProviderAuth, type SignInEvent, type SignInInteraction, type SignInMethod, type SignInOption, type SignInPrompt, type SignInRequest, type SignInResult, } from "./sign-in-api.ts";
|
|
16
16
|
export { credentialFile, providerAuth, signIn, signInOptions } from "./harnesses/models/host.ts";
|
|
17
|
-
export {
|
|
17
|
+
export { McpError, type McpErrorCode, type McpOptions, type McpInspectOptions, type McpConfigInput, type McpAuthorization, type McpGrantRecord, type McpGrantSummary, type McpGrantStore, type McpGrantAccess, type McpServerSummary, type McpSignInRequest, type McpSignInInteraction, } from "./mcp-api.ts";
|
|
18
|
+
export { baseEnv } from "./child-env.ts";
|
|
19
|
+
export { inspectMcp } from "./mcp/host.ts";
|
|
20
|
+
export { signInMcp } from "./mcp/sign-in.ts";
|
|
21
|
+
export { mcpGrantFile } from "./mcp/grants.ts";
|
|
22
|
+
export { byIngress, defineAgent, defineSchedule, needs, type ByIngress, type Ingress, type AgentConfig, type AgentDefaults, type SettingsOf, type Needs, type SecretSpec, type SecretValues, } from "./harnesses/pi-durable/define.ts";
|
|
23
|
+
export type { InstanceConfig } from "./harnesses/pi-durable/config.ts";
|
|
18
24
|
export type { ScheduleConfig } from "./schedule/schedule.ts";
|
|
25
|
+
export { defineDefinition, type AgentDefinition } from "./harnesses/pi-durable/definition.ts";
|
|
19
26
|
export { defineChannel, type ChannelContext, type ChannelHandler, type ChannelModule, type ForkSource, type LongConnection, type LongConnectionChannelModule, type Routes, } from "./channel.ts";
|
|
20
27
|
export { readBodyCapped } from "./channels/body.ts";
|
|
21
28
|
export { text } from "./channels/respond.ts";
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,14 @@ export { ContentNameError, addContent, createAgent, listContent, removeContent,
|
|
|
4
4
|
export { readContentSource } from "./content/source.js";
|
|
5
5
|
export { SignInCancelled, } from "./sign-in-api.js";
|
|
6
6
|
export { credentialFile, providerAuth, signIn, signInOptions } from "./harnesses/models/host.js";
|
|
7
|
-
export {
|
|
7
|
+
export { McpError, } from "./mcp-api.js";
|
|
8
|
+
export { baseEnv } from "./child-env.js";
|
|
9
|
+
export { inspectMcp } from "./mcp/host.js";
|
|
10
|
+
export { signInMcp } from "./mcp/sign-in.js";
|
|
11
|
+
export { mcpGrantFile } from "./mcp/grants.js";
|
|
12
|
+
export { byIngress, defineAgent, defineSchedule, needs, } from "./harnesses/pi-durable/define.js";
|
|
13
|
+
// What `fastagent build` writes into a package's generated entry, never written by hand.
|
|
14
|
+
export { defineDefinition } from "./harnesses/pi-durable/definition.js";
|
|
8
15
|
export { defineChannel, } from "./channel.js";
|
|
9
16
|
// What a channel reads a request with, answers with, and compares its platform's secret with (constant time).
|
|
10
17
|
export { readBodyCapped } from "./channels/body.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const INSTANCE_NAME_ENV = "FASTAGENT_NAME";
|
|
2
|
+
/** `name`, when it can name an instance: one path segment of letters, digits, `-` and `_`; refused otherwise. */
|
|
3
|
+
export declare function checkInstanceName(name: string): string;
|
|
4
|
+
/** The name `FASTAGENT_NAME` gives: unset and empty are the same, as for the path variables. */
|
|
5
|
+
export declare function enteredInstanceName(env?: NodeJS.ProcessEnv): string | undefined;
|
|
6
|
+
/** The instance's name: `given` when there is one (refused when it is not a segment), else the definition's, as one. */
|
|
7
|
+
export declare function instanceName(definitionName: string, given?: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An instance's name (agent-artifact.md §4.5): the one thing `info().name` and a host's report call it. An explicit name
|
|
3
|
+
* is one path segment, so it is safe to name a directory after, and is refused otherwise; the
|
|
4
|
+
* default is the definition's name made into one (`@scope/pkg` is not one), so two instances of one definition on one
|
|
5
|
+
* machine take distinct names only by being given them.
|
|
6
|
+
*/
|
|
7
|
+
import { stripEdges } from "./strip-edges.js";
|
|
8
|
+
export const INSTANCE_NAME_ENV = "FASTAGENT_NAME";
|
|
9
|
+
const SEGMENT = /^[A-Za-z0-9_-]+$/;
|
|
10
|
+
/** `name`, when it can name an instance: one path segment of letters, digits, `-` and `_`; refused otherwise. */
|
|
11
|
+
export function checkInstanceName(name) {
|
|
12
|
+
if (!SEGMENT.test(name)) {
|
|
13
|
+
throw new Error(`the instance name ${JSON.stringify(name)} must be one path segment of letters, digits, "-" and "_"`);
|
|
14
|
+
}
|
|
15
|
+
return name;
|
|
16
|
+
}
|
|
17
|
+
/** The name `FASTAGENT_NAME` gives: unset and empty are the same, as for the path variables. */
|
|
18
|
+
export function enteredInstanceName(env = process.env) {
|
|
19
|
+
return env[INSTANCE_NAME_ENV] || undefined;
|
|
20
|
+
}
|
|
21
|
+
/** The instance's name: `given` when there is one (refused when it is not a segment), else the definition's, as one. */
|
|
22
|
+
export function instanceName(definitionName, given) {
|
|
23
|
+
if (given !== undefined)
|
|
24
|
+
return checkInstanceName(given);
|
|
25
|
+
return stripEdges(definitionName.replace(/[^A-Za-z0-9_-]/g, "-"), (char) => char === "-") || "agent";
|
|
26
|
+
}
|
package/dist/lark.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** `@fastagent-sh/fastagent/lark` — the Lark-international compatibility surface over the canonical Feishu engine. */
|
|
2
|
-
export { larkChannel,
|
|
2
|
+
export { larkChannel, larkWebSocketChannel, defaultLarkRoute, larkEnvelope, type LarkChannelOptions, type LarkWebSocketChannelOptions, type LarkMessageEvent, type LarkMessage, type LarkRoute, type LarkFailure, } from "./channels/lark/lark.ts";
|
|
3
3
|
export { larkThreads, larkTransport, type FeishuTransport as LarkTransport } from "./channels/feishu/shared-api.ts";
|
package/dist/lark.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** `@fastagent-sh/fastagent/lark` — the Lark-international compatibility surface over the canonical Feishu engine. */
|
|
2
|
-
export { larkChannel,
|
|
2
|
+
export { larkChannel, larkWebSocketChannel, defaultLarkRoute, larkEnvelope, } from "./channels/lark/lark.js";
|
|
3
3
|
export { larkThreads, larkTransport } from "./channels/feishu/shared-api.js";
|
package/dist/locked-file.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export interface LockResult<T> {
|
|
|
3
3
|
/** New file content to persist under the lock; undefined = no write. */
|
|
4
4
|
next?: string;
|
|
5
5
|
}
|
|
6
|
-
/** Serialized
|
|
7
|
-
export declare function withLockedFile<T>(path: string, fn: (current: string | undefined) => Promise<LockResult<T>>,
|
|
6
|
+
/** Serialized read-modify-write. `replace` commits immediately under the lock; those writes survive a later failure. */
|
|
7
|
+
export declare function withLockedFile<T>(path: string, fn: (current: string | undefined, replace: (next: string) => void) => Promise<LockResult<T>>,
|
|
8
8
|
/**
|
|
9
9
|
* `mode`: the replaced file's permissions; default {@link SECRET_FILE_MODE}, for the credential and catalog files.
|
|
10
10
|
* `create: false` locks a file that may not exist without creating it (the lock is `<file>.lock` either way), for a
|
package/dist/locked-file.js
CHANGED
|
@@ -26,7 +26,7 @@ function writeTarget(path) {
|
|
|
26
26
|
// ever shows up in a real layout.
|
|
27
27
|
return link?.isSymbolicLink() ? resolve(dirname(path), readlinkSync(path)) : path;
|
|
28
28
|
}
|
|
29
|
-
/** Serialized
|
|
29
|
+
/** Serialized read-modify-write. `replace` commits immediately under the lock; those writes survive a later failure. */
|
|
30
30
|
export async function withLockedFile(path, fn,
|
|
31
31
|
/**
|
|
32
32
|
* `mode`: the replaced file's permissions; default {@link SECRET_FILE_MODE}, for the credential and catalog files.
|
|
@@ -71,7 +71,12 @@ options = {}) {
|
|
|
71
71
|
try {
|
|
72
72
|
throwIfCompromised();
|
|
73
73
|
const current = existsSync(path) ? readFileSync(path, "utf8") : undefined;
|
|
74
|
-
const
|
|
74
|
+
const replace = (next) => {
|
|
75
|
+
throwIfCompromised();
|
|
76
|
+
options.signal?.throwIfAborted();
|
|
77
|
+
writeFileAtomic(writeTarget(path), next, options.mode ?? SECRET_FILE_MODE);
|
|
78
|
+
};
|
|
79
|
+
const out = await fn(current, replace);
|
|
75
80
|
throwIfCompromised();
|
|
76
81
|
// The last moment a caller that gave up can keep its change off disk: waiting for the lock may have outlasted it
|
|
77
82
|
// (another process held the lock through the caller's timeout or cancel).
|
|
@@ -79,7 +84,7 @@ options = {}) {
|
|
|
79
84
|
// Rename, not an in-place rewrite: it is what lets `read` stay unlocked, and it is the only spelling that applies
|
|
80
85
|
// the mode before the content is reachable.
|
|
81
86
|
if (out.next !== undefined) {
|
|
82
|
-
|
|
87
|
+
replace(out.next);
|
|
83
88
|
}
|
|
84
89
|
throwIfCompromised();
|
|
85
90
|
result = out.result;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type AuthorizationServerMetadata, type OAuthProtectedResourceMetadata } from "@modelcontextprotocol/client";
|
|
2
|
+
import { McpError, type McpGrantRecord, type McpGrantStore } from "../mcp-api.ts";
|
|
3
|
+
export interface McpDiscovery {
|
|
4
|
+
metadata: AuthorizationServerMetadata;
|
|
5
|
+
resourceMetadata: OAuthProtectedResourceMetadata;
|
|
6
|
+
issuer: string;
|
|
7
|
+
resource: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function discoverMcp(url: string, fetchImpl: typeof globalThis.fetch): Promise<McpDiscovery>;
|
|
10
|
+
export declare function checkGrantTarget(record: McpGrantRecord, url: string, discovery?: McpDiscovery): void;
|
|
11
|
+
export declare function mcpFailure(error: unknown, operation: string, server?: string): McpError;
|
|
12
|
+
export declare function grantToken(input: {
|
|
13
|
+
store: McpGrantStore;
|
|
14
|
+
id: string;
|
|
15
|
+
url: string;
|
|
16
|
+
fetch: typeof globalThis.fetch;
|
|
17
|
+
discovery?: McpDiscovery;
|
|
18
|
+
rejectedGeneration?: number;
|
|
19
|
+
}): Promise<{
|
|
20
|
+
token: string;
|
|
21
|
+
generation: number;
|
|
22
|
+
}>;
|