@amodalai/runtime 0.3.49 → 0.3.51

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 (161) hide show
  1. package/dist/src/agent/completion-tools.integration.test.d.ts +6 -0
  2. package/dist/src/agent/completion-tools.integration.test.js +263 -0
  3. package/dist/src/agent/completion-tools.integration.test.js.map +1 -0
  4. package/dist/src/agent/load-template-plan.integration.test.d.ts +6 -0
  5. package/dist/src/agent/load-template-plan.integration.test.js +152 -0
  6. package/dist/src/agent/load-template-plan.integration.test.js.map +1 -0
  7. package/dist/src/agent/local-server.js +64 -9
  8. package/dist/src/agent/local-server.js.map +1 -1
  9. package/dist/src/agent/loop-types.d.ts +12 -2
  10. package/dist/src/agent/loop.test.js +5 -2
  11. package/dist/src/agent/loop.test.js.map +1 -1
  12. package/dist/src/agent/propose-plan.integration.test.d.ts +6 -0
  13. package/dist/src/agent/propose-plan.integration.test.js +186 -0
  14. package/dist/src/agent/propose-plan.integration.test.js.map +1 -0
  15. package/dist/src/agent/routes/package-updates.d.ts +42 -0
  16. package/dist/src/agent/routes/package-updates.js +207 -0
  17. package/dist/src/agent/routes/package-updates.js.map +1 -0
  18. package/dist/src/agent/routes/package-updates.test.d.ts +6 -0
  19. package/dist/src/agent/routes/package-updates.test.js +25 -0
  20. package/dist/src/agent/routes/package-updates.test.js.map +1 -0
  21. package/dist/src/agent/setup-state.integration.test.d.ts +6 -0
  22. package/dist/src/agent/setup-state.integration.test.js +182 -0
  23. package/dist/src/agent/setup-state.integration.test.js.map +1 -0
  24. package/dist/src/agent/snapshot-server.js +1 -0
  25. package/dist/src/agent/snapshot-server.js.map +1 -1
  26. package/dist/src/agent/states/executing.d.ts +6 -0
  27. package/dist/src/agent/states/executing.js +63 -27
  28. package/dist/src/agent/states/executing.js.map +1 -1
  29. package/dist/src/agent/states/streaming.js +18 -2
  30. package/dist/src/agent/states/streaming.js.map +1 -1
  31. package/dist/src/agent/tool-executor-local.js +11 -2
  32. package/dist/src/agent/tool-executor-local.js.map +1 -1
  33. package/dist/src/agent/validate-connection.integration.test.d.ts +6 -0
  34. package/dist/src/agent/validate-connection.integration.test.js +160 -0
  35. package/dist/src/agent/validate-connection.integration.test.js.map +1 -0
  36. package/dist/src/api/create-agent.js +1 -0
  37. package/dist/src/api/create-agent.js.map +1 -1
  38. package/dist/src/index.d.ts +2 -0
  39. package/dist/src/index.js +9 -0
  40. package/dist/src/index.js.map +1 -1
  41. package/dist/src/intent/executor.d.ts +48 -0
  42. package/dist/src/intent/executor.js +420 -0
  43. package/dist/src/intent/executor.js.map +1 -0
  44. package/dist/src/intent/executor.test.d.ts +6 -0
  45. package/dist/src/intent/executor.test.js +543 -0
  46. package/dist/src/intent/executor.test.js.map +1 -0
  47. package/dist/src/intent/index.d.ts +10 -0
  48. package/dist/src/intent/index.js +9 -0
  49. package/dist/src/intent/index.js.map +1 -0
  50. package/dist/src/intent/loader.d.ts +16 -0
  51. package/dist/src/intent/loader.js +112 -0
  52. package/dist/src/intent/loader.js.map +1 -0
  53. package/dist/src/intent/loader.test.d.ts +6 -0
  54. package/dist/src/intent/loader.test.js +86 -0
  55. package/dist/src/intent/loader.test.js.map +1 -0
  56. package/dist/src/intent/matcher.d.ts +26 -0
  57. package/dist/src/intent/matcher.js +29 -0
  58. package/dist/src/intent/matcher.js.map +1 -0
  59. package/dist/src/intent/matcher.test.d.ts +6 -0
  60. package/dist/src/intent/matcher.test.js +53 -0
  61. package/dist/src/intent/matcher.test.js.map +1 -0
  62. package/dist/src/intent/onboarding.e2e.test.d.ts +6 -0
  63. package/dist/src/intent/onboarding.e2e.test.js +394 -0
  64. package/dist/src/intent/onboarding.e2e.test.js.map +1 -0
  65. package/dist/src/routes/ai-stream.js +96 -3
  66. package/dist/src/routes/ai-stream.js.map +1 -1
  67. package/dist/src/routes/session-resolver.js +16 -0
  68. package/dist/src/routes/session-resolver.js.map +1 -1
  69. package/dist/src/session/credential-scrubber.d.ts +35 -0
  70. package/dist/src/session/credential-scrubber.js +150 -0
  71. package/dist/src/session/credential-scrubber.js.map +1 -0
  72. package/dist/src/session/credential-scrubber.test.d.ts +6 -0
  73. package/dist/src/session/credential-scrubber.test.js +192 -0
  74. package/dist/src/session/credential-scrubber.test.js.map +1 -0
  75. package/dist/src/session/manager.intent.test.d.ts +6 -0
  76. package/dist/src/session/manager.intent.test.js +197 -0
  77. package/dist/src/session/manager.intent.test.js.map +1 -0
  78. package/dist/src/session/manager.js +114 -0
  79. package/dist/src/session/manager.js.map +1 -1
  80. package/dist/src/session/session-builder.d.ts +16 -1
  81. package/dist/src/session/session-builder.js +209 -41
  82. package/dist/src/session/session-builder.js.map +1 -1
  83. package/dist/src/session/store.js +48 -2
  84. package/dist/src/session/store.js.map +1 -1
  85. package/dist/src/session/tool-context-factory.js +12 -0
  86. package/dist/src/session/tool-context-factory.js.map +1 -1
  87. package/dist/src/session/types.d.ts +12 -1
  88. package/dist/src/setup/commit-setup.d.ts +94 -0
  89. package/dist/src/setup/commit-setup.js +154 -0
  90. package/dist/src/setup/commit-setup.js.map +1 -0
  91. package/dist/src/setup/commit-setup.test.d.ts +6 -0
  92. package/dist/src/setup/commit-setup.test.js +310 -0
  93. package/dist/src/setup/commit-setup.test.js.map +1 -0
  94. package/dist/src/tools/README.md +270 -0
  95. package/dist/src/tools/admin-tools.d.ts +27 -0
  96. package/dist/src/tools/admin-tools.js +734 -0
  97. package/dist/src/tools/admin-tools.js.map +1 -0
  98. package/dist/src/tools/agent-package-discovery.test.d.ts +6 -0
  99. package/dist/src/tools/agent-package-discovery.test.js +90 -0
  100. package/dist/src/tools/agent-package-discovery.test.js.map +1 -0
  101. package/dist/src/tools/builtin/ask-choice.d.ts +8 -0
  102. package/dist/src/tools/builtin/ask-choice.js +54 -0
  103. package/dist/src/tools/builtin/ask-choice.js.map +1 -0
  104. package/dist/src/tools/context.d.ts +154 -0
  105. package/dist/src/tools/context.js +30 -0
  106. package/dist/src/tools/context.js.map +1 -0
  107. package/dist/src/tools/custom-tool-adapter.d.ts +33 -2
  108. package/dist/src/tools/custom-tool-adapter.js +38 -1
  109. package/dist/src/tools/custom-tool-adapter.js.map +1 -1
  110. package/dist/src/tools/custom-tool-adapter.test.js +48 -0
  111. package/dist/src/tools/custom-tool-adapter.test.js.map +1 -1
  112. package/dist/src/tools/fetch-url-tool.js +2 -0
  113. package/dist/src/tools/fetch-url-tool.js.map +1 -1
  114. package/dist/src/tools/file-tools.js +16 -0
  115. package/dist/src/tools/file-tools.js.map +1 -1
  116. package/dist/src/tools/fs/local.test.d.ts +6 -0
  117. package/dist/src/tools/fs/local.test.js +126 -0
  118. package/dist/src/tools/fs/local.test.js.map +1 -0
  119. package/dist/src/tools/index.d.ts +35 -0
  120. package/dist/src/tools/index.js +11 -0
  121. package/dist/src/tools/index.js.map +1 -0
  122. package/dist/src/tools/mcp-tool-adapter.js +2 -0
  123. package/dist/src/tools/mcp-tool-adapter.js.map +1 -1
  124. package/dist/src/tools/memory-tool.js +23 -1
  125. package/dist/src/tools/memory-tool.js.map +1 -1
  126. package/dist/src/tools/permissions.d.ts +36 -0
  127. package/dist/src/tools/permissions.js +97 -0
  128. package/dist/src/tools/permissions.js.map +1 -0
  129. package/dist/src/tools/permissions.test.d.ts +6 -0
  130. package/dist/src/tools/permissions.test.js +62 -0
  131. package/dist/src/tools/permissions.test.js.map +1 -0
  132. package/dist/src/tools/request-tool.js +2 -0
  133. package/dist/src/tools/request-tool.js.map +1 -1
  134. package/dist/src/tools/sdk-context.d.ts +43 -0
  135. package/dist/src/tools/sdk-context.js +94 -0
  136. package/dist/src/tools/sdk-context.js.map +1 -0
  137. package/dist/src/tools/sdk-context.test.d.ts +6 -0
  138. package/dist/src/tools/sdk-context.test.js +134 -0
  139. package/dist/src/tools/sdk-context.test.js.map +1 -0
  140. package/dist/src/tools/store-tools.js +6 -0
  141. package/dist/src/tools/store-tools.js.map +1 -1
  142. package/dist/src/tools/types.d.ts +53 -14
  143. package/dist/src/tools/web-search-tool.js +2 -0
  144. package/dist/src/tools/web-search-tool.js.map +1 -1
  145. package/dist/src/types.d.ts +164 -28
  146. package/dist/src/types.js +9 -3
  147. package/dist/src/types.js.map +1 -1
  148. package/dist/tsconfig.tsbuildinfo +1 -1
  149. package/package.json +16 -4
  150. package/dist/src/tools/agent-config-tool.d.ts +0 -7
  151. package/dist/src/tools/agent-config-tool.js +0 -78
  152. package/dist/src/tools/agent-config-tool.js.map +0 -1
  153. package/dist/src/tools/collect-secret-tool.d.ts +0 -7
  154. package/dist/src/tools/collect-secret-tool.js +0 -47
  155. package/dist/src/tools/collect-secret-tool.js.map +0 -1
  156. package/dist/src/tools/fs/http.d.ts +0 -37
  157. package/dist/src/tools/fs/http.js +0 -88
  158. package/dist/src/tools/fs/http.js.map +0 -1
  159. package/dist/src/tools/http-file-tools.d.ts +0 -13
  160. package/dist/src/tools/http-file-tools.js +0 -146
  161. package/dist/src/tools/http-file-tools.js.map +0 -1
@@ -0,0 +1,186 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Phase D integration test for `propose_plan` + `update_plan`. Pins
8
+ * the agent-admin handlers end-to-end through the actual runtime
9
+ * path: LocalToolExecutor compiles handler.ts via esbuild,
10
+ * dynamic-imports the resulting .mjs, and runs each with a
11
+ * CustomToolContext whose `emit` callback captures SSE events the
12
+ * way the runtime's executing state would.
13
+ *
14
+ * Skips when the agent-admin cache (~/.amodal/admin-agent/latest/)
15
+ * isn't populated.
16
+ */
17
+ import { existsSync } from 'node:fs';
18
+ import { homedir } from 'node:os';
19
+ import * as path from 'node:path';
20
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
21
+ import { LocalToolExecutor } from './tool-executor-local.js';
22
+ const ADMIN_AGENT_PATH = path.join(homedir(), '.amodal', 'admin-agent', 'latest');
23
+ const PROPOSE_HANDLER = path.join(ADMIN_AGENT_PATH, 'tools', 'propose_plan', 'handler.ts');
24
+ const UPDATE_HANDLER = path.join(ADMIN_AGENT_PATH, 'tools', 'update_plan', 'handler.ts');
25
+ const HAS_DEPS = existsSync(PROPOSE_HANDLER) && existsSync(UPDATE_HANDLER);
26
+ const describeWhenReady = HAS_DEPS ? describe : describe.skip;
27
+ describeWhenReady('propose_plan + update_plan (Phase D integration)', () => {
28
+ let executor;
29
+ let emitted;
30
+ beforeEach(() => {
31
+ executor = new LocalToolExecutor();
32
+ emitted = [];
33
+ });
34
+ afterEach(() => {
35
+ executor.dispose();
36
+ });
37
+ function loadedTool(handlerPath, name) {
38
+ return {
39
+ name,
40
+ description: `${name} test`,
41
+ parameters: {},
42
+ confirm: false,
43
+ timeout: 5_000,
44
+ env: [],
45
+ handlerPath,
46
+ location: path.dirname(handlerPath),
47
+ hasPackageJson: false,
48
+ hasSetupScript: false,
49
+ hasRequirementsTxt: false,
50
+ hasDockerfile: false,
51
+ sandboxLanguage: 'typescript',
52
+ };
53
+ }
54
+ function buildCtx() {
55
+ return {
56
+ async request() {
57
+ throw new Error('not used');
58
+ },
59
+ async exec() {
60
+ throw new Error('not used');
61
+ },
62
+ async store() {
63
+ throw new Error('not used');
64
+ },
65
+ env: () => undefined,
66
+ log: () => undefined,
67
+ signal: AbortSignal.timeout(30_000),
68
+ sessionId: 'sess_test',
69
+ emit: (event) => {
70
+ emitted.push(event);
71
+ },
72
+ };
73
+ }
74
+ it('propose_plan emits a proposal SSE event with the right shape', async () => {
75
+ const result = await executor.execute(loadedTool(PROPOSE_HANDLER, 'propose_plan'), {
76
+ summary: 'Plumbing scheduler + reminders',
77
+ skills: [{ label: 'Job Scheduler', description: 'Daily schedule via chat' }],
78
+ requiredConnections: [{ label: 'Twilio', description: 'SMS reminders' }],
79
+ optionalConnections: [{ label: 'Google Calendar', description: 'Sync' }],
80
+ }, buildCtx());
81
+ expect(result).toMatchObject({ ok: true });
82
+ expect(emitted).toHaveLength(1);
83
+ const event = emitted[0];
84
+ expect(event.type).toBe('proposal');
85
+ if (event.type !== 'proposal')
86
+ throw new Error('unreachable');
87
+ expect(event.summary).toBe('Plumbing scheduler + reminders');
88
+ expect(event.skills[0]).toEqual({ label: 'Job Scheduler', description: 'Daily schedule via chat' });
89
+ expect(event.required_connections[0]?.label).toBe('Twilio');
90
+ expect(event.optional_connections[0]?.label).toBe('Google Calendar');
91
+ expect(event.proposal_id).toMatch(/^proposal_/);
92
+ });
93
+ it('propose_plan rejects empty summary with reason: invalid_params', async () => {
94
+ const result = await executor.execute(loadedTool(PROPOSE_HANDLER, 'propose_plan'), {
95
+ summary: '',
96
+ skills: [],
97
+ requiredConnections: [],
98
+ optionalConnections: [],
99
+ }, buildCtx());
100
+ expect(result).toMatchObject({ ok: false, reason: 'invalid_params' });
101
+ expect(emitted).toHaveLength(0);
102
+ });
103
+ it('propose_plan rejects malformed skill entries', async () => {
104
+ const result = await executor.execute(loadedTool(PROPOSE_HANDLER, 'propose_plan'), {
105
+ summary: 'x',
106
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional bad input
107
+ skills: [{ label: 'No description' }],
108
+ requiredConnections: [],
109
+ optionalConnections: [],
110
+ }, buildCtx());
111
+ expect(result).toMatchObject({ ok: false, reason: 'invalid_params' });
112
+ expect(emitted).toHaveLength(0);
113
+ });
114
+ it('propose_plan returns no_emit when ctx.emit is absent', async () => {
115
+ const ctxNoEmit = buildCtx();
116
+ delete ctxNoEmit.emit;
117
+ const result = await executor.execute(loadedTool(PROPOSE_HANDLER, 'propose_plan'), {
118
+ summary: 'x',
119
+ skills: [],
120
+ requiredConnections: [],
121
+ optionalConnections: [],
122
+ }, ctxNoEmit);
123
+ expect(result).toMatchObject({ ok: false, reason: 'no_emit' });
124
+ });
125
+ it('update_plan emits an update_plan SSE event with only the patched fields', async () => {
126
+ const result = await executor.execute(loadedTool(UPDATE_HANDLER, 'update_plan'), {
127
+ proposalId: 'proposal_abc',
128
+ optionalConnections: [{ label: 'QuickBooks', description: 'Invoicing' }],
129
+ }, buildCtx());
130
+ expect(result).toMatchObject({ ok: true, proposalId: 'proposal_abc' });
131
+ expect(emitted).toHaveLength(1);
132
+ const event = emitted[0];
133
+ expect(event.type).toBe('update_plan');
134
+ if (event.type !== 'update_plan')
135
+ throw new Error('unreachable');
136
+ expect(event.proposal_id).toBe('proposal_abc');
137
+ // Only patched fields are emitted; unspecified ones must be omitted
138
+ // so the widget reducer leaves them untouched.
139
+ expect(event.optional_connections).toEqual([{ label: 'QuickBooks', description: 'Invoicing' }]);
140
+ expect(event.skills).toBeUndefined();
141
+ expect(event.required_connections).toBeUndefined();
142
+ expect(event.summary).toBeUndefined();
143
+ });
144
+ it('update_plan rejects empty proposalId', async () => {
145
+ const result = await executor.execute(loadedTool(UPDATE_HANDLER, 'update_plan'), { proposalId: '' }, buildCtx());
146
+ expect(result).toMatchObject({ ok: false, reason: 'invalid_params' });
147
+ });
148
+ it('update_plan accepts an empty array to clear a list', async () => {
149
+ const result = await executor.execute(loadedTool(UPDATE_HANDLER, 'update_plan'), { proposalId: 'p1', optionalConnections: [] }, buildCtx());
150
+ expect(result).toMatchObject({ ok: true });
151
+ const event = emitted[0];
152
+ if (event.type !== 'update_plan')
153
+ throw new Error('unreachable');
154
+ expect(event.optional_connections).toEqual([]);
155
+ });
156
+ it('propose_plan generates unique proposalIds across calls', async () => {
157
+ // Force time progression between calls so the suffix differs.
158
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
159
+ const r1 = await executor.execute(loadedTool(PROPOSE_HANDLER, 'propose_plan'), {
160
+ summary: 'a',
161
+ skills: [],
162
+ requiredConnections: [],
163
+ optionalConnections: [],
164
+ }, buildCtx());
165
+ await sleep(5);
166
+ const r2 = await executor.execute(loadedTool(PROPOSE_HANDLER, 'propose_plan'), {
167
+ summary: 'b',
168
+ skills: [],
169
+ requiredConnections: [],
170
+ optionalConnections: [],
171
+ }, buildCtx());
172
+ const id1 = r1.proposalId;
173
+ const id2 = r2.proposalId;
174
+ expect(id1).not.toBe(id2);
175
+ });
176
+ it('update_plan returns no_emit when ctx.emit is absent', async () => {
177
+ const ctxNoEmit = buildCtx();
178
+ delete ctxNoEmit.emit;
179
+ const result = await executor.execute(loadedTool(UPDATE_HANDLER, 'update_plan'), { proposalId: 'p1' }, ctxNoEmit);
180
+ expect(result).toMatchObject({ ok: false, reason: 'no_emit' });
181
+ });
182
+ });
183
+ // vi import is intentionally retained even when unused by individual cases:
184
+ // vitest's mock factory may be needed in the future for ctx variations.
185
+ void vi;
186
+ //# sourceMappingURL=propose-plan.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propose-plan.integration.test.js","sourceRoot":"","sources":["../../../src/agent/propose-plan.integration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;GAUG;AAEH,OAAO,EAAC,UAAU,EAAC,MAAM,SAAS,CAAC;AACnC,OAAO,EAAC,OAAO,EAAC,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAC,MAAM,QAAQ,CAAC;AAIvE,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAE3D,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;AAClF,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;AAC3F,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;AAEzF,MAAM,QAAQ,GAAG,UAAU,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,cAAc,CAAC,CAAC;AAC3E,MAAM,iBAAiB,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;AAE9D,iBAAiB,CAAC,kDAAkD,EAAE,GAAG,EAAE;IACzE,IAAI,QAA2B,CAAC;IAChC,IAAI,OAAgC,CAAC;IAErC,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACnC,OAAO,GAAG,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,SAAS,UAAU,CAAC,WAAmB,EAAE,IAAY;QACnD,OAAO;YACL,IAAI;YACJ,WAAW,EAAE,GAAG,IAAI,OAAO;YAC3B,UAAU,EAAE,EAAE;YACd,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,EAAE;YACP,WAAW;YACX,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;YACnC,cAAc,EAAE,KAAK;YACrB,cAAc,EAAE,KAAK;YACrB,kBAAkB,EAAE,KAAK;YACzB,aAAa,EAAE,KAAK;YACpB,eAAe,EAAE,YAAY;SAC9B,CAAC;IACJ,CAAC;IAED,SAAS,QAAQ;QACf,OAAO;YACL,KAAK,CAAC,OAAO;gBACX,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;YAC9B,CAAC;YACD,KAAK,CAAC,IAAI;gBACR,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;YAC9B,CAAC;YACD,KAAK,CAAC,KAAK;gBACT,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;YAC9B,CAAC;YACD,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS;YACpB,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS;YACpB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;YACnC,SAAS,EAAE,WAAW;YACtB,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;gBACd,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;SACF,CAAC;IACJ,CAAC;IAED,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CACnC,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,EAC3C;YACE,OAAO,EAAE,gCAAgC;YACzC,MAAM,EAAE,CAAC,EAAC,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,yBAAyB,EAAC,CAAC;YAC1E,mBAAmB,EAAE,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAC,CAAC;YACtE,mBAAmB,EAAE,CAAC,EAAC,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,EAAC,CAAC;SACvE,EACD,QAAQ,EAAE,CACX,CAAC;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAC,EAAE,EAAE,IAAI,EAAC,CAAC,CAAC;QACzC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAC,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,yBAAyB,EAAC,CAAC,CAAC;QAClG,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACrE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CACnC,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,EAC3C;YACE,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,EAAE;YACV,mBAAmB,EAAE,EAAE;YACvB,mBAAmB,EAAE,EAAE;SACxB,EACD,QAAQ,EAAE,CACX,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAC,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CACnC,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,EAC3C;YACE,OAAO,EAAE,GAAG;YACZ,uFAAuF;YACvF,MAAM,EAAE,CAAC,EAAC,KAAK,EAAE,gBAAgB,EAAC,CAAQ;YAC1C,mBAAmB,EAAE,EAAE;YACvB,mBAAmB,EAAE,EAAE;SACxB,EACD,QAAQ,EAAE,CACX,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAC,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,SAAS,GAAsB,QAAQ,EAAE,CAAC;QAChD,OAAQ,SAA8B,CAAC,IAAI,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CACnC,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,EAC3C;YACE,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,EAAE;YACV,mBAAmB,EAAE,EAAE;YACvB,mBAAmB,EAAE,EAAE;SACxB,EACD,SAAS,CACV,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAC,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CACnC,UAAU,CAAC,cAAc,EAAE,aAAa,CAAC,EACzC;YACE,UAAU,EAAE,cAAc;YAC1B,mBAAmB,EAAE,CAAC,EAAC,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAC,CAAC;SACvE,EACD,QAAQ,EAAE,CACX,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAC,CAAC,CAAC;QACrE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC/C,oEAAoE;QACpE,+CAA+C;QAC/C,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,CAAC,EAAC,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAC9F,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,aAAa,EAAE,CAAC;QACnD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CACnC,UAAU,CAAC,cAAc,EAAE,aAAa,CAAC,EACzC,EAAC,UAAU,EAAE,EAAE,EAAC,EAChB,QAAQ,EAAE,CACX,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CACnC,UAAU,CAAC,cAAc,EAAE,aAAa,CAAC,EACzC,EAAC,UAAU,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAC,EAC3C,QAAQ,EAAE,CACX,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAC,EAAE,EAAE,IAAI,EAAC,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,8DAA8D;QAC9D,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACpE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,OAAO,CAC/B,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,EAC3C;YACE,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,EAAE;YACV,mBAAmB,EAAE,EAAE;YACvB,mBAAmB,EAAE,EAAE;SACxB,EACD,QAAQ,EAAE,CACX,CAAC;QACF,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;QACf,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,OAAO,CAC/B,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,EAC3C;YACE,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,EAAE;YACV,mBAAmB,EAAE,EAAE;YACvB,mBAAmB,EAAE,EAAE;SACxB,EACD,QAAQ,EAAE,CACX,CAAC;QAGF,MAAM,GAAG,GAAI,EAA2B,CAAC,UAAU,CAAC;QAEpD,MAAM,GAAG,GAAI,EAA2B,CAAC,UAAU,CAAC;QACpD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,SAAS,GAAsB,QAAQ,EAAE,CAAC;QAChD,OAAQ,SAA8B,CAAC,IAAI,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CACnC,UAAU,CAAC,cAAc,EAAE,aAAa,CAAC,EACzC,EAAC,UAAU,EAAE,IAAI,EAAC,EAClB,SAAS,CACV,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAC,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,4EAA4E;AAC5E,wEAAwE;AAExE,KAAK,EAAE,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * GET /api/package-updates — checks every entry in `amodal.json#packages`
8
+ * for a newer published npm version and returns the diff. Cached in-memory
9
+ * for 1 day so refreshing the home screen doesn't hammer the registry.
10
+ *
11
+ * POST /api/package-updates/install — runs `npm install <pkg>@latest` in
12
+ * the repo root, then invalidates the cache so the next GET reflects the
13
+ * new state.
14
+ */
15
+ import { type Router } from 'express';
16
+ import type { Logger } from '../../logger.js';
17
+ export interface PackageUpdate {
18
+ /** Package name, e.g. "@amodalai/connection-slack". */
19
+ name: string;
20
+ /** Currently installed version (from node_modules/<pkg>/package.json). */
21
+ installed: string | null;
22
+ /** Latest version published to npm. Null if the registry call failed. */
23
+ latest: string | null;
24
+ /** True when latest > installed (string compare on semver-like values). */
25
+ hasUpdate: boolean;
26
+ }
27
+ interface RouterDeps {
28
+ /** Repo root used to resolve `amodal.json` and `node_modules/<pkg>`. */
29
+ repoPath: string;
30
+ logger: Logger;
31
+ }
32
+ export declare function createPackageUpdatesRouter(deps: RouterDeps): Router;
33
+ declare function readAmodalPackages(repoPath: string): string[];
34
+ declare function readInstalledVersion(repoPath: string, name: string): string | null;
35
+ /**
36
+ * Loose semver compare: split on dots, compare numerically when possible.
37
+ * Returns negative when a < b, positive when a > b, 0 when equal. Tags like
38
+ * "1.2.0-beta.1" sort by lexical order on the tail — good enough for "is
39
+ * there an update available?".
40
+ */
41
+ export declare function compareVersions(a: string, b: string): number;
42
+ export { readAmodalPackages, readInstalledVersion };
@@ -0,0 +1,207 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * GET /api/package-updates — checks every entry in `amodal.json#packages`
8
+ * for a newer published npm version and returns the diff. Cached in-memory
9
+ * for 1 day so refreshing the home screen doesn't hammer the registry.
10
+ *
11
+ * POST /api/package-updates/install — runs `npm install <pkg>@latest` in
12
+ * the repo root, then invalidates the cache so the next GET reflects the
13
+ * new state.
14
+ */
15
+ import express, {} from 'express';
16
+ import { execFile } from 'node:child_process';
17
+ import { readFileSync, existsSync } from 'node:fs';
18
+ import { promisify } from 'node:util';
19
+ import * as path from 'node:path';
20
+ const execFileAsync = promisify(execFile);
21
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 1 day
22
+ const NPM_VIEW_TIMEOUT_MS = 10_000;
23
+ const NPM_INSTALL_TIMEOUT_MS = 120_000;
24
+ const PACKAGE_NAME_REGEX = /^(?:@[a-z0-9-]+\/)?[a-z0-9][a-z0-9._-]*$/;
25
+ /**
26
+ * Resolve a path beneath `<repoPath>/node_modules` and verify the
27
+ * result stays inside that base. Returns null on traversal attempts
28
+ * (symlinks, double-resolved paths, etc.). The regex above already
29
+ * blocks `/` outside the scope segment, but CodeQL flags any flow
30
+ * from user input into a path expression — this is the belt and
31
+ * suspenders.
32
+ */
33
+ function safeNodeModulesPath(repoPath, name, ...rest) {
34
+ const base = path.resolve(repoPath, 'node_modules');
35
+ const candidate = path.resolve(base, name, ...rest);
36
+ if (candidate !== base && !candidate.startsWith(base + path.sep))
37
+ return null;
38
+ return candidate;
39
+ }
40
+ export function createPackageUpdatesRouter(deps) {
41
+ const router = express.Router();
42
+ const cache = { payload: null };
43
+ router.get('/api/package-updates', (_req, res) => {
44
+ void (async () => {
45
+ try {
46
+ const fresh = cache.payload && Date.now() - cache.payload.checkedAt < CACHE_TTL_MS;
47
+ if (!fresh) {
48
+ cache.payload = await refreshUpdates(deps);
49
+ }
50
+ res.json(cache.payload);
51
+ }
52
+ catch (err) {
53
+ deps.logger.warn('package_updates_failed', { error: err instanceof Error ? err.message : String(err) });
54
+ res.status(500).json({ error: 'package_updates_failed' });
55
+ }
56
+ })();
57
+ });
58
+ // Read the installed card.json for a single package — drives the
59
+ // "See what changed" page so it can show the user what they have today
60
+ // before they hit Update.
61
+ router.get('/api/package-card', (req, res) => {
62
+ void (async () => {
63
+ const name = typeof req.query['name'] === 'string' ? req.query['name'] : '';
64
+ if (!PACKAGE_NAME_REGEX.test(name)) {
65
+ res.status(400).json({ error: 'invalid_package_name' });
66
+ return;
67
+ }
68
+ // Allowlist gate: only read card.json for packages declared in
69
+ // amodal.json#packages. Belt to safeNodeModulesPath's suspenders —
70
+ // the regex above already blocks traversal characters, but explicit
71
+ // allowlisting tells static analyzers (CodeQL) that the eventual
72
+ // path expression depends on a sanitized value, not raw user input.
73
+ const declared = new Set(readAmodalPackages(deps.repoPath));
74
+ if (!declared.has(name)) {
75
+ res.status(404).json({ error: 'card_not_found' });
76
+ return;
77
+ }
78
+ const cardPath = safeNodeModulesPath(deps.repoPath, name, 'card', 'card.json');
79
+ if (cardPath === null || !existsSync(cardPath)) {
80
+ res.status(404).json({ error: 'card_not_found' });
81
+ return;
82
+ }
83
+ try {
84
+ const raw = readFileSync(cardPath, 'utf-8');
85
+ res.type('application/json').send(raw);
86
+ }
87
+ catch (err) {
88
+ deps.logger.warn('package_card_read_failed', { name, error: err instanceof Error ? err.message : String(err) });
89
+ res.status(500).json({ error: 'card_read_failed' });
90
+ }
91
+ })();
92
+ });
93
+ router.post('/api/package-updates/install', express.json({ limit: '8kb' }), (req, res) => {
94
+ void (async () => {
95
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- parsing JSON body at module boundary
96
+ const body = req.body;
97
+ const name = body.name;
98
+ if (typeof name !== 'string' || !PACKAGE_NAME_REGEX.test(name)) {
99
+ res.status(400).json({ error: 'invalid_package_name' });
100
+ return;
101
+ }
102
+ try {
103
+ await execFileAsync('npm', ['install', `${name}@latest`], {
104
+ cwd: deps.repoPath,
105
+ timeout: NPM_INSTALL_TIMEOUT_MS,
106
+ });
107
+ cache.payload = null; // force refresh on next GET
108
+ res.json({ ok: true, name });
109
+ }
110
+ catch (err) {
111
+ const message = err instanceof Error ? err.message : String(err);
112
+ deps.logger.warn('package_install_failed', { name, error: message });
113
+ res.status(500).json({ error: 'install_failed', message });
114
+ }
115
+ })();
116
+ });
117
+ return router;
118
+ }
119
+ // ---------------------------------------------------------------------------
120
+ // Refresh logic
121
+ // ---------------------------------------------------------------------------
122
+ async function refreshUpdates(deps) {
123
+ const { repoPath, logger } = deps;
124
+ const installedNames = readAmodalPackages(repoPath);
125
+ if (installedNames.length === 0) {
126
+ return { updates: [], checkedAt: Date.now() };
127
+ }
128
+ const updates = await Promise.all(installedNames.map(async (name) => {
129
+ const installed = readInstalledVersion(repoPath, name);
130
+ const latest = await fetchLatestVersion(name, logger);
131
+ const hasUpdate = installed !== null && latest !== null && compareVersions(installed, latest) < 0;
132
+ return { name, installed, latest, hasUpdate };
133
+ }));
134
+ return { updates, checkedAt: Date.now() };
135
+ }
136
+ function readAmodalPackages(repoPath) {
137
+ const configPath = path.join(repoPath, 'amodal.json');
138
+ if (!existsSync(configPath))
139
+ return [];
140
+ try {
141
+ const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
142
+ if (typeof raw !== 'object' || raw === null)
143
+ return [];
144
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- guarded above
145
+ const packagesRaw = raw['packages'];
146
+ if (!Array.isArray(packagesRaw))
147
+ return [];
148
+ return packagesRaw.filter((n) => typeof n === 'string' && PACKAGE_NAME_REGEX.test(n));
149
+ }
150
+ catch {
151
+ return [];
152
+ }
153
+ }
154
+ function readInstalledVersion(repoPath, name) {
155
+ const pkgPath = safeNodeModulesPath(repoPath, name, 'package.json');
156
+ if (pkgPath === null || !existsSync(pkgPath))
157
+ return null;
158
+ try {
159
+ const raw = JSON.parse(readFileSync(pkgPath, 'utf-8'));
160
+ if (typeof raw !== 'object' || raw === null)
161
+ return null;
162
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- guarded above
163
+ const version = raw['version'];
164
+ return typeof version === 'string' ? version : null;
165
+ }
166
+ catch {
167
+ return null;
168
+ }
169
+ }
170
+ async function fetchLatestVersion(name, logger) {
171
+ try {
172
+ const { stdout } = await execFileAsync('npm', ['view', name, 'version'], {
173
+ timeout: NPM_VIEW_TIMEOUT_MS,
174
+ });
175
+ const version = stdout.trim();
176
+ return version === '' ? null : version;
177
+ }
178
+ catch (err) {
179
+ logger.debug('npm_view_failed', { name, error: err instanceof Error ? err.message : String(err) });
180
+ return null;
181
+ }
182
+ }
183
+ /**
184
+ * Loose semver compare: split on dots, compare numerically when possible.
185
+ * Returns negative when a < b, positive when a > b, 0 when equal. Tags like
186
+ * "1.2.0-beta.1" sort by lexical order on the tail — good enough for "is
187
+ * there an update available?".
188
+ */
189
+ export function compareVersions(a, b) {
190
+ const partsA = a.split('.');
191
+ const partsB = b.split('.');
192
+ const len = Math.max(partsA.length, partsB.length);
193
+ for (let i = 0; i < len; i++) {
194
+ const av = partsA[i] ?? '0';
195
+ const bv = partsB[i] ?? '0';
196
+ const an = Number.parseInt(av, 10);
197
+ const bn = Number.parseInt(bv, 10);
198
+ if (!Number.isNaN(an) && !Number.isNaN(bn) && an !== bn)
199
+ return an - bn;
200
+ if (av !== bv)
201
+ return av < bv ? -1 : 1;
202
+ }
203
+ return 0;
204
+ }
205
+ // Re-export for unit test access without going through the router.
206
+ export { readAmodalPackages, readInstalledVersion };
207
+ //# sourceMappingURL=package-updates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-updates.js","sourceRoot":"","sources":["../../../../src/agent/routes/package-updates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;GAQG;AAEH,OAAO,OAAO,EAAE,EAA0C,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAC,QAAQ,EAAC,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAC,YAAY,EAAE,UAAU,EAAC,MAAM,SAAS,CAAC;AACjD,OAAO,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,QAAQ;AAClD,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACnC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AACvC,MAAM,kBAAkB,GAAG,0CAA0C,CAAC;AAEtE;;;;;;;GAOG;AACH,SAAS,mBAAmB,CAAC,QAAgB,EAAE,IAAY,EAAE,GAAG,IAAc;IAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;IACpD,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9E,OAAO,SAAS,CAAC;AACnB,CAAC;AAyBD,MAAM,UAAU,0BAA0B,CAAC,IAAgB;IACzD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAChC,MAAM,KAAK,GAAqC,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC;IAEhE,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QAClE,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,GAAG,YAAY,CAAC;gBACnF,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,KAAK,CAAC,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;gBAC7C,CAAC;gBACD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAC,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAC,CAAC,CAAC;gBACtG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,wBAAwB,EAAC,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,iEAAiE;IACjE,uEAAuE;IACvE,0BAA0B;IAC1B,MAAM,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QAC9D,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5E,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,sBAAsB,EAAC,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;YACD,+DAA+D;YAC/D,mEAAmE;YACnE,oEAAoE;YACpE,iEAAiE;YACjE,oEAAoE;YACpE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,gBAAgB,EAAC,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YAC/E,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,gBAAgB,EAAC,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC5C,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAC,IAAI,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAC,CAAC,CAAC;gBAC9G,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,kBAAkB,EAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,OAAO,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,KAAK,EAAC,CAAC,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QACxG,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,+GAA+G;YAC/G,MAAM,IAAI,GAAG,GAAG,CAAC,IAAwB,CAAC;YAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACvB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,sBAAsB,EAAC,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,GAAG,IAAI,SAAS,CAAC,EAAE;oBACxD,GAAG,EAAE,IAAI,CAAC,QAAQ;oBAClB,OAAO,EAAE,sBAAsB;iBAChC,CAAC,CAAC;gBACH,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,4BAA4B;gBAClD,GAAG,CAAC,IAAI,CAAC,EAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;YAC7B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAC,CAAC,CAAC;gBACnE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAC,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,KAAK,UAAU,cAAc,CAAC,IAAgB;IAC5C,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,IAAI,CAAC;IAChC,MAAM,cAAc,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,EAAC,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAC,CAAC;IAC9C,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAA0B,EAAE;QACxD,MAAM,SAAS,GAAG,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,SAAS,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAClG,OAAO,EAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAC,CAAC;IAC9C,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,EAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAC,CAAC;AAC1C,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACtD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACnE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;QACvD,wFAAwF;QACxF,MAAM,WAAW,GAAI,GAA+B,CAAC,UAAU,CAAC,CAAC;QACjE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;YAAE,OAAO,EAAE,CAAC;QAC3C,OAAO,WAAW,CAAC,MAAM,CACvB,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CACxE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB,EAAE,IAAY;IAC1D,MAAM,OAAO,GAAG,mBAAmB,CAAC,QAAQ,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IACpE,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1D,IAAI,CAAC;QACH,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACzD,wFAAwF;QACxF,MAAM,OAAO,GAAI,GAA+B,CAAC,SAAS,CAAC,CAAC;QAC5D,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,IAAY,EAAE,MAAc;IAC5D,IAAI,CAAC;QACH,MAAM,EAAC,MAAM,EAAC,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE;YACrE,OAAO,EAAE,mBAAmB;SAC7B,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAC,IAAI,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAC,CAAC,CAAC;QACjG,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,CAAS;IAClD,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QAC5B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QAC5B,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnC,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QACxE,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,mEAAmE;AACnE,OAAO,EAAC,kBAAkB,EAAE,oBAAoB,EAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export {};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { describe, it, expect } from 'vitest';
7
+ import { compareVersions } from './package-updates.js';
8
+ describe('compareVersions', () => {
9
+ it('orders patch bumps numerically, not lexically', () => {
10
+ expect(compareVersions('1.2.10', '1.2.9')).toBeGreaterThan(0);
11
+ expect(compareVersions('1.2.9', '1.2.10')).toBeLessThan(0);
12
+ });
13
+ it('treats missing components as zero', () => {
14
+ expect(compareVersions('1.2', '1.2.0')).toBe(0);
15
+ expect(compareVersions('1.2', '1.2.1')).toBeLessThan(0);
16
+ });
17
+ it('returns 0 for identical versions', () => {
18
+ expect(compareVersions('0.3.40', '0.3.40')).toBe(0);
19
+ });
20
+ it('orders prereleases lexically on the tail', () => {
21
+ expect(compareVersions('1.0.0-beta.1', '1.0.0-beta.2')).toBeLessThan(0);
22
+ expect(compareVersions('1.0.0-beta.10', '1.0.0-beta.9')).toBeGreaterThan(0);
23
+ });
24
+ });
25
+ //# sourceMappingURL=package-updates.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-updates.test.js","sourceRoot":"","sources":["../../../../src/agent/routes/package-updates.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAC,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAErD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,eAAe,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export {};