@naanlang/naan 1.3.1 → 1.4.0

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 (44) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +3 -3
  3. package/bin/index.js +2 -2
  4. package/dist/naan.min.js +4 -4
  5. package/frameworks/browser/sworker.js +23 -23
  6. package/frameworks/browser/terminals.nlg +26 -11
  7. package/frameworks/browser/workers.nlg +3 -0
  8. package/frameworks/browser/ws_client.nlg +1 -1
  9. package/frameworks/client/psm_client.nlg +1 -1
  10. package/frameworks/client/relaycon.nlg +2 -1
  11. package/frameworks/common/common.nlg +6 -10
  12. package/frameworks/common/preferences.nlg +1 -1
  13. package/frameworks/node/apiserver.nlg +3 -3
  14. package/frameworks/node/https_request.nlg +97 -12
  15. package/frameworks/node/node.nlg +1 -0
  16. package/frameworks/node/worker.nlg +103 -45
  17. package/frameworks/project/build.nlg +12 -7
  18. package/frameworks/project/jszip.js +0 -0
  19. package/frameworks/project/projects.nlg +7 -3
  20. package/frameworks/running/executors.nlg +64 -28
  21. package/frameworks/running/running.nlg +85 -3
  22. package/frameworks/running/taskexec.nlg +24 -4
  23. package/frameworks/storage/dbt_pouch.nlg +1 -1
  24. package/frameworks/storage/psm.nlg +11 -1
  25. package/lib/browser/env_web.js +6 -6
  26. package/lib/browser/env_webworker.js +2 -0
  27. package/lib/core/naanlib.js +4 -4
  28. package/lib/env_nodeworker.js +2 -0
  29. package/package.json +1 -1
  30. package/plugins/gitClient/gitutils.nlg +2 -2
  31. package/plugins/nodeLib/node_https.nlg +2 -2
  32. package/plugins/serviceAws/dbt_aws.nlg +3 -0
  33. package/plugins/serviceAws/lambda_naan_control.nlg +3 -3
  34. package/plugins/serviceGC/gc_api.nlg +263 -0
  35. package/plugins/serviceGC/russian_trusted_root_ca_pem.crt +33 -0
  36. package/plugins/serviceGC/serviceGC.nlg +31 -0
  37. package/plugins/serviceGitHub/gitops.nlg +4 -3
  38. package/plugins/serviceGitHub/psm_github.nlg +1 -1
  39. package/plugins/serviceGitLab/gitops.nlg +2 -1
  40. package/plugins/serviceGitLab/psm_gitlab.nlg +1 -1
  41. package/plugins/serviceYC/yc_speechrec.nlg +138 -0
  42. package/plugins/serviceYC/yc_vm.nlg +1 -1
  43. package/test/test_02_context.nlg +1 -1
  44. package/test/test_07_lingo.nlg +3 -3
@@ -164,6 +164,8 @@ exports.NaanWorkerActivate = function NaanWorkerActivate(cbReady) {
164
164
  naanlib.textLine(msg.text); // keyboard text from terminal
165
165
  else if (msg.id == "start")
166
166
  { // start execution with optional state
167
+ workSelf.workerID = msg.workerID;
168
+ workSelf.workerGUID = msg.workerGUID;
167
169
  if (typeof(__dirname) !== "undefined")
168
170
  naanlib.js.h = naanlib.js.d; // set host directory path
169
171
  if (msg.dirpath)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naanlang/naan",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "author": "Richard C. Zulch",
5
5
  "description": "Naan™ software platform",
6
6
  "main": "./lib/core/naanlib.js",
@@ -213,7 +213,7 @@ closure GitTree(local fs, reporoot, gtree, repodir, stagedir) {
213
213
  closure fileHash(fspath, callback) {
214
214
  if !callback
215
215
  return (syncAdapter(fileHash, fspath))
216
- fs.readFile(fspath, false, function(error, strdata, local hash) {
216
+ fs.readFile(fspath, false, function(error, strdata) {
217
217
  if error
218
218
  callback(error)
219
219
  else
@@ -1025,7 +1025,7 @@ closure GitTree(local fs, reporoot, gtree, repodir, stagedir) {
1025
1025
 
1026
1026
  // comrecur
1027
1027
  // Recursively copy portions of tree that should be in commit.
1028
- function comrecur(input, parpath, chout, local node, nodout, path, action) {
1028
+ function comrecur(input, parpath, chout, local node, nodout, path) {
1029
1029
  for node in input {
1030
1030
  nodout = { name: node.name }
1031
1031
  path = joinode(parpath, node)
@@ -17,7 +17,7 @@
17
17
  *
18
18
  */
19
19
 
20
- closure HttpsGetJson(hostname, pathname, query, local https, options, pending, req) {
20
+ closure HttpsGetJson(hostname, pathname, query, local options, pending, req) {
21
21
  if query
22
22
  pathname = EncodeQuery(pathname.concat("?"), query)
23
23
  debuglog("HttpsGetJson", hostname, pathname)
@@ -55,7 +55,7 @@ closure HttpsGetJson(hostname, pathname, query, local https, options, pending, r
55
55
  */
56
56
 
57
57
  closure HttpsDownloadFile(hostname, pathname, query, filepath,
58
- local dirpath, error, pending, writeStream, options, req)
58
+ local error, pending, writeStream, options, req)
59
59
  {
60
60
  filepath = nodePath.resolve("/tmp", filepath)
61
61
  if query
@@ -128,10 +128,13 @@ closure dawsBucket(s3b, local bucket, s3) {
128
128
  "jpg": "image/jpeg",
129
129
  "js": "text/javascript",
130
130
  "json": "application/json",
131
+ "mov": "video/mp4",
131
132
  "mp3": "audio/mpeg",
132
133
  "mp4": "video/mp4",
133
134
  "nlg": "text/plain",
134
135
  "npk": "application/json",
136
+ "ogg": "video/ogg",
137
+ "png": "image/png",
135
138
  "svg": "image/svg+xml",
136
139
  "text": "text/plain",
137
140
  "txt": "text/plain",
@@ -33,7 +33,7 @@ closure lancoRest(local url, client) {
33
33
  request.addEventListener("error", function reqFailed(event, local errtext) {
34
34
  if request.status == 0
35
35
  errtext = "connectivity"
36
- ellse
36
+ else
37
37
  errtext = "request failed"
38
38
  error = Error(errtext, {
39
39
  status: request.status
@@ -92,7 +92,7 @@ closure lancoWs(local url, laws) {
92
92
  // onmessage
93
93
  // A message was received from the worker via WebSockets.
94
94
 
95
- laws.ws.onmessage = function onmessage(e, local message, msg) {
95
+ laws.ws.onmessage = function onmessage(e) {
96
96
  laws.doMessage(e.data)
97
97
  }
98
98
 
@@ -114,7 +114,7 @@ closure lancoWs(local url, laws) {
114
114
  // doMessage
115
115
  //
116
116
  // Process the specified undecoded message.
117
- laws.doMessage = function doMessage(text, local message, msg) {
117
+ laws.doMessage = function doMessage(text, local message) {
118
118
  try {
119
119
  message = new(JSONparse(text))
120
120
  } catch {
@@ -0,0 +1,263 @@
1
+ /*
2
+ * gc_api.nlg
3
+ * serviceGC
4
+ *
5
+ * NodeJS REST API client for serviceGC.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2024 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * GcApi
16
+ *
17
+ * GC API object. This handles access token acquisition and refresh.
18
+ *
19
+ * options:
20
+ * {
21
+ * preview: <boolean> // true for preview models
22
+ * debug: <boolean> // https requests have additional diagnostics
23
+ * sseHook: <proc> // call procedure with SSE messages
24
+ * }
25
+ *
26
+ */
27
+
28
+ closure GcApi(options, local gcapi, cacert, renew, access_token, expires_at) {
29
+ global(js, https, JSpath)
30
+ gcapi = new(object, this)
31
+ if options.preview {
32
+ gcapi.urlbase = "https://gigachat-preview.devices.sberbank.ru/api/v1/"
33
+ gcapi.model_suffix = "-preview"
34
+ }
35
+ else
36
+ gcapi.urlbase = "https://gigachat.devices.sberbank.ru/api/v1/"
37
+
38
+ // auth
39
+ //
40
+ // Authenticate the API and get an access token and expiration date. The creds dictionary will be
41
+ // modified, so pass a copy if desired. Returns standard error tuple.
42
+ //
43
+ closure auth(creds, local path, error, headers, data) {
44
+ if defined(creds, `rootCert)
45
+ cacert = creds.rootCert // use supplied cacert or false
46
+ else { // load our default
47
+ path = JSpath.resolve(js.d, module.locpath, "russian_trusted_root_ca_pem.crt")
48
+ `(error, cacert) = require("../nodeLib/node_fs.nlg").ReadFile(path, "binary")
49
+ if error
50
+ return (list(Error("gc: unable to load root cert", error)))
51
+ creds.rootCert = cacert // save for renewal
52
+ }
53
+ gcapi.rqUID = UUID()
54
+ headers = [
55
+ `("Content-Type", "application/x-www-form-urlencoded")
56
+ `("Accept", "application/json")
57
+ list("RqUID", gcapi.rqUID)
58
+ list("Authorization", "${creds.authType} ${creds.authKey}")
59
+ ]
60
+ `(error, data) = https.HttpsApiRequest(creds.url, {
61
+ putdata: "scope=${creds.scope}"
62
+ headers: headers
63
+ cacert: cacert || undefined
64
+ debug: options.debug || undefined })
65
+ if error
66
+ return (list(Error("gc: unable to authenticate api", error)))
67
+ renew = creds
68
+ access_token = data.access_token
69
+ expires_at = data.expires_at
70
+ list(false, { ok: true })
71
+ }
72
+
73
+ // request
74
+ //
75
+ // Make an HTTPS request on the API, renewing the access token first if needed.
76
+ //
77
+ closure request(url, put, local error, data, status) {
78
+ if !(milliseconds() < expires_at - 60000) {
79
+ `(error, data) = auth(renew)
80
+ if error
81
+ return (list(Error("gc: unable to renew access")))
82
+ }
83
+ `(error, data, status) = https.HttpsApiRequest(url, {
84
+ putdata: put || undefined
85
+ cacert: cacert || undefined
86
+ headers: [
87
+ `(Accept, "application/json"),
88
+ list(`Authorization, "Bearer ".concat(access_token))
89
+ ]
90
+ sseHook: options.sseHook || undefined
91
+ })
92
+ if error
93
+ list(error)
94
+ else
95
+ list(false, new(data))
96
+ }
97
+
98
+ // login
99
+ //
100
+ // Login to the GC API with the specified credentials.
101
+ //
102
+ // creds:
103
+ // {
104
+ // authType: <string> // "Basic"
105
+ // authKey: <string> // "NTdkM...Zg=="
106
+ // [ url: <string> ] // "https://ngw.devices.sberbank.ru:9443/api/v2/oauth"
107
+ // [ scope: <string> ] // GIGACHAT_API_PERS | GIGACHAT_API_B2B | GIGACHAT_API_CORP
108
+ // [ rootCert: <Uint8Array> ] // optional root_ca_pem.crt, omit for default, or false for none
109
+ // }
110
+ //
111
+ gcapi.login = function login(creds) {
112
+ if !string(creds.authType) || !string(creds.authKey)
113
+ return (list(Error("gc: invalid credentials")))
114
+ creds = merge({
115
+ scope: "GIGACHAT_API_CORP"
116
+ url: "https://ngw.devices.sberbank.ru:9443/api/v2/oauth"
117
+ }, creds)
118
+ auth(creds)
119
+ }
120
+
121
+ // modelList
122
+ //
123
+ // Return a list of available models.
124
+ //
125
+ gcapi.modelList = closure modelList() {
126
+ request(gcapi.urlbase.concat("models"))
127
+ }
128
+
129
+ // chatCompletion
130
+ //
131
+ // Return a chat completion.
132
+ //
133
+ // query defined by GC:
134
+ // {
135
+ // model: <string> // desired model from modelList
136
+ // messages: [
137
+ // {
138
+ // role: <string> // system | user | assistant | function
139
+ // content: <string> | <dictionary> // prompts | function arguments
140
+ // }
141
+ // ...
142
+ // ]
143
+ // attachments: [
144
+ // <string> // name of an attachment
145
+ // ...
146
+ // ]
147
+ // temp: <float>
148
+ // top_p: <float>
149
+ // max_tokens: <integer>
150
+ // repetition_penalty: <float>
151
+ // stream: <boolean>
152
+ // update_interval: <float>
153
+ // }
154
+ //
155
+ // response defined by GC:
156
+ // {
157
+ // choice: [
158
+ // message: {
159
+ // role: <string> // system | user | assistant | function
160
+ // content: <string> | <dictionary> // prompts | function arguments
161
+ // }
162
+ // index: <integer>
163
+ // finish_reason: <string> // stop | length | function_call | blacklist
164
+ // ]
165
+ // create: <integer>
166
+ // model: <string>
167
+ // usage: {
168
+ // prompt_tokens: <integer> // role: user
169
+ // completion_tokens: <integer> // role: assistant
170
+ // total_tokens: <integer>
171
+ // }
172
+ // object: <string>
173
+ // }
174
+ //
175
+ gcapi.chatCompletion = closure chatCompletion(query) {
176
+ if options.preview {
177
+ query = new(query)
178
+ if !query.model.endsWith("-preview")
179
+ query.model = query.model.concat("-preview")
180
+ }
181
+ request(gcapi.urlbase.concat("chat/completions"), query)
182
+ }
183
+
184
+ // uploadFile
185
+ //
186
+ gcapi.uploadFile = closure uploadFile(image) {
187
+ request(gcapi.urlbase.concat("files"), image)
188
+ }
189
+
190
+ // listFiles
191
+ //
192
+ gcapi.listFiles = closure listFiles() {
193
+ request(gcapi.urlbase.concat("files"))
194
+ }
195
+
196
+ // fileInfo
197
+ //
198
+ gcapi.fileInfo = closure fileInfo(fileID) {
199
+ request(gcapi.urlbase.concat("files/:${fileID}"))
200
+ }
201
+
202
+ // downloadFile
203
+ //
204
+ gcapi.downloadFile = closure downloadFile(fileID) {
205
+ request(gcapi.urlbase.concat("files/:${fileID}/content"))
206
+ }
207
+
208
+ // createEmbedding
209
+ //
210
+ // query:
211
+ // {
212
+ // [ model: <string> ] // model name
213
+ // input: <string> || [ <string>... ] // string or array thereof
214
+ // }
215
+ //
216
+ gcapi.createEmbedding = closure createEmbedding(query) {
217
+ if !query.model {
218
+ query = new(query)
219
+ query.model = "Embeddings"
220
+ }
221
+ request(gcapi.urlbase.concat("embeddings"), query)
222
+ }
223
+
224
+ // countTokens
225
+ //
226
+ // input defined by gc:
227
+ // {
228
+ // model: <string> // model name
229
+ // input: <string> || [ <string>... ]
230
+ // }
231
+ //
232
+ // output defined by gc:
233
+ // {
234
+ // object: <string> // "tokens"
235
+ // tokens: <integer>
236
+ // characters: <integer>
237
+ // }
238
+ //
239
+ gcapi.countTokens = closure countTokens(request) {
240
+ request(gcapi.urlbase.concat("tokens/count"), request)
241
+ }
242
+
243
+ // fin
244
+ gcapi
245
+ };
246
+
247
+
248
+ /*
249
+ * gcapiInit
250
+ *
251
+ * Initialize the module.
252
+ *
253
+ */
254
+
255
+ function gcapiInit(local manifest) {
256
+ manifest = `(GcApi, gcapiInit)
257
+
258
+ Naan.module.build(module.id, "gc_api", function(modobj, compobj) {
259
+ compobj.manifest = manifest
260
+ require("./serviceGC.nlg")
261
+ module.exports.GcApi = GcApi
262
+ })
263
+ } ();
@@ -0,0 +1,33 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFwjCCA6qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwcDELMAkGA1UEBhMCUlUx
3
+ PzA9BgNVBAoMNlRoZSBNaW5pc3RyeSBvZiBEaWdpdGFsIERldmVsb3BtZW50IGFu
4
+ ZCBDb21tdW5pY2F0aW9uczEgMB4GA1UEAwwXUnVzc2lhbiBUcnVzdGVkIFJvb3Qg
5
+ Q0EwHhcNMjIwMzAxMjEwNDE1WhcNMzIwMjI3MjEwNDE1WjBwMQswCQYDVQQGEwJS
6
+ VTE/MD0GA1UECgw2VGhlIE1pbmlzdHJ5IG9mIERpZ2l0YWwgRGV2ZWxvcG1lbnQg
7
+ YW5kIENvbW11bmljYXRpb25zMSAwHgYDVQQDDBdSdXNzaWFuIFRydXN0ZWQgUm9v
8
+ dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMfFOZ8pUAL3+r2n
9
+ qqE0Zp52selXsKGFYoG0GM5bwz1bSFtCt+AZQMhkWQheI3poZAToYJu69pHLKS6Q
10
+ XBiwBC1cvzYmUYKMYZC7jE5YhEU2bSL0mX7NaMxMDmH2/NwuOVRj8OImVa5s1F4U
11
+ zn4Kv3PFlDBjjSjXKVY9kmjUBsXQrIHeaqmUIsPIlNWUnimXS0I0abExqkbdrXbX
12
+ YwCOXhOO2pDUx3ckmJlCMUGacUTnylyQW2VsJIyIGA8V0xzdaeUXg0VZ6ZmNUr5Y
13
+ Ber/EAOLPb8NYpsAhJe2mXjMB/J9HNsoFMBFJ0lLOT/+dQvjbdRZoOT8eqJpWnVD
14
+ U+QL/qEZnz57N88OWM3rabJkRNdU/Z7x5SFIM9FrqtN8xewsiBWBI0K6XFuOBOTD
15
+ 4V08o4TzJ8+Ccq5XlCUW2L48pZNCYuBDfBh7FxkB7qDgGDiaftEkZZfApRg2E+M9
16
+ G8wkNKTPLDc4wH0FDTijhgxR3Y4PiS1HL2Zhw7bD3CbslmEGgfnnZojNkJtcLeBH
17
+ BLa52/dSwNU4WWLubaYSiAmA9IUMX1/RpfpxOxd4Ykmhz97oFbUaDJFipIggx5sX
18
+ ePAlkTdWnv+RWBxlJwMQ25oEHmRguNYf4Zr/Rxr9cS93Y+mdXIZaBEE0KS2iLRqa
19
+ OiWBki9IMQU4phqPOBAaG7A+eP8PAgMBAAGjZjBkMB0GA1UdDgQWBBTh0YHlzlpf
20
+ BKrS6badZrHF+qwshzAfBgNVHSMEGDAWgBTh0YHlzlpfBKrS6badZrHF+qwshzAS
21
+ BgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
22
+ AAOCAgEAALIY1wkilt/urfEVM5vKzr6utOeDWCUczmWX/RX4ljpRdgF+5fAIS4vH
23
+ tmXkqpSCOVeWUrJV9QvZn6L227ZwuE15cWi8DCDal3Ue90WgAJJZMfTshN4OI8cq
24
+ W9E4EG9wglbEtMnObHlms8F3CHmrw3k6KmUkWGoa+/ENmcVl68u/cMRl1JbW2bM+
25
+ /3A+SAg2c6iPDlehczKx2oa95QW0SkPPWGuNA/CE8CpyANIhu9XFrj3RQ3EqeRcS
26
+ AQQod1RNuHpfETLU/A2gMmvn/w/sx7TB3W5BPs6rprOA37tutPq9u6FTZOcG1Oqj
27
+ C/B7yTqgI7rbyvox7DEXoX7rIiEqyNNUguTk/u3SZ4VXE2kmxdmSh3TQvybfbnXV
28
+ 4JbCZVaqiZraqc7oZMnRoWrXRG3ztbnbes/9qhRGI7PqXqeKJBztxRTEVj8ONs1d
29
+ WN5szTwaPIvhkhO3CO5ErU2rVdUr89wKpNXbBODFKRtgxUT70YpmJ46VVaqdAhOZ
30
+ D9EUUn4YaeLaS8AjSF/h7UkjOibNc4qVDiPP+rkehFWM66PVnP1Msh93tc+taIfC
31
+ EYVMxjh8zNbFuoc7fzvvrFILLe7ifvEIUqSVIC/AzplM/Jxw7buXFeGP1qVCBEHq
32
+ 391d/9RAfaZ12zkwFsl+IKwE/OZxW8AHa9i1p4GO0YSNuczzEm4=
33
+ -----END CERTIFICATE-----
@@ -0,0 +1,31 @@
1
+ /*
2
+ * serviceGC.nlg
3
+ * serviceGC
4
+ *
5
+ * ServiceGC module configuration and management for NodeJS.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2024 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * segcInit
16
+ *
17
+ * Initialize the GC module.
18
+ *
19
+ */
20
+
21
+ function segcInit(local manifest) {
22
+ manifest = `(segcInit)
23
+
24
+ Naan.module.build(module.id, "serviceGC", function(modobj, compobj) {
25
+ compobj.manifest = manifest
26
+ require("naanlib:frameworks/common").LiveImport()
27
+ if !js.g
28
+ throw("serviceGC: NodeJS required")
29
+ https = require("naanlib:frameworks/node/https_request.nlg")
30
+ })
31
+ } ();
@@ -244,7 +244,7 @@ closure GitHubRepo(access, repodict, local gepo, url) {
244
244
  // Return a list of commits in the repo, optionally matching the specified file path.
245
245
  //
246
246
  //
247
- gepo.commits = closure commits(filepath, local pardict, query, error, response, result) {
247
+ gepo.commits = closure commits(filepath, local pardict, query) {
248
248
  pardict = {
249
249
  per_page: 100
250
250
  }
@@ -420,7 +420,8 @@ closure GitHubRepo(access, repodict, local gepo, url) {
420
420
  // ref: <commit> - branch, tag or commit hash, default to main branch
421
421
  // }
422
422
  //
423
- gepo.readfile = closure readfile(filepath, options, local ref, params, query, method, error, response, result) {
423
+ gepo.readfile = closure readfile(filepath, options
424
+ local ref, params, query) {
424
425
  if !string(filepath)
425
426
  return (list(Error("filepath must be a string:", filepath)))
426
427
  ref = options.ref
@@ -489,7 +490,7 @@ closure GitHubRepo(access, repodict, local gepo, url) {
489
490
 
490
491
  gtopParseLinkHeaderRegExp;
491
492
 
492
- function gtopParseLinkHeader(header, local segment, output) {
493
+ function gtopParseLinkHeader(header, local output) {
493
494
  if !jsInstanceOf(gtopParseLinkHeaderRegExp, RegExp.prototype)
494
495
  gtopParseLinkHeaderRegExp = RegExp('<([^?]+\\?[=\\w&?]+page=(\\d+))>;\\s*rel="(\\w+)"', 'g')
495
496
  output = { }
@@ -183,7 +183,7 @@ closure phubConnector(psm, local connClassID, connector, watch) {
183
183
  //
184
184
  // Connect to an ghub bucket filesystem, returning a view.
185
185
 
186
- connector.connect = function connect(resID, service, args, local error, ghub, gitremote, table) {
186
+ connector.connect = function connect(resID, service, args, local error, ghub, gitremote) {
187
187
  `(error, ghub) = connector.access(resID)
188
188
  if !error
189
189
  `(error, gitremote) = GitHubOps(ghub) // get GitHub as a git remote
@@ -464,7 +464,8 @@ closure GitLabRepo(access, repodict, local gepo, url) {
464
464
  // head: <boolean> - true to obtain metadata only without contents
465
465
  // }
466
466
  //
467
- gepo.readfile = closure readfile(filepath, options, local ref, params, query, method, error, response, result) {
467
+ gepo.readfile = closure readfile(filepath, options
468
+ local ref, params, query, method) {
468
469
  if !string(filepath)
469
470
  return (list(Error("filepath must be a string:", filepath)))
470
471
  ref = options.ref
@@ -183,7 +183,7 @@ closure plabConnector(psm, local connClassID, connector, watch) {
183
183
  //
184
184
  // Connect to an GitLab filesystem.
185
185
 
186
- connector.connect = function connect(resID, service, args, local error, glab, gitremote, table) {
186
+ connector.connect = function connect(resID, service, args, local error, glab, gitremote) {
187
187
  `(error, glab) = connector.access(resID)
188
188
  if !error
189
189
  `(error, gitremote) = GitLabOps(glab) // get GitLab as a git remote
@@ -0,0 +1,138 @@
1
+ /*
2
+ * yc_speechrec.nlg
3
+ * serviceYC
4
+ *
5
+ * Access to Yandex Speechkit recognition.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2024 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * YCSpeechRec
16
+ *
17
+ * Speech recognition object.
18
+ *
19
+ */
20
+
21
+ closure YCSpeechRec(options, local ycspr) {
22
+ ycspr = new(object, this)
23
+ ycspr.recogURL = "https://transcribe.api.cloud.yandex.net/speech/stt/v2/longRunningRecognize"
24
+ ycspr.checkURL = "https://operation.api.cloud.yandex.net/operations/"
25
+
26
+ // login
27
+ //
28
+ ycspr.login = closure login(creds) {
29
+ ycspr.creds = creds
30
+ list(false, { ok: true })
31
+ }
32
+
33
+ // startRecog
34
+ //
35
+ // Start a speech recognition task using audio from the specified YC Cloud Storage object.
36
+ //
37
+ // Available options are:
38
+ // {
39
+ // language: <string> // e.g. "ru-RU", "en-US", or false for auto-detect
40
+ // deferred: <boolean> // up to 24 hours for 1/4 the price
41
+ // debug: <boolean> // extra debug logging for https request
42
+ // }
43
+ //
44
+ // This returns an Operation object containing the ID of the asynchronous recognition operation:
45
+ // {
46
+ // done: <boolean> // recognition complete
47
+ // recogID: <string> // operationID to poll for completion
48
+ // createdAt: <date> // when operation started
49
+ // createdBy: <string> // YC ID of user who started it
50
+ // modifiedAt: <date> // last modified
51
+ // // following items only when operation complete:
52
+ // response: {
53
+ // "@type": <string> // gRPC type
54
+ // chunks: <array> // array of chunks
55
+ // }
56
+ // }
57
+ //
58
+ ycspr.startRecog = closure startRecog(audioURI, options, local error, data) {
59
+ params = {
60
+ config: {
61
+ specification: {
62
+ languageCode: options.language || "auto" // e.g. "ru-RU", "en-US"
63
+ model: options.deferred && "deferred-general" || "general"
64
+ audioEncoding: "MP3"
65
+ // profanityFilter: false // default value
66
+ // literature_text: false // default for language "auto"
67
+ // sampleRateHertz: 48000 // default value for LPCM format
68
+ // audioChannelCount: ... // only for LPCM format
69
+ // rawResults: false // write numbers as digits
70
+ }
71
+ }
72
+ audio: {
73
+ uri: audioURI
74
+ }
75
+ }
76
+ `(error, data) = https.HttpsApiRequest(ycspr.recogURL, {
77
+ putdata: params
78
+ headers: [
79
+ list(`Authorization, "Api-Key ".concat(ycspr.creds.apiKeySecret))
80
+ ]
81
+ debug: options.debug || undefined })
82
+ if error
83
+ list(Error("YCSpeechRec.startRecog failed:", error))
84
+ else
85
+ list(false, {
86
+ done: data.done
87
+ recogID: data.id
88
+ createdAt: Date(data.createdAt)
89
+ createdBy: data.createdBy
90
+ modifiedAt: Date(data.modifiedAt)
91
+ })
92
+ }
93
+
94
+ // checkRecog
95
+ //
96
+ // Check if a recognition operation, identified by recogID, has completed. If called too often
97
+ // this can encounter an API rate limit, which is 2500/hour total as of 20241007.
98
+ //
99
+ ycspr.checkRecog = closure checkRecog(recogID, local error, data) {
100
+ `(error, data) = https.HttpsApiRequest(ycspr.checkURL.concat(recogID), {
101
+ headers: [
102
+ list(`Authorization, "Api-Key ".concat(ycspr.creds.apiKeySecret))
103
+ ]})
104
+ if error
105
+ list(Error("YCSpeechRec.checkRecog failed:", error))
106
+ else
107
+ list(false, {
108
+ done: data.done
109
+ recogID: data.id
110
+ createdAt: Date(data.createdAt)
111
+ createdBy: data.createdBy
112
+ modifiedAt: Date(data.modifiedAt)
113
+ response: data.response || undefined
114
+ })
115
+ }
116
+
117
+ // finis
118
+ ycspr
119
+ }
120
+
121
+
122
+ /*
123
+ * ycSpeechRecInit
124
+ *
125
+ * Initialize the module.
126
+ *
127
+ */
128
+
129
+ function ycSpeechRecInit(local manifest) {
130
+ manifest = `(YCSpeechRec, ycSpeechRecInit)
131
+
132
+ Naan.module.build(module.id, "yc_speechrec", function(modobj, compobj) {
133
+ require("./serviceYC.nlg")
134
+ compobj.manifest = manifest
135
+ modobj.exports.YCSpeechRec = YCSpeechRec
136
+ })
137
+
138
+ } ();
@@ -22,7 +22,7 @@ vmState = false;
22
22
  */
23
23
 
24
24
  closure VmControl(local ycvm) {
25
- global(https, nodeHttp, vmState)
25
+ global(js, https, nodeHttp, vmState)
26
26
  if vmState.ycvm
27
27
  return (vmState.ycvm) // singleton
28
28
  ycvm = new(object, this)
@@ -263,7 +263,7 @@ RegisterTestCategory("context", [
263
263
  //
264
264
 
265
265
  [ "closure Xx(y, local xx) { xx = new(object, this) };", "Xx" ],
266
- [ "x = Xx(33);", "Object{0}" ],
266
+ [ "x = Xx(33);", "{object Xx}" ],
267
267
  [ "car(x@\\.closure.proc.2.0)", "33" ],
268
268
  [ "new(object, 3)@*", "false" ]
269
269
  ]);
@@ -646,18 +646,18 @@ RegisterTestCategory("Lingo", [
646
646
  [ "closure myob(initv, local myob) {\n"
647
647
  " myob = new(object)\n"
648
648
  " myob.value = initv\n"
649
- " myob.\\.tostring = function \\.tostring(obj) {\n"
649
+ " myob@\\.tostring = function \\.tostring(obj) {\n"
650
650
  " \"myob-\".concat(myob.value) }\n"
651
651
  " myob };",
652
652
  "myob" ],
653
- [ "myob(3);>", "Object{2}" ],
653
+ [ "myob(3);>", "Object{1}" ],
654
654
  [ "myob(3);", "myob-3" ],
655
655
 
656
656
  //
657
657
  // dialects
658
658
  //
659
659
 
660
- [ "dt = Dialect.derive('test');", "Object{22}" ],
660
+ [ "dt = Dialect.derive('test');", "{object dialect}" ],
661
661
  [ "dt.redefine(`^, function(x,y,local z) {z=1,while y-- > 0 z *= x,z});", "^" ],
662
662
  [ "$$ = dt.parse(new(textstream, '2^9;'));", "(false, 2^9)" ],
663
663
  [ "eval($$);", "(false, 512)" ],