instar 0.26.4 → 0.26.6
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 +61 -7
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +156 -3
- package/dist/commands/server.js.map +1 -1
- package/dist/core/SessionManager.d.ts +31 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +164 -20
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/TopicResumeMap.d.ts +5 -0
- package/dist/core/TopicResumeMap.d.ts.map +1 -1
- package/dist/core/TopicResumeMap.js +7 -0
- package/dist/core/TopicResumeMap.js.map +1 -1
- package/dist/core/types.d.ts +0 -4
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/messaging/imessage/IMessageAdapter.d.ts +16 -0
- package/dist/messaging/imessage/IMessageAdapter.d.ts.map +1 -1
- package/dist/messaging/imessage/IMessageAdapter.js +60 -2
- package/dist/messaging/imessage/IMessageAdapter.js.map +1 -1
- package/dist/messaging/imessage/types.d.ts +11 -0
- package/dist/messaging/imessage/types.d.ts.map +1 -1
- package/dist/messaging/slack/SlackAdapter.d.ts.map +1 -1
- package/dist/messaging/slack/SlackAdapter.js +46 -12
- package/dist/messaging/slack/SlackAdapter.js.map +1 -1
- package/dist/scaffold/templates.d.ts +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +32 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +1 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +155 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +65 -49
- package/src/templates/hooks/intercept-imsg-send.js +68 -0
- package/src/templates/scripts/imessage-reply.sh +130 -0
- package/upgrades/0.26.5.md +15 -0
- package/upgrades/0.26.6.md +23 -0
- package/upgrades/NEXT.md +0 -35
- /package/.claude/skills/secret-setup/{SKILL.md → skill.md} +0 -0
package/dist/server/routes.js
CHANGED
|
@@ -1254,6 +1254,22 @@ export function createRoutes(ctx) {
|
|
|
1254
1254
|
adapter: !!ctx.telegram,
|
|
1255
1255
|
bidirectional: hasTelegramConfig && hasTelegramReplyScript && !!ctx.telegram,
|
|
1256
1256
|
};
|
|
1257
|
+
// iMessage
|
|
1258
|
+
const hasIMessageConfig = ctx.config.messaging?.some(m => m.type === 'imessage' && m.enabled) ?? false;
|
|
1259
|
+
const imessage = {
|
|
1260
|
+
configured: hasIMessageConfig,
|
|
1261
|
+
adapter: !!ctx.imessage,
|
|
1262
|
+
connected: ctx.imessage?.getConnectionInfo().state === 'connected',
|
|
1263
|
+
endpoints: ctx.imessage ? [
|
|
1264
|
+
'GET /imessage/status',
|
|
1265
|
+
'POST /imessage/validate-send/:recipient — validate + get send token (Layer 3)',
|
|
1266
|
+
'POST /imessage/reply/:recipient — confirm delivery with token (called by imessage-reply.sh)',
|
|
1267
|
+
'GET /imessage/chats',
|
|
1268
|
+
'GET /imessage/chats/:chatId/history',
|
|
1269
|
+
'GET /imessage/search?q=...',
|
|
1270
|
+
'GET /imessage/log-stats',
|
|
1271
|
+
] : [],
|
|
1272
|
+
};
|
|
1257
1273
|
// Jobs
|
|
1258
1274
|
let jobCount = 0;
|
|
1259
1275
|
let jobSlugs = [];
|
|
@@ -1292,6 +1308,7 @@ export function createRoutes(ctx) {
|
|
|
1292
1308
|
scripts,
|
|
1293
1309
|
hooks,
|
|
1294
1310
|
telegram,
|
|
1311
|
+
imessage,
|
|
1295
1312
|
scheduler: {
|
|
1296
1313
|
enabled: ctx.config.scheduler.enabled,
|
|
1297
1314
|
jobCount,
|
|
@@ -3253,6 +3270,144 @@ export function createRoutes(ctx) {
|
|
|
3253
3270
|
links: ctx.messageBridge.getLinks(),
|
|
3254
3271
|
});
|
|
3255
3272
|
});
|
|
3273
|
+
// ── iMessage ─────────────────────────────────────────────────────
|
|
3274
|
+
router.get('/imessage/status', (_req, res) => {
|
|
3275
|
+
if (!ctx.imessage) {
|
|
3276
|
+
res.status(503).json({ error: 'iMessage not configured' });
|
|
3277
|
+
return;
|
|
3278
|
+
}
|
|
3279
|
+
res.json(ctx.imessage.getConnectionInfo());
|
|
3280
|
+
});
|
|
3281
|
+
// ── Outbound Safety: validate-before-send endpoint ──
|
|
3282
|
+
// Called by imessage-reply.sh BEFORE sending. Issues a single-use token
|
|
3283
|
+
// that binds validation to the actual send (TOCTOU mitigation).
|
|
3284
|
+
router.post('/imessage/validate-send/:recipient', (req, res) => {
|
|
3285
|
+
if (!ctx.imessage) {
|
|
3286
|
+
res.status(503).json({ error: 'iMessage not configured' });
|
|
3287
|
+
return;
|
|
3288
|
+
}
|
|
3289
|
+
const { recipient } = req.params;
|
|
3290
|
+
if (!recipient) {
|
|
3291
|
+
res.status(400).json({ error: 'recipient parameter required' });
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
const result = ctx.imessage.validateSend(decodeURIComponent(recipient));
|
|
3295
|
+
if (!result.allowed) {
|
|
3296
|
+
res.status(403).json({
|
|
3297
|
+
allowed: false,
|
|
3298
|
+
reason: result.reason,
|
|
3299
|
+
});
|
|
3300
|
+
return;
|
|
3301
|
+
}
|
|
3302
|
+
res.json({
|
|
3303
|
+
allowed: true,
|
|
3304
|
+
token: result.token,
|
|
3305
|
+
sendMode: result.sendMode,
|
|
3306
|
+
});
|
|
3307
|
+
});
|
|
3308
|
+
// Reply confirmation endpoint — called by imessage-reply.sh AFTER sending via imsg CLI.
|
|
3309
|
+
// Requires a valid send token from validate-send (TOCTOU mitigation).
|
|
3310
|
+
// Logs the outbound message and clears stall tracking.
|
|
3311
|
+
router.post('/imessage/reply/:recipient', (req, res) => {
|
|
3312
|
+
if (!ctx.imessage) {
|
|
3313
|
+
res.status(503).json({ error: 'iMessage not configured' });
|
|
3314
|
+
return;
|
|
3315
|
+
}
|
|
3316
|
+
const { recipient } = req.params;
|
|
3317
|
+
if (!recipient) {
|
|
3318
|
+
res.status(400).json({ error: 'recipient parameter required' });
|
|
3319
|
+
return;
|
|
3320
|
+
}
|
|
3321
|
+
const decodedRecipient = decodeURIComponent(recipient);
|
|
3322
|
+
// Validate recipient is authorized
|
|
3323
|
+
if (!ctx.imessage.isAuthorized(decodedRecipient)) {
|
|
3324
|
+
res.status(403).json({ error: 'recipient not in authorizedContacts' });
|
|
3325
|
+
return;
|
|
3326
|
+
}
|
|
3327
|
+
const { text, sendToken } = req.body;
|
|
3328
|
+
if (!text || typeof text !== 'string') {
|
|
3329
|
+
res.status(400).json({ error: '"text" field required' });
|
|
3330
|
+
return;
|
|
3331
|
+
}
|
|
3332
|
+
// Validate send token if provided (TOCTOU binding)
|
|
3333
|
+
if (sendToken) {
|
|
3334
|
+
const tokenResult = ctx.imessage.confirmSend(sendToken, decodedRecipient, text);
|
|
3335
|
+
if (!tokenResult.ok) {
|
|
3336
|
+
res.status(403).json({ error: tokenResult.reason });
|
|
3337
|
+
return;
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
// Log outbound message
|
|
3341
|
+
ctx.imessage.logOutboundMessage(decodedRecipient, text);
|
|
3342
|
+
// Clear stall tracking for this sender
|
|
3343
|
+
ctx.imessage.clearStallForSender(decodedRecipient);
|
|
3344
|
+
// Also clear in SessionManager if available
|
|
3345
|
+
if (ctx.sessionManager && 'clearIMessageInjectionTracker' in ctx.sessionManager) {
|
|
3346
|
+
ctx.sessionManager.clearIMessageInjectionTracker(decodedRecipient);
|
|
3347
|
+
}
|
|
3348
|
+
res.json({ ok: true, recipient: decodedRecipient, logged: true });
|
|
3349
|
+
});
|
|
3350
|
+
router.get('/imessage/chats', async (req, res) => {
|
|
3351
|
+
if (!ctx.imessage) {
|
|
3352
|
+
res.status(503).json({ error: 'iMessage not configured' });
|
|
3353
|
+
return;
|
|
3354
|
+
}
|
|
3355
|
+
const limit = parseInt(req.query.limit) || 20;
|
|
3356
|
+
try {
|
|
3357
|
+
const chats = await ctx.imessage.listChats(limit);
|
|
3358
|
+
res.json(chats);
|
|
3359
|
+
}
|
|
3360
|
+
catch (err) {
|
|
3361
|
+
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
3362
|
+
}
|
|
3363
|
+
});
|
|
3364
|
+
router.get('/imessage/chats/:chatId/history', async (req, res) => {
|
|
3365
|
+
if (!ctx.imessage) {
|
|
3366
|
+
res.status(503).json({ error: 'iMessage not configured' });
|
|
3367
|
+
return;
|
|
3368
|
+
}
|
|
3369
|
+
const { chatId } = req.params;
|
|
3370
|
+
const limit = parseInt(req.query.limit) || 50;
|
|
3371
|
+
try {
|
|
3372
|
+
const history = await ctx.imessage.getChatHistory(chatId, limit);
|
|
3373
|
+
res.json(history);
|
|
3374
|
+
}
|
|
3375
|
+
catch (err) {
|
|
3376
|
+
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
3377
|
+
}
|
|
3378
|
+
});
|
|
3379
|
+
router.get('/imessage/log-stats', (_req, res) => {
|
|
3380
|
+
if (!ctx.imessage) {
|
|
3381
|
+
res.status(503).json({ error: 'iMessage not configured' });
|
|
3382
|
+
return;
|
|
3383
|
+
}
|
|
3384
|
+
try {
|
|
3385
|
+
const stats = ctx.imessage.messageLogger.getStats();
|
|
3386
|
+
res.json(stats);
|
|
3387
|
+
}
|
|
3388
|
+
catch (err) {
|
|
3389
|
+
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
3390
|
+
}
|
|
3391
|
+
});
|
|
3392
|
+
router.get('/imessage/search', (_req, res) => {
|
|
3393
|
+
if (!ctx.imessage) {
|
|
3394
|
+
res.status(503).json({ error: 'iMessage not configured' });
|
|
3395
|
+
return;
|
|
3396
|
+
}
|
|
3397
|
+
const query = (_req.query.q || '').trim();
|
|
3398
|
+
if (!query) {
|
|
3399
|
+
res.status(400).json({ error: 'q parameter required' });
|
|
3400
|
+
return;
|
|
3401
|
+
}
|
|
3402
|
+
const limit = parseInt(_req.query.limit) || 50;
|
|
3403
|
+
try {
|
|
3404
|
+
const results = ctx.imessage.messageLogger.search({ query, limit });
|
|
3405
|
+
res.json({ results, count: results.length });
|
|
3406
|
+
}
|
|
3407
|
+
catch (err) {
|
|
3408
|
+
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
3409
|
+
}
|
|
3410
|
+
});
|
|
3256
3411
|
// ── Relationships ─────────────────────────────────────────────────
|
|
3257
3412
|
router.get('/relationships', (req, res) => {
|
|
3258
3413
|
if (!ctx.relationships) {
|