@semiont/backend 0.5.2 → 0.5.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/dist/index.js +327 -159
- package/dist/index.js.map +1 -1
- package/dist/openapi.json +280 -144
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import winston from 'winston';
|
|
|
3
3
|
import { recordSubscriberConnect, recordSubscriberDisconnect, withTraceparent, withSpan, recordBusEmit, SpanKind, injectTraceparent, getLogTraceContext } from '@semiont/observability';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import jwt from 'jsonwebtoken';
|
|
6
|
-
import { email, userId, googleCredential, EventBus, accessToken, resourceId, CHANNEL_SCHEMAS,
|
|
6
|
+
import { email, userId, googleCredential, agentToDid, EventBus, accessToken, userToDid, resourceId, CHANNEL_SCHEMAS, busLog, getPrimaryMediaType, decodeRepresentation } from '@semiont/core';
|
|
7
7
|
import { cors } from 'hono/cors';
|
|
8
8
|
import { serve } from '@hono/node-server';
|
|
9
9
|
import { Hono } from 'hono';
|
|
@@ -180,6 +180,12 @@ var init_jwt_types = __esm({
|
|
|
180
180
|
domain: z.string(),
|
|
181
181
|
provider: z.string(),
|
|
182
182
|
isAdmin: z.boolean(),
|
|
183
|
+
// For software-agent tokens: the agent's DID is asserted by the auth
|
|
184
|
+
// route (which knows the (inferenceProvider, model) the token is being
|
|
185
|
+
// issued for) and carried on the JWT. The bus uses this directly as
|
|
186
|
+
// `_userId` instead of recomputing `userToDid(user)`. Unset for human
|
|
187
|
+
// tokens.
|
|
188
|
+
agentDid: z.string().optional(),
|
|
183
189
|
iat: z.number().optional(),
|
|
184
190
|
exp: z.number().optional()
|
|
185
191
|
});
|
|
@@ -222,6 +228,18 @@ var init_jwt = __esm({
|
|
|
222
228
|
}
|
|
223
229
|
return this.siteConfig;
|
|
224
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Get the deployment domain to use for issuing agent identities.
|
|
233
|
+
* Used by `/api/tokens/agent` to mint DIDs of the shape
|
|
234
|
+
* `did:web:<domain>:agents:<provider>:<model>`.
|
|
235
|
+
*/
|
|
236
|
+
static getDomainForAgent() {
|
|
237
|
+
const config2 = this.getSiteConfig();
|
|
238
|
+
if (!config2.domain) {
|
|
239
|
+
throw new Error("site.domain is required to issue agent tokens");
|
|
240
|
+
}
|
|
241
|
+
return config2.domain;
|
|
242
|
+
}
|
|
225
243
|
/**
|
|
226
244
|
* Override configuration for testing purposes
|
|
227
245
|
* @param config The configuration to use
|
|
@@ -10538,48 +10556,103 @@ var openapi_default = {
|
|
|
10538
10556
|
]
|
|
10539
10557
|
},
|
|
10540
10558
|
Agent: {
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
10548
|
-
|
|
10549
|
-
|
|
10550
|
-
|
|
10551
|
-
|
|
10552
|
-
|
|
10553
|
-
|
|
10559
|
+
description: "Web Annotation / W3C PROV Agent. Discriminated by @type \u2014 Person, Organization, or Software. Each branch carries fields appropriate to its kind. Software peers are first-class participants, not a sub-class of Person.",
|
|
10560
|
+
oneOf: [
|
|
10561
|
+
{
|
|
10562
|
+
type: "object",
|
|
10563
|
+
additionalProperties: true,
|
|
10564
|
+
properties: {
|
|
10565
|
+
"@type": {
|
|
10566
|
+
type: "string",
|
|
10567
|
+
const: "Person"
|
|
10568
|
+
},
|
|
10569
|
+
"@id": {
|
|
10570
|
+
type: "string",
|
|
10571
|
+
format: "uri",
|
|
10572
|
+
description: "DID-shaped identifier (e.g. did:web:host:users:email%40host)"
|
|
10573
|
+
},
|
|
10574
|
+
name: {
|
|
10575
|
+
type: "string",
|
|
10576
|
+
description: "Display name"
|
|
10577
|
+
},
|
|
10578
|
+
nickname: {
|
|
10554
10579
|
type: "string"
|
|
10555
10580
|
},
|
|
10556
|
-
{
|
|
10557
|
-
type: "
|
|
10558
|
-
|
|
10559
|
-
|
|
10560
|
-
|
|
10561
|
-
|
|
10581
|
+
email: {
|
|
10582
|
+
type: "string"
|
|
10583
|
+
},
|
|
10584
|
+
email_sha1: {
|
|
10585
|
+
type: "string"
|
|
10586
|
+
},
|
|
10587
|
+
homepage: {
|
|
10588
|
+
type: "string"
|
|
10562
10589
|
}
|
|
10590
|
+
},
|
|
10591
|
+
required: [
|
|
10592
|
+
"@type",
|
|
10593
|
+
"name"
|
|
10563
10594
|
]
|
|
10564
10595
|
},
|
|
10565
|
-
|
|
10566
|
-
type: "
|
|
10567
|
-
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
|
|
10574
|
-
|
|
10575
|
-
|
|
10596
|
+
{
|
|
10597
|
+
type: "object",
|
|
10598
|
+
additionalProperties: true,
|
|
10599
|
+
properties: {
|
|
10600
|
+
"@type": {
|
|
10601
|
+
type: "string",
|
|
10602
|
+
const: "Organization"
|
|
10603
|
+
},
|
|
10604
|
+
"@id": {
|
|
10605
|
+
type: "string",
|
|
10606
|
+
format: "uri"
|
|
10607
|
+
},
|
|
10608
|
+
name: {
|
|
10609
|
+
type: "string"
|
|
10610
|
+
},
|
|
10611
|
+
homepage: {
|
|
10612
|
+
type: "string"
|
|
10613
|
+
}
|
|
10614
|
+
},
|
|
10615
|
+
required: [
|
|
10616
|
+
"@type",
|
|
10617
|
+
"name"
|
|
10618
|
+
]
|
|
10576
10619
|
},
|
|
10577
|
-
|
|
10578
|
-
type: "
|
|
10620
|
+
{
|
|
10621
|
+
type: "object",
|
|
10622
|
+
additionalProperties: true,
|
|
10623
|
+
properties: {
|
|
10624
|
+
"@type": {
|
|
10625
|
+
type: "string",
|
|
10626
|
+
const: "Software"
|
|
10627
|
+
},
|
|
10628
|
+
"@id": {
|
|
10629
|
+
type: "string",
|
|
10630
|
+
format: "uri",
|
|
10631
|
+
description: "DID-shaped identifier (e.g. did:web:host:agents:provider:model)"
|
|
10632
|
+
},
|
|
10633
|
+
name: {
|
|
10634
|
+
type: "string",
|
|
10635
|
+
description: "Stable human-friendly label. Not parsed; UI composes display from structured fields."
|
|
10636
|
+
},
|
|
10637
|
+
provider: {
|
|
10638
|
+
type: "string",
|
|
10639
|
+
description: "Inference provider (e.g. ollama, anthropic)"
|
|
10640
|
+
},
|
|
10641
|
+
model: {
|
|
10642
|
+
type: "string",
|
|
10643
|
+
description: "Model identifier (e.g. gemma2:27b, claude-3-5-sonnet)"
|
|
10644
|
+
},
|
|
10645
|
+
parameters: {
|
|
10646
|
+
type: "object",
|
|
10647
|
+
additionalProperties: true,
|
|
10648
|
+
description: "Inference parameters (temperature, maxTokens, systemPrompt, etc.). Runtime metadata, not part of identity."
|
|
10649
|
+
}
|
|
10650
|
+
},
|
|
10651
|
+
required: [
|
|
10652
|
+
"@type",
|
|
10653
|
+
"name"
|
|
10654
|
+
]
|
|
10579
10655
|
}
|
|
10580
|
-
},
|
|
10581
|
-
required: [
|
|
10582
|
-
"name"
|
|
10583
10656
|
]
|
|
10584
10657
|
},
|
|
10585
10658
|
Annotation: {
|
|
@@ -10637,7 +10710,8 @@ var openapi_default = {
|
|
|
10637
10710
|
description: "W3C Web Annotation body. Optional per the W3C spec \u2014 annotations whose motivation alone is meaningful (highlighting) legitimately omit it. Present values are either a single body or a non-empty array of bodies; the prior empty-array 'stub' branch has been removed (it was a naming lie shared between highlights and never-actually-emitted stub references, and the source of the #651 reference-annotation validator bug)."
|
|
10638
10711
|
},
|
|
10639
10712
|
creator: {
|
|
10640
|
-
$ref: "#/components/schemas/Agent"
|
|
10713
|
+
$ref: "#/components/schemas/Agent",
|
|
10714
|
+
description: "Web Annotation creator \u2014 the entity that initiated the annotation. For human-driven work this is a Person; for autonomous-agent work this is a Software peer."
|
|
10641
10715
|
},
|
|
10642
10716
|
created: {
|
|
10643
10717
|
type: "string"
|
|
@@ -10646,7 +10720,34 @@ var openapi_default = {
|
|
|
10646
10720
|
type: "string"
|
|
10647
10721
|
},
|
|
10648
10722
|
generator: {
|
|
10649
|
-
|
|
10723
|
+
oneOf: [
|
|
10724
|
+
{
|
|
10725
|
+
$ref: "#/components/schemas/Agent"
|
|
10726
|
+
},
|
|
10727
|
+
{
|
|
10728
|
+
type: "array",
|
|
10729
|
+
items: {
|
|
10730
|
+
$ref: "#/components/schemas/Agent"
|
|
10731
|
+
},
|
|
10732
|
+
minItems: 1
|
|
10733
|
+
}
|
|
10734
|
+
],
|
|
10735
|
+
description: "Web Annotation generator \u2014 the SoftwareAgent that produced the annotation, when software was involved. Absent for purely manual annotations. Single object is the common case; array supports pipelines that combine multiple software peers."
|
|
10736
|
+
},
|
|
10737
|
+
wasAttributedTo: {
|
|
10738
|
+
oneOf: [
|
|
10739
|
+
{
|
|
10740
|
+
$ref: "#/components/schemas/Agent"
|
|
10741
|
+
},
|
|
10742
|
+
{
|
|
10743
|
+
type: "array",
|
|
10744
|
+
items: {
|
|
10745
|
+
$ref: "#/components/schemas/Agent"
|
|
10746
|
+
},
|
|
10747
|
+
minItems: 1
|
|
10748
|
+
}
|
|
10749
|
+
],
|
|
10750
|
+
description: "PROV-O wasAttributedTo \u2014 all parties responsible for this annotation. For human-prompted AI work this combines `creator` (the Person) and `generator` (the Software). For purely manual annotations it equals `[creator]`; for autonomous-agent work it equals `[generator]` (and `creator` may be the same Software)."
|
|
10650
10751
|
}
|
|
10651
10752
|
},
|
|
10652
10753
|
required: [
|
|
@@ -11731,18 +11832,6 @@ var openapi_default = {
|
|
|
11731
11832
|
contentByteSize: {
|
|
11732
11833
|
type: "integer"
|
|
11733
11834
|
},
|
|
11734
|
-
creationMethod: {
|
|
11735
|
-
type: "string",
|
|
11736
|
-
enum: [
|
|
11737
|
-
"api",
|
|
11738
|
-
"upload",
|
|
11739
|
-
"ui",
|
|
11740
|
-
"reference",
|
|
11741
|
-
"cli",
|
|
11742
|
-
"clone",
|
|
11743
|
-
"generated"
|
|
11744
|
-
]
|
|
11745
|
-
},
|
|
11746
11835
|
entityTypes: {
|
|
11747
11836
|
type: "array",
|
|
11748
11837
|
items: {
|
|
@@ -11794,8 +11883,7 @@ var openapi_default = {
|
|
|
11794
11883
|
required: [
|
|
11795
11884
|
"name",
|
|
11796
11885
|
"format",
|
|
11797
|
-
"contentChecksum"
|
|
11798
|
-
"creationMethod"
|
|
11886
|
+
"contentChecksum"
|
|
11799
11887
|
]
|
|
11800
11888
|
},
|
|
11801
11889
|
ResourceClonedPayload: {
|
|
@@ -11817,18 +11905,6 @@ var openapi_default = {
|
|
|
11817
11905
|
parentResourceId: {
|
|
11818
11906
|
type: "string"
|
|
11819
11907
|
},
|
|
11820
|
-
creationMethod: {
|
|
11821
|
-
type: "string",
|
|
11822
|
-
enum: [
|
|
11823
|
-
"api",
|
|
11824
|
-
"upload",
|
|
11825
|
-
"ui",
|
|
11826
|
-
"reference",
|
|
11827
|
-
"cli",
|
|
11828
|
-
"clone",
|
|
11829
|
-
"generated"
|
|
11830
|
-
]
|
|
11831
|
-
},
|
|
11832
11908
|
entityTypes: {
|
|
11833
11909
|
type: "array",
|
|
11834
11910
|
items: {
|
|
@@ -11843,8 +11919,7 @@ var openapi_default = {
|
|
|
11843
11919
|
"name",
|
|
11844
11920
|
"format",
|
|
11845
11921
|
"contentChecksum",
|
|
11846
|
-
"parentResourceId"
|
|
11847
|
-
"creationMethod"
|
|
11922
|
+
"parentResourceId"
|
|
11848
11923
|
]
|
|
11849
11924
|
},
|
|
11850
11925
|
ResourceUpdatedPayload: {
|
|
@@ -11988,6 +12063,18 @@ var openapi_default = {
|
|
|
11988
12063
|
"entityType"
|
|
11989
12064
|
]
|
|
11990
12065
|
},
|
|
12066
|
+
TagSchemaAddedPayload: {
|
|
12067
|
+
type: "object",
|
|
12068
|
+
description: "Payload for frame:tag-schema-added domain event (system-level, no resourceId \u2014 fan-out is global to the KB).",
|
|
12069
|
+
properties: {
|
|
12070
|
+
schema: {
|
|
12071
|
+
$ref: "#/components/schemas/TagSchema"
|
|
12072
|
+
}
|
|
12073
|
+
},
|
|
12074
|
+
required: [
|
|
12075
|
+
"schema"
|
|
12076
|
+
]
|
|
12077
|
+
},
|
|
11991
12078
|
EntityTagChangedPayload: {
|
|
11992
12079
|
type: "object",
|
|
11993
12080
|
description: "Payload for mark:entity-tag-added and mark:entity-tag-removed domain events",
|
|
@@ -12398,6 +12485,20 @@ var openapi_default = {
|
|
|
12398
12485
|
"entityReferences"
|
|
12399
12486
|
]
|
|
12400
12487
|
},
|
|
12488
|
+
GetTagSchemasResponse: {
|
|
12489
|
+
type: "object",
|
|
12490
|
+
properties: {
|
|
12491
|
+
tagSchemas: {
|
|
12492
|
+
type: "array",
|
|
12493
|
+
items: {
|
|
12494
|
+
$ref: "#/components/schemas/TagSchema"
|
|
12495
|
+
}
|
|
12496
|
+
}
|
|
12497
|
+
},
|
|
12498
|
+
required: [
|
|
12499
|
+
"tagSchemas"
|
|
12500
|
+
]
|
|
12501
|
+
},
|
|
12401
12502
|
GoogleAuthRequest: {
|
|
12402
12503
|
type: "object",
|
|
12403
12504
|
properties: {
|
|
@@ -12958,19 +13059,6 @@ var openapi_default = {
|
|
|
12958
13059
|
type: "boolean",
|
|
12959
13060
|
description: "Application-specific: Whether this resource is a draft"
|
|
12960
13061
|
},
|
|
12961
|
-
creationMethod: {
|
|
12962
|
-
type: "string",
|
|
12963
|
-
enum: [
|
|
12964
|
-
"api",
|
|
12965
|
-
"upload",
|
|
12966
|
-
"ui",
|
|
12967
|
-
"reference",
|
|
12968
|
-
"cli",
|
|
12969
|
-
"clone",
|
|
12970
|
-
"generated"
|
|
12971
|
-
],
|
|
12972
|
-
description: "Application-specific: How this resource was created"
|
|
12973
|
-
},
|
|
12974
13062
|
sourceAnnotationId: {
|
|
12975
13063
|
type: "string",
|
|
12976
13064
|
description: "Application-specific: ID of annotation that triggered generation"
|
|
@@ -14162,6 +14250,34 @@ var openapi_default = {
|
|
|
14162
14250
|
"path"
|
|
14163
14251
|
]
|
|
14164
14252
|
},
|
|
14253
|
+
BrowseTagSchemasRequest: {
|
|
14254
|
+
type: "object",
|
|
14255
|
+
description: "Request to browse registered tag schemas",
|
|
14256
|
+
properties: {
|
|
14257
|
+
correlationId: {
|
|
14258
|
+
type: "string"
|
|
14259
|
+
}
|
|
14260
|
+
},
|
|
14261
|
+
required: [
|
|
14262
|
+
"correlationId"
|
|
14263
|
+
]
|
|
14264
|
+
},
|
|
14265
|
+
BrowseTagSchemasResult: {
|
|
14266
|
+
type: "object",
|
|
14267
|
+
description: "Result of browsing tag schemas",
|
|
14268
|
+
properties: {
|
|
14269
|
+
correlationId: {
|
|
14270
|
+
type: "string"
|
|
14271
|
+
},
|
|
14272
|
+
response: {
|
|
14273
|
+
$ref: "#/components/schemas/GetTagSchemasResponse"
|
|
14274
|
+
}
|
|
14275
|
+
},
|
|
14276
|
+
required: [
|
|
14277
|
+
"correlationId",
|
|
14278
|
+
"response"
|
|
14279
|
+
]
|
|
14280
|
+
},
|
|
14165
14281
|
FragmentSelector: {
|
|
14166
14282
|
type: "object",
|
|
14167
14283
|
description: "W3C Web Annotation FragmentSelector for media fragment identifiers (RFC 3778 for PDFs)",
|
|
@@ -15022,6 +15138,22 @@ var openapi_default = {
|
|
|
15022
15138
|
"tag"
|
|
15023
15139
|
]
|
|
15024
15140
|
},
|
|
15141
|
+
FrameAddTagSchemaCommand: {
|
|
15142
|
+
type: "object",
|
|
15143
|
+
description: "Bus command to register a tag schema with the KB's runtime registry. Carried on the `frame:add-tag-schema` channel \u2014 Frame is the schema-layer flow that owns vocabulary writes. Most-recent registration of a given `schema.id` wins; the projection reflects the latest content. Identical re-registrations are silent; differing content overwrites and logs a warning.",
|
|
15144
|
+
properties: {
|
|
15145
|
+
schema: {
|
|
15146
|
+
$ref: "#/components/schemas/TagSchema"
|
|
15147
|
+
},
|
|
15148
|
+
_userId: {
|
|
15149
|
+
type: "string",
|
|
15150
|
+
description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
|
|
15151
|
+
}
|
|
15152
|
+
},
|
|
15153
|
+
required: [
|
|
15154
|
+
"schema"
|
|
15155
|
+
]
|
|
15156
|
+
},
|
|
15025
15157
|
MarkArchiveCommand: {
|
|
15026
15158
|
type: "object",
|
|
15027
15159
|
description: "Bus command to archive a resource and optionally remove its file.",
|
|
@@ -15558,6 +15690,61 @@ var openapi_default = {
|
|
|
15558
15690
|
"value"
|
|
15559
15691
|
]
|
|
15560
15692
|
},
|
|
15693
|
+
TagCategory: {
|
|
15694
|
+
type: "object",
|
|
15695
|
+
description: "A single category within a tag schema (e.g. 'Issue' in IRAC, 'distinguished' in legal-citation-treatment). Each category carries methodology-bound semantics: a name, a description, and examples used in the LLM prompt.",
|
|
15696
|
+
properties: {
|
|
15697
|
+
name: {
|
|
15698
|
+
type: "string"
|
|
15699
|
+
},
|
|
15700
|
+
description: {
|
|
15701
|
+
type: "string"
|
|
15702
|
+
},
|
|
15703
|
+
examples: {
|
|
15704
|
+
type: "array",
|
|
15705
|
+
items: {
|
|
15706
|
+
type: "string"
|
|
15707
|
+
}
|
|
15708
|
+
}
|
|
15709
|
+
},
|
|
15710
|
+
required: [
|
|
15711
|
+
"name",
|
|
15712
|
+
"description",
|
|
15713
|
+
"examples"
|
|
15714
|
+
]
|
|
15715
|
+
},
|
|
15716
|
+
TagSchema: {
|
|
15717
|
+
type: "object",
|
|
15718
|
+
description: "A structural-analysis schema (e.g. legal-irac, scientific-imrad, argument-toulmin). Defines a methodology framework as an id, name, description, domain hint, and an ordered list of categories. KBs and their skills register schemas with the runtime registry via `frame.addTagSchema(...)` at session start.",
|
|
15719
|
+
properties: {
|
|
15720
|
+
id: {
|
|
15721
|
+
type: "string"
|
|
15722
|
+
},
|
|
15723
|
+
name: {
|
|
15724
|
+
type: "string"
|
|
15725
|
+
},
|
|
15726
|
+
description: {
|
|
15727
|
+
type: "string"
|
|
15728
|
+
},
|
|
15729
|
+
domain: {
|
|
15730
|
+
type: "string",
|
|
15731
|
+
description: "Free-form domain hint (e.g. 'legal', 'scientific', 'general'). Used in the LLM prompt to tune the model's analysis voice. KB authors choose."
|
|
15732
|
+
},
|
|
15733
|
+
tags: {
|
|
15734
|
+
type: "array",
|
|
15735
|
+
items: {
|
|
15736
|
+
$ref: "#/components/schemas/TagCategory"
|
|
15737
|
+
}
|
|
15738
|
+
}
|
|
15739
|
+
},
|
|
15740
|
+
required: [
|
|
15741
|
+
"id",
|
|
15742
|
+
"name",
|
|
15743
|
+
"description",
|
|
15744
|
+
"domain",
|
|
15745
|
+
"tags"
|
|
15746
|
+
]
|
|
15747
|
+
},
|
|
15561
15748
|
YieldCloneCreateCommand: {
|
|
15562
15749
|
type: "object",
|
|
15563
15750
|
description: "Bus command to create a cloned resource from a clone token.",
|
|
@@ -15674,9 +15861,6 @@ var openapi_default = {
|
|
|
15674
15861
|
type: "string"
|
|
15675
15862
|
}
|
|
15676
15863
|
},
|
|
15677
|
-
creationMethod: {
|
|
15678
|
-
type: "string"
|
|
15679
|
-
},
|
|
15680
15864
|
isDraft: {
|
|
15681
15865
|
type: "boolean"
|
|
15682
15866
|
},
|
|
@@ -15770,57 +15954,6 @@ var openapi_default = {
|
|
|
15770
15954
|
"toUri"
|
|
15771
15955
|
]
|
|
15772
15956
|
},
|
|
15773
|
-
YieldRequestCommand: {
|
|
15774
|
-
type: "object",
|
|
15775
|
-
description: "Bus command to request yield (generation) of a new resource from an annotation.",
|
|
15776
|
-
properties: {
|
|
15777
|
-
correlationId: {
|
|
15778
|
-
type: "string",
|
|
15779
|
-
description: "Client-supplied id used to match this command to its result event(s) on the events-stream. Generated by the route handler if absent."
|
|
15780
|
-
},
|
|
15781
|
-
annotationId: {
|
|
15782
|
-
type: "string"
|
|
15783
|
-
},
|
|
15784
|
-
resourceId: {
|
|
15785
|
-
type: "string"
|
|
15786
|
-
},
|
|
15787
|
-
options: {
|
|
15788
|
-
type: "object",
|
|
15789
|
-
properties: {
|
|
15790
|
-
title: {
|
|
15791
|
-
type: "string"
|
|
15792
|
-
},
|
|
15793
|
-
prompt: {
|
|
15794
|
-
type: "string"
|
|
15795
|
-
},
|
|
15796
|
-
language: {
|
|
15797
|
-
type: "string"
|
|
15798
|
-
},
|
|
15799
|
-
temperature: {
|
|
15800
|
-
type: "number"
|
|
15801
|
-
},
|
|
15802
|
-
maxTokens: {
|
|
15803
|
-
type: "integer"
|
|
15804
|
-
},
|
|
15805
|
-
context: {
|
|
15806
|
-
$ref: "#/components/schemas/GatheredContext"
|
|
15807
|
-
},
|
|
15808
|
-
storageUri: {
|
|
15809
|
-
type: "string"
|
|
15810
|
-
}
|
|
15811
|
-
},
|
|
15812
|
-
required: [
|
|
15813
|
-
"title",
|
|
15814
|
-
"storageUri"
|
|
15815
|
-
]
|
|
15816
|
-
}
|
|
15817
|
-
},
|
|
15818
|
-
required: [
|
|
15819
|
-
"annotationId",
|
|
15820
|
-
"resourceId",
|
|
15821
|
-
"options"
|
|
15822
|
-
]
|
|
15823
|
-
},
|
|
15824
15957
|
YieldUpdateCommand: {
|
|
15825
15958
|
type: "object",
|
|
15826
15959
|
description: "Bus command to update a yielded resource's storage content.",
|
|
@@ -16066,7 +16199,15 @@ var OAuthService = class {
|
|
|
16066
16199
|
const refreshToken = JWTService.generateToken(jwtPayload, "30d");
|
|
16067
16200
|
return { user, token, refreshToken, isNewUser };
|
|
16068
16201
|
}
|
|
16069
|
-
|
|
16202
|
+
/**
|
|
16203
|
+
* Resolve a JWT to its authenticated principal — the User row plus the
|
|
16204
|
+
* principal's DID when the token was issued for a software agent. The
|
|
16205
|
+
* `agentDid` is set by `/api/tokens/agent` and is the read-side
|
|
16206
|
+
* inverse of "who is this token *acting as*?" — bus middleware uses it
|
|
16207
|
+
* directly so emits attribute to the agent rather than the synthetic
|
|
16208
|
+
* service-account User backing the token.
|
|
16209
|
+
*/
|
|
16210
|
+
static async getPrincipalFromToken(token) {
|
|
16070
16211
|
const payload = JWTService.verifyToken(token);
|
|
16071
16212
|
if (!payload.userId) {
|
|
16072
16213
|
throw new Error("Invalid token: missing userId");
|
|
@@ -16078,7 +16219,7 @@ var OAuthService = class {
|
|
|
16078
16219
|
if (!user || !user.isActive) {
|
|
16079
16220
|
throw new Error("User not found or inactive");
|
|
16080
16221
|
}
|
|
16081
|
-
return user;
|
|
16222
|
+
return payload.agentDid ? { user, agentDid: payload.agentDid } : { user };
|
|
16082
16223
|
}
|
|
16083
16224
|
static async acceptTerms(userId2) {
|
|
16084
16225
|
const prisma2 = DatabaseConnection.getClient();
|
|
@@ -16135,9 +16276,10 @@ var authMiddleware = async (c, next) => {
|
|
|
16135
16276
|
return c.json({ error: "Unauthorized" }, 401);
|
|
16136
16277
|
}
|
|
16137
16278
|
try {
|
|
16138
|
-
const user = await OAuthService.
|
|
16279
|
+
const { user, agentDid } = await OAuthService.getPrincipalFromToken(accessToken(tokenStr));
|
|
16139
16280
|
c.set("user", user);
|
|
16140
16281
|
c.set("token", tokenStr);
|
|
16282
|
+
c.set("principalDid", agentDid ?? userToDid(user));
|
|
16141
16283
|
logger2.debug("Authentication successful", {
|
|
16142
16284
|
type: "auth_success",
|
|
16143
16285
|
userId: user.id,
|
|
@@ -16522,10 +16664,10 @@ authRouter.post("/api/tokens/mcp-generate", authMiddleware, async (c) => {
|
|
|
16522
16664
|
return c.json({ error: "Failed to generate refresh token" }, 401);
|
|
16523
16665
|
}
|
|
16524
16666
|
});
|
|
16525
|
-
authRouter.post("/api/tokens/
|
|
16667
|
+
authRouter.post("/api/tokens/agent", async (c) => {
|
|
16526
16668
|
const workerSecret = process.env.SEMIONT_WORKER_SECRET;
|
|
16527
16669
|
if (!workerSecret) {
|
|
16528
|
-
return c.json({ error: "
|
|
16670
|
+
return c.json({ error: "Agent authentication not configured" }, 503);
|
|
16529
16671
|
}
|
|
16530
16672
|
let body;
|
|
16531
16673
|
try {
|
|
@@ -16534,24 +16676,51 @@ authRouter.post("/api/tokens/worker", async (c) => {
|
|
|
16534
16676
|
return c.json({ error: "Invalid request body" }, 400);
|
|
16535
16677
|
}
|
|
16536
16678
|
if (body.secret !== workerSecret) {
|
|
16537
|
-
return c.json({ error: "Invalid
|
|
16538
|
-
}
|
|
16679
|
+
return c.json({ error: "Invalid agent secret" }, 401);
|
|
16680
|
+
}
|
|
16681
|
+
if (!body.provider || typeof body.provider !== "string") {
|
|
16682
|
+
return c.json({ error: "provider is required" }, 400);
|
|
16683
|
+
}
|
|
16684
|
+
if (!body.model || typeof body.model !== "string") {
|
|
16685
|
+
return c.json({ error: "model is required" }, 400);
|
|
16686
|
+
}
|
|
16687
|
+
const inferenceProvider = body.provider;
|
|
16688
|
+
const model = body.model;
|
|
16689
|
+
const siteDomain = JWTService.getDomainForAgent();
|
|
16690
|
+
const emailHost = siteDomain.split(":")[0];
|
|
16691
|
+
const providerId = `${inferenceProvider}:${model}`;
|
|
16692
|
+
const slug = providerId.replace(/[^a-zA-Z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
16693
|
+
const agentEmail = `${slug}@agents.${emailHost}`;
|
|
16694
|
+
const agentName = `${inferenceProvider} ${model}`;
|
|
16539
16695
|
const prisma2 = DatabaseConnection.getClient();
|
|
16540
|
-
const
|
|
16541
|
-
where: {
|
|
16696
|
+
const agentUser = await prisma2.user.upsert({
|
|
16697
|
+
where: { provider_providerId: { provider: "agent", providerId } },
|
|
16698
|
+
update: {
|
|
16699
|
+
name: agentName,
|
|
16700
|
+
isActive: true,
|
|
16701
|
+
lastLogin: /* @__PURE__ */ new Date()
|
|
16702
|
+
},
|
|
16703
|
+
create: {
|
|
16704
|
+
email: agentEmail,
|
|
16705
|
+
name: agentName,
|
|
16706
|
+
provider: "agent",
|
|
16707
|
+
providerId,
|
|
16708
|
+
domain: siteDomain,
|
|
16709
|
+
isActive: true,
|
|
16710
|
+
isAdmin: false
|
|
16711
|
+
}
|
|
16542
16712
|
});
|
|
16543
|
-
|
|
16544
|
-
return c.json({ error: "Worker user not found \u2014 run: semiont useradd --email worker@semiont.local --generate-password --upsert" }, 503);
|
|
16545
|
-
}
|
|
16713
|
+
const did = agentToDid({ domain: siteDomain, provider: inferenceProvider, model });
|
|
16546
16714
|
const token = JWTService.generateToken({
|
|
16547
|
-
userId: userId(
|
|
16548
|
-
email: email(
|
|
16549
|
-
name:
|
|
16550
|
-
domain:
|
|
16551
|
-
provider:
|
|
16552
|
-
isAdmin: false
|
|
16715
|
+
userId: userId(agentUser.id),
|
|
16716
|
+
email: email(agentUser.email),
|
|
16717
|
+
name: agentUser.name ?? agentName,
|
|
16718
|
+
domain: agentUser.domain,
|
|
16719
|
+
provider: agentUser.provider,
|
|
16720
|
+
isAdmin: false,
|
|
16721
|
+
agentDid: did
|
|
16553
16722
|
}, "24h");
|
|
16554
|
-
return c.json({ token }, 200);
|
|
16723
|
+
return c.json({ token, did }, 200);
|
|
16555
16724
|
});
|
|
16556
16725
|
authRouter.post("/api/tokens/media", authMiddleware, async (c) => {
|
|
16557
16726
|
const user = c.get("user");
|
|
@@ -17135,7 +17304,8 @@ function deriveStorageUri(name, format) {
|
|
|
17135
17304
|
function registerCreateResource(router) {
|
|
17136
17305
|
router.post("/resources", async (c) => {
|
|
17137
17306
|
const user = c.get("user");
|
|
17138
|
-
|
|
17307
|
+
const principalDid = c.get("principalDid");
|
|
17308
|
+
if (!user || !principalDid) {
|
|
17139
17309
|
throw new HTTPException(401, { message: "Authentication required" });
|
|
17140
17310
|
}
|
|
17141
17311
|
const formData = await c.req.formData();
|
|
@@ -17144,7 +17314,6 @@ function registerCreateResource(router) {
|
|
|
17144
17314
|
const formatRaw = formData.get("format");
|
|
17145
17315
|
const language = formData.get("language");
|
|
17146
17316
|
const entityTypesStr = formData.get("entityTypes");
|
|
17147
|
-
const creationMethod = formData.get("creationMethod");
|
|
17148
17317
|
const storageUri = formData.get("storageUri");
|
|
17149
17318
|
const sourceAnnotationId = formData.get("sourceAnnotationId");
|
|
17150
17319
|
const sourceResourceId = formData.get("sourceResourceId");
|
|
@@ -17192,13 +17361,12 @@ function registerCreateResource(router) {
|
|
|
17192
17361
|
format,
|
|
17193
17362
|
language: language || void 0,
|
|
17194
17363
|
entityTypes,
|
|
17195
|
-
creationMethod: creationMethod || void 0,
|
|
17196
17364
|
generatedFrom,
|
|
17197
17365
|
generationPrompt: generationPrompt || void 0,
|
|
17198
17366
|
generator,
|
|
17199
17367
|
isDraft: isDraftStr ? isDraftStr === "true" : void 0
|
|
17200
17368
|
},
|
|
17201
|
-
userId(
|
|
17369
|
+
userId(principalDid),
|
|
17202
17370
|
eventBus2
|
|
17203
17371
|
);
|
|
17204
17372
|
},
|
|
@@ -17537,9 +17705,9 @@ function createBusRouter(authMiddleware2) {
|
|
|
17537
17705
|
throw new HTTPException(400, { message: `Invalid payload for ${channel}: ${errorMessage}` });
|
|
17538
17706
|
}
|
|
17539
17707
|
}
|
|
17540
|
-
const
|
|
17541
|
-
if (
|
|
17542
|
-
payload._userId =
|
|
17708
|
+
const principalDid = c.get("principalDid");
|
|
17709
|
+
if (principalDid) {
|
|
17710
|
+
payload._userId = principalDid;
|
|
17543
17711
|
}
|
|
17544
17712
|
const traceparent = c.req.header("traceparent");
|
|
17545
17713
|
const tracestate = c.req.header("tracestate");
|