agl 22.0.2 → 22.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agl",
3
- "version": "22.0.2",
3
+ "version": "22.0.4",
4
4
  "controllerUpgradeManagementVersion": 2,
5
5
  "private": false,
6
6
  "description": "Agent Gateway Layer for OpenCode and FlexHarness sessions",
@@ -20,13 +20,13 @@
20
20
  "@api.global/typedrequest-interfaces": "7.1.0",
21
21
  "@api.global/typedserver": "11.1.0",
22
22
  "@api.global/typedsocket": "8.0.0",
23
- "@design.estate/dees-catalog": "6.10.1",
23
+ "@design.estate/dees-catalog": "6.10.2",
24
24
  "@design.estate/dees-element": "2.4.0",
25
25
  "@modelprofile.com/browser-runtime": "3.0.1",
26
26
  "@modelprofile.com/crossharness-mcp": "4.1.1",
27
- "@modelprofile.com/flexharness": "4.1.1",
27
+ "@modelprofile.com/flexharness": "4.1.2",
28
28
  "@opencode-ai/sdk": "1.18.15",
29
- "@push.rocks/smartagent": "5.0.0",
29
+ "@push.rocks/smartagent": "5.0.1",
30
30
  "@push.rocks/smartai": "6.0.0",
31
31
  "@push.rocks/smartbrowser": "4.0.0",
32
32
  "@push.rocks/smartcli": "4.3.0",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: 'agl',
6
- version: '22.0.2',
6
+ version: '22.0.4',
7
7
  description: 'Agent Gateway Layer for OpenCode and FlexHarness sessions'
8
8
  }
@@ -2110,6 +2110,50 @@ export class SmartDataAuthStore implements IAuthStore {
2110
2110
  return toPublicSessionState(ControllerSessionStateModel.exact.toPersisted(stored));
2111
2111
  }
2112
2112
 
2113
+ public readFlexProjectTasks(
2114
+ projectIdArg: string,
2115
+ sessionIdArg: string,
2116
+ sessionGenerationArg: Readonly<TFlexSessionGeneration>,
2117
+ ): Promise<plugins.flexharness.IFlexProjectTask[]> {
2118
+ return this.runSessionStateMutation(async () => {
2119
+ assertFlexSessionGeneration(sessionGenerationArg);
2120
+ const stored = await this.findStoredSessionState(projectIdArg, {
2121
+ harnessId: 'flex',
2122
+ nativeId: sessionIdArg,
2123
+ });
2124
+ if (!stored) return [];
2125
+ const record = stored.flexProjectManagement;
2126
+ if (!record) return [];
2127
+ plugins.flexharness.assertFlexProjectManagementRecord(record);
2128
+ const storageKey = projectManagementStoreKey(projectIdArg, sessionIdArg);
2129
+ if (record.sessionGenerationId === sessionGenerationArg.sessionGenerationId) {
2130
+ if (record.sessionGenerationSequence !== sessionGenerationArg.sessionGenerationSequence) {
2131
+ throw new plugins.flexharness.FlexHarnessStoreConflictError(
2132
+ storageKey,
2133
+ 0,
2134
+ record.revision,
2135
+ );
2136
+ }
2137
+ if ('deletedAt' in record) {
2138
+ throw new plugins.flexharness.FlexHarnessNotFoundError(
2139
+ 'Project management state',
2140
+ sessionIdArg,
2141
+ );
2142
+ }
2143
+ return structuredClone(record.tasks);
2144
+ }
2145
+ if (
2146
+ 'deletedAt' in record
2147
+ && record.sessionGenerationSequence < sessionGenerationArg.sessionGenerationSequence
2148
+ ) return [];
2149
+ throw new plugins.flexharness.FlexHarnessStoreConflictError(
2150
+ storageKey,
2151
+ 0,
2152
+ record.revision,
2153
+ );
2154
+ });
2155
+ }
2156
+
2113
2157
  public loadFlexProjectManagement(
2114
2158
  projectIdArg: string,
2115
2159
  sessionIdArg: string,
@@ -28,6 +28,7 @@ import {
28
28
  type IControllerPendingPrompt,
29
29
  type IControllerReasoningUpdate,
30
30
  type IControllerTextUpdate,
31
+ type IControllerTodo,
31
32
  type TControllerModelChoice,
32
33
  type IControllerModelRefreshJob,
33
34
  type IControllerPermission,
@@ -8978,14 +8979,36 @@ export class OpenCodeController {
8978
8979
  messagePage: IControllerMessagePage;
8979
8980
  permissions: IControllerPermission[];
8980
8981
  questions: IControllerQuestion[];
8981
- todos: [];
8982
+ todos: IControllerTodo[];
8982
8983
  model?: string;
8983
8984
  effort?: string;
8984
8985
  }> {
8985
8986
  const reader = this.requireFlexProjectionReader();
8986
8987
  const supervisor = this.flexSupervisor;
8987
- const [session, messagePage, permissionResult] = await Promise.all([
8988
- reader.getSession(projectIdArg, sessionIdArg, signalArg),
8988
+ const sessionPromise = reader.getSession(projectIdArg, sessionIdArg, signalArg);
8989
+ const todosPromise: Promise<IControllerTodo[]> = sessionPromise.then(async (session) => {
8990
+ if (
8991
+ session.sessionGenerationId === undefined
8992
+ || session.sessionGenerationSequence === undefined
8993
+ ) return [];
8994
+ signalArg?.throwIfAborted();
8995
+ const tasks = await this.requireAuthStore().readFlexProjectTasks(
8996
+ projectIdArg,
8997
+ sessionIdArg,
8998
+ {
8999
+ sessionGenerationId: session.sessionGenerationId,
9000
+ sessionGenerationSequence: session.sessionGenerationSequence,
9001
+ },
9002
+ );
9003
+ signalArg?.throwIfAborted();
9004
+ return tasks.map((task) => ({
9005
+ id: flexRuntimeId(task.id),
9006
+ content: task.content,
9007
+ status: task.status,
9008
+ }));
9009
+ });
9010
+ const [session, messagePage, permissionResult, todos] = await Promise.all([
9011
+ sessionPromise,
8989
9012
  reader.listMessagePage(projectIdArg, sessionIdArg, {
8990
9013
  limit: controllerInitialMessageBundleLimit,
8991
9014
  }, signalArg),
@@ -8995,6 +9018,7 @@ export class OpenCodeController {
8995
9018
  familyRootSessionId: sessionIdArg,
8996
9019
  }, signalArg).catch(() => ({ permissions: [] as TFlexPermissionRequest[] }))
8997
9020
  : Promise.resolve({ permissions: [] as TFlexPermissionRequest[] }),
9021
+ todosPromise,
8998
9022
  ]);
8999
9023
  const bundles = messagePage.messages.map((message) => this.toFlexMessageBundle(message));
9000
9024
  const messages = bundles.flatMap((bundle) => bundle.messages);
@@ -9016,7 +9040,7 @@ export class OpenCodeController {
9016
9040
  }),
9017
9041
  permissions: permissionResult.permissions.map((permission) => this.toFlexPermission(permission)),
9018
9042
  questions: [],
9019
- todos: [],
9043
+ todos,
9020
9044
  ...(model === undefined ? {} : { model }),
9021
9045
  ...(effort === undefined ? {} : { effort }),
9022
9046
  };
@@ -117,12 +117,19 @@ interface IUnknownBudget {
117
117
  const isRecord = (value: unknown): value is Record<string, unknown> =>
118
118
  typeof value === 'object' && value !== null && !Array.isArray(value);
119
119
 
120
- const isOpenCodeNotFoundError = (valueArg: unknown): boolean =>
120
+ const isOpenCodeNotFoundBody = (valueArg: unknown): boolean =>
121
121
  isRecord(valueArg)
122
122
  && valueArg.name === 'NotFoundError'
123
123
  && isRecord(valueArg.data)
124
124
  && typeof valueArg.data.message === 'string';
125
125
 
126
+ const isOpenCodeNotFoundError = (valueArg: unknown): boolean => {
127
+ if (isOpenCodeNotFoundBody(valueArg)) return true;
128
+ if (!isRecord(valueArg) || !isRecord(valueArg.cause)) return false;
129
+ return valueArg.cause.status === 404
130
+ && isOpenCodeNotFoundBody(valueArg.cause.body);
131
+ };
132
+
126
133
  const hasExactKeys = (
127
134
  valueArg: Record<string, unknown>,
128
135
  requiredArg: readonly string[],
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: 'agl',
6
- version: '22.0.2',
6
+ version: '22.0.4',
7
7
  description: 'Agent Gateway Layer for OpenCode and FlexHarness sessions'
8
8
  }
@@ -4240,9 +4240,14 @@ export class HarnessControllerApp extends plugins.deesElement.DeesElement {
4240
4240
  const historyBecameTerminal = sameSession
4241
4241
  && this.detailHistoryCursor !== undefined
4242
4242
  && response.messagePage.nextCursor === undefined;
4243
+ const sessionBecameSettled = sameSession
4244
+ && (currentDetail!.session.status === 'busy' || currentDetail!.session.status === 'retry')
4245
+ && response.session.status !== 'busy'
4246
+ && response.session.status !== 'retry';
4243
4247
  const restartEnrichment = restartEnrichmentArg
4244
4248
  || coreBoundaryChanged
4245
4249
  || historyBecameTerminal
4250
+ || sessionBecameSettled
4246
4251
  || toolEpochAdvanced
4247
4252
  || messageEpochAdvanced;
4248
4253
  const nextCoreBundleKeySet = new Set(nextCoreBundleKeys);
@@ -11089,12 +11094,14 @@ export class HarnessControllerApp extends plugins.deesElement.DeesElement {
11089
11094
  .intelligenceBusy=${this.intelligenceAskIdsBySession.has(operationKey)
11090
11095
  || detailArg.intelligenceExchanges.some((exchange) => exchange.status === 'running')}
11091
11096
  .intelligenceError=${intelligenceError}
11092
- .todos=${isOpenCode ? detailArg.todos.map((todoArg) => ({
11097
+ .todos=${detailArg.todos.map((todoArg) => ({
11093
11098
  ...todoArg,
11094
11099
  ...(todoArg.id ? { id: controllerRuntimeIdToUiKey(todoArg.id) } : {}),
11095
- })) : []}
11100
+ }))}
11101
+ .todosAuthoritative=${true}
11096
11102
  .busy=${detailArg.session.status === 'busy' || detailArg.session.status === 'retry'}
11097
11103
  .queuedCount=${detailArg.pendingPrompts.length}
11104
+ .steeringEnabled=${false}
11098
11105
  .disabled=${this.detailLoading
11099
11106
  || this.mutationPending
11100
11107
  || this.sessionModelPending
@@ -11112,7 +11119,7 @@ export class HarnessControllerApp extends plugins.deesElement.DeesElement {
11112
11119
  .modelOptions=${this.modelOptionsForHarness(sessionId.harnessId, account)}
11113
11120
  .reasoningEffort=${this.resolveSessionEffortString(sessionId) || 'default'}
11114
11121
  .effortOptions=${this.resolveSessionEffortOptions(sessionId)}
11115
- .showTodosPanel=${isOpenCode}
11122
+ .showTodosPanel=${true}
11116
11123
  heading=${detailArg.session.title || `${sessionHarnessLabel(sessionId.harnessId)} session`}
11117
11124
  subheading=${readOnly
11118
11125
  ? `Flex unavailable · saved projection · read-only · ${runtimeIdDisplay(sessionId)}`