@supaku/agentfactory-nextjs 0.6.2 → 0.6.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../../src/handlers/public/stats.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAK1C,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;CACvB;AAUD,wBAAgB,wBAAwB;;mBAhBvB,MAAM;mBACN,MAAM;gBACT,MAAM;oBACF,MAAM;uBACH,MAAM;oBACT,MAAM;IAsEvB"}
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../../src/handlers/public/stats.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAK1C,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;CACvB;AAUD,wBAAgB,wBAAwB;;mBAhBvB,MAAM;mBACN,MAAM;gBACT,MAAM;oBACF,MAAM;uBACH,MAAM;oBACT,MAAM;IAyEvB"}
@@ -14,12 +14,14 @@ function getTodayStart() {
14
14
  export function createPublicStatsHandler() {
15
15
  return async function GET() {
16
16
  try {
17
- const [allSessions, workers, capacity, queueLength] = await Promise.all([
17
+ // Fetch workers once and pass to getTotalCapacity to avoid
18
+ // redundant listWorkers() calls that can return different snapshots
19
+ const [allSessions, workers, queueLength] = await Promise.all([
18
20
  getAllSessions(),
19
21
  listWorkers(),
20
- getTotalCapacity(),
21
22
  getQueueLength(),
22
23
  ]);
24
+ const capacity = await getTotalCapacity(workers);
23
25
  const todayStart = getTodayStart();
24
26
  const agentsWorking = allSessions.filter((s) => s.status === 'running' || s.status === 'claimed').length;
25
27
  const completedToday = allSessions.filter((s) => s.status === 'completed' &&
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/handlers/workers/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAK1C,wBAAgB,uBAAuB;;;;;;;;;;;;;IA0BtC"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/handlers/workers/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAK1C,wBAAgB,uBAAuB;;;;;;;;;;;;;IA2BtC"}
@@ -10,11 +10,11 @@ const log = createLogger('api:workers:list');
10
10
  export function createWorkerListHandler() {
11
11
  return async function GET() {
12
12
  try {
13
- const [workers, capacity, queueLength] = await Promise.all([
13
+ const [workers, queueLength] = await Promise.all([
14
14
  listWorkers(),
15
- getTotalCapacity(),
16
15
  getQueueLength(),
17
16
  ]);
17
+ const capacity = await getTotalCapacity(workers);
18
18
  return NextResponse.json({
19
19
  workers,
20
20
  summary: {
@@ -1 +1 @@
1
- {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../../../src/handlers/workers/poll.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAavD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChC;AAED,wBAAgB,uBAAuB,KACX,SAAS,WAAW,EAAE,YAAY,WAAW,oCAkGxE"}
1
+ {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../../../src/handlers/workers/poll.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAavD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChC;AAED,wBAAgB,uBAAuB,KACX,SAAS,WAAW,EAAE,YAAY,WAAW,oCAoGxE"}
@@ -21,7 +21,9 @@ export function createWorkerPollHandler() {
21
21
  if (!worker) {
22
22
  return NextResponse.json({ error: 'Not Found', message: 'Worker not found' }, { status: 404 });
23
23
  }
24
- const availableCapacity = worker.capacity - worker.activeCount;
24
+ // Use activeSessions.length (authoritative Redis set) instead of
25
+ // activeCount (heartbeat-reported, can be stale after re-registration)
26
+ const availableCapacity = worker.capacity - worker.activeSessions.length;
25
27
  let work = [];
26
28
  if (availableCapacity > 0) {
27
29
  const desiredCount = Math.min(availableCapacity, 5);
@@ -1 +1 @@
1
- {"version":3,"file":"session-created.d.ts","sourceRoot":"","sources":["../../../../src/webhook/handlers/session-created.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,EAAE,oBAAoB,EAAiB,MAAM,6BAA6B,CAAA;AAiBtF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAQ3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAE/D,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,GAAG,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,GACnC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAiR9B"}
1
+ {"version":3,"file":"session-created.d.ts","sourceRoot":"","sources":["../../../../src/webhook/handlers/session-created.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,EAAE,oBAAoB,EAAiB,MAAM,6BAA6B,CAAA;AAiBtF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAQ3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAE/D,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,GAAG,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,GACnC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA4S9B"}
@@ -115,10 +115,29 @@ export async function handleSessionCreated(config, payload, rawPayload, log) {
115
115
  workType,
116
116
  });
117
117
  }
118
- // Phase 2.5: Auto-detect parent issues for coordination
118
+ // Phase 2.5: Auto-detect parent/child issues for coordination routing
119
119
  if (workType === 'development' && workTypeSource === 'status') {
120
120
  try {
121
121
  const linearClient = await config.linearClient.getClient(payload.organizationId);
122
+ // Skip child/sub-issues for non-mention sessions — these are managed
123
+ // by the parent issue's coordinator agent, not dispatched independently.
124
+ const isChild = await linearClient.isChildIssue(issueId);
125
+ if (isChild) {
126
+ sessionLog.info('Sub-issue detected, skipping independent agent dispatch', {
127
+ issueIdentifier,
128
+ });
129
+ try {
130
+ await emitActivity(linearClient, sessionId, 'response', `This is a sub-issue. Work will be coordinated by the parent issue's agent.`);
131
+ }
132
+ catch (err) {
133
+ sessionLog.warn('Failed to emit sub-issue skip activity', { error: err });
134
+ }
135
+ return NextResponse.json({
136
+ success: true,
137
+ skipped: true,
138
+ reason: 'sub_issue_managed_by_parent',
139
+ });
140
+ }
122
141
  const isParent = await linearClient.isParentIssue(issueId);
123
142
  if (isParent) {
124
143
  workType = 'coordination';
@@ -128,7 +147,7 @@ export async function handleSessionCreated(config, payload, rawPayload, log) {
128
147
  }
129
148
  }
130
149
  catch (err) {
131
- sessionLog.warn('Failed to check if issue is parent', { error: err });
150
+ sessionLog.warn('Failed to check issue parent/child status', { error: err });
132
151
  }
133
152
  }
134
153
  // Check terminal state
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supaku/agentfactory-nextjs",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "type": "module",
5
5
  "description": "Next.js API route handlers for AgentFactory — webhook processor, worker/session management, public stats",
6
6
  "author": "Supaku (https://supaku.com)",
@@ -48,9 +48,9 @@
48
48
  "LICENSE"
49
49
  ],
50
50
  "dependencies": {
51
- "@supaku/agentfactory-linear": "0.6.2",
52
- "@supaku/agentfactory-server": "0.6.2",
53
- "@supaku/agentfactory": "0.6.2"
51
+ "@supaku/agentfactory": "0.6.3",
52
+ "@supaku/agentfactory-linear": "0.6.3",
53
+ "@supaku/agentfactory-server": "0.6.3"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "next": ">=14.0.0"