@timqi/pier 0.1.0 → 0.1.1

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.
Files changed (158) hide show
  1. package/README.md +58 -125
  2. package/dist/agent/config.js +6 -15
  3. package/dist/agent/credentials.js +11 -23
  4. package/dist/agent/events.js +42 -64
  5. package/dist/agent/listing.js +39 -92
  6. package/dist/agent/pi.js +103 -252
  7. package/dist/boards/boards.js +19 -29
  8. package/dist/channels/attach.js +14 -42
  9. package/dist/channels/chains.js +33 -37
  10. package/dist/channels/chunk.js +8 -28
  11. package/dist/channels/commands.js +3 -14
  12. package/dist/channels/config.js +33 -52
  13. package/dist/channels/control.js +4 -13
  14. package/dist/channels/conversations.js +8 -25
  15. package/dist/channels/dedup.js +8 -17
  16. package/dist/channels/gatekeeper.js +13 -23
  17. package/dist/channels/lark-api.js +23 -63
  18. package/dist/channels/lark-outbound.js +12 -44
  19. package/dist/channels/lark-panel.js +7 -23
  20. package/dist/channels/lark-render.js +18 -62
  21. package/dist/channels/lark.js +52 -141
  22. package/dist/channels/lines.js +13 -15
  23. package/dist/channels/panel.js +16 -36
  24. package/dist/channels/receipts.js +29 -52
  25. package/dist/channels/routes.js +3 -9
  26. package/dist/channels/runtime.js +12 -23
  27. package/dist/channels/slack-api.js +34 -86
  28. package/dist/channels/slack-directory.js +7 -23
  29. package/dist/channels/slack-outbound.js +12 -56
  30. package/dist/channels/slack-panel.js +4 -13
  31. package/dist/channels/slack-render.js +23 -91
  32. package/dist/channels/slack-tool.js +48 -171
  33. package/dist/channels/slack.js +73 -239
  34. package/dist/channels/telegram-api.js +8 -20
  35. package/dist/channels/telegram-panel.js +5 -21
  36. package/dist/channels/telegram-render.js +13 -40
  37. package/dist/channels/telegram.js +54 -146
  38. package/dist/channels/types.js +5 -16
  39. package/dist/cli.js +17 -41
  40. package/dist/config-sync.js +87 -4
  41. package/dist/core/hub.js +7 -20
  42. package/dist/core/identity.js +20 -59
  43. package/dist/core/inbound-file.js +15 -49
  44. package/dist/core/inbox.js +12 -34
  45. package/dist/core/queue.js +3 -5
  46. package/dist/core/reply.js +41 -142
  47. package/dist/core/router.js +209 -264
  48. package/dist/core/types.js +4 -0
  49. package/dist/db.js +88 -272
  50. package/dist/drain.js +57 -50
  51. package/dist/extensions/index.js +3 -11
  52. package/dist/extensions/web/anthropic.js +3 -9
  53. package/dist/extensions/web/artifacts.js +2 -5
  54. package/dist/extensions/web/content.js +4 -12
  55. package/dist/extensions/web/http.js +2 -6
  56. package/dist/extensions/web/language.js +8 -18
  57. package/dist/extensions/web/openai.js +1 -1
  58. package/dist/extensions/web/provider.js +5 -18
  59. package/dist/extensions/web/tools.js +19 -63
  60. package/dist/lock.js +98 -0
  61. package/dist/log.js +9 -26
  62. package/dist/main.js +84 -183
  63. package/dist/paths.js +10 -26
  64. package/dist/secrets.js +18 -45
  65. package/dist/service.js +31 -73
  66. package/dist/settings.js +19 -63
  67. package/dist/tasks/agent.js +24 -45
  68. package/dist/tasks/callbacks.js +8 -16
  69. package/dist/tasks/command.js +2 -6
  70. package/dist/tasks/definitions.js +39 -62
  71. package/dist/tasks/execution.js +41 -39
  72. package/dist/tasks/groups.js +8 -11
  73. package/dist/tasks/messages.js +88 -155
  74. package/dist/tasks/outbox.js +33 -54
  75. package/dist/tasks/routes.js +4 -7
  76. package/dist/tasks/runs.js +4 -9
  77. package/dist/tasks/service.js +29 -42
  78. package/dist/tasks/store.js +36 -27
  79. package/dist/tasks/tool.js +59 -60
  80. package/dist/tools-task.js +20 -60
  81. package/dist/tools.js +98 -325
  82. package/dist/update.js +20 -43
  83. package/dist/web/auth.js +118 -179
  84. package/dist/web/config-sync.js +2 -2
  85. package/dist/web/config.js +3 -7
  86. package/dist/web/explorer.js +10 -21
  87. package/dist/web/fs.js +20 -42
  88. package/dist/web/instance.js +35 -82
  89. package/dist/web/providers.js +5 -11
  90. package/dist/web/public/assets/{activity-Bl3vZukb.js → activity-B89_hH7q.js} +1 -1
  91. package/dist/web/public/assets/activity-B89_hH7q.js.br +0 -0
  92. package/dist/web/public/assets/activity-B89_hH7q.js.gz +0 -0
  93. package/dist/web/public/assets/{boards-DYuf4Mlj.js → boards-BeKW0ZXK.js} +1 -1
  94. package/dist/web/public/assets/boards-BeKW0ZXK.js.br +0 -0
  95. package/dist/web/public/assets/boards-BeKW0ZXK.js.gz +0 -0
  96. package/dist/web/public/assets/explorer-DIuMlaV3.js +4 -0
  97. package/dist/web/public/assets/explorer-DIuMlaV3.js.br +0 -0
  98. package/dist/web/public/assets/explorer-DIuMlaV3.js.gz +0 -0
  99. package/dist/web/public/assets/index-DzXDXra_.js +85 -0
  100. package/dist/web/public/assets/index-DzXDXra_.js.br +0 -0
  101. package/dist/web/public/assets/index-DzXDXra_.js.gz +0 -0
  102. package/dist/web/public/assets/index-eqQLVS8Q.css +2 -0
  103. package/dist/web/public/assets/index-eqQLVS8Q.css.br +0 -0
  104. package/dist/web/public/assets/index-eqQLVS8Q.css.gz +0 -0
  105. package/dist/web/public/assets/{runs-BLJu7EXN.js → runs-Cwy0mN8i.js} +1 -1
  106. package/dist/web/public/assets/runs-Cwy0mN8i.js.br +0 -0
  107. package/dist/web/public/assets/runs-Cwy0mN8i.js.gz +0 -0
  108. package/dist/web/public/assets/{settings-BrdVh-Zi.js → settings-DzZLmujq.js} +1 -1
  109. package/dist/web/public/assets/settings-DzZLmujq.js.br +0 -0
  110. package/dist/web/public/assets/settings-DzZLmujq.js.gz +0 -0
  111. package/dist/web/public/assets/{task-runs-CeQS1rxa.js → task-runs-BCakxFk8.js} +1 -1
  112. package/dist/web/public/assets/task-runs-BCakxFk8.js.br +0 -0
  113. package/dist/web/public/assets/task-runs-BCakxFk8.js.gz +0 -0
  114. package/dist/web/public/assets/tasks-BlzEbk11.js +4 -0
  115. package/dist/web/public/assets/tasks-BlzEbk11.js.br +0 -0
  116. package/dist/web/public/assets/tasks-BlzEbk11.js.gz +0 -0
  117. package/dist/web/public/index.html +30 -16
  118. package/dist/web/public/index.html.br +0 -0
  119. package/dist/web/public/index.html.gz +0 -0
  120. package/dist/web/public/sw.js +14 -2
  121. package/dist/web/public/sw.js.br +0 -0
  122. package/dist/web/public/sw.js.gz +0 -0
  123. package/dist/web/push.js +55 -77
  124. package/dist/web/route.js +3 -7
  125. package/dist/web/server.js +109 -190
  126. package/dist/web/session-state.js +13 -53
  127. package/dist/web/types.js +2 -4
  128. package/dist/web/webpush.js +10 -25
  129. package/docs/deploy.md +115 -330
  130. package/package.json +1 -1
  131. package/skills/pier-boards/SKILL.md +81 -160
  132. package/skills/pier-help/SKILL.md +23 -20
  133. package/skills/pier-slack/SKILL.md +2 -2
  134. package/skills/pier-tasks/SKILL.md +23 -15
  135. package/dist/config-sync-fetch.js +0 -84
  136. package/dist/limits.js +0 -14
  137. package/dist/web/public/assets/activity-Bl3vZukb.js.br +0 -0
  138. package/dist/web/public/assets/activity-Bl3vZukb.js.gz +0 -0
  139. package/dist/web/public/assets/boards-DYuf4Mlj.js.br +0 -0
  140. package/dist/web/public/assets/boards-DYuf4Mlj.js.gz +0 -0
  141. package/dist/web/public/assets/explorer-qJH_9nTE.js +0 -4
  142. package/dist/web/public/assets/explorer-qJH_9nTE.js.br +0 -0
  143. package/dist/web/public/assets/explorer-qJH_9nTE.js.gz +0 -0
  144. package/dist/web/public/assets/index-Dqdb-Eqt.js +0 -85
  145. package/dist/web/public/assets/index-Dqdb-Eqt.js.br +0 -0
  146. package/dist/web/public/assets/index-Dqdb-Eqt.js.gz +0 -0
  147. package/dist/web/public/assets/index-DzmMzvi_.css +0 -2
  148. package/dist/web/public/assets/index-DzmMzvi_.css.br +0 -0
  149. package/dist/web/public/assets/index-DzmMzvi_.css.gz +0 -0
  150. package/dist/web/public/assets/runs-BLJu7EXN.js.br +0 -0
  151. package/dist/web/public/assets/runs-BLJu7EXN.js.gz +0 -0
  152. package/dist/web/public/assets/settings-BrdVh-Zi.js.br +0 -0
  153. package/dist/web/public/assets/settings-BrdVh-Zi.js.gz +0 -0
  154. package/dist/web/public/assets/task-runs-CeQS1rxa.js.br +0 -0
  155. package/dist/web/public/assets/task-runs-CeQS1rxa.js.gz +0 -0
  156. package/dist/web/public/assets/tasks-bcb3fYdK.js +0 -4
  157. package/dist/web/public/assets/tasks-bcb3fYdK.js.br +0 -0
  158. package/dist/web/public/assets/tasks-bcb3fYdK.js.gz +0 -0
package/dist/update.js CHANGED
@@ -1,30 +1,19 @@
1
- // The newer Pier: whether one exists, and when this one may become it.
2
- //
3
- // The registry is asked, not the GitHub API: `registry.npmjs.org` is a CDN with
4
- // no rate limit and no token, and it is the same place `npm i -g` would look,
5
- // so what it reports is what an update would actually get.
6
- //
7
- // Nothing here installs anything. Applying is handed to whatever supervises
8
- // this process (service.ts's oneshot unit, injected as `apply`): a web server
9
- // holding provider keys must not npm-install as its own child, and the two
10
- // gates below — the operator switched it on, and nothing is running — are why
11
- // a self-replacing timer is not simply a supply-chain surface (AGENTS.md 8).
1
+ // The newer Pier: whether one exists, and when this one may become it. The npm
2
+ // registry is asked (no rate limit, and what `npm i -g` would get). Nothing
3
+ // here installs: a web server holding provider keys must not npm-install as its
4
+ // own child, so applying is handed to the supervisor (service.ts).
12
5
  import { createRequire } from "node:module";
13
6
  import { logger } from "./log.js";
14
7
  const log = logger("update");
15
8
  const PACKAGE = "@timqi/pier";
16
9
  const ENDPOINT = `https://registry.npmjs.org/${PACKAGE}/latest`;
17
- /** One conditional-GET-sized request against a CDN, so the cost of asking is
18
- * not what sets this — how long a released fix may sit unnoticed is. */
10
+ /** Set by how long a released fix may sit unnoticed, not by request cost. */
19
11
  const TTL_MS = 30 * 60_000;
20
12
  const TIMEOUT_MS = 5_000;
21
13
  export const currentVersion = () => createRequire(import.meta.url)("../package.json").version;
22
14
  export const isValidVersion = (version) => /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.test(version);
23
- /**
24
- * `1.2.3` against `1.10.0`, numerically per field: a string compare would call
25
- * the second one older. A prerelease suffix loses to the release it precedes,
26
- * which is all the semver this needs.
27
- */
15
+ /** Numeric per field (a string compare calls `1.10.0` older than `1.2.3`); a
16
+ * prerelease loses to its release, which is all the semver this needs. */
28
17
  export function isNewer(candidate, than) {
29
18
  const parse = (v) => (v.split("-")[0] ?? "").split(".").map((n) => Number.parseInt(n, 10) || 0);
30
19
  const [a, b] = [parse(candidate), parse(than)];
@@ -32,7 +21,6 @@ export function isNewer(candidate, than) {
32
21
  if ((a[i] ?? 0) !== (b[i] ?? 0))
33
22
  return (a[i] ?? 0) > (b[i] ?? 0);
34
23
  }
35
- // Equal numbers: a prerelease is older than the release of the same version.
36
24
  const pre = (v) => v.split("-")[1] ?? "";
37
25
  return pre(candidate) === "" && pre(than) !== "";
38
26
  }
@@ -49,9 +37,8 @@ export class UpdateCheck {
49
37
  this.fetchLatest = fetchLatest;
50
38
  this.now = now;
51
39
  }
52
- /** The last answer, and a refresh in the background when it is stale. Never
53
- * awaits the network: a workbench that loads is worth more than a fresh
54
- * version number. */
40
+ /** Never awaits the network: a workbench that loads is worth more than a
41
+ * fresh version number. */
55
42
  status() {
56
43
  if (this.now() - this.#checkedAt >= TTL_MS)
57
44
  void this.refresh();
@@ -61,16 +48,14 @@ export class UpdateCheck {
61
48
  available: this.#latest !== null && isNewer(this.#latest, this.current),
62
49
  };
63
50
  }
64
- /** The answer, waiting for the very first check instead of reporting "no
65
- * idea". A browser asks once per page load, so a process that had never
66
- * checked told every one of them `latest: null` — which is exactly how a
67
- * published release looked undetected. Later loads are served from cache. */
51
+ /** Waits for the very first check: `latest: null` on every page load is how
52
+ * a published release goes undetected. */
68
53
  async statusNow() {
69
54
  if (this.#checkedAt === 0)
70
55
  await this.refresh();
71
56
  return this.status();
72
57
  }
73
- /** Ask now. Concurrent callers share the one request. */
58
+ /** Concurrent callers share the one request. */
74
59
  refresh() {
75
60
  this.#inFlight ??= this.fetchLatest()
76
61
  .then((latest) => {
@@ -78,8 +63,7 @@ export class UpdateCheck {
78
63
  if (isNewer(latest, this.current))
79
64
  log.info(`${latest} is available (running ${this.current})`);
80
65
  })
81
- // A failed check is not a failure: no network, an offline box, a registry
82
- // hiccup. It is reported once at debug and retried at the next TTL.
66
+ // No network or a registry hiccup is not a failure; retried at the next TTL.
83
67
  .catch((err) => log.debug(`registry check failed: ${String(err)}`))
84
68
  .finally(() => {
85
69
  this.#checkedAt = this.now();
@@ -88,19 +72,16 @@ export class UpdateCheck {
88
72
  return this.#inFlight;
89
73
  }
90
74
  }
91
- /** Often enough to catch an idle window on a busy box, and cheap: the registry
92
- * itself is still only asked once per TTL (`status()` owns that). */
75
+ /** Often enough to catch an idle window on a busy box; the registry is still
76
+ * asked only once per TTL. */
93
77
  const AUTO_POLL_MS = 15 * 60_000;
94
78
  /** Watch for the moment all three conditions hold. Returns its own stop. */
95
79
  export function startAutoUpdate(check, auto, pollMs = AUTO_POLL_MS) {
96
- // A handover drains first, which can outlast a poll interval; a second
97
- // attempt on top of it would drain an already-draining Pier.
80
+ // A drain can outlast a poll interval.
98
81
  let handingOver = false;
99
82
  const tick = async () => {
100
83
  if (handingOver || !auto.enabled())
101
84
  return;
102
- // Refreshes in the background when stale; today's answer is good enough,
103
- // because the next tick is a quarter of an hour away either way.
104
85
  const { latest, available } = check.status();
105
86
  if (!available || !auto.idle())
106
87
  return;
@@ -108,9 +89,7 @@ export function startAutoUpdate(check, auto, pollMs = AUTO_POLL_MS) {
108
89
  handingOver = true;
109
90
  try {
110
91
  const started = await auto.apply();
111
- // Not silent (§5b): an update that never happens must not look like an
112
- // update that was never wanted. `busy` is the one non-start that is
113
- // fine — someone else is already restarting this Pier.
92
+ // §5: an update that never happens must not look like one never wanted.
114
93
  if (started === "busy")
115
94
  log.info("auto-update: a handover or restart is already in progress");
116
95
  else if (started !== "started")
@@ -120,18 +99,16 @@ export function startAutoUpdate(check, auto, pollMs = AUTO_POLL_MS) {
120
99
  log.error("auto-update failed", err);
121
100
  }
122
101
  finally {
123
- // Only reached when the handover did *not* take the process with it, so
124
- // the next tick is allowed to try again.
102
+ // Only reached when the handover did not take the process with it.
125
103
  handingOver = false;
126
104
  }
127
105
  };
128
106
  const timer = setInterval(() => void tick(), pollMs);
129
- timer.unref(); // a pending check must never be what keeps the process alive
107
+ timer.unref();
130
108
  return () => clearInterval(timer);
131
109
  }
132
110
  async function fetchLatestVersion() {
133
- // Plain JSON: the abbreviated-packument content type npm uses for a whole
134
- // package is a 406 on this endpoint, which answers one version already.
111
+ // npm's abbreviated-packument content type is a 406 on this endpoint.
135
112
  const res = await fetch(ENDPOINT, {
136
113
  signal: AbortSignal.timeout(TIMEOUT_MS),
137
114
  headers: { accept: "application/json" },